"""--split, --from-md, YAML-Kopf und --jpeg-quality.""" import zipfile import pytest import pdf2md as p from conftest import needs_pandoc from test_e2e import run BOOK = """# Das Buch ## Inhaltsverzeichnis Teil I 1 Anfang ## Teil I: Der Anfang Einleitung zum Teil. ### 1 Anfang Text eins. ``` # kein Kapitel, nur ein Kommentar ``` ### 2 Weiter Text zwei. ## Impressum Alle Rechte vorbehalten. """ def test_frontmatter_round_trip(): meta = {"title": "Ein \"Buch\": Teil 1", "author": "Max Muster", "chapter": 3, "leer": ""} text = p.make_frontmatter(meta) + "# Text\n" parsed, body = p.split_frontmatter(text) assert parsed == {"title": "Ein \"Buch\": Teil 1", "author": "Max Muster", "chapter": 3} assert body == "# Text\n" def test_text_without_frontmatter_is_unchanged(): assert p.split_frontmatter("---\n\nText\n") == ({}, "---\n\nText\n") def test_slugify(): assert p.slugify("2 Ein Brief – eine Liste – ein Vermächtnis") == "2-ein-brief-eine-liste-ein-vermaechtnis" assert p.slugify("Größe & Maß") == "groesse-mass" assert p.slugify("!!!") == "abschnitt" def test_split_by_chapters(): sections = p.split_markdown(BOOK, "kapitel") assert [s["title"] for s in sections] == [ "Vorspann", "Teil I: Der Anfang", "1 Anfang", "2 Weiter", "Impressum", ] assert sections[0]["body"].startswith("# Das Buch") and "## Inhaltsverzeichnis" in sections[0]["body"] assert sections[2]["part"] == "Teil I: Der Anfang" and sections[2]["chapter"] == 1 assert "# kein Kapitel" in sections[2]["body"] # Codeblock wird nicht geschnitten assert "".join(s["body"] for s in sections).replace("\n", "") == BOOK.replace("\n", "") def test_split_by_parts(): sections = p.split_markdown(BOOK, "teile") assert [s["title"] for s in sections] == ["Vorspann", "Teil I: Der Anfang", "Impressum"] assert "### 2 Weiter" in sections[1]["body"] def test_write_split_and_read_back(tmp_path): sections = p.split_markdown(BOOK, "kapitel") files = p.write_split(tmp_path / "buch", sections, {"title": "Das Buch", "author": "Max"}) assert [f.name for f in files][:3] == ["00_vorspann.md", "01_teil-i-der-anfang.md", "02_1-anfang.md"] meta, body, base = p.read_markdown_source(tmp_path / "buch") assert meta["title"] == "Das Buch" and base == tmp_path / "buch" assert body.replace("\n", "") == BOOK.replace("\n", "") head, _ = p.split_frontmatter(files[2].read_text()) assert head == {"title": "1 Anfang", "part": "Teil I: Der Anfang", "chapter": 1, "order": 2, "book": "Das Buch", "author": "Max"} def test_missing_index_entry_is_reported(tmp_path): folder = tmp_path / "buch" p.write_split(folder, p.split_markdown(BOOK, "teile"), {"title": "X"}) (folder / "01_teil-i-der-anfang.md").unlink() with pytest.raises(RuntimeError, match="nicht vorhanden"): p.read_markdown_source(folder) # --- Ende zu Ende ------------------------------------------------------------------ def test_cli_split_writes_folder(pdfs, tmp_path): run(pdfs["digital"], tmp_path / "buch.md", "--split", "kapitel", "--images") folder = tmp_path / "buch" names = sorted(f.name for f in folder.glob("*.md")) assert names[0] == "00_vorspann.md" and "index.md" in names assert any(n.endswith("_1-der-notar.md") for n in names) assert (folder / "images" / "cover.jpg").is_file() text = "".join(f.read_text() for f in folder.glob("*.md")) assert "](images/" in text and "_images/" not in text @needs_pandoc def test_from_md_folder_follows_index_order(pdfs, tmp_path): run(pdfs["digital"], tmp_path / "buch.md", "--split", "kapitel", "--epub") index = tmp_path / "buch" / "index.md" lines = index.read_text().split("\n") i = next(n for n, line in enumerate(lines) if "1-der-notar" in line) j = next(n for n, line in enumerate(lines) if "2-ein-brief" in line) lines[i], lines[j] = lines[j], lines[i] index.write_text("\n".join(lines)) run("--from-md", tmp_path / "buch", "--epub-file", tmp_path / "neu.epub") with zipfile.ZipFile(tmp_path / "neu.epub") as z: nav = z.read("EPUB/nav.xhtml").decode() opf = z.read("EPUB/content.opf").decode() assert nav.index("2 Ein Brief") < nav.index("1 Der Notar") assert "Erika Muster" in opf and "cover" in opf @needs_pandoc def test_from_md_file_uses_frontmatter_and_overrides(pdfs, tmp_path): run(pdfs["digital"], tmp_path / "buch.md", "--images") md = tmp_path / "buch.md" md.write_text(md.read_text().replace("Der Regen", "Der starke Regen")) run("--from-md", md, "--title", "Neuer Titel") with zipfile.ZipFile(tmp_path / "buch.epub") as z: opf = z.read("EPUB/content.opf").decode() text = "".join(z.read(n).decode() for n in z.namelist() if n.endswith(".xhtml")) assert ">Neuer Titel<" in opf and "Erika Muster" in opf and "cover" in opf assert "Der starke Regen" in text and "title:" not in text def test_jpeg_quality_changes_image_size(pdfs, tmp_path): def size(quality): out = tmp_path / f"q{quality}" / "buch.md" run(pdfs["digital"], out, "--images", "--jpeg-quality", str(quality)) return sum(f.stat().st_size for f in (out.parent / "buch_images").glob("*.jpg")) assert size(30) < size(95)