123 lines
3.3 KiB
TypeScript
123 lines
3.3 KiB
TypeScript
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { bench, describe } from "vitest";
|
|
import { lezerToParseTree } from "../../client/markdown_parser/parse_tree.ts";
|
|
import {
|
|
extendedMarkdownLanguage,
|
|
parseMarkdown,
|
|
} from "../../client/markdown_parser/parser.ts";
|
|
import {
|
|
addParentPointers,
|
|
cloneTree,
|
|
collectNodesMatching,
|
|
collectNodesOfType,
|
|
findNodeOfType,
|
|
type ParseTree,
|
|
removeParentPointers,
|
|
renderToText,
|
|
replaceNodesMatching,
|
|
traverseTree,
|
|
} from "./tree.ts";
|
|
|
|
// --- Load all docs markdown files ---
|
|
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
const docsDir = join(__dirname, "../../docs");
|
|
|
|
type PageData = {
|
|
name: string;
|
|
text: string;
|
|
};
|
|
|
|
function loadMarkdownFiles(dir: string, base = ""): PageData[] {
|
|
const pages: PageData[] = [];
|
|
for (const entry of readdirSync(dir)) {
|
|
const fullPath = join(dir, entry);
|
|
const relativePath = base ? `${base}/${entry}` : entry;
|
|
const stat = statSync(fullPath);
|
|
if (stat.isDirectory()) {
|
|
pages.push(...loadMarkdownFiles(fullPath, relativePath));
|
|
} else if (entry.endsWith(".md")) {
|
|
pages.push({
|
|
name: relativePath.replace(/\.md$/, ""),
|
|
text: readFileSync(fullPath, "utf-8"),
|
|
});
|
|
}
|
|
}
|
|
return pages;
|
|
}
|
|
|
|
const pages = loadMarkdownFiles(docsDir);
|
|
|
|
// Pre-parse trees for tree-operation benchmarks
|
|
const parsedTrees: ParseTree[] = pages.map((p) => parseMarkdown(p.text));
|
|
|
|
describe("Tree API Benchmarks", () => {
|
|
bench("lezerToParseTree (all pages)", () => {
|
|
for (const p of pages) {
|
|
// Remove \r like parse() does, then run lezer + conversion
|
|
const text = p.text.replaceAll("\r", "");
|
|
const lezerTree = extendedMarkdownLanguage.parser.parse(text);
|
|
lezerToParseTree(text, lezerTree.topNode);
|
|
}
|
|
});
|
|
|
|
bench("addParentPointers (all pages)", () => {
|
|
for (const tree of parsedTrees) {
|
|
addParentPointers(tree);
|
|
}
|
|
});
|
|
|
|
bench("removeParentPointers (all pages)", () => {
|
|
// First add them so we can remove them
|
|
for (const tree of parsedTrees) {
|
|
addParentPointers(tree);
|
|
}
|
|
for (const tree of parsedTrees) {
|
|
removeParentPointers(tree);
|
|
}
|
|
});
|
|
|
|
bench("collectNodesOfType (all pages, 'WikiLink')", () => {
|
|
for (const tree of parsedTrees) {
|
|
collectNodesOfType(tree, "WikiLink");
|
|
}
|
|
});
|
|
|
|
bench("collectNodesMatching (all pages, ATXHeading*)", () => {
|
|
for (const tree of parsedTrees) {
|
|
collectNodesMatching(tree, (n) => !!n.type?.startsWith("ATXHeading"));
|
|
}
|
|
});
|
|
|
|
bench("findNodeOfType (all pages, 'FrontMatter')", () => {
|
|
for (const tree of parsedTrees) {
|
|
findNodeOfType(tree, "FrontMatter");
|
|
}
|
|
});
|
|
|
|
bench("traverseTree (all pages, full walk)", () => {
|
|
for (const tree of parsedTrees) {
|
|
traverseTree(tree, (_n) => false);
|
|
}
|
|
});
|
|
|
|
bench("replaceNodesMatching (all pages, no-op)", () => {
|
|
for (const tree of parsedTrees) {
|
|
replaceNodesMatching(tree, (_n) => undefined);
|
|
}
|
|
});
|
|
|
|
bench("renderToText (all pages)", () => {
|
|
for (const tree of parsedTrees) {
|
|
renderToText(tree);
|
|
}
|
|
});
|
|
|
|
bench("cloneTree (all pages)", () => {
|
|
for (const tree of parsedTrees) {
|
|
cloneTree(tree);
|
|
}
|
|
});
|
|
});
|