68 lines
1.7 KiB
JavaScript
68 lines
1.7 KiB
JavaScript
import GithubSlugger from 'github-slugger'
|
|
|
|
const defaultOptions = {
|
|
maxDepth: 4,
|
|
}
|
|
|
|
const nodeAsTocEntry = (node, slugger) => ({
|
|
text: node.children[0].value,
|
|
level: node.depth,
|
|
slug: slugger.slug(node.children[0].value),
|
|
})
|
|
|
|
const extractToc = (node, options, slugger) => {
|
|
const toc = []
|
|
for (const el of node.children.filter((node) => node.type === 'heading')) {
|
|
if (el.depth <= options.maxDepth) toc.push(nodeAsTocEntry(el, slugger))
|
|
}
|
|
|
|
return toc
|
|
}
|
|
|
|
const asObjectPropertyString = (key, val) => ({
|
|
type: 'Property',
|
|
method: false,
|
|
shorthand: false,
|
|
computed: false,
|
|
kind: 'init',
|
|
key: { type: 'Literal', value: key },
|
|
value: { type: 'Literal', value: val },
|
|
})
|
|
|
|
const tocAsProperty = (toc) => ({
|
|
type: 'Property',
|
|
method: false,
|
|
shorthand: false,
|
|
computed: false,
|
|
kind: 'init',
|
|
key: { type: 'Literal', value: 'toc' },
|
|
value: {
|
|
type: 'ArrayExpression',
|
|
elements: toc.map((entry) => ({
|
|
type: 'ObjectExpression',
|
|
properties: [
|
|
asObjectPropertyString('title', entry.text || 'FIXME: Title not found in toc'),
|
|
asObjectPropertyString('level', entry.level),
|
|
asObjectPropertyString('slug', entry.slug),
|
|
],
|
|
})),
|
|
},
|
|
})
|
|
|
|
export default function mdxToc(options = {}) {
|
|
return (node) => {
|
|
const slugger = new GithubSlugger()
|
|
options = { ...defaultOptions, options }
|
|
const esm = node.children.filter((child) => child.type === 'mdxjsEsm')
|
|
if (
|
|
esm &&
|
|
esm.length === 1 &&
|
|
esm[0].data?.estree?.body?.[0]?.declaration?.declarations?.[0]?.init?.properties
|
|
)
|
|
esm[0].data.estree.body[0].declaration.declarations[0].init.properties.push(
|
|
tocAsProperty(extractToc(node, options, slugger))
|
|
)
|
|
|
|
return node
|
|
}
|
|
}
|