dorfteich/docs/architecture/adr/0009-import-export-converters.md
Claude Fable 5 0629411966 Add architecture documentation, ADRs, and operations concept
Initial deliverable of the architecture phase: 16 ADRs (stack, CRDT
collaboration, plugin sandbox, import/export, backups, CI/CD), data
model, permission model, real-time collaboration and plugin concepts,
deployment/operations/security documentation, and the milestone roadmap
that the implementation issues are derived from.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 14:36:16 +02:00

58 lines
2.7 KiB
Markdown

# ADR 0009: Pandoc + Gotenberg sidecars for import/export
- Status: accepted
- Date: 2026-07-04
## Context
Requirements: Markdown as the primary import/export format (including
copy/paste), import of Word (`.docx`) and OpenOffice/LibreOffice (`.odt`)
documents, export to Word, OpenOffice, and PDF. Kickoff decision: import is
**best-effort structural** — headings, paragraphs, lists, tables, images,
links, bold/italic are preserved reliably; layout fidelity (columns, text
boxes, exact spacing) is explicitly out of scope. Document conversion is
CPU-heavy and full of parser edge cases; it must not run inside the Node API
process.
## Decision
- **Markdown** conversion (both directions, including clipboard paste) is
implemented **in-process** in TypeScript via `prosemirror-markdown` with
extensions for our custom nodes (wikilinks, section styles). This is the
primary, lossless-as-possible path.
- **`pandoc-server`** (official pandoc image, HTTP server mode, internal
network only) handles:
- import: `.docx` / `.odt` → Markdown (+ extracted media, which the API
stores as uploads and rewrites to image nodes),
- export: Markdown → `.docx` / `.odt` (structure-true best effort).
- **Gotenberg** (internal only) handles **PDF export**: the API renders the
page to standalone HTML (same renderer as the public read-only HTML
endpoint, with the pond's fonts inlined) and sends it to Gotenberg's
Chromium route. PDF output is for reading/sharing, not print production.
- The API's `import-export` module orchestrates conversions asynchronously
(job table + polling endpoint) with size limits and timeouts; sidecar
failures degrade gracefully into a user-visible error, never a crash.
- Plugin blocks render their manifest-declared static `fallback` in all
exports (ADR 0008).
## Consequences
- Two extra containers in the Compose stack; both are stateless, official
images, and internal-only (no ingress). Self-hosting stays
`docker compose up`.
- Import fidelity is testable: a fixture corpus of `.docx`/`.odt` files with
expected Markdown output lives in the repo (stories reference it).
- Copy/paste from Word into the editor goes through the editor's HTML paste
handling (structural, same fidelity philosophy), not through pandoc.
## Alternatives considered
- **mammoth.js in-process** for docx: good HTML output, but no `.odt`
support and no export direction; pandoc covers all four directions with
one tool.
- **LibreOffice headless for everything**: heavyweight, slower startup,
layout-oriented rather than structure-oriented output.
- **Browser-print PDF (client-side)**: inconsistent results across clients;
server-side Chromium (Gotenberg) gives reproducible PDFs and enables
"export without opening the page".