Skip to content
This repository was archived by the owner on Aug 20, 2026. It is now read-only.

docs: state why the public API has no DocumentPackage read/write pair - #73

Merged
Mearman merged 3 commits into
mainfrom
feat/document-package-api
Aug 19, 2026
Merged

Mearman merged 3 commits into
mainfrom
feat/document-package-api

Conversation

@Mearman

@Mearman Mearman commented Aug 19, 2026

Copy link
Copy Markdown
Member

Went in to give this package a DocumentPackage-native read/write pair alongside a ContentDocument-based one, the same way the other codecs in the family are getting one now that document-schema.js 4.3.0 exports decompose/flattenPackage/factorStyles/assemblePackage. There is nothing here to wrap: this package has no ContentDocument surface at all, public or internal.

What the inventory actually found, against origin/main:

  • readPdf(bytes, options?) -> LayoutDocument and writePdf(doc, options?) -> Uint8Array, plus pdfCodec, a z.codec() over the pair with LayoutDocumentSchema on the far side. That is the whole content-level surface.
  • LayoutDocument is this package's own type since the 4.0.0 layout demotion (src/layout.ts, Demote LayoutDocument to codec-private; map to and from frames at the edge #65), so readPdf/writePdf never touch document-schema.js's content model.
  • src/content-read.ts and src/content-write.ts are PDF content streams (the graphics operator sequence), not ContentDocument. Both are internal and unexported. The only occurrences of the string ContentDocument anywhere under src/ are in comments explaining what a sourcePath value points back at.
  • No reconstruction module exists here, by charter. documents.js owns reconstructWordprocessing/reconstructPresentation/reconstructDrawing/reconstructSpreadsheet and calls readPdf from its own composition graph.

So the rename half of the plan (readPdf -> readPdfContent, new tree-native readPdf) has nothing to rename, and the wrapper half would have to invent the missing piece rather than wrap it. Reading, that means owning a geometry-to-structure reconstruction heuristic; writing, a font-measuring, line-breaking layout engine. Both are semantic policy that documents.js already owns, and either one here would point this package at the package that depends on it.

The change is therefore documentation only: the barrel header and the README's usage section now say that the absence is deliberate, and point a caller wanting PDF to or from a DocumentPackage at convertDocument's onDocument callback and ConversionResult.package in documents.js. Worth writing down because the next reader hitting readPdf with the sibling packages' new API in mind will otherwise ask exactly this question, and the plausible-looking answer is the wrong one.

document-schema.js needed no bump: origin/main is already on ^4.3.0, and the lockfile resolves 4.3.0.

typecheck, lint, test (1119 tests), test:workers, and build are all green.


Generated with Claude Code

Every other codec in this family reads its format into the flat
ContentDocument, so each can layer a tree-native entry point on top of
its own flat one -- decompose/assemblePackage outward, flattenPackage
back, now that document-schema.js 4.3.0 exports all four.

PDF cannot follow that pattern in either direction.
A PDF states positions, not structure:
readPdf yields layout cheaply because positioned glyphs and paths are
all the format actually carries, and semantic content comes only from a
separate, lossy reconstruction pass that infers paragraphs, headings,
tables, and shapes back out of geometry.
The write direction is asymmetric for the same reason -- a DocumentPackage
reaches PDF bytes only through a font-measuring, line-breaking layout
engine, and writePdf takes the positioned LayoutDocument that engine
produces.
Both passes are semantic policy rather than codec business and live in
documents.js, which also means a wrapper here would invert the dependency
onto the package that already depends on this one.

Records that in the barrel header, next to the readPdf/writePdf exports
a reader would otherwise expect a package-native pair beside, and in the
README's usage section, naming convertDocument's onDocument callback and
ConversionResult.package as where a caller gets a PDF as a tree.
The write-direction claim was wrong: turning a DocumentPackage into PDF bytes
does not need a font-measuring, line-breaking layout engine. documents.js's
buildDocumentBytes reaches PDF only for a package that already carries frames
from a prior layout pass, and layoutDocumentFromPackage is a mechanical walk
of those existing positions, not a layout pass of its own; a frameless
package (a bridge conversion's own dump) cannot reach PDF at all. Restate the
real asymmetry: read needs a lossy geometry-to-structure reconstruction,
write needs frames a layout pass already stamped, and both the stamping and
the walk-back live in documents.js.

Also fix three adjacent inaccuracies in the same passage: convertDocument
returns bytes only and never exposes ConversionResult.package, which is
populated separately by createLocalDocumentConverter()'s DocumentConverter
port; the #65 citation quoted only the reconstruction-stays-
in-documents.js bullet while omitting that the frames-mapping half it scoped
to this package was never implemented here; and "every other codec reads
into ContentDocument" doesn't hold at the codec level -- ooxml.js's
readDocx/readPptx and odf.js's readOdt/readOds return their own native
models, and it's documents.js's own readXContent wrapper layer that projects
each into the flat ContentDocument.
@Mearman
Mearman merged commit 707341d into main Aug 19, 2026
11 checks passed
@Mearman
Mearman deleted the feat/document-package-api branch August 19, 2026 06:26
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.0.4 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant