diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..fa9e7c11 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,21 @@ +name: Linting + +on: + pull_request: + types: [opened, synchronize, reopened] + push: + branches: + - main + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.0 + bundler-cache: true + - run: bundle install + - name: Rubocop + run: bundle exec rake rubocop diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..f23c7f0a --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,39 @@ +name: CI + +on: + pull_request: + types: [opened, synchronize, reopened] + push: + branches: + - production + +jobs: + test: + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - macos-latest + - windows-latest + ruby-version: [3.0.0, 2.7.2, 2.6.6, 2.5.8] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Set up Ruby ${{ matrix.ruby-version }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true + + - name: Install dependencies + run: bundle install + + - name: Run ${{ matrix.os }} tests + shell: bash + run: script/cibuild diff --git a/.rubocop.yml b/.rubocop.yml index 70e8e126..de8d0a1f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,13 +1,7 @@ inherit_gem: rubocop-standard: - config/default.yml - -Style/StringLiterals: - Enabled: true - EnforcedStyle: single_quotes - -Naming/FileName: - Enabled: false + - config/minitest.yml AllCops: Exclude: diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 34585092..00000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -sudo: false -language: ruby -cache: bundler -rvm: - - 2.3.6 - - 2.4.3 - - 2.5.0 - - 2.6.0 - -git: - depth: 10 - -before_install: - - gem update --system - - gem install bundler - -script: script/cibuild - -matrix: - include: - - script: bundle exec rake rubocop - rvm: 2.6.0 diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 71d7fcee..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,16 +0,0 @@ -# appveyor.yml -install: - - set PATH=C:\Ruby24\bin;%PATH% - - git submodule init - - git submodule update - - bundle install - -build: off - -before_test: - - ruby -v - - gem -v - - bundle -v - -test_script: - - bundle exec rake diff --git a/bin/commonmarker b/bin/commonmarker index 5e033602..611b75fc 100755 --- a/bin/commonmarker +++ b/bin/commonmarker @@ -92,7 +92,7 @@ doc = CommonMarker.render_doc(ARGF.read, options.active_parse_options, options.a if options.renderer renderer = CommonMarker::HtmlRenderer.new(extensions: options.active_extensions) - STDOUT.write(renderer.render(doc)) + $stdout.write(renderer.render(doc)) else - STDOUT.write(doc.to_html(options.active_render_options, options.active_extensions)) + $stdout.write(doc.to_html(options.active_render_options, options.active_extensions)) end diff --git a/commonmarker.gemspec b/commonmarker.gemspec index 24340ac7..571aef65 100644 --- a/commonmarker.gemspec +++ b/commonmarker.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |s| s.executables = ['commonmarker'] s.require_paths = %w[lib ext] + s.required_ruby_version = ['>= 2.4.10', '< 4.0'] s.rdoc_options += ['-x', 'ext/commonmarker/cmark/.*'] diff --git a/lib/commonmarker/config.rb b/lib/commonmarker/config.rb index 9757bd41..0e599a57 100644 --- a/lib/commonmarker/config.rb +++ b/lib/commonmarker/config.rb @@ -31,10 +31,11 @@ class Render def self.process_options(option, type) type = Config.const_get(type.capitalize) - if option.is_a?(Symbol) + case option + when Symbol check_option(option, type) type.to_h[option] - elsif option.is_a?(Array) + when Array option = [nil] if option.empty? # neckbearding around. the map will both check the opts and then bitwise-OR it option.map do |o| diff --git a/lib/commonmarker/node.rb b/lib/commonmarker/node.rb index 20839e40..131334a4 100644 --- a/lib/commonmarker/node.rb +++ b/lib/commonmarker/node.rb @@ -11,7 +11,7 @@ class Node # # blk - A {Proc} representing the action to take for each child def walk(&block) - return enum_for(:walk) unless block_given? + return enum_for(:walk) unless block yield self each do |child| diff --git a/lib/commonmarker/renderer.rb b/lib/commonmarker/renderer.rb index 4d593d7e..66aa071a 100644 --- a/lib/commonmarker/renderer.rb +++ b/lib/commonmarker/renderer.rb @@ -6,6 +6,7 @@ module CommonMarker class Renderer attr_accessor :in_tight, :warnings, :in_plain + def initialize(options: :DEFAULT, extensions: []) @opts = Config.process_options(options, :render) @stream = StringIO.new(+'') @@ -18,11 +19,12 @@ def initialize(options: :DEFAULT, extensions: []) def out(*args) args.each do |arg| - if arg == :children + case arg + when :children @node.each { |child| out(child) } - elsif arg.is_a?(Array) + when Array arg.each { |x| render(x) } - elsif arg.is_a?(Node) + when Node render(arg) else @stream.write(arg) diff --git a/script/cibuild b/script/cibuild index b8eb300b..6c9db2f2 100755 --- a/script/cibuild +++ b/script/cibuild @@ -2,11 +2,6 @@ set -e -if [ -d /usr/share/rbenv/shims ]; then - export PATH=/usr/share/rbenv/shims:$PATH - export RBENV_VERSION="2.1.7-github" -fi - git submodule sync git submodule update --init bundle diff --git a/test/test_commands.rb b/test/test_commands.rb index f28c14dc..1a9e3b23 100644 --- a/test/test_commands.rb +++ b/test/test_commands.rb @@ -5,27 +5,27 @@ class TestCommands < Minitest::Test def test_basic out = make_bin('strong.md') - assert_equal out, '

I am strong

' + assert_equal('

I am strong

', out) end def test_does_not_have_extensions out = make_bin('table.md') - assert out.include?('| a') - refute out.include?('

hi') - refute out.include?('') + assert_includes out, '| a' + refute_includes out, '

hi' + refute_includes out, '

a c
' end def test_understands_extensions out = make_bin('table.md', '--extension=table') - refute out.include?('| a') - refute out.include?('

hi') - %w[

a c
].each { |html| assert out.include?(html) } + refute_includes out, '| a' + refute_includes out, '

hi' + %w[

a c
].each { |html| assert_includes out, html } end def test_understands_multiple_extensions out = make_bin('table.md', '--extension=table,strikethrough') - refute out.include?('| a') - assert out.include?('

hi') - %w[

a c
].each { |html| assert out.include?(html) } + refute_includes out, '| a' + assert_includes out, '

hi' + %w[

a c
].each { |html| assert_includes out, html } end end diff --git a/test/test_commonmark.rb b/test/test_commonmark.rb index 66bae9af..75980e03 100644 --- a/test/test_commonmark.rb +++ b/test/test_commonmark.rb @@ -30,7 +30,7 @@ def test_to_commonmark compare = render_doc(@markdown).to_commonmark assert_equal \ - render_doc(@markdown).to_html.gsub(/ +/, ' ').gsub(HTML_COMMENT, ''), - render_doc(compare).to_html.gsub(/ +/, ' ').gsub(HTML_COMMENT, '') + render_doc(@markdown).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 0796ed2f..c2a8649a 100644 --- a/test/test_doc.rb +++ b/test/test_doc.rb @@ -17,114 +17,114 @@ def setup end def test_get_type - assert_equal @doc.type, :document + assert_equal(:document, @doc.type) end def test_get_type_string - assert_equal @doc.type_string, 'document' + assert_equal('document', @doc.type_string) end def test_get_first_child - assert_equal @first_child.type, :paragraph + assert_equal(:paragraph, @first_child.type) end def test_get_next - assert_equal @first_child.first_child.next.type, :emph + assert_equal(:emph, @first_child.first_child.next.type) end def test_insert_before paragraph = Node.new(:paragraph) - assert_equal @first_child.insert_before(paragraph), true + assert(@first_child.insert_before(paragraph)) assert_match "

\n

Hi there.", @doc.to_html end def test_insert_after paragraph = Node.new(:paragraph) - assert_equal @first_child.insert_after(paragraph), true + 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_equal @first_child.prepend_child(code), true + assert(@first_child.prepend_child(code)) assert_match '

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

\n", @doc.to_html end def test_get_last_child - assert_equal @last_child.type, :paragraph + assert_equal(:paragraph, @last_child.type) end def test_get_parent - assert_equal @first_child.first_child.next.parent.type, :paragraph + assert_equal(:paragraph, @first_child.first_child.next.parent.type) end def test_get_previous - assert_equal @first_child.first_child.next.previous.type, :text + assert_equal(:text, @first_child.first_child.next.previous.type) end def test_get_url - assert_equal @link.url, 'https://www.github.com' + assert_equal('https://www.github.com', @link.url) end def test_set_url - assert_equal @link.url = 'https://www.mozilla.org', 'https://www.mozilla.org' + assert_equal('https://www.mozilla.org', @link.url = 'https://www.mozilla.org') end def test_get_title - assert_equal @image.title, 'Favicon' + assert_equal('Favicon', @image.title) end def test_set_title - assert_equal @image.title = 'Octocat', 'Octocat' + assert_equal('Octocat', @image.title = 'Octocat') end def test_get_header_level - assert_equal @header.header_level, 3 + assert_equal(3, @header.header_level) end def test_set_header_level - assert_equal @header.header_level = 6, 6 + assert_equal(6, @header.header_level = 6) end def test_get_list_type - assert_equal @ul_list.list_type, :bullet_list - assert_equal @ol_list.list_type, :ordered_list + assert_equal(:bullet_list, @ul_list.list_type) + assert_equal(:ordered_list, @ol_list.list_type) end def test_set_list_type - assert_equal @ul_list.list_type = :ordered_list, :ordered_list - assert_equal @ol_list.list_type = :bullet_list, :bullet_list + assert_equal(:ordered_list, @ul_list.list_type = :ordered_list) + assert_equal(:bullet_list, @ol_list.list_type = :bullet_list) end def test_get_list_start - assert_equal @ol_list.list_start, 1 + assert_equal(1, @ol_list.list_start) end def test_set_list_start - assert_equal @ol_list.list_start = 8, 8 + assert_equal(8, @ol_list.list_start = 8) end def test_get_list_tight - assert_equal @ul_list.list_tight, true - assert_equal @ol_list.list_tight, true + assert(@ul_list.list_tight) + assert(@ol_list.list_tight) end def test_set_list_tight - assert_equal @ul_list.list_tight = false, false - assert_equal @ol_list.list_tight = false, false + refute(@ul_list.list_tight = false) + refute(@ol_list.list_tight = false) end def test_get_fence_info - assert_equal @fence.fence_info, 'ruby' + assert_equal('ruby', @fence.fence_info) end def test_set_fence_info - assert_equal @fence.fence_info = 'javascript', 'javascript' + assert_equal('javascript', @fence.fence_info = 'javascript') end end diff --git a/test/test_encoding.rb b/test/test_encoding.rb index f977515d..8a96cf9f 100644 --- a/test/test_encoding.rb +++ b/test/test_encoding.rb @@ -8,13 +8,13 @@ def test_encoding contents = fixtures_file('curly.md') doc = CommonMarker.render_doc(contents, :SMART) render = doc.to_html - assert_equal render.rstrip, '

This curly quote “makes commonmarker throw an exception”.

' + assert_equal('

This curly quote “makes commonmarker throw an exception”.

', render.rstrip) end def test_string_content_is_utf8 doc = CommonMarker.render_doc('Hi *there*') text = doc.first_child.last_child.first_child - assert_equal text.string_content, 'there' - assert_equal text.string_content.encoding.name, 'UTF-8' + assert_equal('there', text.string_content) + assert_equal('UTF-8', text.string_content.encoding.name) end end diff --git a/test/test_extensions.rb b/test/test_extensions.rb index d1d456d9..b904becc 100644 --- a/test/test_extensions.rb +++ b/test/test_extensions.rb @@ -9,30 +9,30 @@ def setup def test_uses_specified_extensions CommonMarker.render_html(@markdown, :DEFAULT, %i[]).tap do |out| - assert out.include?('| a') - assert out.include?('| x') - assert out.include?('~~hi~~') + assert_includes out, '| a' + assert_includes out, '| x' + assert_includes out, '~~hi~~' end CommonMarker.render_html(@markdown, :DEFAULT, %i[table]).tap do |out| - refute out.include?('| a') - %w[
a c
x].each { |html| assert out.include?(html) } - assert out.include?('~~hi~~') + refute_includes out, '| a' + %w[
a c
x].each { |html| assert_includes out, html } + assert_includes out, '~~hi~~' end CommonMarker.render_html(@markdown, :DEFAULT, %i[strikethrough]).tap do |out| - assert out.include?('| a') - refute out.include?('~~hi~~') - assert out.include?('hi') + assert_includes out, '| a' + refute_includes out, '~~hi~~' + assert_includes out, 'hi' end doc = CommonMarker.render_doc('~a~ ~~b~~ ~~~c~~~', :STRIKETHROUGH_DOUBLE_TILDE, [:strikethrough]) - assert_equal doc.to_html, "

~a~ b ~~~c~~~

\n" + assert_equal("

~a~ b ~~~c~~~

\n", doc.to_html) CommonMarker.render_html(@markdown, :DEFAULT, %i[table strikethrough]).tap do |out| - refute out.include?('| a') - refute out.include?('| x') - refute out.include?('~~hi~~') + refute_includes out, '| a' + refute_includes out, '| x' + refute_includes out, '~~hi~~' end end @@ -40,19 +40,19 @@ def test_extensions_with_renderers doc = CommonMarker.render_doc(@markdown, :DEFAULT, %i[table]) doc.to_html.tap do |out| - refute out.include?('| a') - %w[
a c
x].each { |html| assert out.include?(html) } - assert out.include?('~~hi~~') + refute_includes out, '| a' + %w[
a c
x].each { |html| assert_includes out, html } + assert_includes out, '~~hi~~' end HtmlRenderer.new.render(doc).tap do |out| - refute out.include?('| a') - %w[
a c
x].each { |html| assert out.include?(html) } - assert out.include?('~~hi~~') + refute_includes out, '| a' + %w[
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 HtmlRenderer.new.render(doc), "

~a~ b ~~~c~~~

\n" + assert_equal("

~a~ b ~~~c~~~

\n", HtmlRenderer.new.render(doc)) end def test_bad_extension_specifications diff --git a/test/test_helper.rb b/test/test_helper.rb index 44cebda9..5963982c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -44,8 +44,8 @@ def open_spec_file(filename) example_number += 1 end_line = line_number tests << { - markdown: markdown_lines.join('').tr('→', "\t"), - html: html_lines.join('').tr('→', "\t").rstrip, + markdown: markdown_lines.join.tr('→', "\t"), + html: html_lines.join.tr('→', "\t").rstrip, example: example_number, start_line: start_line, end_line: end_line, diff --git a/test/test_maliciousness.rb b/test/test_maliciousness.rb index f7b5b1dd..e017796c 100644 --- a/test/test_maliciousness.rb +++ b/test/test_maliciousness.rb @@ -70,7 +70,7 @@ def test_rendering_with_bad_type err = assert_raises TypeError do CommonMarker.render_html("foo \n baz", [:SMART]) end - assert_equal err.message, 'option \':SMART\' does not exist for CommonMarker::Config::Render' + assert_equal('option \':SMART\' does not exist for CommonMarker::Config::Render', err.message) assert_raises TypeError do CommonMarker.render_doc("foo \n baz", 123) @@ -79,7 +79,7 @@ def test_rendering_with_bad_type err = assert_raises TypeError do CommonMarker.render_doc("foo \n baz", :safe) end - assert_equal err.message, 'option \':safe\' does not exist for CommonMarker::Config::Parse' + assert_equal('option \':safe\' does not exist for CommonMarker::Config::Parse', err.message) assert_raises TypeError do CommonMarker.render_doc("foo \n baz", :totes_fake) diff --git a/test/test_pathological_inputs.rb b/test/test_pathological_inputs.rb index c0b08800..b94e4575 100644 --- a/test/test_pathological_inputs.rb +++ b/test/test_pathological_inputs.rb @@ -10,7 +10,7 @@ def markdown(str) # list of pairs consisting of input and a regex that must match the output. pathological = { 'nested strong emph' => - [('*a **a ' * 65_000) + 'b' + (' a** a*' * 65_000), + ["#{'*a **a ' * 65_000}b#{' a** a*' * 65_000}", Regexp.compile('(a a ){65_000}b( a a){65_000}')], 'many emph closers with no openers' => [('a_ ' * 65_000), @@ -34,10 +34,10 @@ def markdown(str) ['**x [a*b**c*](d)', Regexp.compile('\\*\\*x abc')], 'nested brackets' => - [('[' * 50_000) + 'a' + (']' * 50_000), + ["#{'[' * 50_000}a#{']' * 50_000}", Regexp.compile('\[{50000}a\]{50000}')], 'nested block quotes' => - [(('> ' * 50_000) + 'a'), + ["#{'> ' * 50_000}a", Regexp.compile('(
\n){50000}')], 'U+0000 in input' => ['abc\u0000de\u0000', @@ -53,41 +53,41 @@ def markdown(str) if ENV['BENCH'] class PathologicalInputsPerformanceTest < Minitest::Benchmark - def bench_pathological_1 + def test_bench_pathological_one assert_performance_linear 0.99 do |n| star = '*' * (n * 10) markdown("#{star}#{star}hi#{star}#{star}") end end - def bench_pathological_2 + def test_bench_pathological_two assert_performance_linear 0.99 do |n| c = '`t`t`t`t`t`t' * (n * 10) markdown(c) end end - def bench_pathological_3 + def test_bench_pathological_three assert_performance_linear 0.99 do |n| markdown(" [a]: #{'A' * n}\n\n#{'[a][]' * n}\n") end end - def bench_pathological_4 + def test_bench_pathological_four assert_performance_linear 0.5 do |n| markdown("#{'[' * n}a#{']' * n}") end end - def bench_pathological_5 + def test_bench_pathological_five assert_performance_linear 0.99 do |n| markdown("#{'**a *a ' * n}#{'a* a**' * n}") end end - def bench_unbound_recursion + def test_bench_unbound_recursion assert_performance_linear 0.99 do |n| - markdown(('[' * n) + 'foo' + ('](bar)' * n)) + markdown("#{'[' * n}foo#{'](bar)' * n}") end end end
a c