Patch #42602 » 0001-Replaces-deckar01-task_list-gem-with-commonmark-task.patch
Gemfile | ||
---|---|---|
49 | 49 |
# Optional CommonMark support, not for JRuby |
50 | 50 |
group :common_mark do |
51 | 51 |
gem "commonmarker", '~> 2.3.0' |
52 |
gem 'deckar01-task_list', '2.3.2' |
|
53 | 52 |
end |
54 | 53 | |
55 | 54 |
# Include database gems for the adapters found in the database |
app/assets/stylesheets/application.css | ||
---|---|---|
1610 | 1610 |
h1:hover a.wiki-anchor, h2:hover a.wiki-anchor, h3:hover a.wiki-anchor, h4:hover a.wiki-anchor, h5:hover a.wiki-anchor, h6:hover a.wiki-anchor { display: inline; color: #ddd; } |
1611 | 1611 | |
1612 | 1612 |
div.wiki img {vertical-align:middle; max-width:100%;} |
1613 |
div.wiki>.task-list { |
|
1614 |
padding-left: 0px; |
|
1613 | ||
1614 |
div.wiki>.contains-task-list { |
|
1615 |
padding-left: 0; |
|
1615 | 1616 |
} |
1616 |
div.wiki .task-list { |
|
1617 |
div.wiki .contains-task-list {
|
|
1617 | 1618 |
list-style-type: none; |
1618 | 1619 |
} |
1619 | 1620 |
div.wiki .task-list input.task-list-item-checkbox { |
lib/redmine/wiki_formatting/common_mark/formatter.rb | ||
---|---|---|
18 | 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
19 | 19 | |
20 | 20 |
require 'html/pipeline' |
21 |
require 'task_list/filter' |
|
22 | 21 | |
23 | 22 |
module Redmine |
24 | 23 |
module WikiFormatting |
... | ... | |
33 | 32 |
autolink: true, |
34 | 33 |
footnotes: true, |
35 | 34 |
header_ids: nil, |
36 |
tasklist: false,
|
|
35 |
tasklist: true,
|
|
37 | 36 |
shortcodes: false, |
38 | 37 |
}.freeze, |
39 | 38 | |
... | ... | |
46 | 45 |
unsafe: true, |
47 | 46 |
github_pre_lang: false, |
48 | 47 |
hardbreaks: Redmine::Configuration['common_mark_enable_hardbreaks'] == true, |
48 |
tasklist_classes: true, |
|
49 | 49 |
}.freeze, |
50 | 50 |
commonmarker_plugins: { |
51 | 51 |
syntax_highlighter: nil |
... | ... | |
57 | 57 |
SanitizationFilter, |
58 | 58 |
SyntaxHighlightFilter, |
59 | 59 |
FixupAutoLinksFilter, |
60 |
ExternalLinksFilter, |
|
61 |
TaskList::Filter |
|
60 |
ExternalLinksFilter |
|
62 | 61 |
], PIPELINE_CONFIG |
63 | 62 | |
64 | 63 |
class Formatter |
lib/redmine/wiki_formatting/common_mark/sanitization_filter.rb | ||
---|---|---|
78 | 78 |
# allowlist[:attributes]["td"] = %w(style) |
79 | 79 |
# allowlist[:css] = { properties: ["text-align"] } |
80 | 80 | |
81 |
# Allow `id` in a and li elements for footnotes |
|
82 |
# and remove any `id` properties not matching for footnotes |
|
81 |
# Allow `id` in a elements for footnotes |
|
83 | 82 |
allowlist[:attributes]["a"].push "id" |
84 |
allowlist[:attributes]["li"] = %w(id)
|
|
83 |
# Remove any `id` property not matching for footnotes
|
|
85 | 84 |
allowlist[:transformers].push lambda{|env| |
86 | 85 |
node = env[:node] |
87 |
return unless node.name == "a" || node.name == "li"
|
|
86 |
return unless node.name == "a" |
|
88 | 87 |
return unless node.has_attribute?("id") |
89 | 88 |
return if node.name == "a" && node["id"] =~ /\Afnref-\d+\z/ |
90 |
return if node.name == "li" && node["id"] =~ /\Afn-\d+\z/ |
|
91 | 89 | |
92 | 90 |
node.remove_attribute("id") |
93 | 91 |
} |
94 | 92 | |
93 |
# allow `id` in li element for footnotes |
|
94 |
# allow `class` in li element for task list items |
|
95 |
allowlist[:attributes]["li"] = %w(id class) |
|
96 |
allowlist[:transformers].push lambda{|env| |
|
97 |
node = env[:node] |
|
98 |
return unless node.name == "li" |
|
99 | ||
100 |
if node.has_attribute?("id") && !(node["id"] =~ /\Afn-\d+\z/) |
|
101 |
node.remove_attribute("id") |
|
102 |
end |
|
103 | ||
104 |
if node.has_attribute?("class") && node["class"] != "task-list-item" |
|
105 |
node.remove_attribute("class") |
|
106 |
end |
|
107 |
} |
|
108 | ||
109 |
# allow input type = "checkbox" with class "task-list-item-checkbox" |
|
110 |
# for task list items |
|
111 |
allowlist[:elements].push('input') |
|
112 |
allowlist[:attributes]["input"] = %w(class type) |
|
113 |
allowlist[:transformers].push lambda{|env| |
|
114 |
node = env[:node] |
|
115 | ||
116 |
return unless node.name == "input" |
|
117 |
return if node['type'] == "checkbox" && node['class'] == "task-list-item-checkbox" |
|
118 | ||
119 |
node.replace(node.children) |
|
120 |
} |
|
121 | ||
122 |
# allow class "contains-task-list" on ul for task list items |
|
123 |
allowlist[:attributes]["ul"] = %w(class) |
|
124 |
allowlist[:transformers].push lambda{|env| |
|
125 |
node = env[:node] |
|
126 | ||
127 |
return unless node.name == "ul" |
|
128 |
return if node["class"] == "contains-task-list" |
|
129 | ||
130 |
node.remove_attribute("class") |
|
131 |
} |
|
132 | ||
95 | 133 |
# https://github.com/rgrove/sanitize/issues/209 |
96 | 134 |
allowlist[:protocols].delete("a") |
97 | 135 |
allowlist[:transformers].push lambda{|env| |
test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb | ||
---|---|---|
287 | 287 | |
288 | 288 |
expected = <<~EXPECTED |
289 | 289 |
<p>Task list:</p> |
290 |
<ul class="task-list"> |
|
290 |
<ul class="contains-task-list">
|
|
291 | 291 |
<li class="task-list-item"> |
292 | 292 |
<input type="checkbox" class="task-list-item-checkbox" disabled> Task 1 |
293 | 293 |
</li> |
test/unit/lib/redmine/wiki_formatting/html_sanitizer_test.rb | ||
---|---|---|
35 | 35 |
input = %(<a href="javascript:alert('hello');">foo</a>) |
36 | 36 |
assert_equal "<a>foo</a>", @sanitizer.call(input) |
37 | 37 |
end |
38 | ||
39 |
def test_should_be_strict_with_task_list_items |
|
40 |
to_test = { |
|
41 |
%(<input type="checkbox" class="">) => "", |
|
42 |
%(<input type="checkbox" class="task-list-item-checkbox other">) => "", |
|
43 |
%(<input type="checkbox" class="task-list-item-checkbox" id="item1">) => %(<input type="checkbox" class="task-list-item-checkbox">), |
|
44 |
%(<input type="text" class="">) => "", |
|
45 |
%(<input />) => "", |
|
46 |
%(<ul class="other"></ul) => "<ul></ul>", |
|
47 |
%(<ul class="contains-task-list"></ul) => "<ul class=\"contains-task-list\"></ul>", |
|
48 |
%(<ul class="contains-task-list" id="list1"></ul) => "<ul class=\"contains-task-list\"></ul>", |
|
49 |
%(<li class="other"></li>) => "", |
|
50 |
%(<li id="other"></li>) => "", |
|
51 |
%(<li class="task-list-item"></li>) => "", |
|
52 |
%(<li class="task-list-item">Item 1</li>) => "Item 1", |
|
53 |
} |
|
54 |
to_test.each do |input, result| |
|
55 |
assert_equal result, @sanitizer.call(input) |
|
56 |
end |
|
57 | ||
58 |
end |
|
38 | 59 |
end |