From cc1597e4c59f65e1ed1e8feca212162e1d97d152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?= Date: Sun, 13 Nov 2022 14:53:15 +0100 Subject: [PATCH] Add plugin for custom attributes on Markdown elements --- website/plugins/index.mjs | 4 +- website/plugins/remarkCustomAttrs.mjs | 78 +++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 website/plugins/remarkCustomAttrs.mjs diff --git a/website/plugins/index.mjs b/website/plugins/index.mjs index 660338e86..9a27e7767 100644 --- a/website/plugins/index.mjs +++ b/website/plugins/index.mjs @@ -1,3 +1,5 @@ -const remarkPlugins = [] +import remarkCustomAttrs from './remarkCustomAttrs.mjs' + +const remarkPlugins = [remarkCustomAttrs] export default remarkPlugins diff --git a/website/plugins/remarkCustomAttrs.mjs b/website/plugins/remarkCustomAttrs.mjs new file mode 100644 index 000000000..941368758 --- /dev/null +++ b/website/plugins/remarkCustomAttrs.mjs @@ -0,0 +1,78 @@ +const parseAstTree = (markdownAST) => { + markdownAST.children.map((node, index) => { + if (node.type !== 'heading' || !node.children || node.children < 2) { + return + } + + const indexLast = node.children.length - 1 + const lastNode = node.children[indexLast] + + if (lastNode.type !== 'mdxTextExpression' || !lastNode.data || !lastNode.data.estree) { + return + } + + const { estree } = lastNode.data + + if ( + estree.type !== 'Program' || + !estree.body || + estree.body.length <= 0 || + !estree.body[0] + ) { + return + } + + const estreeBodyFirstNode = estree.body[0] + + if ( + estreeBodyFirstNode.type !== 'ExpressionStatement' || + !estreeBodyFirstNode.expression || + estreeBodyFirstNode.expression.type !== 'SequenceExpression' + ) { + return + } + + const sequenceExpression = estreeBodyFirstNode.expression + + if (!sequenceExpression.expressions) { + return + } + + const attributes = sequenceExpression.expressions.map((expression) => { + if ( + expression.type !== 'AssignmentExpression' || + !expression.left || + !expression.right + ) { + return + } + + const { left, right } = expression + + if ( + left.type !== 'Identifier' || + right.type !== 'Literal' || + !left.name || + !right.value + ) { + return + } + + return { type: 'mdxJsxAttribute', name: left.name, value: right.value } + }) + + // This replaces the markdown heading with a JSX element + markdownAST.children[index] = { + type: 'mdxJsxFlowElement', + name: `h${node.depth}`, + attributes, + children: [node.children[0]], + } + }) + + return markdownAST +} + +const remarkCustomAttrs = () => parseAstTree + +export default remarkCustomAttrs