Skip to content

feat(document-schema.js): record what a node's content was in the source - #1202

Merged
Mearman merged 1 commit into
mainfrom
feat/content-origin
Sep 11, 2026
Merged

feat(document-schema.js): record what a node's content was in the source#1202
Mearman merged 1 commit into
mainfrom
feat/content-origin

Conversation

@fcbwilliams

Copy link
Copy Markdown
Member

The content model deliberately flattens different source constructs onto
the same node, and a consumer holding one cannot tell which it has. A
`ContentTable` is a native table, a chart's cached series/category data,
or a spreadsheet range; a `ContentParagraph` is body prose or a SmartArt
node's label.

That distinction is not cosmetic. A chart's cached numbers are exact and
quotable; a SmartArt diagram's labels have lost the relationships
between them (a five-stage process arrives as five labels with no
indication it is a sequence); and once a vision pass exists, an image's
recovered text is a model's reading rather than the document's words.
A consumer that cannot tell them apart treats all three as equally
authoritative.

`ContentOrigin` is `"chart" | "diagram" | "image"`, optional on
`ContentParagraph`, `ContentTable` and `ContentImageBlock` -- the three
variants that can carry content from a construct other than their own
kind. Absence is the common case and means the node is exactly what its
kind says: authored body content. Deliberately not added to
`pageBreak`/`constructStart`/`constructEnd`, which have no content to
have an origin for.

Each value is here because a reader can actually distinguish it and a
consumer can act on it; the vocabulary is open to extension rather than
complete. `styleId` was not a candidate: it is a producer's own style
name, meaningful only to a consumer that already knows that producer's
convention, and it says nothing at all for a chart or a diagram.

ooxml.js sets the two it can today: `readChartTable` marks its table
`"chart"`, and `readDiagramText` marks every node paragraph `"diagram"`.
`"image"` is reserved for the vision work in #1197 and set by nobody
yet.

Additive and optional throughout, so no existing document, reader,
writer or consumer changes behaviour.

Two notes for review, both places the change had to be made twice:

`ContentTable`'s TypeScript interface is hand-written rather than
inferred (z.lazy collapses a recursive child to `unknown` in the pinned
Zod version), so the field is declared on both the interface and the
schema. Adding it to only one compiles away silently -- the runtime
validated it while `tsc` denied it existed, which is how I found this.

Six hand-authored JSON Schema fragments needed it, not three:
`HeadingParagraph`, `ListParagraph` and `ContentSheetImage` inherit the
field by extending their base schemas. The live-`z.toJSONSchema()`
comparison test caught every one.

Refs #1197.
@Mearman
Mearman force-pushed the feat/content-origin branch from a04805f to e6f10c3 Compare September 11, 2026 03:09
@Mearman

Mearman commented Sep 11, 2026

Copy link
Copy Markdown
Member

Your branch is rebased onto current main with the representation side resolved against the landed schema work: the schema-side hunks of your PR (the three-value ContentOriginSchema, the per-node field additions, the JSON-fragment edits) are superseded by what #1204 and #1208 already merged — the shared origin enum admits all three of your values, and the hand-written interfaces now carry the fields (the omission was a genuine #1204 defect your wiring's typecheck caught, fixed in #1208).

What your branch now carries is the durable part: the ooxml.js reader wiring (readChartTable with origin: 'chart', the SmartArt origin: 'diagram' mapping, and the tests). That is exactly the reader-side follow-on #1197 named, and it validates against the shared enum unchanged.

One naming note: your absence-means-authored-body reading is preserved by the merged shape — absence on the six-value enum still means "the reader has nothing to say", so nothing in your wiring needs to mark ordinary prose.

@Mearman
Mearman merged commit f4b4901 into main Sep 11, 2026
22 checks passed
@Mearman
Mearman deleted the feat/content-origin branch September 11, 2026 03:23
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 8.12.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants