5.3 KiB
5.3 KiB
CHUNK #6 — Export Pipeline
Duration: ~3 days · Prereqs: CHUNK #3 (editor, ProseMirror JSON) · Follows: CHUNK #5 · Unblocks: CHUNK #11 (packaging ships exports)
Purpose: Ship a single export engine that turns a project's ProseMirror JSON into Markdown, single-file HTML, EPUB 3, DOCX, ODT, and PDF — all with title/author/cover/TOC/styling options. Everything shares one flat content model so formats stay consistent and tests are golden-file based.
Steps
1. Shared flat model (packages/exporters/src/model.ts)
flattenProject(project)→ a linear list ofBlocks:{ type: 'heading'|'paragraph'|'sceneBreak'|'blockquote'|'codeBlock'|'list'|'footnote', text, marks[], level?, children? }, plus frontmatter{ title, author, language, cover, chapters: [{title, order}] }.- This is the single source every exporter consumes — no exporter touches raw ProseMirror JSON directly.
2. Markdown & HTML (packages/exporters/src/md.ts, html.ts)
- Markdown export (
exportMarkdown(blocks)): headings (#–###), scene breaks as***, blockquotes, code fences, lists, footnotes as[1]refs with a notes section. Round-trips with Chunk 3's importer. - Single-file HTML (
exportHtml(blocks, opts)): one self-contained.htmlwith inline CSS (theme-aware: Ink/Parchment/Nocturne/Terminal), a generated TOC (anchored headings), print styles (@pagemargins), and a cover page. No external assets.
3. EPUB 3 (packages/exporters/src/epub.ts)
- Build a valid EPUB 3 container by hand (no runtime deps):
mimetype(uncompressed,application/epub+zip) first in the zip.META-INF/container.xml→content.opf.content.opf: metadata (title, author, language, UUID, cover), manifest (chapterN.xhtml,toc.ncx,cover.svg,style.css), spine (chapter order).chapterN.xhtml: one file per chapter, semantic HTML5 (<h1>,<p>,<hr>for scene breaks), anavTOC.cover.svg: renders the project's cover color + title/author.
- Zip with
jszip(already a dep). Output.epub. - Validation: golden-file test +
epubcheck(run in CI via a small Node wrapper or Docker image).
4. DOCX (packages/exporters/src/docx.ts)
- Use the maintained
docxnpm package:Document→Section→Paragraph/Heading/Quote; add aTableOfContents(fieldTOC), a cover paragraph, and page breaks between chapters. - Styles: map themes to Word styles (font, size, heading colors). Export
.docx.
5. ODT (packages/exporters/src/odt.ts)
- Build a valid OpenDocument container (parallel to EPUB):
mimetype(application/vnd.oasis.opendocument.text) first, uncompressed.content.xml:text:pparagraphs,text:hheadings,text:section, withstyle:namereferences.manifest.xml,meta.xml(title/author),styles.xml(basic paragraph styles),thumbs/thumbnail.png(optional).
- Zip with
jszip. Output.odt. (LibreOffice-openable; golden-file unzip-validate in CI.)
6. PDF (packages/exporters/src/pdf.ts)
- Two backends (chosen by env):
- Server/desktop: headless Chromium
page.pdf()over the single-file HTML → pixel-perfect, themes intact, real TOC. This is the default. - Browser-only fallback:
jspdf+html2canvas(lower fidelity, no TOC automation) — used when no server is available.
- Server/desktop: headless Chromium
exportPdf(blocks, opts)returns aUint8Array. Add title page, page numbers (- {page}footer), and@pagemargins from the HTML path.
7. Export dialog (apps/web/src/features/export/ExportDialog.tsx)
- Select: format (multi-select), scope (current chapter / whole book / whole project), options (cover, TOC, theme, page size).
- Live preview thumbnail (HTML/EPUB), progress bar, download button(s). Desktop uses Tauri FS save dialog; web uses native download.
- Batch export: "Export all formats" → zips results.
8. Tests
- Golden-file tests: for each format, snapshot the output bytes of the seed project; assert stable across runs (whitespace-normalized for HTML/PDF).
- Round-trip: MD export → import → MD export is identical.
- Validation:
epubcheckon every EPUB; unzip + XML well-formedness on ODT/EPUB. - CI: run epubcheck; unzip-validate all archives.
Acceptance criteria (all must pass)
- Export a project to MD, HTML, EPUB, DOCX, ODT, PDF — all succeed from the dialog.
- EPUB passes
epubcheckwith zero errors; opens in Calibre/Readers. - ODT opens cleanly in LibreOffice; styles preserved.
- DOCX opens in Word; TOC field present (update-on-open).
- PDF has title page, TOC (HTML backend), page numbers, correct margins.
- Theme applied in HTML/EPUB/PDF (Ink dark / Parchment light, etc.).
- Golden-file tests stable; round-trip MD identical.
- CI validates EPUB + unzip-validates all archives.
Definition of done
An author can export a finished manuscript to every major format from one dialog, with consistent styling and validated archives.
Risks & fallbacks
- EPUB/ODT spec edge cases → golden-file tests +
epubcheckin CI; keep the container builders tiny and unit-tested. - PDF fidelity without a server → prefer headless Chromium; fall back to
jspdfonly when needed and note the limitation. - Cover image sizing → normalize covers to EPUB-recommended dimensions (e.g. 1600×2560) before embedding.