{"id":27821534,"url":"https://github.com/JS-DevTools/rehype-toc","last_synced_at":"2025-05-01T17:03:45.450Z","repository":{"id":38455182,"uuid":"192908382","full_name":"JS-DevTools/rehype-toc","owner":"JS-DevTools","description":"A rehype plugin that adds a table of contents (TOC) to the page","archived":false,"fork":false,"pushed_at":"2024-07-29T17:11:53.000Z","size":227,"stargazers_count":76,"open_issues_count":12,"forks_count":17,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-18T10:57:26.414Z","etag":null,"topics":["html","html5","javascript","nodejs","rehype","rehype-plugin","table-of-contents","toc","unified"],"latest_commit_sha":null,"homepage":"https://jstools.dev/rehype-toc/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JS-DevTools.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-20T11:33:48.000Z","updated_at":"2025-04-14T06:15:37.000Z","dependencies_parsed_at":"2024-06-18T14:08:04.018Z","dependency_job_id":"a7427a38-8164-4695-928f-317792cdebdf","html_url":"https://github.com/JS-DevTools/rehype-toc","commit_stats":{"total_commits":80,"total_committers":2,"mean_commits":40.0,"dds":"0.012499999999999956","last_synced_commit":"195e8ace40e38564f0ba886c93debc95ff1cc08d"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":"JS-DevTools/template-node-typescript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JS-DevTools%2Frehype-toc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JS-DevTools%2Frehype-toc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JS-DevTools%2Frehype-toc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JS-DevTools%2Frehype-toc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JS-DevTools","download_url":"https://codeload.github.com/JS-DevTools/rehype-toc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251912749,"owners_count":21664087,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["html","html5","javascript","nodejs","rehype","rehype-plugin","table-of-contents","toc","unified"],"created_at":"2025-05-01T17:01:46.492Z","updated_at":"2025-05-01T17:03:45.410Z","avatar_url":"https://github.com/JS-DevTools.png","language":"JavaScript","readme":"# Table of Contents plugin for Rehype\nA [rehype](https://github.com/rehypejs/rehype) plugin that adds a table of contents (TOC) to the page\n\n[![Cross-Platform Compatibility](https://jstools.dev/img/badges/os-badges.svg)](https://github.com/JS-DevTools/rehype-toc/actions)\n[![Build Status](https://github.com/JS-DevTools/rehype-toc/workflows/CI-CD/badge.svg)](https://github.com/JS-DevTools/rehype-toc/actions)\n\n[![Coverage Status](https://coveralls.io/repos/github/JS-DevTools/rehype-toc/badge.svg?branch=master)](https://coveralls.io/github/JS-DevTools/rehype-toc)\n[![Dependencies](https://david-dm.org/JS-DevTools/rehype-toc.svg)](https://david-dm.org/JS-DevTools/rehype-toc)\n\n[![npm](https://img.shields.io/npm/v/@jsdevtools/rehype-toc.svg)](https://www.npmjs.com/package/@jsdevtools/rehype-toc)\n[![License](https://img.shields.io/npm/l/@jsdevtools/rehype-toc.svg)](LICENSE)\n[![Buy us a tree](https://img.shields.io/badge/Treeware-%F0%9F%8C%B3-lightgreen)](https://plant.treeware.earth/JS-DevTools/rehype-toc)\n\n\n\nFeatures\n--------------------------\n- Adds a `\u003cnav\u003e` and `\u003col\u003e` list outlining all headings on the page\n- Combine with [rehype-slug](https://github.com/rehypejs/rehype-slug) to create links to each heading\n- Ignores headings outside of `\u003cmain\u003e` if it exists\n- You can customize which headings are included (defaults to `\u003ch1\u003e` - `\u003ch6\u003e`)\n- You can customize the CSS classes on every TOC element\n- Hooks give you complete customization of the generated HTML\n\n\n\nExample\n--------------------------\n\n**input.html**\u003cbr\u003e\nHere's the original HTML file. There are three levels of headings (`\u003ch1\u003e` - `\u003ch3\u003e`), and none of them have IDs.\n\n```html\n\u003chtml\u003e\n  \u003cbody\u003e\n    \u003ch1\u003eApple Pie Recipe\u003c/h1\u003e\n    \u003cp\u003eThis is the world's best apple pie recipe...\u003c/p\u003e\n\n    \u003cdiv\u003e\n      \u003ch2\u003eFilling\u003c/h2\u003e\n      \u003cp\u003eThe filling is the best part...\u003c/p\u003e\n\n      \u003ch3\u003ePreparing the apples\u003c/h3\u003e\n      \u003cp\u003eCut the apples into 1/4 inch slices...\u003c/p\u003e\n\n      \u003ch3\u003ePreparing the spice mix\u003c/h3\u003e\n      \u003cp\u003eIn a mixing bowl, combine sugar, cinnamon...\u003c/p\u003e\n    \u003c/div\u003e\n\n    \u003cdiv\u003e\n      \u003ch2\u003eCrust\u003c/h2\u003e\n      \u003cp\u003eHow to make the perfect flaky crust...\u003c/p\u003e\n\n      \u003ch3\u003ePreparing the dough\u003c/h3\u003e\n      \u003cp\u003eCombine flour, sugar, salt...\u003c/p\u003e\n\n      \u003ch3\u003eThe criss-cross top\u003c/h3\u003e\n      \u003cp\u003eCut the top crust into 1/2 inch strips...\u003c/p\u003e\n    \u003c/div\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n**example.js**\u003cbr\u003e\nThis script reads the `input.html` file above writes the results to `output.html` (shown below). The script uses [unified](https://unifiedjs.com/), [rehype-parse](https://github.com/rehypejs/rehype/tree/master/packages/rehype-parse), [rehype-slug](https://github.com/rehypejs/rehype-slug), and [rehype-stringify](https://github.com/rehypejs/rehype/tree/master/packages/rehype-stringify).\n\n\n```javascript\nconst unified = require(\"unified\");\nconst parse = require(\"rehype-parse\");\nconst slug = require(\"rehype-slug\");\nconst toc = require(\"@jsdevtools/rehype-toc\");\nconst stringify = require(\"rehype-stringify\");\nconst fs = require(\"fs\");\n\nasync function example() {\n  // Create a Rehype processor with the TOC plugin\n  const processor = unified()\n    .use(parse)\n    .use(slug)\n    .use(toc)\n    .use(stringify);\n\n  // Read the original HTML file\n  let inputHTML = await fs.promises.readFile(\"input.html\");\n\n  // Process the HTML, adding heading IDs and Table of Contents\n  let outputHTML = await processor.process(inputHTML);\n\n  // Save the new HTML\n  await fs.promises.writeFile(\"output.html\", outputHTML);\n}\n```\n\n**output.html**\u003cbr\u003e\nHere's the HTML that gets created by the above script. Notice that a table of contents has been added at the top of the `\u003cbody\u003e`, with links to each of the headings on the page. The headings also now have IDs, thanks to [rehype-slug](https://github.com/rehypejs/rehype-slug).\n\n```html\n\u003chtml\u003e\n  \u003cbody\u003e\n    \u003cnav class=\"toc\"\u003e\n      \u003col class=\"toc-level toc-level-1\"\u003e\n        \u003cli class=\"toc-item toc-item-h1\"\u003e\n          \u003ca class=\"toc-link toc-link-h1\" href=\"#apple-pie-recipe\"\u003e\n            Apple Pie Recipe\n          \u003c/a\u003e\n\n          \u003col class=\"toc-level toc-level-2\"\u003e\n            \u003cli class=\"toc-item toc-item-h2\"\u003e\n              \u003ca class=\"toc-link toc-link-h2\" href=\"#filling\"\u003e\n                Filling\n              \u003c/a\u003e\n\n              \u003col class=\"toc-level toc-level-3\"\u003e\n                \u003cli class=\"toc-item toc-item-h3\"\u003e\n                  \u003ca class=\"toc-link toc-link-h3\" href=\"#preparing-the-apples\"\u003e\n                    Preparing the apples\n                  \u003c/a\u003e\n                \u003c/li\u003e\n                \u003cli class=\"toc-item toc-item-h3\"\u003e\n                  \u003ca class=\"toc-link toc-link-h3\" href=\"#preparing-the-spice-mix\"\u003e\n                    Preparing the spice mix\n                  \u003c/a\u003e\n                \u003c/li\u003e\n              \u003c/ol\u003e\n            \u003c/li\u003e\n\n            \u003cli class=\"toc-item toc-item-h2\"\u003e\n              \u003ca class=\"toc-link toc-link-h2\" href=\"#crust\"\u003e\n                Crust\n              \u003c/a\u003e\n\n              \u003col class=\"toc-level toc-level-3\"\u003e\n                \u003cli class=\"toc-item toc-item-h3\"\u003e\n                  \u003ca class=\"toc-link toc-link-h3\" href=\"#preparing-the-dough\"\u003e\n                    Preparing the dough\n                  \u003c/a\u003e\n                \u003c/li\u003e\n                \u003cli class=\"toc-item toc-item-h3\"\u003e\n                  \u003ca class=\"toc-link toc-link-h3\" href=\"#the-criss-cross-top\"\u003e\n                    The criss-cross top\n                  \u003c/a\u003e\n                \u003c/li\u003e\n              \u003c/ol\u003e\n            \u003c/li\u003e\n          \u003c/ol\u003e\n        \u003c/li\u003e\n      \u003c/ol\u003e\n    \u003c/nav\u003e\n\n    \u003ch1 id=\"apple-pie-recipe\"\u003eApple Pie Recipe\u003c/h1\u003e\n    \u003cp\u003eThis is the world's best apple pie recipe...\u003c/p\u003e\n\n    \u003cdiv\u003e\n      \u003ch2 id=\"filling\"\u003eFilling\u003c/h2\u003e\n      \u003cp\u003eThe filling is the best part...\u003c/p\u003e\n\n      \u003ch3 id=\"preparing-the-apples\"\u003ePreparing the apples\u003c/h3\u003e\n      \u003cp\u003eCut the apples into 1/4 inch slices...\u003c/p\u003e\n\n      \u003ch3 id=\"preparing-the-spice-mix\"\u003ePreparing the spice mix\u003c/h3\u003e\n      \u003cp\u003eIn a mixing bowl, combine sugar, cinnamon...\u003c/p\u003e\n    \u003c/div\u003e\n\n    \u003cdiv\u003e\n      \u003ch2 id=\"crust\"\u003eCrust\u003c/h2\u003e\n      \u003cp\u003eHow to make the perfect flaky crust...\u003c/p\u003e\n\n      \u003ch3 id=\"preparing-the-dough\"\u003ePreparing the dough\u003c/h3\u003e\n      \u003cp\u003eCombine flour, sugar, salt...\u003c/p\u003e\n\n      \u003ch3 id=\"the-criss-cross-top\"\u003eThe criss-cross top\u003c/h3\u003e\n      \u003cp\u003eCut the top crust into 1/2 inch strips...\u003c/p\u003e\n    \u003c/div\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n\n\nInstallation\n--------------------------\nYou can install Rehype TOC via [npm](https://docs.npmjs.com/about-npm/).\n\n```bash\nnpm install @jsdevtools/rehype-toc\n```\n\nYou'll probably want to install [unified](https://unifiedjs.com/), [rehype-parse](https://github.com/rehypejs/rehype/tree/master/packages/rehype-parse), [rehype-stringify](https://github.com/rehypejs/rehype/tree/master/packages/rehype-stringify), and [rehype-slug](https://github.com/rehypejs/rehype-slug) as well.\n\n```bash\nnpm install unified rehype-parse rehype-stringify rehype-slug\n```\n\n\n\nUsage\n--------------------------\nUsing the Rehype TOC plugin requires an understanding of how to use Unified and Rehype. [Here is an excelleng guide](https://unifiedjs.com/learn/guide/introduction-to-unified/) to learn the basics.\n\nThe Rehype TOC plugin works just like any other Rehype plugin. Pass it to [the `.use()` method](https://github.com/unifiedjs/unified#processoruseplugin-options), optionally with an [options object](#options).\n\n```javascript\nconst unified = require(\"unified\");\nconst toc = require(\"@jsdevtools/rehype-toc\");\n\n// Use the Rehype TOC plugin with its default options\nunified().use(toc);\n\n// Use the Rehype TOC plugin with custom options\nunified().use(toc, {\n  headings: [\"h1\", \"h2\"],     // Only include \u003ch1\u003e and \u003ch2\u003e headings in the TOC\n  cssClasses: {\n    toc: \"page-outline\",      // Change the CSS class for the TOC\n    link: \"page-link\",        // Change the CSS class for links in the TOC\n  }\n});\n```\n\n\n\nOptions\n--------------------------\nThe Rehype TOC plugin supports the following options:\n\n|Option                |Type                |Default                |Description\n|:---------------------|:-------------------|:----------------------|:-----------------------------------------\n|`nav`                 |boolean             |true                   |Determines whether the table of contents is wrapped in a `\u003cnav\u003e` element.\n|`position`            |string              |\"afterbegin\"           |The position at which the table of contents should be inserted, relative to the `\u003cmain\u003e` or `\u003cbody\u003e` element. Can be \"beforebegin\", \"afterbegin\", \"beforeend\", or \"afterend\". See [the `insertAdjacentElement()` docs](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement) for an explanation of each value.\n|`headings`            |array of strings    |h1, h2, h3, h4, h5, h6 |The HTML heading tags to include in the table of contents\n|`cssClasses.toc`      |string              |toc                    |The CSS class name for the top-level `\u003cnav\u003e` or `\u003col\u003e` element that contains the whole table of contents.\n|`cssClasses.list`     |string              |toc-level              |The CSS class name for all `\u003col\u003e` elements in the table of contents, including the top-level one.\n|`cssClasses.listItem` |string              |toc-item               |The CSS class name for all `\u003cli\u003e` elements in the table of contents.\n|`cssClasses.link`     |string              |toc-link               |The CSS class name for all `\u003ca\u003e` elements in the table of contents.\n|`customizeTOC`        |function(toc)       |                       |Allows you to customize the table of contents before it is added to the page.\u003cbr\u003e\u003cbr\u003eThe function receives the TOC node tree and can modify it in any way you want. Or you can return a new node tree to use instead. Or return `false` to prevent the the TOC from being added to the page.\n|`customizeTOCItem`    |function(toc, heading)|                     |Allows you to customize each item in the table of contents before it is added to the page.\u003cbr\u003e\u003cbr\u003eThe function receives the TOC item's node tree and the heading node that it refers to. You can modify the nodes in any way you want. Or you can return a new node tree to use instead. Or return `false` to prevent the the TOC from being added to the page.\n\n\n\nContributing\n--------------------------\nContributions, enhancements, and bug-fixes are welcome!  [Open an issue](https://github.com/JS-DevTools/rehype-toc/issues) on GitHub and [submit a pull request](https://github.com/JS-DevTools/rehype-toc/pulls).\n\n#### Building\nTo build the project locally on your computer:\n\n1. __Clone this repo__\u003cbr\u003e\n`git clone https://github.com/JS-DevTools/rehype-toc.git`\n\n2. __Install dependencies__\u003cbr\u003e\n`npm install`\n\n3. __Build the code__\u003cbr\u003e\n`npm run build`\n\n4. __Run the tests__\u003cbr\u003e\n`npm test`\n\n\n\nLicense\n--------------------------\nRehype TOC is 100% free and open-source, under the [MIT license](LICENSE). Use it however you want.\n\nThis package is [Treeware](http://treeware.earth). If you use it in production, then we ask that you [**buy the world a tree**](https://plant.treeware.earth/JS-DevTools/rehype-toc) to thank us for our work. By contributing to the Treeware forest you’ll be creating employment for local families and restoring wildlife habitats.\n\n\n\nBig Thanks To\n--------------------------\nThanks to these awesome companies for their support of Open Source developers ❤\n\n[![Travis CI](https://jstools.dev/img/badges/travis-ci.svg)](https://travis-ci.com)\n[![SauceLabs](https://jstools.dev/img/badges/sauce-labs.svg)](https://saucelabs.com)\n[![Coveralls](https://jstools.dev/img/badges/coveralls.svg)](https://coveralls.io)\n","funding_links":[],"categories":["Plugins"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJS-DevTools%2Frehype-toc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJS-DevTools%2Frehype-toc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJS-DevTools%2Frehype-toc/lists"}