"""Erzeugt die statische GitLab-Pages-Seite (DB-UX-Look). Schreibt: public/index.html -> DB-gestylte Oberflaeche mit Filter (extern/intern/allgemein), Suche und Klick-in-Dokument (Modal mit dem Markdown-Inhalt) public/data.json -> alle Dokumente (Metadaten + Text), per fetch() geladen Aufruf: python -m src.site --data output --staging staging --out public """ from __future__ import annotations import argparse import html as _html import json import re from pathlib import Path def _md_inline(s: str) -> str: """Minimal: escape + **bold**, `code`, [text](url).""" s = _html.escape(s) s = re.sub(r"\*\*(.+?)\*\*", r"\1", s) s = re.sub(r"`(.+?)`", r"\1", s) s = re.sub(r"\[(.+?)\]\((.+?)\)", r'\1', s) return s def _md_to_html(md: str) -> str: """Sehr kleiner Markdown->HTML-Renderer (Headings, Listen, Absaetze) fuer das Changelog.""" out: list[str] = [] in_list = False def close_list(): nonlocal in_list if in_list: out.append("") in_list = False for raw in md.splitlines(): line = raw.rstrip() if not line.strip(): close_list() continue if line.startswith("### "): close_list() out.append(f"

{_md_inline(line[4:])}

") elif line.startswith("## "): close_list() out.append(f"

{_md_inline(line[3:])}

") elif line.startswith("# "): close_list() out.append(f"

{_md_inline(line[2:])}

") elif line.lstrip().startswith(("- ", "* ")): if not in_list: out.append("