kentcdodds / mdx-bundler

🦤 Give me MDX/TSX strings and I'll give you back a component you can render. Supports imports!
MIT License
1.77k stars 75 forks source link

to generate a table of contents #203

Open monsterooo opened 1 year ago

monsterooo commented 1 year ago

Problem description:

Thanks to a great project like mdx-bundler that helped me reduce my development workload.

I want to create a directory of articles in mdx-bundler, but so far I haven't found a way to do it. I don't know if you have any ideas

I found an article, but I don't know how to do it in mdx-bundler

A huge thank you

Owen-Tsai commented 1 year ago

Go ahead and check this config option, you can load up remark and rehype plugins for generating TOC. If I remembered right, remark-extract-toc is able to extract TOC (and export it as a named object) from the .mdx file.

Then you might need to access the named exports. You can check this section for details.

Alternatively, implement a plugin yourself is not that hard. Try the following code:

import { visit } from 'unist-util-visit'
import { slug } from 'github-slugger'
import { toString } from 'mdast-util-to-string'

const remarkToc = (options) => {
  return (tree) => visit(tree, 'heading', (node, index, parent) => {
    const text= toString(node)
    options.exportRef.push({
      text,
      url: `#${slug(text)}`,
      depth: node.depth
    })
  })
}

export default remarkToc

Import remarkToc and load it to the plugins list:

const toc = []

const { code } = await bundleMDX({
  // ...other options
  mdxOptions: (options, frontmatter) => {
      options.remarkPlugins = [
        ...(options.remarkPlugins || []),
        [remarkToc, {
          exportRef: toc
        }],
      ]
    return options
  }
})

// now you can use `toc` to render the table of contents!

The structure of toc is what we described in the remarkToc plugin. It looks like this:

[{
  text: "一级标题",
  url: "#一级标题",
  depth: 1
}, {
  text: "second level heading",
  url: "#second-level-heading",
  depth: 2
}, {
  text: "中英文混排 heading",
  url: "#中英文混排-heading",
  depth: 1
}]