Defect #37394 » 37394-v2.patch
| Gemfile | ||
|---|---|---|
| 36 | 36 |
gem "html-pipeline", "~> 2.13.2" |
| 37 | 37 |
gem "sanitize", "~> 6.0" |
| 38 | 38 | |
| 39 |
gem "commonmarker", '~> 2.3.0' |
|
| 40 |
gem 'deckar01-task_list', '2.3.2' |
|
| 41 | ||
| 39 | 42 |
# Optional gem for LDAP authentication |
| 40 | 43 |
group :ldap do |
| 41 | 44 |
gem 'net-ldap', '~> 0.17.0' |
| ... | ... | |
| 46 | 49 |
gem 'mini_magick', '~> 5.2.0' |
| 47 | 50 |
end |
| 48 | 51 | |
| 49 |
# Optional CommonMark support, not for JRuby |
|
| 50 |
group :common_mark do |
|
| 51 |
gem "commonmarker", '~> 2.3.0' |
|
| 52 |
gem 'deckar01-task_list', '2.3.2' |
|
| 53 |
end |
|
| 54 | ||
| 55 | 52 |
# Include database gems for the adapters found in the database |
| 56 | 53 |
# configuration file |
| 57 | 54 |
database_file = File.join(File.dirname(__FILE__), "config/database.yml") |
| lib/redmine.rb | ||
|---|---|---|
| 24 | 24 |
rescue LoadError |
| 25 | 25 |
# MiniMagick is not available |
| 26 | 26 |
end |
| 27 |
begin |
|
| 28 |
require 'commonmarker' unless Object.const_defined?(:Commonmarker) |
|
| 29 |
rescue LoadError |
|
| 30 |
# CommonMarker is not available |
|
| 31 |
end |
|
| 32 | 27 | |
| 33 | 28 |
module Redmine |
| 34 | 29 |
end |
| lib/redmine/preparation.rb | ||
|---|---|---|
| 408 | 408 | |
| 409 | 409 |
WikiFormatting.map do |format| |
| 410 | 410 |
format.register :textile |
| 411 |
if Object.const_defined?(:Commonmarker) |
|
| 412 |
format.register :common_mark, label: 'CommonMark Markdown (GitHub Flavored)' |
|
| 413 |
end |
|
| 411 |
format.register :common_mark, label: 'CommonMark Markdown (GitHub Flavored)' |
|
| 414 | 412 |
end |
| 415 | 413 | |
| 416 | 414 |
ActionView::Template.register_template_handler :rsb, Views::ApiTemplateHandler |
| test/helpers/application_helper_test.rb | ||
|---|---|---|
| 252 | 252 |
end |
| 253 | 253 | |
| 254 | 254 |
def test_attached_images_with_markdown_and_non_ascii_filename |
| 255 |
skip unless Object.const_defined?(:CommonMarker) |
|
| 256 | ||
| 257 | 255 |
to_test = {
|
| 258 | 256 |
'CAFÉ.JPG' => 'CAF%C3%89.JPG', |
| 259 | 257 |
'crème.jpg' => 'cr%C3%A8me.jpg', |
| ... | ... | |
| 1658 | 1656 |
end |
| 1659 | 1657 |
end |
| 1660 | 1658 | |
| 1661 |
if Object.const_defined?(:Commonmarker) |
|
| 1662 |
def test_toc_with_markdown_formatting_should_be_parsed |
|
| 1663 |
with_settings :text_formatting => 'common_mark' do |
|
| 1664 |
assert_select_in textilizable("{{toc}}\n\n# Heading"), 'ul.toc li', :text => 'Heading'
|
|
| 1665 |
assert_select_in textilizable("{{<toc}}\n\n# Heading"), 'ul.toc.left li', :text => 'Heading'
|
|
| 1666 |
assert_select_in textilizable("{{>toc}}\n\n# Heading"), 'ul.toc.right li', :text => 'Heading'
|
|
| 1667 |
end |
|
| 1659 |
def test_toc_with_markdown_formatting_should_be_parsed |
|
| 1660 |
with_settings :text_formatting => 'common_mark' do |
|
| 1661 |
assert_select_in textilizable("{{toc}}\n\n# Heading"), 'ul.toc li', :text => 'Heading'
|
|
| 1662 |
assert_select_in textilizable("{{<toc}}\n\n# Heading"), 'ul.toc.left li', :text => 'Heading'
|
|
| 1663 |
assert_select_in textilizable("{{>toc}}\n\n# Heading"), 'ul.toc.right li', :text => 'Heading'
|
|
| 1668 | 1664 |
end |
| 1669 | 1665 |
end |
| 1670 | 1666 | |
| test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb | ||
|---|---|---|
| 20 | 20 |
require_relative '../../../../../test_helper' |
| 21 | 21 | |
| 22 | 22 |
class Redmine::WikiFormatting::CommonMark::ApplicationHelperTest < Redmine::HelperTest |
| 23 |
if Object.const_defined?(:Commonmarker)
|
|
| 23 |
include ERB::Util
|
|
| 24 | 24 | |
| 25 |
include ERB::Util |
|
| 26 | ||
| 27 |
def setup |
|
| 28 |
super |
|
| 29 |
set_tmp_attachments_directory |
|
| 30 |
end |
|
| 25 |
def setup |
|
| 26 |
super |
|
| 27 |
set_tmp_attachments_directory |
|
| 28 |
end |
|
| 31 | 29 | |
| 32 |
def test_attached_images_with_markdown_and_non_ascii_filename |
|
| 33 |
to_test = {
|
|
| 34 |
'CAFÉ.JPG' => 'CAF%C3%89.JPG', |
|
| 35 |
'crème.jpg' => 'cr%C3%A8me.jpg', |
|
| 36 |
} |
|
| 37 |
with_settings :text_formatting => 'common_mark' do |
|
| 38 |
to_test.each do |filename, result| |
|
| 39 |
attachment = Attachment.generate!(:filename => filename) |
|
| 40 |
assert_include %(<img src="/attachments/download/#{attachment.id}/#{result}" alt="" loading="lazy">), textilizable("", :attachments => [attachment])
|
|
| 41 |
end |
|
| 30 |
def test_attached_images_with_markdown_and_non_ascii_filename |
|
| 31 |
to_test = {
|
|
| 32 |
'CAFÉ.JPG' => 'CAF%C3%89.JPG', |
|
| 33 |
'crème.jpg' => 'cr%C3%A8me.jpg', |
|
| 34 |
} |
|
| 35 |
with_settings :text_formatting => 'common_mark' do |
|
| 36 |
to_test.each do |filename, result| |
|
| 37 |
attachment = Attachment.generate!(:filename => filename) |
|
| 38 |
assert_include %(<img src="/attachments/download/#{attachment.id}/#{result}" alt="" loading="lazy">), textilizable("", :attachments => [attachment])
|
|
| 42 | 39 |
end |
| 43 | 40 |
end |
| 41 |
end |
|
| 44 | 42 | |
| 45 |
def test_toc_with_markdown_formatting_should_be_parsed |
|
| 46 |
with_settings :text_formatting => 'common_mark' do |
|
| 47 |
assert_select_in textilizable("{{toc}}\n\n# Heading"), 'ul.toc li', :text => 'Heading'
|
|
| 48 |
assert_select_in textilizable("{{<toc}}\n\n# Heading"), 'ul.toc.left li', :text => 'Heading'
|
|
| 49 |
assert_select_in textilizable("{{>toc}}\n\n# Heading"), 'ul.toc.right li', :text => 'Heading'
|
|
| 50 |
end |
|
| 43 |
def test_toc_with_markdown_formatting_should_be_parsed |
|
| 44 |
with_settings :text_formatting => 'common_mark' do |
|
| 45 |
assert_select_in textilizable("{{toc}}\n\n# Heading"), 'ul.toc li', :text => 'Heading'
|
|
| 46 |
assert_select_in textilizable("{{<toc}}\n\n# Heading"), 'ul.toc.left li', :text => 'Heading'
|
|
| 47 |
assert_select_in textilizable("{{>toc}}\n\n# Heading"), 'ul.toc.right li', :text => 'Heading'
|
|
| 51 | 48 |
end |
| 49 |
end |
|
| 52 | 50 | |
| 53 |
def test_attached_image_alt_attribute_with_madkrown
|
|
| 54 |
attachments = Attachment.all
|
|
| 55 |
with_settings text_formatting: 'common_mark' do
|
|
| 56 |
# When alt text is set
|
|
| 57 |
assert_match %r[<img src=".+?" alt="alt text" loading=".+?">],
|
|
| 58 |
textilizable('', attachments: attachments)
|
|
| 51 |
def test_attached_image_alt_attribute_with_madkrown |
|
| 52 |
attachments = Attachment.all |
|
| 53 |
with_settings text_formatting: 'common_mark' do |
|
| 54 |
# When alt text is set |
|
| 55 |
assert_match %r[<img src=".+?" alt="alt text" loading=".+?">], |
|
| 56 |
textilizable('', attachments: attachments)
|
|
| 59 | 57 | |
| 60 |
# When alt text is not set
|
|
| 61 |
assert_match %r[<img src=".+?" title="This is a logo" alt="This is a logo" loading=".+?">],
|
|
| 62 |
textilizable('', attachments: attachments)
|
|
| 58 |
# When alt text is not set |
|
| 59 |
assert_match %r[<img src=".+?" title="This is a logo" alt="This is a logo" loading=".+?">], |
|
| 60 |
textilizable('', attachments: attachments)
|
|
| 63 | 61 | |
| 64 |
# When alt text is not set and the attachment has no description
|
|
| 65 |
assert_match %r[<img src=".+?" alt="" loading=".+?">],
|
|
| 66 |
textilizable('', attachments: attachments)
|
|
| 62 |
# When alt text is not set and the attachment has no description |
|
| 63 |
assert_match %r[<img src=".+?" alt="" loading=".+?">], |
|
| 64 |
textilizable('', attachments: attachments)
|
|
| 67 | 65 | |
| 68 |
# When no matching attachments are found
|
|
| 69 |
assert_match %r[<img src=".+?" alt="">],
|
|
| 70 |
textilizable('', attachments: attachments)
|
|
| 71 |
assert_match %r[<img src=".+?" alt="alt text">],
|
|
| 72 |
textilizable('', attachments: attachments)
|
|
| 66 |
# When no matching attachments are found |
|
| 67 |
assert_match %r[<img src=".+?" alt="">], |
|
| 68 |
textilizable('', attachments: attachments)
|
|
| 69 |
assert_match %r[<img src=".+?" alt="alt text">], |
|
| 70 |
textilizable('', attachments: attachments)
|
|
| 73 | 71 | |
| 74 |
# When no attachment is registered |
|
| 75 |
assert_match %r[<img src=".+?" alt="">], |
|
| 76 |
textilizable('', attachments: [])
|
|
| 77 |
assert_match %r[<img src=".+?" alt="alt text">], |
|
| 78 |
textilizable('', attachments: [])
|
|
| 79 |
end |
|
| 72 |
# When no attachment is registered |
|
| 73 |
assert_match %r[<img src=".+?" alt="">], |
|
| 74 |
textilizable('', attachments: [])
|
|
| 75 |
assert_match %r[<img src=".+?" alt="alt text">], |
|
| 76 |
textilizable('', attachments: [])
|
|
| 80 | 77 |
end |
| 81 | 78 |
end |
| 82 | 79 |
end |
| test/unit/lib/redmine/wiki_formatting/common_mark/external_links_filter_test.rb | ||
|---|---|---|
| 18 | 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 19 | 19 | |
| 20 | 20 |
require_relative '../../../../../test_helper' |
| 21 |
require 'redmine/wiki_formatting/common_mark/external_links_filter' |
|
| 21 | 22 | |
| 22 |
if Object.const_defined?(:Commonmarker) |
|
| 23 |
require 'redmine/wiki_formatting/common_mark/external_links_filter' |
|
| 24 | ||
| 25 |
class Redmine::WikiFormatting::CommonMark::ExternalLinksFilterTest < ActiveSupport::TestCase |
|
| 26 |
def filter(html) |
|
| 27 |
Redmine::WikiFormatting::CommonMark::ExternalLinksFilter.to_html(html, @options) |
|
| 28 |
end |
|
| 23 |
class Redmine::WikiFormatting::CommonMark::ExternalLinksFilterTest < ActiveSupport::TestCase |
|
| 24 |
def filter(html) |
|
| 25 |
Redmine::WikiFormatting::CommonMark::ExternalLinksFilter.to_html(html, @options) |
|
| 26 |
end |
|
| 29 | 27 | |
| 30 |
def setup
|
|
| 31 |
@options = { }
|
|
| 32 |
end
|
|
| 28 |
def setup |
|
| 29 |
@options = { }
|
|
| 30 |
end |
|
| 33 | 31 | |
| 34 |
def test_external_links_should_have_external_css_class
|
|
| 35 |
assert_equal %(<a href="http://example.net/" class="external">link</a>), filter(%(<a href="http://example.net/">link</a>))
|
|
| 36 |
end
|
|
| 32 |
def test_external_links_should_have_external_css_class |
|
| 33 |
assert_equal %(<a href="http://example.net/" class="external">link</a>), filter(%(<a href="http://example.net/">link</a>)) |
|
| 34 |
end |
|
| 37 | 35 | |
| 38 |
def test_locals_links_should_not_have_external_css_class
|
|
| 39 |
assert_equal %(<a href="/">home</a>), filter(%(<a href="/">home</a>))
|
|
| 40 |
assert_equal %(<a href="relative">relative</a>), filter(%(<a href="relative">relative</a>))
|
|
| 41 |
assert_equal %(<a href="#anchor">anchor</a>), filter(%(<a href="#anchor">anchor</a>))
|
|
| 42 |
end
|
|
| 36 |
def test_locals_links_should_not_have_external_css_class |
|
| 37 |
assert_equal %(<a href="/">home</a>), filter(%(<a href="/">home</a>)) |
|
| 38 |
assert_equal %(<a href="relative">relative</a>), filter(%(<a href="relative">relative</a>)) |
|
| 39 |
assert_equal %(<a href="#anchor">anchor</a>), filter(%(<a href="#anchor">anchor</a>)) |
|
| 40 |
end |
|
| 43 | 41 | |
| 44 |
def test_mailto_links_should_have_email_class
|
|
| 45 |
assert_equal %(<a href="mailto:user@example.org" class="email">user</a>), filter(%(<a href="mailto:user@example.org">user</a>))
|
|
| 46 |
end
|
|
| 42 |
def test_mailto_links_should_have_email_class |
|
| 43 |
assert_equal %(<a href="mailto:user@example.org" class="email">user</a>), filter(%(<a href="mailto:user@example.org">user</a>)) |
|
| 44 |
end |
|
| 47 | 45 | |
| 48 |
def test_malformed_uri_should_not_cause_exception |
|
| 49 |
assert_nothing_raised do |
|
| 50 |
filter(%(<a href="http://example.com/foo#bar#">Malformed URI</a>)) |
|
| 51 |
end |
|
| 46 |
def test_malformed_uri_should_not_cause_exception |
|
| 47 |
assert_nothing_raised do |
|
| 48 |
filter(%(<a href="http://example.com/foo#bar#">Malformed URI</a>)) |
|
| 52 | 49 |
end |
| 50 |
end |
|
| 53 | 51 | |
| 54 |
def test_external_links_with_target_get_rel_noopener |
|
| 55 |
assert_equal( |
|
| 56 |
%(<a target="_blank" href="http://example.net/" class="external" rel="noopener">link</a>), |
|
| 57 |
filter(%(<a target="_blank" href="http://example.net/">link</a>)) |
|
| 58 |
) |
|
| 59 |
assert_equal( |
|
| 60 |
%(<a target="_blank" href="http://example.net/" rel="nofollow noopener" class="external">link</a>), |
|
| 61 |
filter(%(<a target="_blank" href="http://example.net/" rel="nofollow">link</a>)) |
|
| 62 |
) |
|
| 63 |
end |
|
| 52 |
def test_external_links_with_target_get_rel_noopener |
|
| 53 |
assert_equal( |
|
| 54 |
%(<a target="_blank" href="http://example.net/" class="external" rel="noopener">link</a>), |
|
| 55 |
filter(%(<a target="_blank" href="http://example.net/">link</a>)) |
|
| 56 |
) |
|
| 57 |
assert_equal( |
|
| 58 |
%(<a target="_blank" href="http://example.net/" rel="nofollow noopener" class="external">link</a>), |
|
| 59 |
filter(%(<a target="_blank" href="http://example.net/" rel="nofollow">link</a>)) |
|
| 60 |
) |
|
| 64 | 61 |
end |
| 65 | 62 |
end |
| test/unit/lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter_test.rb | ||
|---|---|---|
| 18 | 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 19 | 19 | |
| 20 | 20 |
require_relative '../../../../../test_helper' |
| 21 |
require 'redmine/wiki_formatting/common_mark/fixup_auto_links_filter' |
|
| 21 | 22 | |
| 22 |
if Object.const_defined?(:Commonmarker) |
|
| 23 |
require 'redmine/wiki_formatting/common_mark/fixup_auto_links_filter' |
|
| 24 | ||
| 25 |
class Redmine::WikiFormatting::CommonMark::FixupAutoLinksFilterTest < ActiveSupport::TestCase |
|
| 26 |
def filter(html) |
|
| 27 |
Redmine::WikiFormatting::CommonMark::FixupAutoLinksFilter.to_html(html, @options) |
|
| 28 |
end |
|
| 23 |
class Redmine::WikiFormatting::CommonMark::FixupAutoLinksFilterTest < ActiveSupport::TestCase |
|
| 24 |
def filter(html) |
|
| 25 |
Redmine::WikiFormatting::CommonMark::FixupAutoLinksFilter.to_html(html, @options) |
|
| 26 |
end |
|
| 29 | 27 | |
| 30 |
def format(markdown)
|
|
| 31 |
Redmine::WikiFormatting::CommonMark::MarkdownFilter.to_html(markdown, Redmine::WikiFormatting::CommonMark::PIPELINE_CONFIG)
|
|
| 32 |
end
|
|
| 28 |
def format(markdown) |
|
| 29 |
Redmine::WikiFormatting::CommonMark::MarkdownFilter.to_html(markdown, Redmine::WikiFormatting::CommonMark::PIPELINE_CONFIG) |
|
| 30 |
end |
|
| 33 | 31 | |
| 34 |
def setup
|
|
| 35 |
@options = { }
|
|
| 36 |
end
|
|
| 32 |
def setup |
|
| 33 |
@options = { }
|
|
| 34 |
end |
|
| 37 | 35 | |
| 38 |
def test_should_fixup_autolinked_user_references
|
|
| 39 |
text = "user:user@example.org"
|
|
| 40 |
assert_equal "<p>#{text}</p>", filter(format(text))
|
|
| 41 |
text = "@user@example.org"
|
|
| 42 |
assert_equal "<p>#{text}</p>", filter(format(text))
|
|
| 43 |
end
|
|
| 36 |
def test_should_fixup_autolinked_user_references |
|
| 37 |
text = "user:user@example.org" |
|
| 38 |
assert_equal "<p>#{text}</p>", filter(format(text))
|
|
| 39 |
text = "@user@example.org" |
|
| 40 |
assert_equal "<p>#{text}</p>", filter(format(text))
|
|
| 41 |
end |
|
| 44 | 42 | |
| 45 |
def test_should_fixup_autolinked_hires_files |
|
| 46 |
text = "printscreen@2x.png" |
|
| 47 |
assert_equal "<p>#{text}</p>", filter(format(text))
|
|
| 48 |
end |
|
| 43 |
def test_should_fixup_autolinked_hires_files |
|
| 44 |
text = "printscreen@2x.png" |
|
| 45 |
assert_equal "<p>#{text}</p>", filter(format(text))
|
|
| 49 | 46 |
end |
| 50 | 47 |
end |
| test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb | ||
|---|---|---|
| 20 | 20 |
require_relative '../../../../../test_helper' |
| 21 | 21 | |
| 22 | 22 |
class Redmine::WikiFormatting::CommonMark::FormatterTest < ActionView::TestCase |
| 23 |
if Object.const_defined?(:Commonmarker) |
|
| 24 | ||
| 25 |
def setup |
|
| 26 |
@formatter = Redmine::WikiFormatting::CommonMark::Formatter |
|
| 27 |
end |
|
| 23 |
def setup |
|
| 24 |
@formatter = Redmine::WikiFormatting::CommonMark::Formatter |
|
| 25 |
end |
|
| 28 | 26 | |
| 29 |
def to_html(text)
|
|
| 30 |
@formatter.new(text).to_html
|
|
| 31 |
end
|
|
| 27 |
def to_html(text) |
|
| 28 |
@formatter.new(text).to_html |
|
| 29 |
end |
|
| 32 | 30 | |
| 33 |
def test_should_render_hard_breaks
|
|
| 34 |
html ="<p>foo<br>\nbar</p>"
|
|
| 35 |
assert_equal html, to_html("foo\\\nbar")
|
|
| 36 |
assert_equal html, to_html("foo \nbar")
|
|
| 37 |
end
|
|
| 31 |
def test_should_render_hard_breaks |
|
| 32 |
html ="<p>foo<br>\nbar</p>" |
|
| 33 |
assert_equal html, to_html("foo\\\nbar")
|
|
| 34 |
assert_equal html, to_html("foo \nbar")
|
|
| 35 |
end |
|
| 38 | 36 | |
| 39 |
def test_should_render_soft_breaks
|
|
| 40 |
assert_equal "<p>foo<br>\nbar</p>", to_html("foo\nbar")
|
|
| 41 |
end
|
|
| 37 |
def test_should_render_soft_breaks |
|
| 38 |
assert_equal "<p>foo<br>\nbar</p>", to_html("foo\nbar")
|
|
| 39 |
end |
|
| 42 | 40 | |
| 43 |
def test_syntax_error_in_image_reference_should_not_raise_exception
|
|
| 44 |
assert to_html("!>[](foo.png)")
|
|
| 45 |
end
|
|
| 41 |
def test_syntax_error_in_image_reference_should_not_raise_exception |
|
| 42 |
assert to_html("!>[](foo.png)")
|
|
| 43 |
end |
|
| 46 | 44 | |
| 47 |
def test_empty_image_should_not_raise_exception
|
|
| 48 |
assert to_html("![]()")
|
|
| 49 |
end
|
|
| 45 |
def test_empty_image_should_not_raise_exception |
|
| 46 |
assert to_html("![]()")
|
|
| 47 |
end |
|
| 50 | 48 | |
| 51 |
def test_inline_style
|
|
| 52 |
assert_equal "<p><strong>foo</strong></p>", to_html("**foo**")
|
|
| 53 |
end
|
|
| 49 |
def test_inline_style |
|
| 50 |
assert_equal "<p><strong>foo</strong></p>", to_html("**foo**")
|
|
| 51 |
end |
|
| 54 | 52 | |
| 55 |
def test_not_set_intra_emphasis
|
|
| 56 |
assert_equal "<p>foo_bar_baz</p>", to_html("foo_bar_baz")
|
|
| 57 |
end
|
|
| 53 |
def test_not_set_intra_emphasis |
|
| 54 |
assert_equal "<p>foo_bar_baz</p>", to_html("foo_bar_baz")
|
|
| 55 |
end |
|
| 58 | 56 | |
| 59 |
def test_wiki_links_should_be_preserved
|
|
| 60 |
text = 'This is a wiki link: [[Foo]]'
|
|
| 61 |
assert_include '[[Foo]]', to_html(text)
|
|
| 62 |
end
|
|
| 57 |
def test_wiki_links_should_be_preserved |
|
| 58 |
text = 'This is a wiki link: [[Foo]]' |
|
| 59 |
assert_include '[[Foo]]', to_html(text) |
|
| 60 |
end |
|
| 63 | 61 | |
| 64 |
def test_redmine_links_with_double_quotes_should_be_preserved
|
|
| 65 |
text = 'This is a redmine link: version:"1.0"'
|
|
| 66 |
assert_include 'version:"1.0"', to_html(text)
|
|
| 67 |
end
|
|
| 62 |
def test_redmine_links_with_double_quotes_should_be_preserved |
|
| 63 |
text = 'This is a redmine link: version:"1.0"' |
|
| 64 |
assert_include 'version:"1.0"', to_html(text) |
|
| 65 |
end |
|
| 68 | 66 | |
| 69 |
def test_links_by_id_should_be_preserved
|
|
| 70 |
text = "[project#3]"
|
|
| 71 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 72 |
end
|
|
| 67 |
def test_links_by_id_should_be_preserved |
|
| 68 |
text = "[project#3]" |
|
| 69 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 70 |
end |
|
| 73 | 71 | |
| 74 |
def test_links_to_users_should_be_preserved
|
|
| 75 |
text = "[@login]"
|
|
| 76 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 77 |
text = "[user:login]"
|
|
| 78 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 79 |
text = "user:user@example.org"
|
|
| 80 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 81 |
text = "[user:user@example.org]"
|
|
| 82 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 83 |
text = "@user@example.org"
|
|
| 84 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 85 |
text = "[@user@example.org]"
|
|
| 86 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 87 |
end
|
|
| 72 |
def test_links_to_users_should_be_preserved |
|
| 73 |
text = "[@login]" |
|
| 74 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 75 |
text = "[user:login]" |
|
| 76 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 77 |
text = "user:user@example.org" |
|
| 78 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 79 |
text = "[user:user@example.org]" |
|
| 80 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 81 |
text = "@user@example.org" |
|
| 82 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 83 |
text = "[@user@example.org]" |
|
| 84 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 85 |
end |
|
| 88 | 86 | |
| 89 |
def test_files_with_at_should_not_end_up_as_mailto_links
|
|
| 90 |
text = "printscreen@2x.png"
|
|
| 91 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 92 |
text = "[printscreen@2x.png]"
|
|
| 93 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 94 |
end
|
|
| 87 |
def test_files_with_at_should_not_end_up_as_mailto_links |
|
| 88 |
text = "printscreen@2x.png" |
|
| 89 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 90 |
text = "[printscreen@2x.png]" |
|
| 91 |
assert_equal "<p>#{text}</p>", to_html(text)
|
|
| 92 |
end |
|
| 95 | 93 | |
| 96 |
def test_should_support_syntax_highlight |
|
| 97 |
text = <<~STR |
|
| 98 |
~~~ruby |
|
| 99 |
def foo |
|
| 100 |
end |
|
| 101 |
~~~ |
|
| 102 |
STR |
|
| 103 |
assert_select_in to_html(text), 'pre code.ruby.syntaxhl' do |
|
| 104 |
assert_select 'span.k', :text => 'def' |
|
| 105 |
assert_select "[data-language='ruby']" |
|
| 94 |
def test_should_support_syntax_highlight |
|
| 95 |
text = <<~STR |
|
| 96 |
~~~ruby |
|
| 97 |
def foo |
|
| 106 | 98 |
end |
| 99 |
~~~ |
|
| 100 |
STR |
|
| 101 |
assert_select_in to_html(text), 'pre code.ruby.syntaxhl' do |
|
| 102 |
assert_select 'span.k', :text => 'def' |
|
| 103 |
assert_select "[data-language='ruby']" |
|
| 107 | 104 |
end |
| 105 |
end |
|
| 108 | 106 | |
| 109 |
def test_should_support_syntax_highlight_for_language_with_special_chars |
|
| 110 |
text = <<~STR |
|
| 111 |
~~~c++ |
|
| 112 |
int main() {
|
|
| 113 |
} |
|
| 114 |
~~~ |
|
| 115 |
STR |
|
| 116 | ||
| 117 |
assert_select_in to_html(text), 'pre' do |
|
| 118 |
assert_select 'code[class=?]', "c++ syntaxhl" |
|
| 119 |
assert_select 'span.kt', :text => 'int' |
|
| 120 |
assert_select "[data-language=?]", "c++" |
|
| 121 |
end |
|
| 107 |
def test_should_support_syntax_highlight_for_language_with_special_chars |
|
| 108 |
text = <<~STR |
|
| 109 |
~~~c++ |
|
| 110 |
int main() {
|
|
| 111 |
} |
|
| 112 |
~~~ |
|
| 113 |
STR |
|
| 114 | ||
| 115 |
assert_select_in to_html(text), 'pre' do |
|
| 116 |
assert_select 'code[class=?]', "c++ syntaxhl" |
|
| 117 |
assert_select 'span.kt', :text => 'int' |
|
| 118 |
assert_select "[data-language=?]", "c++" |
|
| 122 | 119 |
end |
| 120 |
end |
|
| 123 | 121 | |
| 124 |
def test_external_links_should_have_external_css_class
|
|
| 125 |
text = 'This is a [link](http://example.net/)'
|
|
| 126 |
assert_equal '<p>This is a <a href="http://example.net/" class="external">link</a></p>', to_html(text)
|
|
| 127 |
end
|
|
| 122 |
def test_external_links_should_have_external_css_class |
|
| 123 |
text = 'This is a [link](http://example.net/)' |
|
| 124 |
assert_equal '<p>This is a <a href="http://example.net/" class="external">link</a></p>', to_html(text) |
|
| 125 |
end |
|
| 128 | 126 | |
| 129 |
def test_locals_links_should_not_have_external_css_class
|
|
| 130 |
text = 'This is a [link](/issues)'
|
|
| 131 |
assert_equal '<p>This is a <a href="/issues">link</a></p>', to_html(text)
|
|
| 132 |
end
|
|
| 127 |
def test_locals_links_should_not_have_external_css_class |
|
| 128 |
text = 'This is a [link](/issues)' |
|
| 129 |
assert_equal '<p>This is a <a href="/issues">link</a></p>', to_html(text) |
|
| 130 |
end |
|
| 133 | 131 | |
| 134 |
def test_markdown_should_not_require_surrounded_empty_line
|
|
| 135 |
text = <<-STR
|
|
| 136 |
This is a list: |
|
| 137 |
* One |
|
| 138 |
* Two |
|
| 139 |
STR
|
|
| 140 |
assert_equal "<p>This is a list:</p>\n<ul>\n<li>One</li>\n<li>Two</li>\n</ul>", to_html(text)
|
|
| 141 |
end
|
|
| 132 |
def test_markdown_should_not_require_surrounded_empty_line |
|
| 133 |
text = <<~STR
|
|
| 134 |
This is a list:
|
|
| 135 |
* One
|
|
| 136 |
* Two
|
|
| 137 |
STR |
|
| 138 |
assert_equal "<p>This is a list:</p>\n<ul>\n<li>One</li>\n<li>Two</li>\n</ul>", to_html(text) |
|
| 139 |
end |
|
| 142 | 140 | |
| 143 |
def test_footnotes
|
|
| 144 |
text = <<~STR
|
|
| 145 |
This is some text[^1].
|
|
| 141 |
def test_footnotes |
|
| 142 |
text = <<~STR |
|
| 143 |
This is some text[^1]. |
|
| 146 | 144 | |
| 147 |
[^1]: This is the foot note
|
|
| 148 |
STR
|
|
| 145 |
[^1]: This is the foot note |
|
| 146 |
STR |
|
| 149 | 147 | |
| 150 |
expected = <<~EXPECTED
|
|
| 151 |
<p>This is some text<sup><a href="#fn-1" id="fnref-1">1</a></sup>.</p>
|
|
| 152 |
<ol>
|
|
| 153 |
<li id="fn-1">
|
|
| 154 |
<p>This is the foot note <a href="#fnref-1" aria-label="Back to reference 1">↩</a></p>
|
|
| 155 |
</li>
|
|
| 156 |
</ol>
|
|
| 157 |
EXPECTED
|
|
| 148 |
expected = <<~EXPECTED |
|
| 149 |
<p>This is some text<sup><a href="#fn-1" id="fnref-1">1</a></sup>.</p> |
|
| 150 |
<ol> |
|
| 151 |
<li id="fn-1"> |
|
| 152 |
<p>This is the foot note <a href="#fnref-1" aria-label="Back to reference 1">↩</a></p> |
|
| 153 |
</li> |
|
| 154 |
</ol> |
|
| 155 |
EXPECTED |
|
| 158 | 156 | |
| 159 |
assert_equal expected.gsub(%r{[\r\n\t]}, ''), to_html(text).gsub(%r{[\r\n\t]}, '').rstrip
|
|
| 160 |
end |
|
| 157 |
assert_equal expected.gsub(%r{[\r\n\t]}, ''), to_html(text).gsub(%r{[\r\n\t]}, '').rstrip
|
|
| 158 |
end |
|
| 159 | ||
| 160 |
STR_WITH_PRE = [ |
|
| 161 |
# 0 |
|
| 162 |
<<~STR.chomp, |
|
| 163 |
# Title |
|
| 161 | 164 | |
| 162 |
STR_WITH_PRE = [ |
|
| 163 |
# 0 |
|
| 164 |
<<~STR.chomp, |
|
| 165 |
# Title |
|
| 166 |
|
|
| 167 |
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero. |
|
| 168 |
STR |
|
| 169 |
# 1 |
|
| 170 |
<<~STR.chomp, |
|
| 171 |
## Heading 2 |
|
| 172 |
|
|
| 173 |
~~~ruby |
|
| 174 |
def foo |
|
| 175 |
end |
|
| 176 |
~~~ |
|
| 177 |
|
|
| 178 |
Morbi facilisis accumsan orci non pharetra. |
|
| 179 |
|
|
| 180 |
~~~ ruby |
|
| 165 |
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero. |
|
| 166 |
STR |
|
| 167 |
# 1 |
|
| 168 |
<<~STR.chomp, |
|
| 169 |
## Heading 2 |
|
| 170 | ||
| 171 |
~~~ruby |
|
| 181 | 172 |
def foo |
| 182 | 173 |
end |
| 183 |
~~~ |
|
| 184 |
|
|
| 185 |
``` |
|
| 186 |
Pre Content: |
|
| 187 |
|
|
| 188 |
## Inside pre |
|
| 189 |
|
|
| 190 |
<tag> inside pre block |
|
| 191 |
|
|
| 192 |
Morbi facilisis accumsan orci non pharetra. |
|
| 193 |
``` |
|
| 194 |
STR |
|
| 195 |
# 2 |
|
| 196 |
<<~STR.chomp, |
|
| 197 |
### Heading 3 |
|
| 198 |
|
|
| 199 |
Nulla nunc nisi, egestas in ornare vel, posuere ac libero. |
|
| 200 |
STR |
|
| 201 |
] |
|
| 202 | ||
| 203 |
def test_get_section_should_ignore_pre_content |
|
| 204 |
text = STR_WITH_PRE.join("\n\n")
|
|
| 205 | ||
| 206 |
assert_section_with_hash STR_WITH_PRE[1..2].join("\n\n"), text, 2
|
|
| 207 |
assert_section_with_hash STR_WITH_PRE[2], text, 3 |
|
| 208 |
end |
|
| 174 |
~~~ |
|
| 209 | 175 | |
| 210 |
def test_get_section_should_not_recognize_double_hash_issue_reference_as_heading |
|
| 211 |
text = <<~STR |
|
| 212 |
## Section A |
|
| 176 |
Morbi facilisis accumsan orci non pharetra. |
|
| 213 | 177 | |
| 214 |
This text is a part of Section A. |
|
| 178 |
~~~ ruby |
|
| 179 |
def foo |
|
| 180 |
end |
|
| 181 |
~~~ |
|
| 215 | 182 | |
| 216 |
##1 : This is an issue reference, not an ATX heading. |
|
| 183 |
``` |
|
| 184 |
Pre Content: |
|
| 217 | 185 | |
| 218 |
This text is also a part of Section A. |
|
| 219 |
<!-- Section A ends here --> |
|
| 220 |
STR |
|
| 186 |
## Inside pre |
|
| 221 | 187 | |
| 222 |
assert_section_with_hash text.chomp, text, 1 |
|
| 223 |
end |
|
| 188 |
<tag> inside pre block |
|
| 224 | 189 | |
| 225 |
def test_update_section_should_not_escape_pre_content_outside_section |
|
| 226 |
text = STR_WITH_PRE.join("\n\n")
|
|
| 227 |
replacement = "New text" |
|
| 190 |
Morbi facilisis accumsan orci non pharetra. |
|
| 191 |
``` |
|
| 192 |
STR |
|
| 193 |
# 2 |
|
| 194 |
<<~STR.chomp, |
|
| 195 |
### Heading 3 |
|
| 228 | 196 | |
| 229 |
assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"),
|
|
| 230 |
@formatter.new(text).update_section(3, replacement)
|
|
| 231 |
end
|
|
| 197 |
Nulla nunc nisi, egestas in ornare vel, posuere ac libero.
|
|
| 198 |
STR
|
|
| 199 |
]
|
|
| 232 | 200 | |
| 233 |
def test_should_emphasize_text |
|
| 234 |
text = 'This _text_ should be emphasized' |
|
| 235 |
assert_equal '<p>This <em>text</em> should be emphasized</p>', to_html(text) |
|
| 236 |
end |
|
| 201 |
def test_get_section_should_ignore_pre_content |
|
| 202 |
text = STR_WITH_PRE.join("\n\n")
|
|
| 237 | 203 | |
| 238 |
def test_should_strike_through_text |
|
| 239 |
text = 'This ~~text~~ should be striked through' |
|
| 240 |
assert_equal '<p>This <del>text</del> should be striked through</p>', to_html(text) |
|
| 241 |
end |
|
| 204 |
assert_section_with_hash STR_WITH_PRE[1..2].join("\n\n"), text, 2
|
|
| 205 |
assert_section_with_hash STR_WITH_PRE[2], text, 3 |
|
| 206 |
end |
|
| 242 | 207 | |
| 243 |
def test_should_autolink_urls_and_emails |
|
| 244 |
[ |
|
| 245 |
["http://example.org", '<p><a href="http://example.org" class="external">http://example.org</a></p>'], |
|
| 246 |
["http://www.redmine.org/projects/redmine/issues?utf8=✓", |
|
| 247 |
'<p><a href="http://www.redmine.org/projects/redmine/issues?utf8=%E2%9C%93" class="external">http://www.redmine.org/projects/redmine/issues?utf8=✓</a></p>'], |
|
| 248 |
['[Letters](https://yandex.ru/search/?text=кол-во)', '<p><a href="https://yandex.ru/search/?text=%D0%BA%D0%BE%D0%BB-%D0%B2%D0%BE" class="external">Letters</a></p>'], |
|
| 249 |
["www.example.org", '<p><a href="http://www.example.org" class="external">www.example.org</a></p>'], |
|
| 250 |
["user@example.org", '<p><a href="mailto:user@example.org" class="email">user@example.org</a></p>'] |
|
| 251 |
].each do |text, html| |
|
| 252 |
assert_equal html, to_html(text) |
|
| 253 |
end |
|
| 254 |
end |
|
| 208 |
def test_get_section_should_not_recognize_double_hash_issue_reference_as_heading |
|
| 209 |
text = <<~STR |
|
| 210 |
## Section A |
|
| 211 | ||
| 212 |
This text is a part of Section A. |
|
| 213 | ||
| 214 |
##1 : This is an issue reference, not an ATX heading. |
|
| 215 | ||
| 216 |
This text is also a part of Section A. |
|
| 217 |
<!-- Section A ends here --> |
|
| 218 |
STR |
|
| 219 | ||
| 220 |
assert_section_with_hash text.chomp, text, 1 |
|
| 221 |
end |
|
| 255 | 222 | |
| 256 |
def test_should_support_html_tables |
|
| 257 |
text = '<table style="background: red"><tr><td>Cell</td></tr></table>' |
|
| 258 |
assert_equal '<table><tr><td>Cell</td></tr></table>', to_html(text) |
|
| 223 |
def test_update_section_should_not_escape_pre_content_outside_section |
|
| 224 |
text = STR_WITH_PRE.join("\n\n")
|
|
| 225 |
replacement = "New text" |
|
| 226 | ||
| 227 |
assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"),
|
|
| 228 |
@formatter.new(text).update_section(3, replacement) |
|
| 229 |
end |
|
| 230 | ||
| 231 |
def test_should_emphasize_text |
|
| 232 |
text = 'This _text_ should be emphasized' |
|
| 233 |
assert_equal '<p>This <em>text</em> should be emphasized</p>', to_html(text) |
|
| 234 |
end |
|
| 235 | ||
| 236 |
def test_should_strike_through_text |
|
| 237 |
text = 'This ~~text~~ should be striked through' |
|
| 238 |
assert_equal '<p>This <del>text</del> should be striked through</p>', to_html(text) |
|
| 239 |
end |
|
| 240 | ||
| 241 |
def test_should_autolink_urls_and_emails |
|
| 242 |
[ |
|
| 243 |
["http://example.org", '<p><a href="http://example.org" class="external">http://example.org</a></p>'], |
|
| 244 |
["http://www.redmine.org/projects/redmine/issues?utf8=✓", |
|
| 245 |
'<p><a href="http://www.redmine.org/projects/redmine/issues?utf8=%E2%9C%93" class="external">http://www.redmine.org/projects/redmine/issues?utf8=✓</a></p>'], |
|
| 246 |
['[Letters](https://yandex.ru/search/?text=кол-во)', '<p><a href="https://yandex.ru/search/?text=%D0%BA%D0%BE%D0%BB-%D0%B2%D0%BE" class="external">Letters</a></p>'], |
|
| 247 |
["www.example.org", '<p><a href="http://www.example.org" class="external">www.example.org</a></p>'], |
|
| 248 |
["user@example.org", '<p><a href="mailto:user@example.org" class="email">user@example.org</a></p>'] |
|
| 249 |
].each do |text, html| |
|
| 250 |
assert_equal html, to_html(text) |
|
| 259 | 251 |
end |
| 252 |
end |
|
| 260 | 253 | |
| 261 |
def test_should_remove_unsafe_uris |
|
| 262 |
[ |
|
| 263 |
['<img src="data:foobar">', '<img>'], |
|
| 264 |
['<a href="javascript:bla">click me</a>', '<p><a>click me</a></p>'], |
|
| 265 |
].each do |text, html| |
|
| 266 |
assert_equal html, to_html(text) |
|
| 267 |
end |
|
| 254 |
def test_should_support_html_tables |
|
| 255 |
text = '<table style="background: red"><tr><td>Cell</td></tr></table>' |
|
| 256 |
assert_equal '<table><tr><td>Cell</td></tr></table>', to_html(text) |
|
| 257 |
end |
|
| 258 | ||
| 259 |
def test_should_remove_unsafe_uris |
|
| 260 |
[ |
|
| 261 |
['<img src="data:foobar">', '<img>'], |
|
| 262 |
['<a href="javascript:bla">click me</a>', '<p><a>click me</a></p>'], |
|
| 263 |
].each do |text, html| |
|
| 264 |
assert_equal html, to_html(text) |
|
| 268 | 265 |
end |
| 266 |
end |
|
| 269 | 267 | |
| 270 |
def test_should_escape_unwanted_tags |
|
| 268 |
def test_should_escape_unwanted_tags |
|
| 269 |
[ |
|
| 271 | 270 |
[ |
| 272 |
[ |
|
| 273 |
%[<p>sit<br>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script></p>],
|
|
| 274 |
%[sit<br/>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script>]
|
|
| 275 |
] |
|
| 276 |
].each do |expected, input| |
|
| 277 |
assert_equal expected, to_html(input) |
|
| 278 |
end |
|
| 271 |
%[<p>sit<br>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script></p>],
|
|
| 272 |
%[sit<br/>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script>]
|
|
| 273 |
] |
|
| 274 |
].each do |expected, input| |
|
| 275 |
assert_equal expected, to_html(input) |
|
| 279 | 276 |
end |
| 277 |
end |
|
| 280 | 278 | |
| 281 |
def test_should_support_task_list
|
|
| 282 |
text = <<~STR
|
|
| 283 |
Task list:
|
|
| 284 |
* [ ] Task 1
|
|
| 285 |
* [x] Task 2
|
|
| 286 |
STR
|
|
| 287 | ||
| 288 |
expected = <<~EXPECTED
|
|
| 289 |
<p>Task list:</p>
|
|
| 290 |
<ul class="task-list">
|
|
| 291 |
<li class="task-list-item">
|
|
| 292 |
<input type="checkbox" class="task-list-item-checkbox" disabled> Task 1
|
|
| 293 |
</li>
|
|
| 294 |
<li class="task-list-item">
|
|
| 295 |
<input type="checkbox" class="task-list-item-checkbox" checked disabled> Task 2</li>
|
|
| 296 |
</ul>
|
|
| 297 |
EXPECTED
|
|
| 298 | ||
| 299 |
assert_equal expected.gsub(%r{[\r\n\t]}, ''), to_html(text).gsub(%r{[\r\n\t]}, '').rstrip
|
|
| 300 |
end
|
|
| 279 |
def test_should_support_task_list |
|
| 280 |
text = <<~STR |
|
| 281 |
Task list: |
|
| 282 |
* [ ] Task 1 |
|
| 283 |
* [x] Task 2 |
|
| 284 |
STR |
|
| 285 | ||
| 286 |
expected = <<~EXPECTED |
|
| 287 |
<p>Task list:</p> |
|
| 288 |
<ul class="task-list"> |
|
| 289 |
<li class="task-list-item"> |
|
| 290 |
<input type="checkbox" class="task-list-item-checkbox" disabled> Task 1 |
|
| 291 |
</li> |
|
| 292 |
<li class="task-list-item"> |
|
| 293 |
<input type="checkbox" class="task-list-item-checkbox" checked disabled> Task 2</li> |
|
| 294 |
</ul> |
|
| 295 |
EXPECTED |
|
| 296 | ||
| 297 |
assert_equal expected.gsub(%r{[\r\n\t]}, ''), to_html(text).gsub(%r{[\r\n\t]}, '').rstrip
|
|
| 298 |
end |
|
| 301 | 299 | |
| 302 |
private
|
|
| 300 |
private |
|
| 303 | 301 | |
| 304 |
def assert_section_with_hash(expected, text, index)
|
|
| 305 |
result = @formatter.new(text).get_section(index)
|
|
| 302 |
def assert_section_with_hash(expected, text, index) |
|
| 303 |
result = @formatter.new(text).get_section(index) |
|
| 306 | 304 | |
| 307 |
assert_kind_of Array, result |
|
| 308 |
assert_equal 2, result.size |
|
| 309 |
assert_equal expected, result.first, "section content did not match" |
|
| 310 |
assert_equal ActiveSupport::Digest.hexdigest(expected), result.last, "section hash did not match" |
|
| 311 |
end |
|
| 305 |
assert_kind_of Array, result |
|
| 306 |
assert_equal 2, result.size |
|
| 307 |
assert_equal expected, result.first, "section content did not match" |
|
| 308 |
assert_equal ActiveSupport::Digest.hexdigest(expected), result.last, "section hash did not match" |
|
| 312 | 309 |
end |
| 313 | 310 |
end |
| test/unit/lib/redmine/wiki_formatting/common_mark/markdown_filter_test.rb | ||
|---|---|---|
| 18 | 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 19 | 19 | |
| 20 | 20 |
require_relative '../../../../../test_helper' |
| 21 |
require 'redmine/wiki_formatting/common_mark/markdown_filter' |
|
| 21 | 22 | |
| 22 |
if Object.const_defined?(:Commonmarker) |
|
| 23 |
require 'redmine/wiki_formatting/common_mark/markdown_filter' |
|
| 24 | ||
| 25 |
class Redmine::WikiFormatting::CommonMark::MarkdownFilterTest < ActiveSupport::TestCase |
|
| 26 |
def filter(markdown) |
|
| 27 |
Redmine::WikiFormatting::CommonMark::MarkdownFilter.to_html(markdown) |
|
| 28 |
end |
|
| 23 |
class Redmine::WikiFormatting::CommonMark::MarkdownFilterTest < ActiveSupport::TestCase |
|
| 24 |
def filter(markdown) |
|
| 25 |
Redmine::WikiFormatting::CommonMark::MarkdownFilter.to_html(markdown) |
|
| 26 |
end |
|
| 29 | 27 | |
| 30 |
# just a basic sanity test. more formatting tests in the formatter_test |
|
| 31 |
def test_should_render_markdown |
|
| 32 |
assert_equal "<p><strong>bold</strong></p>", filter("**bold**")
|
|
| 33 |
end |
|
| 28 |
# just a basic sanity test. more formatting tests in the formatter_test |
|
| 29 |
def test_should_render_markdown |
|
| 30 |
assert_equal "<p><strong>bold</strong></p>", filter("**bold**")
|
|
| 34 | 31 |
end |
| 35 | 32 |
end |
| test/unit/lib/redmine/wiki_formatting/common_mark/sanitization_filter_test.rb | ||
|---|---|---|
| 18 | 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 19 | 19 | |
| 20 | 20 |
require_relative '../../../../../test_helper' |
| 21 |
require 'redmine/wiki_formatting/common_mark/sanitization_filter' |
|
| 21 | 22 | |
| 22 |
if Object.const_defined?(:Commonmarker) |
|
| 23 |
require 'redmine/wiki_formatting/common_mark/sanitization_filter' |
|
| 23 |
class Redmine::WikiFormatting::CommonMark::SanitizationFilterTest < ActiveSupport::TestCase |
|
| 24 |
def filter(html) |
|
| 25 |
Redmine::WikiFormatting::CommonMark::SanitizationFilter.to_html(html, @options) |
|
| 26 |
end |
|
| 24 | 27 | |
| 25 |
class Redmine::WikiFormatting::CommonMark::SanitizationFilterTest < ActiveSupport::TestCase |
|
| 26 |
def filter(html) |
|
| 27 |
Redmine::WikiFormatting::CommonMark::SanitizationFilter.to_html(html, @options) |
|
| 28 |
end |
|
| 28 |
def setup |
|
| 29 |
@options = { }
|
|
| 30 |
end |
|
| 29 | 31 | |
| 30 |
def setup |
|
| 31 |
@options = { }
|
|
| 32 |
end |
|
| 32 |
def test_should_filter_tags |
|
| 33 |
input = %(<textarea>foo</textarea> <blink>dont blink</blink>) |
|
| 34 |
assert_equal %(foo dont blink), filter(input) |
|
| 35 |
end |
|
| 33 | 36 | |
| 34 |
def test_should_filter_tags
|
|
| 35 |
input = %(<textarea>foo</textarea> <blink>dont blink</blink>)
|
|
| 36 |
assert_equal %(foo dont blink), filter(input)
|
|
| 37 |
end
|
|
| 37 |
def test_should_sanitize_attributes
|
|
| 38 |
input = %(<a href="foo" onclick="bar" baz="foo">link</a>)
|
|
| 39 |
assert_equal %(<a href="foo">link</a>), filter(input)
|
|
| 40 |
end |
|
| 38 | 41 | |
| 39 |
def test_should_sanitize_attributes
|
|
| 40 |
input = %(<a href="foo" onclick="bar" baz="foo">link</a>)
|
|
| 41 |
assert_equal %(<a href="foo">link</a>), filter(input)
|
|
| 42 |
end
|
|
| 42 |
def test_should_allow_relative_links
|
|
| 43 |
input = %(<a href="foo/bar">foo/bar</a>)
|
|
| 44 |
assert_equal input, filter(input)
|
|
| 45 |
end |
|
| 43 | 46 | |
| 44 |
def test_should_allow_relative_links |
|
| 45 |
input = %(<a href="foo/bar">foo/bar</a>) |
|
| 46 |
assert_equal input, filter(input) |
|
| 47 |
end |
|
| 47 |
def test_should_support_footnotes |
|
| 48 |
input = %(<a href="#fn-1" id="fnref-1">foo</a>) |
|
| 49 |
assert_equal input, filter(input) |
|
| 50 |
input = %(<ol><li id="fn-1">footnote</li></ol>) |
|
| 51 |
assert_equal input, filter(input) |
|
| 52 |
end |
|
| 48 | 53 | |
| 49 |
def test_should_support_footnotes
|
|
| 50 |
input = %(<a href="#fn-1" id="fnref-1">foo</a>)
|
|
| 51 |
assert_equal input, filter(input)
|
|
| 52 |
input = %(<ol><li id="fn-1">footnote</li></ol>)
|
|
| 53 |
assert_equal input, filter(input)
|
|
| 54 |
end
|
|
| 54 |
def test_should_remove_invalid_ids
|
|
| 55 |
input = %(<a href="#fn1" id="foo">foo</a>)
|
|
| 56 |
assert_equal %(<a href="#fn1">foo</a>), filter(input)
|
|
| 57 |
input = %(<ol><li id="foo">footnote</li></ol>)
|
|
| 58 |
assert_equal %(<ol><li>footnote</li></ol>), filter(input)
|
|
| 59 |
end |
|
| 55 | 60 | |
| 56 |
def test_should_remove_invalid_ids |
|
| 57 |
input = %(<a href="#fn1" id="foo">foo</a>) |
|
| 58 |
assert_equal %(<a href="#fn1">foo</a>), filter(input) |
|
| 59 |
input = %(<ol><li id="foo">footnote</li></ol>) |
|
| 60 |
assert_equal %(<ol><li>footnote</li></ol>), filter(input) |
|
| 61 |
end |
|
| 61 |
def test_should_allow_class_on_code_only |
|
| 62 |
input = %(<p class="foo">bar</p>) |
|
| 63 |
assert_equal %(<p>bar</p>), filter(input) |
|
| 62 | 64 | |
| 63 |
def test_should_allow_class_on_code_only |
|
| 64 |
input = %(<p class="foo">bar</p>) |
|
| 65 |
assert_equal %(<p>bar</p>), filter(input) |
|
| 65 |
input = %(<code class="language-ruby">foo</code>) |
|
| 66 |
assert_equal input, filter(input) |
|
| 66 | 67 | |
| 67 |
input = %(<code class="language-ruby">foo</code>) |
|
| 68 |
assert_equal input, filter(input) |
|
| 68 |
input = %(<code class="foo">foo</code>) |
|
| 69 |
assert_equal %(<code>foo</code>), filter(input) |
|
| 70 |
end |
|
| 69 | 71 | |
| 70 |
input = %(<code class="foo">foo</code>) |
|
| 71 |
assert_equal %(<code>foo</code>), filter(input) |
|
| 72 |
def test_should_allow_links_with_safe_url_schemes |
|
| 73 |
%w(http https ftp ssh foo).each do |scheme| |
|
| 74 |
input = %(<a href="#{scheme}://example.org/">foo</a>)
|
|
| 75 |
assert_equal input, filter(input) |
|
| 72 | 76 |
end |
| 77 |
end |
|
| 73 | 78 | |
| 74 |
def test_should_allow_links_with_safe_url_schemes |
|
| 75 |
%w(http https ftp ssh foo).each do |scheme| |
|
| 76 |
input = %(<a href="#{scheme}://example.org/">foo</a>)
|
|
| 77 |
assert_equal input, filter(input) |
|
| 78 |
end |
|
| 79 |
end |
|
| 79 |
def test_should_allow_mailto_links |
|
| 80 |
input = %(<a href="mailto:foo@example.org">bar</a>) |
|
| 81 |
assert_equal input, filter(input) |
|
| 82 |
end |
|
| 80 | 83 | |
| 81 |
def test_should_allow_mailto_links |
|
| 82 |
input = %(<a href="mailto:foo@example.org">bar</a>) |
|
| 83 |
assert_equal input, filter(input) |
|
| 84 |
end |
|
| 84 |
def test_should_remove_empty_link |
|
| 85 |
input = %(<a href="">bar</a>) |
|
| 86 |
assert_equal %(<a>bar</a>), filter(input) |
|
| 87 |
input = %(<a href=" ">bar</a>) |
|
| 88 |
assert_equal %(<a>bar</a>), filter(input) |
|
| 89 |
end |
|
| 90 | ||
| 91 |
# samples taken from the Sanitize test suite |
|
| 92 |
# rubocop:disable Layout/LineLength |
|
| 93 |
STRINGS = [ |
|
| 94 |
[ |
|
| 95 |
'<span style="color: #333; background: url(\'https://example.com/evil.svg\')">hello</span>"', |
|
| 96 |
'<span style="color: #333; ">hello</span>"' |
|
| 97 |
], |
|
| 98 |
[ |
|
| 99 |
'<img src="photo.jpg" style="min-width: 100px; max-width: 200px; min-height: 100px; max-height: 200px;">', |
|
| 100 |
'<img src="photo.jpg" style="min-width: 100px; max-width: 200px; min-height: 100px; max-height: 200px;">' |
|
| 101 |
], |
|
| 102 |
[ |
|
| 103 |
'<b>Lo<!-- comment -->rem</b> <a href="pants" title="foo" style="text-decoration: underline;">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script>',
|
|
| 104 |
'<b>Lorem</b> <a href="pants" title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet .foo { color: #fff; } '
|
|
| 105 |
], |
|
| 106 |
[ |
|
| 107 |
'Lo<!-- comment -->rem</b> <a href=pants title="foo>ipsum <a href="http://foo.com/"><strong>dolor</a></strong> sit<br/>amet <script>alert("hello world");',
|
|
| 108 |
'Lorem <a href="pants" title="foo>ipsum <a href="><strong>dolor</strong></a> sit<br>amet ' |
|
| 109 |
], |
|
| 110 |
[ |
|
| 111 |
'<p>a</p><blockquote>b', |
|
| 112 |
'<p>a</p><blockquote>b</blockquote>' |
|
| 113 |
], |
|
| 114 |
[ |
|
| 115 |
'<b>Lo<!-- comment -->rem</b> <a href="javascript:pants" title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <<foo>script>alert("hello world");</script>',
|
|
| 116 |
'<b>Lorem</b> <a title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet <script>alert("hello world");'
|
|
| 117 |
] |
|
| 118 |
] |
|
| 119 |
# rubocop:enable Layout/LineLength |
|
| 85 | 120 | |
| 86 |
def test_should_remove_empty_link |
|
| 87 |
input = %(<a href="">bar</a>) |
|
| 88 |
assert_equal %(<a>bar</a>), filter(input) |
|
| 89 |
input = %(<a href=" ">bar</a>) |
|
| 90 |
assert_equal %(<a>bar</a>), filter(input) |
|
| 121 |
def test_should_sanitize_html_strings |
|
| 122 |
STRINGS.each do |input, expected| |
|
| 123 |
assert_equal expected, filter(input) |
|
| 91 | 124 |
end |
| 125 |
end |
|
| 126 | ||
| 127 |
# samples taken from the Sanitize test suite |
|
| 128 |
PROTOCOLS = {
|
|
| 129 |
'protocol-based JS injection: simple, no spaces' => [ |
|
| 130 |
'<a href="javascript:alert(\'XSS\');">foo</a>', |
|
| 131 |
'<a>foo</a>' |
|
| 132 |
], |
|
| 133 | ||
| 134 |
'protocol-based JS injection: simple, spaces before' => [ |
|
| 135 |
'<a href="javascript :alert(\'XSS\');">foo</a>', |
|
| 136 |
'<a>foo</a>' |
|
| 137 |
], |
|
| 138 | ||
| 139 |
'protocol-based JS injection: simple, spaces after' => [ |
|
| 140 |
'<a href="javascript: alert(\'XSS\');">foo</a>', |
|
| 141 |
'<a>foo</a>' |
|
| 142 |
], |
|
| 143 | ||
| 144 |
'protocol-based JS injection: simple, spaces before and after' => [ |
|
| 145 |
'<a href="javascript : alert(\'XSS\');">foo</a>', |
|
| 146 |
'<a>foo</a>' |
|
| 147 |
], |
|
| 148 | ||
| 149 |
'protocol-based JS injection: preceding colon' => [ |
|
| 150 |
'<a href=":javascript:alert(\'XSS\');">foo</a>', |
|
| 151 |
'<a>foo</a>' |
|
| 152 |
], |
|
| 153 | ||
| 154 |
'protocol-based JS injection: UTF-8 encoding' => [ |
|
| 155 |
'<a href="javascript:">foo</a>', |
|
| 156 |
'<a>foo</a>' |
|
| 157 |
], |
|
| 158 | ||
| 159 |
'protocol-based JS injection: long UTF-8 encoding' => [ |
|
| 160 |
'<a href="javascript:">foo</a>', |
|
| 161 |
'<a>foo</a>' |
|
| 162 |
], |
|
| 92 | 163 | |
| 93 |
# samples taken from the Sanitize test suite |
|
| 94 | 164 |
# rubocop:disable Layout/LineLength |
| 95 |
STRINGS = [ |
|
| 96 |
[ |
|
| 97 |
'<span style="color: #333; background: url(\'https://example.com/evil.svg\')">hello</span>"', |
|
| 98 |
'<span style="color: #333; ">hello</span>"' |
|
| 99 |
], |
|
| 100 |
[ |
|
| 101 |
'<img src="photo.jpg" style="min-width: 100px; max-width: 200px; min-height: 100px; max-height: 200px;">', |
|
| 102 |
'<img src="photo.jpg" style="min-width: 100px; max-width: 200px; min-height: 100px; max-height: 200px;">' |
|
| 103 |
], |
|
| 104 |
[ |
|
| 105 |
'<b>Lo<!-- comment -->rem</b> <a href="pants" title="foo" style="text-decoration: underline;">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script>',
|
|
| 106 |
'<b>Lorem</b> <a href="pants" title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet .foo { color: #fff; } '
|
|
| 107 |
], |
|
| 108 |
[ |
|
| 109 |
'Lo<!-- comment -->rem</b> <a href=pants title="foo>ipsum <a href="http://foo.com/"><strong>dolor</a></strong> sit<br/>amet <script>alert("hello world");',
|
|
| 110 |
'Lorem <a href="pants" title="foo>ipsum <a href="><strong>dolor</strong></a> sit<br>amet ' |
|
| 111 |
], |
|
| 112 |
[ |
|
| 113 |
'<p>a</p><blockquote>b', |
|
| 114 |
'<p>a</p><blockquote>b</blockquote>' |
|
| 115 |
], |
|
| 116 |
[ |
|
| 117 |
'<b>Lo<!-- comment -->rem</b> <a href="javascript:pants" title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <<foo>script>alert("hello world");</script>',
|
|
| 118 |
'<b>Lorem</b> <a title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet <script>alert("hello world");'
|
|
| 119 |
] |
|
| 120 |
] |
|
| 165 |
'protocol-based JS injection: long UTF-8 encoding without semicolons' => [ |
|
| 166 |
'<a href=javascript:alert('XSS')>foo</a>', |
|
| 167 |
'<a>foo</a>' |
|
| 168 |
], |
|
| 121 | 169 |
# rubocop:enable Layout/LineLength |
| 122 | 170 | |
| 123 |
def test_should_sanitize_html_strings |
|
| 124 |
STRINGS.each do |input, expected| |
|
| 125 |
assert_equal expected, filter(input) |
|
| 126 |
end |
|
| 127 |
end |
|
| 128 | ||
| 129 |
# samples taken from the Sanitize test suite |
|
| 130 |
PROTOCOLS = {
|
|
| 131 |
'protocol-based JS injection: simple, no spaces' => [ |
|
| 132 |
'<a href="javascript:alert(\'XSS\');">foo</a>', |
|
| 133 |
'<a>foo</a>' |
|
| 134 |
], |
|
| 135 | ||
| 136 |
'protocol-based JS injection: simple, spaces before' => [ |
|
| 137 |
'<a href="javascript :alert(\'XSS\');">foo</a>', |
|
| 138 |
'<a>foo</a>' |
|
| 139 |
], |
|
| 140 | ||
| 141 |
'protocol-based JS injection: simple, spaces after' => [ |
|
| 142 |
'<a href="javascript: alert(\'XSS\');">foo</a>', |
|
| 143 |
'<a>foo</a>' |
|
| 144 |
], |
|
| 145 | ||
| 146 |
'protocol-based JS injection: simple, spaces before and after' => [ |
|
| 147 |
'<a href="javascript : alert(\'XSS\');">foo</a>', |
|
| 148 |
'<a>foo</a>' |
|
| 149 |
], |
|
| 150 | ||
| 151 |
'protocol-based JS injection: preceding colon' => [ |
|
| 152 |
'<a href=":javascript:alert(\'XSS\');">foo</a>', |
|
| 153 |
'<a>foo</a>' |
|
| 154 |
], |
|
| 155 | ||
| 156 |
'protocol-based JS injection: UTF-8 encoding' => [ |
|
| 157 |
'<a href="javascript:">foo</a>', |
|
| 158 |
'<a>foo</a>' |
|
| 159 |
], |
|
| 160 | ||
| 161 |
'protocol-based JS injection: long UTF-8 encoding' => [ |
|
| 162 |
'<a href="javascript:">foo</a>', |
|
| 163 |
'<a>foo</a>' |
|
| 164 |
], |
|
| 165 | ||
| 166 |
# rubocop:disable Layout/LineLength |
|
| 167 |
'protocol-based JS injection: long UTF-8 encoding without semicolons' => [ |
|
| 168 |
'<a href=javascript:alert('XSS')>foo</a>', |
|
| 169 |
'<a>foo</a>' |
|
| 170 |
], |
|
| 171 |
# rubocop:enable Layout/LineLength |
|
| 172 | ||
| 173 |
'protocol-based JS injection: hex encoding' => [ |
|
| 174 |
'<a href="javascript:">foo</a>', |
|
| 175 |
'<a>foo</a>' |
|
| 176 |
], |
|
| 177 | ||
| 178 |
'protocol-based JS injection: long hex encoding' => [ |
|
| 179 |
'<a href="javascript:">foo</a>', |
|
| 180 |
'<a>foo</a>' |
|
| 181 |
], |
|
| 182 | ||
| 183 |
'protocol-based JS injection: hex encoding without semicolons' => [ |
|
| 184 |
'<a href=javascript:alert('XSS')>foo</a>', |
|
| 185 |
'<a>foo</a>' |
|
| 186 |
], |
|
| 187 | ||
| 188 |
'protocol-based JS injection: null char' => [ |
|
| 189 |
"<img src=java\0script:alert(\"XSS\")>", |
|
| 190 |
'<img src="java">' |
|
| 191 |
# '<img>' |
|
| 192 |
], |
|
| 193 | ||
| 194 |
'protocol-based JS injection: invalid URL char' => [ |
|
| 195 |
'<img src=java\script:alert("XSS")>',
|
|
| 196 |
'<img>' |
|
| 197 |
], |
|
| 198 | ||
| 199 |
'protocol-based JS injection: spaces and entities' => [ |
|
| 200 |
'<img src="  javascript:alert(\'XSS\');">', |
|
| 201 |
'<img src="">' |
|
| 202 |
# '<img>' |
|
| 203 |
], |
|
| 204 | ||
| 205 |
'protocol whitespace' => [ |
|
| 206 |
'<a href=" http://example.com/"></a>', |
|
| 207 |
'<a href="http://example.com/"></a>' |
|
| 208 |
], |
|
| 209 | ||
| 210 |
'data images sources' => [ |
|
| 211 |
'<img src="data:image/png;base64,foobar">', |
|
| 212 |
'<img>' |
|
| 213 |
], |
|
| 214 | ||
| 215 |
'data URIs' => [ |
|
| 216 |
'<a href="data:text/html;base64,foobar">XSS</a>', |
|
| 217 |
'<a>XSS</a>' |
|
| 218 |
], |
|
| 219 | ||
| 220 |
'vbscript URIs' => [ |
|
| 221 |
'<a href="vbscript:foobar">XSS</a>', |
|
| 222 |
'<a>XSS</a>' |
|
| 223 |
], |
|
| 224 |
} |
|
| 225 | ||
| 226 |
PROTOCOLS.each do |name, strings| |
|
| 227 |
test "should not allow #{name}" do
|
|
| 228 |
input, expected = *strings |
|
| 229 |
assert_equal expected, filter(input) |
|
| 230 |
end |
|
| 171 |
'protocol-based JS injection: hex encoding' => [ |
|
| 172 |
'<a href="javascript:">foo</a>', |
|
| 173 |
'<a>foo</a>' |
|
| 174 |
], |
|
| 175 | ||
| 176 |
'protocol-based JS injection: long hex encoding' => [ |
|
| 177 |
'<a href="javascript:">foo</a>', |
|
| 178 |
'<a>foo</a>' |
|
| 179 |
], |
|
| 180 | ||
| 181 |
'protocol-based JS injection: hex encoding without semicolons' => [ |
|
| 182 |
'<a href=javascript:alert('XSS')>foo</a>', |
|
| 183 |
'<a>foo</a>' |
|
| 184 |
], |
|
| 185 | ||
| 186 |
'protocol-based JS injection: null char' => [ |
|
| 187 |
"<img src=java\0script:alert(\"XSS\")>", |
|
| 188 |
'<img src="java">' |
|
| 189 |
# '<img>' |
|
| 190 |
], |
|
| 191 | ||
| 192 |
'protocol-based JS injection: invalid URL char' => [ |
|
| 193 |
'<img src=java\script:alert("XSS")>',
|
|
| 194 |
'<img>' |
|
| 195 |
], |
|
| 196 | ||
| 197 |
'protocol-based JS injection: spaces and entities' => [ |
|
| 198 |
'<img src="  javascript:alert(\'XSS\');">', |
|
| 199 |
'<img src="">' |
|
| 200 |
# '<img>' |
|
| 201 |
], |
|
| 202 | ||
| 203 |
'protocol whitespace' => [ |
|
| 204 |
'<a href=" http://example.com/"></a>', |
|
| 205 |
'<a href="http://example.com/"></a>' |
|
| 206 |
], |
|
| 207 | ||
| 208 |
'data images sources' => [ |
|
| 209 |
'<img src="data:image/png;base64,foobar">', |
|
| 210 |
'<img>' |
|
| 211 |
], |
|
| 212 | ||
| 213 |
'data URIs' => [ |
|
| 214 |
'<a href="data:text/html;base64,foobar">XSS</a>', |
|
| 215 |
'<a>XSS</a>' |
|
| 216 |
], |
|
| 217 | ||
| 218 |
'vbscript URIs' => [ |
|
| 219 |
'<a href="vbscript:foobar">XSS</a>', |
|
| 220 |
'<a>XSS</a>' |
|
| 221 |
], |
|
| 222 |
} |
|
| 223 | ||
| 224 |
PROTOCOLS.each do |name, strings| |
|
| 225 |
test "should not allow #{name}" do
|
|
| 226 |
input, expected = *strings |
|
| 227 |
assert_equal expected, filter(input) |
|
| 231 | 228 |
end |
| 232 | 229 |
end |
| 233 | 230 |
end |
| test/unit/lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter_test.rb | ||
|---|---|---|
| 18 | 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 19 | 19 | |
| 20 | 20 |
require_relative '../../../../../test_helper' |
| 21 |
if Object.const_defined?(:Commonmarker) |
|
| 22 |
require 'redmine/wiki_formatting/common_mark/syntax_highlight_filter' |
|
| 21 |
require 'redmine/wiki_formatting/common_mark/syntax_highlight_filter' |
|
| 23 | 22 | |
| 24 |
class Redmine::WikiFormatting::CommonMark::SyntaxHighlightFilterTest < ActiveSupport::TestCase
|
|
| 25 |
def filter(html)
|
|
| 26 |
Redmine::WikiFormatting::CommonMark::SyntaxHighlightFilter.to_html(html, @options)
|
|
| 27 |
end
|
|
| 23 |
class Redmine::WikiFormatting::CommonMark::SyntaxHighlightFilterTest < ActiveSupport::TestCase |
|
| 24 |
def filter(html) |
|
| 25 |
Redmine::WikiFormatting::CommonMark::SyntaxHighlightFilter.to_html(html, @options) |
|
| 26 |
end |
|
| 28 | 27 | |
| 29 |
def setup
|
|
| 30 |
@options = { }
|
|
| 31 |
end
|
|
| 28 |
def setup |
|
| 29 |
@options = { }
|
|
| 30 |
end |
|
| 32 | 31 | |
| 33 |
def test_should_highlight_supported_language
|
|
| 34 |
input = <<~HTML
|
|
| 35 |
<pre><code class="language-ruby">
|
|
| 36 |
def foo
|
|
| 37 |
end
|
|
| 38 |
</code></pre>
|
|
| 39 |
HTML
|
|
| 40 |
expected = <<~HTML
|
|
| 41 |
<pre><code class="ruby syntaxhl" data-language="ruby">
|
|
| 42 |
<span class="k">def</span> <span class="nf">foo</span>
|
|
| 43 |
<span class="k">end</span>
|
|
| 44 |
</code></pre>
|
|
| 45 |
HTML
|
|
| 46 |
assert_equal expected, filter(input)
|
|
| 47 |
end
|
|
| 32 |
def test_should_highlight_supported_language |
|
| 33 |
input = <<~HTML |
|
| 34 |
<pre><code class="language-ruby"> |
|
| 35 |
def foo |
|
| 36 |
end |
|
| 37 |
</code></pre> |
|
| 38 |
HTML |
|
| 39 |
expected = <<~HTML |
|
| 40 |
<pre><code class="ruby syntaxhl" data-language="ruby"> |
|
| 41 |
<span class="k">def</span> <span class="nf">foo</span> |
|
| 42 |
<span class="k">end</span> |
|
| 43 |
</code></pre> |
|
| 44 |
HTML |
|
| 45 |
assert_equal expected, filter(input) |
|
| 46 |
end |
|
| 48 | 47 | |
| 49 |
def test_should_highlight_supported_language_with_special_chars
|
|
| 50 |
input = <<~HTML
|
|
| 51 |
<pre><code class="language-c-k&r">
|
|
| 52 |
int i;
|
|
| 53 |
</code></pre>
|
|
| 54 |
HTML
|
|
| 55 |
expected = <<~HTML
|
|
| 56 |
<pre><code data-language="c-k&r">
|
|
| 57 |
int i;
|
|
| 58 |
</code></pre>
|
|
| 59 |
HTML
|
|
| 60 |
assert_equal expected, filter(input)
|
|
| 61 |
end
|
|
| 48 |
def test_should_highlight_supported_language_with_special_chars |
|
| 49 |
input = <<~HTML |
|
| 50 |
<pre><code class="language-c-k&r"> |
|
| 51 |
int i; |
|
| 52 |
</code></pre> |
|
| 53 |
HTML |
|
| 54 |
expected = <<~HTML |
|
| 55 |
<pre><code data-language="c-k&r"> |
|
| 56 |
int i; |
|
| 57 |
</code></pre> |
|
| 58 |
HTML |
|
| 59 |
assert_equal expected, filter(input) |
|
| 60 |
end |
|
| 62 | 61 | |
| 63 |
def test_should_strip_code_class_and_preserve_data_language_attr_for_unknown_language
|
|
| 64 |
input = <<~HTML
|
|
| 65 |
<pre><code class="language-foobar">
|
|
| 66 |
def foo
|
|
| 67 |
end
|
|
| 68 |
</code></pre>
|
|
| 69 |
HTML
|
|
| 70 |
expected = <<~HTML
|
|
| 71 |
<pre><code data-language="foobar">
|
|
| 72 |
def foo
|
|
| 73 |
end
|
|
| 74 |
</code></pre>
|
|
| 75 |
HTML
|
|
| 76 |
assert_equal expected, filter(input)
|
|
| 77 |
end
|
|
| 62 |
def test_should_strip_code_class_and_preserve_data_language_attr_for_unknown_language |
|
| 63 |
input = <<~HTML |
|
| 64 |
<pre><code class="language-foobar"> |
|
| 65 |
def foo |
|
| 66 |
end |
|
| 67 |
</code></pre> |
|
| 68 |
HTML |
|
| 69 |
expected = <<~HTML |
|
| 70 |
<pre><code data-language="foobar"> |
|
| 71 |
def foo |
|
| 72 |
end |
|
| 73 |
</code></pre> |
|
| 74 |
HTML |
|
| 75 |
assert_equal expected, filter(input) |
|
| 76 |
end |
|
| 78 | 77 | |
| 79 |
def test_should_ignore_code_without_class |
|
| 80 |
input = <<~HTML |
|
| 81 |
<pre><code> |
|
| 82 |
def foo |
|
| 83 |
end |
|
| 84 |
</code></pre> |
|
| 85 |
HTML |
|
| 86 |
assert_equal input, filter(input) |
|
| 87 |
end |
|
| 78 |
def test_should_ignore_code_without_class |
|
| 79 |
input = <<~HTML |
|
| 80 |
<pre><code> |
|
| 81 |
def foo |
|
| 82 |
end |
|
| 83 |
</code></pre> |
|
| 84 |
HTML |
|
| 85 |
assert_equal input, filter(input) |
|
| 88 | 86 |
end |
| 89 | 87 |
end |
- « Previous
- 1
- 2
- Next »