diora-web/e2e/make_epub.py
mrwnslz ffcb6fba4f
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Has been cancelled
Refactoring Schritt 1: Browser-Tests für den Reader, in der CI; Plan in docs/refactoring.md
- e2e/reader.spec.js: ein Test-EPUB (e2e/make_epub.py) hochladen, öffnen ohne
  zu senden, lesen und Lesestand nach Neuladen, Fußnote, Markierung und
  Notizleiste, Hell/Dunkel samt Reader, alle Tabs ohne Seitenfehler.
- e2e/env.js: E2E_PORT und E2E_PYTHON; nie einen laufenden Server
  wiederverwenden (dahinter läge eine echte Datenbank).
- CI: eigener Job e2e (Playwright + Chromium); blockiert den Docker-Build nicht.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:25:06 +02:00

58 lines
2.9 KiB
Python

"""A small EPUB for the e2e tests: 12 chapters of numbered paragraphs (long enough
to scroll and to have a reading position), one footnote. Written to the path in
argv[1]; e2e/global-setup.js calls it for every run."""
import sys
import zipfile
CONTAINER = """<?xml version="1.0"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles><rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/></rootfiles>
</container>"""
def chapter(n):
paras = []
for p in range(1, 41):
text = f'Kapitel {n}, Absatz {p}. ' + ' '.join(
f'Wort{w} im Absatz {p} des Kapitels {n} steht hier, damit der Absatz einige Zeilen lang wird.'
for w in range(1, 6))
if n == 1 and p == 3:
text += ' Mit Fußnote<a href="ch12.xhtml#fn1" epub:type="noteref"><sup>1</sup></a>.'
paras.append(f'<p id="c{n}p{p}">{text}</p>')
notes = ''
if n == 12:
notes = '<aside epub:type="footnote" id="fn1"><p>1 Der Text der Fußnote.</p></aside>'
return f"""<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head><title>Kapitel {n}</title></head>
<body><h1>Kapitel {n}</h1>{''.join(paras)}{notes}</body></html>"""
def main(path):
chapters = range(1, 13)
manifest = ''.join(f'<item id="c{n}" href="ch{n}.xhtml" media-type="application/xhtml+xml"/>' for n in chapters)
spine = ''.join(f'<itemref idref="c{n}"/>' for n in chapters)
nav_items = ''.join(f'<li><a href="ch{n}.xhtml">Kapitel {n}</a></li>' for n in chapters)
opf = f"""<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" unique-identifier="id">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:identifier id="id">diora-e2e-book</dc:identifier>
<dc:title>E2E Testbuch</dc:title><dc:creator>diora</dc:creator><dc:language>de</dc:language>
</metadata>
<manifest><item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>{manifest}</manifest>
<spine>{spine}</spine>
</package>"""
nav = f"""<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head><title>Inhalt</title></head><body><nav epub:type="toc"><ol>{nav_items}</ol></nav></body></html>"""
with zipfile.ZipFile(path, 'w') as z:
z.writestr(zipfile.ZipInfo('mimetype'), 'application/epub+zip', compress_type=zipfile.ZIP_STORED)
z.writestr('META-INF/container.xml', CONTAINER, compress_type=zipfile.ZIP_DEFLATED)
z.writestr('OEBPS/content.opf', opf, compress_type=zipfile.ZIP_DEFLATED)
z.writestr('OEBPS/nav.xhtml', nav, compress_type=zipfile.ZIP_DEFLATED)
for n in chapters:
z.writestr(f'OEBPS/ch{n}.xhtml', chapter(n), compress_type=zipfile.ZIP_DEFLATED)
if __name__ == '__main__':
main(sys.argv[1])