PostHTML TOC
August 27, 2020 · View on GitHub
A table of contents, usually headed simply Contents and abbreviated informally as TOC, is a list, usually found on a page before the start of a written work, of its chapter or section titles or brief descriptions with their commencing page numbers. Wikipedia
The plugin works particularly well with markdown documents.
By defaults
Before:
<html>
<body>
<h1 id="title1">Title 1</h1>
<p>p1</p>
<h2 id="title2">Title 2</h2>
<p>p2</p>
<h3 id="title3">Title 3</h3>
<p>p3</p>
</body>
</html>
After:
<html>
<body>
<h1 id="title1">Title 1</h1>
<div id="toc">
<div id="toctitle">Contents</div>
<ul>
<li>
<a href="#title2">Title 2</a>
<ul>
<li><a href="#title3">Title 3</a></li>
</ul>
</li>
</ul>
</div>
<p>p1</p>
<h2 id="title2">Title 2</h2>
<p>p2</p>
<h3 id="title3">Title 3</h3>
<p>p3</p>
</body>
</html>
Install
Installation in your project
npm i posthtml posthtml-toc
Usage
const fs = require('fs');
const posthtml = require('posthtml');
const toc = require('posthtml-toc');
posthtml()
.use(toc({ /* options */ }))
.process(html/*, options */)
.then(result => fs.writeFileSync('./after.html', result.html));
Options
Defaults options
insert = { after: 'h1' }— insert the TOC immediately after the first<h1>title = "Content"— Title TOC blockignoreMissingSelector = false— throw an error if the selector is not foundignoreMissingHeadings = false— throw an error if the no headings are foundtoggleis undefined
insert option
This option allows you to specify where the TOC will be inserted in the HTML output. The option expects an object with exactly one key with a string value, as in this schema:
{ insert: { <position>: <selector> } }
<selector> is a string used to select an HTML element by matching one of three
patterns:
-
'<tag>'— matches the first element with the name<tag>.Example:
'nav'matches<nav>. -
'#<id>'— matches the first element with<id>as theidattribute value.Example:
'#here'matches<div id="here">. -
'.<class>'— matches the first element with<class>as one of the space-separated strings in theclassattribute value.Example:
'.here'matches<div class="are you here or there">.
<position> can be one of the following:
-
after— The TOC will be inserted immediately after the matching node.Example:
{ insert: { after: 'h1' } }(default) produces:<h1>...</h1> +<div id="toc">...</div> <p>...</p> -
before— The TOC will be inserted immediately before the matching node.Example:
{ insert: { before: '#here' } }produces:<p>...</p> +<div id="toc">...</div> <div id="here">...</div> -
afterChildren— The TOC will be inserted into the contents of the matching node after the last child.Example:
{ insert: { afterChildren: '.here' } }produces:<nav class="here"> <p>...</p> + <div id="toc">...</div> </nav> -
beforeChildren— The TOC will be inserted into the contents of the matching node before the first child.Example:
{ insert: { beforeChildren: '.here' } }produces:<nav class="here"> + <div id="toc">...</div> <p>...</p> </nav>
toggle options
Before:
<html>
<body>
<h1 id="title1">Title 1</h1>
<p>p1</p>
<h2 id="title2">Title 2</h2>
<p>p2</p>
<h3 id="title3">Title 3</h3>
<p>p3</p>
</body>
</html>
Add option:
const fs = require('fs');
const posthtml = require('posthtml');
const toc = require('posthtml-toc');
posthtml()
.use(toc({
toggle: ['show', 'hide', true]
}))
.process(html/*, options */)
.then(result => fs.writeFileSync('./after.html', result.html));
After:
<html>
<body>
<h1 id="title1">Title 1</h1>
<style>
#toctoggle,#toctoggle:checked~ul{display:none}
#toctoggle~label:after{content:"hide"}
#toctoggle:checked~label:after{content:"show"}
#toc label{cursor:pointer}
</style>
<div id="toc">
<input type="checkbox" role="button" id="toctoggle" checked>
<h2>Content</h2>
<label for="toctoggle"></label>
<ul>
<li>
<a href="#title2">Title 2</a>
<ul>
<li><a href="#title3">Title 3</a></li>
</ul>
</li>
</ul>
</div>
<p>p1</p>
<h2 id="title2">Title 2</h2>
<p>p2</p>
<h3 id="title3">Title 3</h3>
<p>p3</p>
</body>
</html>
ignoreMissingSelector option
-
{ ignoreMissingSelector: false }(default) — throw an error if the selector (the defaulth1tag or the value passed tooptions.after) is not found.For example, with this option, you get an error on the second file because there is no
h1tag:<!-- file-with-toc.html --> <h1>Title 1</h1> <h2 id="title2">Title 2</h2><!-- file-without-toc.html --> <div></div> -
{ ignoreMissingSelector: true }— ignore HTML input that does not have the selector.This is useful if you want to uniformly process a number of files but don't want to insert a TOC in all of them.
For example, with the files mentioned above, instead of an error, the first file is modified and the second file is unchanged:
<!-- file-with-toc.html --> <h1>Title 1</h1> <div id="toc"><h2>Content</h2><ul><li><a href="#title2">Title 2</a></li></ul></div> <h2 id="title2">Title 2</h2><!-- file-without-toc.html --> <div></div>
ignoreMissingHeadings option
This option controls what happens when no headings (h2, h3, h4, h5,
h6) are found in the HTML input.
-
{ ignoreMissingHeadings: false }(default) — throw an error if no headings are found. -
{ ignoreMissingHeadings: true }— do not throw an error if no headings are found. Instead, a TOC with an empty list (i.e.<ul></ul>) will be inserted.
Contributing
See PostHTML Guidelines and contribution guide.