feat: Wabenhain Honig-Shop Anwendung

Vollstaendige Next.js/Prisma-E-Commerce-Anwendung fuer eine Imkerei:
Shop, Warenkorb, Stripe-Checkout, Kundenkonto mit 2FA, Admin-Bereich
(Produkte, Ernten, Chargen, Bestellungen, Gutscheine, admin-editierbare
Website-Inhalte), i18n (DE/EN), Rate-Limiting/CSP/Audit-Log-Haertung,
PostgreSQL- und MySQL-Unterstuetzung ueber austauschbare Prisma-
Treiber-Adapter, Unit-/Komponenten-/E2E-Tests.
This commit is contained in:
Nick Szaunig committed 2026-08-17 14:30:28 +02:00
1 parent 5c76fcc266
commit c7927f2883
240 files changed
+26096 -137

No files matched your search

+50
View File
@@ -0,0 +1,50 @@
import type { TitledText, LegalSectionContent } from "@/i18n/dictionary-type";
/**
* Reine Parser-Funktionen fuer das Klartext-Format, in dem die
* Content-Registry-Felder (siehe content-registry.ts) gespeichert werden.
* Bewusst in einer eigenen Datei ohne DB-/Prisma-Import: content.ts zieht
* @/lib/prisma nach sich, dessen Modul-Ladezeit-Treiber-Adapter ohne gesetzte
* DATABASE_URL wirft — das wuerde jeden Test dieser reinen Funktionen
* zwingen, eine DB-Verbindung vorzutaeuschen, obwohl sie keine brauchen.
*/
export function parseListSimple(text: string): string[] {
return text.split("\n").map((line) => line.trim()).filter(Boolean);
}
export function parseListTitled(text: string): TitledText[] {
return text
.split("\n")
.map((line) => line.trim())
.filter(Boolean)
.map((line) => {
const [title, ...rest] = line.split("|");
return { title: (title ?? "").trim(), text: rest.join("|").trim() };
});
}
export function parseListNumbered(text: string): { number: string; title: string; text: string }[] {
return text
.split("\n")
.map((line) => line.trim())
.filter(Boolean)
.map((line) => {
const [number, title, ...rest] = line.split("|");
return { number: (number ?? "").trim(), title: (title ?? "").trim(), text: rest.join("|").trim() };
});
}
export function parseSections(text: string): LegalSectionContent[] {
const blocks = text.split(/\n(?=##\s)/).map((b) => b.trim()).filter(Boolean);
return blocks.map((block) => {
const headingMatch = block.match(/^##\s*(.*)$/m);
const heading = headingMatch ? headingMatch[1].trim() : "";
const body = block.replace(/^##\s*.*$/m, "").trim();
const paragraphs = body
.split(/\n\s*\n/)
.map((p) => p.trim())
.filter(Boolean);
return { heading, paragraphs };
});
}