1
0
mirror of https://github.com/meineerde/redmine.git synced 2026-01-31 11:37:14 +00:00

Unify code block and add "data-language" attribute with the user-supplied language for Textile and Markdown formaters (#35104).

Patch by Martin Cizek.

git-svn-id: http://svn.redmine.org/redmine/trunk@21183 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Marius Balteanu 2021-08-15 21:00:16 +00:00
parent 5699253da6
commit b7798e6e1c
5 changed files with 47 additions and 17 deletions

View File

@ -38,12 +38,14 @@ module Redmine
def block_code(code, language)
if language.present? && Redmine::SyntaxHighlighting.language_supported?(language)
"<pre><code class=\"#{CGI.escapeHTML language} syntaxhl\">" +
Redmine::SyntaxHighlighting.highlight_by_language(code, language) +
"</code></pre>"
html = Redmine::SyntaxHighlighting.highlight_by_language(code, language)
classattr = " class=\"#{CGI.escapeHTML language} syntaxhl\""
else
"<pre>" + CGI.escapeHTML(code) + "</pre>"
html = CGI.escapeHTML(code)
end
# original language for extension development
langattr = " data-language=\"#{CGI.escapeHTML language}\"" if language.present?
"<pre><code#{classattr}#{langattr}>#{html}</code></pre>"
end
def image(link, title, alt_text)

View File

@ -128,12 +128,14 @@ module Redmine
if content.match(/<code\s+class=(?:"([^"]+)"|'([^']+)')>\s?(.*)/m)
language = $1 || $2
text = $3
# original language for extension development
langattr = " data-language=\"#{CGI.escapeHTML language}\"" if language.present?
if Redmine::SyntaxHighlighting.language_supported?(language)
text.gsub!(/x%x%/, '&')
content = "<code class=\"#{language} syntaxhl\">" +
content = "<code class=\"#{CGI.escapeHTML language} syntaxhl\"#{langattr}>" +
Redmine::SyntaxHighlighting.highlight_by_language(text, language)
else
content = "<code>#{ERB::Util.h(text)}"
content = "<code#{langattr}>#{ERB::Util.h(text)}"
end
end
content

View File

@ -1328,7 +1328,7 @@ class ApplicationHelperTest < Redmine::HelperTest
</code></pre>
RAW
expected = <<~EXPECTED
<pre><code class="ECMA_script syntaxhl"><span class="cm">/* Hello */</span><span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="dl">"</span><span class="s2">Hello World!</span><span class="dl">"</span><span class="p">);</span></code></pre>
<pre><code class="ECMA_script syntaxhl" data-language=\"ECMA_script\"><span class="cm">/* Hello */</span><span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="dl">"</span><span class="s2">Hello World!</span><span class="dl">"</span><span class="p">);</span></code></pre>
EXPECTED
assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
end
@ -1340,7 +1340,7 @@ class ApplicationHelperTest < Redmine::HelperTest
</code></pre>
RAW
expected = <<~EXPECTED
<pre><code class=\"ruby syntaxhl\"><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">a</span> <span class=\"o\">&amp;</span> <span class=\"n\">b</span></code></pre>
<pre><code class=\"ruby syntaxhl\" data-language=\"ruby\"><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">a</span> <span class=\"o\">&amp;</span> <span class=\"n\">b</span></code></pre>
EXPECTED
with_settings :text_formatting => 'textile' do
assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')

View File

@ -70,6 +70,7 @@ class Redmine::WikiFormatting::MarkdownFormatterTest < ActionView::TestCase
STR
assert_select_in @formatter.new(text).to_html, 'pre code.ruby.syntaxhl' do
assert_select 'span.k', :text => 'def'
assert_select "[data-language='ruby']"
end
end
@ -79,7 +80,16 @@ class Redmine::WikiFormatting::MarkdownFormatterTest < ActionView::TestCase
test
~~~
STR
assert_equal "<pre>test\n</pre>", @formatter.new(text).to_html
assert_equal "<pre><code data-language=\"foo\">test\n</code></pre>", @formatter.new(text).to_html
end
def test_should_preserve_code_block_language_in_data_language
text = <<~STR
~~~c-k&r
test
~~~
STR
assert_equal "<pre><code data-language=\"c-k&amp;r\">test\n</code></pre>", @formatter.new(text).to_html
end
def test_external_links_should_have_external_css_class

View File

@ -596,12 +596,16 @@ class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase
end
def test_should_not_allow_arbitrary_class_attribute_on_offtags
%w(code pre kbd).each do |tag|
assert_html_output({"<#{tag} class=\"foo\">test</#{tag}>" => "<#{tag}>test</#{tag}>"}, false)
assert_html_output({"<#{tag} class='foo'>test</#{tag}>" => "<#{tag}>test</#{tag}>"}, false)
assert_html_output({"<#{tag} class=\"ruby foo\">test</#{tag}>" => "<#{tag}>test</#{tag}>"}, false)
assert_html_output({"<#{tag} class='ruby foo'>test</#{tag}>" => "<#{tag}>test</#{tag}>"}, false)
assert_html_output({"<#{tag} class=\"ruby \"foo\" bar\">test</#{tag}>" => "<#{tag}>test</#{tag}>"}, false)
{
"class=\"foo\"" => "data-language=\"foo\"",
"class='foo'" => "data-language=\"foo\"",
"class=\"ruby foo\"" => "data-language=\"ruby foo\"",
"class='ruby foo'" => "data-language=\"ruby foo\"",
"class=\"ruby \"foo\" bar\"" => "data-language=\"ruby \"",
}.each do |classattr, codeattr|
assert_html_output({"<code #{classattr}>test</code>" => "<code #{codeattr}>test</code>"}, false)
assert_html_output({"<pre #{classattr}>test</pre>" => "<pre>test</pre>"}, false)
assert_html_output({"<kbd #{classattr}>test</kbd>" => "<kbd>test</kbd>"}, false)
end
assert_html_output({"<notextile class=\"foo\">test</notextile>" => "test"}, false)
@ -615,13 +619,25 @@ class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase
# language name is double-quoted
assert_html_output(
{"<code class=\"ruby\">test</code>" =>
"<code class=\"ruby syntaxhl\"><span class=\"nb\">test</span></code>"},
"<code class=\"ruby syntaxhl\" data-language=\"ruby\"><span class=\"nb\">test</span></code>"},
false
)
# language name is single-quoted
assert_html_output(
{"<code class='ruby'>test</code>" =>
"<code class=\"ruby syntaxhl\"><span class=\"nb\">test</span></code>"},
"<code class=\"ruby syntaxhl\" data-language=\"ruby\"><span class=\"nb\">test</span></code>"},
false
)
end
def test_should_preserve_code_language_class_attribute_in_data_language
assert_html_output(
{
"<code class=\"foolang\">unsupported language</code>" =>
"<code data-language=\"foolang\">unsupported language</code>",
"<code class=\"c-k&r\">special-char language</code>" =>
"<code data-language=\"c-k&#38;r\">special-char language</code>",
},
false
)
end