UNPKG

eleventy-plugin-nesting-toc

Version:

Eleventy plugin which adds a filter to generate a Table of Contents from html

143 lines (107 loc) 4.69 kB
# Table of Contents (nesting) Eleventy Plugin This Eleventy plugin will generate a (property nested) TOC from page content using an Eleventy filter. HTML: ```html <h1>Hello, World</h1> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad animi assumenda consequuntur debitis ea eligendi eos hic necessitatibus, odio recusandae rem similique, totam unde. Asperiores cumque facere nisi quibusdam vitae. <h2 id="greetings-from-mars">Greetings from Mars</h2> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus aperiam at blanditiis dolorem ea, eius impedit maxime non omnis quia repudiandae sit, suscipit vel veniam voluptas. Dignissimos eos porro sit. <h3 id="the-red-planet">The red planet</h3> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut consequatur dicta doloremque est iure minima placeat recusandae sit. Dolorum quis quod sequi! Commodi cupiditate debitis, dolore error excepturi nulla optio. <h2 id="greetings-from-pluto">Greetings from Pluto</h2> ``` Generated TOC: * [Greetings from Mars](#greetings-from-mars) * [The red planet](#the-red-planet) * [Greetings from Pluto](#greetings-from-pluto) ```html <nav class="toc"> <ol> <li><a href="#greetings-from-mars">Greetings from Mars</a></li> <ol> <li><a href="#the-red-planet">The red planet</a></li> </ol> <li><a href="#greetings-from-pluto">Greetings from Pluto</a></li> </ol> </nav> ``` <hr> # This Readme * [Options](#options) * [Install](#install) * [Adding it to Eleventy](#adding-it-to-the-eleventy-engine) * [Using the filter](#using-the-provided-filter) * [Configuring](#configuring) * [Gotchyas](#gotchyas) ## Options ```javascript const defaults = { tags: ['h2', 'h3', 'h4'], // Which heading tags are selected (headings must each have an ID attribute) ignoredElements: [], // Elements to ignore when constructing the label for every header (useful for ignoring permalinks, must be selectors) wrapper: 'nav', // Element to put around the root `ol` wrapperClass: 'toc', // Class for the element around the root `ol` headingText: '', // Optional text to show in heading above the wrapper element headingTag: 'h2' // Heading tag when showing heading above the wrapper element } ``` ## Install ```sh npm i --save eleventy-plugin-nesting-toc ``` ## Usage ### Adding it to the Eleventy Engine **IMPORTANT NOTE**: Your heading tags will need to have `id`s on them, so that the TOC can provide proper anchor links to them. Eleventy does not do this for you ootb. You can use a plugin like [markdown-it-anchor](https://www.npmjs.com/package/markdown-it-anchor) to add those `id`s to the headings automagically ```diff // .eleventy.js module.exports = function (eleventyConfig) { //... + const pluginTOC = require('eleventy-plugin-nesting-toc'); + eleventyConfig.addPlugin(pluginTOC); // Example Markdown configuration (to add IDs to the headers) const markdownIt = require('markdown-it'); const markdownItAnchor = require('markdown-it-anchor'); eleventyConfig.setLibrary("md", markdownIt({ html: true, linkify: true, typographer: true, }).use(markdownItAnchor, {}) ); //... } ``` ### Using the provided filter ```nunjucks <aside> {{ content | toc | safe }} </aside> <article> {{ content }} </article> ``` ### Configuring You can override any of the [options](#options) at the time that you call it, or when you add it to the eleventy engine. All the options will be merged together, with the precedence being `when invoking the filter > .eleventy.js > defaults`. Override the defaults for your whole site: ```diff module.exports = function (eleventyConfig) { //... + const pluginTOC = require('eleventy-plugin-nesting-toc'); + eleventyConfig.addPlugin(pluginTOC, {tags: ['h2']}); //... } ``` And override those just for one template, as it's being invoked ```nunjucks <aside> {{ content | toc(tags=['h2', 'h3'], wrapperClass='fixed toc') | safe }} </aside> ``` If you have specific headings which you don't want to be included in the TOC, you can add the `data-toc-exclude` attribute to exclude these headings. One way to add this attribute is via the use of the <a href="https://www.npmjs.com/package/markdown-it-attrs" target="_blank" rel="noopener">markdown-it-attrs</a> npm package. ```markdown ### Level 3 heading to ignore {data-toc-exclude} ``` ## Gotchyas A few things must be in place for this to work properly, and provide the proper nested structure * The first matched heading on the page should be the topmost. _Don't put an h3 before an h2_. * you can only use actual heading tags. _Don't use `tags=['section']`, etc._