feat: Buchanfang Cover → Titel → Impressum → Inhaltsverzeichnis für alle Bücher

- Kapitelerkennung: erstes Kapitel nur aus einem Bild = Cover ("[Titelinfo]",
  "Deckblatt"), Titel "Titel" = Titelseite
- epub2md_merge: Vorspann reicht bis vor den Hauptteil (Teil, Vorwort,
  Einleitung, nummerierter Titel, > 1000 Wörter), kurze Zwischenseiten
  (Auflage, Verlagsbrief, "Über dieses Buch") bleiben davor
- book.lua: Cover am Inhalt erkannt; LaTeX-Weg (Filter in beiden Schritten):
  \tableofcontents hinter dem Vorspann, \clearpage je Kapitel, kein \maketitle
  vor dem Cover, A4, seitengroßes Cover, DejaVu-Schriften und Mathe-Symbole
  für fehlende Glyphen (Mathebuch: >10.000 fehlende Zeichen → 0)
- Buch-README: bei Formeln LaTeX-Weg empfohlen, sonst weasyprint
- Alle sechs Beispielbücher geprüft: Seite 1 Cover, Verzeichnis nach dem Vorspann

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-10-06 06:48:18 +02:00
commit 86aa93c12c

View file

@ -185,3 +185,18 @@ def test_special_chapter_is_not_split_further(convert):
"<h1>Register</h1><h2>A</h2><p>Apfel</p><h2>Index</h2><p>x</p>")
run = convert(Book(docs=[Doc("a.xhtml", body)]))
assert [p.name for p in run.chapters()] == ["001-literatur.md", "002-register.md"]
def test_first_image_only_chapter_is_cover_and_titel_is_title_page(convert):
from conftest import PNG
docs = [Doc("info.xhtml", '<div><img src="c.png" alt=""/></div>', "[Titelinfo]"),
Doc("t.xhtml", "<p>Erika Musterfrau</p><p>Testbuch</p>", "Titel"),
Doc("d.xhtml", '<div><img src="c.png" alt="Deckblatt"/></div>', "Deckblatt"),
Doc("c1.xhtml", "<h1>Eins</h1><p>Text</p>")]
run = convert(Book(docs=docs, nav=[("Eins", "c1.xhtml")], media={"c.png": PNG}))
types = {c["file"]: c["types"] for c in run.report["chapters"]}
first, second, third = sorted(types)[:3]
assert "cover" in types[first]
assert "titlepage" in types[second]
assert "cover" in types[third] # 'Deckblatt' by title
assert "cover" not in types[sorted(types)[3]]