Files
PubScript/CHUNK#6.md
T

5.3 KiB
Raw Blame History

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 Blocks: { 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.