# CHUNK #6 — Export Pipeline **Status:** ✅ Complete — committed `63f34b3` (feat(export): Chunk #6 Export Pipeline). All 7 exporters, the ExportDialog, and the test suite are green. **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`) 1. `flattenProject(project)` → a linear list of `Block`s: `{ type: 'heading'|'paragraph'|'sceneBreak'|'blockquote'|'codeBlock'|'list'|'footnote', text, marks[], level?, children? }`, plus frontmatter `{ title, author, language, cover, chapters: [{title, order}] }`. 2. 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`) 1. **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. 2. **Single-file HTML** (`exportHtml(blocks, opts)`): one self-contained `.html` with inline CSS (theme-aware: Ink/Parchment/Nocturne/Terminal), a generated TOC (anchored headings), print styles (`@page` margins), and a cover page. No external assets. ### 3. EPUB 3 (`packages/exporters/src/epub.ts`) 1. 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 (`

`, `

`, `


` for scene breaks), a `nav` TOC. - `cover.svg`: renders the project's cover color + title/author. 2. Zip with `jszip` (already a dep). Output `.epub`. 3. **Validation**: golden-file test + `epubcheck` (run in CI via a small Node wrapper or Docker image). ### 4. DOCX (`packages/exporters/src/docx.ts`) 1. Use the maintained **`docx`** npm package: `Document` → `Section` → `Paragraph`/`Heading`/`Quote`; add a `TableOfContents` (field `TOC`), a cover paragraph, and page breaks between chapters. 2. Styles: map themes to Word styles (font, size, heading colors). Export `.docx`. ### 5. ODT (`packages/exporters/src/odt.ts`) 1. Build a valid OpenDocument container (parallel to EPUB): - `mimetype` (`application/vnd.oasis.opendocument.text`) first, uncompressed. - `content.xml`: `text:p` paragraphs, `text:h` headings, `text:section`, with `style:name` references. - `manifest.xml`, `meta.xml` (title/author), `styles.xml` (basic paragraph styles), `thumbs/thumbnail.png` (optional). 2. Zip with `jszip`. Output `.odt`. (LibreOffice-openable; golden-file unzip-validate in CI.) ### 6. PDF (`packages/exporters/src/pdf.ts`) 1. **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. 2. `exportPdf(blocks, opts)` returns a `Uint8Array`. Add title page, page numbers (`- {page}` footer), and `@page` margins from the HTML path. ### 7. Export dialog (`apps/web/src/features/export/ExportDialog.tsx`) 1. Select: format (multi-select), scope (current chapter / whole book / whole project), options (cover, TOC, theme, page size). 2. Live preview thumbnail (HTML/EPUB), progress bar, download button(s). Desktop uses Tauri FS save dialog; web uses native download. 3. **Batch export**: "Export all formats" → zips results. ### 8. Tests 1. **Golden-file tests**: for each format, snapshot the output bytes of the seed project; assert stable across runs (whitespace-normalized for HTML/PDF). 2. **Round-trip**: MD export → import → MD export is identical. 3. **Validation**: `epubcheck` on every EPUB; unzip + XML well-formedness on ODT/EPUB. 4. **CI**: run epubcheck; unzip-validate all archives. --- ## Acceptance criteria (all must pass) - [x] Export a project to MD, HTML, EPUB, DOCX, ODT, PDF — all succeed from the dialog. - [x] EPUB passes `epubcheck` with zero errors; opens in Calibre/Readers. - [x] ODT opens cleanly in LibreOffice; styles preserved. - [x] DOCX opens in Word; TOC field present (update-on-open). - [x] PDF has title page, TOC (HTML backend), page numbers, correct margins. - [x] Theme applied in HTML/EPUB/PDF (Ink dark / Parchment light, etc.). - [x] Golden-file tests stable; round-trip MD identical. - [x] 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 + `epubcheck` in CI; keep the container builders tiny and unit-tested. - **PDF fidelity without a server** → prefer headless Chromium; fall back to `jspdf` only when needed and note the limitation. - **Cover image sizing** → normalize covers to EPUB-recommended dimensions (e.g. 1600×2560) before embedding.