Skip to content

Commit

Permalink
Merge pull request #54 from toshimaru/add-notoc-test
Browse files Browse the repository at this point in the history
Yet another no_toc implementation
  • Loading branch information
toshimaru authored Sep 29, 2018
2 parents 5563612 + ce9fc53 commit 2a79a88
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 19 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ It looks like the image below.

## Customization

### Skip TOC(`no_toc`)

The heding is ignored in the toc when you add `no_toc` to the class.

```html
<h1>h1</h1>
<h1 class="no_toc">This heding is ignored in the toc</h1>
<h2>h2</h2>
```

### TOC level

The toc levels can be configured on `_config.yml`.
Expand Down
4 changes: 3 additions & 1 deletion lib/jekyll-toc.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'nokogiri'
require 'table_of_contents/parser'

Expand Down Expand Up @@ -33,7 +35,7 @@ def toc_enabled?
end

def toc_config
@context.registers[:site].config["toc"] || {}
@context.registers[:site].config['toc'] || {}
end
end
end
Expand Down
21 changes: 10 additions & 11 deletions lib/table_of_contents/parser.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# frozen_string_literal: true

module Jekyll
module TableOfContents
# Parse html contents and generate table of contents
class Parser
PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u

DEFAULT_CONFIG = {
"min_level" => 1,
"max_level" => 6,
}
'min_level' => 1,
'max_level' => 6
}.freeze

def initialize(html, options = {})
@doc = Nokogiri::HTML::DocumentFragment.parse(html)
options = generate_option_hash(options)
@toc_levels = options["min_level"]..options["max_level"]
@toc_levels = options['min_level']..options['max_level']
@entries = parse_content
end

Expand Down Expand Up @@ -41,11 +43,11 @@ def parse_content
headers = Hash.new(0)

# TODO: Use kramdown auto ids
@doc.css(toc_headings).each do |node|
@doc.css(toc_headings).reject { |n| n.classes.include?('no_toc') }.each do |node|
text = node.text
id = text.downcase
id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation
id.gsub!(' ', '-') # replace spaces with dash
id.tr!(' ', '-') # replace spaces with dash

uniq = headers[id] > 0 ? "-#{headers[id]}" : ''
headers[id] += 1
Expand All @@ -57,7 +59,6 @@ def parse_content
uniq: uniq,
text: text,
node_name: node.name,
no_toc: node.attribute('class') && node.attribute('class').value.include?('no_toc'),
content_node: header_content,
h_num: node.name.delete('h').to_i
}
Expand All @@ -69,14 +70,12 @@ def parse_content
# Returns the list items for entries
def build_toc_list(entries, last_ul_used: false)
i = 0
toc_list = ''
toc_list = ''.dup
min_h_num = entries.map { |e| e[:h_num] }.min

while i < entries.count
entry = entries[i]
if entry[:no_toc]
# Do nothing / skip entry
elsif entry[:h_num] == min_h_num
if entry[:h_num] == min_h_num
# If the current entry should not be indented in the list, add the entry to the list
toc_list << %(<li class="toc-entry toc-#{entry[:node_name]}"><a href="##{entry[:id]}#{entry[:uniq]}">#{entry[:text]}</a>)
# If the next entry should be indented in the list, generate a sublist
Expand Down
2 changes: 1 addition & 1 deletion lib/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module JekyllToc
VERSION = '0.7.0.alpha1'.freeze
VERSION = '0.7.0.beta1'.freeze
end
3 changes: 2 additions & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'simplecov'
SimpleCov.start

Expand All @@ -12,7 +14,6 @@
<h4>Simple H4</h4>
<h5>Simple H5</h5>
<h6>Simple H6</h6>
<h1 class="no_toc">No-toc H1</h1>
HTML

module TestHelpers
Expand Down
2 changes: 2 additions & 0 deletions test/test_inject_anchors_filter.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'test_helper'

class TestInjectAnchorsFilter < Minitest::Test
Expand Down
2 changes: 2 additions & 0 deletions test/test_kramdown_list.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'test_helper'

class TestKramdownList < Minitest::Test
Expand Down
2 changes: 2 additions & 0 deletions test/test_option_error.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'test_helper'

class TestOptionError < Minitest::Test
Expand Down
2 changes: 2 additions & 0 deletions test/test_toc_filter.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'test_helper'

class TestTOCFilter < Minitest::Test
Expand Down
2 changes: 2 additions & 0 deletions test/test_toc_only_filter.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'test_helper'

class TestTOCOnlyFilter < Minitest::Test
Expand Down
54 changes: 49 additions & 5 deletions test/test_various_toc_html.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'test_helper'

class TestVariousTocHtml < Minitest::Test
Expand Down Expand Up @@ -31,6 +33,17 @@ class TestVariousTocHtml < Minitest::Test
<h5>h5</h5>
HTML

NO_TOC_HTML = <<-HTML
<h1>h1</h1>
<h1 class="no_toc">no_toc h1</h1>
<h2>h2</h2>
<h2 class="no_toc">no_toc h2</h2>
<h3>h3</h3>
<h3 class="no_toc">no_toc h3</h3>
<h4>h4</h4>
<h4 class="no_toc">no_toc h4</h4>
HTML

def test_nested_toc
parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_1)
doc = Nokogiri::HTML(parser.toc)
Expand All @@ -49,8 +62,9 @@ def test_nested_toc
</li>
</ul>
HTML
actual = doc.css('ul.section-nav').to_s

assert_equal(expected, doc.css('ul.section-nav').to_s)
assert_equal(expected, actual)
end

def test_nested_toc_with_min_and_max
Expand All @@ -61,8 +75,9 @@ def test_nested_toc_with_min_and_max
<li class="toc-entry toc-h3"><a href="#h3">h3</a></li>
</ul>
HTML
actual = doc.css('ul.section-nav').to_s

assert_equal(expected, doc.css('ul.section-nav').to_s)
assert_equal(expected, actual)
end

def test_complex_nested_toc
Expand All @@ -84,8 +99,9 @@ def test_complex_nested_toc
</li>
</ul>
HTML
actual = doc.css('ul.section-nav').to_s

assert_equal(expected, doc.css('ul.section-nav').to_s)
assert_equal(expected, actual)
end

def test_decremental_headings1
Expand All @@ -101,11 +117,11 @@ def test_decremental_headings1
<li class="toc-entry toc-h1"><a href="#h1">h1</a></li>
</ul>
HTML
actual = doc.css('ul.section-nav').to_s

assert_equal(expected, doc.css('ul.section-nav').to_s)
assert_equal(expected, actual)
end


def test_decremental_headings2
parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_4)
doc = Nokogiri::HTML(parser.toc)
Expand Down Expand Up @@ -133,4 +149,32 @@ def test_decremental_headings2

assert_equal(expected, doc.css('ul.section-nav').to_s)
end

def test_no_toc
parser = Jekyll::TableOfContents::Parser.new(NO_TOC_HTML)
doc = Nokogiri::HTML(parser.toc)
expected = <<-HTML
<ul class="section-nav">
<li class="toc-entry toc-h1">
<a href="#h1">h1</a>
<ul>
<li class="toc-entry toc-h2">
<a href="#h2">h2</a>
<ul>
<li class="toc-entry toc-h3">
<a href="#h3">h3</a>
<ul>
<li class="toc-entry toc-h4"><a href="#h4">h4</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
HTML
actual = doc.css('ul.section-nav').to_s

assert_equal(expected, actual)
end
end

0 comments on commit 2a79a88

Please sign in to comment.