Skip to content

Commit

Permalink
TOC configuration: configurable heading min_level and max_level (#39)
Browse files Browse the repository at this point in the history
* Fix duplicated method name

* Add toc_enabled? method

* Add kramdown heading test

* Create `toc` liqud  custom tag

* Check toc is enabled

* unregister_tag toc

* Add TODO

* Make toc headings dynamic

* Add max_level, min_level test
  • Loading branch information
toshimaru authored Nov 25, 2017
1 parent 1e363e1 commit c9e5625
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 17 deletions.
32 changes: 21 additions & 11 deletions lib/jekyll-toc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,41 @@
require 'table_of_contents/parser'

module Jekyll
class TocTag < Liquid::Tag
def render(context)
return unless context.registers[:page]['toc'] == true
content_html = context.registers[:page].content
::Jekyll::TableOfContents::Parser.new(content_html).build_toc
end
end

module TableOfContentsFilter
def toc_only(html)
return html unless page['toc']

::Jekyll::TableOfContents::Parser.new(html).build_toc
return html unless toc_enabled?
::Jekyll::TableOfContents::Parser.new(html, toc_config).build_toc
end

def inject_anchors(html)
return html unless page['toc']

::Jekyll::TableOfContents::Parser.new(html).inject_anchors_into_html
return html unless toc_enabled?
::Jekyll::TableOfContents::Parser.new(html, toc_config).inject_anchors_into_html
end

def toc(html)
return html unless page['toc']

::Jekyll::TableOfContents::Parser.new(html).toc
return html unless toc_enabled?
::Jekyll::TableOfContents::Parser.new(html, toc_config).toc
end

private

def page
@context.registers[:page]
def toc_enabled?
@context.registers[:page]['toc'] == true
end

def toc_config
@context.registers[:site].config["toc"]
end
end
end

Liquid::Template.register_filter(Jekyll::TableOfContentsFilter)
# Liquid::Template.register_tag('toc', Jekyll::TocTag) # will be enabled at v1.0
16 changes: 14 additions & 2 deletions lib/table_of_contents/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@ module TableOfContents
class Parser
PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u

def initialize(html)
DEFAULT_CONFIG = {
"min_level" => 1,
"max_level" => 6,
}

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

Expand Down Expand Up @@ -33,7 +40,8 @@ def parse_content
entries = []
headers = Hash.new(0)

@doc.css('h1, h2, h3, h4, h5, h6').each do |node|
# TODO: Use kramdown auto ids
@doc.css(toc_headings).each do |node|
text = node.text
id = text.downcase
id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation
Expand Down Expand Up @@ -104,6 +112,10 @@ def get_nest_entries(entries, min_h_num)
nest_entries << entry
end
end

def toc_headings
@toc_levels.map { |level| "h#{level}" }.join(",")
end
end
end
end
24 changes: 22 additions & 2 deletions test/test_kramdown_list.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
require 'test_helper'

class TestKramdownList < Minitest::Test
# NOTE: kramdown automatically injects `id` attribute
# TODO: test Japanese heading
def test_kramdown_heading
text = <<-MARKDOWN
# h1
## h2
MARKDOWN
expected = <<-HTML
<h1 id="h1">h1</h1>
<h2 id=\"h2\">h2</h2>
HTML

assert_equal(expected, Kramdown::Document.new(text).to_html)
end

def test_kramdown_list_1
text = <<-MARKDOWN
* level-1
Expand Down Expand Up @@ -72,12 +89,15 @@ def test_kramdown_list_3
* level-1
MARKDOWN
expected = <<-HTML
<pre><code> * level-4
* level-3 * level-2 * level-1
</code></pre>
HTML

assert_equal(expected, Kramdown::Document.new(text).to_html)
end

def test_kramdown_list_3
def test_kramdown_list_4
text = <<-MARKDOWN
* level-1
* level-4
Expand All @@ -101,7 +121,7 @@ def test_kramdown_list_3
assert_equal(expected, Kramdown::Document.new(text).to_html)
end

def test_kramdown_list_3
def test_kramdown_list_5
text = <<-MARKDOWN
* level-1
* level-3
Expand Down
16 changes: 14 additions & 2 deletions test/test_various_toc_html.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ def test_nested_toc
assert_equal(expected, doc.css('ul.section-nav').to_s)
end

def test_nested_toc_with_min_and_max
parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_1, { "min_level" => 2, "max_level" => 5 })
doc = Nokogiri::HTML(parser.toc)
expected = <<-HTML
<ul class="section-nav">
<li class="toc-entry toc-h3"><a href="#h3">h3</a></li>
</ul>
HTML

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

def test_complex_nested_toc
parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_2)
doc = Nokogiri::HTML(parser.toc)
Expand All @@ -76,7 +88,7 @@ def test_complex_nested_toc
assert_equal(expected, doc.css('ul.section-nav').to_s)
end

def test_decremental_headings
def test_decremental_headings1
parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_3)
doc = Nokogiri::HTML(parser.toc)
expected = <<-HTML
Expand All @@ -94,7 +106,7 @@ def test_decremental_headings
end


def test_decremental_headings
def test_decremental_headings2
parser = Jekyll::TableOfContents::Parser.new(TEST_HTML_4)
doc = Nokogiri::HTML(parser.toc)
expected = <<-HTML
Expand Down

0 comments on commit c9e5625

Please sign in to comment.