feat(document-schema.js): record what a node's content was in the source - #1202
Open
fcbwilliams wants to merge 1 commit into
Open
feat(document-schema.js): record what a node's content was in the source#1202fcbwilliams wants to merge 1 commit into
fcbwilliams wants to merge 1 commit into
Conversation
fcbwilliams
commented
Sep 10, 2026
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.
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.