UNPKG

@nuxtjs/mdc

Version:
60 lines (59 loc) 2.19 kB
import { visit } from "unist-util-visit"; import { toString } from "hast-util-to-string"; export default rehypeHighlight; export function rehypeHighlight(opts) { const options = opts; return async (tree) => { const tasks = []; const styles = []; visit( tree, (_node) => { const node = _node; if (!["pre", "code"].includes(node.tagName)) { return false; } const hasHighlightableLanguage = node.properties?.language !== void 0 && node.properties?.language !== "text"; const hasHighlightableLines = Boolean(node.properties?.highlights); return hasHighlightableLanguage || hasHighlightableLines; }, (node) => { const _node = node; const highlights = typeof _node.properties.highlights === "string" ? _node.properties.highlights.split(/[,\s]+/).map(Number) : Array.isArray(_node.properties.highlights) ? _node.properties.highlights.map(Number) : []; const task = options.highlighter( toString(node), _node.properties.language, options.theme, { highlights: highlights.filter(Boolean), meta: _node.properties.meta } ).then(({ tree: tree2, className, style, inlineStyle }) => { _node.properties.className = ((_node.properties.className || "") + " " + className).trim(); _node.properties.style = ((_node.properties.style || "") + " " + inlineStyle).trim(); if (_node.children[0]?.tagName === "code") { _node.children[0].children = tree2; } else { _node.children = tree2[0].children || tree2; } if (style) styles.push(style); }); tasks.push(task); } ); if (tasks.length) { await Promise.all(tasks); tree.children.push({ type: "element", tagName: "style", children: [{ type: "text", value: cleanCSS(styles.join("")) }], properties: {} }); } }; } const cleanCSS = (css) => { const styles = css.split("}").filter((s) => Boolean(s.trim())).map((s) => s.trim() + "}"); return Array.from(new Set(styles)).join(""); };