@nuxtjs/mdc
Version:
Nuxt MDC module
60 lines (59 loc) • 2.19 kB
JavaScript
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("");
};