"""Mini-Markdown-Renderer für PM-Bodies — Python-Spiegelbild der JS-Funktion ``renderPmBody`` in ``v2/screens/aktuelle-themen.html``. Der Renderer interpretiert eine kleine Untermenge von Markdown: - ``**bold**`` und ``__bold__`` → ``...`` - ``*italic*`` und ``_italic_`` → ``...`` (vorsichtig — nur wenn nicht zwischen Ziffern oder Word-Charakters) - Zeilen, die mit ``- `` oder ``* `` beginnen → ```` - Doppel-Newlines trennen Absätze → ``

...

`` - Einzelne Newlines innerhalb eines Absatzes → ``
`` - HTML-Special-Chars (``&``, ``<``, ``>``) werden escaped. Die Python-Variante existiert primär zum Testen. Im Produktiv-Frontend wird die JS-Variante benutzt (kein Round-Trip zum Server). """ from __future__ import annotations import re # 1) HTML-Escape (analog zur JS-Variante, in dieser Reihenfolge) def _html_escape(s: str) -> str: return s.replace("&", "&").replace("<", "<").replace(">", ">") # 2) Bold-Marker: **...** und __...__ _RE_BOLD_STAR = re.compile(r"\*\*([^*\n]+?)\*\*") _RE_BOLD_UNDER = re.compile(r"__([^_\n]+?)__") # 3) Italic-Marker: *…* und _…_, jeweils nicht zw. Word-Chars _RE_ITALIC_STAR = re.compile(r"(? str: """Render Mini-Markdown zu HTML. Leere/None-Eingabe → leerer String.""" if not body: return "" s = _html_escape(body) s = _RE_BOLD_STAR.sub(r"\1", s) s = _RE_BOLD_UNDER.sub(r"\1", s) s = _RE_ITALIC_STAR.sub(r"\1", s) s = _RE_ITALIC_UNDER.sub(r"\1", s) # Listen: konsekutive "- "/"* "-Zeilen zu einem ") s = "\n".join(out_lines) # Paragraphen-Split bei doppelten Newlines, einzelne →
paras = re.split(r"\n\s*\n", s) rendered = [] for p in paras: trimmed = p.strip() if not trimmed: continue if trimmed.startswith("<"): rendered.append(trimmed) else: rendered.append( '

' + trimmed.replace("\n", "
") + "

" ) return "\n".join(rendered)