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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a6987cd0c0489041a425e9da09b74af6847e148
4
- data.tar.gz: 0eee9d6b1ed1eb887fea59a9f5f489a663d8bc8b
3
+ metadata.gz: d5182d04d94e419e33025caaa66a64d016d1db78
4
+ data.tar.gz: 131cf0a03478c80523fc94bca791dc4e1e0424a8
5
5
  SHA512:
6
- metadata.gz: be71a8215c97908a15d25a167753c9e66fd0d13a9f7663acdb3b26255fc26a5d0cfdc57f33923d35150d4ba3c5eda37aeb4fcc1c374a3f7f5dd0da81e3cc97e7
7
- data.tar.gz: e28a6858a6d61be4f5fddb87374173861097983826d470ffbfaad5e79b71dcb5194d9a6954231664db0ee9632931bd1b2c52edfacccb2528ebdcff088972f0fd
6
+ metadata.gz: 267d7551a141b3007950892e24d618a869a48af010c9d912cd62d940e21d439a0f3df2fa1f78c67c9a0a353f7a7e975da9fdcdc484058e5f4f6651e1076233d7
7
+ data.tar.gz: c399807b95bf22b474184677296a973c1909cc89a322e0b416b11797f4ec09a0d9321e3cec4b3e9fe3959fe297c287ff5e6be2640c86f8a514cc5d92ba1c7301
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0
4
+ - 2.1
5
+ - 2.2
6
+ gemfile:
7
+ - gemfiles/jekyll_3.1.gemfile
8
+ - gemfiles/jekyll_3.gemfile
9
+ - gemfiles/jekyll_2.gemfile
data/Appraisals ADDED
@@ -0,0 +1,11 @@
1
+ appraise "jekyll-3.1" do
2
+ gem "jekyll", "3.1.2"
3
+ end
4
+
5
+ appraise "jekyll-3" do
6
+ gem "jekyll", "3.0.3"
7
+ end
8
+
9
+ appraise "jekyll-2" do
10
+ gem "jekyll", "2.5.3"
11
+ end
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in ruboty.gemspec
4
3
  gemspec
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # jekyll-toc
2
2
 
3
+ [![Build Status](https://travis-ci.org/toshimaru/jekyll-toc.svg?branch=master)](https://travis-ci.org/toshimaru/jekyll-toc)
3
4
  [![Gem Version](https://badge.fury.io/rb/jekyll-toc.svg)](http://badge.fury.io/rb/jekyll-toc)
4
5
  [![Dependency Status](https://gemnasium.com/toshimaru/jekyll-toc.svg)](https://gemnasium.com/toshimaru/jekyll-toc)
5
6
  [![Code Climate](https://codeclimate.com/github/toshimaru/jekyll-toc/badges/gpa.svg)](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
  ![screenshot](https://cloud.githubusercontent.com/assets/803398/5723662/f0bc84c8-9b88-11e4-986c-90608ca88184.png)
71
100
 
72
- ## TODO
73
- * Test
74
- * Travis CI
75
- * Coverage & Coverall
76
- * Close toc with JavaScript
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
+
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "jekyll", "2.5.3"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "jekyll", "3.1.2"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "jekyll", "3.0.3"
6
+
7
+ gemspec :path => "../"
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 = "Jekyll plugin which generates a table of contents at the top of the content"
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
- # parse logic is from html-pipeline toc_filter
5
- # https://github.com/jch/html-pipeline/blob/v1.1.0/lib/html/pipeline/toc_filter.rb
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
- PUNCTUATION_REGEXP = RUBY_VERSION > "1.9" ? /[^\p{Word}\- ]/u : /[^\w\- ]/
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["toc"]
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 + doc.inner_html
87
+ Jekyll::TableOfContents::Parser.new(html).toc
33
88
  end
34
89
  end
35
90
  end
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module JekyllToc
2
- VERSION = "0.0.4"
2
+ VERSION = '0.1.0'
3
3
  end
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
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: 2015-01-18 00:00:00.000000000 Z
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: Jekyll plugin which generates a table of contents at the top of the content
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.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