From de6f84346cfe7fc89dd4b3541fc88b1d56919e5f Mon Sep 17 00:00:00 2001 From: karim Date: Thu, 21 May 2026 13:05:11 +0200 Subject: [PATCH] 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 --- rhino/text_editor.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/rhino/text_editor.py b/rhino/text_editor.py index 395e3bc..d94712d 100644 --- a/rhino/text_editor.py +++ b/rhino/text_editor.py @@ -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