"""Pandoc path: merged file → EPUB/HTML with the filters from pandoc/ (skipped without pandoc).""" import re import shutil import subprocess import zipfile from pathlib import Path import pytest from conftest import Book, Doc from epub2md.merge import main as merge_main pytestmark = pytest.mark.skipif(shutil.which("pandoc") is None, reason="pandoc nicht installiert") FILTERS = Path(__file__).resolve().parent.parent / "pandoc" def merged(convert, book: Book) -> Path: run = convert(book) assert merge_main([str(run.out)]) == 0 return run.out / f"{run.report['input']['name'][:-5]}.md" def pandoc(md: Path, *args: str) -> subprocess.CompletedProcess: return subprocess.run(["pandoc", md.name, *args], cwd=md.parent, capture_output=True, text=True, check=True) def links_and_ids(epub: Path) -> tuple[list[tuple[str, str]], dict[str, set[str]]]: with zipfile.ZipFile(epub) as z: docs = {n: z.read(n).decode("utf-8") for n in z.namelist() if n.endswith(".xhtml")} ids = {n: set(re.findall(r'\bid="([^"]+)"', t)) for n, t in docs.items()} links = [(n, h) for n, t in docs.items() for h in re.findall(r'href="([^"]+)"', t) if not re.match(r"^[a-z]+:", h) and not h.endswith(".css")] return links, ids def test_epub_links_to_chapter_starts_resolve(convert): """Chapter start anchors must begin with a letter: Pandoc's EPUB writer breaks '#039-…' (QA3-05).""" docs = [Doc("a.xhtml", '
Text B.
"), Doc("c.xhtml", "Nur eine Bildseite ohne Überschrift.
")] md = merged(convert, Book(docs=docs)) pandoc(md, "--toc", "-o", "buch.epub") links, ids = links_and_ids(md.parent / "buch.epub") broken = [] for doc, href in links: file, _, frag = href.partition("#") target = str(Path(doc).parent / file).replace("\\", "/") if file else doc target = re.sub(r"[^/]+/\.\./", "", target) if target not in ids or (frag and frag not in ids[target]): broken.append(f"{doc}: {href}") assert not broken def test_book_filter_turns_chapter_anchors_into_chapter_starts(convert): docs = [Doc("a.xhtml", "a
"), Doc("b.xhtml", "b
")] md = merged(convert, Book(docs=docs)) html = pandoc(md, "-s", "--lua-filter", str(FILTERS / "book.lua"), "-t", "html").stdout assert html.count('class="chapter-start"') == 2 assert 'id="TOC"' in html and "Kapitel B" in html