35 lines
2.0 KiB
JavaScript
35 lines
2.0 KiB
JavaScript
import { readFileSync } from "node:fs";
|
|
const rows = JSON.parse(readFileSync(process.argv[2], "utf8"));
|
|
const root = process.argv[3];
|
|
let ident = 0, nl = 0, other = 0, totalLines = 0, changedLines = 0;
|
|
const classes = new Map();
|
|
const bump = (k, f) => { const c = classes.get(k) ?? { n: 0, files: new Set() }; c.n++; c.files.add(f); classes.set(k, c); };
|
|
for (const r of rows) {
|
|
const src = readFileSync(root + "/" + r.file, "utf8");
|
|
const a = src.split("\n"), b = r.once.split("\n");
|
|
totalLines += a.length;
|
|
if (r.once === src) { ident++; continue; }
|
|
if (r.once === src.replace(/\n+$/, "") || r.once + "\n" === src) { nl++; continue; }
|
|
other++;
|
|
// line-level classification via simple LCS-free heuristic: compare sets
|
|
const bs = new Set(b);
|
|
for (const l of a) if (!bs.has(l)) {
|
|
changedLines++;
|
|
if (/^\s*- /.test(l)) bump("bullet - rewritten (to *)", r.file);
|
|
else if (/^\s*\|/.test(l) || /^\|?[-: |]+\|?$/.test(l)) bump("table row", r.file);
|
|
else if (/^(-{3,}|\*{3,}|_{3,})\s*$/.test(l)) bump("thematic break", r.file);
|
|
else if (/^\s*<[\w!/]/.test(l)) bump("html line", r.file);
|
|
else if (/^\s*```/.test(l)) bump("code fence line", r.file);
|
|
else if (/^#{1,6} /.test(l)) bump("heading line", r.file);
|
|
else if (/^\s*\d+[.)] /.test(l)) bump("ordered item line", r.file);
|
|
else if (/^\s*>/.test(l)) bump("quote line", r.file);
|
|
else if (/[_]/.test(l) && /\*/.test(l) === false) bump("prose with _ (emphasis or escaped)", r.file);
|
|
else if (/ {2,}$/.test(l) || /\\$/.test(l)) bump("hard break", r.file);
|
|
else if (/\[[^\]]*\]\([^)]*\)|\[[^\]]*\]\[/.test(l)) bump("link line", r.file);
|
|
else if (/[*`\\\[\]<>|&]/.test(l)) bump("prose with markup chars (escapes)", r.file);
|
|
else bump("plain prose line (wrap, blank, spacing)", r.file);
|
|
}
|
|
}
|
|
console.log({ files: rows.length, identical: ident, onlyTrailingNewline: nl, otherDiffs: other, totalLines, linesNotInOutput: changedLines });
|
|
for (const [k, c] of [...classes].sort((x, y) => y[1].n - x[1].n)) console.log(String(c.n).padStart(6), String(c.files.size).padStart(4), "files ", k);
|