Files
PubScript/CHUNK#6.md
T

76 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`)
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 (`<h1>`, `<p>`, `<hr>` 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)
- [ ] Export a project to MD, HTML, EPUB, DOCX, ODT, PDF — all succeed from the dialog.
- [ ] EPUB passes `epubcheck` with 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 + `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.