A Markdown-It plugin that extracts and processes headers from Markdown content. This plugin is ideal for generating Table of Contents (ToC) or managing headers for documentation and static sites.
NOTE: When using with vue-router
be sure to use history
mode and not hash
mode otherwise your hash links will not work as expected.
Features
- Extracts headers based on specified levels (e.g.,
h1
, h2
, h3
).
- Supports custom slugification for header IDs.
- Allows custom formatting for header titles.
- Provides nested structure for headers (e.g., hierarchical ToC generation).
- Compatible with Markdown-It environments for additional flexibility.
Installation
Install the plugin via your preferred package manager:
pnpm add @md-plugins/md-plugin-headers
yarn add @md-plugins/md-plugin-headers
npm install @md-plugins/md-plugin-headers
Usage
Basic Setup
import MarkdownIt from 'markdown-it';
import { headersPlugin } from '@md-plugins/md-plugin-headers';
import type { MarkdownItEnv } from '@md-plugins/shared';
const md = new MarkdownIt();
md.use(headersPlugin, {
level: [1, 2, 3],
slugify: (str) => str.toLowerCase().replace(/\s+/g, '-'),
format: (title) => title.toUpperCase(),
});
const markdownContent = `
# Header 1
## Subheader 1.1
### Subheader 1.1.1
`;
const env: MarkdownItEnv = {};
const renderedOutput = md.render(markdownContent, env);
console.log('Rendered Output:', renderedOutput);
console.log('Extracted Headers:', env.toc);
Example Output
The plugin processes headers and stores them in the toc
property of the Markdown-It environment (env
):
[
{
"level": 1,
"title": "HEADER 1",
"id": "header-1",
"link": "#header-1",
"children": [
{
"level": 2,
"title": "SUBHEADER 1.1",
"id": "subheader-1-1",
"link": "#subheader-1-1",
"children": [
{
"level": 3,
"title": "SUBHEADER 1.1.1",
"id": "subheader-1-1-1",
"link": "#subheader-1-1-1",
"children": []
}
]
}
]
}
]
Options
The md-plugin-headers
plugin supports the following options:
level | number[] | [2, 3] | Heading levels to extract (e.g., [2, 3] for h2, h3). |
slugify | function | (str) => str | Function to generate slugs for header IDs. |
format | function | (str) => str | Function to format header titles. |
shouldAllowNested | boolean | false | Whether to allow headers inside nested blocks (e.g., lists, quotes). |
Advanced Usage
Generating a Table of Contents (ToC)
With the toc
property in env
, you can build a ToC dynamically:
function generateToC(toc) {
const list = toc
.map((item) => {
const children = item.children ? `<ul>${generateToC(item.children)}</ul>` : ''
return `<li><a href="${item.link}">${item.title}</a>${children}</li>`
})
.join('')
return `<ul>${list}</ul>`
}
const tocHtml = generateToC(env.toc)
console.log('Generated ToC:', tocHtml)
Custom Slugify Function
You can use your own slugification logic for header IDs:
md.use(headersPlugin, {
slugify: (str) => encodeURIComponent(str.replace(/\s+/g, '_')),
})
Whatever you use on the backend, should be the same logic on the frontend for slugification so that they match when using hash links.
Enable nested headers to include headers inside blockquotes or lists:
md.use(headersPlugin, {
shouldAllowNested: true,
})
Testing
pnpm test
Documentation
In case this README falls out of date, please refer to the documentation for the latest information.
License
This project is licensed under the MIT License. See the LICENSE file for details.