feat: Inhaltsverzeichnis nach Cover, Titelseite und Impressum (pandoc/book.lua)

Pandocs --toc setzt Inhaltsverzeichnis und Titelkopf immer vor den
Buchtext, also vor Cover, Titelseite und Impressum.

- epub2md_merge.py: Kapiteltypen aus manifest.json; Platzhalter
  <div id="epub2md-toc"> hinter dem Vorspann und, ohne eigene Titelseite,
  <div id="epub2md-titlepage"> hinter dem Cover; --toc-Liste an derselben Stelle
- pandoc/book.lua (HTML/weasyprint, statt --toc): baut dort das
  Inhaltsverzeichnis, lässt Pandocs Titelkopf bei eigener Titelseite weg,
  Cover ohne Bildunterschrift, Kapitelanker → div.chapter-start;
  andere Formate: nur Platzhalter entfernen
- print.css: jedes Kapitel (auch Cover/Titelseite/Impressum) und das
  Verzeichnis auf neuer Seite, Verzeichnis mit Punktlinie und Seitenzahl
- Buch-README, Bedienungsanleitung, README: Befehle mit book.lua

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

View file

@ -84,3 +84,37 @@ def test_merge_shortens_iso_date(convert):
assert merge_main([str(run.out)]) == 0
text = (run.out / f"{run.report['input']['name'][:-5]}.md").read_text(encoding="utf-8")
assert yaml.safe_load(text.split("---\n")[1])["date"] == "01.01.2024"
def front_book() -> Book:
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("impressum.xhtml", "<p>© 2024 Testverlag</p><p>Das Werk ist urheberrechtlich geschützt.</p>"),
Doc("a.xhtml", "<h1>Kapitel A</h1><p>a</p>")]
return Book(title="Vorspann", docs=docs, nav=[("Kapitel A", "a.xhtml")], media={"img/a.png": PNG})
def test_merge_places_toc_placeholder_after_front_matter(convert):
run = convert(front_book())
assert merge_main([str(run.out)]) == 0
text = (run.out / f"{run.report['input']['name'][:-5]}.md").read_text(encoding="utf-8")
cover, title, imprint = text.index("![Cover]"), text.index("\nRoman"), text.index("© 2024")
toc, first = text.index('<div id="epub2md-toc"></div>'), text.index("# Kapitel A")
assert cover < title < imprint < toc < first
assert "epub2md-titlepage" not in text # the book has its own title page
def test_merge_title_placeholder_after_cover_without_own_title_page(convert):
docs = [Doc("cover.xhtml", '<div><img src="img/a.png" alt="Cover"/></div>'), Doc("a.xhtml", "<h1>Kapitel A</h1><p>a</p>")]
run = convert(Book(title="Ohne Titelei", docs=docs, nav=[("Kapitel A", "a.xhtml")], media={"img/a.png": PNG}))
assert merge_main([str(run.out)]) == 0
text = (run.out / f"{run.report['input']['name'][:-5]}.md").read_text(encoding="utf-8")
assert text.index("![Cover]") < text.index('<div id="epub2md-titlepage"></div>') \
< text.index('<div id="epub2md-toc"></div>') < text.index("# Kapitel A")
def test_merge_own_toc_replaces_placeholder(convert):
run = convert(front_book())
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")