Markdown-Sonderzeichen maskieren, Verszeilen mit Satzende erhalten

- md_escape im Span-Patch: \ ` * [ ] < > $ ~ ^ und "_" an Wortgrenzen
  werden maskiert (__add__ nicht mehr fett, <p> nicht mehr HTML); Code
  bleibt wörtlich
- Folgeschritte maskierungsfest: norm_title, clean_inline, link_urls
  (Positionstabelle inkl. Backslash), link_anchors, --split-Titel
- Kurze Zeile mit Satzende ist nur bei eingerückter Folgezeile ein
  Absatzende, sonst eine Verszeile; Einrückung gegen den Spaltenrand der
  Seite gemessen (trennt auch verklebte einzeilige Dialogabsätze)
- Tests, README, Bedienungsanleitung, TODO

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-10-02 19:28:56 +02:00
commit d6a8c11b0a

View file

@ -401,3 +401,32 @@ def test_link_urls_joins_printed_continuation_without_pdf_target():
"Siehe <https://a.org/digital_dispatches/towards-x/>. und "
"<https://b.de/Docs/artikel.html>. Oder <https://c.de/> und mehr.\n"
)
# --- Markdown-Sonderzeichen --------------------------------------------------------
@pytest.mark.parametrize("text, escaped", [
("__add__", "\\_\\_add\\_\\_"),
("snake_case", "snake_case"),
("a*b [1] <p> $5 x^2 ~x", "a\\*b \\[1\\] \\<p\\> \\$5 x\\^2 \\~x"),
])
def test_md_escape_round_trip(text, escaped):
assert p.md_escape(text) == escaped
assert p.md_unescape(escaped) == text
def test_pymupdf4llm_patch_escapes_text_but_not_code():
spans = [
{"text": "__add__ und *", "flags": 0, "char_flags": 16, "font": "x", "block": 0, "line": 0},
{"text": "a_b*c", "flags": 8, "char_flags": int(p.VISIBLE_TEXT), "font": "Courier",
"block": 0, "line": 0},
]
output, _ = p.document_layout.get_styled_text(spans)
assert output.strip() == "\\_\\_add\\_\\_ und \\* `a_b*c`"
def test_escaped_text_survives_link_steps():
md = "\\_\\_add\\_\\_, 180\\\nSiehe https://a.de/Leitlinien\\_ x.\n"
out = p.link_anchors(p.link_urls(md, ["https://a.de/Leitlinien_x"]), [])
assert out.startswith("\\_\\_add\\_\\_, 180\\\n")
assert "<https://a.de/Leitlinien_x>" in out