1
0
Fork 0
freesewing/sites/shared/mdx/remark-intro-as-frontmatter.mjs
2023-10-09 13:47:36 +02:00

59 lines
1.9 KiB
JavaScript

/*
* This is a remark plugin that will pull the (text of the)
* first few paragraph out of a markdown document and add it
* as the `lead` field in the documents's frontmatter.
*
* It will only do anything if the document has frontmatter.
* It also places this in the *lead* frontmatter key so that
* people can manually specify a *intro* key that will take
* precendence.
*
* I wrote this specifically to pull the intro out of our
* markdown content for SEO and open graph.
* I'm not publishing this as a proper remark plugin because
* while this works for our use-cases, it may or may not
* work for the many different ways people use markdown and
* remark out there.
*/
const extractIntro = (node) => {
const intro = []
for (const el of node.children.filter((node) => node.type === 'paragraph').slice(0, 3)) {
for (const child of el.children) {
if (child.type === 'text' && child.value) intro.push(child.value)
else if (['link', 'strong', 'emphasis'].includes(child.type) && child.children) {
for (const grandchild of child.children) {
if (grandchild.type === 'text' && grandchild.value) intro.push(grandchild.value)
}
}
}
}
return intro.length < 1 ? 'FIXME -- No intro found' : intro.join('')
}
const introAsProperty = (intro) => ({
type: 'Property',
method: false,
shorthand: false,
computed: false,
kind: 'init',
key: { type: 'Literal', value: 'lead' },
value: { type: 'Literal', value: intro },
})
export function remarkIntroAsFrontmatter() {
return (node) => {
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(
introAsProperty(extractIntro(node))
)
return node
}
}