Files

30 lines
2.4 KiB
JavaScript

// Per-block round trip: parse each top-level block's own source and serialise it again.
import { readFileSync } from "node:fs";
import { pathToFileURL } from "node:url";
const [, , pmdist, mdindex, root, list] = process.argv;
const PM = await import(pathToFileURL(pmdist).href);
const MarkdownIt = (await import(pathToFileURL(mdindex).href)).default;
const { MarkdownParser, MarkdownSerializer, defaultMarkdownParser: D, defaultMarkdownSerializer: S, schema } = PM;
const tokenizer = MarkdownIt("commonmark", { html: false });
const keepWraps = { parse(text, env) { const ts = tokenizer.parse(text, env); for (const t of ts) if (t.children) for (const c of t.children) if (c.type === "softbreak") { c.type = "text"; c.content = "\n"; } return ts; } };
const P2 = new MarkdownParser(schema, keepWraps, D.tokens);
const S2 = new MarkdownSerializer({ ...S.nodes, bullet_list(state, node) { state.renderList(node, " ", () => "- "); } }, S.marks);
const mi = MarkdownIt("commonmark", { html: true }).enable("table");
const stat = {}; const bump = (k, v) => { const s = (stat[k] ??= { n: 0, stock: 0, fixed: 0 }); s.n++; if (v.stock) s.stock++; if (v.fixed) s.fixed++; };
for (const f of readFileSync(list, "utf8").split("\n").filter(Boolean)) {
const src = readFileSync(`${root}/${f}`, "utf8"), lines = src.split("\n");
for (const t of mi.parse(src, {})) {
if (t.level !== 0 || !t.map || t.nesting === -1) continue;
const kind = t.type.replace(/_open$/, "");
if (!["paragraph", "heading", "bullet_list", "ordered_list", "fence", "blockquote", "code_block"].includes(kind)) continue;
const text = lines.slice(t.map[0], t.map[1]).join("\n").replace(/\n+$/, "");
let a = false, b = false;
try { a = S.serialize(D.parse(text)) === text; } catch {}
try { b = S2.serialize(P2.parse(text)) === text; } catch {}
bump(kind, { stock: a, fixed: b });
}
}
let N = 0, A = 0, B = 0;
for (const [k, s] of Object.entries(stat)) { N += s.n; A += s.stock; B += s.fixed; console.log(k.padEnd(13), String(s.n).padStart(5), "stock exact", String(s.stock).padStart(5), (100 * s.stock / s.n).toFixed(0) + "%", " wraps+dash exact", String(s.fixed).padStart(5), (100 * s.fixed / s.n).toFixed(0) + "%"); }
console.log("ALL".padEnd(13), String(N).padStart(5), "stock exact", String(A).padStart(5), (100 * A / N).toFixed(0) + "%", " wraps+dash exact", String(B).padStart(5), (100 * B / N).toFixed(0) + "%");