diff --git a/lib/commonmarker.rb b/lib/commonmarker.rb index edfc0e57..7d0f0cb2 100755 --- a/lib/commonmarker.rb +++ b/lib/commonmarker.rb @@ -12,32 +12,34 @@ require "awesome_print" rescue LoadError; end # rubocop:disable Lint/SuppressedException module CommonMarker - # Public: Parses a Markdown string into an HTML string. - # - # text - A {String} of text - # option - Either a {Symbol} or {Array of Symbol}s indicating the render options - # extensions - An {Array of Symbol}s indicating the extensions to use - # - # Returns a {String} of converted HTML. - def self.render_html(text, options = :DEFAULT, extensions = []) - raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String) + class << self + # Public: Parses a Markdown string into an HTML string. + # + # text - A {String} of text + # option - Either a {Symbol} or {Array of Symbol}s indicating the render options + # extensions - An {Array of Symbol}s indicating the extensions to use + # + # Returns a {String} of converted HTML. + def render_html(text, options = :DEFAULT, extensions = []) + raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String) - opts = Config.process_options(options, :render) - Node.markdown_to_html(text.encode("UTF-8"), opts, extensions) - end + opts = Config.process_options(options, :render) + Node.markdown_to_html(text.encode("UTF-8"), opts, extensions) + end - # Public: Parses a Markdown string into a `document` node. - # - # string - {String} to be parsed - # option - A {Symbol} or {Array of Symbol}s indicating the parse options - # extensions - An {Array of Symbol}s indicating the extensions to use - # - # Returns the `document` node. - def self.render_doc(text, options = :DEFAULT, extensions = []) - raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String) + # Public: Parses a Markdown string into a `document` node. + # + # string - {String} to be parsed + # option - A {Symbol} or {Array of Symbol}s indicating the parse options + # extensions - An {Array of Symbol}s indicating the extensions to use + # + # Returns the `document` node. + def render_doc(text, options = :DEFAULT, extensions = []) + raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String) - opts = Config.process_options(options, :parse) - text = text.encode("UTF-8") - Node.parse_document(text, text.bytesize, opts, extensions) - end + opts = Config.process_options(options, :parse) + text = text.encode("UTF-8") + Node.parse_document(text, text.bytesize, opts, extensions) + end +end end diff --git a/lib/commonmarker/config.rb b/lib/commonmarker/config.rb index 59f02790..db09d8ac 100644 --- a/lib/commonmarker/config.rb +++ b/lib/commonmarker/config.rb @@ -33,20 +33,22 @@ module Config format: [:html, :xml, :commonmark, :plaintext].freeze, }.freeze - def self.process_options(option, type) - case option - when Symbol - OPTS.fetch(type).fetch(option) - when Array - raise TypeError if option.none? + class << self + def process_options(option, type) + case option + when Symbol + OPTS.fetch(type).fetch(option) + when Array + raise TypeError if option.none? - # neckbearding around. the map will both check the opts and then bitwise-OR it - OPTS.fetch(type).fetch_values(*option).inject(0, :|) - else - raise TypeError, "option type must be a valid symbol or array of symbols within the #{name}::OPTS[:#{type}] context" + # neckbearding around. the map will both check the opts and then bitwise-OR it + OPTS.fetch(type).fetch_values(*option).inject(0, :|) + else + raise TypeError, "option type must be a valid symbol or array of symbols within the #{name}::OPTS[:#{type}] context" + end + rescue KeyError => e + raise TypeError, "option ':#{e.key}' does not exist for #{name}::OPTS[:#{type}]" end - rescue KeyError => e - raise TypeError, "option ':#{e.key}' does not exist for #{name}::OPTS[:#{type}]" - end + end end end diff --git a/lib/commonmarker/renderer.rb b/lib/commonmarker/renderer.rb index 3be353e6..049e4c7f 100644 --- a/lib/commonmarker/renderer.rb +++ b/lib/commonmarker/renderer.rb @@ -113,7 +113,7 @@ def tagfilter(str) ) (?=\s|>|/>) }xi, - '<\1' + '<\1', ) else str diff --git a/test/test_basics.rb b/test/test_basics.rb index 70bbe76b..d6958a2c 100644 --- a/test/test_basics.rb +++ b/test/test_basics.rb @@ -13,6 +13,7 @@ def test_to_html def test_markdown_to_html html = CommonMarker.render_html("Hi *there*") + assert_equal("

Hi there

\n", html) end diff --git a/test/test_commands.rb b/test/test_commands.rb index f26fe89f..9dc31ff2 100644 --- a/test/test_commands.rb +++ b/test/test_commands.rb @@ -5,11 +5,13 @@ class TestCommands < Minitest::Test def test_basic out = make_bin("strong.md") + assert_equal("

I am strong

", out) end def test_does_not_have_extensions out = make_bin("table.md") + assert_includes(out, "| a") refute_includes(out, "

hi") refute_includes(out, "") @@ -17,6 +19,7 @@ def test_does_not_have_extensions def test_understands_extensions out = make_bin("table.md", "--extension=table") + refute_includes(out, "| a") refute_includes(out, "

hi") ["

a c
", "", "", ""].each { |html| assert_includes(out, html) } @@ -24,6 +27,7 @@ def test_understands_extensions def test_understands_multiple_extensions out = make_bin("table.md", "--extension=table,strikethrough") + refute_includes(out, "| a") assert_includes(out, "

hi") ["

", "a", "", "c", "
", "", "", ""].each { |html| assert_includes(out, html) } @@ -31,6 +35,7 @@ def test_understands_multiple_extensions def test_understands_html_format_with_renderer_and_extensions out = make_bin("table.md", "--to=html --extension=table,strikethrough --html-renderer") + refute_includes(out, "| a") assert_includes(out, "

hi") ["

", "a", "", "c", "
", "", "", ""].each { |html| assert_includes(out, html) } @@ -38,17 +43,20 @@ def test_understands_html_format_with_renderer_and_extensions def test_understands_xml_format out = make_bin("strong.md", "--to=xml") + assert_includes(out, '') assert_includes(out, 'strong') end def test_understands_commonmark_format out = make_bin("strong.md", "--to=commonmark") + assert_equal("I am **strong**", out) end def test_understands_plaintext_format out = make_bin("strong.md", "--to=plaintext") + assert_equal("I am strong", out) end diff --git a/test/test_commonmark.rb b/test/test_commonmark.rb index 0c8d00ca..e4861359 100644 --- a/test/test_commonmark.rb +++ b/test/test_commonmark.rb @@ -31,7 +31,7 @@ def test_to_commonmark assert_equal(\ render_doc(@markdown).to_html.squeeze(" ").gsub(HTML_COMMENT, ""), - render_doc(compare).to_html.squeeze(" ").gsub(HTML_COMMENT, "") + render_doc(compare).to_html.squeeze(" ").gsub(HTML_COMMENT, ""), ) end end diff --git a/test/test_doc.rb b/test/test_doc.rb index 9b77a638..c77cb980 100644 --- a/test/test_doc.rb +++ b/test/test_doc.rb @@ -34,24 +34,28 @@ def test_get_next def test_insert_before paragraph = Node.new(:paragraph) + assert(@first_child.insert_before(paragraph)) assert_match("

\n

Hi there.", @doc.to_html) end def test_insert_after paragraph = Node.new(:paragraph) + assert(@first_child.insert_after(paragraph)) assert_match("many nodes!

\n

\n", @doc.to_html) end def test_prepend_child code = Node.new(:code) + assert(@first_child.prepend_child(code)) assert_match("

Hi there.", @doc.to_html) end def test_append_child strong = Node.new(:strong) + assert(@first_child.append_child(strong)) assert_match("!

\n", @doc.to_html) end diff --git a/test/test_encoding.rb b/test/test_encoding.rb index 35d5c33c..50e08fa9 100644 --- a/test/test_encoding.rb +++ b/test/test_encoding.rb @@ -8,15 +8,18 @@ def test_encoding contents = fixtures_file("curly.md") doc = CommonMarker.render_doc(contents, :SMART) render = doc.to_html + assert_equal("

This curly quote “makes commonmarker throw an exception”.

", render.rstrip) render = doc.to_xml + assert_includes(render, 'This curly quote “makes commonmarker throw an exception”.') end def test_string_content_is_utf8 doc = CommonMarker.render_doc("Hi *there*") text = doc.first_child.last_child.first_child + assert_equal("there", text.string_content) assert_equal("UTF-8", text.string_content.encoding.name) end diff --git a/test/test_extensions.rb b/test/test_extensions.rb index ced40e34..4faf69d7 100644 --- a/test/test_extensions.rb +++ b/test/test_extensions.rb @@ -17,6 +17,7 @@ def test_uses_specified_extensions CommonMarker.render_html(@markdown, :DEFAULT, [:table]).tap do |out| refute_includes(out, "| a") ["
", "a", "", "c", "
", "", "", "", "x"].each { |html| assert_includes(out, html) } + assert_includes(out, "~~hi~~") end @@ -27,9 +28,11 @@ def test_uses_specified_extensions end doc = CommonMarker.render_doc("~a~ ~~b~~ ~~~c~~~", :STRIKETHROUGH_DOUBLE_TILDE, [:strikethrough]) + assert_equal("

~a~ b ~~~c~~~

\n", doc.to_html) html = CommonMarker.render_html("~a~ ~~b~~ ~~~c~~~", :STRIKETHROUGH_DOUBLE_TILDE, [:strikethrough]) + assert_equal("

~a~ b ~~~c~~~

\n", html) CommonMarker.render_html(@markdown, :DEFAULT, [:table, :strikethrough]).tap do |out| @@ -45,16 +48,19 @@ def test_extensions_with_renderers doc.to_html.tap do |out| refute_includes(out, "| a") ["
", "a", "", "c", "
", "", "", "", "x"].each { |html| assert_includes(out, html) } + assert_includes(out, "~~hi~~") end HtmlRenderer.new.render(doc).tap do |out| refute_includes(out, "| a") ["
", "a", "", "c", "
", "", "", "", "x"].each { |html| assert_includes(out, html) } + assert_includes(out, "~~hi~~") end doc = CommonMarker.render_doc("~a~ ~~b~~ ~~~c~~~", :STRIKETHROUGH_DOUBLE_TILDE, [:strikethrough]) + assert_equal("

~a~ b ~~~c~~~

\n", HtmlRenderer.new.render(doc)) end diff --git a/test/test_gc.rb b/test/test_gc.rb index 05456e45..24e78279 100644 --- a/test/test_gc.rb +++ b/test/test_gc.rb @@ -24,6 +24,7 @@ def test_drop_child_reference GC.start # Test that the cached child object is still valid. text = doc.first_child.last_child.first_child + assert_equal("there", text.string_content) end diff --git a/test/test_linebreaks.rb b/test/test_linebreaks.rb index f81b049c..1fa885e5 100644 --- a/test/test_linebreaks.rb +++ b/test/test_linebreaks.rb @@ -5,11 +5,13 @@ class TestLinebreaks < Minitest::Test def test_hardbreak_no_spaces doc = CommonMarker.render_doc("foo\nbaz") + assert_equal("

foo
\nbaz

\n", doc.to_html(:HARDBREAKS)) end def test_hardbreak_with_spaces doc = CommonMarker.render_doc("foo \nbaz") + assert_equal("

foo
\nbaz

\n", doc.to_html(:HARDBREAKS)) end end diff --git a/test/test_maliciousness.rb b/test/test_maliciousness.rb index 454cf50f..dac58fb6 100644 --- a/test/test_maliciousness.rb +++ b/test/test_maliciousness.rb @@ -74,6 +74,7 @@ def test_rendering_with_bad_type err = assert_raises(TypeError) do CommonMarker.render_doc("foo \n baz", :safe) end + assert_equal("option ':safe' does not exist for CommonMarker::Config::OPTS[:parse]", err.message) assert_raises(TypeError) do diff --git a/test/test_node.rb b/test/test_node.rb index b21c4269..48f29994 100644 --- a/test/test_node.rb +++ b/test/test_node.rb @@ -12,6 +12,7 @@ def test_walk @doc.walk do |node| nodes << node.type end + assert_equal([:document, :paragraph, :text, :emph, :text, :text], nodes) end @@ -20,6 +21,7 @@ def test_each @doc.first_child.each do |node| nodes << node.type end + assert_equal([:text, :emph, :text], nodes) end @@ -30,18 +32,21 @@ def test_deprecated_each_child nodes << node.type end end + assert_equal([:text, :emph, :text], nodes) assert_match(/`each_child` is deprecated/, err) end def test_select nodes = @doc.first_child.select { |node| node.type == :text } + assert_equal(CommonMarker::Node, nodes.first.class) assert_equal([:text, :text], nodes.map(&:type)) end def test_map nodes = @doc.first_child.map(&:type) + assert_equal([:text, :emph, :text], nodes) end @@ -58,6 +63,7 @@ def test_to_html def test_html_renderer renderer = HtmlRenderer.new result = renderer.render(@doc) + assert_equal("

Hi there, I am mostly text!

\n", result) end @@ -66,6 +72,7 @@ def test_walk_and_set_string_content node.string_content = "world" if node.type == :text && node.string_content == "there" end result = HtmlRenderer.new.render(@doc) + assert_equal("

Hi world, I am mostly text!

\n", result) end @@ -76,6 +83,7 @@ def test_walk_and_delete_node node.delete end end + assert_equal("

Hi there, I am mostly text!

\n", @doc.to_html) end diff --git a/test/test_pathological_inputs.rb b/test/test_pathological_inputs.rb index eb8fca3e..427fc64d 100644 --- a/test/test_pathological_inputs.rb +++ b/test/test_pathological_inputs.rb @@ -47,6 +47,7 @@ def markdown(str) pathological.each_pair do |name, description| define_method("test_#{name}") do input, = description + assert markdown(input) end end diff --git a/test/test_renderer.rb b/test/test_renderer.rb index d3209a29..a13ca975 100644 --- a/test/test_renderer.rb +++ b/test/test_renderer.rb @@ -10,6 +10,7 @@ def setup def test_html_renderer renderer = HtmlRenderer.new result = renderer.render(@doc) + assert_equal("

Hi there

\n", result) end @@ -25,6 +26,7 @@ def test_multiple_tables DOC doc = CommonMarker.render_doc(content, :DEFAULT, [:autolink, :table, :tagfilter]) results = CommonMarker::HtmlRenderer.new.render(doc) + assert_equal(2, results.scan(//).size) end @@ -41,6 +43,7 @@ def text(node) end renderer = my_renderer.new + assert_equal(Encoding::UTF_8, renderer.render(@doc).encoding) assert_equal(renderer.input_encoding, renderer.output_encoding) end diff --git a/test/test_smartpunct.rb b/test/test_smartpunct.rb index c2e308ee..f9ee8568 100644 --- a/test/test_smartpunct.rb +++ b/test/test_smartpunct.rb @@ -22,6 +22,7 @@ def test_smart_hardbreak_no_spaces_render_doc markdown = "\"foo\"\nbaz" result = "

“foo”
\nbaz

\n" doc = CommonMarker.render_doc(markdown, :SMART) + assert_equal(result, doc.to_html([:HARDBREAKS])) end end diff --git a/test/test_spec.rb b/test/test_spec.rb index 9ef865aa..a7c059a6 100644 --- a/test/test_spec.rb +++ b/test/test_spec.rb @@ -13,17 +13,20 @@ class TestSpec < Minitest::Test define_method("test_to_html_example_#{testcase[:example]}") do actual = doc.to_html(:UNSAFE, testcase[:extensions]).rstrip + assert_equal testcase[:html], actual, testcase[:markdown] end define_method("test_html_renderer_example_#{testcase[:example]}") do actual = HtmlRenderer.new(options: :UNSAFE, extensions: testcase[:extensions]).render(doc).rstrip + assert_equal testcase[:html], actual, testcase[:markdown] end define_method("test_sourcepos_example_#{testcase[:example]}") do lhs = doc.to_html([:UNSAFE, :SOURCEPOS], testcase[:extensions]).rstrip rhs = HtmlRenderer.new(options: [:UNSAFE, :SOURCEPOS], extensions: testcase[:extensions]).render(doc).rstrip + assert_equal lhs, rhs, testcase[:markdown] end end diff --git a/test/test_tasklists.rb b/test/test_tasklists.rb index a135376a..b59db5bc 100644 --- a/test/test_tasklists.rb +++ b/test/test_tasklists.rb @@ -27,6 +27,7 @@ def test_html_renderer def test_tasklist_state list = @doc.first_child + assert_equal("checked", list.first_child.tasklist_state) assert_predicate(list.first_child, :tasklist_item_checked?) assert_equal("unchecked", list.first_child.next.tasklist_state) @@ -36,8 +37,10 @@ def test_tasklist_state def test_set_tasklist_state list = @doc.first_child list.first_child.tasklist_item_checked = false + refute_predicate(list.first_child, :tasklist_item_checked?) list.first_child.next.tasklist_item_checked = true + assert_predicate(list.first_child.next, :tasklist_item_checked?) end end
", "a", "", "c", "