site: parse markdown only once

This commit is contained in:
Glen Huang
2025-10-08 10:50:34 +08:00
committed by Johannes Kirschbauer
parent c252dd7b47
commit 61baf0f6c3
3 changed files with 37 additions and 21 deletions

View File

@@ -14,8 +14,11 @@
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.43.2",
"@sveltejs/vite-plugin-svelte": "^6.2.0",
"hast-util-to-html": "^9.0.5",
"hastscript": "^9.0.1",
"mdast": "^2.3.2",
"mdast-util-from-markdown": "^2.0.2",
"mdast-util-to-hast": "^13.2.0",
"mdast-util-toc": "^7.1.0",
"mdsvex": "^0.12.6",
"prettier": "^3.6.2",
@@ -27,7 +30,6 @@
"remark-directive": "^4.0.0",
"remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.1",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.2",
"remark-stringify": "^11.0.0",
"remark-toc": "^9.0.0",

View File

@@ -20,8 +20,11 @@
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.43.2",
"@sveltejs/vite-plugin-svelte": "^6.2.0",
"hast-util-to-html": "^9.0.5",
"hastscript": "^9.0.1",
"mdast": "^2.3.2",
"mdast-util-from-markdown": "^2.0.2",
"mdast-util-to-hast": "^13.2.0",
"mdast-util-toc": "^7.1.0",
"mdsvex": "^0.12.6",
"prettier": "^3.6.2",
@@ -33,7 +36,6 @@
"remark-directive": "^4.0.0",
"remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.1",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.2",
"remark-stringify": "^11.0.0",
"remark-toc": "^9.0.0",

View File

@@ -1,7 +1,9 @@
import { matter } from "vfile-matter";
import { unified } from "unified";
import { unified, type Processor } from "unified";
import { VFile } from "vfile";
import remarkParse from "remark-parse";
import { fromMarkdown } from "mdast-util-from-markdown";
import { toHast } from "mdast-util-to-hast";
import { toHtml } from "hast-util-to-html";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";
import rehypeShiki from "@shikijs/rehype";
@@ -28,11 +30,9 @@ export default function (): PluginOption {
async transform(code, id) {
if (id.slice(-3) !== ".md") return;
// TODO: move VFile into unified
const file = new VFile(code);
matter(file, { strip: true });
const html = await unified()
const file = await unified()
.use(remarkParse)
.use(remarkToc)
.use(link_migration)
.use(remarkGfm)
.use(remarkDirective)
@@ -55,26 +55,38 @@ export default function (): PluginOption {
.use(rehypeStringify)
.use(rehypeSlug)
.use(rehypeAutolinkHeadings)
.process(String(file));
const parsed = await unified()
.use(remarkParse)
.use(() => (tree) => {
const result = toc(tree as Nodes);
return result.map;
})
.use(remarkRehype)
.use(rehypeStringify)
.process(String(file));
.process(code);
return `
export const content = ${JSON.stringify(String(html))};
export const content = ${JSON.stringify(String(file))};
export const frontmatter = ${JSON.stringify(file.data.matter)};
export const toc = ${JSON.stringify(String(parsed))};`;
export const toc = ${JSON.stringify(file.data.toc)};`;
},
};
}
function remarkParse(this: Processor) {
this.parser = (document, file) => {
matter(file, { strip: true });
return fromMarkdown(String(file));
};
}
function remarkToc() {
return (tree: Nodes, file: VFile) => {
const { map } = toc(tree);
if (!map) {
file.data.toc = "";
return;
}
// Remove the extranuous p element in each toc entry
map.spread = false;
map.children.forEach((child) => {
child.spread = false;
});
file.data.toc = toHtml(toHast(map));
};
}
// Needed according to:
// https://github.com/remarkjs/remark-directive
function styleDirectives() {