jekyll-toc 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +9 -0
- data/Appraisals +11 -0
- data/Gemfile +0 -1
- data/README.md +65 -16
- data/gemfiles/jekyll_2.gemfile +7 -0
- data/gemfiles/jekyll_3.1.gemfile +7 -0
- data/gemfiles/jekyll_3.gemfile +7 -0
- data/jekyll-toc.gemspec +4 -2
- data/lib/jekyll-toc.rb +79 -24
- data/lib/version.rb +1 -1
- data/test/test_helper.rb +16 -0
- data/test/test_inject_anchors_filter.rb +23 -0
- data/test/test_toc_filter.rb +23 -0
- data/test/test_toc_only_filter.rb +23 -0
- metadata +30 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5182d04d94e419e33025caaa66a64d016d1db78
|
4
|
+
data.tar.gz: 131cf0a03478c80523fc94bca791dc4e1e0424a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 267d7551a141b3007950892e24d618a869a48af010c9d912cd62d940e21d439a0f3df2fa1f78c67c9a0a353f7a7e975da9fdcdc484058e5f4f6651e1076233d7
|
7
|
+
data.tar.gz: c399807b95bf22b474184677296a973c1909cc89a322e0b416b11797f4ec09a0d9321e3cec4b3e9fe3959fe297c287ff5e6be2640c86f8a514cc5d92ba1c7301
|
data/.travis.yml
ADDED
data/Appraisals
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# jekyll-toc
|
2
2
|
|
3
|
+
[](https://travis-ci.org/toshimaru/jekyll-toc)
|
3
4
|
[](http://badge.fury.io/rb/jekyll-toc)
|
4
5
|
[](https://gemnasium.com/toshimaru/jekyll-toc)
|
5
6
|
[](https://codeclimate.com/github/toshimaru/jekyll-toc)
|
@@ -19,12 +20,6 @@ gems:
|
|
19
20
|
- jekyll-toc
|
20
21
|
```
|
21
22
|
|
22
|
-
Add `toc` filter to your site's `{{ content }}` (e.g. `_layouts/post.html`).
|
23
|
-
|
24
|
-
```
|
25
|
-
{{ content | toc }}
|
26
|
-
```
|
27
|
-
|
28
23
|
Set `toc: true` in your posts.
|
29
24
|
|
30
25
|
```yml
|
@@ -35,17 +30,51 @@ toc: true
|
|
35
30
|
---
|
36
31
|
```
|
37
32
|
|
33
|
+
There are three Liquid filters available now, which all should be applied
|
34
|
+
to some HTML content, e.g. the Liquid variable `content` available in
|
35
|
+
Jekyll's templates.
|
36
|
+
|
37
|
+
1. `toc_only`
|
38
|
+
Generates the TOC itself as described [below](#generated-table-of-contents-html).
|
39
|
+
Mostly useful in cases where the TOC should _not_ be placed immediately
|
40
|
+
above the content but at some other place of the page, i.e. an aside.
|
41
|
+
|
42
|
+
2. `inject_anchors`
|
43
|
+
Injects HTML anchors into the content without actually outputing the
|
44
|
+
TOC itself.
|
45
|
+
They are of the form:
|
46
|
+
|
47
|
+
```html
|
48
|
+
<a id="heading11" class="anchor" href="#heading1-1" aria-hidden="true">
|
49
|
+
<span class="octicon octicon-link"></span>
|
50
|
+
</a>
|
51
|
+
```
|
52
|
+
|
53
|
+
This is only useful when the TOC itself should be placed at some other
|
54
|
+
location with the `toc_only` filter.
|
55
|
+
|
56
|
+
3. `toc`
|
57
|
+
This is the concatenation of the two above, where the TOC is placed
|
58
|
+
directly above the content.
|
59
|
+
|
60
|
+
Add `toc` filter to your site's `{{ content }}` (e.g. `_layouts/post.html`).
|
61
|
+
|
62
|
+
```
|
63
|
+
{{ content | toc }}
|
64
|
+
```
|
65
|
+
|
66
|
+
|
38
67
|
## Generated Table of Contents HTML
|
39
68
|
|
40
69
|
jekyll-toc generates Unordered List. The final output is as follows.
|
41
70
|
|
42
71
|
```html
|
43
72
|
<ul class="section-nav">
|
44
|
-
<li><a href="#heading1">Heading.1</a></li>
|
45
|
-
<li><a href="#heading2-1">Heading.2-1</a></li>
|
46
|
-
<li><a href="#heading2-2">Heading.2-2</a></li>
|
47
|
-
<li><a href="#heading3">Heading.3</a></li>
|
48
|
-
<li><a href="#heading2-3">Heading.2-3</a></li>
|
73
|
+
<li class="toc-entry toc-h1"><a href="#heading1">Heading.1</a></li>
|
74
|
+
<li class="toc-entry toc-h2"><a href="#heading2-1">Heading.2-1</a></li>
|
75
|
+
<li class="toc-entry toc-h2"><a href="#heading2-2">Heading.2-2</a></li>
|
76
|
+
<li class="toc-entry toc-h3"><a href="#heading3">Heading.3</a></li>
|
77
|
+
<li class="toc-entry toc-h2"><a href="#heading2-3">Heading.2-3</a></li>
|
49
78
|
</ul>
|
50
79
|
```
|
51
80
|
|
@@ -69,8 +98,28 @@ The toc can be modified with CSS. The sample CSS is the following.
|
|
69
98
|
|
70
99
|

|
71
100
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
101
|
+
Each TOC `li` entry has two CSS classes for further styling.
|
102
|
+
The general `toc-entry` is applied to all `li` elements in the `ul.section-nav`.
|
103
|
+
Depending on the heading level each specific entry refers to, it has a second
|
104
|
+
CSS class `toc-XX`, where `XX` is the HTML heading tag name.
|
105
|
+
|
106
|
+
For example, the TOC entry linking to a heading `<h1>...</h1>` (a single
|
107
|
+
`#` in Markdown) will get the CSS class `toc-h1`.
|
108
|
+
|
109
|
+
That way, one can tune the depth of the TOC displayed on the site.
|
110
|
+
The following CSS will display only the first two heading levels and hides
|
111
|
+
all other links:
|
112
|
+
|
113
|
+
```css
|
114
|
+
.toc-entry.toc-h1,
|
115
|
+
.toc-entry.toc-h2
|
116
|
+
{}
|
117
|
+
.toc-entry.toc-h3,
|
118
|
+
.toc-entry.toc-h4,
|
119
|
+
.toc-entry.toc-h5,
|
120
|
+
.toc-entry.toc-h6
|
121
|
+
{
|
122
|
+
display: none;
|
123
|
+
}
|
124
|
+
```
|
125
|
+
|
data/jekyll-toc.gemspec
CHANGED
@@ -6,8 +6,8 @@ Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = 'jekyll-toc'
|
7
7
|
spec.version = JekyllToc::VERSION
|
8
8
|
spec.summary = "Jekyll Table of Contents plugin"
|
9
|
-
spec.description = "
|
10
|
-
spec.authors = ["Toshimaru"]
|
9
|
+
spec.description = "A liquid filter plugin for Jekyll which generates a table of contents."
|
10
|
+
spec.authors = ["Toshimaru", 'torbjoernk']
|
11
11
|
spec.email = 'me@toshimaru.net'
|
12
12
|
spec.files = `git ls-files -z`.split("\x0")
|
13
13
|
spec.homepage = 'https://github.com/toshimaru/jekyll-toc'
|
@@ -16,6 +16,8 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.require_paths = ["lib"]
|
17
17
|
|
18
18
|
spec.add_runtime_dependency "nokogiri", "~> 1.6"
|
19
|
+
|
20
|
+
spec.add_development_dependency "appraisal"
|
19
21
|
spec.add_development_dependency 'minitest', "~> 5.0"
|
20
22
|
spec.add_development_dependency "jekyll", "~> 2.0"
|
21
23
|
spec.add_development_dependency "rake"
|
data/lib/jekyll-toc.rb
CHANGED
@@ -1,35 +1,90 @@
|
|
1
1
|
require 'nokogiri'
|
2
2
|
|
3
3
|
module Jekyll
|
4
|
-
|
5
|
-
|
4
|
+
module TableOfContents
|
5
|
+
PUNCTUATION_REGEXP = RUBY_VERSION > '1.9' ? /[^\p{Word}\- ]/u : /[^\w\- ]/
|
6
|
+
|
7
|
+
class Parser
|
8
|
+
attr_reader :doc
|
9
|
+
|
10
|
+
def initialize(html)
|
11
|
+
@doc = Nokogiri::HTML::DocumentFragment.parse(html)
|
12
|
+
@entries = parse_content
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_toc
|
16
|
+
toc = %Q{<ul class="section-nav">\n}
|
17
|
+
|
18
|
+
@entries.each do |entry|
|
19
|
+
toc << %Q{<li class="toc-entry toc-#{entry[:node_name]}"><a href="##{entry[:id]}#{entry[:uniq]}">#{entry[:text]}</a></li>\n}
|
20
|
+
end
|
21
|
+
|
22
|
+
toc << '</ul>'
|
23
|
+
end
|
24
|
+
|
25
|
+
def inject_anchors_into_html
|
26
|
+
@entries.each do |entry|
|
27
|
+
entry[:content_node].add_previous_sibling(%Q{<a id="#{entry[:id]}#{entry[:uniq]}" class="anchor" href="##{entry[:id]}#{entry[:uniq]}" aria-hidden="true"><span class="octicon octicon-link"></span></a>})
|
28
|
+
end
|
29
|
+
|
30
|
+
@doc.inner_html
|
31
|
+
end
|
32
|
+
|
33
|
+
def toc
|
34
|
+
build_toc + inject_anchors_into_html
|
35
|
+
end
|
36
|
+
|
37
|
+
# parse logic is from html-pipeline toc_filter
|
38
|
+
# https://github.com/jch/html-pipeline/blob/v1.1.0/lib/html/pipeline/toc_filter.rb
|
39
|
+
private
|
40
|
+
def parse_content
|
41
|
+
entries = []
|
42
|
+
headers = Hash.new(0)
|
43
|
+
|
44
|
+
@doc.css('h1, h2, h3, h4, h5, h6').each do |node|
|
45
|
+
text = node.text
|
46
|
+
id = text.downcase
|
47
|
+
id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation
|
48
|
+
id.gsub!(' ', '-') # replace spaces with dash
|
49
|
+
|
50
|
+
uniq = (headers[id] > 0) ? "-#{headers[id]}" : ''
|
51
|
+
headers[id] += 1
|
52
|
+
if header_content = node.children.first
|
53
|
+
entries << {
|
54
|
+
id: id,
|
55
|
+
uniq: uniq,
|
56
|
+
text: text,
|
57
|
+
node_name: node.name,
|
58
|
+
content_node: header_content
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
entries
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
6
68
|
module TableOfContentsFilter
|
7
|
-
|
69
|
+
def toc_only(html)
|
70
|
+
page = @context.registers[:page]
|
71
|
+
return html unless page['toc']
|
72
|
+
|
73
|
+
Jekyll::TableOfContents::Parser.new(html).build_toc
|
74
|
+
end
|
75
|
+
|
76
|
+
def inject_anchors(html)
|
77
|
+
page = @context.registers[:page]
|
78
|
+
return html unless page['toc']
|
79
|
+
|
80
|
+
Jekyll::TableOfContents::Parser.new(html).inject_anchors_into_html
|
81
|
+
end
|
8
82
|
|
9
83
|
def toc(html)
|
10
84
|
page = @context.registers[:page]
|
11
|
-
return html unless page[
|
12
|
-
|
13
|
-
toc = ""
|
14
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(html)
|
15
|
-
headers = Hash.new(0)
|
16
|
-
|
17
|
-
doc.css('h1, h2, h3, h4, h5, h6').each do |node|
|
18
|
-
text = node.text
|
19
|
-
id = text.downcase
|
20
|
-
id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation
|
21
|
-
id.gsub!(' ', '-') # replace spaces with dash
|
22
|
-
|
23
|
-
uniq = (headers[id] > 0) ? "-#{headers[id]}" : ''
|
24
|
-
headers[id] += 1
|
25
|
-
if header_content = node.children.first
|
26
|
-
toc << %Q{<li><a href="##{id}#{uniq}">#{text}</a></li>\n}
|
27
|
-
header_content.add_previous_sibling(%Q{<a id="#{id}#{uniq}" class="anchor" href="##{id}#{uniq}" aria-hidden="true"><span class="octicon octicon-link"></span></a>})
|
28
|
-
end
|
29
|
-
end
|
30
|
-
toc = %Q{<ul class="section-nav">\n#{toc}</ul>} unless toc.empty?
|
85
|
+
return html unless page['toc']
|
31
86
|
|
32
|
-
toc
|
87
|
+
Jekyll::TableOfContents::Parser.new(html).toc
|
33
88
|
end
|
34
89
|
end
|
35
90
|
end
|
data/lib/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -1,2 +1,18 @@
|
|
1
1
|
require 'jekyll'
|
2
2
|
require 'minitest/autorun'
|
3
|
+
|
4
|
+
SIMPLE_HTML = <<EOL
|
5
|
+
<h1>Simple H1</h1>
|
6
|
+
<h2>Simple H2</h2>
|
7
|
+
<h3>Simple H3</h3>
|
8
|
+
<h4>Simple H4</h4>
|
9
|
+
<h5>Simple H5</h5>
|
10
|
+
<h6>Simple H6</h6>
|
11
|
+
EOL
|
12
|
+
|
13
|
+
module TestHelpers
|
14
|
+
def read_html_and_create_parser
|
15
|
+
@parser = Jekyll::TableOfContents::Parser.new(SIMPLE_HTML)
|
16
|
+
assert_match /Simple H1/, @parser.doc.inner_html
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require_relative '../lib/jekyll-toc'
|
3
|
+
|
4
|
+
|
5
|
+
class TestTOCOnlyFilter < Minitest::Test
|
6
|
+
include TestHelpers
|
7
|
+
|
8
|
+
def setup
|
9
|
+
read_html_and_create_parser
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_injects_anchors_into_content
|
13
|
+
html = @parser.inject_anchors_into_html
|
14
|
+
|
15
|
+
assert_match /<a id="simple\-h1" class="anchor" href="#simple\-h1" aria\-hidden="true"><span.*span><\/a>Simple H1/, html
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_does_not_inject_toc
|
19
|
+
html = @parser.inject_anchors_into_html
|
20
|
+
|
21
|
+
assert_nil /<ul class="section-nav">/ =~ html
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require_relative '../lib/jekyll-toc'
|
3
|
+
|
4
|
+
|
5
|
+
class TestTOCFilter < Minitest::Test
|
6
|
+
include TestHelpers
|
7
|
+
|
8
|
+
def setup
|
9
|
+
read_html_and_create_parser
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_injects_anchors
|
13
|
+
html = @parser.toc
|
14
|
+
|
15
|
+
assert_match /<a id="simple\-h1" class="anchor" href="#simple\-h1" aria\-hidden="true"><span.*span><\/a>Simple H1/, html
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_injects_toc_container
|
19
|
+
html = @parser.toc
|
20
|
+
|
21
|
+
assert_match /<ul class="section-nav">/, html
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require_relative '../lib/jekyll-toc'
|
3
|
+
|
4
|
+
|
5
|
+
class TestTOCOnlyFilter < Minitest::Test
|
6
|
+
include TestHelpers
|
7
|
+
|
8
|
+
def setup
|
9
|
+
read_html_and_create_parser
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_injects_toc_container
|
13
|
+
html = @parser.build_toc
|
14
|
+
|
15
|
+
assert_match /<ul class="section-nav">/, html
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_does_not_return_content
|
19
|
+
html = @parser.build_toc
|
20
|
+
|
21
|
+
assert_nil /<h1>Simple H1<\/h1>/ =~ html
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-toc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Toshimaru
|
8
|
+
- torbjoernk
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2016-03-23 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: nokogiri
|
@@ -24,6 +25,20 @@ dependencies:
|
|
24
25
|
- - "~>"
|
25
26
|
- !ruby/object:Gem::Version
|
26
27
|
version: '1.6'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: appraisal
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
27
42
|
- !ruby/object:Gem::Dependency
|
28
43
|
name: minitest
|
29
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,21 +81,29 @@ dependencies:
|
|
66
81
|
- - ">="
|
67
82
|
- !ruby/object:Gem::Version
|
68
83
|
version: '0'
|
69
|
-
description:
|
84
|
+
description: A liquid filter plugin for Jekyll which generates a table of contents.
|
70
85
|
email: me@toshimaru.net
|
71
86
|
executables: []
|
72
87
|
extensions: []
|
73
88
|
extra_rdoc_files: []
|
74
89
|
files:
|
75
90
|
- ".gitignore"
|
91
|
+
- ".travis.yml"
|
92
|
+
- Appraisals
|
76
93
|
- Gemfile
|
77
94
|
- LICENSE.md
|
78
95
|
- README.md
|
79
96
|
- Rakefile
|
97
|
+
- gemfiles/jekyll_2.gemfile
|
98
|
+
- gemfiles/jekyll_3.1.gemfile
|
99
|
+
- gemfiles/jekyll_3.gemfile
|
80
100
|
- jekyll-toc.gemspec
|
81
101
|
- lib/jekyll-toc.rb
|
82
102
|
- lib/version.rb
|
83
103
|
- test/test_helper.rb
|
104
|
+
- test/test_inject_anchors_filter.rb
|
105
|
+
- test/test_toc_filter.rb
|
106
|
+
- test/test_toc_only_filter.rb
|
84
107
|
homepage: https://github.com/toshimaru/jekyll-toc
|
85
108
|
licenses:
|
86
109
|
- MIT
|
@@ -101,9 +124,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
124
|
version: '0'
|
102
125
|
requirements: []
|
103
126
|
rubyforge_project:
|
104
|
-
rubygems_version: 2.4.
|
127
|
+
rubygems_version: 2.4.5
|
105
128
|
signing_key:
|
106
129
|
specification_version: 4
|
107
130
|
summary: Jekyll Table of Contents plugin
|
108
131
|
test_files:
|
109
132
|
- test/test_helper.rb
|
133
|
+
- test/test_inject_anchors_filter.rb
|
134
|
+
- test/test_toc_filter.rb
|
135
|
+
- test/test_toc_only_filter.rb
|