/** * Schreibt CHANGELOG.md aus src/lib/changelog.ts. * * node scripts/changelog.mjs erzeugen * node scripts/changelog.mjs --check nur prüfen, ob die Datei aktuell ist * * Warum erzeugt und nicht von Hand gepflegt: Die Anwendung zeigt denselben * Verlauf unter /version an. Zwei gepflegte Listen liefen unweigerlich * auseinander — und ein Changelog, der nicht stimmt, ist schlimmer als keiner. */ import { readFileSync, writeFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; const wurzel = join(dirname(fileURLToPath(import.meta.url)), ".."); const ziel = join(wurzel, "CHANGELOG.md"); /** * Die Quelle ist TypeScript, dieses Skript aber schlichtes Node. Statt einen * Übersetzer dazuzunehmen, wird der Datenteil gelesen und ausgewertet — er * besteht ausschließlich aus Zeichenketten und Listen. */ function ladeVerlauf() { const quelle = readFileSync(join(wurzel, "src", "lib", "changelog.ts"), "utf8"); const anfang = quelle.indexOf("export const CHANGELOG"); if (anfang === -1) throw new Error("CHANGELOG-Liste nicht gefunden."); const start = quelle.indexOf("[", anfang); const ende = quelle.indexOf("\n];", start); if (start === -1 || ende === -1) throw new Error("Liste nicht abgrenzbar."); const literal = quelle.slice(start, ende + 2); return Function(`"use strict"; return (${literal});`)(); } function formatiereDatum(iso) { const [jahr, monat, tag] = iso.split("-"); return `${tag}.${monat}.${jahr}`; } function baue(verlauf) { const zeilen = [ "# Änderungen", "", "Was in welcher Fassung dazugekommen ist. Dieselbe Liste steht in der", "Anwendung unter **Version und Änderungen**, erreichbar über die", "Versionsnummer in der Fußzeile.", "", "> Diese Datei wird erzeugt: `npm run changelog`.", "> Gepflegt wird der Verlauf in `src/lib/changelog.ts`.", "", ]; for (const eintrag of verlauf) { zeilen.push(`## ${eintrag.version} — ${formatiereDatum(eintrag.date)}`, ""); zeilen.push(eintrag.summary, ""); for (const änderung of eintrag.changes) zeilen.push(`- ${änderung}`); zeilen.push(""); } return zeilen.join("\n"); } const inhalt = baue(ladeVerlauf()); if (process.argv.includes("--check")) { let vorhanden = ""; try { vorhanden = readFileSync(ziel, "utf8"); } catch { console.error("CHANGELOG.md fehlt. Erzeugen mit: npm run changelog"); process.exit(1); } if (vorhanden !== inhalt) { console.error( "CHANGELOG.md passt nicht mehr zu src/lib/changelog.ts. Neu erzeugen mit: npm run changelog", ); process.exit(1); } console.log("CHANGELOG.md ist aktuell."); } else { writeFileSync(ziel, inhalt, "utf8"); console.log("CHANGELOG.md geschrieben."); }