remark-subtitle

node v12.22.12
version: 2.0.0
endpointsharetweet
// These `unist-util-*` utilities are super useful when work with // unified-compatible syntax trees const is = require("unist-util-is"); const visit = require("unist-util-visit"); // We're going to need this to convert some mdast nodes to hast nodes later on const mdastToHast = require("mdast-util-to-hast"); // Our plugin's constructor function. This would receive configuration options. function subtitlePlugin() { // Plugins need to return a transform function that takes a unified compatable // AST and manipulate or walk it. return async function transform(tree) { // Go through the markdown document (in mdast form) and call my callback // whenever you see paragraph nodes. visit(tree, "paragraph", (paragraphNode) => { const { children } = paragraphNode; // Get the first child node under the paragraph and make sure it's a text // node. If it's not, skip processing this paragraph node. const textNode = children && children[0]; if (!is(textNode, "text")) { return; } // Does this text node start with a sequence of hash ('#') signs followed // by a dash ('-')? const text = typeof textNode.value === "string" ? textNode.value.trimLeft() : ""; const re = /^(#{1,6})-\s+/; const matches = text.match(re); if (typeof text === "string" && !matches) { return; } // If it did let's count the number of '#'s as that will be our subtitle // depth const depth = matches[1].length; // Once we have what we need, let's make a copy of this text node without // the leading subtitle syntax. // i.e. '##- hello world' becomes 'hello world' const newValue = text.replace(re, ""); // We can now attach some metadata to an mdast node. If the node is being // serialized to html by a hast-compatible library, it will know to use // these overrides instead of the default behaviour of rendering a plain // <p> tag. paragraphNode.data = { // we could use a different html tag but "p" is semantically correct for // the subtitle hName: "p", // The <p> tag will have the following attributes added to it. // Note that we need to use "className" for the html "class" attribute. hProperties: { className: `subtitle subtitle--${depth}`, "data-remark-subtype": "subtitle", "data-subtitle": depth, }, // When we are passing custom children, it is our responsibility to make // sure they are in hast format instead of mdast. We use the library, // mdast-util-to-hast, to do this conversion. hChildren: [ // We pass in a modified text node without the leading subtitle // characters { ...textNode, value: newValue, }, // Then we pass in the rest of the children under this paragraph node ...children.slice(1), ].map(mdastToHast), // Finally convert it all to hast }; }); }; }; // === Our pipeline === // A markdown parser that spits out mdast const remark = require("remark"); // An mdast to html serializer const html = require("remark-html"); const text = ` # Hello ###- How are __you__? Great!`; remark() .use(subtitlePlugin) // the plugin we'll write .use(html) .process(text /* markdown in */, function (err, file) { if (err) throw err; console.log(String(file)); /* html out */ });
Loading…

no comments

    sign in to comment