import yaml
from conftest import Book, Doc
def frontmatter(text: str) -> dict:
assert text.startswith("---\n")
return yaml.safe_load(text.split("---\n")[1])
def test_files_are_numbered_and_slugged(convert):
docs = [Doc("c1.xhtml", "
Übersicht & Größen
a
"), Doc("c2.xhtml", "Übersicht & Größen
b
")]
run = convert(Book(docs=docs))
assert [p.name for p in run.chapters()] == ["001-uebersicht-groessen.md", "002-uebersicht-groessen.md"]
run_en = convert(Book(docs=docs), "--slug-language", "en")
assert run_en.chapters()[0].name == "001-ubersicht-grossen.md"
run_none = convert(Book(docs=docs), "--slug-language", "none")
assert run_none.chapters()[0].name == "001-übersicht-größen.md"
def test_h1_split_inside_one_file(convert):
body = "Eins
a
Eins.Eins
b
Zwei
c
"
run = convert(Book(docs=[Doc("all.xhtml", body)]))
assert [p.name for p in run.chapters()] == ["001-eins.md", "002-zwei.md"]
assert "## Eins.Eins" in run.chapter("001")
def test_h2_split_with_chapter_level_2(convert):
body = "Teil I
Intro
Kapitel 1
a
Kapitel 2
b
"
run = convert(Book(docs=[Doc("all.xhtml", body)]), "--chapter-level", "2")
names = [p.name for p in run.chapters()]
assert names == ["001-teil-i.md", "002-kapitel-1.md", "003-kapitel-2.md"]
assert run.chapter("002").count("\n# ") == 1 # exactly one H1 per file
def test_section_files_without_h1_continue_previous_chapter(convert):
docs = [
Doc("01.xhtml", "Kapitel 1
a
"),
Doc("01b.xhtml", ''),
Doc("02.xhtml", "Kapitel 2
c
"),
]
run = convert(Book(docs=docs))
assert len(run.chapters()) == 2
first = run.chapter("001")
assert "## 1.1 Abschnitt" in first
assert frontmatter(first)["source_hrefs"] == ["01.xhtml", "01b.xhtml"]
def test_headingless_documents_become_own_chapters_with_nav_title(convert):
docs = [Doc("titel.xhtml", "Widmung für alle
"), Doc("c.xhtml", "Start
x
")]
book = Book(docs=docs, nav=[("Widmung", "titel.xhtml"), ("Start", "c.xhtml")])
run = convert(book)
assert [p.name for p in run.chapters()] == ["001-widmung.md", "002-start.md"]
fm = frontmatter(run.chapter("001"))
assert fm["chapter_title"] == "Widmung"
assert "dedication" in fm["epub_type"]
def test_semantic_sections_are_split_and_classified(convert):
body = (
''
''
''
''
''
)
run = convert(Book(docs=[Doc("b.xhtml", body)]))
names = [p.name for p in run.chapters()]
assert names == ["001-kapitel.md", "002-glossar.md", "003-literatur.md", "004-sachregister.md", "005-personenregister.md"]
assert frontmatter(run.chapter("002"))["epub_type"] == ["glossary"]
assert "**API:** Schnittstelle." in run.chapter("002")
lit = run.chapter("003")
assert "[doi:10.1000/xyz](https://doi.org/10.1000/xyz)" in lit and "ISBN 978-0-201-89683-1" in lit
assert "index-persons" in frontmatter(run.chapter("005"))["epub_type"]
readme = (run.out / "README.md").read_text(encoding="utf-8")
assert "Glossar: [Glossar](chapters/002-glossar.md)" in readme
assert "Personenregister: [Personenregister](chapters/005-personenregister.md)" in readme
types = {s["type"] for s in run.report["special_sections"]}
assert {"glossary", "bibliography", "index", "index-persons"} <= types
def test_wrapper_preamble_belongs_to_heading_chapter(convert):
body = ''
run = convert(Book(docs=[Doc("c.xhtml", body)]))
assert len(run.chapters()) == 1
text = run.chapter("001")
assert "Kontextinfo" in text and text.count("# Kapitel") == 1
def test_html_toc_document_is_not_duplicated(convert):
toc = 'Inhaltsverzeichnis
Kapitel A
Kapitel B
B.1
'
docs = [Doc("toc.xhtml", toc), Doc("a.xhtml", "A
a
"), Doc("b.xhtml", 'B
b
')]
run = convert(Book(docs=docs, nav=[("A", "a.xhtml"), ("B", "b.xhtml")]))
assert [p.name for p in run.chapters()] == ["001-a.md", "002-b.md"]
assert run.report["skipped_documents"] == [{"href": "OEBPS/toc.xhtml", "reason": "html-toc"}]
def test_short_title_page_is_kept(convert):
docs = [Doc("t.xhtml", "Für M.
", "Widmung"), Doc("c.xhtml", "K
x
")]
run = convert(Book(docs=docs, nav=[]))
assert len(run.chapters()) == 2
assert "Für M." in run.chapter("001")
def test_layout_table_headings_are_recognized(convert):
body = (
''
"Text
"
'mehr
'
)
run = convert(Book(docs=[Doc("c.xhtml", body)]))
text = run.chapter("001")
assert "# 3 Grundlagen" in text
assert "## 3.1 Einführung" in text
assert " must not end up inside the bold markers."""
body = ('K
API
Glossar
'
'- API
- Schnittstelle.
')
text = convert(Book(docs=[Doc("c.xhtml", body)])).chapter("002")
assert '**API:** Schnittstelle.' in text
def test_large_chapter_with_subheadings_suggests_deeper_chapter_level(convert):
words = " ".join(["Wort"] * 11000)
body = "Teil 1
" + "".join(f"Kapitel {i}
{words}
" for i in range(3))
run = convert(Book(docs=[Doc("t.xhtml", body)]))
hints = [w for w in run.report["warnings"] if w["code"] == "chapter-large"]
assert len(hints) == 1
assert "--chapter-level 2" in hints[0]["message"] and "3 Unterabschnitte" in hints[0]["message"]
small = convert(Book(docs=[Doc("t.xhtml", "Teil
A
x
B
y
")]))
assert not any(w["code"] == "chapter-large" for w in small.report["warnings"])
def test_titles_derived_from_content_when_no_other_source(convert):
docs = [
Doc("ccover.xhtml", ''),
Doc("cinner.xhtml", "Erika Musterfrau
Testbuch
Roman
"),
Doc("cimp.xhtml", "© 2024 Testverlag
Das Werk ist urheberrechtlich geschützt.
"),
Doc("cwid.xhtml", "Für Anna, die immer an mich geglaubt hat, und für alle anderen.
"),
Doc("c1.xhtml", "Eins
Text
"),
]
from conftest import PNG
run = convert(Book(docs=docs, nav=[("Eins", "c1.xhtml")], media={"c.png": PNG}))
names = [p.name for p in run.chapters()]
assert names == ["001-cover.md", "002-titelseite.md", "003-impressum.md",
"004-fuer-anna-die-immer-an-mich-geglaubt-hat.md", "005-eins.md"]
types = {c["file"]: c["types"] for c in run.report["chapters"]}
assert "cover" in types["chapters/001-cover.md"]
assert "titlepage" in types["chapters/002-titelseite.md"]
assert "colophon" in types["chapters/003-impressum.md"]