NASA Proceeds to Mars

    remark-toc
    TypeScript icon, indicating that this package has built-in type declarations

    8.0.1 • Public • Published

    remark-toc

    Build Coverage Downloads Size Sponsors Backers Chat

    remark plugin to generate a table of contents.

    Contents

    What is this?

    This package is a unified (remark) plugin to generate a table of contents of the document such as the one above.

    unified is a project that transforms content with abstract syntax trees (ASTs). remark adds support for markdown to unified. mdast is the markdown AST that remark uses. This is a remark plugin that transforms mdast.

    When should I use this?

    This project is useful when authors are writing docs in markdown that are sometimes quite long and hence would benefit from automated overviews inside them. It is assumed that headings define the structure of documents and that they can be linked to. When this plugin is used, authors can add a certain heading (say, ## Contents) to documents and this plugin will populate those sections with lists that link to all following sections.

    GitHub and similar services automatically add IDs (and anchors that link-to-self) to headings. You can add similar features when combining remark with rehype through remark-rehype after this plugin. Then it’s possible to use the rehype plugins rehype-slug (for IDs on headings) and rehype-autolink-headings (for anchors that link-to-self).

    This plugin does not generate a table of contents for the whole document or expose it to other plugins. You can use the underlying mdast utility mdast-util-toc and create a plugin yourself to do that and more.

    Install

    This package is ESM only. In Node.js (version 12.20+, 14.14+, or 16.0+), install with npm:

    npm install remark-toc

    In Deno with Skypack:

    import remarkToc from 'https://cdn.skypack.dev/remark-toc@8?dts'

    In browsers with Skypack:

    <script type="module">
      import remarkToc from 'https://cdn.skypack.dev/remark-toc@8?min'
    </script>

    Use

    Say we have the following file, example.md:

    # Alpha
    
    ## Table of contents
    
    ## Bravo
    
    ### Charlie
    
    ## Delta

    And our module, example.js, looks as follows:

    import {read} from 'to-vfile'
    import {remark} from 'remark'
    import remarkToc from 'remark-toc'
    
    main()
    
    async function main() {
      const file = await remark()
        .use(remarkToc)
        .process(await read('example.md'))
    
      console.log(String(file))
    }

    Now, running node example yields:

    # Alpha
    
    ## Table of contents
    
    *   [Bravo](#bravo)
    
        *   [Charlie](#charlie)
    
    *   [Delta](#delta)
    
    ## Bravo
    
    ### Charlie
    
    ## Delta

    API

    This package exports no identifiers. The default export is remarkToc.

    unified().use(remarkToc[, options])

    Generate a table of contents. Looks for a certain heading, removes everything between it and an equal or higher heading, and replaces that with a list representing the document structure, linking to all further headings.

    options

    Configuration (optional).

    options.heading

    Pattern text of heading to look for (string, default: 'toc|table[ -]of[ -]contents?'). Wrapped in new RegExp('^(' + options.heading + ')$', 'i'), so it’s case-insensitive and matches the whole heading text.

    options.skip

    Pattern text of headings to exclude from the generated list (string, optional). Wrapped in new RegExp('^(' + options.skip + ')$', 'i'), so it’s case-insensitive and matches whole heading texts.

    options.maxDepth

    Maximum heading depth to include in the generated list (number?, default: 6). This is inclusive: when set to 3, headings with a rank of 3 are included (those with three hashes: ###).

    options.tight

    Whether to compile list items tightly (boolean?, default: false). The default is to add space around items.

    options.ordered

    Whether to compile list items as an ordered list (boolean?, default: false). The default is to use an unordered list.

    options.prefix

    String to prepend before links to headings (string?, default: null, example: 'user-content-'). This is useful when combining remark with rehype through remark-rehype after this plugin, and using rehype-sanitize to prevent DOM clobbering of user generated markdown.

    options.parents

    Parents (such as block quotes and lists) of headings to include in the generated list (is-compatible test, default: the root node). By default only top level headings are used. Pass ['root', 'blockquote'] to also link to headings in block quotes.

    Examples

    Example: a different heading

    The option heading can be set to search for a different heading. The example from before can be changed to search for different headings like so:

    @@ -6,7 +6,7 @@ main()
    
     async function main() {
       const file = await remark()
    -    .use(remarkToc)
    +    .use(remarkToc, {heading: 'contents'})
         .process(await read('example.md'))
    
       console.log(String(file))

    …that would search for Contents (case-insensitive) headings.

    Example: ordered, tight list

    The options ordered and tight can be turned on to change the list. The example from before can be changed to generate a tight, ordered list like so:

    @@ -6,7 +6,10 @@ main()
    
     async function main() {
       const file = await remark()
    -    .use(remarkToc)
    +    .use(remarkToc, {tight: true, ordered: true})
         .process(await read('example.md'))
    
       console.log(String(file))

    …that would generate the following list:

    1.  [Bravo](#bravo)
        1.  [Charlie](#charlie)
    2.  [Delta](#delta)

    Example: including and excluding headings

    The options maxDepth, skip, and parents can be used to include and exclude certain headings from list. The example from before can be changed to generate a tight, ordered list like so:

    @@ -6,7 +6,10 @@ main()
    
     async function main() {
       const file = await remark()
    -    .use(remarkToc)
    +    .use(remarkToc, {maxDepth: 3, skip: 'delta', parents: ['root', 'listItem']})
         .process(await read('example.md'))
    
       console.log(String(file))

    …that would exclude level 4, 5, and 6 headings, exclude headings of delta (case-insensitive, full match), and include headings directly in a list item.

    Example: adding a prefix

    The option prefix can set to prepend a string to all links to headings in the generated list:

    @@ -6,7 +6,10 @@ main()
    
     async function main() {
       const file = await remark()
    -    .use(remarkToc)
    +    .use(remarkToc, {prefix: 'user-content-'})
         .process(await read('example.md'))
    
       console.log(String(file))

    …that would generate the following list:

    *   [Bravo](#user-content-bravo)
    
        *   [Charlie](#user-content-charlie)
    
    *   [Delta](#user-content-delta)

    Types

    This package is fully typed with TypeScript. It exports an Options type, which specifies the interface of the accepted options.

    Compatibility

    Projects maintained by the unified collective are compatible with all maintained versions of Node.js. As of now, that is Node.js 12.20+, 14.14+, and 16.0+. Our projects sometimes work with older versions, but this is not guaranteed.

    This plugin works with unified version 3+ and remark version 4+.

    Security

    Use of remark-toc involves user content and changes the tree, so it can open you up for a cross-site scripting (XSS) attack.

    Existing nodes are copied into the table of contents. The following example shows how an existing script is copied into the table of contents.

    The following markdown:

    # Table of Contents
    
    ## Bravo<script>alert(1)</script>
    
    ## Charlie

    Yields:

    # Table of Contents
    
    -   [Bravo<script>alert(1)</script>](#bravoscriptalert1script)
    -   [Charlie](#charlie)
    
    ## Bravo<script>alert(1)</script>
    
    ## Charlie

    This may become a problem if the markdown is later transformed to rehype (hast) or opened in an unsafe markdown viewer.

    Related

    Contribute

    See contributing.md in remarkjs/.github for ways to get started. See support.md for ways to get help.

    This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.

    License

    MIT © Titus Wormer

    Install

    npm i remark-toc

    DownloadsWeekly Downloads

    97,301

    Version

    8.0.1

    License

    MIT

    Unpacked Size

    16.8 kB

    Total Files

    5

    Last publish

    Collaborators

    • johno
    • wooorm