/** * Bezeichner für die öffentliche URL /erklaerung/. * * Gleiche Regel wie in `lib/slug.ts`, damit Dateinamen unter data/policies/, * Importe und URLs übereinstimmen. */ function slugify(value) { return String(value) // Zusammengesetzte Zeichen vereinheitlichen: Aus PDFs kommt "ä" oft als // "a" plus Trema-Zeichen, das die Ersetzungen unten sonst nicht treffen. .normalize("NFC") .toLowerCase() .replace(/ä/g, "ae").replace(/ö/g, "oe").replace(/ü/g, "ue").replace(/ß/g, "ss") .replace(/[^a-z0-9]+/g, "-") .replace(/^-|-$/g, "") .slice(0, 60) } /** Hängt bei Kollision `-2`, `-3`, … an, bis der Bezeichner frei ist. */ function uniqueSlug(value, vergeben) { const basis = slugify(value) || "erklaerung" if (!vergeben.has(basis)) return basis let zaehler = 2 while (vergeben.has(`${basis}-${zaehler}`)) zaehler++ return `${basis}-${zaehler}` } /** * Bestimmt den Bezeichner beim Import. Ein bestehender Datensatz behält seinen, * solange der Titel unverändert ist – veröffentlichte Links bleiben gültig. */ async function resolveSlug(prisma, title, existing) { if (existing && existing.title.trim() === String(title).trim()) { return existing.slug } const rows = await prisma.privacyPolicy.findMany({ select: { id: true, slug: true } }) const vergeben = new Set( rows.filter((r) => !existing || r.id !== existing.id).map((r) => r.slug) ) return uniqueSlug(title, vergeben) } module.exports = { slugify, uniqueSlug, resolveSlug }