RTF: Leerzeilen via {space}\par-Filler zwischen \par

Rhinos Parser collapsed mehrere \\par in Folge zu einem einzelnen
Linebreak. Loesung: jeder zusaetzliche \\par bekommt einen
{ }-Space-Group vor sich, damit der leere Paragraph "Inhalt" hat
und als echte Leerzeile gerendert wird.

Why: User-Test "TITEL\\n\\nTEXT" renderte als zwei aufeinander-
folgende Zeilen ohne Leerzeile dazwischen, obwohl die zweite \\n
korrekt in pending_pars gezaehlt wurde.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 13:05:11 +02:00
parent 29699b5eda
commit de6f84346c
+13 -9
View File
@@ -403,6 +403,16 @@ def _runs_to_rtf(runs, default_font, base_size_m=0.20):
else: codes.append("\\nosupersub")
body_parts.append("{{{} {}}}".format("".join(codes), _escape_no_par(seg)))
def _flush_pars(n):
# 1 \\par = einfacher Zeilenumbruch. N>1 \\par hintereinander
# wuerde Rhino zu einem einzigen Umbruch collapsen — fuer
# jede zusaetzliche Leerzeile schieben wir einen Space-Group
# dazwischen, damit der leere Paragraph Inhalt hat.
if n <= 0: return
body_parts.append("\\par ")
for _ in range(n - 1):
body_parts.append("{ }\\par ")
first_emitted = False
for run in runs:
raw = run.get("text") or ""
@@ -411,19 +421,13 @@ def _runs_to_rtf(runs, default_font, base_size_m=0.20):
if i > 0:
pending_pars += 1
if seg:
# Pending \\par vor dem naechsten Inhalt — aber nur wenn
# schon mal Inhalt da war (sonst fuehrender \\par bringt
# Leerzeile am Anfang)
if first_emitted:
for _ in range(pending_pars):
body_parts.append("\\par ")
_flush_pars(pending_pars)
pending_pars = 0
_emit_group(run, seg)
first_emitted = True
# Trailing \\par auch noch emittieren (= Leerzeilen am Ende)
if first_emitted:
for _ in range(pending_pars):
body_parts.append("\\par ")
if first_emitted and pending_pars > 0:
_flush_pars(pending_pars)
# ────────────────────────────────────────────────────────────────
# PASS 2: RTF-Header mit JETZT vollstaendigen Tables + Body