pax_global_header 0000666 0000000 0000000 00000000064 14050066561 0014515 g ustar 00root root 0000000 0000000 52 comment=22b07a30847359930d16c4d007c2e2b73bb22d9e
jekyll-toc-0.17.1/ 0000775 0000000 0000000 00000000000 14050066561 0013660 5 ustar 00root root 0000000 0000000 jekyll-toc-0.17.1/.github/ 0000775 0000000 0000000 00000000000 14050066561 0015220 5 ustar 00root root 0000000 0000000 jekyll-toc-0.17.1/.github/dependabot.yml 0000664 0000000 0000000 00000001126 14050066561 0020050 0 ustar 00root root 0000000 0000000 # To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "bundler"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- toshimaru
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- toshimaru
jekyll-toc-0.17.1/.github/workflows/ 0000775 0000000 0000000 00000000000 14050066561 0017255 5 ustar 00root root 0000000 0000000 jekyll-toc-0.17.1/.github/workflows/ci.yml 0000664 0000000 0000000 00000001272 14050066561 0020375 0 ustar 00root root 0000000 0000000 name: CI
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
ruby: [2.5, 2.6, 2.7, 3.0]
gemfile:
- gemfiles/jekyll_3.9.gemfile
- gemfiles/jekyll_4.0.gemfile
- gemfiles/jekyll_4.1.gemfile
- gemfiles/jekyll_4.2.gemfile
env:
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Ruby ${{ matrix.ruby }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
- name: bundle install
run: |
gem install bundler
bundle install --jobs 4 --retry 3
- name: Run Test
run: bundle exec rake
jekyll-toc-0.17.1/.github/workflows/coverage.yml 0000664 0000000 0000000 00000001156 14050066561 0021576 0 ustar 00root root 0000000 0000000 name: Coverage
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
ruby: [3.0]
runs-on: ubuntu-latest
name: coverage
steps:
- uses: actions/checkout@v2
- name: Set up Ruby ${{ matrix.ruby }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
- name: bundle install
run: bundle install --jobs 4 --retry 3
- uses: paambaati/codeclimate-action@v2.7.5
env:
CC_TEST_REPORTER_ID: 6b81e393ea6ad38560386f650ea2fb0e57a7beb5e20f8c8364fabee30d5bff07
with:
coverageCommand: bundle exec rake
jekyll-toc-0.17.1/.github/workflows/rubocop.yml 0000664 0000000 0000000 00000000716 14050066561 0021455 0 ustar 00root root 0000000 0000000 name: RuboCop
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
ruby: [3.0]
runs-on: ubuntu-latest
name: rubocop
steps:
- uses: actions/checkout@v2
- name: Set up Ruby ${{ matrix.ruby }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
- name: bundle install
run: bundle install --jobs 4 --retry 3
- name: Run RuboCop
run: bundle exec rubocop
jekyll-toc-0.17.1/.gitignore 0000664 0000000 0000000 00000000067 14050066561 0015653 0 ustar 00root root 0000000 0000000 *.gem
/Gemfile.lock
/.bundle/
/coverage
*.gemfile.lock
jekyll-toc-0.17.1/.rubocop.yml 0000664 0000000 0000000 00000001320 14050066561 0016126 0 ustar 00root root 0000000 0000000 AllCops:
TargetRubyVersion: 2.5
NewCops: enable
Exclude:
- "*.gemspec"
- "gemfiles/*"
- "vendor/**/*"
- Rakefile
- Gemfile
require:
- rubocop-performance
- rubocop-minitest
Metrics/MethodLength:
Enabled: false
Metrics/AbcSize:
Enabled: false
Metrics/ClassLength:
Enabled: false
Naming/FileName:
Enabled: false
Layout/LineLength:
Enabled: false
Layout/SpaceAroundMethodCallOperator:
Enabled: true
Lint/RaiseException:
Enabled: true
Lint/StructNewOverride:
Enabled: true
Style/WordArray:
Enabled: false
Style/HashEachMethods:
Enabled: true
Style/HashTransformKeys:
Enabled: true
Style/HashTransformValues:
Enabled: true
Style/ExponentialNotation:
Enabled: true
jekyll-toc-0.17.1/Appraisals 0000664 0000000 0000000 00000000277 14050066561 0015710 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
SUPPORTED_VERSIONS = %w[3.8 3.9 4.0 4.1 4.2].freeze
SUPPORTED_VERSIONS.each do |version|
appraise "jekyll-#{version}" do
gem 'jekyll', version
end
end
jekyll-toc-0.17.1/CHANGELOG.md 0000664 0000000 0000000 00000000143 14050066561 0015467 0 ustar 00root root 0000000 0000000 Changelog is maintained under [Github Releases](https://github.com/toshimaru/jekyll-toc/releases).
jekyll-toc-0.17.1/Gemfile 0000664 0000000 0000000 00000000344 14050066561 0015154 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gemspec
gem 'appraisal'
gem 'minitest-reporters'
gem 'minitest'
gem 'pry'
gem 'rake'
gem 'rubocop-minitest'
gem 'rubocop-performance'
gem 'rubocop-rake'
gem 'rubocop'
gem 'simplecov', '~> 0.17.1'
jekyll-toc-0.17.1/LICENSE.md 0000664 0000000 0000000 00000002064 14050066561 0015266 0 ustar 00root root 0000000 0000000 The MIT License (MIT)
Copyright (c) 2020 Toshimaru
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
jekyll-toc-0.17.1/README.md 0000664 0000000 0000000 00000017741 14050066561 0015151 0 ustar 00root root 0000000 0000000 # jekyll-toc

[](https://badge.fury.io/rb/jekyll-toc)
[](https://codeclimate.com/github/toshimaru/jekyll-toc)
[](https://codeclimate.com/github/toshimaru/jekyll-toc/test_coverage)
## Table of Contents
- [Installation](#installation)
- [Usage](#usage)
- [Basic Usage](#basic-usage)
- [Advanced Usage](#advanced-usage)
- [Generated HTML](#generated-html)
- [Customization](#customization)
- [Default Configuration](#default-configuration)
- [TOC levels](#toc-levels)
- [Enable TOC by default](#enable-toc-by-default)
- [Skip TOC](#skip-toc)
- [Skip TOC Sectionally](#skip-toc-sectionally)
- [CSS Styling](#css-styling)
- [Custom CSS Class and ID](#custom-css-class-and-id)
- [Using Unordered/Ordered lists](#using-unorderedordered-lists)
- [Alternative Tools](#alternative-tools)
## Installation
Add jekyll-toc plugin in your site's `Gemfile`, and run `bundle install`.
```ruby
gem 'jekyll-toc'
```
Add jekyll-toc to the `gems:` section in your site's `_config.yml`.
```yml
plugins:
- jekyll-toc
```
Set `toc: true` in posts for which you want the TOC to appear.
```yml
---
layout: post
title: "Welcome to Jekyll!"
toc: true
---
```
## Usage
There are three Liquid filters, which can be applied to HTML content,
e.g. the Liquid variable `content` available in Jekyll's templates.
### Basic Usage
#### `toc` filter
Add the `toc` filter to your site's `{{ content }}` (e.g. `_layouts/post.html`).
```liquid
{{ content | toc }}
```
This filter places the TOC directly above the content.
### Advanced Usage
If you'd like separated TOC and content, you can use `{% toc %}` tag (or `toc_only` filter) and `inject_anchors` filter.
#### `{% toc %}` tag / `toc_only` filter
Generates the TOC itself as described [below](#generated-html).
Mostly useful in cases where the TOC should _not_ be placed immediately
above the content but at some other place of the page, i.e. an aside.
```html
```
:warning: **`{% toc %}` Tag Limitation**
`{% toc %}` works only for [Jekyll Posts](https://jekyllrb.com/docs/step-by-step/08-blogging/) and [Jekyll Collections](https://jekyllrb.com/docs/collections/).
If you'd like to use `{% toc %}` except posts or collections, please use `toc_only` filter as described below.
```html
{{ content | toc_only }}
{{ content | inject_anchors }}
```
#### `inject_anchors` filter
Injects HTML anchors into the content without actually outputting the TOC itself.
They are of the form:
```html
```
This is only useful when the TOC itself should be placed at some other
location with the `toc_only` filter.
## Generated HTML
jekyll-toc generates an unordered list by default. The HTML output is as follows.
```html
```

## Customization
jekyll-toc is customizable on `_config.yml`.
### Default Configuration
```yml
# _config.yml
toc:
min_level: 1
max_level: 6
ordered_list: false
no_toc_section_class: no_toc_section
list_id: toc
list_class: section-nav
sublist_class: ''
item_class: toc-entry
item_prefix: toc-
```
### TOC levels
```yml
# _config.yml
toc:
min_level: 2 # default: 1
max_level: 5 # default: 6
```
The default heading range is from `` to ``.
### Enable TOC by default
You can enable TOC by default with [Front Matter Defaults](https://jekyllrb.com/docs/configuration/front-matter-defaults/):
```yml
# _config.yml
defaults:
- scope:
path: ""
values:
toc: true
```
### Skip TOC
The heading is ignored in the toc by adding `no_toc` class.
```html
h1
This heading is ignored in the TOC
h2
```
### Skip TOC Sectionally
The headings are ignored inside the element which has `no_toc_section` class.
```html
h1
This heading is ignored in the TOC
This heading is ignored in the TOC
h4
```
Which would result in only the `` & `` within the example being included in the TOC.
The class can be configured on `_config.yml`:
```yml
# _config.yml
toc:
no_toc_section_class: exclude # default: no_toc_section
```
Configuring multiple classes are allowed:
```yml
# _config.yml
toc:
no_toc_section_class:
- no_toc_section
- exclude
- your_custom_skip_class_name
```
### CSS Styling
The toc can be modified with CSS. The sample CSS is the following.
```css
.section-nav {
background-color: #fff;
margin: 5px 0;
padding: 10px 30px;
border: 1px solid #e8e8e8;
border-radius: 3px;
}
```

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`.
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.
For example, the TOC entry linking to a heading `...
` (a single `#` in Markdown) will get the CSS class `toc-h1`.
### Custom CSS Class and ID
You can apply custom CSS classes to the generated `` and `- ` tags.
```yml
# _config.yml
toc:
list_id: my-toc-id # Default: "toc"
list_class: my-list-class # Default: "section-nav"
sublist_class: my-sublist-class # Default: no class for sublists
item_class: my-item-class # Default: "toc-entry"
item_prefix: item- # Default: "toc-":
```
### Using Unordered/Ordered lists
By default the table of contents will be generated as an unordered list via `` tags. This can be configured to use ordered lists instead `
`.
This can be configured in `_config.yml`:
```yml
# _config.yml
toc:
ordered_list: true # default is false
```
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.
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.
Example
```yml
# _config.yml
toc:
ordered_list: true
list_class: my-list-class
sublist_class: my-sublist-class
```
```css
.my-list-class {
list-style-type: upper-alpha;
}
.my-sublist-class: {
list-style-type: lower-alpha;
}
```
This will produce:

## Alternative Tools
- Adding anchor to headings
- [AnchorJS](https://www.bryanbraun.com/anchorjs/)
- Generating TOC for kramdown content
- [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))
jekyll-toc-0.17.1/Rakefile 0000664 0000000 0000000 00000000321 14050066561 0015321 0 ustar 00root root 0000000 0000000 require "bundler/gem_tasks"
task :default => [:test]
require 'rake/testtask'
Rake::TestTask.new(:test) do |test|
test.libs << 'lib' << 'test'
test.pattern = 'test/**/test_*.rb'
test.verbose = true
end
jekyll-toc-0.17.1/gemfiles/ 0000775 0000000 0000000 00000000000 14050066561 0015453 5 ustar 00root root 0000000 0000000 jekyll-toc-0.17.1/gemfiles/jekyll_3.8.gemfile 0000664 0000000 0000000 00000000454 14050066561 0020672 0 ustar 00root root 0000000 0000000 # This file was generated by Appraisal
source "https://rubygems.org"
gem "appraisal"
gem "minitest-reporters"
gem "minitest"
gem "pry"
gem "rake"
gem "rubocop-minitest"
gem "rubocop-performance"
gem "rubocop-rake"
gem "rubocop"
gem "simplecov", "~> 0.17.1"
gem "jekyll", "3.8"
gemspec path: "../"
jekyll-toc-0.17.1/gemfiles/jekyll_3.9.gemfile 0000664 0000000 0000000 00000000454 14050066561 0020673 0 ustar 00root root 0000000 0000000 # This file was generated by Appraisal
source "https://rubygems.org"
gem "appraisal"
gem "minitest-reporters"
gem "minitest"
gem "pry"
gem "rake"
gem "rubocop-minitest"
gem "rubocop-performance"
gem "rubocop-rake"
gem "rubocop"
gem "simplecov", "~> 0.17.1"
gem "jekyll", "3.9"
gemspec path: "../"
jekyll-toc-0.17.1/gemfiles/jekyll_4.0.gemfile 0000664 0000000 0000000 00000000454 14050066561 0020663 0 ustar 00root root 0000000 0000000 # This file was generated by Appraisal
source "https://rubygems.org"
gem "appraisal"
gem "minitest-reporters"
gem "minitest"
gem "pry"
gem "rake"
gem "rubocop-minitest"
gem "rubocop-performance"
gem "rubocop-rake"
gem "rubocop"
gem "simplecov", "~> 0.17.1"
gem "jekyll", "4.0"
gemspec path: "../"
jekyll-toc-0.17.1/gemfiles/jekyll_4.1.gemfile 0000664 0000000 0000000 00000000454 14050066561 0020664 0 ustar 00root root 0000000 0000000 # This file was generated by Appraisal
source "https://rubygems.org"
gem "appraisal"
gem "minitest-reporters"
gem "minitest"
gem "pry"
gem "rake"
gem "rubocop-minitest"
gem "rubocop-performance"
gem "rubocop-rake"
gem "rubocop"
gem "simplecov", "~> 0.17.1"
gem "jekyll", "4.1"
gemspec path: "../"
jekyll-toc-0.17.1/gemfiles/jekyll_4.2.gemfile 0000664 0000000 0000000 00000000454 14050066561 0020665 0 ustar 00root root 0000000 0000000 # This file was generated by Appraisal
source "https://rubygems.org"
gem "appraisal"
gem "minitest-reporters"
gem "minitest"
gem "pry"
gem "rake"
gem "rubocop-minitest"
gem "rubocop-performance"
gem "rubocop-rake"
gem "rubocop"
gem "simplecov", "~> 0.17.1"
gem "jekyll", "4.2"
gemspec path: "../"
jekyll-toc-0.17.1/jekyll-toc.gemspec 0000664 0000000 0000000 00000001640 14050066561 0017303 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'table_of_contents/version'
Gem::Specification.new do |spec|
spec.name = 'jekyll-toc'
spec.version = Jekyll::TableOfContents::VERSION
spec.summary = 'Jekyll Table of Contents plugin'
spec.description = 'Jekyll (Ruby static website generator) plugin which generates a Table of Contents for the page.'
spec.authors = %w(toshimaru torbjoernk)
spec.email = 'me@toshimaru.net'
spec.files = `git ls-files -z`.split("\x0")
spec.homepage = 'https://github.com/toshimaru/jekyll-toc'
spec.license = 'MIT'
spec.test_files = spec.files.grep(%r{^(test|spec)/})
spec.require_paths = ['lib']
spec.required_ruby_version = '>= 2.5'
spec.add_dependency 'jekyll', '>= 3.9'
spec.add_dependency 'nokogiri', '~> 1.11'
end
jekyll-toc-0.17.1/lib/ 0000775 0000000 0000000 00000000000 14050066561 0014426 5 ustar 00root root 0000000 0000000 jekyll-toc-0.17.1/lib/jekyll-toc.rb 0000664 0000000 0000000 00000002456 14050066561 0017037 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'nokogiri'
require 'table_of_contents/configuration'
require 'table_of_contents/parser'
module Jekyll
# toc tag for Jekyll
class TocTag < Liquid::Tag
def render(context)
return '' unless context.registers[:page]['toc']
content_html = context.registers[:page]['content']
toc_config = context.registers[:site].config['toc'] || {}
TableOfContents::Parser.new(content_html, toc_config).build_toc
end
end
# Jekyll Table of Contents filter plugin
module TableOfContentsFilter
# Deprecated method. Removed in v1.0.
def toc_only(html)
return '' unless toc_enabled?
TableOfContents::Parser.new(html, toc_config).build_toc
end
def inject_anchors(html)
return html unless toc_enabled?
TableOfContents::Parser.new(html, toc_config).inject_anchors_into_html
end
def toc(html)
return html unless toc_enabled?
TableOfContents::Parser.new(html, toc_config).toc
end
private
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
jekyll-toc-0.17.1/lib/table_of_contents/ 0000775 0000000 0000000 00000000000 14050066561 0020116 5 ustar 00root root 0000000 0000000 jekyll-toc-0.17.1/lib/table_of_contents/configuration.rb 0000664 0000000 0000000 00000002465 14050066561 0023321 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Jekyll
module TableOfContents
# jekyll-toc configuration class
class Configuration
attr_reader :toc_levels, :no_toc_class, :ordered_list, :no_toc_section_class,
:list_id, :list_class, :sublist_class, :item_class, :item_prefix
DEFAULT_CONFIG = {
'min_level' => 1,
'max_level' => 6,
'ordered_list' => false,
'no_toc_section_class' => 'no_toc_section',
'list_id' => 'toc',
'list_class' => 'section-nav',
'sublist_class' => '',
'item_class' => 'toc-entry',
'item_prefix' => 'toc-'
}.freeze
def initialize(options)
options = generate_option_hash(options)
@toc_levels = options['min_level']..options['max_level']
@ordered_list = options['ordered_list']
@no_toc_class = 'no_toc'
@no_toc_section_class = options['no_toc_section_class']
@list_id = options['list_id']
@list_class = options['list_class']
@sublist_class = options['sublist_class']
@item_class = options['item_class']
@item_prefix = options['item_prefix']
end
private
def generate_option_hash(options)
DEFAULT_CONFIG.merge(options)
rescue TypeError
DEFAULT_CONFIG
end
end
end
end
jekyll-toc-0.17.1/lib/table_of_contents/helper.rb 0000664 0000000 0000000 00000000641 14050066561 0021723 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Jekyll
module TableOfContents
# helper methods for Parser
module Helper
PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u.freeze
def generate_toc_id(text)
text = text.downcase
.gsub(PUNCTUATION_REGEXP, '') # remove punctuation
.tr(' ', '-') # replace spaces with dash
CGI.escape(text)
end
end
end
end
jekyll-toc-0.17.1/lib/table_of_contents/parser.rb 0000664 0000000 0000000 00000010734 14050066561 0021744 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'table_of_contents/helper'
module Jekyll
module TableOfContents
# Parse html contents and generate table of contents
class Parser
include ::Jekyll::TableOfContents::Helper
def initialize(html, options = {})
@doc = Nokogiri::HTML::DocumentFragment.parse(html)
@configuration = Configuration.new(options)
@entries = parse_content
end
def toc
build_toc + inject_anchors_into_html
end
def build_toc
%(<#{list_tag} id="#{@configuration.list_id}" class="#{@configuration.list_class}">\n#{build_toc_list(@entries)}#{list_tag}>)
end
def inject_anchors_into_html
@entries.each do |entry|
# NOTE: `entry[:id]` is automatically URL encoded by Nokogiri
entry[:header_content].add_previous_sibling(
%()
)
end
@doc.inner_html
end
private
# parse logic is from html-pipeline toc_filter
# https://github.com/jch/html-pipeline/blob/v1.1.0/lib/html/pipeline/toc_filter.rb
def parse_content
headers = Hash.new(0)
(@doc.css(toc_headings) - @doc.css(toc_headings_in_no_toc_section))
.reject { |n| n.classes.include?(@configuration.no_toc_class) }
.inject([]) do |entries, node|
text = node.text
id = node.attribute('id') || generate_toc_id(text)
suffix_num = headers[id]
headers[id] += 1
entries << {
id: suffix_num.zero? ? id : "#{id}-#{suffix_num}",
text: CGI.escapeHTML(text),
node_name: node.name,
header_content: node.children.first,
h_num: node.name.delete('h').to_i
}
end
end
# Returns the list items for entries
def build_toc_list(entries)
i = 0
toc_list = +''
min_h_num = entries.map { |e| e[:h_num] }.min
while i < entries.count
entry = entries[i]
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 << %( - #{entry[:text]})
# If the next entry should be indented in the list, generate a sublist
next_i = i + 1
if next_i < entries.count && entries[next_i][:h_num] > min_h_num
nest_entries = get_nest_entries(entries[next_i, entries.count], min_h_num)
toc_list << %(\n<#{list_tag}#{ul_attributes}>\n#{build_toc_list(nest_entries)}#{list_tag}>\n)
i += nest_entries.count
end
# Add the closing tag for the current entry in the list
toc_list << %(
\n)
elsif entry[:h_num] > min_h_num
# If the current entry should be indented in the list, generate a sublist
nest_entries = get_nest_entries(entries[i, entries.count], min_h_num)
toc_list << build_toc_list(nest_entries)
i += nest_entries.count - 1
end
i += 1
end
toc_list
end
# Returns the entries in a nested list
# The nested list starts at the first entry in entries (inclusive)
# The nested list ends at the first entry in entries with depth min_h_num or greater (exclusive)
def get_nest_entries(entries, min_h_num)
entries.inject([]) do |nest_entries, entry|
break nest_entries if entry[:h_num] == min_h_num
nest_entries << entry
end
end
def toc_headings
@configuration.toc_levels.map { |level| "h#{level}" }.join(',')
end
def toc_headings_in_no_toc_section
if @configuration.no_toc_section_class.is_a?(Array)
@configuration.no_toc_section_class.map { |cls| toc_headings_within(cls) }.join(',')
else
toc_headings_within(@configuration.no_toc_section_class)
end
end
def toc_headings_within(class_name)
@configuration.toc_levels.map { |level| ".#{class_name} h#{level}" }.join(',')
end
def ul_attributes
@ul_attributes ||= @configuration.sublist_class.empty? ? '' : %( class="#{@configuration.sublist_class}")
end
def list_tag
@list_tag ||= @configuration.ordered_list ? 'ol' : 'ul'
end
end
end
end
jekyll-toc-0.17.1/lib/table_of_contents/version.rb 0000664 0000000 0000000 00000000147 14050066561 0022132 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Jekyll
module TableOfContents
VERSION = '0.17.1'
end
end
jekyll-toc-0.17.1/test/ 0000775 0000000 0000000 00000000000 14050066561 0014637 5 ustar 00root root 0000000 0000000 jekyll-toc-0.17.1/test/parser/ 0000775 0000000 0000000 00000000000 14050066561 0016133 5 ustar 00root root 0000000 0000000 jekyll-toc-0.17.1/test/parser/test_inject_anchors_filter.rb 0000664 0000000 0000000 00000001016 14050066561 0024053 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'test_helper'
class TestInjectAnchorsFilter < Minitest::Test
include TestHelpers
def setup
read_html_and_create_parser
end
def test_injects_anchors_into_content
html = @parser.inject_anchors_into_html
assert_match(%r{Simple H1}, html)
end
def test_does_not_inject_toc
html = @parser.inject_anchors_into_html
refute_includes(html, %())
end
end
jekyll-toc-0.17.1/test/parser/test_invalid_options.rb 0000664 0000000 0000000 00000001557 14050066561 0022730 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'test_helper'
class TestInvalidOptions < Minitest::Test
BASE_HTML = 'h1
'
EXPECTED_HTML = <<~HTML.chomp
HTML
def test_option_is_nil
parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, nil)
assert_equal(EXPECTED_HTML, parser.build_toc)
end
def test_option_is_epmty_string
parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, '')
assert_equal(EXPECTED_HTML, parser.build_toc)
end
def test_option_is_string
parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, 'string')
assert_equal(EXPECTED_HTML, parser.build_toc)
end
def test_option_is_array
parser = Jekyll::TableOfContents::Parser.new(BASE_HTML, [])
assert_equal(EXPECTED_HTML, parser.build_toc)
end
end
jekyll-toc-0.17.1/test/parser/test_ordered_list.rb 0000664 0000000 0000000 00000003417 14050066561 0022203 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'test_helper'
class TestOrderedList < Minitest::Test
include TestHelpers
def test_default_configuration
configuration = Jekyll::TableOfContents::Configuration.new({})
refute(configuration.ordered_list)
end
def test_disabled_ordered_list
configuration = Jekyll::TableOfContents::Configuration.new('ordered_list' => false)
refute(configuration.ordered_list)
end
def test_enabled_ordered_list
configuration = Jekyll::TableOfContents::Configuration.new('ordered_list' => true)
assert(configuration.ordered_list)
end
def test_basic_ordered_list_top_heading
parse_with_ordered_list
html = @parser.toc
assert_match(/^/, html)
end
def test_ordered_list_sub_headings
parse_with_ordered_list
html = @parser.toc
assert_match(/\n- /, html)
end
def test_ordered_list_sub_headings_with_classes
parse_with_ordered_list_and_classes
html = @parser.toc
assert_match(/
/, html)
end
def test_ordered_list_subheadings_with_classes_nested_structure
parse_with_ordered_list_and_classes
html = @parser.toc
occurrences = html.scan(//).count
assert_equal(5, occurrences)
end
private
def parse_with_ordered_list
read_html_and_create_parser('ordered_list' => true)
end
def parse_with_ordered_list_and_classes
read_html_and_create_parser(
'ordered_list' => true,
'list_class' => 'top-list-class',
'sublist_class' => 'sublist-class'
)
end
end
jekyll-toc-0.17.1/test/parser/test_toc_filter.rb 0000664 0000000 0000000 00000001605 14050066561 0021653 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'test_helper'
class TestTOCFilter < Minitest::Test
include TestHelpers
def setup
read_html_and_create_parser
end
def test_injects_anchors
html = @parser.toc
assert_match(%r{Simple H1}, html)
end
def test_nested_toc
doc = Nokogiri::HTML(@parser.toc)
nested_h6_text = doc.css('ul.section-nav')
.css('li.toc-h1')
.css('li.toc-h2')
.css('li.toc-h3')
.css('li.toc-h4')
.css('li.toc-h5')
.css('li.toc-h6')
.text
assert_equal('Simple H6', nested_h6_text)
end
def test_injects_toc_container
html = @parser.toc
assert_match(//, html)
end
end
jekyll-toc-0.17.1/test/parser/test_toc_only_filter.rb 0000664 0000000 0000000 00000000653 14050066561 0022716 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'test_helper'
class TestTOCOnlyFilter < Minitest::Test
include TestHelpers
def setup
read_html_and_create_parser
end
def test_injects_toc_container
html = @parser.build_toc
assert_includes(html, %(