@sveltek/unplugins
Version:
Sveltek's Unified plugins for Markdown preprocessor.
79 lines (75 loc) • 2.41 kB
JavaScript
import { visit } from 'unist-util-visit';
const remarkToc = (options = {}) => {
const { depth = 3, links = true } = options;
return (tree, vfile) => {
const frontmatter = vfile.data.frontmatter;
const toc = [];
let i = 0;
visit(tree, "heading", (node) => {
const [child] = node.children;
let value = "";
let id = "";
if (child.type === "text") {
value = child.value;
id = value.toLowerCase().replace(/[^a-z0-9\s-]/g, "").trim().replace(/\s+/g, "-");
}
if (links) {
node.children = [];
node.children.push({
type: "link",
url: `#${id}`,
children: [{ type: "text", value }]
});
}
const data = node.data || (node.data = {});
const props = data.hProperties || (data.hProperties = {});
if (node.depth > 1 && node.depth <= depth) {
if (toc.some((h) => h.id === id)) id = `${id}-${i + 1}`;
if (!props.id) props.id = id;
toc.push({ id, depth: node.depth, value });
}
});
frontmatter.toc = toc;
};
};
const rehypeShiki = function(options = {}) {
const {
theme,
themes,
langs,
highlighter,
codeToHtml: codeHtml,
root = (node) => {
node.tagName = "div";
}
} = options;
const defaultTheme = theme || "github-dark-default";
const defaultLangs = langs || ["javascript", "typescript", "svelte"];
return async (tree, file) => {
const { rehypeHighlight } = await import('@sveltek/markdown');
const { getSingletonHighlighter } = await import('shiki');
const shikiHighlighter = getSingletonHighlighter({
...highlighter,
themes: highlighter?.themes || themes && Object.values(themes) || [defaultTheme],
langs: highlighter?.langs || defaultLangs
});
const { codeToHtml } = await shikiHighlighter;
const highlightOptions = {
highlighter: async ({ code, lang, meta }) => {
options.parseMeta?.(meta);
if (code) {
return codeToHtml(code, {
...codeHtml,
lang: lang || "text",
...themes ? { themes: codeHtml?.themes || themes } : { theme: codeHtml?.theme || defaultTheme }
});
}
},
root
};
const transformer = rehypeHighlight.call(this, highlightOptions);
return transformer?.(tree, file, () => {
});
};
};
export { rehypeShiki, remarkToc };