jekyll-toc-plus 0.20.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 +7 -0
- data/.rubocop.yml +44 -0
- data/Appraisals +9 -0
- data/CHANGELOG.md +1 -0
- data/Gemfile +14 -0
- data/LICENSE.md +22 -0
- data/README.md +486 -0
- data/Rakefile +10 -0
- data/gemfiles/jekyll_3.9.gemfile +17 -0
- data/gemfiles/jekyll_4.0.gemfile +17 -0
- data/gemfiles/jekyll_4.1.gemfile +17 -0
- data/gemfiles/jekyll_4.2.gemfile +17 -0
- data/gemfiles/jekyll_4.3.gemfile +17 -0
- data/lib/jekyll-toc-plus.rb +63 -0
- data/lib/table_of_contents/configuration.rb +52 -0
- data/lib/table_of_contents/helper.rb +25 -0
- data/lib/table_of_contents/parser.rb +156 -0
- data/lib/table_of_contents/version.rb +7 -0
- metadata +91 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7673dcb756b228f2940af9eb43c7e2e18bb42afd1aae9a508da44991d67c3428
|
|
4
|
+
data.tar.gz: f44af3e46bad9e0339246603ae38409ce2ef7301c1d5003bf5f86a5267fa2d0c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4e1552ac001c4036bf30b849a41eb0f64cb75c5de1202518cffaab3d6ce87e145ec90929047cbded341008572823128365e35c44d8a7c61a53650e30486f9f0a
|
|
7
|
+
data.tar.gz: ba0c7b2eb8ba036284909822ad1dada88227c0adc4c318d5ec8b782ed12bd5359759d03ea4b2be8bf16fa2aa502e1c4904b031993783ac5b263bbae7d54e92e6
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 2.7
|
|
3
|
+
NewCops: enable
|
|
4
|
+
Exclude:
|
|
5
|
+
- "*.gemspec"
|
|
6
|
+
- "gemfiles/*"
|
|
7
|
+
- "vendor/**/*"
|
|
8
|
+
- Rakefile
|
|
9
|
+
- Gemfile
|
|
10
|
+
require:
|
|
11
|
+
- rubocop-minitest
|
|
12
|
+
- rubocop-rake
|
|
13
|
+
- rubocop-performance
|
|
14
|
+
|
|
15
|
+
Metrics/MethodLength:
|
|
16
|
+
Enabled: false
|
|
17
|
+
Metrics/AbcSize:
|
|
18
|
+
Enabled: false
|
|
19
|
+
Metrics/ClassLength:
|
|
20
|
+
Enabled: false
|
|
21
|
+
|
|
22
|
+
Naming/FileName:
|
|
23
|
+
Enabled: false
|
|
24
|
+
|
|
25
|
+
Layout/LineLength:
|
|
26
|
+
Enabled: false
|
|
27
|
+
Layout/SpaceAroundMethodCallOperator:
|
|
28
|
+
Enabled: true
|
|
29
|
+
|
|
30
|
+
Lint/RaiseException:
|
|
31
|
+
Enabled: true
|
|
32
|
+
Lint/StructNewOverride:
|
|
33
|
+
Enabled: true
|
|
34
|
+
|
|
35
|
+
Style/WordArray:
|
|
36
|
+
Enabled: false
|
|
37
|
+
Style/HashEachMethods:
|
|
38
|
+
Enabled: true
|
|
39
|
+
Style/HashTransformKeys:
|
|
40
|
+
Enabled: true
|
|
41
|
+
Style/HashTransformValues:
|
|
42
|
+
Enabled: true
|
|
43
|
+
Style/ExponentialNotation:
|
|
44
|
+
Enabled: true
|
data/Appraisals
ADDED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Changelog is maintained under [Github Releases](https://github.com/jannewaren/jekyll-toc-plus/releases).
|
data/Gemfile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
gemspec
|
|
4
|
+
|
|
5
|
+
gem 'appraisal'
|
|
6
|
+
gem 'minitest-reporters'
|
|
7
|
+
gem 'minitest'
|
|
8
|
+
gem 'pry'
|
|
9
|
+
gem 'rake'
|
|
10
|
+
gem 'rubocop-minitest'
|
|
11
|
+
gem 'rubocop-performance'
|
|
12
|
+
gem 'rubocop-rake'
|
|
13
|
+
gem 'rubocop'
|
|
14
|
+
gem 'simplecov', '~> 0.22.0'
|
data/LICENSE.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020-2021 Toshimaru
|
|
4
|
+
Copyright (c) 2025 Janne Warén
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
# jekyll-toc-plus
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
[](https://badge.fury.io/rb/jekyll-toc-plus)
|
|
5
|
+
|
|
6
|
+
## About this fork
|
|
7
|
+
|
|
8
|
+
`jekyll-toc-plus` is a fork of [`toshimaru/jekyll-toc`](https://github.com/toshimaru/jekyll-toc).
|
|
9
|
+
All credit for the original plugin goes to its upstream authors — this fork simply adds a
|
|
10
|
+
few extra options (`div_list`, `flat_list`, `toc_only_direct_text`, and per-page
|
|
11
|
+
`toc_config` overrides) on top of their work, and is published to RubyGems so others can
|
|
12
|
+
`gem install` it directly.
|
|
13
|
+
|
|
14
|
+
It is otherwise a drop-in replacement. The maintainer makes **no promise to maintain this
|
|
15
|
+
as a full author**, but contributions and pull requests are welcome.
|
|
16
|
+
|
|
17
|
+
## Table of Contents
|
|
18
|
+
|
|
19
|
+
- [Installation](#installation)
|
|
20
|
+
- [Usage](#usage)
|
|
21
|
+
- [Basic Usage](#basic-usage)
|
|
22
|
+
- [Advanced Usage](#advanced-usage)
|
|
23
|
+
- [Generated HTML](#generated-html)
|
|
24
|
+
- [Customization](#customization)
|
|
25
|
+
- [Default Configuration](#default-configuration)
|
|
26
|
+
- [TOC levels](#toc-levels)
|
|
27
|
+
- [Enable TOC by default](#enable-toc-by-default)
|
|
28
|
+
- [Skip TOC](#skip-toc)
|
|
29
|
+
- [Skip TOC Sectionally](#skip-toc-sectionally)
|
|
30
|
+
- [TOC Only Direct Text](#toc-only-direct-text)
|
|
31
|
+
- [CSS Styling](#css-styling)
|
|
32
|
+
- [Custom CSS Class and ID](#custom-css-class-and-id)
|
|
33
|
+
- [Using Unordered/Ordered lists](#using-unorderedordered-lists)
|
|
34
|
+
- [Using divs as list elements](#using-divs-as-list-elements)
|
|
35
|
+
- [Using a flat list](#using-a-flat-list)
|
|
36
|
+
- [Alternative Tools](#alternative-tools)
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
Add jekyll-toc-plus plugin in your site's `Gemfile`, and run `bundle install`.
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
gem 'jekyll-toc-plus'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Add jekyll-toc-plus to the `plugins:` section in your site's `_config.yml`.
|
|
47
|
+
|
|
48
|
+
```yml
|
|
49
|
+
plugins:
|
|
50
|
+
- jekyll-toc-plus
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Set `toc: true` in posts for which you want the TOC to appear.
|
|
54
|
+
|
|
55
|
+
```yml
|
|
56
|
+
---
|
|
57
|
+
layout: post
|
|
58
|
+
title: "Welcome to Jekyll!"
|
|
59
|
+
toc: true
|
|
60
|
+
---
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
There are three Liquid filters, which can be applied to HTML content,
|
|
66
|
+
e.g. the Liquid variable `content` available in Jekyll's templates.
|
|
67
|
+
|
|
68
|
+
### Basic Usage
|
|
69
|
+
|
|
70
|
+
#### `toc` filter
|
|
71
|
+
|
|
72
|
+
Add the `toc` filter to your site's `{{ content }}` (e.g. `_layouts/post.html`).
|
|
73
|
+
|
|
74
|
+
```liquid
|
|
75
|
+
{{ content | toc }}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This filter places the TOC directly above the content.
|
|
79
|
+
|
|
80
|
+
### Advanced Usage
|
|
81
|
+
|
|
82
|
+
If you'd like separated TOC and content, you can use `{% toc %}` tag (or `toc_only` filter) and `inject_anchors` filter.
|
|
83
|
+
|
|
84
|
+
#### `{% toc %}` tag / `toc_only` filter
|
|
85
|
+
|
|
86
|
+
Generates the TOC itself as described [below](#generated-html).
|
|
87
|
+
Mostly useful in cases where the TOC should _not_ be placed immediately
|
|
88
|
+
above the content but at some other place of the page, i.e. an aside.
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<div>
|
|
92
|
+
<div id="table-of-contents">
|
|
93
|
+
{% toc %}
|
|
94
|
+
</div>
|
|
95
|
+
<div id="markdown-content">
|
|
96
|
+
{{ content }}
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
:warning: **`{% toc %}` Tag Limitation**
|
|
102
|
+
|
|
103
|
+
`{% toc %}` works only for [Jekyll Posts](https://jekyllrb.com/docs/step-by-step/08-blogging/) and [Jekyll Collections](https://jekyllrb.com/docs/collections/).
|
|
104
|
+
If you'd like to use `{% toc %}` except posts or collections, please use `toc_only` filter as described below.
|
|
105
|
+
|
|
106
|
+
```html
|
|
107
|
+
<div>
|
|
108
|
+
<div id="table-of-contents">
|
|
109
|
+
{{ content | toc_only }}
|
|
110
|
+
</div>
|
|
111
|
+
<div id="markdown-content">
|
|
112
|
+
{{ content | inject_anchors }}
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### `inject_anchors` filter
|
|
118
|
+
|
|
119
|
+
Injects HTML anchors into the content without actually outputting the TOC itself.
|
|
120
|
+
They are of the form:
|
|
121
|
+
|
|
122
|
+
```html
|
|
123
|
+
<a class="anchor" href="#heading1-1" aria-hidden="true">
|
|
124
|
+
<span class="octicon octicon-link"></span>
|
|
125
|
+
</a>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
This is only useful when the TOC itself should be placed at some other
|
|
129
|
+
location with the `toc_only` filter.
|
|
130
|
+
|
|
131
|
+
## Generated HTML
|
|
132
|
+
|
|
133
|
+
jekyll-toc generates an unordered list by default. The HTML output is as follows.
|
|
134
|
+
|
|
135
|
+
```html
|
|
136
|
+
<ul id="toc" class="section-nav">
|
|
137
|
+
<li class="toc-entry toc-h1"><a href="#heading1">Heading.1</a>
|
|
138
|
+
<ul>
|
|
139
|
+
<li class="toc-entry toc-h2"><a href="#heading1-1">Heading.1-1</a></li>
|
|
140
|
+
<li class="toc-entry toc-h2"><a href="#heading1-2">Heading.1-2</a></li>
|
|
141
|
+
</ul>
|
|
142
|
+
</li>
|
|
143
|
+
<li class="toc-entry toc-h1"><a href="#heading2">Heading.2</a>
|
|
144
|
+
<ul>
|
|
145
|
+
<li class="toc-entry toc-h2"><a href="#heading2-1">Heading.2-1</a>
|
|
146
|
+
<ul>
|
|
147
|
+
<li class="toc-entry toc-h3"><a href="#heading2-1-1">Heading.2-1-1</a></li>
|
|
148
|
+
<li class="toc-entry toc-h3"><a href="#heading2-1-2">Heading.2-1-2</a></li>
|
|
149
|
+
</ul>
|
|
150
|
+
</li>
|
|
151
|
+
<li class="toc-entry toc-h2"><a href="#heading2-2">Heading.2-2</a></li>
|
|
152
|
+
</ul>
|
|
153
|
+
</li>
|
|
154
|
+
</ul>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+

|
|
158
|
+
|
|
159
|
+
## Customization
|
|
160
|
+
|
|
161
|
+
jekyll-toc is customizable on `_config.yml`.
|
|
162
|
+
|
|
163
|
+
### Default Configuration
|
|
164
|
+
|
|
165
|
+
```yml
|
|
166
|
+
# _config.yml
|
|
167
|
+
toc:
|
|
168
|
+
min_level: 1
|
|
169
|
+
max_level: 6
|
|
170
|
+
ordered_list: false
|
|
171
|
+
no_toc_section_class: no_toc_section
|
|
172
|
+
list_id: toc
|
|
173
|
+
list_class: section-nav
|
|
174
|
+
sublist_class: ''
|
|
175
|
+
item_class: toc-entry
|
|
176
|
+
item_prefix: toc-
|
|
177
|
+
div_list: false
|
|
178
|
+
flat_list: false
|
|
179
|
+
toc_only_direct_text: false
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### TOC levels
|
|
183
|
+
|
|
184
|
+
```yml
|
|
185
|
+
# _config.yml
|
|
186
|
+
toc:
|
|
187
|
+
min_level: 2 # default: 1
|
|
188
|
+
max_level: 5 # default: 6
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The default heading range is from `<h1>` to `<h6>`.
|
|
192
|
+
|
|
193
|
+
#### Per-Page TOC Level Override
|
|
194
|
+
|
|
195
|
+
You can override the `min_level` and `max_level` settings for individual pages or posts by adding a `toc_config` key to the YAML front matter:
|
|
196
|
+
|
|
197
|
+
```yml
|
|
198
|
+
---
|
|
199
|
+
layout: post
|
|
200
|
+
title: "My Post"
|
|
201
|
+
toc: true
|
|
202
|
+
toc_config:
|
|
203
|
+
min_level: 2 # Override: Start from H2 for this page only
|
|
204
|
+
max_level: 4 # Override: Stop at H4 for this page only
|
|
205
|
+
---
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
This is useful when you want different TOC depths for different types of content.
|
|
209
|
+
|
|
210
|
+
### Enable TOC by default
|
|
211
|
+
|
|
212
|
+
You can enable TOC by default with [Front Matter Defaults](https://jekyllrb.com/docs/configuration/front-matter-defaults/):
|
|
213
|
+
|
|
214
|
+
```yml
|
|
215
|
+
# _config.yml
|
|
216
|
+
defaults:
|
|
217
|
+
- scope:
|
|
218
|
+
path: ""
|
|
219
|
+
values:
|
|
220
|
+
toc: true
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Skip TOC
|
|
224
|
+
|
|
225
|
+
The heading is ignored in the toc by adding `no_toc` class.
|
|
226
|
+
|
|
227
|
+
```html
|
|
228
|
+
<h1>h1</h1>
|
|
229
|
+
<h1 class="no_toc">This heading is ignored in the TOC</h1>
|
|
230
|
+
<h2>h2</h2>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Skip TOC Sectionally
|
|
234
|
+
|
|
235
|
+
The headings are ignored inside the element which has `no_toc_section` class.
|
|
236
|
+
|
|
237
|
+
```html
|
|
238
|
+
<h1>h1</h1>
|
|
239
|
+
<div class="no_toc_section">
|
|
240
|
+
<h2>This heading is ignored in the TOC</h2>
|
|
241
|
+
<h3>This heading is ignored in the TOC</h3>
|
|
242
|
+
</div>
|
|
243
|
+
<h4>h4</h4>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Which would result in only the `<h1>` & `<h4>` within the example being included in the TOC.
|
|
247
|
+
|
|
248
|
+
The class can be configured on `_config.yml`:
|
|
249
|
+
|
|
250
|
+
```yml
|
|
251
|
+
# _config.yml
|
|
252
|
+
toc:
|
|
253
|
+
no_toc_section_class: exclude # default: no_toc_section
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Configuring multiple classes are allowed:
|
|
257
|
+
|
|
258
|
+
```yml
|
|
259
|
+
# _config.yml
|
|
260
|
+
toc:
|
|
261
|
+
no_toc_section_class:
|
|
262
|
+
- no_toc_section
|
|
263
|
+
- exclude
|
|
264
|
+
- your_custom_skip_class_name
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### toc_only_direct_text
|
|
268
|
+
|
|
269
|
+
By default, the TOC includes all text content from headings, including text within nested HTML elements. The `toc_only_direct_text` option allows you to extract only the direct text nodes from headings, excluding all child elements.
|
|
270
|
+
|
|
271
|
+
This is particularly useful when using custom HTML components or tags within headings (like badges, icons, or status indicators) that you don't want to appear in the table of contents.
|
|
272
|
+
|
|
273
|
+
```yml
|
|
274
|
+
# _config.yml
|
|
275
|
+
toc:
|
|
276
|
+
toc_only_direct_text: true # default: false
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Example:**
|
|
280
|
+
|
|
281
|
+
Given this heading:
|
|
282
|
+
|
|
283
|
+
```html
|
|
284
|
+
<h2>formatName <tag>Required</tag></h2>
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
- With `toc_only_direct_text: false` (default): TOC shows "formatName Required"
|
|
288
|
+
- With `toc_only_direct_text: true`: TOC shows "formatName"
|
|
289
|
+
|
|
290
|
+
**Per-page override:**
|
|
291
|
+
|
|
292
|
+
You can override this setting for specific pages using front matter:
|
|
293
|
+
|
|
294
|
+
```yml
|
|
295
|
+
---
|
|
296
|
+
layout: post
|
|
297
|
+
title: "My Post"
|
|
298
|
+
toc: true
|
|
299
|
+
toc_config:
|
|
300
|
+
toc_only_direct_text: true
|
|
301
|
+
---
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### CSS Styling
|
|
305
|
+
|
|
306
|
+
The toc can be modified with CSS. The sample CSS is the following.
|
|
307
|
+
|
|
308
|
+
```css
|
|
309
|
+
.section-nav {
|
|
310
|
+
background-color: #fff;
|
|
311
|
+
margin: 5px 0;
|
|
312
|
+
padding: 10px 30px;
|
|
313
|
+
border: 1px solid #e8e8e8;
|
|
314
|
+
border-radius: 3px;
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+

|
|
319
|
+
|
|
320
|
+
Each TOC `li` entry has two CSS classes for further styling. The general `toc-entry` is applied to all `li` elements in the `ul.section-nav`.
|
|
321
|
+
|
|
322
|
+
Depending on the heading level each specific entry refers to, it has a second CSS class `toc-XX`, where `XX` is the HTML heading tag name.
|
|
323
|
+
For example, the TOC entry linking to a heading `<h1>...</h1>` (a single `#` in Markdown) will get the CSS class `toc-h1`.
|
|
324
|
+
|
|
325
|
+
### Custom CSS Class and ID
|
|
326
|
+
|
|
327
|
+
You can apply custom CSS classes to the generated `<ul>` and `<li>` tags.
|
|
328
|
+
|
|
329
|
+
```yml
|
|
330
|
+
# _config.yml
|
|
331
|
+
toc:
|
|
332
|
+
list_id: my-toc-id # Default: "toc"
|
|
333
|
+
list_class: my-list-class # Default: "section-nav"
|
|
334
|
+
sublist_class: my-sublist-class # Default: no class for sublists
|
|
335
|
+
item_class: my-item-class # Default: "toc-entry"
|
|
336
|
+
item_prefix: item- # Default: "toc-":
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Using Unordered/Ordered lists
|
|
340
|
+
|
|
341
|
+
By default the table of contents will be generated as an unordered list via `<ul></ul>` tags. This can be configured to use ordered lists instead `<ol></ol>`.
|
|
342
|
+
This can be configured in `_config.yml`:
|
|
343
|
+
|
|
344
|
+
```yml
|
|
345
|
+
# _config.yml
|
|
346
|
+
toc:
|
|
347
|
+
ordered_list: true # default is false
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
In order to change the list type, use the [list-style-type](https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type) css property.
|
|
351
|
+
Add a class to the `sublist_class` configuration to append it to the `ol` tags so that you can add the `list-style-type` property.
|
|
352
|
+
|
|
353
|
+
Example
|
|
354
|
+
|
|
355
|
+
```yml
|
|
356
|
+
# _config.yml
|
|
357
|
+
toc:
|
|
358
|
+
ordered_list: true
|
|
359
|
+
list_class: my-list-class
|
|
360
|
+
sublist_class: my-sublist-class
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
```css
|
|
364
|
+
.my-list-class {
|
|
365
|
+
list-style-type: upper-alpha;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.my-sublist-class {
|
|
369
|
+
list-style-type: lower-alpha;
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
This will produce:
|
|
374
|
+
|
|
375
|
+

|
|
376
|
+
|
|
377
|
+
### Using divs as list elements
|
|
378
|
+
|
|
379
|
+
By default, the table of contents is generated using `<ul>`, `<ol>`, and `<li>` tags. If you prefer to use `<div>` elements instead (for custom styling or accessibility reasons), you can enable this by setting the `div_list` option in your `_config.yml`:
|
|
380
|
+
|
|
381
|
+
```yml
|
|
382
|
+
# _config.yml
|
|
383
|
+
toc:
|
|
384
|
+
div_list: true # default is false
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
When `div_list` is set to `true`, the TOC will be rendered using `<div>` elements for both the list container and each entry, instead of `<ul>`, `<ol>`, and `<li>`. You can still use the `list_class`, `sublist_class`, and `item_class` options to add custom CSS classes for styling:
|
|
388
|
+
|
|
389
|
+
```yml
|
|
390
|
+
# _config.yml
|
|
391
|
+
toc:
|
|
392
|
+
div_list: true
|
|
393
|
+
list_class: my-list-class
|
|
394
|
+
sublist_class: my-sublist-class
|
|
395
|
+
item_class: my-item-class
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Example CSS for styling the TOC with `<div>` elements:
|
|
399
|
+
|
|
400
|
+
```css
|
|
401
|
+
.my-list-class {
|
|
402
|
+
/* Styles for the TOC container */
|
|
403
|
+
margin: 10px 0;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.my-item-class {
|
|
407
|
+
/* Styles for each TOC entry */
|
|
408
|
+
padding: 4px 0;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.my-sublist-class {
|
|
412
|
+
/* Styles for nested TOC containers */
|
|
413
|
+
margin-left: 20px;
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
This will produce a TOC structure like:
|
|
418
|
+
|
|
419
|
+
```html
|
|
420
|
+
<div id="toc" class="my-list-class">
|
|
421
|
+
<div class="my-item-class toc-h1"><a href="#heading1">Heading.1</a>
|
|
422
|
+
<div class="my-sublist-class">
|
|
423
|
+
<div class="my-item-class toc-h2"><a href="#heading1-1">Heading.1-1</a></div>
|
|
424
|
+
<div class="my-item-class toc-h2"><a href="#heading1-2">Heading.1-2</a></div>
|
|
425
|
+
</div>
|
|
426
|
+
</div>
|
|
427
|
+
<div class="my-item-class toc-h1"><a href="#heading2">Heading.2</a></div>
|
|
428
|
+
</div>
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Use this option if you want more flexibility in styling or need to avoid list semantics for accessibility or design reasons.
|
|
432
|
+
|
|
433
|
+
### Using a flat list
|
|
434
|
+
|
|
435
|
+
By default, the table of contents is generated as a nested structure that reflects the hierarchy of headings in your content. If you prefer a flat list with no nesting (where all TOC entries appear at the same level regardless of their heading level), you can enable this by setting the `flat_list` option in your `_config.yml`:
|
|
436
|
+
|
|
437
|
+
```yml
|
|
438
|
+
# _config.yml
|
|
439
|
+
toc:
|
|
440
|
+
flat_list: true # default is false
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
When `flat_list` is set to `true`, all TOC entries will be rendered at the same level without any nesting, while still retaining the CSS classes that indicate their heading level. This is useful when you want to style headings differently based on their level but prefer a simplified, non-nested list structure.
|
|
444
|
+
|
|
445
|
+
The flat list option works with both standard lists (`<ul>`, `<ol>`) and div-based lists (when `div_list` is set to `true`).
|
|
446
|
+
|
|
447
|
+
Example with standard lists:
|
|
448
|
+
|
|
449
|
+
```html
|
|
450
|
+
<ul id="toc" class="section-nav">
|
|
451
|
+
<li class="toc-entry toc-h1"><a href="#heading1">Heading.1</a></li>
|
|
452
|
+
<li class="toc-entry toc-h2"><a href="#heading1-1">Heading.1-1</a></li>
|
|
453
|
+
<li class="toc-entry toc-h2"><a href="#heading1-2">Heading.1-2</a></li>
|
|
454
|
+
<li class="toc-entry toc-h1"><a href="#heading2">Heading.2</a></li>
|
|
455
|
+
<li class="toc-entry toc-h2"><a href="#heading2-1">Heading.2-1</a></li>
|
|
456
|
+
<li class="toc-entry toc-h3"><a href="#heading2-1-1">Heading.2-1-1</a></li>
|
|
457
|
+
</ul>
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Example with div-based lists:
|
|
461
|
+
|
|
462
|
+
```html
|
|
463
|
+
<div id="toc" class="section-nav">
|
|
464
|
+
<div class="toc-entry toc-h1"><a href="#heading1">Heading.1</a></div>
|
|
465
|
+
<div class="toc-entry toc-h2"><a href="#heading1-1">Heading.1-1</a></div>
|
|
466
|
+
<div class="toc-entry toc-h2"><a href="#heading1-2">Heading.1-2</a></div>
|
|
467
|
+
<div class="toc-entry toc-h1"><a href="#heading2">Heading.2</a></div>
|
|
468
|
+
<div class="toc-entry toc-h2"><a href="#heading2-1">Heading.2-1</a></div>
|
|
469
|
+
<div class="toc-entry toc-h3"><a href="#heading2-1-1">Heading.2-1-1</a></div>
|
|
470
|
+
</div>
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Use this option when you want a simplified TOC structure but still want to style entries differently based on their heading level using CSS. For example:
|
|
474
|
+
|
|
475
|
+
```css
|
|
476
|
+
.toc-h1 { font-weight: bold; font-size: 1.2em; }
|
|
477
|
+
.toc-h2 { font-weight: normal; font-size: 1.1em; }
|
|
478
|
+
.toc-h3 { font-style: italic; font-size: 1em; }
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
## Alternative Tools
|
|
482
|
+
|
|
483
|
+
- Adding anchor to headings
|
|
484
|
+
- [AnchorJS](https://www.bryanbraun.com/anchorjs/)
|
|
485
|
+
- Generating TOC for kramdown content
|
|
486
|
+
- [Automatic “Table of Contents” Generation](https://kramdown.gettalong.org/converter/html.html#toc) (See also. [Create Table of Contents in kramdown](https://blog.toshima.ru/2020/05/22/kramdown-toc))
|
data/Rakefile
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
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-minitest"
|
|
11
|
+
gem "rubocop-performance"
|
|
12
|
+
gem "rubocop-rake"
|
|
13
|
+
gem "rubocop"
|
|
14
|
+
gem "simplecov", "~> 0.22.0"
|
|
15
|
+
gem "jekyll", "3.9"
|
|
16
|
+
|
|
17
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,17 @@
|
|
|
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-minitest"
|
|
11
|
+
gem "rubocop-performance"
|
|
12
|
+
gem "rubocop-rake"
|
|
13
|
+
gem "rubocop"
|
|
14
|
+
gem "simplecov", "~> 0.22.0"
|
|
15
|
+
gem "jekyll", "4.0"
|
|
16
|
+
|
|
17
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,17 @@
|
|
|
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-minitest"
|
|
11
|
+
gem "rubocop-performance"
|
|
12
|
+
gem "rubocop-rake"
|
|
13
|
+
gem "rubocop"
|
|
14
|
+
gem "simplecov", "~> 0.22.0"
|
|
15
|
+
gem "jekyll", "4.1"
|
|
16
|
+
|
|
17
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,17 @@
|
|
|
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-minitest"
|
|
11
|
+
gem "rubocop-performance"
|
|
12
|
+
gem "rubocop-rake"
|
|
13
|
+
gem "rubocop"
|
|
14
|
+
gem "simplecov", "~> 0.22.0"
|
|
15
|
+
gem "jekyll", "4.2"
|
|
16
|
+
|
|
17
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,17 @@
|
|
|
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-minitest"
|
|
11
|
+
gem "rubocop-performance"
|
|
12
|
+
gem "rubocop-rake"
|
|
13
|
+
gem "rubocop"
|
|
14
|
+
gem "simplecov", "~> 0.22.0"
|
|
15
|
+
gem "jekyll", "4.3"
|
|
16
|
+
|
|
17
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'nokogiri'
|
|
4
|
+
require 'table_of_contents/configuration'
|
|
5
|
+
require 'table_of_contents/parser'
|
|
6
|
+
|
|
7
|
+
module Jekyll
|
|
8
|
+
# toc tag for Jekyll
|
|
9
|
+
class TocTag < Liquid::Tag
|
|
10
|
+
def render(context)
|
|
11
|
+
return '' unless context.registers[:page]['toc']
|
|
12
|
+
|
|
13
|
+
content_html = context.registers[:page]['content']
|
|
14
|
+
toc_config = merge_toc_config(context)
|
|
15
|
+
TableOfContents::Parser.new(content_html, toc_config).build_toc
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def merge_toc_config(context)
|
|
21
|
+
site_config = context.registers[:site].config['toc'] || {}
|
|
22
|
+
page_config = context.registers[:page]['toc_config'] || {}
|
|
23
|
+
site_config.merge(page_config)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Jekyll Table of Contents filter plugin
|
|
28
|
+
module TableOfContentsFilter
|
|
29
|
+
# Deprecated method. Removed in v1.0.
|
|
30
|
+
def toc_only(html)
|
|
31
|
+
return '' unless toc_enabled?
|
|
32
|
+
|
|
33
|
+
TableOfContents::Parser.new(html, toc_config).build_toc
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def inject_anchors(html)
|
|
37
|
+
return html unless toc_enabled?
|
|
38
|
+
|
|
39
|
+
TableOfContents::Parser.new(html, toc_config).inject_anchors_into_html
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def toc(html)
|
|
43
|
+
return html unless toc_enabled?
|
|
44
|
+
|
|
45
|
+
TableOfContents::Parser.new(html, toc_config).toc
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def toc_enabled?
|
|
51
|
+
@context.registers[:page]['toc'] == true
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def toc_config
|
|
55
|
+
site_config = @context.registers[:site].config['toc'] || {}
|
|
56
|
+
page_config = @context.registers[:page]['toc_config'] || {}
|
|
57
|
+
site_config.merge(page_config)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
Liquid::Template.register_filter(Jekyll::TableOfContentsFilter)
|
|
63
|
+
Liquid::Template.register_tag('toc', Jekyll::TocTag) # will be enabled at v1.0
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module TableOfContents
|
|
5
|
+
# jekyll-toc configuration class
|
|
6
|
+
class Configuration
|
|
7
|
+
attr_reader :toc_levels, :no_toc_class, :ordered_list, :no_toc_section_class,
|
|
8
|
+
:list_id, :list_class, :sublist_class, :item_class, :item_prefix, :div_list, :flat_list,
|
|
9
|
+
:toc_only_direct_text
|
|
10
|
+
|
|
11
|
+
DEFAULT_CONFIG = {
|
|
12
|
+
'min_level' => 1,
|
|
13
|
+
'max_level' => 6,
|
|
14
|
+
'ordered_list' => false,
|
|
15
|
+
'no_toc_section_class' => 'no_toc_section',
|
|
16
|
+
'list_id' => 'toc',
|
|
17
|
+
'list_class' => 'section-nav',
|
|
18
|
+
'sublist_class' => '',
|
|
19
|
+
'item_class' => 'toc-entry',
|
|
20
|
+
'item_prefix' => 'toc-',
|
|
21
|
+
'div_list' => false,
|
|
22
|
+
'flat_list' => false,
|
|
23
|
+
'toc_only_direct_text' => false
|
|
24
|
+
}.freeze
|
|
25
|
+
|
|
26
|
+
def initialize(options)
|
|
27
|
+
options = generate_option_hash(options)
|
|
28
|
+
|
|
29
|
+
@toc_levels = options['min_level']..options['max_level']
|
|
30
|
+
@ordered_list = options['ordered_list']
|
|
31
|
+
@no_toc_class = 'no_toc'
|
|
32
|
+
@no_toc_section_class = options['no_toc_section_class']
|
|
33
|
+
@list_id = options['list_id']
|
|
34
|
+
@list_class = options['list_class']
|
|
35
|
+
@sublist_class = options['sublist_class']
|
|
36
|
+
@item_class = options['item_class']
|
|
37
|
+
@item_prefix = options['item_prefix']
|
|
38
|
+
@div_list = options['div_list']
|
|
39
|
+
@flat_list = options['flat_list']
|
|
40
|
+
@toc_only_direct_text = options['toc_only_direct_text']
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def generate_option_hash(options)
|
|
46
|
+
DEFAULT_CONFIG.merge(options)
|
|
47
|
+
rescue TypeError
|
|
48
|
+
DEFAULT_CONFIG
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
|
|
16
|
+
def extract_text(node, only_direct_text: false)
|
|
17
|
+
if only_direct_text
|
|
18
|
+
node.children.select(&:text?).map { |child| child.text.strip }.reject(&:empty?).join(' ')
|
|
19
|
+
else
|
|
20
|
+
node.text.strip
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'table_of_contents/helper'
|
|
4
|
+
|
|
5
|
+
module Jekyll
|
|
6
|
+
module TableOfContents
|
|
7
|
+
# Parse html contents and generate table of contents
|
|
8
|
+
class Parser
|
|
9
|
+
include ::Jekyll::TableOfContents::Helper
|
|
10
|
+
|
|
11
|
+
def initialize(html, options = {})
|
|
12
|
+
@doc = Nokogiri::HTML::DocumentFragment.parse(html)
|
|
13
|
+
@configuration = Configuration.new(options)
|
|
14
|
+
@entries = parse_content
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def toc
|
|
18
|
+
build_toc + inject_anchors_into_html
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def build_toc
|
|
22
|
+
%(<#{list_tag} id="#{@configuration.list_id}" class="#{@configuration.list_class}">\n#{build_toc_list(@entries)}</#{list_tag}>)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def inject_anchors_into_html
|
|
26
|
+
@entries.each do |entry|
|
|
27
|
+
# NOTE: `entry[:id]` is automatically URL encoded by Nokogiri
|
|
28
|
+
entry[:header_content].add_previous_sibling(
|
|
29
|
+
%(<a class="anchor" href="##{entry[:id]}" aria-hidden="true"><span class="octicon octicon-link"></span></a>)
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
@doc.inner_html
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
# parse logic is from html-pipeline toc_filter
|
|
39
|
+
# https://github.com/jch/html-pipeline/blob/v1.1.0/lib/html/pipeline/toc_filter.rb
|
|
40
|
+
def parse_content
|
|
41
|
+
headers = Hash.new(0)
|
|
42
|
+
|
|
43
|
+
(@doc.css(toc_headings) - @doc.css(toc_headings_in_no_toc_section))
|
|
44
|
+
.reject { |n| n.classes.include?(@configuration.no_toc_class) }
|
|
45
|
+
.inject([]) do |entries, node|
|
|
46
|
+
text = extract_text(node, only_direct_text: @configuration.toc_only_direct_text)
|
|
47
|
+
id = node.attribute('id') || generate_toc_id(text)
|
|
48
|
+
|
|
49
|
+
suffix_num = headers[id]
|
|
50
|
+
headers[id] += 1
|
|
51
|
+
|
|
52
|
+
entries << {
|
|
53
|
+
id: suffix_num.zero? ? id : "#{id}-#{suffix_num}",
|
|
54
|
+
text: CGI.escapeHTML(text),
|
|
55
|
+
node_name: node.name,
|
|
56
|
+
header_content: node.children.first,
|
|
57
|
+
h_num: node.name.delete('h').to_i
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Returns the list items for entries
|
|
63
|
+
def build_toc_list(entries)
|
|
64
|
+
if @configuration.flat_list
|
|
65
|
+
build_flat_toc_list(entries)
|
|
66
|
+
else
|
|
67
|
+
build_nested_toc_list(entries)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Returns the list items for entries in a flat structure
|
|
72
|
+
def build_flat_toc_list(entries)
|
|
73
|
+
toc_list = +''
|
|
74
|
+
|
|
75
|
+
entries.each do |entry|
|
|
76
|
+
toc_list << %(<#{list_parent_tag} class="#{@configuration.item_class} #{@configuration.item_prefix}#{entry[:node_name]}"><a href="##{entry[:id]}">#{entry[:text]}</a></#{list_parent_tag}>\n)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
toc_list
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Returns the list items for entries in a nested structure
|
|
83
|
+
def build_nested_toc_list(entries)
|
|
84
|
+
i = 0
|
|
85
|
+
toc_list = +''
|
|
86
|
+
min_h_num = entries.map { |e| e[:h_num] }.min
|
|
87
|
+
|
|
88
|
+
while i < entries.count
|
|
89
|
+
entry = entries[i]
|
|
90
|
+
if entry[:h_num] == min_h_num
|
|
91
|
+
# If the current entry should not be indented in the list, add the entry to the list
|
|
92
|
+
# If the next entry should be indented in the list, generate a sublist
|
|
93
|
+
toc_list << %(<#{list_parent_tag} class="#{@configuration.item_class} #{@configuration.item_prefix}#{entry[:node_name]}"><a href="##{entry[:id]}">#{entry[:text]}</a>)
|
|
94
|
+
next_i = i + 1
|
|
95
|
+
if next_i < entries.count && entries[next_i][:h_num] > min_h_num
|
|
96
|
+
nest_entries = get_nest_entries(entries[next_i, entries.count], min_h_num)
|
|
97
|
+
toc_list << %(\n<#{list_tag}#{ul_attributes}>\n#{build_nested_toc_list(nest_entries)}</#{list_tag}>\n)
|
|
98
|
+
i += nest_entries.count
|
|
99
|
+
end
|
|
100
|
+
toc_list << %(</#{list_parent_tag}>\n)
|
|
101
|
+
elsif entry[:h_num] > min_h_num
|
|
102
|
+
nest_entries = get_nest_entries(entries[i, entries.count], min_h_num)
|
|
103
|
+
toc_list << build_nested_toc_list(nest_entries)
|
|
104
|
+
i += nest_entries.count - 1
|
|
105
|
+
end
|
|
106
|
+
i += 1
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
toc_list
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Returns the entries in a nested list
|
|
113
|
+
# The nested list starts at the first entry in entries (inclusive)
|
|
114
|
+
# The nested list ends at the first entry in entries with depth min_h_num or greater (exclusive)
|
|
115
|
+
def get_nest_entries(entries, min_h_num)
|
|
116
|
+
entries.inject([]) do |nest_entries, entry|
|
|
117
|
+
break nest_entries if entry[:h_num] == min_h_num
|
|
118
|
+
|
|
119
|
+
nest_entries << entry
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def toc_headings
|
|
124
|
+
@configuration.toc_levels.map { |level| "h#{level}" }.join(',')
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def toc_headings_in_no_toc_section
|
|
128
|
+
if @configuration.no_toc_section_class.is_a?(Array)
|
|
129
|
+
@configuration.no_toc_section_class.map { |cls| toc_headings_within(cls) }.join(',')
|
|
130
|
+
else
|
|
131
|
+
toc_headings_within(@configuration.no_toc_section_class)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def toc_headings_within(class_name)
|
|
136
|
+
@configuration.toc_levels.map { |level| ".#{class_name} h#{level}" }.join(',')
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def ul_attributes
|
|
140
|
+
@ul_attributes ||= @configuration.sublist_class.empty? ? '' : %( class="#{@configuration.sublist_class}")
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def list_parent_tag
|
|
144
|
+
@list_parent_tag ||= @configuration.div_list ? 'div' : 'li'
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def list_tag
|
|
148
|
+
@list_tag ||= if @configuration.div_list
|
|
149
|
+
'div'
|
|
150
|
+
else
|
|
151
|
+
(@configuration.ordered_list ? 'ol' : 'ul')
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: jekyll-toc-plus
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.20.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- toshimaru
|
|
8
|
+
- torbjoernk
|
|
9
|
+
- Janne Warén
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: jekyll
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
requirements:
|
|
18
|
+
- - ">="
|
|
19
|
+
- !ruby/object:Gem::Version
|
|
20
|
+
version: '3.9'
|
|
21
|
+
type: :runtime
|
|
22
|
+
prerelease: false
|
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
24
|
+
requirements:
|
|
25
|
+
- - ">="
|
|
26
|
+
- !ruby/object:Gem::Version
|
|
27
|
+
version: '3.9'
|
|
28
|
+
- !ruby/object:Gem::Dependency
|
|
29
|
+
name: nokogiri
|
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
|
31
|
+
requirements:
|
|
32
|
+
- - "~>"
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: '1.12'
|
|
35
|
+
type: :runtime
|
|
36
|
+
prerelease: false
|
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - "~>"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '1.12'
|
|
42
|
+
description: Jekyll (Ruby static website generator) plugin which generates a Table
|
|
43
|
+
of Contents for the page.
|
|
44
|
+
email: janne.waren@gmail.com
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- ".rubocop.yml"
|
|
50
|
+
- Appraisals
|
|
51
|
+
- CHANGELOG.md
|
|
52
|
+
- Gemfile
|
|
53
|
+
- LICENSE.md
|
|
54
|
+
- README.md
|
|
55
|
+
- Rakefile
|
|
56
|
+
- gemfiles/jekyll_3.9.gemfile
|
|
57
|
+
- gemfiles/jekyll_4.0.gemfile
|
|
58
|
+
- gemfiles/jekyll_4.1.gemfile
|
|
59
|
+
- gemfiles/jekyll_4.2.gemfile
|
|
60
|
+
- gemfiles/jekyll_4.3.gemfile
|
|
61
|
+
- lib/jekyll-toc-plus.rb
|
|
62
|
+
- lib/table_of_contents/configuration.rb
|
|
63
|
+
- lib/table_of_contents/helper.rb
|
|
64
|
+
- lib/table_of_contents/parser.rb
|
|
65
|
+
- lib/table_of_contents/version.rb
|
|
66
|
+
homepage: https://github.com/jannewaren/jekyll-toc-plus
|
|
67
|
+
licenses:
|
|
68
|
+
- MIT
|
|
69
|
+
metadata:
|
|
70
|
+
homepage_uri: https://github.com/jannewaren/jekyll-toc-plus
|
|
71
|
+
source_code_uri: https://github.com/jannewaren/jekyll-toc-plus
|
|
72
|
+
changelog_uri: https://github.com/jannewaren/jekyll-toc-plus/releases
|
|
73
|
+
rubygems_mfa_required: 'true'
|
|
74
|
+
rdoc_options: []
|
|
75
|
+
require_paths:
|
|
76
|
+
- lib
|
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '2.7'
|
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
84
|
+
- - ">="
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: '0'
|
|
87
|
+
requirements: []
|
|
88
|
+
rubygems_version: 4.0.10
|
|
89
|
+
specification_version: 4
|
|
90
|
+
summary: Jekyll Table of Contents plugin
|
|
91
|
+
test_files: []
|