Skip to content

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

Open
fcbwilliams wants to merge 1 commit into
mainfrom
feat/content-origin
Open

feat(document-schema.js): record what a node's content was in the source#1202
fcbwilliams wants to merge 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant