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 |