jekyll-toc 0.12.2 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,13 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
+ gem "appraisal"
6
+ gem "minitest-reporters"
7
+ gem "minitest"
8
+ gem "pry"
9
+ gem "rake"
10
+ gem "rubocop", "~> 0.81"
11
+ gem "simplecov", "~> 0.17.1"
5
12
  gem "jekyll", "3.8"
6
13
 
7
14
  gemspec path: "../"
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "minitest-reporters"
7
+ gem "minitest"
8
+ gem "pry"
9
+ gem "rake"
10
+ gem "rubocop", "~> 0.81"
11
+ gem "simplecov", "~> 0.17.1"
12
+ gem "jekyll", "3.9"
13
+
14
+ gemspec path: "../"
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "minitest-reporters"
7
+ gem "minitest"
8
+ gem "pry"
9
+ gem "rake"
10
+ gem "rubocop", "~> 0.81"
11
+ gem "simplecov", "~> 0.17.1"
12
+ gem "jekyll", "4.0"
13
+
14
+ gemspec path: "../"
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "minitest-reporters"
7
+ gem "minitest"
8
+ gem "pry"
9
+ gem "rake"
10
+ gem "rubocop", "~> 0.81"
11
+ gem "simplecov", "~> 0.17.1"
12
+ gem "jekyll", "4.1"
13
+
14
+ gemspec path: "../"
@@ -1,30 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path('../lib', __FILE__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'version'
5
+ require 'table_of_contents/version'
4
6
 
5
7
  Gem::Specification.new do |spec|
6
8
  spec.name = 'jekyll-toc'
7
- spec.version = JekyllToc::VERSION
9
+ spec.version = Jekyll::TableOfContents::VERSION
8
10
  spec.summary = 'Jekyll Table of Contents plugin'
9
- spec.description = 'A liquid filter plugin for Jekyll which generates a table of contents.'
11
+ spec.description = 'Jekyll (Ruby static website generator) plugin which generates a Table of Contents for the page.'
10
12
  spec.authors = %w(toshimaru torbjoernk)
11
13
  spec.email = 'me@toshimaru.net'
12
14
  spec.files = `git ls-files -z`.split("\x0")
13
15
  spec.homepage = 'https://github.com/toshimaru/jekyll-toc'
14
16
  spec.license = 'MIT'
15
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.test_files = spec.files.grep(%r{^(test|spec)/})
16
18
  spec.require_paths = ['lib']
17
19
 
18
- spec.required_ruby_version = '>= 2.3'
19
-
20
- spec.add_runtime_dependency 'nokogiri', '~> 1.9'
20
+ spec.required_ruby_version = '>= 2.4'
21
21
 
22
- spec.add_development_dependency 'appraisal'
23
- spec.add_development_dependency 'jekyll', '>= 3.5'
24
- spec.add_development_dependency 'minitest', '~> 5.11'
25
- spec.add_development_dependency 'minitest-reporters'
26
- spec.add_development_dependency 'pry'
27
- spec.add_development_dependency 'rake'
28
- spec.add_development_dependency 'rubocop'
29
- spec.add_development_dependency 'simplecov'
22
+ spec.add_dependency 'jekyll', '>= 3.8'
23
+ spec.add_dependency 'nokogiri', '~> 1.10'
30
24
  end
@@ -4,12 +4,13 @@ module Jekyll
4
4
  module TableOfContents
5
5
  # jekyll-toc configuration class
6
6
  class Configuration
7
- attr_accessor :toc_levels, :no_toc_class, :no_toc_section_class,
8
- :list_class, :sublist_class, :item_class, :item_prefix
7
+ attr_reader :toc_levels, :no_toc_class, :ordered_list, :no_toc_section_class,
8
+ :list_class, :sublist_class, :item_class, :item_prefix
9
9
 
10
10
  DEFAULT_CONFIG = {
11
11
  'min_level' => 1,
12
12
  'max_level' => 6,
13
+ 'ordered_list' => false,
13
14
  'no_toc_section_class' => 'no_toc_section',
14
15
  'list_class' => 'section-nav',
15
16
  'sublist_class' => '',
@@ -21,6 +22,7 @@ module Jekyll
21
22
  options = generate_option_hash(options)
22
23
 
23
24
  @toc_levels = options['min_level']..options['max_level']
25
+ @ordered_list = options['ordered_list']
24
26
  @no_toc_class = 'no_toc'
25
27
  @no_toc_section_class = options['no_toc_section_class']
26
28
  @list_class = options['list_class']
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module TableOfContents
5
+ # helper methods for Parser
6
+ module Helper
7
+ PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u.freeze
8
+
9
+ def generate_toc_id(text)
10
+ text = text.downcase
11
+ .gsub(PUNCTUATION_REGEXP, '') # remove punctuation
12
+ .tr(' ', '-') # replace spaces with dash
13
+ CGI.escape(text)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'table_of_contents/helper'
4
+
3
5
  module Jekyll
4
6
  module TableOfContents
5
7
  # Parse html contents and generate table of contents
6
8
  class Parser
7
- PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u
9
+ include ::Jekyll::TableOfContents::Helper
8
10
 
9
11
  def initialize(html, options = {})
10
12
  @doc = Nokogiri::HTML::DocumentFragment.parse(html)
@@ -17,11 +19,12 @@ module Jekyll
17
19
  end
18
20
 
19
21
  def build_toc
20
- %(<ul class="#{@configuration.list_class}">\n#{build_toc_list(@entries)}</ul>)
22
+ %(<#{list_tag} class="#{@configuration.list_class}">\n#{build_toc_list(@entries)}</#{list_tag}>)
21
23
  end
22
24
 
23
25
  def inject_anchors_into_html
24
26
  @entries.each do |entry|
27
+ # NOTE: `entry[:id]` is automatically URL encoded by Nokogiri
25
28
  entry[:header_content].add_previous_sibling(
26
29
  %(<a class="anchor" href="##{entry[:id]}" aria-hidden="true"><span class="octicon octicon-link"></span></a>)
27
30
  )
@@ -41,10 +44,7 @@ module Jekyll
41
44
  .reject { |n| n.classes.include?(@configuration.no_toc_class) }
42
45
  .inject([]) do |entries, node|
43
46
  text = node.text
44
- id = node.attribute('id') || text
45
- .downcase
46
- .gsub(PUNCTUATION_REGEXP, '') # remove punctuation
47
- .tr(' ', '-') # replace spaces with dash
47
+ id = node.attribute('id') || generate_toc_id(text)
48
48
 
49
49
  suffix_num = headers[id]
50
50
  headers[id] += 1
@@ -74,7 +74,7 @@ module Jekyll
74
74
  next_i = i + 1
75
75
  if next_i < entries.count && entries[next_i][:h_num] > min_h_num
76
76
  nest_entries = get_nest_entries(entries[next_i, entries.count], min_h_num)
77
- toc_list << %(\n<ul#{ul_attributes}>\n#{build_toc_list(nest_entries)}</ul>\n)
77
+ toc_list << %(\n<#{list_tag}#{ul_attributes}>\n#{build_toc_list(nest_entries)}</#{list_tag}>\n)
78
78
  i += nest_entries.count
79
79
  end
80
80
  # Add the closing tag for the current entry in the list
@@ -107,7 +107,7 @@ module Jekyll
107
107
  end
108
108
 
109
109
  def toc_headings_in_no_toc_section
110
- if @configuration.no_toc_section_class.is_a? Array
110
+ if @configuration.no_toc_section_class.is_a?(Array)
111
111
  @configuration.no_toc_section_class.map { |cls| toc_headings_within(cls) }.join(',')
112
112
  else
113
113
  toc_headings_within(@configuration.no_toc_section_class)
@@ -121,6 +121,10 @@ module Jekyll
121
121
  def ul_attributes
122
122
  @ul_attributes ||= @configuration.sublist_class.empty? ? '' : %( class="#{@configuration.sublist_class}")
123
123
  end
124
+
125
+ def list_tag
126
+ @list_tag ||= @configuration.ordered_list ? 'ol' : 'ul'
127
+ end
124
128
  end
125
129
  end
126
130
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module TableOfContents
5
+ VERSION = '0.15.0'
6
+ end
7
+ end
@@ -18,6 +18,6 @@ class TestInjectAnchorsFilter < Minitest::Test
18
18
  def test_does_not_inject_toc
19
19
  html = @parser.inject_anchors_into_html
20
20
 
21
- assert_nil(/<ul class="section-nav">/ =~ html)
21
+ refute_includes(html, %(<ul class="section-nav">))
22
22
  end
23
23
  end
@@ -2,9 +2,9 @@
2
2
 
3
3
  require 'test_helper'
4
4
 
5
- class TestOptionError < Minitest::Test
5
+ class TestInvalidOptions < Minitest::Test
6
6
  BASE_HTML = '<h1>h1</h1>'
7
- EXPECTED_HTML = <<~HTML
7
+ EXPECTED_HTML = <<~HTML.chomp
8
8
  <ul class="section-nav">
9
9
  <li class="toc-entry toc-h1"><a href="#h1">h1</a></li>
10
10
  </ul>
@@ -12,29 +12,21 @@ class TestOptionError < Minitest::Test
12
12
 
13
13
  def test_option_is_nil
14
14
  parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, nil)
15
- doc = Nokogiri::HTML(parser.toc)
16
- expected = EXPECTED_HTML
17
- assert_equal(expected, doc.css('ul.section-nav').to_s)
15
+ assert_equal(EXPECTED_HTML, parser.build_toc)
18
16
  end
19
17
 
20
18
  def test_option_is_epmty_string
21
19
  parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, '')
22
- doc = Nokogiri::HTML(parser.toc)
23
- expected = EXPECTED_HTML
24
- assert_equal(expected, doc.css('ul.section-nav').to_s)
20
+ assert_equal(EXPECTED_HTML, parser.build_toc)
25
21
  end
26
22
 
27
23
  def test_option_is_string
28
24
  parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, 'string')
29
- doc = Nokogiri::HTML(parser.toc)
30
- expected = EXPECTED_HTML
31
- assert_equal(expected, doc.css('ul.section-nav').to_s)
25
+ assert_equal(EXPECTED_HTML, parser.build_toc)
32
26
  end
33
27
 
34
28
  def test_option_is_array
35
29
  parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, [])
36
- doc = Nokogiri::HTML(parser.toc)
37
- expected = EXPECTED_HTML
38
- assert_equal(expected, doc.css('ul.section-nav').to_s)
30
+ assert_equal(EXPECTED_HTML, parser.build_toc)
39
31
  end
40
32
  end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class TestOrderedList < Minitest::Test
6
+ include TestHelpers
7
+
8
+ def test_default_configuration
9
+ configuration = Jekyll::TableOfContents::Configuration.new({})
10
+
11
+ refute(configuration.ordered_list)
12
+ end
13
+
14
+ def test_disabled_ordered_list
15
+ configuration = Jekyll::TableOfContents::Configuration.new('ordered_list' => false)
16
+
17
+ refute(configuration.ordered_list)
18
+ end
19
+
20
+ def test_enabled_ordered_list
21
+ configuration = Jekyll::TableOfContents::Configuration.new('ordered_list' => true)
22
+
23
+ assert(configuration.ordered_list)
24
+ end
25
+
26
+ def test_basic_ordered_list_top_heading
27
+ parse_with_ordered_list
28
+ html = @parser.toc
29
+
30
+ assert_match(/^<ol class="section-nav">/, html)
31
+ end
32
+
33
+ def test_ordered_list_sub_headings
34
+ parse_with_ordered_list
35
+ html = @parser.toc
36
+
37
+ assert_match(/<ol>\n<li class="toc-entry/, html)
38
+ end
39
+
40
+ def test_ordered_list_top_heading_with_classes
41
+ parse_with_ordered_list_and_classes
42
+ html = @parser.toc
43
+
44
+ assert_match(/^<ol class="top-list-class">/, html)
45
+ end
46
+
47
+ def test_ordered_list_sub_headings_with_classes
48
+ parse_with_ordered_list_and_classes
49
+ html = @parser.toc
50
+
51
+ assert_match(/<ol class="sublist-class">/, html)
52
+ end
53
+
54
+ def test_ordered_list_subheadings_with_classes_nested_structure
55
+ parse_with_ordered_list_and_classes
56
+ html = @parser.toc
57
+
58
+ occurrences = html.scan(/<ol class="sublist-class">/).count
59
+
60
+ assert_equal(5, occurrences)
61
+ end
62
+
63
+ private
64
+
65
+ def parse_with_ordered_list
66
+ read_html_and_create_parser('ordered_list' => true)
67
+ end
68
+
69
+ def parse_with_ordered_list_and_classes
70
+ read_html_and_create_parser(
71
+ 'ordered_list' => true,
72
+ 'list_class' => 'top-list-class',
73
+ 'sublist_class' => 'sublist-class'
74
+ )
75
+ end
76
+ end
@@ -12,12 +12,12 @@ class TestTOCOnlyFilter < Minitest::Test
12
12
  def test_injects_toc_container
13
13
  html = @parser.build_toc
14
14
 
15
- assert_match(/<ul class="section-nav">/, html)
15
+ assert_includes(html, %(<ul class="section-nav">))
16
16
  end
17
17
 
18
18
  def test_does_not_return_content
19
19
  html = @parser.build_toc
20
20
 
21
- assert_nil(%r{<h1>Simple H1</h1>} =~ html)
21
+ refute_includes(html, %(<h1>Simple H1</h1>))
22
22
  end
23
23
  end
@@ -3,75 +3,19 @@
3
3
  require 'test_helper'
4
4
 
5
5
  class TestVariousTocHtml < Minitest::Test
6
- # ref. https://github.com/toshimaru/jekyll-toc/issues/45
7
- ANGLE_BRACKET_HTML = <<~HTML
8
- <h1>h1</h1>
9
- <h1>&lt;base href&gt;</h1>
10
- <h1>&amp; &lt; &gt;</h1>
11
- HTML
12
-
13
- NO_TOC_HTML = <<~HTML
14
- <h1>h1</h1>
15
- <h1 class="no_toc">no_toc h1</h1>
16
- <h2>h2</h2>
17
- <h2 class="no_toc">no_toc h2</h2>
18
- <h3>h3</h3>
19
- <h3 class="no_toc">no_toc h3</h3>
20
- <h4>h4</h4>
21
- <h4 class="no_toc">no_toc h4</h4>
22
- HTML
23
-
24
- JAPANESE_HEADINGS_HTML = <<~HTML
25
- <h1>あ</h1>
26
- <h2>い</h2>
27
- <h3>う</h3>
28
- HTML
29
-
30
- TAGS_INSIDE_HEADINGS_HTML = <<~HTML
31
- <h2><strong>h2</strong></h2>
32
- <h2><em>h2</em></h2>
33
- HTML
34
-
35
- TEST_HTML_1 = <<~HTML
36
- <h1>h1</h1>
37
- <h3>h3</h3>
38
- <h6>h6</h6>
39
- HTML
40
-
41
- TEST_HTML_2 = <<~HTML
6
+ TEST_HTML = <<~HTML
42
7
  <h1>h1</h1>
43
8
  <h3>h3</h3>
44
- <h2>h2</h2>
45
- <h6>h6</h6>
46
- HTML
47
-
48
- TEST_HTML_3 = <<~HTML
49
9
  <h6>h6</h6>
50
- <h5>h5</h5>
51
- <h4>h4</h4>
52
- <h3>h3</h3>
53
- <h2>h2</h2>
54
- <h1>h1</h1>
55
- HTML
56
-
57
- TEST_HTML_4 = <<~HTML
58
- <h1>h1</h1>
59
- <h3>h3</h3>
60
- <h2>h2</h2>
61
- <h4>h4</h4>
62
- <h5>h5</h5>
63
10
  HTML
64
11
 
65
12
  def test_nested_toc
66
- parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_1)
67
- doc = Nokogiri::HTML(parser.toc)
68
- expected = <<~HTML
13
+ parser = Jekyll::TableOfContents::Parser.new(TEST_HTML)
14
+ expected = <<~HTML.chomp
69
15
  <ul class="section-nav">
70
- <li class="toc-entry toc-h1">
71
- <a href="#h1">h1</a>
16
+ <li class="toc-entry toc-h1"><a href="#h1">h1</a>
72
17
  <ul>
73
- <li class="toc-entry toc-h3">
74
- <a href="#h3">h3</a>
18
+ <li class="toc-entry toc-h3"><a href="#h3">h3</a>
75
19
  <ul>
76
20
  <li class="toc-entry toc-h6"><a href="#h6">h6</a></li>
77
21
  </ul>
@@ -80,35 +24,34 @@ class TestVariousTocHtml < Minitest::Test
80
24
  </li>
81
25
  </ul>
82
26
  HTML
83
- actual = doc.css('ul.section-nav').to_s
84
27
 
85
- assert_equal(expected, actual)
28
+ assert_equal(expected, parser.build_toc)
86
29
  end
87
30
 
88
31
  def test_nested_toc_with_min_and_max
89
- parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_1, 'min_level' => 2, 'max_level' => 5)
90
- doc = Nokogiri::HTML(parser.toc)
91
- expected = <<~HTML
32
+ parser = Jekyll::TableOfContents::Parser.new(TEST_HTML, 'min_level' => 2, 'max_level' => 5)
33
+ expected = <<~HTML.chomp
92
34
  <ul class="section-nav">
93
35
  <li class="toc-entry toc-h3"><a href="#h3">h3</a></li>
94
36
  </ul>
95
37
  HTML
96
- actual = doc.css('ul.section-nav').to_s
97
38
 
98
- assert_equal(expected, actual)
39
+ assert_equal(expected, parser.build_toc)
99
40
  end
100
41
 
101
42
  def test_complex_nested_toc
102
- parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_2)
103
- doc = Nokogiri::HTML(parser.toc)
104
- expected = <<~HTML
43
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML)
44
+ <h1>h1</h1>
45
+ <h3>h3</h3>
46
+ <h2>h2</h2>
47
+ <h6>h6</h6>
48
+ HTML
49
+ expected = <<~HTML.chomp
105
50
  <ul class="section-nav">
106
- <li class="toc-entry toc-h1">
107
- <a href="#h1">h1</a>
51
+ <li class="toc-entry toc-h1"><a href="#h1">h1</a>
108
52
  <ul>
109
53
  <li class="toc-entry toc-h3"><a href="#h3">h3</a></li>
110
- <li class="toc-entry toc-h2">
111
- <a href="#h2">h2</a>
54
+ <li class="toc-entry toc-h2"><a href="#h2">h2</a>
112
55
  <ul>
113
56
  <li class="toc-entry toc-h6"><a href="#h6">h6</a></li>
114
57
  </ul>
@@ -117,15 +60,20 @@ class TestVariousTocHtml < Minitest::Test
117
60
  </li>
118
61
  </ul>
119
62
  HTML
120
- actual = doc.css('ul.section-nav').to_s
121
63
 
122
- assert_equal(expected, actual)
64
+ assert_equal(expected, parser.build_toc)
123
65
  end
124
66
 
125
67
  def test_decremental_headings1
126
- parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_3)
127
- doc = Nokogiri::HTML(parser.toc)
128
- expected = <<~HTML
68
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML)
69
+ <h6>h6</h6>
70
+ <h5>h5</h5>
71
+ <h4>h4</h4>
72
+ <h3>h3</h3>
73
+ <h2>h2</h2>
74
+ <h1>h1</h1>
75
+ HTML
76
+ expected = <<~HTML.chomp
129
77
  <ul class="section-nav">
130
78
  <li class="toc-entry toc-h6"><a href="#h6">h6</a></li>
131
79
  <li class="toc-entry toc-h5"><a href="#h5">h5</a></li>
@@ -135,25 +83,26 @@ class TestVariousTocHtml < Minitest::Test
135
83
  <li class="toc-entry toc-h1"><a href="#h1">h1</a></li>
136
84
  </ul>
137
85
  HTML
138
- actual = doc.css('ul.section-nav').to_s
139
86
 
140
- assert_equal(expected, actual)
87
+ assert_equal(expected, parser.build_toc)
141
88
  end
142
89
 
143
90
  def test_decremental_headings2
144
- parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_4)
145
- doc = Nokogiri::HTML(parser.toc)
146
- expected = <<~HTML
91
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML)
92
+ <h1>h1</h1>
93
+ <h3>h3</h3>
94
+ <h2>h2</h2>
95
+ <h4>h4</h4>
96
+ <h5>h5</h5>
97
+ HTML
98
+ expected = <<~HTML.chomp
147
99
  <ul class="section-nav">
148
- <li class="toc-entry toc-h1">
149
- <a href="#h1">h1</a>
100
+ <li class="toc-entry toc-h1"><a href="#h1">h1</a>
150
101
  <ul>
151
102
  <li class="toc-entry toc-h3"><a href="#h3">h3</a></li>
152
- <li class="toc-entry toc-h2">
153
- <a href="#h2">h2</a>
103
+ <li class="toc-entry toc-h2"><a href="#h2">h2</a>
154
104
  <ul>
155
- <li class="toc-entry toc-h4">
156
- <a href="#h4">h4</a>
105
+ <li class="toc-entry toc-h4"><a href="#h4">h4</a>
157
106
  <ul>
158
107
  <li class="toc-entry toc-h5"><a href="#h5">h5</a></li>
159
108
  </ul>
@@ -165,22 +114,27 @@ class TestVariousTocHtml < Minitest::Test
165
114
  </ul>
166
115
  HTML
167
116
 
168
- assert_equal(expected, doc.css('ul.section-nav').to_s)
117
+ assert_equal(expected, parser.build_toc)
169
118
  end
170
119
 
171
120
  def test_no_toc
172
- parser = Jekyll::TableOfContents::Parser.new(NO_TOC_HTML)
173
- doc = Nokogiri::HTML(parser.toc)
174
- expected = <<~HTML
121
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML)
122
+ <h1>h1</h1>
123
+ <h1 class="no_toc">no_toc h1</h1>
124
+ <h2>h2</h2>
125
+ <h2 class="no_toc">no_toc h2</h2>
126
+ <h3>h3</h3>
127
+ <h3 class="no_toc">no_toc h3</h3>
128
+ <h4>h4</h4>
129
+ <h4 class="no_toc">no_toc h4</h4>
130
+ HTML
131
+ expected = <<~HTML.chomp
175
132
  <ul class="section-nav">
176
- <li class="toc-entry toc-h1">
177
- <a href="#h1">h1</a>
133
+ <li class="toc-entry toc-h1"><a href="#h1">h1</a>
178
134
  <ul>
179
- <li class="toc-entry toc-h2">
180
- <a href="#h2">h2</a>
135
+ <li class="toc-entry toc-h2"><a href="#h2">h2</a>
181
136
  <ul>
182
- <li class="toc-entry toc-h3">
183
- <a href="#h3">h3</a>
137
+ <li class="toc-entry toc-h3"><a href="#h3">h3</a>
184
138
  <ul>
185
139
  <li class="toc-entry toc-h4"><a href="#h4">h4</a></li>
186
140
  </ul>
@@ -191,21 +145,21 @@ class TestVariousTocHtml < Minitest::Test
191
145
  </li>
192
146
  </ul>
193
147
  HTML
194
- actual = doc.css('ul.section-nav').to_s
195
148
 
196
- assert_equal(expected, actual)
149
+ assert_equal(expected, parser.build_toc)
197
150
  end
198
151
 
199
152
  def test_japanese_toc
200
- parser = Jekyll::TableOfContents::Parser.new(JAPANESE_HEADINGS_HTML)
201
- doc = Nokogiri::HTML(parser.toc)
202
- expected = <<~HTML
153
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML)
154
+ <h1>あ</h1>
155
+ <h2>い</h2>
156
+ <h3>う</h3>
157
+ HTML
158
+ expected = <<~HTML.chomp
203
159
  <ul class="section-nav">
204
- <li class="toc-entry toc-h1">
205
- <a href="#%E3%81%82">あ</a>
160
+ <li class="toc-entry toc-h1"><a href="#%E3%81%82">あ</a>
206
161
  <ul>
207
- <li class="toc-entry toc-h2">
208
- <a href="#%E3%81%84">い</a>
162
+ <li class="toc-entry toc-h2"><a href="#%E3%81%84">い</a>
209
163
  <ul>
210
164
  <li class="toc-entry toc-h3"><a href="#%E3%81%86">う</a></li>
211
165
  </ul>
@@ -214,59 +168,61 @@ class TestVariousTocHtml < Minitest::Test
214
168
  </li>
215
169
  </ul>
216
170
  HTML
217
- actual = doc.css('ul.section-nav').to_s
218
171
 
219
- assert_equal(expected, actual)
172
+ assert_equal(expected, parser.build_toc)
173
+ html_with_anchors = parser.inject_anchors_into_html
174
+ assert_match(%r{<a class="anchor" href="#%E3%81%82" aria-hidden="true"><span.*span></a>あ}, html_with_anchors)
175
+ assert_match(%r{<a class="anchor" href="#%E3%81%84" aria-hidden="true"><span.*span></a>い}, html_with_anchors)
176
+ assert_match(%r{<a class="anchor" href="#%E3%81%86" aria-hidden="true"><span.*span></a>う}, html_with_anchors)
220
177
  end
221
178
 
179
+ # ref. https://github.com/toshimaru/jekyll-toc/issues/45
222
180
  def test_angle_bracket
223
- parser = Jekyll::TableOfContents::Parser.new(ANGLE_BRACKET_HTML)
224
- doc = Nokogiri::HTML(parser.toc)
225
- expected = <<~HTML
181
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML)
182
+ <h1>h1</h1>
183
+ <h1>&lt;base href&gt;</h1>
184
+ <h1>&amp; &lt; &gt;</h1>
185
+ HTML
186
+ expected = <<~HTML.chomp
226
187
  <ul class="section-nav">
227
188
  <li class="toc-entry toc-h1"><a href="#h1">h1</a></li>
228
189
  <li class="toc-entry toc-h1"><a href="#base-href">&lt;base href&gt;</a></li>
229
190
  <li class="toc-entry toc-h1"><a href="#--">&amp; &lt; &gt;</a></li>
230
191
  </ul>
231
192
  HTML
232
- actual = doc.css('ul.section-nav').to_s
233
193
 
234
- assert_equal(expected, actual)
194
+ assert_equal(expected, parser.build_toc)
235
195
  end
236
196
 
237
197
  def test_tags_inside_heading
238
- parser = Jekyll::TableOfContents::Parser.new(TAGS_INSIDE_HEADINGS_HTML)
239
- doc = Nokogiri::HTML(parser.toc)
240
- expected = <<~HTML
198
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML)
199
+ <h2><strong>h2</strong></h2>
200
+ <h2><em>h2</em></h2>
201
+ HTML
202
+ expected = <<~HTML.chomp
241
203
  <ul class="section-nav">
242
204
  <li class="toc-entry toc-h2"><a href="#h2">h2</a></li>
243
205
  <li class="toc-entry toc-h2"><a href="#h2-1">h2</a></li>
244
206
  </ul>
245
207
  HTML
246
- actual = doc.css('ul.section-nav').to_s
247
208
 
248
- assert_equal(expected, actual)
209
+ assert_equal(expected, parser.build_toc)
249
210
  end
250
211
 
251
- TEST_HTML_IGNORE = <<~HTML
252
- <h1>h1</h1>
253
- <div class="no_toc_section">
254
- <h2>h2</h2>
255
- </div>
256
- <h3>h3</h3>
257
- <h6>h6</h6>
258
- HTML
259
-
260
212
  def test_nested_toc_with_no_toc_section_class
261
- parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_IGNORE)
262
- doc = Nokogiri::HTML(parser.toc)
263
- expected = <<~HTML
213
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML)
214
+ <h1>h1</h1>
215
+ <div class="no_toc_section">
216
+ <h2>h2</h2>
217
+ </div>
218
+ <h3>h3</h3>
219
+ <h6>h6</h6>
220
+ HTML
221
+ expected = <<~HTML.chomp
264
222
  <ul class="section-nav">
265
- <li class="toc-entry toc-h1">
266
- <a href="#h1">h1</a>
223
+ <li class="toc-entry toc-h1"><a href="#h1">h1</a>
267
224
  <ul>
268
- <li class="toc-entry toc-h3">
269
- <a href="#h3">h3</a>
225
+ <li class="toc-entry toc-h3"><a href="#h3">h3</a>
270
226
  <ul>
271
227
  <li class="toc-entry toc-h6"><a href="#h6">h6</a></li>
272
228
  </ul>
@@ -275,8 +231,7 @@ class TestVariousTocHtml < Minitest::Test
275
231
  </li>
276
232
  </ul>
277
233
  HTML
278
- actual = doc.css('ul.section-nav').to_s
279
- assert_equal(expected, actual)
234
+ assert_equal(expected, parser.build_toc)
280
235
 
281
236
  html = parser.inject_anchors_into_html
282
237
  assert_match(%r{<h1>.+</h1>}m, html)
@@ -285,29 +240,24 @@ class TestVariousTocHtml < Minitest::Test
285
240
  assert_includes(html, '<h2>h2</h2>')
286
241
  end
287
242
 
288
- TEST_HTML_IGNORE_2 = <<~HTML
289
- <h1>h1</h1>
290
- <div class="exclude">
291
- <h2>h2</h2>
292
- </div>
293
- <h3>h3</h3>
294
- <div class="exclude">
295
- <h4>h4</h4>
296
- <h5>h5</h5>
297
- </div>
298
- <h6>h6</h6>
299
- HTML
300
-
301
243
  def test_nested_toc_with_no_toc_section_class_option
302
- parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_IGNORE_2, 'no_toc_section_class' => 'exclude')
303
- doc = Nokogiri::HTML(parser.toc)
304
- expected = <<~HTML
244
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML, 'no_toc_section_class' => 'exclude')
245
+ <h1>h1</h1>
246
+ <div class="exclude">
247
+ <h2>h2</h2>
248
+ </div>
249
+ <h3>h3</h3>
250
+ <div class="exclude">
251
+ <h4>h4</h4>
252
+ <h5>h5</h5>
253
+ </div>
254
+ <h6>h6</h6>
255
+ HTML
256
+ expected = <<~HTML.chomp
305
257
  <ul class="section-nav">
306
- <li class="toc-entry toc-h1">
307
- <a href="#h1">h1</a>
258
+ <li class="toc-entry toc-h1"><a href="#h1">h1</a>
308
259
  <ul>
309
- <li class="toc-entry toc-h3">
310
- <a href="#h3">h3</a>
260
+ <li class="toc-entry toc-h3"><a href="#h3">h3</a>
311
261
  <ul>
312
262
  <li class="toc-entry toc-h6"><a href="#h6">h6</a></li>
313
263
  </ul>
@@ -316,8 +266,7 @@ class TestVariousTocHtml < Minitest::Test
316
266
  </li>
317
267
  </ul>
318
268
  HTML
319
- actual = doc.css('ul.section-nav').to_s
320
- assert_equal(expected, actual)
269
+ assert_equal(expected, parser.build_toc)
321
270
 
322
271
  html = parser.inject_anchors_into_html
323
272
  assert_match(%r{<h1>.+</h1>}m, html)
@@ -328,29 +277,24 @@ class TestVariousTocHtml < Minitest::Test
328
277
  assert_includes(html, '<h5>h5</h5>')
329
278
  end
330
279
 
331
- TEST_HTML_IGNORE_3 = <<~HTML
332
- <h1>h1</h1>
333
- <div class="no_toc_section">
334
- <h2>h2</h2>
335
- </div>
336
- <h3>h3</h3>
337
- <div class="exclude">
338
- <h4>h4</h4>
339
- <h5>h5</h5>
340
- </div>
341
- <h6>h6</h6>
342
- HTML
343
-
344
280
  def test_multiple_no_toc_section_classes
345
- parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_IGNORE_3, 'no_toc_section_class' => ['no_toc_section', 'exclude'])
346
- doc = Nokogiri::HTML(parser.toc)
347
- expected = <<~HTML
281
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML, 'no_toc_section_class' => ['no_toc_section', 'exclude'])
282
+ <h1>h1</h1>
283
+ <div class="no_toc_section">
284
+ <h2>h2</h2>
285
+ </div>
286
+ <h3>h3</h3>
287
+ <div class="exclude">
288
+ <h4>h4</h4>
289
+ <h5>h5</h5>
290
+ </div>
291
+ <h6>h6</h6>
292
+ HTML
293
+ expected = <<~HTML.chomp
348
294
  <ul class="section-nav">
349
- <li class="toc-entry toc-h1">
350
- <a href="#h1">h1</a>
295
+ <li class="toc-entry toc-h1"><a href="#h1">h1</a>
351
296
  <ul>
352
- <li class="toc-entry toc-h3">
353
- <a href="#h3">h3</a>
297
+ <li class="toc-entry toc-h3"><a href="#h3">h3</a>
354
298
  <ul>
355
299
  <li class="toc-entry toc-h6"><a href="#h6">h6</a></li>
356
300
  </ul>
@@ -359,8 +303,7 @@ class TestVariousTocHtml < Minitest::Test
359
303
  </li>
360
304
  </ul>
361
305
  HTML
362
- actual = doc.css('ul.section-nav').to_s
363
- assert_equal(expected, actual)
306
+ assert_equal(expected, parser.build_toc)
364
307
 
365
308
  html = parser.inject_anchors_into_html
366
309
  assert_match(%r{<h1>.+</h1>}m, html)
@@ -371,24 +314,20 @@ class TestVariousTocHtml < Minitest::Test
371
314
  assert_includes(html, '<h5>h5</h5>')
372
315
  end
373
316
 
374
- TEST_EXPLICIT_ID = <<~HTML
375
- <h1>h1</h1>
376
- <h1 id="second">h2</h1>
377
- <h1 id="third">h3</h1>
378
- HTML
379
-
380
317
  def test_toc_with_explicit_id
381
- parser = Jekyll::TableOfContents::Parser.new(TEST_EXPLICIT_ID)
382
- doc = Nokogiri::HTML(parser.toc)
383
- expected = <<~HTML
318
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML)
319
+ <h1>h1</h1>
320
+ <h1 id="second">h2</h1>
321
+ <h1 id="third">h3</h1>
322
+ HTML
323
+ expected = <<~HTML.chomp
384
324
  <ul class="section-nav">
385
325
  <li class="toc-entry toc-h1"><a href="#h1">h1</a></li>
386
326
  <li class="toc-entry toc-h1"><a href="#second">h2</a></li>
387
327
  <li class="toc-entry toc-h1"><a href="#third">h3</a></li>
388
328
  </ul>
389
329
  HTML
390
- actual = doc.css('ul.section-nav').to_s
391
- assert_equal(expected, actual)
330
+ assert_equal(expected, parser.build_toc)
392
331
 
393
332
  html = parser.inject_anchors_into_html
394
333
  assert_includes(html, %(<a class="anchor" href="#h1" aria-hidden="true">))
@@ -396,39 +335,33 @@ class TestVariousTocHtml < Minitest::Test
396
335
  assert_includes(html, %(<a class="anchor" href="#third" aria-hidden="true">))
397
336
  end
398
337
 
399
- TEST_UNIQ_ID = <<~HTML
400
- <h1>h1</h1>
401
- <h1>h1</h1>
402
- <h1>h1</h1>
403
- HTML
404
-
405
338
  def test_anchor_is_uniq
406
- parser = Jekyll::TableOfContents::Parser.new(TEST_UNIQ_ID)
407
- doc = Nokogiri::HTML(parser.toc)
408
- expected = <<~HTML
339
+ parser = Jekyll::TableOfContents::Parser.new(<<~HTML)
340
+ <h1>h1</h1>
341
+ <h1>h1</h1>
342
+ <h1>h1</h1>
343
+ HTML
344
+ expected = <<~HTML.chomp
409
345
  <ul class="section-nav">
410
346
  <li class="toc-entry toc-h1"><a href="#h1">h1</a></li>
411
347
  <li class="toc-entry toc-h1"><a href="#h1-1">h1</a></li>
412
348
  <li class="toc-entry toc-h1"><a href="#h1-2">h1</a></li>
413
349
  </ul>
414
350
  HTML
415
- actual = doc.css('ul.section-nav').to_s
416
- assert_equal(expected, actual)
351
+
352
+ assert_equal(expected, parser.build_toc)
417
353
  end
418
354
 
419
355
  def test_custom_css_classes
420
356
  parser = Jekyll::TableOfContents::Parser.new(
421
- TEST_HTML_1,
357
+ TEST_HTML,
422
358
  'item_class' => 'custom-item', 'list_class' => 'custom-list', 'sublist_class' => 'custom-sublist', 'item_prefix' => 'custom-prefix-'
423
359
  )
424
- doc = Nokogiri::HTML(parser.toc)
425
- expected = <<~HTML
360
+ expected = <<~HTML.chomp
426
361
  <ul class="custom-list">
427
- <li class="custom-item custom-prefix-h1">
428
- <a href="#h1">h1</a>
362
+ <li class="custom-item custom-prefix-h1"><a href="#h1">h1</a>
429
363
  <ul class="custom-sublist">
430
- <li class="custom-item custom-prefix-h3">
431
- <a href="#h3">h3</a>
364
+ <li class="custom-item custom-prefix-h3"><a href="#h3">h3</a>
432
365
  <ul class="custom-sublist">
433
366
  <li class="custom-item custom-prefix-h6"><a href="#h6">h6</a></li>
434
367
  </ul>
@@ -438,6 +371,6 @@ class TestVariousTocHtml < Minitest::Test
438
371
  </ul>
439
372
  HTML
440
373
 
441
- assert_equal(expected, doc.css('ul.custom-list').to_s)
374
+ assert_equal(expected, parser.build_toc)
442
375
  end
443
376
  end