rehype-custom-toc
v1.0.1
Published
rehype plugin to generate a customizable table of contents
Downloads
846
Maintainers
Readme
rehype-custom-toc
rehype plugin to generate a customizable table of contents. If you are using Astro, you can use the convenient wrapper astro-custom-toc.
Installation
npm install rehype-custom-tocExample usage
The table of contents will be inserted at the location of the <!-- toc --> comment or at the beginning of the file if no comment is found.
When parsing HTML with rehype, the <!-- toc --> comment is preserved as-is, but when converting from Markdown you need to convert Markdown comments to HTML comments (as shown below with remark-comment) so rehype-custom-toc can detect the ToC marker.
import remarkComment from "remark-comment";
import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import rehypeCustomToc from "rehype-custom-toc";
import rehypeStringify from "rehype-stringify";
import { unified } from "unified";
/**
* A comment node generated by the `remark-comment` plugin.
*/
interface Comment extends Node {
type: "comment";
value: "";
commentValue: string;
}
const processor = unified()
.use(remarkParse)
.use(remarkComment, {
ast: true
})
.use(remarkRehype, {
handlers: {
/**
* Convert a mdast comment node to a hast comment node.
* @param _ State
* @param node mdast comment node
* @returns hast comment node
*/
comment: (_, node: Comment) => ({
type: "comment",
value: node.commentValue
})
}
})
.use(rehypeCustomToc)
.use(rehypeStringify);
const markdown = `
# Title
This is a sample markdown paragraph.
<!-- toc -->
## Section 1
### Subsection 1.1
`;
processor.process(markdown).then((result) => {
console.log(result.toString());
});The above code will output the following (formatted for readability):
<h1 id="title">Title</h1>
<p>This is a sample markdown paragraph.</p>
<aside class="toc">
<h2>Contents</h2>
<nav>
<ul>
<li><a href="#title">Title</a></li>
<ul>
<li><a href="#section-1">Section 1</a></li>
<ul>
<li><a href="#subsection-11">Subsection 1.1</a></li>
</ul>
</ul>
</ul>
</nav>
</aside>
<h2 id="section-1">Section 1</h2>
<h3 id="subsection-11">Subsection 1.1</h3>Options
template
A function that takes the generated HTML and returns the final HTML. This can be used to wrap the generated HTML in a custom template.
Default:
const defaultTemplate = (html) => {
return `
<aside class="toc">
<h2>Contents</h2>
<nav>
${html}
</nav>
</aside>`.trim();
};maxDepth
The maximum depth of headings to include in the table of contents.
Default: 3
ordered
Whether to use an ordered list (<ol>) or an unordered list (<ul>).
Default: false
