From 9af2ba2c13d2dc706bdf1387110c13b82175a0cf Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Wed, 11 Aug 2021 21:40:56 +0000 Subject: Adds CommonMark Markdown (GitHub Flavored) as third text formatting option (#32424). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Jens Krämer. git-svn-id: http://svn.redmine.org/redmine/trunk@21156 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../common_mark/application_helper_test.rb | 66 +++++ .../common_mark/external_links_filter_test.rb | 48 ++++ .../common_mark/fixup_auto_links_filter_test.rb | 50 ++++ .../wiki_formatting/common_mark/formatter_test.rb | 270 +++++++++++++++++++++ .../common_mark/markdown_filter_test.rb | 35 +++ .../common_mark/sanitization_filter_test.rb | 211 ++++++++++++++++ .../common_mark/syntax_highlight_filter_test.rb | 75 ++++++ 7 files changed, 755 insertions(+) create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/external_links_filter_test.rb create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter_test.rb create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/markdown_filter_test.rb create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/sanitization_filter_test.rb create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter_test.rb (limited to 'test') diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb new file mode 100644 index 000000000..fecafd660 --- /dev/null +++ b/test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.expand_path('../../../../../../test_helper', __FILE__) + +class Redmine::WikiFormatting::CommonMark::ApplicationHelperTest < Redmine::HelperTest + if Object.const_defined?(:CommonMarker) + + include ERB::Util + include Rails.application.routes.url_helpers + + fixtures :projects, :enabled_modules, + :users, :email_addresses, + :members, :member_roles, :roles, + :repositories, :changesets, + :projects_trackers, + :trackers, :issue_statuses, :issues, :versions, :documents, :journals, + :wikis, :wiki_pages, :wiki_contents, + :boards, :messages, :news, + :attachments, :enumerations, + :custom_values, :custom_fields, :custom_fields_projects + + def setup + super + set_tmp_attachments_directory + end + + def test_attached_images_with_markdown_and_non_ascii_filename + to_test = { + 'CAFÉ.JPG' => 'CAF%C3%89.JPG', + 'crème.jpg' => 'cr%C3%A8me.jpg', + } + with_settings :text_formatting => 'common_mark' do + to_test.each do |filename, result| + attachment = Attachment.generate!(:filename => filename) + assert_include %(), textilizable("![](#{filename})", :attachments => [attachment]) + end + end + end + + def test_toc_with_markdown_formatting_should_be_parsed + with_settings :text_formatting => 'common_mark' do + assert_select_in textilizable("{{toc}}\n\n# Heading"), 'ul.toc li', :text => 'Heading' + assert_select_in textilizable("{{ 'Heading' + assert_select_in textilizable("{{>toc}}\n\n# Heading"), 'ul.toc.right li', :text => 'Heading' + end + end + + end +end diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/external_links_filter_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/external_links_filter_test.rb new file mode 100644 index 000000000..d4e8fa0df --- /dev/null +++ b/test/unit/lib/redmine/wiki_formatting/common_mark/external_links_filter_test.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.expand_path('../../../../../../test_helper', __FILE__) + +if Object.const_defined?(:CommonMarker) + require 'redmine/wiki_formatting/common_mark/external_links_filter' + + class Redmine::WikiFormatting::CommonMark::ExternalLinksFilterTest < ActiveSupport::TestCase + def filter(html) + Redmine::WikiFormatting::CommonMark::ExternalLinksFilter.to_html(html, @options) + end + + def setup + @options = { } + end + + def test_external_links_should_have_external_css_class + assert_equal %(link), filter(%(link)) + end + + def test_locals_links_should_not_have_external_css_class + assert_equal %(home), filter(%(home)) + assert_equal %(relative), filter(%(relative)) + assert_equal %(anchor), filter(%(anchor)) + end + + def test_mailto_links_should_have_email_class + assert_equal %(), filter(%(user)) + end + end +end diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter_test.rb new file mode 100644 index 000000000..92b324151 --- /dev/null +++ b/test/unit/lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter_test.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.expand_path('../../../../../../test_helper', __FILE__) + +if Object.const_defined?(:CommonMarker) + require 'redmine/wiki_formatting/common_mark/fixup_auto_links_filter' + + class Redmine::WikiFormatting::CommonMark::FixupAutoLinksFilterTest < ActiveSupport::TestCase + def filter(html) + Redmine::WikiFormatting::CommonMark::FixupAutoLinksFilter.to_html(html, @options) + end + + def format(markdown) + Redmine::WikiFormatting::CommonMark::MarkdownFilter.to_html(markdown, Redmine::WikiFormatting::CommonMark::PIPELINE_CONFIG) + end + + def setup + @options = { } + end + + def test_should_fixup_autolinked_user_references + text = "user:user@example.org" + assert_equal "

#{text}

", filter(format(text)) + text = "@user@example.org" + assert_equal "

#{text}

", filter(format(text)) + end + + def test_should_fixup_autolinked_hires_files + text = "printscreen@2x.png" + assert_equal "

#{text}

", filter(format(text)) + end + end +end diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb new file mode 100644 index 000000000..9f23dba30 --- /dev/null +++ b/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb @@ -0,0 +1,270 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.expand_path('../../../../../../test_helper', __FILE__) + +class Redmine::WikiFormatting::CommonMark::FormatterTest < ActionView::TestCase + if Object.const_defined?(:CommonMarker) + + def setup + @formatter = Redmine::WikiFormatting::CommonMark::Formatter + end + + def format(text) + @formatter.new(text).to_html + end + + def test_should_render_hard_breaks + html ="

foo
\nbar

" + assert_equal html, format("foo\\\nbar") + assert_equal html, format("foo \nbar") + end + + def test_should_ignore_soft_breaks + assert_equal "

foo\nbar

", format("foo\nbar") + end + + def test_syntax_error_in_image_reference_should_not_raise_exception + assert format("!>[](foo.png)") + end + + def test_empty_image_should_not_raise_exception + assert format("![]()") + end + + def test_inline_style + assert_equal "

foo

", format("**foo**") + end + + def test_not_set_intra_emphasis + assert_equal "

foo_bar_baz

", format("foo_bar_baz") + end + + def test_wiki_links_should_be_preserved + text = 'This is a wiki link: [[Foo]]' + assert_include '[[Foo]]', format(text) + end + + def test_redmine_links_with_double_quotes_should_be_preserved + text = 'This is a redmine link: version:"1.0"' + assert_include 'version:"1.0"', format(text) + end + + def test_links_by_id_should_be_preserved + text = "[project#3]" + assert_equal "

#{text}

", format(text) + end + + def test_links_to_users_should_be_preserved + text = "[@login]" + assert_equal "

#{text}

", format(text) + text = "[user:login]" + assert_equal "

#{text}

", format(text) + text = "user:user@example.org" + assert_equal "

#{text}

", format(text) + text = "[user:user@example.org]" + assert_equal "

#{text}

", format(text) + text = "@user@example.org" + assert_equal "

#{text}

", format(text) + text = "[@user@example.org]" + assert_equal "

#{text}

", format(text) + end + + def test_files_with_at_should_not_end_up_as_mailto_links + text = "printscreen@2x.png" + assert_equal "

#{text}

", format(text) + text = "[printscreen@2x.png]" + assert_equal "

#{text}

", format(text) + end + + def test_should_support_syntax_highlight + text = <<-STR + ~~~ruby + def foo + end + ~~~ + STR + assert_select_in format(text), 'pre code.ruby.syntaxhl' do + assert_select 'span.k', :text => 'def' + end + end + + def test_should_not_allow_invalid_language_for_code_blocks + text = <<-STR + ~~~foo + test + ~~~ + STR + assert_equal "
test\n
", format(text) + end + + def test_external_links_should_have_external_css_class + text = 'This is a [link](http://example.net/)' + assert_equal '

This is a link

', format(text) + end + + def test_locals_links_should_not_have_external_css_class + text = 'This is a [link](/issues)' + assert_equal '

This is a link

', format(text) + end + + def test_markdown_should_not_require_surrounded_empty_line + text = <<-STR + This is a list: + * One + * Two + STR + assert_equal "

This is a list:

\n", format(text) + end + + def test_footnotes + text = <<-STR + This is some text[^1]. + + [^1]: This is the foot note + STR + + expected = <<-EXPECTED +

This is some text1.

+
    +
  1. +

    This is the foot note

    +
  2. +
+ EXPECTED + + assert_equal expected.gsub(%r{[\r\n\t]}, ''), format(text).gsub(%r{[\r\n\t]}, '') + end + + STR_WITH_PRE = [ + # 0 + <<~STR.chomp, + # Title + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero. + STR + # 1 + <<~STR.chomp, + ## Heading 2 + + ~~~ruby + def foo + end + ~~~ + + Morbi facilisis accumsan orci non pharetra. + + ~~~ ruby + def foo + end + ~~~ + + ``` + Pre Content: + + ## Inside pre + + inside pre block + + Morbi facilisis accumsan orci non pharetra. + ``` + STR + # 2 + <<~STR.chomp, + ### Heading 3 + + Nulla nunc nisi, egestas in ornare vel, posuere ac libero. + STR + ] + + def test_get_section_should_ignore_pre_content + text = STR_WITH_PRE.join("\n\n") + + assert_section_with_hash STR_WITH_PRE[1..2].join("\n\n"), text, 2 + assert_section_with_hash STR_WITH_PRE[2], text, 3 + end + + def test_update_section_should_not_escape_pre_content_outside_section + text = STR_WITH_PRE.join("\n\n") + replacement = "New text" + + assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"), + @formatter.new(text).update_section(3, replacement) + end + + def test_should_emphasize_text + text = 'This _text_ should be emphasized' + assert_equal '

This text should be emphasized

', format(text) + end + + def test_should_strike_through_text + text = 'This ~~text~~ should be striked through' + assert_equal '

This text should be striked through

', format(text) + end + + def test_should_autolink_urls_and_emails + [ + ["http://example.org", '

http://example.org

'], + ["http://www.redmine.org/projects/redmine/issues?utf8=✓", + '

http://www.redmine.org/projects/redmine/issues?utf8=✓

'], + ['[Letters](https://yandex.ru/search/?text=кол-во)', '

Letters

'], + ["www.example.org", '

www.example.org

'], + ["user@example.org", '

'] + ].each do |text, html| + assert_equal html, format(text) + end + end + + def test_should_support_html_tables + text = '
Cell
' + assert_equal '
Cell
', format(text) + end + + def test_should_remove_unsafe_uris + [ + ['', ''], + ['click me', '

click me

'], + ].each do |text, html| + assert_equal html, format(text) + end + end + + def test_should_escape_unwanted_tags + [ + [ + %[

sit
amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script>

], + %[sit
amet ] + ] + ].each do |expected, input| + assert_equal expected, format(input) + end + end + + private + + def assert_section_with_hash(expected, text, index) + result = @formatter.new(text).get_section(index) + + assert_kind_of Array, result + assert_equal 2, result.size + assert_equal expected, result.first, "section content did not match" + assert_equal Digest::MD5.hexdigest(expected), result.last, "section hash did not match" + end + end +end diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/markdown_filter_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/markdown_filter_test.rb new file mode 100644 index 000000000..195c3e11e --- /dev/null +++ b/test/unit/lib/redmine/wiki_formatting/common_mark/markdown_filter_test.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.expand_path('../../../../../../test_helper', __FILE__) + +if Object.const_defined?(:CommonMarker) + require 'redmine/wiki_formatting/common_mark/markdown_filter' + + class Redmine::WikiFormatting::CommonMark::MarkdownFilterTest < ActiveSupport::TestCase + def filter(markdown) + Redmine::WikiFormatting::CommonMark::MarkdownFilter.to_html(markdown) + end + + # just a basic sanity test. more formatting tests in the formatter_test + def test_should_render_markdown + assert_equal "

bold

", filter("**bold**") + end + end +end diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/sanitization_filter_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/sanitization_filter_test.rb new file mode 100644 index 000000000..72ef52a63 --- /dev/null +++ b/test/unit/lib/redmine/wiki_formatting/common_mark/sanitization_filter_test.rb @@ -0,0 +1,211 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.expand_path('../../../../../../test_helper', __FILE__) + +if Object.const_defined?(:CommonMarker) + require 'redmine/wiki_formatting/common_mark/sanitization_filter' + + class Redmine::WikiFormatting::CommonMark::SanitizationFilterTest < ActiveSupport::TestCase + def filter(html) + Redmine::WikiFormatting::CommonMark::SanitizationFilter.to_html(html, @options) + end + + def setup + @options = { } + end + + def test_should_filter_tags + input = %( dont blink) + assert_equal %(foo dont blink), filter(input) + end + + def test_should_sanitize_attributes + input = %(link) + assert_equal %(link), filter(input) + end + + def test_should_allow_relative_links + input = %(foo/bar) + assert_equal input, filter(input) + end + + def test_should_support_footnotes + input = %(foo) + assert_equal input, filter(input) + input = %(
  1. footnote
) + assert_equal input, filter(input) + end + + def test_should_remove_invalid_ids + input = %(foo) + assert_equal %(foo), filter(input) + input = %(
  1. footnote
) + assert_equal %(
  1. footnote
), filter(input) + end + + def test_should_allow_class_on_code_only + input = %(

bar

) + assert_equal %(

bar

), filter(input) + + input = %(foo) + assert_equal input, filter(input) + + input = %(foo) + assert_equal %(foo), filter(input) + end + + # samples taken from the Sanitize test suite + # rubocop:disable Layout/LineLength + STRINGS = [ + [ + 'Lorem ipsum dolor sit
amet ', + 'Lorem ipsum dolor sit
amet .foo { color: #fff; } ' + ], + [ + 'Lorem dolor sit
amet ', + 'Lorem ipsum dolor sit
amet <script>alert("hello world");' + ] + ] + # rubocop:enable Layout/LineLength + + def test_should_sanitize_html_strings + STRINGS.each do |input, expected| + assert_equal expected, filter(input) + end + end + + # samples taken from the Sanitize test suite + PROTOCOLS = { + 'protocol-based JS injection: simple, no spaces' => [ + 'foo', + 'foo' + ], + + 'protocol-based JS injection: simple, spaces before' => [ + 'foo', + 'foo' + ], + + 'protocol-based JS injection: simple, spaces after' => [ + 'foo', + 'foo' + ], + + 'protocol-based JS injection: simple, spaces before and after' => [ + 'foo', + 'foo' + ], + + 'protocol-based JS injection: preceding colon' => [ + 'foo', + 'foo' + ], + + 'protocol-based JS injection: UTF-8 encoding' => [ + 'foo', + 'foo' + ], + + 'protocol-based JS injection: long UTF-8 encoding' => [ + 'foo', + 'foo' + ], + + # rubocop:disable Layout/LineLength + 'protocol-based JS injection: long UTF-8 encoding without semicolons' => [ + 'foo', + 'foo' + ], + # rubocop:enable Layout/LineLength + + 'protocol-based JS injection: hex encoding' => [ + 'foo', + 'foo' + ], + + 'protocol-based JS injection: long hex encoding' => [ + 'foo', + 'foo' + ], + + 'protocol-based JS injection: hex encoding without semicolons' => [ + 'foo', + 'foo' + ], + + 'protocol-based JS injection: null char' => [ + "", + '' + # '' + ], + + 'protocol-based JS injection: invalid URL char' => [ + '', + '' + ], + + 'protocol-based JS injection: spaces and entities' => [ + '', + '' + # '' + ], + + 'protocol whitespace' => [ + '', + '' + ], + + 'data images sources' => [ + '', + '' + ], + + 'data URIs' => [ + 'XSS', + 'XSS' + ], + + 'vbscript URIs' => [ + 'XSS', + 'XSS' + ], + + 'invalid URIs' => [ + 'link', + 'link' + ], + } + + PROTOCOLS.each do |name, strings| + test "should not allow #{name}" do + input, expected = *strings + assert_equal expected, filter(input) + end + end + end +end diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter_test.rb new file mode 100644 index 000000000..e7e782d53 --- /dev/null +++ b/test/unit/lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter_test.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.expand_path('../../../../../../test_helper', __FILE__) +if Object.const_defined?(:CommonMarker) + require 'redmine/wiki_formatting/common_mark/syntax_highlight_filter' + + class Redmine::WikiFormatting::CommonMark::SyntaxHighlightFilterTest < ActiveSupport::TestCase + def filter(html) + Redmine::WikiFormatting::CommonMark::SyntaxHighlightFilter.to_html(html, @options) + end + + def setup + @options = { } + end + + def test_should_highlight_supported_language + input = <<~HTML +

+        def foo
+        end
+        
+ HTML + expected = <<~HTML +

+        def foo
+        end
+        
+ HTML + assert_equal expected, filter(input) + end + + def test_should_strip_code_for_unknown_lang + input = <<~HTML +

+        def foo
+        end
+        
+ HTML + expected = <<~HTML +
+        def foo
+        end
+        
+ HTML + assert_equal expected, filter(input) + end + + def test_should_ignore_code_without_class + input = <<~HTML +

+        def foo
+        end
+        
+ HTML + assert_equal input, filter(input) + end + end +end -- cgit v1.2.3