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:
parent
99c3c609ca
commit
86aa93c12c
3 changed files with 257 additions and 46 deletions
|
|
@ -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]]
|
||||
|
|
|
|||
|
|
@ -118,3 +118,21 @@ def test_merge_own_toc_replaces_placeholder(convert):
|
|||
assert merge_main([str(run.out), "--toc"]) == 0
|
||||
text = (run.out / f"{run.report['input']['name'][:-5]}.md").read_text(encoding="utf-8")
|
||||
assert "epub2md-toc" not in text and text.index("© 2024") < text.index("## Inhalt") < text.index("# Kapitel A")
|
||||
|
||||
|
||||
def test_merge_front_matter_region_with_gaps(convert):
|
||||
"""Krooss/Blake-like: short untyped pages between title page and imprint; main matter starts at '1 …'."""
|
||||
docs = [Doc("cover.xhtml", '<div><img src="img/a.png" alt="Cover"/></div>'),
|
||||
Doc("titel.xhtml", "<p>Erika Musterfrau</p><p>Vorspann</p><p>Roman</p>"),
|
||||
Doc("auflage.xhtml", "<h1>Vorspann</h1><p>4. Auflage 2025</p>"),
|
||||
Doc("impressum.xhtml", "<p>© 2024 Testverlag</p><p>Das Werk ist urheberrechtlich geschützt.</p>"),
|
||||
Doc("brief.xhtml", "<h1>Liebe Leserin, lieber Leser,</h1><p>Viel Spaß.</p>"),
|
||||
Doc("k1.xhtml", "<h1>1 Der Einstieg</h1><p>a</p>"), Doc("k2.xhtml", "<h1>Zwischenspiel</h1><p>b</p>")]
|
||||
book = Book(title="Vorspann", docs=docs, nav=[("1 Der Einstieg", "k1.xhtml"), ("Zwischenspiel", "k2.xhtml")],
|
||||
media={"img/a.png": PNG})
|
||||
run = convert(book)
|
||||
assert merge_main([str(run.out)]) == 0
|
||||
text = (run.out / f"{run.report['input']['name'][:-5]}.md").read_text(encoding="utf-8")
|
||||
toc = text.index('<div id="epub2md-toc"></div>')
|
||||
assert text.index("© 2024") < text.index("Viel Spaß.") < toc < text.index("# 1 Der Einstieg")
|
||||
assert text.count("epub2md-toc") == 1 and "epub2md-titlepage" not in text
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ def test_qa2_10_book_readme_recommends_pdf_via_html(convert):
|
|||
"""Pandoc drops raw HTML (tables, <a id>) when going Markdown -> LaTeX; the HTML route keeps both."""
|
||||
run = convert(Book(docs=[Doc("a.xhtml", "<h1>A</h1><p>x</p>")]))
|
||||
readme = (run.out / "README.md").read_text(encoding="utf-8")
|
||||
assert re.search(r"pandoc \S+\.md -s -o \S+\.html && pandoc \S+\.html --toc --pdf-engine=xelatex -o \S+\.pdf", readme)
|
||||
book = r"--lua-filter \S+/pandoc/book\.lua" # table of contents after the front matter (both steps)
|
||||
assert re.search(rf"pandoc \S+\.md -s {book} -o \S+\.html && pandoc \S+\.html {book} --pdf-engine=xelatex -o \S+\.pdf",
|
||||
readme)
|
||||
|
||||
|
||||
def test_qa2_11_code_language_hint(convert):
|
||||
|
|
|
|||
Loading…
Reference in a new issue