Files
rustycms/scripts/normalize-markdown-slugs.mjs

104 lines
3.3 KiB
JavaScript

#!/usr/bin/env node
/**
* Normalisiert alle Markdown-Dateien: _slug und Dateiname = "markdown-" + beschreibender Teil.
* - component-markdown-X → markdown-X
* - X-markdown / X-Markdown → markdown-X
* - markdown-X bleibt markdown-X (evtl. _ → -)
* - Sonstige → markdown-X
* Aktualisiert alle Referenzen in content/de.
*/
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const CONTENT_DE = path.join(__dirname, "..", "content", "de");
const MARKDOWN_DIR = path.join(CONTENT_DE, "markdown");
function normalize(base) {
let rest = base.replace(/_/g, "-").toLowerCase();
if (rest.startsWith("component-markdown-")) {
rest = rest.slice(19);
} else if (rest.startsWith("markdown-")) {
rest = rest.slice(9);
} else if (rest.endsWith("-markdown")) {
rest = rest.slice(0, -9);
} else {
// z. B. "energiequelle-...", "Page-blog-Markdown" -> schon lowercase "page-blog-markdown" -> rest = "page-blog"
if (rest.endsWith("-markdown")) rest = rest.slice(0, -9);
}
return "markdown-" + rest;
}
function parseJson5(str) {
try {
return JSON.parse(str);
} catch {
return null;
}
}
const files = fs.readdirSync(MARKDOWN_DIR).filter((f) => f.endsWith(".json5")).sort();
const oldToNew = new Map();
const used = new Set();
for (const file of files) {
const base = file.replace(/\.json5$/, "");
const raw = fs.readFileSync(path.join(MARKDOWN_DIR, file), "utf8");
const data = parseJson5(raw);
const oldSlug = data?._slug || base;
let newSlug = normalize(base);
let n = 0;
while (used.has(newSlug)) {
n++;
newSlug = normalize(base) + (n === 1 ? "-1" : "-" + n);
}
used.add(newSlug);
oldToNew.set(oldSlug, newSlug);
}
console.log("Markdown-Slug-Map (Anzahl:", oldToNew.size, ")");
for (const [oldSlug, newSlug] of oldToNew) {
if (oldSlug !== newSlug) console.log(" ", oldSlug, "→", newSlug);
}
for (const file of files) {
const base = file.replace(/\.json5$/, "");
const oldSlug = parseJson5(fs.readFileSync(path.join(MARKDOWN_DIR, file), "utf8"))?._slug || base;
const newSlug = oldToNew.get(oldSlug);
if (!newSlug) continue;
const filePath = path.join(MARKDOWN_DIR, file);
const data = parseJson5(fs.readFileSync(filePath, "utf8"));
data._slug = newSlug;
const newPath = path.join(MARKDOWN_DIR, newSlug + ".json5");
fs.writeFileSync(newPath, JSON.stringify(data, null, 2) + "\n", "utf8");
if (path.basename(newPath) !== file) fs.unlinkSync(filePath);
}
function walkDir(dir, fn) {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const e of entries) {
const full = path.join(dir, e.name);
if (e.isDirectory()) walkDir(full, fn);
else if (e.name.endsWith(".json5")) fn(full);
}
}
walkDir(CONTENT_DE, (filePath) => {
let content = fs.readFileSync(filePath, "utf8");
let changed = false;
for (const [oldSlug, newSlug] of oldToNew) {
if (oldSlug === newSlug) continue;
const escaped = oldSlug.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const newContent = content.replace(new RegExp('"' + escaped + '"', "g"), '"' + newSlug + '"');
if (newContent !== content) {
content = newContent;
changed = true;
}
}
if (changed) fs.writeFileSync(filePath, content, "utf8");
});
console.log("Fertig. Markdown-Slugs normalisiert und Referenzen aktualisiert.");