Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C API stable test #201

Merged
merged 3 commits into from
Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ name: Linting

on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- main

jobs:
test:
Expand Down
6 changes: 1 addition & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ name: CI

on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- production

jobs:
test:
Expand All @@ -16,7 +12,7 @@ jobs:
- ubuntu-latest
- macos-latest
- windows-latest
ruby-version: [3.1, 3.0.0, 2.7.2, 2.6.6]
ruby-version: [3.1]

runs-on: ${{ matrix.os }}

Expand Down
52 changes: 27 additions & 25 deletions lib/commonmarker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
28 changes: 15 additions & 13 deletions lib/commonmarker/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion lib/commonmarker/renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def tagfilter(str)
)
(?=\s|>|/>)
}xi,
'&lt;\1'
'&lt;\1',
)
else
str
Expand Down
2 changes: 1 addition & 1 deletion lib/commonmarker/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module CommonMarker
VERSION = "0.23.6"
VERSION = "0.23.7.pre1"
end
1 change: 1 addition & 0 deletions test/test_basics.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def test_to_html

def test_markdown_to_html
html = CommonMarker.render_html("Hi *there*")

assert_equal("<p>Hi <em>there</em></p>\n", html)
end

Expand Down
8 changes: 8 additions & 0 deletions test/test_commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,58 @@
class TestCommands < Minitest::Test
def test_basic
out = make_bin("strong.md")

assert_equal("<p>I am <strong>strong</strong></p>", out)
end

def test_does_not_have_extensions
out = make_bin("table.md")

assert_includes(out, "| a")
refute_includes(out, "<p><del>hi</del>")
refute_includes(out, "<table> <tr> <th> a </th> <td> c </td>")
end

def test_understands_extensions
out = make_bin("table.md", "--extension=table")

refute_includes(out, "| a")
refute_includes(out, "<p><del>hi</del>")
["<table>", "<tr>", "<th>", "a", "</th>", "<td>", "c", "</td>"].each { |html| assert_includes(out, html) }
end

def test_understands_multiple_extensions
out = make_bin("table.md", "--extension=table,strikethrough")

refute_includes(out, "| a")
assert_includes(out, "<p><del>hi</del>")
["<table>", "<tr>", "<th>", "a", "</th>", "<td>", "c", "</td>"].each { |html| assert_includes(out, html) }
end

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, "<p><del>hi</del>")
["<table>", "<tr>", "<th>", "a", "</th>", "<td>", "c", "</td>"].each { |html| assert_includes(out, html) }
end

def test_understands_xml_format
out = make_bin("strong.md", "--to=xml")

assert_includes(out, '<?xml version="1.0" encoding="UTF-8"?>')
assert_includes(out, '<text xml:space="preserve">strong</text>')
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

Expand Down
2 changes: 1 addition & 1 deletion test/test_commonmark.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions test/test_doc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,28 @@ def test_get_next

def test_insert_before
paragraph = Node.new(:paragraph)

assert(@first_child.insert_before(paragraph))
assert_match("<p></p>\n<p>Hi <em>there</em>.", @doc.to_html)
end

def test_insert_after
paragraph = Node.new(:paragraph)

assert(@first_child.insert_after(paragraph))
assert_match("<strong>many nodes</strong>!</p>\n<p></p>\n", @doc.to_html)
end

def test_prepend_child
code = Node.new(:code)

assert(@first_child.prepend_child(code))
assert_match("<p><code></code>Hi <em>there</em>.", @doc.to_html)
end

def test_append_child
strong = Node.new(:strong)

assert(@first_child.append_child(strong))
assert_match("!<strong></strong></p>\n", @doc.to_html)
end
Expand Down
3 changes: 3 additions & 0 deletions test/test_encoding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ def test_encoding
contents = fixtures_file("curly.md")
doc = CommonMarker.render_doc(contents, :SMART)
render = doc.to_html

assert_equal("<p>This curly quote “makes commonmarker throw an exception”.</p>", render.rstrip)

render = doc.to_xml

assert_includes(render, '<text xml:space="preserve">This curly quote “makes commonmarker throw an exception”.</text>')
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
Expand Down
6 changes: 6 additions & 0 deletions test/test_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def test_uses_specified_extensions
CommonMarker.render_html(@markdown, :DEFAULT, [:table]).tap do |out|
refute_includes(out, "| a")
["<table>", "<tr>", "<th>", "a", "</th>", "<td>", "c", "</td>", "<strong>x</strong>"].each { |html| assert_includes(out, html) }

assert_includes(out, "~~hi~~")
end

Expand All @@ -27,9 +28,11 @@ def test_uses_specified_extensions
end

doc = CommonMarker.render_doc("~a~ ~~b~~ ~~~c~~~", :STRIKETHROUGH_DOUBLE_TILDE, [:strikethrough])

assert_equal("<p>~a~ <del>b</del> ~~~c~~~</p>\n", doc.to_html)

html = CommonMarker.render_html("~a~ ~~b~~ ~~~c~~~", :STRIKETHROUGH_DOUBLE_TILDE, [:strikethrough])

assert_equal("<p>~a~ <del>b</del> ~~~c~~~</p>\n", html)

CommonMarker.render_html(@markdown, :DEFAULT, [:table, :strikethrough]).tap do |out|
Expand All @@ -45,16 +48,19 @@ def test_extensions_with_renderers
doc.to_html.tap do |out|
refute_includes(out, "| a")
["<table>", "<tr>", "<th>", "a", "</th>", "<td>", "c", "</td>", "<strong>x</strong>"].each { |html| assert_includes(out, html) }

assert_includes(out, "~~hi~~")
end

HtmlRenderer.new.render(doc).tap do |out|
refute_includes(out, "| a")
["<table>", "<tr>", "<th>", "a", "</th>", "<td>", "c", "</td>", "<strong>x</strong>"].each { |html| assert_includes(out, html) }

assert_includes(out, "~~hi~~")
end

doc = CommonMarker.render_doc("~a~ ~~b~~ ~~~c~~~", :STRIKETHROUGH_DOUBLE_TILDE, [:strikethrough])

assert_equal("<p>~a~ <del>b</del> ~~~c~~~</p>\n", HtmlRenderer.new.render(doc))
end

Expand Down
1 change: 1 addition & 0 deletions test/test_gc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions test/test_linebreaks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
class TestLinebreaks < Minitest::Test
def test_hardbreak_no_spaces
doc = CommonMarker.render_doc("foo\nbaz")

assert_equal("<p>foo<br />\nbaz</p>\n", doc.to_html(:HARDBREAKS))
end

def test_hardbreak_with_spaces
doc = CommonMarker.render_doc("foo \nbaz")

assert_equal("<p>foo<br />\nbaz</p>\n", doc.to_html(:HARDBREAKS))
end
end
1 change: 1 addition & 0 deletions test/test_maliciousness.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions test/test_node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -20,6 +21,7 @@ def test_each
@doc.first_child.each do |node|
nodes << node.type
end

assert_equal([:text, :emph, :text], nodes)
end

Expand All @@ -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

Expand All @@ -58,6 +63,7 @@ def test_to_html
def test_html_renderer
renderer = HtmlRenderer.new
result = renderer.render(@doc)

assert_equal("<p>Hi <em>there</em>, I am mostly text!</p>\n", result)
end

Expand All @@ -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("<p>Hi <em>world</em>, I am mostly text!</p>\n", result)
end

Expand All @@ -76,6 +83,7 @@ def test_walk_and_delete_node
node.delete
end
end

assert_equal("<p>Hi there, I am mostly text!</p>\n", @doc.to_html)
end

Expand Down