From e2b10e2d9c778a19e617efd2d1f1268d9d6e1e3b Mon Sep 17 00:00:00 2001 From: Toshimaru Date: Mon, 4 May 2020 19:27:42 +0900 Subject: [PATCH 01/41] Require rubocop v0.81+ / Update rubocop configuration (#112) * require rubocop v0.81~ * Add new cops --- .rubocop.yml | 18 +++++++++++------- Gemfile | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 523762b..635cd75 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -8,27 +8,31 @@ AllCops: Metrics/MethodLength: Enabled: false - Metrics/AbcSize: Enabled: false - Metrics/ClassLength: Enabled: false -Style/WordArray: - Enabled: false - Naming/FileName: Enabled: false Layout/LineLength: Enabled: false +Layout/SpaceAroundMethodCallOperator: + Enabled: true -Style/HashEachMethods: +Lint/RaiseException: + Enabled: true +Lint/StructNewOverride: Enabled: true +Style/WordArray: + Enabled: false +Style/HashEachMethods: + Enabled: true Style/HashTransformKeys: Enabled: true - Style/HashTransformValues: Enabled: true +Style/ExponentialNotation: + Enabled: true diff --git a/Gemfile b/Gemfile index b6a433a..e0cf846 100644 --- a/Gemfile +++ b/Gemfile @@ -7,5 +7,5 @@ gem 'minitest-reporters' gem 'minitest' gem 'pry' gem 'rake' -gem 'rubocop' +gem 'rubocop', '~> 0.81' gem 'simplecov', '~> 0.17.1' From af89f4f8f471d6e4b06c35a7a8aa438c297a54a4 Mon Sep 17 00:00:00 2001 From: Toshimaru Date: Wed, 6 May 2020 02:52:38 +0900 Subject: [PATCH 02/41] URL-Encoding for anchor link inside toc (#113) * Url-Encoding for element id (spaces and UTF-8 support) * Create Helper module and move method to helper * TestOptionError -> TestInvalidOptions * Update test_japanese_toc * Use parser.build_toc instead of Nokogiri::HTML * Use CGI.escape instead of ERB url_encode * Use url-encoded string * Remove Nokogiri::HTML * attr_accessor -> attr_reader * Add comment for auto URL encoded string * Test: parser.inject_anchors_into_html for Japanese Co-authored-by: Nicolas Karg <50399433+N7K4@users.noreply.github.com> --- lib/table_of_contents/configuration.rb | 4 +- lib/table_of_contents/helper.rb | 17 + lib/table_of_contents/parser.rb | 10 +- ...ption_error.rb => test_invalid_options.rb} | 20 +- test/parser/test_various_toc_html.rb | 361 +++++++----------- 5 files changed, 177 insertions(+), 235 deletions(-) create mode 100644 lib/table_of_contents/helper.rb rename test/parser/{test_option_error.rb => test_invalid_options.rb} (51%) diff --git a/lib/table_of_contents/configuration.rb b/lib/table_of_contents/configuration.rb index 61eeeeb..7988402 100644 --- a/lib/table_of_contents/configuration.rb +++ b/lib/table_of_contents/configuration.rb @@ -4,8 +4,8 @@ module Jekyll module TableOfContents # jekyll-toc configuration class class Configuration - attr_accessor :toc_levels, :no_toc_class, :no_toc_section_class, - :list_class, :sublist_class, :item_class, :item_prefix + attr_reader :toc_levels, :no_toc_class, :no_toc_section_class, + :list_class, :sublist_class, :item_class, :item_prefix DEFAULT_CONFIG = { 'min_level' => 1, diff --git a/lib/table_of_contents/helper.rb b/lib/table_of_contents/helper.rb new file mode 100644 index 0000000..8ed9118 --- /dev/null +++ b/lib/table_of_contents/helper.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Jekyll + module TableOfContents + # helper methods for Parser + module Helper + PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u.freeze + + def generate_toc_id(text) + text = text.downcase + .gsub(PUNCTUATION_REGEXP, '') # remove punctuation + .tr(' ', '-') # replace spaces with dash + CGI.escape(text) + end + end + end +end diff --git a/lib/table_of_contents/parser.rb b/lib/table_of_contents/parser.rb index 036251d..9b6ba3a 100644 --- a/lib/table_of_contents/parser.rb +++ b/lib/table_of_contents/parser.rb @@ -1,10 +1,12 @@ # frozen_string_literal: true +require 'table_of_contents/helper' + module Jekyll module TableOfContents # Parse html contents and generate table of contents class Parser - PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u.freeze + include ::Jekyll::TableOfContents::Helper def initialize(html, options = {}) @doc = Nokogiri::HTML::DocumentFragment.parse(html) @@ -22,6 +24,7 @@ def build_toc def inject_anchors_into_html @entries.each do |entry| + # NOTE: `entry[:id]` is automatically URL encoded by Nokogiri entry[:header_content].add_previous_sibling( %() ) @@ -41,10 +44,7 @@ def parse_content .reject { |n| n.classes.include?(@configuration.no_toc_class) } .inject([]) do |entries, node| text = node.text - id = node.attribute('id') || text - .downcase - .gsub(PUNCTUATION_REGEXP, '') # remove punctuation - .tr(' ', '-') # replace spaces with dash + id = node.attribute('id') || generate_toc_id(text) suffix_num = headers[id] headers[id] += 1 diff --git a/test/parser/test_option_error.rb b/test/parser/test_invalid_options.rb similarity index 51% rename from test/parser/test_option_error.rb rename to test/parser/test_invalid_options.rb index c469e29..db2ad38 100644 --- a/test/parser/test_option_error.rb +++ b/test/parser/test_invalid_options.rb @@ -2,9 +2,9 @@ require 'test_helper' -class TestOptionError < Minitest::Test +class TestInvalidOptions < Minitest::Test BASE_HTML = '

h1

' - EXPECTED_HTML = <<~HTML + EXPECTED_HTML = <<~HTML.chomp @@ -12,29 +12,21 @@ class TestOptionError < Minitest::Test def test_option_is_nil parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, nil) - doc = Nokogiri::HTML(parser.toc) - expected = EXPECTED_HTML - assert_equal(expected, doc.css('ul.section-nav').to_s) + assert_equal(EXPECTED_HTML, parser.build_toc) end def test_option_is_epmty_string parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, '') - doc = Nokogiri::HTML(parser.toc) - expected = EXPECTED_HTML - assert_equal(expected, doc.css('ul.section-nav').to_s) + assert_equal(EXPECTED_HTML, parser.build_toc) end def test_option_is_string parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, 'string') - doc = Nokogiri::HTML(parser.toc) - expected = EXPECTED_HTML - assert_equal(expected, doc.css('ul.section-nav').to_s) + assert_equal(EXPECTED_HTML, parser.build_toc) end def test_option_is_array parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, []) - doc = Nokogiri::HTML(parser.toc) - expected = EXPECTED_HTML - assert_equal(expected, doc.css('ul.section-nav').to_s) + assert_equal(EXPECTED_HTML, parser.build_toc) end end diff --git a/test/parser/test_various_toc_html.rb b/test/parser/test_various_toc_html.rb index 2668b31..26e4ccf 100644 --- a/test/parser/test_various_toc_html.rb +++ b/test/parser/test_various_toc_html.rb @@ -3,75 +3,19 @@ require 'test_helper' class TestVariousTocHtml < Minitest::Test - # ref. https://github.com/toshimaru/jekyll-toc/issues/45 - ANGLE_BRACKET_HTML = <<~HTML -

h1

-

<base href>

-

& < >

- HTML - - NO_TOC_HTML = <<~HTML -

h1

-

no_toc h1

-

h2

-

no_toc h2

-

h3

-

no_toc h3

-

h4

-

no_toc h4

- HTML - - JAPANESE_HEADINGS_HTML = <<~HTML -

-

-

- HTML - - TAGS_INSIDE_HEADINGS_HTML = <<~HTML -

h2

-

h2

- HTML - - TEST_HTML_1 = <<~HTML -

h1

-

h3

-
h6
- HTML - - TEST_HTML_2 = <<~HTML + TEST_HTML = <<~HTML

h1

h3

-

h2

-
h6
- HTML - - TEST_HTML_3 = <<~HTML
h6
-
h5
-

h4

-

h3

-

h2

-

h1

- HTML - - TEST_HTML_4 = <<~HTML -

h1

-

h3

-

h2

-

h4

-
h5
HTML def test_nested_toc - parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_1) - doc = Nokogiri::HTML(parser.toc) - expected = <<~HTML + parser = Jekyll::TableOfContents::Parser.new(TEST_HTML) + expected = <<~HTML.chomp