1
0
Fork 0
freesewing/sites/shared/mdx/mdx-plugin-toc.mjs
2023-06-17 17:36:41 +02:00

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
}
}