This repository was archived by the owner on Aug 20, 2026. It is now read-only.
Give the typed readers a DocumentPackage-native API - #66
Merged
Conversation
readOdt, readOdp, readOdg, readOds, and readOdfFormula now return document-schema.js's DocumentPackage -- the hierarchical artefact where structure, layout, and content are one tree -- instead of a flat, format-local shape. Each is its flat reader plus document-schema.js's assemblePackage: decompose the content into the tree, splice the envelope onto the root, mint the styles table. assemblePackage rather than bare decompose because a reader is a package construction site and owes its caller a whole package, which is the same call documents.js's conversion pipeline already makes at every package it builds. No pages argument is passed: rendered page geometry only exists after a layout pass, so a reader has none to report. The flat readers keep their behaviour under *Content names and remain the right level for a caller working in the flat codec-exchange form. Each package-native reader calls its own *Content sibling, so the two levels are one read of the file. Round-trip tests per format assert schema validity with no stray fields, flattenPackage reproducing the flat reader's own output exactly over real fixture bytes, and factorStyles re-minting the identical table. The workers suite covers the package-native path too, since assemblePackage is a second package's code running in the same isolate. BREAKING CHANGE: the flat typed readers move to *Content names, freeing the bare names for the DocumentPackage-native readers: readOdt -> readOdtContent, readOdp -> readOdpContent, readOdg -> readOdgContent, readOds -> readOdsContent, readOdfFormulaDocument -> readOdfFormulaContent, and readOdfFormula -> readOdfFormulaMathMl. Behaviour is unchanged in every case; each new bare name returns a DocumentPackage, which is assignable to none of the old return types, so an unmigrated call site fails to compile rather than changing meaning silently.
The README documented one reader per format returning a format-local shape. It now documents both levels each reader has -- the DocumentPackage the bare name returns and the flat *Content function beneath it -- with a per-format table, the flattenPackage equality that relates them, and a migration table for the renamed flat functions. Also corrects the schema dependency's description: LayoutDocument left document-schema.js for pdf-codec, and DocumentPackage is what odf.js shares with ooxml.js alongside ContentDocument.
…af nodes DocumentPackageSchema.parse does not strip or reject an unrecognised key on a leaf node. Group descriptors are .strict() and isGroupWrapper restricts a group node's own keys to node/style/children, so a stray key on a GROUP node makes the parse throw. A leaf is validated by a z.custom guard, which returns its input unchanged on success rather than a stripped, reparsed value, so a stray leaf key survives undetected by expect(parse(pkg)).toEqual(pkg).
…ation section readOdbForm does read an embedded document via readOdtContent, since a form's sub-document is a complete, ordinary ODF text document -- so the prior claim that none of the untouched readers reads document content was wrong for this one. It still gets no package-native form, because that OdtDocument is nested inside the form's own control-tree return value rather than being the function's own top-level return.
Replace the "previously the bare readOdX name" / "before this landed" framing in src/index.ts and src/typed/formula/read.ts with comments that state only the evergreen fact: why each ladder exists and which level a caller should reach for. The old wording described one specific rename rather than a lasting property of the code; the README's migration table is already the correct home for the old-to-new name mapping.
… page The "shapes as groups" assertion only inspected the fixture's first page, which has zero shapes, so it passed even when shape-group assembly was mutated away entirely -- the children-length check reduces to vectors.length alone when shapes.length is zero. Extend the same assertions to the second page, which has one shape and no vectors, so a dropped shape group now fails the length check.
Contributor
|
🎉 This PR is included in version 5.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
readOdt,readOdp,readOdg,readOds, andreadOdfFormulanow returndocument-schema.js'sDocumentPackagerather than a flat, format-local shape. Each is its existing flat reader plusassemblePackage— decompose into the tree, splice the envelope onto the root, mint the styles table — which is the same calldocuments.jsmakes at every package it builds. Nothing is passed forpages: a reader runs before any layout pass, so there is no rendered page geometry to report.The flat readers are untouched behaviourally and keep working under
*Contentnames, which is still the right level for anything working in the flat codec-exchange form (documents.js's conversion pipeline reads there today). A package-native reader calls its own*Contentsibling, so both levels are one read of the file and cannot disagree.Breaking, hence the major: the bare names now belong to the package-native readers.
readOdtreadOdtContentreadOdpreadOdpContentreadOdgreadOdgContentreadOdsreadOdsContentreadOdfFormulaDocumentreadOdfFormulaContentreadOdfFormulareadOdfFormulaMathMlEvery new bare name returns a
DocumentPackage, which is assignable to none of the old return types, so an unmigrated call site is a compile error rather than a silent change of meaning.documents.jsis the one in-family caller and will need the rename applied.readOdmand most.odbreaders are deliberately left alone: a master document's chapters are external file references andreadOdbInventory/readOdbReportdescribe structure rather than content, so none of those three has aContentDocumentto decompose.readOdbFormdoes read an embedded ODF text document viareadOdtContent— a form's sub-document is a genuine, complete ODF text document — but that result is nested inside the form's own control-tree return value rather than being the function's own top-level return, so it doesn't get a package-native form either.On testing: each format gets a round trip over its real fixture rather than a no-throw check —
DocumentPackageSchema.parsecompared back against the input (proving the package satisfies document-schema.js's own tree guards, though only a stray key on a group node is actually rejected by this; a leaf's z.custom guard passes a stray key through unchanged),flattenPackagereproducing the flat reader's own output exactly, andfactorStylesre-minting the identical table. That last pair is as close to bytes → package → bytes as this package can get, since it has readers and no writers. The workers suite exercises the package-native path too, becauseassemblePackageis a second package's code running in the same isolate and its Worker-safety shouldn't be assumed.Typecheck, lint, unit, workers, build, and smoke are all green locally.
🤖 Generated with Claude Code