import { parse } from 'acorn'; import { visit } from 'unist-util-visit'; /** * @typedef {import('@types/mdast').Root} Root - https://github.com/syntax-tree/mdast#root * @typedef {import('@types/mdast').Heading} Heading - https://github.com/syntax-tree/mdast#heading */ /** * Find all headings within a MDX document, and export them as JS array. * This uses the MDAST's `heading` and tries to guess the children's content. * When the node has an ID, generated by `remark-slug`, the ID is added to the exported object. * * @param {object} options * @param {string} [options.exportName="headings"] */ export default function remarkExportHeadings(options = {}) { const { exportName = 'headings' } = options; /** @param {Root} tree */ return tree => { const headings = []; /** @param {Heading} node */ const visitor = node => { if (node.children.length > 0) { headings.push({ id: node.data?.id, depth: node.depth, type: node.children.find(node => node.type !== 'text')?.type || 'text', title: node.children.map(child => child.value).join(' '), }); } }; visit(tree, 'heading', visitor); tree.children.push({ type: 'mdxjsEsm', data: { estree: parse(`export const ${exportName} = ${JSON.stringify(headings)};`, { sourceType: 'module', ecmaVersion: 2022, }), }, }); }; }