Files
suaveplan/scripts/lint/clean-stacked-end-markers.ts
2026-05-27 23:47:53 +01:00

77 lines
2.7 KiB
TypeScript

#!/usr/bin/env bun
/**
* One-shot cleanup: strips stacked `<!-- end:auto-docs -->` markers from
* every .md file in packages/. Keeps the first end marker after each begin
* marker and removes any additional end markers that follow before the next
* begin marker (or end-of-file).
*
* Why this exists: an earlier doc-generator bug accumulated trailing
* `<!-- end:auto-docs -->` markers across runs. Once stacked, the current
* generator's replace-between-markers logic preserves them on subsequent
* runs (it picks the FIRST end and concatenates everything after it
* verbatim). This script normalises the existing corruption.
*/
import { readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
import { join } from "node:path";
const BEGIN = "<!-- begin:auto-docs -->";
const END = "<!-- end:auto-docs -->";
function walkMd(dir: string): string[] {
const out: string[] = [];
for (const name of readdirSync(dir)) {
const full = join(dir, name);
const s = statSync(full);
if (s.isDirectory()) {
if (name === "node_modules" || name === "dist" || name === ".turbo")
continue;
out.push(...walkMd(full));
} else if (name.endsWith(".md")) {
out.push(full);
}
}
return out;
}
function clean(src: string): string {
// Split on BEGIN markers; for each section after a BEGIN, keep content up
// to and including the first END marker, then strip any additional END
// markers (and any whitespace/newlines immediately surrounding them)
// before the next BEGIN.
const parts = src.split(BEGIN);
if (parts.length === 1) return src; // no markers, untouched
const out: string[] = [parts[0] as string];
for (let i = 1; i < parts.length; i++) {
const section = parts[i] as string;
const endIdx = section.indexOf(END);
if (endIdx === -1) {
out.push(BEGIN + section);
continue;
}
const head = section.slice(0, endIdx + END.length);
let tail = section.slice(endIdx + END.length);
// Strip any further END markers (with optional surrounding whitespace
// or trailing-spaces-then-newline) until the next BEGIN or EOF.
tail = tail.replace(/(?:[ \t]*<!-- end:auto-docs -->[ \t]*\n?)+/g, "");
out.push(BEGIN + head + tail);
}
return out.join("");
}
function main(): void {
const files = walkMd("packages");
let changed = 0;
for (const file of files) {
const src = readFileSync(file, "utf8");
const next = clean(src);
if (next !== src) {
writeFileSync(file, next);
changed++;
}
}
console.log(`Cleaned ${changed} .md files.`);
}
main();