30 lines
1.7 KiB
JavaScript
30 lines
1.7 KiB
JavaScript
// Prototype of the splice idea: top-level blocks with source line ranges from markdown-it token maps.
|
|
// Checks that gaps + blocks reassemble every file byte for byte, and counts block kinds.
|
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
import { pathToFileURL } from "node:url";
|
|
const md = (await import(pathToFileURL(process.argv[2]).href)).default;
|
|
const root = process.argv[3];
|
|
const files = readFileSync(process.argv[4], "utf8").split("\n").filter(Boolean);
|
|
const mi = md("commonmark", { html: true }).enable("table").enable("strikethrough");
|
|
const kinds = new Map(); let ok = 0, bad = [], total = 0, fm = 0;
|
|
for (const f of files) {
|
|
const src = readFileSync(root + "/" + f, "utf8");
|
|
const lines = src.split("\n"); // keep \r on lines; join restores exact bytes
|
|
const toks = mi.parse(src, {});
|
|
const blocks = [];
|
|
for (const t of toks) if (t.level === 0 && t.map && (t.nesting === 1 || t.nesting === 0)) blocks.push({ type: t.type.replace(/_open$/, ""), from: t.map[0], to: t.map[1] });
|
|
let out = [], cursor = 0;
|
|
for (const b of blocks) {
|
|
if (b.from < cursor) { bad.push(f + " overlap"); break; }
|
|
out.push(lines.slice(cursor, b.from).join("\n") + (b.from > cursor ? "\n" : "")); // gap
|
|
out.push(lines.slice(b.from, b.to).join("\n") + (b.to < lines.length ? "\n" : "")); // block
|
|
cursor = b.to;
|
|
total++; kinds.set(b.type, (kinds.get(b.type) ?? 0) + 1);
|
|
}
|
|
out.push(lines.slice(cursor).join("\n"));
|
|
if (out.join("") === src) ok++; else bad.push(f);
|
|
if (/^---\r?\n[\s\S]*?\n---\r?\n/.test(src)) fm++;
|
|
}
|
|
console.log({ files: files.length, reassembledExactly: ok, bad: bad.slice(0, 5), topLevelBlocks: total, withFrontMatter: fm });
|
|
console.log([...kinds].sort((a, b) => b[1] - a[1]).map(([k, n]) => k + "=" + n).join(" "));
|