@docx-editor.dev/core/store
@docx-editor.dev/core/store — the canonical OOXML tree and the only write path into it.
Bytes become a typed-where-layout-needs-it, generic-everywhere-else tree. Every mutation is a TreeDocOp addressed by node id plus UTF-16 offset, applied in one transaction, so a batch refused halfway leaves the document exactly as it was.
This is also the trust boundary: zip and XML limits, entity-free parsing, OPC name validation, and inert executable content all live here, because everything downstream assumes a sanitized projection.
Functions (300)
addCommentfunctionSource ↗
Add a comment, or a reply, in ONE transaction.
The comment id and the w14:paraId are computed before the transaction opens, because the story markers have to carry the same id the body does and deriving each separately is how the two come to disagree.
w14:paraId is minted here and only here: on a comment WRITE. Allocating on load would rewrite a document nobody edited and break fingerprint equality on an untouched round trip.
declare function addComment(store: TreeDocumentStore, request: AddCommentRequest): AddCommentResult;allocateContentControlIdfunctionSource ↗
The next w:id to write, seeded from the document's own maximum plus one.
Never a clock, a timestamp, a random source or a hash: those collide with ids already in the file and produce values Word rejects. Null when the document already reaches the signed 32-bit bound, so the caller refuses rather than wrapping into a negative id.
declare function allocateContentControlId(root: OoxmlNode): number | null;allocateDrawingPropertyIdfunctionSource ↗
Mint a wp:docPr id unused anywhere in the package.
Package-wide rather than per-part: Word treats these ids as document-global, and a collision makes it renumber on open.
declare function allocateDrawingPropertyId(pkg: OoxmlPackage): DrawingPropertyIdResult;allocateNoteIdfunctionSource ↗
Allocate the next positive signed 32-bit note id for a notes-part root. Seeds from max(existing)+1; never returns ≤0; null on exhaustion.
declare function allocateNoteId(notesRoot: OoxmlNode): number | null;applyEditsfunctionSource ↗
Apply several primitives as ONE atomic step.
Each edit runs against the result of the previous one, and the whole sequence is validated once at the end. If any step fails, the ORIGINAL part is what the caller keeps — there is no partially-edited intermediate to publish. This is the shape a multi-DocOp store transaction needs.
declare function applyEdits(part: OoxmlPart, edits: readonly ((current: OoxmlPart) => OoxmlEditResult)[], options?: EditOptions): OoxmlEditResult;applyHeaderFooterLifecycleOpfunctionSource ↗
Apply one furniture lifecycle op atomically. Rejected ops leave the input package untouched (pure function — callers discard the result).
declare function applyHeaderFooterLifecycleOp(pkg: OoxmlPackage, op: HeaderFooterLifecycleOp): HeaderFooterLifecycleResult;applyNoteLifecycleOpfunctionSource ↗
Apply one note lifecycle op atomically. Rejected ops leave the input package untouched.
declare function applyNoteLifecycleOp(pkg: OoxmlPackage, op: NoteLifecycleOp, options?: NoteLifecycleOptions): NoteLifecycleResult;applyTreeOpfunctionSource ↗
Apply one validated op to a part.
Validation runs first and returns before any tree work, so a rejected op is a true no-op: the caller keeps the part it passed in, unchanged and still frozen.
options.deferValidation passes through to the edit primitives: a transaction applying many ops re-validates the whole part once at its commit boundary rather than after every primitive, which is the difference between a paste that is linear and one that is quadratic in document size.
declare function applyTreeOp(part: OoxmlPart, op: TreeDocOp, options?: EditOptions): TreeOpResult;asciiFoldfunctionSource ↗
ASCII-only lowercase fold. OPC part-name/extension equivalence is US-ASCII case-insensitive; a locale toLowerCase() mis-folds e.g. Turkish I/İ and could let two "equivalent" part names evade duplicate detection.
declare function asciiFold(s: string): string;assertLimitInvariantsfunctionSource ↗
Assert the finite-default / hard-ceiling invariant holds for every limit.
declare function assertLimitInvariants(): void;assertValidIdfunctionSource ↗
Validate an identifier, throwing when it is malformed.
Throws rather than returning: a bad id is an author mistake at registration time, not file input, and accepting it would produce a registry whose identities silently collide.
declare function assertValidId(id: string, kind?: IdKind): void;assertValidQNamefunctionSource ↗
Validate a qualified name, throwing when it is malformed.
Guards the serializer: an invalid QName written into XML produces a file Word cannot open, so it fails here rather than at save.
declare function assertValidQName(name: string): void;atomicFieldSpansOffunctionSource ↗
Collect well-formed atomic field spans in document order.
Demotion (no span emitted — callers surface interior text normally): - end without matching begin - orphan instrText outside an open field - missing end before paragraph end - nesting deeper than maxNesting - instruction longer than maxInstructionChars (still forms a span when begin/end pair closes, but callers may treat evaluation as inert; addressing stays atomic)
Cross-paragraph fields never form: this walk is per paragraph.
declare function atomicFieldSpansOf(paragraph: OoxmlParagraphNode, options?: {
readonly maxNesting?: number;
readonly maxInstructionChars?: number;
}): readonly AtomicFieldSpan[];atomicNoteSpansOffunctionSource ↗
Collect typed note atoms in document order (one segment each).
Walks the same paragraph-inline surface as segmentsOf / walkParagraphInline: hyperlinks and content controls flatten; only direct run children contribute atoms. A demoted run-inner SDT husk stays opaque — no phantom addressable hit.
declare function atomicNoteSpansOf(paragraph: OoxmlParagraphNode): readonly AtomicNoteSpan[];authorableHyperlinkTargetfunctionSource ↗
The target this engine would write for url, or null when it would write none.
The VALIDATION half of [ensureHyperlinkRelationship](ensureHyperlinkRelationship), exported so a caller that must decide "would this be authored?" before it is allowed to change the package can ask without changing it. A relationship outlives a refusal — it lives beside the trees, outside the undo stack — so a caller planning a batch that may yet be refused has to ask this and mint later.
Same rules, one implementation: sanitizeHref's allowlist, a bound on the length, XML-writable text, and the absolute-URI gate the READ side applies. There is no legitimate reason for this engine to author a scheme it would refuse to open.
declare function authorableHyperlinkTarget(url: string): string | null;authoredDocumentEndnotePropertiesfunctionSource ↗
Authored document-level endnotePr from settings.
declare function authoredDocumentEndnoteProperties(settings: OoxmlPart | null | undefined): AuthoredNoteProperties | undefined;authoredDocumentFootnotePropertiesfunctionSource ↗
Authored document-level footnotePr from settings.
declare function authoredDocumentFootnoteProperties(settings: OoxmlPart | null | undefined): AuthoredNoteProperties | undefined;authoredEndnotePropertiesFromSectPrfunctionSource ↗
Authored endnotePr on a sectPr node.
declare function authoredEndnotePropertiesFromSectPr(sectPr: OoxmlNode | null | undefined): AuthoredNoteProperties | undefined;authoredFootnotePropertiesFromSectPrfunctionSource ↗
Authored footnotePr on a sectPr node.
declare function authoredFootnotePropertiesFromSectPr(sectPr: OoxmlNode | null | undefined): AuthoredNoteProperties | undefined;authoredPropertiesfunctionSource ↗
What a container itself authors, narrowed to the names an op is allowed to carry.
declare function authoredProperties(container: OoxmlNode | undefined, authorable: ReadonlySet<string>): readonly OoxmlProperty[];beginOperationfunctionSource ↗
Begin an operation, capturing its immutable environment snapshot.
Resolves and freezes limits and configuration, carves the root budget, and creates the cancellation controller — everything downstream work needs, fixed for the operation's duration.
declare function beginOperation(init: OperationInit): OperationContext;bodyStoryRootfunctionSource ↗
The main body story of a part, or null when the part holds none.
declare function bodyStoryRoot(part: OoxmlPart): OoxmlNode | null;bookmarkPairNodesfunctionSource ↗
Create bookmarkStart/End pair nodes for insertion at the start of a paragraph.
declare function bookmarkPairNodes(mint: () => string, name: string, id: string): {
readonly start: OoxmlNode;
readonly end: OoxmlNode;
};boundCustomXmlNodeIdOffunctionSource ↗
The node id one control binds to in the named store, or null when it binds to nothing there.
declare function boundCustomXmlNodeIdOf(control: OoxmlNode, storeItemId: string): string | null;boundCustomXmlNodeIdsfunctionSource ↗
Every node id the story's controls bind to in one store, in document order.
This is the input the orphan sweep takes: a node whose id is not in here is one no control names, whether it was deleted in this editor or in Word. Reading it from the STORY rather than from a host's bookkeeping is what makes the two cases one mechanism.
declare function boundCustomXmlNodeIds(part: OoxmlPart, storeItemId: string): Set<string>;boundCustomXmlNodeIdsInPackagefunctionSource ↗
Every node id ANY story in the package binds, in one store.
THE WHOLE PACKAGE, not one story. A payload is reachable from a header as easily as from the body — Word enumerates its data store from the main part, but nothing stops a control elsewhere quoting the same w:storeItemID — and the two callers that decide what is an orphan both destroy data when they are wrong. The sweep would collect a payload a header still paints; the export would strip a store a header still names, which is a document Word offers to repair.
Costs one walk per story per store, on open and on export. Neither is a keystroke.
declare function boundCustomXmlNodeIdsInPackage(pkg: OoxmlPackage, storeItemId: string): Set<string>;buildBookmarkIndexfunctionSource ↗
Build name -> position for every bookmark start in a part, in document order.
FIRST IN DOCUMENT ORDER WINS on a duplicate name. Word treats a repeated bookmark name as the same bookmark and jumps to the first, and the alternative — last-wins — makes a jump target move when an edit far away happens to duplicate a name.
The offset is measured the way the ops measure: text of the runs before the marker inside its own paragraph, hyperlink runs included, so the position a jump places the caret at is a position setSelection accepts.
declare function buildBookmarkIndex(part: OoxmlPart): BookmarkIndex;buildContentTypeIndexfunctionSource ↗
Build a resolved content-type index, failing closed on conflict/duplicate/MIME errors. maxRecords bounds the combined record count (N/N+1 gate).
declare function buildContentTypeIndex(records: ContentTypeRecords, maxRecords?: number): IndexResult;buildRelationshipSetfunctionSource ↗
Group relationships by owner in authored order; reject duplicate ids per owner.
declare function buildRelationshipSet(records: readonly RelationshipRecord[]): RelationshipSetResult;buildTocContentControlfunctionSource ↗
Build an SDT-wrapped complex TOC field with an already planned cached result.
declare function buildTocContentControl(mint: () => string, entries: readonly TocEntryPlan[], instruction: TocInstruction, alias: string): OoxmlNode;buildTocEntryParagraphfunctionSource ↗
Build one TOC entry paragraph node.
declare function buildTocEntryParagraph(mint: () => string, entry: TocEntryPlan, instruction: TocInstruction, paragraphPropertiesTemplate?: OoxmlNode): OoxmlNode;canonicalizefunctionSource ↗
Produce a canonical string for value, dropping any object key whose name is in ephemera at any depth. Numbers are emitted losslessly; -0 normalizes to 0; non-finite numbers are rejected (they must never enter a comparator input).
declare function canonicalize(value: unknown, ephemera?: ReadonlySet<string>): string;canonicalOoxmlFingerprintfunctionSource ↗
Repository-owned namespace-aware semantic XML oracle.
declare function canonicalOoxmlFingerprint(value: OoxmlPart | OoxmlNode): string;cascadeDeletedNoteReferencesfunctionSource ↗
Remove note bodies for references that disappeared between two package snapshots. Used when deleteText or deleteBlock removes a noteReference atom so body+ref stay one undo unit.
Each snapshot gets an independent full visited/part budget. If either scan truncates the cascade fails closed so a hostile package cannot skip body deletion silently — without accidentally halving capacity by charging both walks to one counter.
declare function cascadeDeletedNoteReferences(before: OoxmlPackage, after: OoxmlPackage, options?: CascadeDeletedNoteReferencesOptions): OoxmlPackage | null;cascadeEmptiedCommentsfunctionSource ↗
Delete every comment the edit between before and after emptied.
The shape cascadeDeletedNoteReferences established: a before/after diff rather than a rule inside each op, because the ops that can empty a range are several (deleteText, deleteBlock, a row deletion, accepting a tracked deletion) and a rule written into each one drifts.
THE TEST, exactly. A comment dies when the words it covered are gone and nothing still places it: either every marker naming it went with them, or its markers are all still there with no characters left between them. What it deliberately does NOT do is read "no usable range" as "emptied" — a comment whose w:commentRangeStart was carried off by a deleted block still has its reference and its end, and Word keeps it, because the reference is the element that anchors a comment. Reaping there deleted a remark whose text was still on screen, which is the one mistake worse than leaving a stale card.
SKIPS rather than refuses when the package is too large to scan. Returning null there made transact roll the edit back, so on a package past the part cap every keystroke in a commented paragraph was silently refused and the document read as frozen. A skipped reap leaves a stale card — recoverable, visible, and the behaviour before any of this existed. Null is reserved for a removal that actually failed, which the caller must roll back.
declare function cascadeEmptiedComments(before: OoxmlPackage, after: OoxmlPackage): OoxmlPackage | null;childElementsfunctionSource ↗
All direct child elements with the given name.
declare function childElements(node: Extract<XmlNode, {
type: 'element';
}>, name: string): Extract<XmlNode, {
type: 'element';
}>[];collectFlowBlocksfunctionSource ↗
Collect paragraph and table blocks from a sibling list, flattening through content-control wrappers up to [MAX_CONTENT_CONTROL_NESTING](MAX_CONTENT_CONTROL_NESTING).
accept filters which typed blocks are kept (e.g. skip revision-removed paragraphs). When nesting exceeds the bound the wrapper is skipped entirely — same fail-closed rule as the historical storyBlocks walk.
declare function collectFlowBlocks(children: readonly OoxmlNode[], depth?: number, accept?: (block: OoxmlElement) => boolean): OoxmlElement[];collectNodeIdsfunctionSource ↗
Every node id currently present in the part.
declare function collectNodeIds(part: OoxmlPart): Set<string>;collectNoteReferencesfunctionSource ↗
Walk a part for addressable typed note references. Bounded by visited nodes; skips deep hostile nesting by marking the shared budget truncated. When budget is supplied it is shared and mutated in place. Hits are segment-aligned (segmentsOf); demoted wrappers never invent atomOffsets.
declare function collectNoteReferences(part: OoxmlPart, options?: {
readonly maxHits?: number;
readonly budget?: NoteReferenceScanBudget;
}): readonly NoteReferenceHit[];collectPackageNoteReferencesfunctionSource ↗
Collect references across every XML part under one shared part + visited-node budget.
declare function collectPackageNoteReferences(pkg: OoxmlPackage, options?: {
readonly budget?: NoteReferenceScanBudget;
readonly maxHits?: number;
}): readonly NoteReferenceHit[];collectReviewItemsfunctionSource ↗
Everything the review surface lists, in document order.
Order is by paragraph position within the story, then by offset. A comment and the revision it covers therefore arrive together, which is what lets a surface group them. Furniture stories rank after the body in one merged order — their geometry (the page they first paint on) is a layout question the queue deliberately does not answer.
declare function collectReviewItems(input: ReviewModelInput): ReviewItem[];collectRevisionSitesfunctionSource ↗
Every revision-bearing element in the part, with the classification that decides whether it can be resolved.
One walk, so accept-all does not pay a traversal per revision — and paragraphs the last commit did not touch are answered from [paragraphSitesCache](paragraphSitesCache) rather than re-walked.
declare function collectRevisionSites(part: OoxmlPart): RevisionSite[];collectSectionPropertyNodesfunctionSource ↗
w:sectPr nodes in section order, aligned with layout's enumerateDocumentSections.
null means a section with no w:sectPr node (Word defaults, inherits HF from previous). Paragraph-level breaks first; the final entry covers remaining blocks (body-level or null).
declare function collectSectionPropertyNodes(root: OoxmlNode): Array<OoxmlElement | null>;collectStoryParagraphsfunctionSource ↗
The block walk itself, appending into out.
Exported so allParagraphs in the binding lane is the same traversal rather than a second copy of it.
declare function collectStoryParagraphs(children: readonly OoxmlNode[], out: OoxmlNode[], sdtDepth: number): void;commentAnchorsOfStoryfunctionSource ↗
Every comment anchor in one story, in document order.
Overlapping and nested ranges are supported because each anchor is resolved independently — Word produces both, and a model that assumed ranges nest cleanly would mis-anchor them.
A start with no matching end anchors to the end of its own paragraph and is reported orphaned rather than guessed at: extending it to the next end marker would attach a reviewer's remark to text they never saw.
declare function commentAnchorsOfStory(part: OoxmlPart): CommentAnchor[];commentBodyTextfunctionSource ↗
Plain text of a comment's body, so a card never re-implements the run walk.
declare function commentBodyText(comment: CommentRecord): string;commentInitialsfunctionSource ↗
Author initials for an avatar, from @w:initials or the name.
declare function commentInitials(comment: CommentRecord): string;commentItemsOffunctionSource ↗
Comment cards, threaded however the file says so and flat when nothing says so.
ECMA-376 §17.13.4.2 gives CT_Comment no parent pointer, so threading is never something the standard states outright. Three sources, strongest first: @w15:paraIdParent, then @w16cid:parentId — both in namespaces outside Part 1 — and finally a COINCIDENT anchor, a comment whose w:commentRangeStart/End cover exactly the characters an earlier comment's cover. The ranges are Part 1's own vocabulary and the only part of a thread that survives a producer dropping the extension parts. Coincidence is the last resort and never overrides a stated link.
Deliberately not containment. A remark on one word inside another remark's sentence nests without being a reply, and reading that as a thread would bury an independent comment inside someone else's.
declare function commentItemsOf(comments: readonly CommentRecord[], anchors: readonly {
commentId: string;
partName: string;
start: ReviewPosition;
end: ReviewPosition;
orphaned: boolean;
}[], threadState: ReadonlyMap<string, CommentThreadState>): ReviewCommentItem[];commentPartNameOffunctionSource ↗
Exposed so a surface can tell "no comment part yet" from "no comments".
declare function commentPartNameOf(pkg: OoxmlPackage, storyPartName: string): string;commentsExtendedPartNameOffunctionSource ↗
The commentsExtended.xml a story points at.
Exported for the same reason as [commentPartNameOf](commentPartNameOf): the READER has to resolve the same name the writer does. Hardcoding /word/comments.xml on one side and following the relationship on the other is a split that shows up as a comment written and never read back.
declare function commentsExtendedPartNameOf(pkg: OoxmlPackage, storyPartName: string): string;commentsOfPartfunctionSource ↗
The comments in word/comments.xml, in authored order.
Every value here comes from a file an attacker fully controls, so nothing is interpreted: author, initials and date are carried verbatim for a surface that will set them as TEXT.
declare function commentsOfPart(part: OoxmlPart): CommentRecord[];compareArtifactsfunctionSource ↗
Compare two artifacts under a named comparator. canonical-exact and exact compare canonical forms (exact drops no ephemera). tolerance requires an epsilon and compares finite numbers structurally. sync-optimization-only throws — such artifacts are never an equivalence basis.
declare function compareArtifacts(name: ComparatorName, left: unknown, right: unknown, opts?: {
epsilon?: number;
}): ComparisonResult;compareSemVerfunctionSource ↗
Order two versions: negative, zero or positive, by major then minor then patch.
declare function compareSemVer(a: SemVer, b: SemVer): -1 | 0 | 1;containsCssFetchfunctionSource ↗
Whether a file-derived CSS fragment contains a url() or @import (must be rejected).
declare function containsCssFetch(value: string): boolean;contentControlContentChildrenfunctionSource ↗
The children of a wrapper's w:sdtContent, typed or demoted, in order.
The one place that knows a control's content is reached through an intermediate element, so the four flattening walks (story blocks, layout, header/footer references, list resolution) ask the same question rather than each re-deriving it.
declare function contentControlContentChildren(wrapper: OoxmlNode): readonly OoxmlNode[];contentControlContentNodeOffunctionSource ↗
A control's w:sdtContent, or null when the wrapper has none.
declare function contentControlContentNodeOf(control: OoxmlNode): OoxmlContentControlContentNode | undefined;contentControlContentOffunctionSource ↗
Children of the first w:sdtContent under a control, or null when absent or not a control.
declare function contentControlContentOf(node: OoxmlNode): readonly OoxmlNode[] | null;contentControlEndPropertiesNodeOffunctionSource ↗
A control's w:sdtEndPr — the run properties applied to its closing marker.
declare function contentControlEndPropertiesNodeOf(control: OoxmlNode): OoxmlContentControlEndPropertiesNode | undefined;contentControlLevelOffunctionSource ↗
How deeply a control is nested inside other controls.
Bounded by [MAX_CONTENT_CONTROL_NESTING](MAX_CONTENT_CONTROL_NESTING): nesting depth comes from a file and is a recursion bound.
declare function contentControlLevelOf(control: OoxmlNode): ContentControlLevel;contentControlPropertiesNodeOffunctionSource ↗
A control's w:sdtPr, or null. Matches structurally, so a Word-demoted node still resolves.
declare function contentControlPropertiesNodeOf(control: OoxmlNode): OoxmlContentControlPropertiesNode | undefined;contentControlPropertiesOffunctionSource ↗
Read a control's properties.
Total: a control with no w:sdtPr at all answers the same shape with the defaults an absent property means, so no caller has to branch on the container's existence.
declare function contentControlPropertiesOf(control: OoxmlNode): ContentControlProperties;contentControlsInfunctionSource ↗
Every control under a node, in document order, bounded in depth and in count.
ONE walk, shared. The nesting bound is the same one layout flattens with, so a control a lane can address is a control every lane can address — and a file that nests past it keeps its content in the tree (the serializer never stops) while no walk recurses further.
declare function contentControlsIn(root: OoxmlNode, options?: {
readonly maxDepth?: number;
readonly limit?: number;
}): readonly ContentControlEntry[];contentControlTextOffunctionSource ↗
The plain text a control's content holds, in reading order.
w:delText is excluded: struck text is not the control's value, and a dropdown whose old item is still present as a tracked deletion would otherwise report both.
declare function contentControlTextOf(control: OoxmlNode): string;contentTypesPartBytesfunctionSource ↗
Locate [Content_Types].xml bytes regardless of zip key spelling.
declare function contentTypesPartBytes(pkg: OoxmlPackage): {
readonly storageKey: string;
readonly bytes: Uint8Array;
} | null;createImageResourceCachefunctionSource ↗
Build the per-document image cache. Validated bytes only; refusals are remembered too.
declare function createImageResourceCache(initialPkg: OoxmlPackage, options: CreateImageResourceCacheOptions): ImageResourceLookup;createNodeIdAllocatorfunctionSource ↗
Mint ids for nodes an edit introduces.
Deterministic and collision-checked against the whole part: a structural-path id from the original parse (/word/document.xml#0.1.2) and a minted one (/word/document.xml#new:3) can never coincide, and the counter skips anything already taken so repeated edits in one session stay unique.
Checks the part's node index directly rather than copying every id into a fresh set: the copy was O(document) per op, and an allocator is created for every op.
declare function createNodeIdAllocator(part: OoxmlPart): () => string;createNoteReferenceScanBudgetfunctionSource ↗
A bounded budget for scanning note references, so a crafted document cannot stall a load.
declare function createNoteReferenceScanBudget(maxVisited?: number, maxParts?: number): NoteReferenceScanBudget;customMarkFollowsfunctionSource ↗
Read @w:customMarkFollows on a note reference. Returns undefined when absent; otherwise the OOXML on/off interpretation.
declare function customMarkFollows(node: OoxmlNode): boolean | undefined;customNodeBindingfunctionSource ↗
The binding for one node in one store, or null when the id cannot be addressed by an XPath.
Refuses rather than escapes: XPath 1.0 has no escape for a quote inside a literal, so an id carrying one could close the predicate and append an expression of the sender's choosing. The ids are minted by a host, so refusing is honest — see ADDRESSABLE_ID.
declare function customNodeBinding(part: CustomXmlDataPart, rootLocalName: string, nodeId: string): CustomNodeBinding | null;customNodePayloadsByControlfunctionSource ↗
The payload every control in a story binds to, keyed by the CONTROL's canonical node id.
Keyed by the control rather than by the store node because that is the question a reader actually has — "what does this chip carry" — and because two stores may each hold a cx1. Resolved here rather than by a capability package: the stores are package parts, and a derivation that only gets story parts has no way to reach them.
Every store the story relates to, so a document carrying two definitions' payloads answers for both without anyone naming a namespace.
declare function customNodePayloadsByControl(pkg: OoxmlPackage, storyPartName: string): ReadonlyMap<string, CustomNodePayloadRead>;customNodePayloadsOffunctionSource ↗
Every payload one store holds, for a caller resolving a control's data.
declare function customNodePayloadsOf(pkg: OoxmlPackage, storyPartName: string, namespaceUri: string): ReadonlyMap<string, {
readonly label: string;
readonly data: string;
}>;customXmlDataPartsfunctionSource ↗
The data parts a story relates to, in relationship order.
Reads the relationships rather than scanning /customXml/ by name: a part nothing relates to is not part of the document, and a package from a hostile sender can hold as many plausibly-named files as it likes.
declare function customXmlDataParts(pkg: OoxmlPackage, storyPartName: string): CustomXmlDataPart[];customXmlLabelXPathfunctionSource ↗
The w:xpath a binding uses to reach a node's label, or null when the id cannot be addressed.
Word needs a prefix for the payload namespace even when the store declares it as a default — an unprefixed step in an XPath means "no namespace", so /docxEditor/node would match nothing in a namespaced store. The prefix is declared in w:prefixMappings beside it.
declare function customXmlLabelXPath(prefix: string, rootLocalName: string, nodeId: string): string | null;customXmlNodesfunctionSource ↗
Every node a store holds, in document order.
declare function customXmlNodes(pkg: OoxmlPackage, partName: string): CustomXmlNode[];customXmlPrefixMappingsfunctionSource ↗
The w:prefixMappings value declaring that prefix, or null when it cannot be written. The namespace sits inside single quotes inside a double-quoted attribute, so a namespace carrying either quote character has no representation here.
declare function customXmlPrefixMappings(prefix: string, namespaceUri: string): string | null;datastoreItemIdForfunctionSource ↗
A ds:itemID derived from the seed rather than drawn at random.
Exported so a caller that authors a store OUTSIDE a package — a template engine splicing markup it will assemble into a .docx later — mints the id the same way this does, rather than inventing a second GUID shape Word has to be tolerant of.
The store is a pure function of what it is asked to write: the same document written twice has to produce the same bytes, or a save/reopen/save round trip stops being a fixed point and every digest taken over saved bytes moves. A GUID's job here is uniqueness within one package, not unguessability, so four FNV-1a passes over a salted seed carry it.
declare function datastoreItemIdFor(seed: string): string;deepParagraphOrderOfPartfunctionSource ↗
Like [paragraphOrderOfPart](paragraphOrderOfPart), but descends INTO paragraphs, so paragraphs nested in a run's content — a textbox's w:txbxContent — rank right after their host.
A separate function on purpose: the shallow order feeds the review queue's card ordering, and re-ranking nested paragraphs there would move cards. This one exists for position containment tests ("is the caret inside this range"), where a paragraph the shallow order cannot see is a position that can never match.
declare function deepParagraphOrderOfPart(part: OoxmlPart): ReadonlyMap<string, number>;deleteCommentThreadfunctionSource ↗
Delete a comment thread outright: body, thread state and story markers.
Returns the package unchanged when the id names no comment, and null when a removal was refused — a caller inside a transaction rolls back rather than committing a package whose comment is half gone.
declare function deleteCommentThread(pkg: OoxmlPackage, commentId: string): OoxmlPackage | null;deobfuscateFontfunctionSource ↗
Undo Word's embedded-font obfuscation (ECMA-376 Part 4 §2.8.1).
The key is the w:fontKey GUID's 16 bytes in REVERSED order — not the per-group little-endian reading a GUID usually gets. It is XORed over the first 32 bytes of the part, applied twice. Getting the order wrong produces a font that looks corrupt rather than obfuscated, which is indistinguishable from a damaged file at the point it fails.
Pure XOR, so the same operation obfuscates and deobfuscates.
declare function deobfuscateFont(bytes: Uint8Array, fontKey: string): Uint8Array | null;deriveOoxmlIndexesfunctionSource ↗
Derive every index from one canonical package revision.
Pure: the same package and revision always produce the same index, which is what makes "rebuild rather than mutate" a safe invalidation strategy.
declare function deriveOoxmlIndexes(pkg: OoxmlPackage, revision: number): OoxmlIndexes;detectBodyTocsfunctionSource ↗
Discover refreshable body TOCs without evaluating any field instruction.
declare function detectBodyTocs(part: OoxmlPart): readonly DetectedToc[];detectDuplicateNamesfunctionSource ↗
Detect archive entries that collide after normalization (before inflation). Returns the case-folded keys that more than one raw name maps to.
declare function detectDuplicateNames(rawNames: readonly string[]): {
readonly duplicates: readonly string[];
readonly rejected: readonly {
raw: string;
reason: NameRejection;
}[];
};diagnoseNoteReferencesfunctionSource ↗
Load diagnostics for dangling note references. Fail-open: never throws or mutates; returns diagnostics for callers to surface. Does not invent missing note bodies.
When the hard visited/part budget truncates or the soft hit cap binds, appends a single note-reference-scan-truncated entry so incomplete coverage is visible without breaking consumers that filter on dangling-note-reference.
declare function diagnoseNoteReferences(pkg: OoxmlPackage): readonly NoteDiagnostic[];diffSemanticDigestsfunctionSource ↗
Every way two digests differ, as readable paths.
Returns the differences rather than a boolean because "the round trip lost something" is useless without saying what — the failure this oracle exists to catch is a silent drop, and a bare false reproduces the silence.
declare function diffSemanticDigests(before: SemanticDigest, after: SemanticDigest): DigestDifference[];digestPartfunctionSource ↗
Digest one part: its paragraphs, and the structure that holds them.
declare function digestPart(part: OoxmlPart): StoryDigest | null;directParagraphMarkPropertiesfunctionSource ↗
What a paragraph MARK itself authors: w:pPr/w:rPr, narrowed to the run vocabulary.
Same rule as a run's own w:rPr, for the same reason — the mark is a run property container, and setParagraphMarkProperties rewrites the names its op carries.
declare function directParagraphMarkProperties(part: OoxmlPart, paragraphId: string): readonly OoxmlProperty[];directParagraphPropertiesfunctionSource ↗
What a paragraph itself authors: its own w:pPr, narrowed to what an op can express.
Properties outside the vocabulary are dropped from the OP, not from the paragraph: the applier keeps every w:pPr child an op cannot name (the mark, w:sectPr, w:pBdr, w:outlineLvl) exactly as authored.
declare function directParagraphProperties(part: OoxmlPart, paragraphId: string): readonly OoxmlProperty[];drawingOpImpactfunctionSource ↗
Impact class for a drawing op — metadata/locks are text-local; geometry/wrap are flow-structural.
declare function drawingOpImpact(op: DrawingTreeDocOp): ImpactClass;endOperationfunctionSource ↗
Release the operation's root budget (requires every child/reservation released).
declare function endOperation(ctx: OperationContext): void;ensureHyperlinkRelationshipfunctionSource ↗
The external hyperlink relationship for url on ownerPart (default: main document), reusing an existing one with the same target, or null when the URL is not something to write.
REUSE IS BY EXACT TARGET, matching Word: linking twice to the same address produces one relationship. It is safe because a hyperlink relationship carries nothing but its target — two links sharing one are indistinguishable from two links with identical targets, and retargeting one always mints rather than rewriting (see the edit op).
Ownership follows the story that holds the w:hyperlink: a header/footer or notes part mints into that part's .rels, never into document.xml.rels. Passing an owner the package does not declare fails closed (null) so a scoped insert cannot leave a stray body relationship behind.
The URL is refused unless sanitizeHref admits it. Storing a javascript: target that a FILE authored is required — round-tripping never rewrites a document — but AUTHORING one here is not: there is no legitimate reason for this engine to write a scheme it would then refuse to open, and writing it would hand the next reader a live target this reader made.
declare function ensureHyperlinkRelationship(pkg: OoxmlPackage, url: string, ownerPart?: string): EnsuredHyperlinkRelationship | null;ensureListDefinitionfunctionSource ↗
Find or create a list definition of kind, returning the package that holds it.
An existing definition of the same kind is REUSED rather than duplicated: Word does the same, and a document that gains one w:abstractNum per toggled paragraph becomes unreadable. Returns null only when the part cannot be built at all.
declare function ensureListDefinition(pkg: OoxmlPackage, kind: ListKind): EnsuredListDefinition | null;ensureNumberingLevelfunctionSource ↗
Declare level in the definition numId names, with Word's default format for that level, or refuse.
Word never greys Increase Indent out on a list item: demoting past the deepest level a w:abstractNum declares makes Word DEFINE the level, cycling its stock bullets (Symbol •, Courier o, Wingdings ▪) or number formats (decimal, lowerLetter, lowerRoman) by depth. This is that write. An already-declared level returns the package unchanged, so callers may ask first and act second without a second lookup.
A delegating definition (w:numStyleLink, 17.9.21) is refused: its levels live on the linked style's definition, and a w:lvl grafted here would be shadowed the moment the link resolves.
declare function ensureNumberingLevel(pkg: OoxmlPackage, numId: string, level: number, kind: ListKind): OoxmlPackage | null;escapeCssStringfunctionSource ↗
CSS string-escape a file-derived value (e.g. an @font-face family name or an inline style value). Emits \<hex> escapes for quotes, backslash, and controls so the value cannot break out of its CSS string.
declare function escapeCssString(value: string): string;escapeXmlfunctionSource ↗
XML-escape a value for validated serialization back into owned OOXML.
declare function escapeXml(value: string): string;extensionKeyfunctionSource ↗
ASCII-case-insensitive extension key (leading dot removed; ASCII-only fold).
declare function extensionKey(extension: string): string;fieldAtomTextfunctionSource ↗
Model text contributed by one atomic field unit.
declare function fieldAtomText(): typeof FIELD_ATOM_CHAR;fieldOnOffAttributefunctionSource ↗
Read an on/off WML attribute (dirty / fldLock).
Returns undefined when absent, otherwise the OOXML on/off interpretation (present without val, or val not explicitly off → true).
declare function fieldOnOffAttribute(node: OoxmlNode, localName: 'dirty' | 'fldLock'): boolean | undefined;findContentControlfunctionSource ↗
Find one control by canonical node id, with the same bounded walk.
declare function findContentControl(root: OoxmlNode, nodeId: string): ContentControlEntry | null;findCustomXmlDataPartfunctionSource ↗
The data part carrying this namespace, or null when the document has none yet.
declare function findCustomXmlDataPart(pkg: OoxmlPackage, storyPartName: string, namespaceUri: string): CustomXmlDataPart | null;findDetectedTocfunctionSource ↗
Locate the table of contents containing a position, or null.
declare function findDetectedToc(tocs: readonly DetectedToc[], tocId: string): DetectedToc | null;findElementfunctionSource ↗
Find the first descendant element with the given qualified name.
declare function findElement(nodes: readonly XmlNode[], name: string): Extract<XmlNode, {
type: 'element';
}> | undefined;findNodefunctionSource ↗
Read a node back out of a part by id.
declare function findNode(part: OoxmlPart, nodeId: string): OoxmlNode | null;findNoteByIdfunctionSource ↗
Find a typed note by id inside a notes-part root.
declare function findNoteById(root: OoxmlNode, noteId: number): OoxmlNoteNode | undefined;findOccurrencesfunctionSource ↗
Every occurrence of query in text, in order, NON-OVERLAPPING.
Non-overlapping is what a find dialog counts: aa in aaaa is two, not three. limit is the caller's remaining budget, so a caller scanning many paragraphs enforces ONE global cap rather than one per paragraph.
declare function findOccurrences(text: string, query: string, limit: number, options?: TextMatchOptions): TextOccurrences;fingerprintfunctionSource ↗
Fingerprint an artifact under a named comparator's canonicalization policy.
declare function fingerprint(name: ComparatorName, value: unknown): string;firstReviewRangefunctionSource ↗
The range an item is anchored at — where its card belongs and how it sorts.
declare function firstReviewRange(item: ReviewItem): ReviewRange | null;flattenContentControlsfunctionSource ↗
A container's children with every content-control wrapper flattened away, bounded in depth.
ONE unwrap rule, for the places where a control sits between a container and the children that container is defined in terms of. CT_SdtRow puts it between w:tbl and w:tr, CT_SdtCell between w:tr and w:tc, and a walk that filtered on the child's kind dropped the row or cell entirely: not measured, not painted, not addressable. Flattening at the point of the filter means a controlled row is the same row to the grid pass, the pagination pass and the story walk.
Returns the SAME array identity when there is nothing to unwrap, so the tables that carry no controls — nearly all of them — allocate nothing and the incremental layout cache still sees its own inputs.
declare function flattenContentControls(children: readonly OoxmlNode[], maxDepth?: number): readonly OoxmlNode[];fldCharTypefunctionSource ↗
Read @w:fldCharType when present and schema-legal.
declare function fldCharType(node: OoxmlNode): FldCharType | null;fldSimpleInstrfunctionSource ↗
@w:instr on w:fldSimple, or undefined when absent.
declare function fldSimpleInstr(node: OoxmlNode): string | undefined;fnv1a32functionSource ↗
FNV-1a over UTF-16 code units — the deterministic mint every id derivation shares.
declare function fnv1a32(value: string): number;foldCasefunctionSource ↗
Lower-case text WITHOUT changing its length.
String.prototype.toLowerCase can expand (Turkish dotted capital I lowercases to two code units), and an expansion mid-paragraph would slide every offset after it — the match would be reported at the wrong place. The per-unit fallback folds only the characters that stay one unit, so an expanding character simply compares case-sensitively. That is a real degradation and it is the safe direction: a missed case-insensitive match beats a match reported at an offset an editor then selects.
declare function foldCase(text: string): string;formatNoteScopeIdfunctionSource ↗
Canonical EditorScope { kind: 'note'; id } encoding.
Footnote id 1 and endnote id 1 coexist, so the kind is part of the string: footnote:2 / endnote:-1. Do not invent a parallel scope union arm.
declare function formatNoteScopeId(noteKind: NoteKind, noteId: number): string;formatOwnedRunIdsfunctionSource ↗
Runs that own field-result formatting for atoms in this paragraph.
declare function formatOwnedRunIds(paragraph: Extract<OoxmlNode, {
kind: 'paragraph';
}>): ReadonlySet<string>;hardBreakAttributesfunctionSource ↗
Attributes for a newly authored w:br.
declare function hardBreakAttributes(kind: 'line' | 'page'): OoxmlHardBreakNode['attributes'];hardBreakKindfunctionSource ↗
Read the semantic break kind from a typed w:br node.
declare function hardBreakKind(node: OoxmlHardBreakNode): HardBreakKind;hardBreakTextfunctionSource ↗
Text projection for a w:br node — one UTF-16 code unit per break.
declare function hardBreakText(node: OoxmlHardBreakNode): string;hasAnyCommentfunctionSource ↗
Whether the package holds any comment record at all — the cheap gate before a reap.
declare function hasAnyComment(pkg: OoxmlPackage): boolean;hasBoundedSvgRootfunctionSource ↗
Bounded scan for an <svg document root (optional <?xml prolog only).
declare function hasBoundedSvgRoot(bytes: Uint8Array): boolean;hasCommentPartfunctionSource ↗
A comment part exists and declares the comment content type.
declare function hasCommentPart(pkg: OoxmlPackage, storyPartName: string): boolean;hashAuthoredfunctionSource ↗
Hash a store's authored state, so two runtimes replaying one fixture can be compared.
declare function hashAuthored(authoredState: unknown): string;hasNodefunctionSource ↗
Whether a node id exists in the part.
declare function hasNode(part: OoxmlPart, nodeId: string): boolean;hyperlinkAnchorOffunctionSource ↗
A typed hyperlink's w:anchor, or undefined.
declare function hyperlinkAnchorOf(link: OoxmlNode): string | undefined;hyperlinkRelationshipIdOffunctionSource ↗
A typed hyperlink's r:id, or undefined.
declare function hyperlinkRelationshipIdOf(link: OoxmlNode): string | undefined;hyperlinkTargetOffunctionSource ↗
Read a typed w:hyperlink into its target record.
r:id wins over w:anchor when a link carries both, matching Word: the relationship names the document and the anchor names a place inside it, so the pair is a link to a bookmark in ANOTHER file — which this engine will not follow, but whose external half is the part that decides where it points.
A link with neither is unresolved: it paints its runs and does nothing.
declare function hyperlinkTargetOf(link: OoxmlNode, resolve: RelationshipTargetResolver): HyperlinkTarget;imageResourceLookupForfunctionSource ↗
Derived cache for one immutable package snapshot. Registry identity is (package snapshot, decodePort object, normalized limits) — the first caller never imposes its decoder or limits on later callers with different options.
declare function imageResourceLookupFor(pkg: OoxmlPackage, options: CreateImageResourceCacheOptions): ImageResourceLookup;indexStylesfunctionSource ↗
Style definitions, read out of the generic w:styles tree.
declare function indexStyles(part: OoxmlPart | undefined): Map<string, StyleIndexEntry>;inlineControlEndingAtfunctionSource ↗
The innermost inline content control whose content ends exactly at offset — the caret at its right outer edge. What Backspace consults to delete the node as ONE unit (pro-review-and-custom-nodes 4.6): deleting its last character from outside would either strip one letter from a content-locked label (refused, so the key looks dead) or leave a half-deleted chip whose tag still claims the full payload.
declare function inlineControlEndingAt(paragraph: OoxmlParagraphNode, offset: number): InlineControlSpan | null;inlineControlStartingAtfunctionSource ↗
The forward-delete mirror: the control whose content STARTS exactly at offset.
declare function inlineControlStartingAt(paragraph: OoxmlParagraphNode, offset: number): InlineControlSpan | null;insertChildrenfunctionSource ↗
Insert children into a node at index (clamped to the child list).
declare function insertChildren(part: OoxmlPart, nodeId: string, index: number, children: readonly OoxmlNode[], options?: EditOptions): OoxmlEditResult;insertCustomNodeWritefunctionSource ↗
Insert one custom node, with its payload, as a single transaction.
Answers the store transaction's own change so the caller can publish it — a payload write is a package write reaching through a story store, exactly as a comment is, and the coordinator needs the change to know which paragraphs went dirty.
declare function insertCustomNodeWrite(store: TreeDocumentStore, write: InsertCustomNodeWrite,
dataOwnerPartName?: string): CustomNodeWriteResult;instrTextValuefunctionSource ↗
Concatenated text descendants of w:instrText (instruction only — never executed).
declare function instrTextValue(node: OoxmlNode): string;isAuthorableRunPropertyfunctionSource ↗
Whether an op may name this run property at all.
The stored-marks lane needs this AT ARM TIME. Every other write reaches the store in the same turn as the press, so a name the store refuses surfaces immediately; an ARMED property is not applied until the user types, and it rides the keystroke's own transaction — a name outside the vocabulary would take the typed characters down with it, silently, on every keystroke until the caret moved.
declare function isAuthorableRunProperty(localName: string): boolean;isContentControlfunctionSource ↗
Block or inline structured-document-tag wrapper — typed or generic during migration.
Generic fallback requires the WordprocessingML namespace so foreign-namespace <x:sdt> elements stay opaque wrappers and are never treated as Word controls.
declare function isContentControl(node: OoxmlNode): node is ContentControlLike;isContentControlContentfunctionSource ↗
True when node is the control's content container (w:sdtContent).
Generic sdtContent requires the WML namespace — same foreign-namespace rule as [isContentControl](isContentControl).
declare function isContentControlContent(node: OoxmlNode): node is ContentControlContentLike;isContentControlContentNodefunctionSource ↗
Whether a node is a w:sdtContent — the container holding a control's actual content.
declare function isContentControlContentNode(node: OoxmlNode): node is OoxmlContentControlContentNode;isContentControlNodefunctionSource ↗
Whether a node is a w:sdt wrapper.
declare function isContentControlNode(node: OoxmlNode): node is OoxmlContentControlNode;isContentControlWrapperfunctionSource ↗
A w:sdt wrapper, TYPED or DEMOTED.
Flattening predates typing and must not stop at a control the reader refused to type: a demoted wrapper still renders its content in place in Word, so a walk that only saw the typed kind would drop every paragraph inside a malformed control out of the story.
declare function isContentControlWrapper(node: OoxmlNode): boolean;isContentRevisionKindfunctionSource ↗
The four content-position revision wrappers, which nest and carry runs.
declare function isContentRevisionKind(kind: OoxmlNode['kind']): kind is 'revisionInsert' | 'revisionDelete' | 'revisionMoveFrom' | 'revisionMoveTo';isContinuationSeparatorNodefunctionSource ↗
Whether a node is the w:continuationSeparator rule used on continuation pages.
declare function isContinuationSeparatorNode(node: OoxmlNode): node is OoxmlContinuationSeparatorNode;isDangerousKeyfunctionSource ↗
Whether a key is one of [DANGEROUS_KEYS](DANGEROUS_KEYS).
declare function isDangerousKey(key: string): boolean;isDrawingTreeDocOpfunctionSource ↗
Whether an op is one of the drawing ops. Narrows the type.
declare function isDrawingTreeDocOp(op: TreeDocOp): op is DrawingTreeDocOp;isEndnotesNodefunctionSource ↗
Whether a node is a w:endnotes part root.
declare function isEndnotesNode(node: OoxmlNode): node is OoxmlEndnotesNode;isEvaluableFieldfunctionSource ↗
Whether a field instruction's leading keyword is safe to evaluate.
declare function isEvaluableField(instruction: string): boolean;isFieldChromefunctionSource ↗
True when a node is field chrome that never contributes its own model text outside an atomic span (markers + instruction). Cached result w:t is separate.
declare function isFieldChrome(node: OoxmlNode): boolean;isFldCharfunctionSource ↗
Typed or generic w:fldChar with the given type.
declare function isFldChar(node: OoxmlNode, type: FldCharType): boolean;isFldCharNodefunctionSource ↗
Whether a node is a w:fldChar field boundary marker.
declare function isFldCharNode(node: OoxmlNode): node is OoxmlFldCharNode;isFldSimplefunctionSource ↗
Typed or generic w:fldSimple.
declare function isFldSimple(node: OoxmlNode): boolean;isFldSimpleNodefunctionSource ↗
Whether a node is w:fldSimple — a field whose instruction and result are one element.
declare function isFldSimpleNode(node: OoxmlNode): node is OoxmlFldSimpleNode;isFootnotesNodefunctionSource ↗
Whether a node is a w:footnotes part root.
declare function isFootnotesNode(node: OoxmlNode): node is OoxmlFootnotesNode;isHeaderFooterLifecycleOpfunctionSource ↗
Whether an op is a header/footer lifecycle op rather than a story-level one.
declare function isHeaderFooterLifecycleOp(op: {
readonly op: string;
}): op is HeaderFooterLifecycleOp;isHyperlinkNodefunctionSource ↗
Whether a node is a typed w:hyperlink.
declare function isHyperlinkNode(node: OoxmlNode): boolean;isInertExecutablefunctionSource ↗
Whether a content kind is one this engine refuses to execute or auto-resolve.
declare function isInertExecutable(kind: string): boolean;isInstrTextfunctionSource ↗
Typed or generic w:instrText.
declare function isInstrText(node: OoxmlNode): boolean;isInstrTextNodefunctionSource ↗
Whether a node is w:instrText — a field's instruction.
Instructions are never EXECUTED or auto-resolved: DDE and INCLUDE* render inert.
declare function isInstrTextNode(node: OoxmlNode): node is OoxmlInstrTextNode;isLegalEndnotePositionfunctionSource ↗
Validate an authored endnote position write — refuse pageBottom.
declare function isLegalEndnotePosition(pos: string): pos is EndnotePosition;isLegalFldCharTypefunctionSource ↗
Whether fldCharType is a legal ST_FldCharType value (used by tests / guards).
declare function isLegalFldCharType(value: string): boolean;isLegalFootnotePositionfunctionSource ↗
Validate an authored footnote position write.
declare function isLegalFootnotePosition(pos: string): pos is FootnotePosition;isLegalNumRestartfunctionSource ↗
Whether a file-supplied string is a legal w:numRestart value. Narrows the type.
declare function isLegalNumRestart(value: string): value is NoteNumRestart;isNormalNotefunctionSource ↗
Whether a note is a normal (body) note — absent type and explicit normal both count.
declare function isNormalNote(node: OoxmlNode): boolean;isNoteAtomNodefunctionSource ↗
True when a run-inner node is a typed note atom that contributes one UTF-16 unit. Demoted/malformed known locals stay generic and contribute nothing.
declare function isNoteAtomNode(node: OoxmlNode): boolean;isNoteLifecycleOpfunctionSource ↗
Whether an op is a note lifecycle op rather than a story-level one.
declare function isNoteLifecycleOp(op: {
readonly op: string;
}): op is NoteLifecycleOp;isNoteNodefunctionSource ↗
Whether a node is a w:footnote or w:endnote body.
declare function isNoteNode(node: OoxmlNode): node is OoxmlNoteNode;isNoteReferenceNodefunctionSource ↗
Whether a node is a body-side w:footnoteReference / w:endnoteReference.
declare function isNoteReferenceNode(node: OoxmlNode): node is OoxmlNoteReferenceNode;isNoteRefNodefunctionSource ↗
Whether a node is the w:footnoteRef / w:endnoteRef mark inside a note's own body.
declare function isNoteRefNode(node: OoxmlNode): node is OoxmlNoteRefNode;isPageBreakNodefunctionSource ↗
Whether a node is a w:br with w:type="page".
declare function isPageBreakNode(node: OoxmlNode): node is OoxmlHardBreakNode;isRangeMarkerKindfunctionSource ↗
Move-range and comment-range boundary markers, which are empty and sit between runs.
declare function isRangeMarkerKind(kind: OoxmlNode['kind']): kind is 'moveFromRangeStart' | 'moveFromRangeEnd' | 'moveToRangeStart' | 'moveToRangeEnd' | 'commentRangeStart' | 'commentRangeEnd';isSearchableQueryfunctionSource ↗
Whether a query is one this module will scan for at all.
declare function isSearchableQuery(query: unknown): query is string;isSeparatorNodefunctionSource ↗
Whether a node is the w:separator rule drawn above the note area.
declare function isSeparatorNode(node: OoxmlNode): node is OoxmlSeparatorNode;isValidIdfunctionSource ↗
Whether a string is a well-formed identifier in either accepted grammar.
Reverse-domain (dev.docx-editor.core.command.insert-text) or package-owned (@docx-editor.dev/engine-core#command/insert-text). Ids are opaque once validated.
declare function isValidId(id: string): boolean;isValidMimefunctionSource ↗
Whether a string is syntactically a MIME type. Syntax only — no registry lookup.
declare function isValidMime(value: string): boolean;isValidNCNamefunctionSource ↗
Whether a string is a valid XML NCName — a name with no colon.
declare function isValidNCName(name: string): boolean;isValidParaIdfunctionSource ↗
Valid per MS-DOCX: 8 hex digits, non-zero, below 0x80000000.
declare function isValidParaId(value: string): boolean;isValidQNamefunctionSource ↗
A QName is an optional prefix: (both NCNames) — never attacker-derived.
declare function isValidQName(name: string): boolean;isWholeWordfunctionSource ↗
Whether a match at [start, end) in text stands alone as a word.
declare function isWholeWord(text: string, start: number, end: number): boolean;linkRevisionRepliesfunctionSource ↗
Attach each comment that answers a tracked change to the change it answers.
The evidence is the RANGE, exactly as it is for a coincident comment thread: replying to a revision writes a comment over that revision's own characters, because OOXML gives w:ins and w:del nowhere else to put the text. Without this the reply came back as an independent card in the rail, sitting beside the change rather than inside it, and the reader had no way to see which change their answer belonged to.
Three things keep it from over-claiming. A ZERO-WIDTH range is evidence of nothing — the same rule the comment threading uses, and a format or paragraph-mark revision decorates no characters at all. A comment already stated to be a REPLY to another comment is not claimed directly, because a stated link always beats an inferred one. And the FIRST revision on a span wins, so a card cannot claim a reply another card already holds.
The WHOLE conversation moves, not its head. A change's card renders replyIds as a flat list, so linking only the top comment of a thread left every answer to that answer rendered by nobody: reply twice to one change and the second reply existed in comments.xml and appeared nowhere on screen. Descendants ride along, in the order they were authored.
IDEMPOTENT, and that is load-bearing. The session re-runs this over a list whose comments are ALREADY linked, so a pass that only ever added links left a stale parentRevisionId behind when a keystroke shifted the revision's offsets out from under it — the rail filters such a comment out of its roots, and with no revision claiming it any more the card vanished until the next full re-derivation. Every link is rebuilt from the ranges on every pass.
declare function linkRevisionReplies<T extends LinkableReviewItem>(items: readonly T[]): T[];liveDrawingReferenceCountfunctionSource ↗
Package-wide live drawing references to a media part name.
declare function liveDrawingReferenceCount(pkg: OoxmlPackage, partName: string): number;locateSitesfunctionSource ↗
Locate every revision site in one walk.
One walk rather than a lookup per site: resolveRevisions learned the same lesson the hard way, where a per-site tree walk inside a per-site loop made accept-all quadratic.
Offsets come from paragraphOffsetIndex, which is segmentsOf's walk. A private one here measured a run by summing its text and gave a note reference, an atomic field and a field's instruction text the wrong lengths, so every card in a paragraph holding one reported a range the caret and the ops disagreed with.
declare function locateSites(part: OoxmlPart): ReadonlyMap<string, SiteLocation>;lockForbidsEditfunctionSource ↗
Whether a resolved lock forbids editing the content it covers.
declare function lockForbidsEdit(lock: ContentControlLock): boolean;lockForbidsRemovalfunctionSource ↗
Whether a resolved lock forbids removing the control itself.
declare function lockForbidsRemoval(lock: ContentControlLock): boolean;makeLimitCounterfunctionSource ↗
A phase-scoped overflow-safe counter for one limit.
declare function makeLimitCounter(limits: ResourceLimits, key: keyof ResourceLimits): BoundedCounter;mergedPropertiesfunctionSource ↗
Merge properties into a set, replacing any entry with the same name.
setRunProperties and setParagraphProperties REPLACE the whole container, so sending one property alone deleted every other: pressing Bold stripped a run's font, size and colour, and pressing Centre stripped a paragraph's style, numbering and indents.
Takes one property or a list, because a toolbar press carries one and an object-model formatting write carries several at once — and applying several one at a time would be the same fold written at every call site.
declare function mergedProperties(existing: readonly OoxmlProperty[], incoming: OoxmlProperty | readonly OoxmlProperty[]): OoxmlProperty[];mintedParagraphIdentityAttributesfunctionSource ↗
The minted [w14:paraId, w14:textId] pair. textId mirrors paraId: it has no uniqueness requirement, no consumer reads it, and one allocator is simpler than two — but Word writes both, so we write both.
declare function mintedParagraphIdentityAttributes(prefix: string, value: string): readonly OoxmlAttribute[];mintParaIdfunctionSource ↗
Deterministic 8-hex mint in (0x00000000, 0x80000000), collision-free against used (uppercase hex). Same seed + same used-set → same value, which is what keeps splitParagraphMany byte-identical to its equivalent single splits and a reopened save identical to the session that produced it.
declare function mintParaId(seed: string, used: ReadonlySet<string>): string;normalizeParagraphIdentityfunctionSource ↗
Load-time paragraph-identity normalization for a session's main part.
Keeps every valid, first-seen paraId verbatim; mints (deterministically, seeded by the paragraph's structural node id) for paragraphs whose id is missing, malformed, zero, out of range, or a duplicate. Adds the root xmlns binding the minted attributes need. Returns the INPUT PART REFERENCE when there is nothing to do — a document Word saved yesterday re-serializes byte-identical.
Attribute-only rebuilds move no child, so every node keeps its structural-path id; the copy respreads only the ancestors of changed paragraphs.
Fail-open: if the rebuilt part does not validate (a bug, or a pathology the prefix choice could not defuse), the original part is returned — a document must never become unopenable over an identity enhancement.
declare function normalizeParagraphIdentity(part: OoxmlPart): OoxmlPart;normalizePartNamefunctionSource ↗
Normalize a ZIP entry name or OPC part name into a canonical part name (/word/document.xml). Accepts leading-slash and no-leading-slash inputs; rejects traversal, dot segments, and the attack surface. Duplicate detection folds ASCII case (OPC part-name equivalence).
declare function normalizePartName(raw: string): NameResult;normalNoteIdsfunctionSource ↗
List normal (body) note ids in document order, bounded.
declare function normalNoteIds(part: OoxmlPart): readonly number[];noteAtomTextfunctionSource ↗
Model text contributed by one atomic note unit.
declare function noteAtomText(): typeof NOTE_ATOM_CHAR;noteIdOffunctionSource ↗
Authored @w:id on a note or noteReference when parseable.
declare function noteIdOf(node: OoxmlNode): number | null;noteKindOffunctionSource ↗
Typed or generic w:footnote / w:endnote.
declare function noteKindOf(node: OoxmlNode): NoteKind | null;noteReferenceKindOffunctionSource ↗
Typed or generic footnote/endnote reference kind.
declare function noteReferenceKindOf(node: OoxmlNode): NoteKind | null;noteRefKindOffunctionSource ↗
Typed or generic w:footnoteRef / w:endnoteRef.
declare function noteRefKindOf(node: OoxmlNode): NoteKind | null;notesOffunctionSource ↗
Collect note bodies from a footnotes/endnotes root, bounded.
declare function notesOf(root: OoxmlNode): readonly OoxmlNoteNode[];notesPartHasIdfunctionSource ↗
Whether a notes-part root contains a note with the given id (any type).
declare function notesPartHasId(part: OoxmlPart, noteId: number): boolean;noteTypeOffunctionSource ↗
Authored @w:type (ST_FtnEdn) when present and schema-legal; else undefined.
declare function noteTypeOf(node: OoxmlNode): NoteType | undefined;nullRecordfunctionSource ↗
A fresh null-prototype record — the only object shape parser intermediates use.
declare function nullRecord<T = unknown>(): Record<string, T>;ooxmlTreesEqualfunctionSource ↗
Structural equality of two canonical trees, ignoring node ids.
Ids differ between two parses of the same bytes, so comparing them would report every reopen as a change. This compares what the document SAYS.
declare function ooxmlTreesEqual(left: OoxmlPart | OoxmlNode, right: OoxmlPart | OoxmlNode): boolean;orderedContentControlPropertiesfunctionSource ↗
Rebuild a w:sdtPr's children in schema order.
Modelled children sort to their declared position and the type element follows them, as the sequence requires. Everything else — a w15:repeatingSection, a vendor extension, the w14:checkbox that is not part of the ECMA-376 choice — keeps the order it was authored in and follows the modelled block, so a write that touches one property neither drops nor reorders anything it does not name.
declare function orderedContentControlProperties(children: readonly OoxmlNode[]): readonly OoxmlNode[];paragraphOffsetIndexfunctionSource ↗
THE paragraph offset authority: maps a paragraph's UTF-16 offsets to the nodes holding them.
One authority on purpose. An atomic field spans many nodes but is ONE unit to an offset, and a second implementation that disagreed would place edits inside content that cannot be split.
declare function paragraphOffsetIndex(paragraph: OoxmlParagraphNode): ParagraphOffsetIndex;paragraphOrderOfPartfunctionSource ↗
Paragraph node id → document position, from the TREE rather than from a layout.
Memoized on the immutable root: one full derivation pass asks this question three times (replacement pairing, the queue's merged order, the session's cached order), and each answer was a fresh full-tree walk. The instance is SHARED, so the return type is ReadonlyMap: a caller mutating it would poison every later reader of this root.
declare function paragraphOrderOfPart(part: OoxmlPart): ReadonlyMap<string, number>;paragraphTextOffunctionSource ↗
Paragraph text as the ops address it, for tests and callers computing offsets.
declare function paragraphTextOf(part: OoxmlPart, paragraphId: string): string | null;paraIdOffunctionSource ↗
The authored w14:paraId value of an element, verbatim, or null.
declare function paraIdOf(node: OoxmlNode): string | null;parentNodeOffunctionSource ↗
The element that holds a node, or null for the root and for unknown ids.
declare function parentNodeOf(part: OoxmlPart, nodeId: string): OoxmlElement | null;parseAuthoredNotePropertiesfunctionSource ↗
Parse authored CT_FtnProps / CT_EdnProps without inventing defaults.
declare function parseAuthoredNoteProperties(propsNode: OoxmlNode | null | undefined): AuthoredNoteProperties | undefined;parseContentControlIdfunctionSource ↗
A signed 32-bit ST_DecimalNumber, or undefined when the file wrote something else.
declare function parseContentControlId(raw: string | undefined): number | undefined;parseNoteIdfunctionSource ↗
Parse a signed decimal note id; reject non-integers and out-of-int32 values.
declare function parseNoteId(raw: string | undefined): number | null;parseNoteScopeIdfunctionSource ↗
Parse [formatNoteScopeId](formatNoteScopeId). Returns null for malformed / out-of-range ids.
declare function parseNoteScopeId(id: string): {
readonly noteKind: NoteKind;
readonly noteId: number;
} | null;parseSemVerfunctionSource ↗
Parse a semantic version, rejecting anything the registry's rules do not need.
Deliberately narrow: an unsupported range form is refused rather than accepted, so a malformed range can never masquerade as "compatible".
declare function parseSemVer(input: string): SemVer;parseTocInstructionfunctionSource ↗
Parse a TOC field instruction string.
Returns null when the leading keyword is not TOC, the string is over-long, or the outline range is hostile. Does not evaluate or fetch anything.
declare function parseTocInstruction(raw: string): TocInstruction | null;partNameKeyfunctionSource ↗
Case-folded key for OPC part-name equivalence / duplicate detection.
declare function partNameKey(partName: string): string;planTocEntriesfunctionSource ↗
Plan TOC entries from the outline and existing bookmarks.
declare function planTocEntries(part: OoxmlPart, outline: readonly TocOutlineHeading[], instruction: TocInstruction, pageNumberByParagraphId: ReadonlyMap<string, string>, excludeParagraphIds: ReadonlySet<string>): {
readonly entries: readonly TocEntryPlan[];
readonly bookmarksToCreate: readonly {
paragraphId: string;
name: string;
}[];
};projectDrawingfunctionSource ↗
Project one w:drawing into the resolved shape layout and chrome read.
Bounded throughout: extents, crops and nesting all come from a file. Returns a projection that reports hidden and its locks rather than throwing, so an unusable drawing degrades to something the surface can skip.
declare function projectDrawing(drawing: OoxmlDrawingNode, context: Readonly<{
ownerPartName: string;
supportedMcRequires: ReadonlySet<string>;
limits: DrawingProjectionLimits;
namespaceScope?: ReadonlyMap<string, string>;
resolveRelationship?: RelationshipTargetResolver;
}>): DrawingProjection | null;propertyContainerfunctionSource ↗
A node's own property container (w:pPr, w:rPr) among its children.
A container the canonical read demoted to generic is still the node's own properties — matching only the typed kind lost the whole set.
declare function propertyContainer(parent: OoxmlNode | null | undefined, kind: 'paragraphProperties' | 'runProperties', localName: 'pPr' | 'rPr'): OoxmlNode | undefined;readCustomXmlNodefunctionSource ↗
One node by id, or null.
declare function readCustomXmlNode(pkg: OoxmlPackage, partName: string, nodeId: string): CustomXmlNode | null;readEmbeddedFontsfunctionSource ↗
Every font the package embeds, deobfuscated.
Silently skips anything malformed rather than rejecting the document: a broken font table is a reason to fall back to substitution, never a reason to refuse to open the file.
declare function readEmbeddedFonts(pkg: OoxmlPackage, fontTable: OoxmlPart | undefined, options?: ReadEmbeddedFontsOptions): EmbeddedFont[];readOnOffChildfunctionSource ↗
OOXML on/off toggle: on only when a same-namespace child is present and its w:val (same namespace as the child) does not explicitly disable. Foreign-namespace siblings with the same local name cannot turn the flag on.
declare function readOnOffChild(parent: OoxmlNode, localName: string, namespaceUri?: string): boolean;readOoxmlPackagefunctionSource ↗
Load DOCX bytes into canonical trees, bounded at every step.
THE trust boundary for a document. Composes the hardened primitives — zip limits and OPC name normalization, content-type indexing, relationship validation, entity-free XML — into one loader, and returns a typed rejection rather than throwing from inside a decoder.
declare function readOoxmlPackage(bytes: Uint8Array, limits?: OoxmlPackageLimits): OoxmlPackageResult;readOoxmlPartfunctionSource ↗
Read one XML part into the additive typed/generic foundation. Existing package parsing and DocumentStore models intentionally remain unchanged until their later migration tasks; this tree is not yet the repository's sole runtime authority. Structural-path IDs are deterministic across normalized reopen. Preserving an identity through moves and edits is deferred to PackageModel/DocumentStore integration.
declare function readOoxmlPart(xml: string, metadata: OoxmlPartMetadata, limits?: XmlLimits): OoxmlReadResult;readTrackingSettingsfunctionSource ↗
Read the tracking settings from a settings.xml root, or the defaults when it has none.
declare function readTrackingSettings(settingsRoot: OoxmlNode | null | undefined): DocumentTrackingSettings;readXmlfunctionSource ↗
Read XML at the trust boundary: bounded, entity-free, and fidelity-preserving.
Pre-rejects DTDs and entity constructs, disables expansion and value coercion, and keeps child order, attributes, whitespace and raw lexical form — everything a lossless re-emit needs.
declare function readXml(xml: string, limits?: XmlLimits): XmlResult;readZipfunctionSource ↗
Inflate a ZIP archive with bounds + OPC name normalization. Entry name, count, compression-ratio, and total-uncompressed-size limits are enforced BEFORE each entry is decompressed (via fflate's pre-inflation filter), so a zip bomb or a traversal name is rejected without ever being inflated. Keys are canonical part names.
declare function readZip(bytes: Uint8Array, limits?: ZipLimits): ZipReadResult;relationshipsOffunctionSource ↗
Relationship records owned by one part, in authored order.
declare function relationshipsOf(pkg: OoxmlPackage, ownerPart: string): readonly RelationshipRecord[];relationshipTargetInfunctionSource ↗
What a part's relationships answer for one r:id, over both maps.
relationships holds the internal records and externalTargets the external ones, so a resolver reading only the first sees every hyperlink as dangling.
declare function relationshipTargetIn(pkg: OoxmlPackage, ownerPart: string, relationshipId: string): {
readonly target: string;
readonly external: boolean;
readonly sinkSafe?: boolean;
} | null;relsPartNameForfunctionSource ↗
The .rels part that owns a part's relationships, by OPC convention.
declare function relsPartNameFor(partName: string): string;removeCustomNodeWritefunctionSource ↗
Remove a control and, in the same transaction, the payload it bound.
The sweep would collect the node eventually — that is what makes deletion in Word survivable — but "eventually" is the next open, and a document saved in between carries a payload for a chip that is gone. Doing it here means the ordinary case is exact and the sweep is a backstop.
declare function removeCustomNodeWrite(store: TreeDocumentStore, controlNodeId: string): CustomNodeWriteResult;removeNodefunctionSource ↗
Remove a node and its subtree.
declare function removeNode(part: OoxmlPart, nodeId: string, options?: EditOptions): OoxmlEditResult;replaceChildrenfunctionSource ↗
Replace one node's children wholesale.
declare function replaceChildren(part: OoxmlPart, nodeId: string, children: readonly OoxmlNode[], options?: EditOptions): OoxmlEditResult;replaceNodefunctionSource ↗
Replace one node with another, keeping its position among its siblings.
declare function replaceNode(part: OoxmlPart, nodeId: string, replacement: OoxmlNode, options?: EditOptions): OoxmlEditResult;replayFixturefunctionSource ↗
Replay a fixture against a store and check every step's outcome, committed revision, and authored-state fingerprint against the fixture's expectations.
declare function replayFixture(fixture: ConformanceFixture, store: ReplayStore): ReplayReport;resolvefunctionSource ↗
Resolve a set of bundles into one registry, or throw.
Deterministic and registration-order independent: selection is by (kind, id) plus version, and ties break only on declared policy. Array order never decides anything.
declare function resolve(bundles: readonly FeatureBundle[], options?: ResolveOptions): ResolvedRegistry;resolveContentControlLockfunctionSource ↗
Resolve the lock a position inherits from the controls enclosing it.
CONSERVATIVE, because a template that says a field cannot be edited and sits inside a section that says it cannot be removed means both. Each half of ST_Lock is taken independently and the strongest wins, so an unlocked control inside a contentLocked one is still content-locked — a nested control cannot grant a permission its parent withheld, which is the only reading under which a lock is a lock.
declare function resolveContentControlLock(chain: readonly ContentControlLock[]): ContentControlLock;resolveContentTypefunctionSource ↗
Resolve a part's content type: Override wins over Default; else unknown.
declare function resolveContentType(index: ContentTypeIndex, partName: string): ResolveResult;resolveContentTypeOffunctionSource ↗
The content type that resolves for a part name, or null when nothing declares one.
declare function resolveContentTypeOf(pkg: OoxmlPackage, partName: string): string | null;resolveEndnotePropertiesfunctionSource ↗
Resolve endnote properties: section → document → defaults. pageBottom is never a legal endnote position — falls back.
declare function resolveEndnoteProperties(section?: AuthoredNoteProperties, document?: AuthoredNoteProperties): ResolvedEndnoteProperties;resolveFootnotePropertiesfunctionSource ↗
Resolve footnote properties: section → document → defaults. Illegal position strings fall through to the next layer / default.
declare function resolveFootnoteProperties(section?: AuthoredNoteProperties, document?: AuthoredNoteProperties): ResolvedFootnoteProperties;resolveHeaderFooterPartsfunctionSource ↗
Resolve the main-document header/footer references to their parts, gated by the settings the section actually declares.
Returns the FINAL section's effective parts (after inheritance). Multi-section hosts should prefer resolveHeaderFooterPartsBySection.
declare function resolveHeaderFooterParts(pkg: OoxmlPackage): HeaderFooterParts;resolveHeaderFooterPartsBySectionfunctionSource ↗
Resolve header/footer parts for every section, applying OOXML inheritance.
Index aligns with enumerateDocumentSections in the layout package.
declare function resolveHeaderFooterPartsBySection(pkg: OoxmlPackage): readonly HeaderFooterParts[];resolveHeaderFooterResolutionBySectionfunctionSource ↗
Resolve header/footer parts for every section with declared-vs-inherited metadata.
Index aligns with enumerateDocumentSections in the layout package. Existing merged maps stay available via [resolveHeaderFooterPartsBySection](resolveHeaderFooterPartsBySection).
declare function resolveHeaderFooterResolutionBySection(pkg: OoxmlPackage): readonly HeaderFooterSectionResolution[];resolveImageRelationshipfunctionSource ↗
Resolve an image relationship id from an owner part. Internal targets resolve owner-relative; external targets are never fetched; a missing id is missing.
declare function resolveImageRelationship(records: readonly RelationshipRecord[] | undefined, ownerPart: string, relationshipId: string): ImageRelationshipResolution;resolveImageResourceLimitsfunctionSource ↗
Resolve caller overrides into frozen image limits; hard ceilings cannot be raised.
declare function resolveImageResourceLimits(overrides?: Partial<ImageResourceLimits>): ImageResourceLimits;resolveInternalTargetfunctionSource ↗
Resolve an internal relationship target against its owner part, without escaping the package root. ownerPartName is a canonical part name; the base is its containing folder. A leading "/" target is package-absolute. ./.. segments resolve on a stack; popping above root is traversal-escape.
declare function resolveInternalTarget(ownerPartName: string, rawTarget: string): NameResult;resolveLimitsfunctionSource ↗
Resolve caller overrides into a frozen, always-finite limit set. Each value is min(override>0 ? override : default, ceiling). Infinity/0/negative/NaN can never disable a limit — the hard ceiling always wins.
declare function resolveLimits(overrides?: Partial<ResourceLimits>): ResourceLimits;resolveNotesPartfunctionSource ↗
Resolve the footnotes or endnotes part via safe Internal document relationships.
Unusable matching relationships (External, unsafe target, missing part, wrong root) are skipped — never fetched, never accepted — so a decoy first match cannot hide a later usable Internal notes part (same continue-past-bad pattern as settingsPartOf).
declare function resolveNotesPart(pkg: OoxmlPackage, noteKind: NoteKind): OoxmlPart | null;resolveRelationshipfunctionSource ↗
Resolve a relationship to a runtime projection while the raw target stays authored. Internal - owner-relative part name; External - sink-safe validation only (never owner-resolved, never fetched). raw is always the verbatim authored target.
declare function resolveRelationship(rec: RelationshipRecord): ResolvedRelationship;resolveTocRowHeadingsfunctionSource ↗
The heading each cached result row stands for, aligned with toc.resultParagraphIds.
null for a row that names no heading this document still has — a stale row, or the chrome/blank paragraphs a cached result can carry. Callers leave those alone rather than writing another row's number into them.
declare function resolveTocRowHeadings(part: OoxmlPart, toc: DetectedToc, outline: readonly TocOutlineHeading[], excludeParagraphIds: ReadonlySet<string>): readonly (string | null)[];reviewItemKeyfunctionSource ↗
The stable key a surface uses for the active item and for a React list.
declare function reviewItemKey(item: ReviewItem): string;reviewItemRangesfunctionSource ↗
Every range a decision touches. One card can cover several, in different paragraphs.
Exported because the geometry half in the layout lane asks the same question, and a second copy of "which ranges does this item cover" is how a card comes to be painted over one range and activated by another.
declare function reviewItemRanges(item: ReviewItem): readonly ReviewRange[];revisionItemsOffunctionSource ↗
Every revision in one story, one card per DECISION.
Sites sharing an (id, author, date) triple are ONE revision — a tracked row insertion is w:trPr/w:ins plus w:cellIns on every cell — so they coalesce into one card listing every range it touches. Keying per site would show the reviewer four decisions where there is one, and accepting any of them would make the other three vanish.
Memoized per part root like the indexes it reads, and for the same reason: a heavily tracked document produces tens of thousands of cards, and rebuilding them per read cost more than everything the memos above saved. The paragraph-scoped view the local review patch derives (revisionItemsOfParagraph's synthetic paragraph-root part) is NOT cached: each keystroke would insert a fresh root and churn the bounded ring. The instance is SHARED, so the return type is readonly.
declare function revisionItemsOf(part: OoxmlPart): readonly ReviewRevisionItem[];runAddressRangesfunctionSource ↗
Per-run UTF-16 ranges from segmentsOf (fields/notes collapse to one unit on begin).
declare function runAddressRanges(paragraph: Extract<OoxmlNode, {
kind: 'paragraph';
}>): Map<string, {
start: number;
end: number;
}>;runPropertyEditsfunctionSource ↗
A range run-property change, split into ONE edit per run it covers, each merged over that run's own w:rPr.
Neither half of that is optional. The base MUST be the run's own properties (see this file's header). And the split MUST be per run: the op REPLACES the properties it names across its whole range, so one op carrying one run's bag over a mixed selection homogenised it — bolding hello + Georgia rewrote the second run's w:rFonts with the first's. Runs are addressed by offset rather than by id because these edits apply in sequence and the applier splits runs at the range edges; offsets are unmoved by a property write, ids are not.
declare function runPropertyEdits(part: OoxmlPart, paragraphId: string, start: number, end: number, incoming: OoxmlProperty | readonly OoxmlProperty[]): readonly RunPropertyEdit[];runsCoveringfunctionSource ↗
Every run that contributes at least one character of [start, end), in document order.
A COLLAPSED range answers the run it sits inside, which is what a caret reads. Callers that want the empty answer for a collapsed range check the offsets themselves.
declare function runsCovering(part: OoxmlPart, paragraphId: string, start: number, end: number): readonly OoxmlNode[];sanitizeHreffunctionSource ↗
Project a file-derived URL for a DOM/navigation sink. Strips embedded tab/LF/CR (used to smuggle java\nscript:), allows relative URLs and the scheme allowlist, and renders everything else inert. Never fetches.
declare function sanitizeHref(raw: string): HrefProjection;satisfiesfunctionSource ↗
Whether version satisfies range. Supported range grammar: - * any version - 1.2.3 exact - ^1.2.3 caret: same major, and = the floor (major 0 pins the minor) - >=1.2.3 <2.0.0 a single lower (inclusive) + upper (exclusive) bound pair Any other shape throws — an unparseable range is a registration error, not a pass.
declare function satisfies(version: string, range: string): boolean;scrubExportfunctionSource ↗
Explicit scrub export: remove inert executable classes, report removals.
declare function scrubExport(items: readonly ContentItem[]): ScrubResult;segmentsOffunctionSource ↗
Flatten a paragraph into UTF-16 addressable segments, in document order.
A HYPERLINK's runs are addressed too. w:hyperlink is a run container, not a leaf, and the characters inside a link are ordinary paragraph text: the user selects them, types over them and deletes them like any other. Skipping the container — which is what iterating only direct w:r children did — left every link's text with no offsets at all, so paragraphTextOf read "Visit or ." for a sentence that says "Visit Example.com or Anthropic's website." and layout, selection and the ops all agreed on the wrong string.
Inline CONTENT CONTROLS are the same class of wrapper: their w:sdtContent runs join the paragraph's offset stream with no break opportunity at the boundary. Nesting is bounded (MAX_CONTENT_CONTROL_NESTING); beyond the bound the wrapper is opaque so recursion cannot exhaust the stack.
runId stays the id of the run the content actually lives in, at whatever depth: the appliers resolve it with findNode and rebuild that run's children, so nesting costs them nothing.
declare function segmentsOf(paragraph: OoxmlParagraphNode): Segment[];semanticDigestfunctionSource ↗
Digest every part, in the given order.
declare function semanticDigest(parts: Iterable<OoxmlPart>): SemanticDigest;serializeOoxmlPartfunctionSource ↗
Serialize normalized XML from a canonical part using repository-controlled prefixes and validated, escaped names and values. This does not yet replace writeDocx; package integration belongs to the subsequent migration pass.
declare function serializeOoxmlPart(part: OoxmlPart): string;setCommentResolvedfunctionSource ↗
Mark a comment thread resolved, or reopen it.
A THREAD, not one remark: Word resolves a conversation, and its own pane greys the replies with the comment they answer. Resolving only the parent would leave a file whose reply still reads as open under a closed remark — a state Word does not produce and no reader would draw sensibly.
@w15:done lives in commentsExtended.xml, which many documents do not have: a file with no reply has no thread state to record. So the part is created when it is missing, exactly as [addComment](addComment) creates it, and every comment being resolved gets an entry — a comment with no w14:paraId gets one minted, because the state is keyed by it and there is nothing else to key it by.
ONE package transaction: the part, its relationship, its content-type override and the entries commit together, so a resolved thread is never half-recorded.
declare function setCommentResolved(store: TreeDocumentStore, commentId: string, resolved: boolean): SetCommentResolvedResult;settingsPartOffunctionSource ↗
Locate settings.xml via the main document relationship when present.
declare function settingsPartOf(pkg: OoxmlPackage): OoxmlPart | null;sniffImageMimefunctionSource ↗
Signature sniffing — authoritative over declared content type.
declare function sniffImageMime(bytes: Uint8Array): RenderableImageMime | PreservedImageMime | 'unknown';stableHashfunctionSource ↗
64-bit FNV-1a over the canonical form, returned as a 16-char hex string.
declare function stableHash(value: unknown, ephemera?: ReadonlySet<string>): string;storyParagraphsfunctionSource ↗
Every paragraph of one story, in reading order.
Descends through tables (rows, cells, nested tables) and flattens block-level content controls. The returned nodes are paragraph elements; a caller addresses them by id.
declare function storyParagraphs(root: OoxmlNode): readonly OoxmlNode[];storyRootsOffunctionSource ↗
Every story root in a part, in document order.
Does not descend INTO a story: a story's blocks are the walk below, and a story root never contains another story root.
declare function storyRootsOf(part: OoxmlPart): readonly OoxmlStoryRoot[];stylesPartOffunctionSource ↗
The package's style definitions part, if it has one.
declare function stylesPartOf(pkg: OoxmlPackage): OoxmlPart | undefined;sweepCustomNodePayloadsfunctionSource ↗
Drop every payload no control binds, in the stores whose namespaces a host claims.
ON OPEN, NOT ON SAVE. A chip cut to the clipboard is unbound for as long as it sits there, so a save mid-cut would destroy the payload the user is about to paste. On open the only unbound nodes are ones a control genuinely lost — deleted here, or deleted in Word, which is the case nothing else can collect.
namespaces is the claim, and it is what keeps this off other people's stores: Word's own Cover Page Properties store rides in most templates, and a sweep that walked every customXml part would be deleting from it on the strength of a name collision.
declare function sweepCustomNodePayloads(pkg: OoxmlPackage, storyPartName: string, namespaces: readonly string[]): CustomNodeSweepResult;textContentfunctionSource ↗
Concatenated text content of an element (all descendant text nodes).
declare function textContent(node: Extract<XmlNode, {
type: 'element';
}>): string;threadStateOfPartfunctionSource ↗
Thread state by w14:paraId, from commentsExtended.xml.
The part being PRESENT is not evidence of threading. issue-68-large-comments-suggestions.docx ships it with 212 entries carrying @w15:done and not one @w15:paraIdParent, so it records resolved state for a flat list. Absent parent means top-level, and that is a fact about the file rather than a default this code chose.
declare function threadStateOfPart(part: OoxmlPart): Map<string, CommentThreadState>;tocEntryTextfunctionSource ↗
Word flattens manual line/tab breaks from a heading into spaces in its TOC cache. Carrying them verbatim makes a short title wrap even when the row has ample room, and the same normalization is what lets a cached row be matched back to the heading it came from.
declare function tocEntryText(text: string): string;tocLeftIndentTwipsfunctionSource ↗
Bounded left-indent twips for a TOC entry level (0-based heading depth).
declare function tocLeftIndentTwips(level: number): number;toSafeRecordfunctionSource ↗
Recursively convert value into null-prototype records, rejecting any dangerous object key. Arrays and primitives pass through (arrays rebuilt so no inherited prototype pollution survives). Throws DangerousKeyError on the first unsafe key, naming its path. Cyclic inputs are rejected.
declare function toSafeRecord(value: unknown, path?: string): unknown;usedParaIdsfunctionSource ↗
Every valid w14:paraId in the tree, uppercased. Memoized per root object.
declare function usedParaIds(root: OoxmlElement): ReadonlySet<string>;validateDrawingOpfunctionSource ↗
Validate a drawing op's extents, crops and positions before it reaches the store.
declare function validateDrawingOp(part: OoxmlPart, op: DrawingTreeDocOp): TreeOpRejection | null;validateExternalTargetfunctionSource ↗
Validate an external-mode relationship target. It MUST be an absolute URI, is retained verbatim by the caller, and is NEVER owner-resolved or fetched here. Unsafe schemes (javascript/vbscript/data/file) are rejected for runtime sinks; the raw lexical form is still preserved separately by the authored record.
declare function validateExternalTarget(raw: string): NameResult;validateFixturefunctionSource ↗
Structurally validate a fixture against the frozen format rules.
declare function validateFixture(fixture: ConformanceFixture): ValidationResult;validateGifHeaderfunctionSource ↗
Structural GIF logical screen descriptor validation before decode.
declare function validateGifHeader(bytes: Uint8Array): ValidatedRasterHeader | null;validateJpegHeaderfunctionSource ↗
Bounded JPEG marker scan through the first supported SOF marker.
declare function validateJpegHeader(bytes: Uint8Array): ValidatedRasterHeader | null;validateOoxmlPartfunctionSource ↗
Validate a parser-created or copy-modified immutable part before publication. Future tree-edit primitives can retain shared nodes and their IDs, while any replacement chooses explicitly whether to retain or allocate identity.
declare function validateOoxmlPart(part: OoxmlPart): OoxmlInvariantResult;validatePackageInvariantsfunctionSource ↗
The two invariants a package must satisfy before it is published.
Both describe the half-written state that splitting a multi-part write across transactions produces, and both make a package Word refuses to open:
- a relationship pointing at a part nobody created; - a part with no content type, which is unopenable even though the XML is well formed.
Checked at the commit boundary rather than inside each primitive, for the same reason part validation moved there: a transaction is allowed to pass through an inconsistent intermediate as long as nothing can observe it.
declare function validatePackageInvariants(pkg: OoxmlPackage): PackageInvariantResult;validatePngHeaderfunctionSource ↗
Structural PNG IHDR validation before decode.
declare function validatePngHeader(bytes: Uint8Array): ValidatedRasterHeader | null;validateRasterHeaderfunctionSource ↗
Validate a raster image's header structurally and report its real MIME type and extent.
Content type is a CLAIM; this is what makes it a fact. A file declaring image/png over JPEG bytes is caught here rather than at decode.
declare function validateRasterHeader(bytes: Uint8Array, mime: SupportedImageMime): ValidatedRasterHeader | null;validateTreeOpfunctionSource ↗
Structural validation, run before any tree work so a rejection changes nothing.
declare function validateTreeOp(part: OoxmlPart, op: TreeDocOp): TreeOpRejection | null;w14RootPrefixfunctionSource ↗
The non-empty prefix the part ROOT binds to the w14 namespace, or null.
Minted attributes require an in-scope binding (the invariant validator reports invalid-qname otherwise, and the serializer would allocate an nsN alias). Only the root binding counts: a binding authored on some descendant does not cover paragraphs elsewhere in the tree.
declare function w14RootPrefix(root: OoxmlElement): string | null;walkAllStoryParagraphsfunctionSource ↗
Every story paragraph in reading order — body, table cells, and flattened block controls.
declare function walkAllStoryParagraphs(children: readonly OoxmlNode[], sdtDepth: number, visit: (paragraph: OoxmlElement) => void): void;walkParagraphInlinefunctionSource ↗
Paragraph-level inline sequence — runs, hyperlinks, and inline content controls in order.
visit receives each direct w:r and any other inline node the caller treats as opaque (bookmarks, drawings, …). Hyperlinks and content controls are descended transparently.
declare function walkParagraphInline(children: readonly OoxmlNode[], depth: number, visit: (child: OoxmlNode) => void): void;walkStoryBlocksfunctionSource ↗
Story blocks in document order, flattening block-level content controls — same shape as layout's storyBlocks and store bodyBlocks.
declare function walkStoryBlocks(children: readonly OoxmlNode[], depth: number, visit: (block: OoxmlElement) => void): void;withBinaryPartfunctionSource ↗
Store raw bytes for a part and declare its exact content type.
Does not create a relationship; callers decide which owner points at the part.
declare function withBinaryPart(pkg: OoxmlPackage, partName: string, bytes: Uint8Array, contentType: string): OoxmlPackage;withContentTypeOverridefunctionSource ↗
Declare a content type for a part, by upserting an <Override> in the content-types tree.
A no-op when the part already resolves to the same type, so repeating a write does not append a duplicate entry. Resolving to a DIFFERENT type replaces the existing Override in place. forceOverride writes an explicit Override even when a Default already matches.
declare function withContentTypeOverride(pkg: OoxmlPackage, partName: string, contentType: string, options?: {
readonly forceOverride?: boolean;
}): OoxmlPackage;withCustomXmlDataPartfunctionSource ↗
Ensure the document carries a data part for this namespace, creating it and everything it needs — properties, both relationships, the properties content type — when it does not.
Idempotent: a package that already has one for the namespace comes back untouched, so a second node added to the same store does not author a second store.
declare function withCustomXmlDataPart(pkg: OoxmlPackage, storyPartName: string, namespaceUri: string, rootLocalName: string): CustomXmlDataPartResult;withCustomXmlNodefunctionSource ↗
Write a node, replacing one that already has the id.
Replace rather than append: a second node with the same id makes the binding xpath ambiguous, and Word resolves an ambiguous xpath to the first match — so an "update" that appended would leave the control showing its old text forever.
declare function withCustomXmlNode(pkg: OoxmlPackage, partName: string, node: CustomXmlNode): OoxmlPackage;withEmbeddedImagefunctionSource ↗
Add image bytes to the package: the media part, its content type, and the relationship.
All three together — bytes with no relationship are unreachable, and a relationship with no content-type record makes the package invalid.
declare function withEmbeddedImage(pkg: OoxmlPackage, ownerPartName: string, input: Readonly<{
bytes: Uint8Array;
mime: SupportedImageMime;
}>): Readonly<{
ok: true;
pkg: OoxmlPackage;
partName: string;
relationshipId: string;
docPrId: number;
}> | Readonly<{
ok: false;
reason: 'invalidArgs' | 'invalid-image';
}>;withExportedCustomNodesfunctionSource ↗
Apply the policy, then take the payloads and the stores the policy orphaned.
Order matters and is the reverse of the write's. The BODY goes first, so the sweep that follows sees the controls that actually survive; the stores go last, once nothing binds them. Doing it the other way would strip a store while a control still quoted its w:storeItemID, which is a document Word opens and offers to repair.
declare function withExportedCustomNodes(pkg: OoxmlPackage, request: CustomNodeExportRequest): CustomNodeExportResult;withNewPartfunctionSource ↗
Add a part that does not exist yet, with the content-type override it needs to be openable.
Deliberately does NOT create a relationship: a part is reachable because something points at it, and which part points at it is the caller's decision. Creating one here would guess.
declare function withNewPart(pkg: OoxmlPackage, partName: string, root: OoxmlElement, contentType: string): OoxmlPackage;withoutCustomXmlDataPartfunctionSource ↗
Remove a store from a document: both parts, both relationships, the Override.
PACKAGE ONLY. It does not touch the body, so a w:sdt bound to the store keeps its w:dataBinding, its w:storeItemID and its w:tag, and Word then opens a control bound to a store that is not there. Stripping those is the export path's job and is not built; this is the half that removes the payload, which is the half a caller can rely on.
ok: false means nothing was removed and the package is unchanged — most often because an owner's .rels was never parsed into a tree, which [withoutPart](withoutPart) refuses to work around. A caller exporting a document has to treat that as a failure to export rather than as a document with nothing to strip, or it ships the payload it meant to remove.
declare function withoutCustomXmlDataPart(pkg: OoxmlPackage, storyPartName: string, namespaceUri: string): WithoutPartResult;withoutCustomXmlNodefunctionSource ↗
Drop one node by id. A store that never held it comes back unchanged.
declare function withoutCustomXmlNode(pkg: OoxmlPackage, partName: string, nodeId: string): OoxmlPackage;withoutOrphanCustomXmlNodesfunctionSource ↗
Drop every node no longer referenced, given the ids the document still binds.
This is the whole deletion story. Deleting a control in THIS editor can remove its node directly, but a control deleted in Word leaves the node behind — Word has no lifecycle link between the two and no way to run our code. Reconciling against what the story actually binds collects both, and is the only thing that can collect the second.
Takes the referenced ids rather than reading the story itself: the caller already walked it, and a sweep that guessed at which controls exist would delete a payload on a mistake.
declare function withoutOrphanCustomXmlNodes(pkg: OoxmlPackage, partName: string, referencedIds: ReadonlySet<string>): {
readonly pkg: OoxmlPackage;
readonly removed: readonly string[];
};withoutUnreferencedImagePartfunctionSource ↗
Remove an orphaned image media part after a package-wide internal relationship target check.
declare function withoutUnreferencedImagePart(pkg: OoxmlPackage, partName: string): OoxmlPackage;withPartfunctionSource ↗
Replace one part's tree, returning a new package. Pure, like the tree edits themselves.
declare function withPart(pkg: OoxmlPackage, part: OoxmlPart): OoxmlPackage;withRelationshipfunctionSource ↗
Add or replace one relationship on a part, returning a new package.
declare function withRelationship(pkg: OoxmlPackage, ownerPart: string, type: string, rawTarget: string): {
readonly pkg: OoxmlPackage;
readonly relationshipId: string;
readonly ok: boolean;
};wrapTargetToAnchorSpecfunctionSource ↗
Map the nine wrap targets to anchor wrap element + behindDoc.
declare function wrapTargetToAnchorSpec(target: ImageWrapTarget): {
readonly behindDocument: boolean;
readonly wrapLocalName: 'wrapNone' | 'wrapSquare' | 'wrapTight' | 'wrapThrough' | 'wrapTopAndBottom';
readonly wrapText?: 'bothSides' | 'left' | 'right' | 'largest';
};writeOoxmlPackagefunctionSource ↗
Serialize a canonical package back to DOCX bytes.
Starts from the ORIGINAL entry bytes and overwrites only the parts held as trees. A part the loader did not model — media, fonts, an XML part outside the modeled set — passes through untouched, so round-tripping a document cannot lose a part the engine never claimed to understand.
The modeled parts are re-emitted NORMALIZED from the tree rather than patched as text. That is the whole point of the canonical tree: correctness is judged by the two D9 oracles (the namespace-aware fingerprint and the save/reopen semantic digest), not by byte equality, so a different-but-equivalent spelling is not a defect.
writeZip re-validates every part name, so a name that became unsafe between load and save cannot be smuggled into the archive.
declare function writeOoxmlPackage(pkg: OoxmlPackage): Uint8Array;writeZipfunctionSource ↗
Deflate a set of canonical-part-name - bytes into a ZIP archive. Every part name is re-validated through the OPC normalization profile before writing, so a traversal/encoded/normalized-alias name from an untrusted serialized model can never be smuggled into a ZIP entry (write-side path-traversal guard).
declare function writeZip(entries: ReadonlyMap<string, Uint8Array>): Uint8Array;Classes (16)
BoundedCounterclassSource ↗
Overflow-safe counting against a fixed limit.
Never silently wraps: it rejects the increment that would cross its limit AND any arithmetic that would exceed Number.MAX_SAFE_INTEGER. That second guard is the point — a file-supplied count must never be trusted into an allocation, and a wrapped counter reads as small.
declare class BoundedCounter| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `BoundedCounter` class |
| add | | Add `n` (default 1). Throws LimitExceededError if the result would exceed the limit (so `limit` itself is reachable but `limit + 1` is not) or overflow the safe-integer range. On rejection the counter is unchanged. |
| canAdd | | Whether adding `n` would be accepted, without mutating. |
| current | number | |
| label | string | |
| limit | number | |
| release | | |
| remaining | number | Remaining headroom before the limit. |
BudgetclassSource ↗
One node in the hierarchical resource budget tree.
An operation owns a root budget; parsers, extensions, workers, layout, transport and output carve children from it, so no subsystem can consume more than the operation as a whole allows.
dispose() REFUSES while children or reservations are outstanding, then runs registered cleanups LIFO — spill files, worker termination — even if one throws. A leaked child budget is a leaked worker, so the refusal is the diagnostic.
declare class Budget| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `Budget` class |
| available | number | |
| capacity | number | |
| child | | Carve a child budget of `capacity` out of this budget's headroom. |
| dispose | | Release this budget. Refuses while any child budget or reservation is outstanding (children must finish first). Runs cleanups LIFO, returns the carve-out to the parent, and marks disposed. Cleanup errors are collected and rethrown after every cleanup has run. |
| inUse | number | |
| isDisposed | boolean | |
| label | string | |
| onRelease | | Register cleanup for a spill file, worker, or queue tied to this budget. |
| reserve | | Reserve `amount` from this budget. Throws if it would exceed capacity. |
BudgetErrorclassSource ↗
A budget was misused: over-carved, over-reserved, or disposed with children outstanding.
declare class BudgetError extends Error| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `BudgetError` class |
CancellationControllerclassSource ↗
The write side of cancellation, and the owner of the phase.
Whoever starts an operation holds this; everything it calls gets only the token.
declare class CancellationController| Member | Type | Summary |
|---|---|---|
| cancel | | |
| derivedOnly | boolean | Cancelled after publication - full rollback is no longer possible. |
| isCancelled | boolean | |
| isPublished | boolean | |
| markPublished | | Mark canonical publication — the point of no return. |
| phase | CancellationPhase | |
| token | CancellationToken |
CancellationErrorclassSource ↗
Thrown from a checkpoint() when the operation has been cancelled.
declare class CancellationError extends Error| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `CancellationError` class |
| derivedOnly | boolean | True when the commit is already published and only derived work is cancelled. |
DangerousKeyErrorclassSource ↗
A file-derived key that would pollute a prototype. Refused, never sanitized-and-accepted.
declare class DangerousKeyError extends Error| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `DangerousKeyError` class |
| key | string | |
| path | string |
DeterministicClockclassSource ↗
Deterministic clock: starts at start and advances by step each call.
declare class DeterministicClock implements ClockPort| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `DeterministicClock` class |
| now | |
DeterministicMemoryMeterclassSource ↗
Deterministic memory substitute. Tracks current and peak "allocated" units against a hard byte ceiling; allocate fails closed (LimitExceededError) past the limit. Used in place of process RSS so memory-limit tests are reproducible and cancellation/cleanup can be asserted without a real allocator.
declare class DeterministicMemoryMeter| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `DeterministicMemoryMeter` class |
| allocate | | |
| currentBytes | number | |
| free | | |
| peakBytes | number | |
| reset | | Release everything (cancellation/cleanup path). |
LimitExceededErrorclassSource ↗
A counter's limit was reached. Carries the label, the limit, and what was attempted.
Thrown at the N → N+1 boundary, so the increment that would have crossed the limit never happens rather than being detected afterwards.
declare class LimitExceededError extends Error| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `LimitExceededError` class |
| attempted | number | |
| label | string | |
| limit | number |
PortRegistryclassSource ↗
The environment-dependent services an engine instance may reach.
Everything outside pure computation — the clock, identity minting, scheduling, fonts, images — is reached only through here, which is what lets browser, worker and server adapters supply only what their runtime actually offers.
declare class PortRegistry| Member | Type | Summary |
|---|---|---|
| availablePorts | | The provided port ids (for bridging to registry.resolve availablePorts). |
| clock | | |
| has | | |
| identity | | |
| missing | | Assert every id in `portIds` is present; returns the missing ones (empty if all present). |
| provide | | |
| resolve | | Resolve a port by id or throw. |
PortResolutionErrorclassSource ↗
A required port the runtime did not provide.
Thrown rather than falling back: silently reaching for a browser global when a worker or server adapter did not supply a port is exactly the coupling ports exist to prevent.
declare class PortResolutionError extends Error| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `PortResolutionError` class |
| portId | string |
PrefixAllocatorclassSource ↗
Controlled namespace-prefix allocation: deterministic, collision-free prefixes for namespace URIs. A known URI always yields the same registered prefix; new URIs get a generated ns{n} prefix, never one derived from file content.
declare class PrefixAllocator| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `PrefixAllocator` class |
| bindings | | The declared bindings, for emitting xmlns declarations. |
| prefixFor | |
RegistryErrorclassSource ↗
A resolution failure naming every responsible party.
Thrown rather than returned: an unresolvable registry is a build-time composition mistake, and an engine running with a half-resolved registry would fail later in ways that do not point back to the bundle that caused it.
declare class RegistryError extends Error| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `RegistryError` class |
| code | RegistryErrorCode | |
| responsible | readonly string[] | Stable identities responsible for the failure (extensions, ids). |
SequentialIdentityclassSource ↗
Sequential identity for tests and deterministic fixtures.
declare class SequentialIdentity implements IdentityPort| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `SequentialIdentity` class |
| newId | |
TreeDocumentStoreclassSource ↗
The document store: one transaction is one atomic publication and one history entry.
apply STAGES ops against a working part and nothing is visible until transact returns, so a batch rejected halfway leaves the revision, the tree, the indexes and every subscriber exactly as they were. That all-or-nothing property is what lets a caller compose ops without having to reason about partial application.
declare class TreeDocumentStore| Member | Type | Summary |
|---|---|---|
| (constructor) | | Open a store over a package, editing the named story part. |
| beginComposition | | Open one history entry for an IME composition. |
| cancelComposition | | Cancel an open composition without recording an entry, leaving whatever it committed in place. An IME cancel is not an undo request; the caller decides what to revert. |
| canRedo | boolean | |
| canUndo | boolean | |
| checkpoint | | Snapshot part, revision, and undo/redo stacks so the package coordinator can roll back a story transaction that fails after commit (e.g. note-reference cascade) or discard a local history entry when promoting to a package undo unit. |
| compositionActive | boolean | |
| endComposition | | Close the composition, recording its entry only if anything actually committed. |
| graftPackage | | Replace the package OUTSIDE the transaction and history lanes. |
| historyDepth | number | Retained entries — the unit `undo()` reverses, so tests can assert grouping. |
| package | OoxmlPackage | Every part, including the ones a multi-part transaction wrote. |
| part | OoxmlPart | The story part being edited. Unchanged for every caller that predates the widening. |
| redo | | |
| replacePart | | Replace the current part without recording history, but advance the revision so revision-keyed projections cannot survive a package snapshot install. |
| restoreCheckpoint | | Full restore — part, revision, history stacks, and composition. |
| restoreHistoryStacks | | Restore undo/redo stacks only, keeping the current part and revision. Used when a story mutation is promoted to a package history pointer so the local orphan entry does not steal a later undo. |
| revision | number | |
| selectionForRedo | | The selection to restore for the entry `redo()` would reapply next. |
| selectionForUndo | | The selection to restore for the entry `undo()` would reverse next. |
| setStoryRef | | Stamp story identity onto subsequent publishes for this store (including undo/redo). Used by the package coordinator so history navigation keeps the same scope tag. |
| subscribe | | |
| transact | | Run one atomic transaction. |
| undo | |
TreePackageStoreclassSource ↗
Package-level mutation authority: routes TreeDocOps to the store for a story part, publishes one ModelChange / undo unit per transaction, and keeps currentPackage() coherent for save/reopen.
declare class TreePackageStore| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `TreePackageStore` class |
| adoptPackageUnit | | Record a write that spanned SEVERAL parts as one package undo unit. |
| applyImageProperties | | Properties batch with hyperlink relationship create/update/remove in one package unit. |
| applyLifecycleOp | | Commit one furniture or note lifecycle op as a single ModelChange / undo unit that restores the entire package atomically (parts, rels, content-types, settings). |
| beginComposition | | |
| bodyStore | | Body store — independent revision/index from every HF store. |
| cancelComposition | | |
| canRedo | boolean | |
| canUndo | boolean | |
| compositionSessionOpen | | Whether a package-wide IME composition session is open on any story. |
| currentPackage | | The current package with every opened story store's part merged in. Pure snapshot of authority; callers must not mutate. |
| deleteImage | | Delete a picture drawing and collect orphaned media in one package undo unit. |
| embedExternalImage | | Fetch external bytes explicitly and embed them; no fetch on open/load. |
| endComposition | | |
| insertImage | | Insert a validated raster image as one package undo unit (task 12). |
| installPackageSnapshot | | Install a full package snapshot (public seam for post-fetch cleanup). |
| lastModelChange | TreeModelChange | null | |
| openedStoryCount | | How many story stores are open (body counts as one). |
| packageRevision | number | |
| partFor | | Current part for a scope, or null when the target is refused. |
| promoteStoryTransactionToPackageUnit | | Promote a story transaction that wrote package bytes to one package undo pointer. Used by image intents and note-reference cascade. |
| publishStoryWrite | | Publish a story transaction the coordinator did not run. |
| redo | | |
| replaceImage | | Replace a picture drawing's embedded media in one package undo unit. |
| replacePackageShell | | Replace the package shell while preserving opened stores. Used when numbering / content-types mutate the package outside story trees. |
| resolveStory | | Resolve a story scope to its store. Fail closed for dangling / wrong-typed / missing targets — layout may fail open on the same rId, but mutation must not invent a part. |
| revisionFor | | Per-story revision, or null when the target is refused. |
| selectionForRedo | | |
| selectionForUndo | | |
| setDrawingMetadataWithHyperlink | | Metadata plus hyperlink target creation in one package transaction. |
| subscribe | | |
| transact | | Commit ops against one story as ONE transaction / undo unit / ModelChange. Header/footer and notes-part commits publish `impact: 'global'`. Deleting a `noteReference` via `deleteText` or a block subtree via `deleteBlock` cascades the note body in the same package undo unit. |
| undo | |
Interfaces (183)
AddCommentRequestinterfaceSource ↗
What adding a comment needs: where it anchors, who wrote it, and its body.
author is required because CT_Comment makes @w:author mandatory — a comment without one writes invalid XML, so the write is refused rather than filled with an empty attribute.
interface AddCommentRequest| Member | Type | Summary |
|---|---|---|
| anchor | CommentAnchorRequest | |
| author | string | Required by `CT_TrackChange`. A comment without one writes invalid XML. |
| date? | string | ISO-8601. Absent writes no `@w:date`, because inventing one is a content change. |
| initials? | string | |
| replyToCommentId? | string | The comment this replies to. Its thread link is written to `commentsExtended.xml`. |
| text | string |
AnchorSnapshotinterfaceSource ↗
Where anchors sat after a step — how a fixture proves positions survived an edit.
interface AnchorSnapshot| Member | Type | Summary |
|---|---|---|
| affinity | 'before' | 'after' | |
| anchorId | string | |
| block | string | |
| story | string |
AtomicFieldSpaninterfaceSource ↗
One atomic field span inside a paragraph for caret / delete / selection.
removeNodeIds lists every node that must leave with the unit (begin…end chrome and cached-result content for complex fields; the fldSimple element for simple fields).
formatRunIds lists the runs whose w:rPr owns displayed result formatting — result-phase runs with measurable cache text for complex fields, child w:rs for fldSimple, or the separate/begin run when the result is empty. Delete / caret addressing still uses runId (the begin / simple node); formatting must not rewrite chrome-only begin runs when the painted glyphs come from a different result run.
interface AtomicFieldSpan| Member | Type | Summary |
|---|---|---|
| formatRunIds | readonly string[] | Runs that own displayed result formatting (may differ from `runId`). |
| kind | 'complex' | 'simple' | |
| node | OoxmlNode | Addressable segment node (begin `fldChar` or `fldSimple`). |
| removeNodeIds | readonly string[] | |
| runId | string | Run that owns the begin marker; empty string for paragraph-level `fldSimple`. |
AtomicNoteSpaninterfaceSource ↗
One atomic note span inside a paragraph for caret / delete / selection.
Each typed note atom is a single-node span (removeNodeIds = that node).
interface AtomicNoteSpan| Member | Type | Summary |
|---|---|---|
| kind | 'noteReference' | 'noteRef' | 'separator' | 'continuationSeparator' | |
| node | OoxmlNode | |
| removeNodeIds | readonly string[] | |
| runId | string |
AuditPortinterfaceSource ↗
Redacted observability sink (raw text never enters here — design D5).
interface AuditPort| Member | Type | Summary |
|---|---|---|
| record | |
AuthoredNotePropertiesinterfaceSource ↗
Authored subset — only keys present in the file appear.
interface AuthoredNoteProperties| Member | Type | Summary |
|---|---|---|
| numFmt? | string | |
| numRestart? | string | |
| numStart? | number | |
| pos? | string |
AuthorizationPortinterfaceSource ↗
Read/write/export authorization decisions.
interface AuthorizationPort| Member | Type | Summary |
|---|---|---|
| authorize | |
BookmarkAnchorinterfaceSource ↗
One bookmark's name and the range its marker pair currently encloses.
interface BookmarkAnchor| Member | Type | Summary |
|---|---|---|
| name | string | |
| offset | number | UTF-16 offset within that paragraph, in `paragraphTextOf`'s vocabulary. |
| paragraphId | string | Canonical node id of the paragraph the marker sits in. |
CancellationPortinterfaceSource ↗
Cancellation source for the current operation.
interface CancellationPort| Member | Type | Summary |
|---|---|---|
| token | CancellationToken |
CancellationTokeninterfaceSource ↗
The read side of cancellation, handed to cooperative work.
Cooperative rather than pre-emptive: long work calls checkpoint() at declared intervals, which is what lets an operation unwind promptly without the engine having to interrupt it mid-mutation.
interface CancellationToken| Member | Type | Summary |
|---|---|---|
| checkpoint | | Throws CancellationError if cancelled; call at declared checkpoint intervals. |
| derivedOnly | boolean | True only when cancelled AND the commit is already published. |
| isCancelled | boolean | |
| phase | CancellationPhase |
CapabilityIdinterfaceSource ↗
A validated (kind, id, version) triple — the registry's unit of identity.
interface CapabilityId| Member | Type | Summary |
|---|---|---|
| id | string | |
| kind | IdKind | |
| version | string |
CascadeDeletedNoteReferencesOptionsinterfaceSource ↗
How deleting text cascades into the notes it referenced.
A note's body and the citation reaching it are one thing to a reader, so removing the reference must remove the body too or the notes part keeps an entry nothing points at.
interface CascadeDeletedNoteReferencesOptions| Member | Type | Summary |
|---|---|---|
| afterBudget? | NoteReferenceScanBudget | |
| beforeBudget? | NoteReferenceScanBudget | Independent full budgets per snapshot. When omitted each snapshot gets its own default budget — never share one counter across before/after walks. |
ClockPortinterfaceSource ↗
Injectable time source — the engine never calls Date.now directly (determinism).
interface ClockPort| Member | Type | Summary |
|---|---|---|
| now | |
CommentAnchorinterfaceSource ↗
Where a comment is anchored, as a range.
orphaned records that the file did not give this comment a usable range — a reference with no range markers, or a start with no end. The comment is still listed, marked orphaned, rather than dropped: a reviewer's remark disappearing silently is worse than one that says it lost its text.
interface CommentAnchor| Member | Type | Summary |
|---|---|---|
| commentId | string | |
| end | CommentPosition | |
| orphaned | boolean | |
| partName | string | Canonical name of the part the range lives in, so a header comment is attributable. |
| start | CommentPosition |
CommentAnchorRequestinterfaceSource ↗
Where a comment is anchored, in the model offset space of one story.
interface CommentAnchorRequest| Member | Type | Summary |
|---|---|---|
| end | number | May sit in the same paragraph or a later one; `endParagraphId` names it when it differs. |
| endParagraphId? | string | |
| paragraphId | string | |
| start | number |
CommentPositioninterfaceSource ↗
A position in one story: a paragraph node id plus a UTF-16 offset inside it.
interface CommentPosition| Member | Type | Summary |
|---|---|---|
| offset | number | |
| paragraphId | string |
CommentRecordinterfaceSource ↗
One comment as authored in word/comments.xml.
interface CommentRecord| Member | Type | Summary |
|---|---|---|
| author | string | |
| blocks | readonly OoxmlElement[] | Body paragraphs, as tree nodes, so the surface renders measured text rather than a string. |
| date? | string | |
| id | string | |
| initials? | string | |
| paraId? | string | `w14:paraId` of the first body paragraph — the key thread state is stored under. |
| parentCommentId? | string | `@w16cid:parentId` — the `w:id` of the comment this replies to, when the file names it. |
CommentThreadStateinterfaceSource ↗
Thread state for one comment, read from commentsExtended.xml.
interface CommentThreadState| Member | Type | Summary |
|---|---|---|
| done | boolean | |
| parentParaId? | string | `@w15:paraIdParent` — the comment this one replies to, absent for a top-level comment. |
ComparatorDescriptorinterfaceSource ↗
One artifact class's comparison mode and its declared ephemera — fields excluded from equality.
interface ComparatorDescriptor| Member | Type | Summary |
|---|---|---|
| ephemera | readonly string[] | Object keys excluded from canonical-exact comparison (declared ephemera). |
| id | string | |
| mode | ComparatorMode | |
| note | string |
ComparisonResultinterfaceSource ↗
Whether two artifacts matched, and where they diverged when they did not.
interface ComparisonResult| Member | Type | Summary |
|---|---|---|
| equal | boolean | |
| left? | string | Canonical forms when unequal (diagnostic). |
| right? | string |
ConformanceFixtureinterfaceSource ↗
The frozen conformance container: revisions, origins, operations, changes, snapshots and hashes.
The CONTAINER is what is frozen — field names, origin membership, revision monotonicity, hash format. The op and change payloads travel opaquely, so their schemas can evolve without invalidating every recorded fixture.
interface ConformanceFixture| Member | Type | Summary |
|---|---|---|
| documentId | string | |
| formatVersion | 1 | |
| snapshots? | readonly EncodedEnvelope[] | |
| source | FixtureSource | |
| steps | readonly FixtureStep[] | |
| updates? | readonly EncodedEnvelope[] |
ContentControlCheckboxinterfaceSource ↗
A checkbox's state and the two glyphs it chooses between.
Both glyphs matter on a write: setting the value has to update w14:checked AND the run's character, or the document's glyph and its recorded state disagree.
interface ContentControlCheckbox| Member | Type | Summary |
|---|---|---|
| checked | boolean | |
| checkedState? | ContentControlCheckboxState | |
| uncheckedState? | ContentControlCheckboxState |
ContentControlCheckboxStateinterfaceSource ↗
One of a checkbox's two glyphs: the font and code point it is drawn with.
interface ContentControlCheckboxState| Member | Type | Summary |
|---|---|---|
| font? | string | |
| value | string | The `w14:val` hex code point of the glyph, exactly as the control declares it. |
ContentControlDataBindinginterfaceSource ↗
w:dataBinding — the custom-XML part and XPath a control's value is bound to.
interface ContentControlDataBinding| Member | Type | Summary |
|---|---|---|
| prefixMappings? | string | |
| storeItemID? | string | |
| xpath? | string |
ContentControlDateFormatinterfaceSource ↗
A date picker's authored format and locale, for rendering and for parsing what it stores.
interface ContentControlDateFormat| Member | Type | Summary |
|---|---|---|
| calendar? | string | |
| dateFormat? | string | |
| fullDate? | string | |
| lid? | string | |
| storeMappedDataAs? | string |
ContentControlEntryinterfaceSource ↗
One control, plus how deeply it is nested and the controls that enclose it.
interface ContentControlEntry| Member | Type | Summary |
|---|---|---|
| ancestors | readonly OoxmlContentControlNode[] | Enclosing controls, outermost first. Empty at depth 0. |
| depth | number | 0 for a top-level control; the nesting depth otherwise. |
| node | OoxmlContentControlNode |
ContentControlListIteminterfaceSource ↗
One declared option of a dropdown or combo box: its display text and its stored value.
interface ContentControlListItem| Member | Type | Summary |
|---|---|---|
| displayText | string | |
| value | string |
ContentControlPropertiesinterfaceSource ↗
A control's whole w:sdtPr, projected into one typed shape.
What every other lane reads instead of walking localName strings — which also means a Word re-save that demotes the properties node to generic does not break the projection.
interface ContentControlProperties| Member | Type | Summary |
|---|---|---|
| alias? | string | |
| checkbox? | ContentControlCheckbox | |
| dataBinding? | ContentControlDataBinding | |
| date? | ContentControlDateFormat | |
| id? | number | `@w:val` of `w:id` when the file declares a parseable one. Never fabricated. |
| label? | string | |
| lastValue? | string | |
| listItems | readonly ContentControlListItem[] | Items a dropdown or combo box offers. Empty for every other type. |
| lock | ContentControlLock | |
| multiLine? | boolean | |
| placeholderDocPart? | string | The glossary entry named by `w:placeholder/w:docPart`. Preserved, never loaded. |
| showingPlaceholder | boolean | |
| tabIndex? | number | |
| tag? | string | |
| temporary | boolean | |
| type | ContentControlKind |
ContentIteminterfaceSource ↗
One item a scrub pass considers: its kind, and where in the package it sits.
interface ContentItem| Member | Type | Summary |
|---|---|---|
| id | string | |
| kind | string |
ContentTypeIndexinterfaceSource ↗
The resolved lookup: Override by case-folded part name, Default by case-insensitive extension.
interface ContentTypeIndex| Member | Type | Summary |
|---|---|---|
| defaults | ReadonlyMap<string, string> | ext key - single MIME (identical duplicates collapsed). |
| overrides | ReadonlyMap<string, string> | case-folded part name - MIME. |
ContentTypeRecordsinterfaceSource ↗
The authored [Content_Types].xml records, in significant order.
Retained rather than collapsed into a lookup, because the file's lexical form and ordering are part of what a lossless save re-emits.
interface ContentTypeRecords| Member | Type | Summary |
|---|---|---|
| defaults | readonly DefaultRecord[] | |
| overrides | readonly OverrideRecord[] |
ContributioninterfaceSource ↗
One thing a bundle contributes: a command, a query, a schema, a port, keyed by (kind, id).
interface Contribution| Member | Type | Summary |
|---|---|---|
| id | string | |
| kind | Exclude<IdKind, 'extension' | 'origin' | 'result'> | |
| payload? | unknown | |
| replaceable? | ReplacementPolicy | Policy this contribution exposes to would-be replacers (default `none`). |
| replaces? | {
readonly targetId: string;
readonly targetRange: string;
readonly priority?: number;
} | If set, this contribution replaces an existing base contribution. |
| version | string |
CreateImageResourceCacheOptionsinterfaceSource ↗
How the image cache decodes, and what it will spend doing so.
interface CreateImageResourceCacheOptions| Member | Type | Summary |
|---|---|---|
| decodePort | ImageDecodePort | |
| limits? | Partial<ImageResourceLimits> |
CustomNodeBindinginterfaceSource ↗
The three attributes a w:dataBinding carries.
interface CustomNodeBinding| Member | Type | Summary |
|---|---|---|
| prefixMappings | string | |
| storeItemId | string | |
| xpath | string |
CustomNodeExportRequestinterfaceSource ↗
How [withExportedCustomNodes](withExportedCustomNodes) decides, and which stores it may tidy afterwards.
interface CustomNodeExportRequest| Member | Type | Summary |
|---|---|---|
| decide | (tag: string) => CustomNodeExportPolicy | The fate of a control carrying this `w:tag`. A control with no tag is never touched. |
| namespaces | readonly string[] | Payload namespaces the caller CLAIMS. |
| storyPartName | string | The story whose controls are policed, and whose relationships the stores hang off. |
CustomNodePayloadReadinterfaceSource ↗
One control's payload, as the store holds it. Both strings are untrusted file input.
interface CustomNodePayloadRead| Member | Type | Summary |
|---|---|---|
| data | string | The payload as authored. JSON by convention, unparsed here. |
| label | string | The text Word paints the control from. |
| nodeId | string | The store node's own id. |
CustomNodePayloadWriteinterfaceSource ↗
The payload half of an insert: which store, which node, and what it holds.
data is opaque here. The lane that owns a schema is the one that declared it, and a store that parsed payloads would be a second opinion about what a host's node means.
interface CustomNodePayloadWrite| Member | Type | Summary |
|---|---|---|
| data | string | The payload, serialized. JSON by convention; never parsed here. |
| label | string | The text the control shows. Word paints this from the store, so an empty one is an empty chip. |
| namespaceUri | string | Namespace of the store's root element — what identifies one store among several. |
| nodeId | string | The node's own id, which the binding's xpath quotes. |
| rootLocalName | string | Local name of that root. An NCName; anything else refuses. |
CustomXmlDataPartinterfaceSource ↗
A data part located in a package: where it lives, and the GUID an SDT binds to.
interface CustomXmlDataPart| Member | Type | Summary |
|---|---|---|
| itemId | string | `ds:itemID`, braced and upper-case, as `w:storeItemID` must spell it. |
| namespaceUri | string | Namespace URI of the payload root, which is what identifies one store among several. |
| partName | string | Canonical part name, e.g. `/customXml/item1.xml`. |
| propsPartName | string | Part name of its properties, e.g. `/customXml/itemProps1.xml`. |
CustomXmlDataPartResultinterfaceSource ↗
What [withCustomXmlDataPart](withCustomXmlDataPart) answers.
interface CustomXmlDataPartResult| Member | Type | Summary |
|---|---|---|
| part | CustomXmlDataPart | null | Null when the part could not be authored; the package then comes back unchanged. |
| pkg | OoxmlPackage |
CustomXmlNodeinterfaceSource ↗
One node in a store: its id, the bound text, and the payload beside it.
interface CustomXmlNode| Member | Type | Summary |
|---|---|---|
| data | string | Payload as authored, JSON by convention and unparsed here. Untrusted file input. |
| id | string | |
| label | string | Text a `w:dataBinding` resolves to. Untrusted file input. |
DefaultRecordinterfaceSource ↗
One <Default>: a file extension mapped to a content type.
interface DefaultRecord| Member | Type | Summary |
|---|---|---|
| contentType | string | |
| extension | string | |
| order | number |
DetectedTocinterfaceSource ↗
A table of contents found in a document, whether wrapped in an SDT or a bare field.
interface DetectedToc| Member | Type | Summary |
|---|---|---|
| beginNodeId | string | |
| beginParagraphId | string | |
| containerId | string | Direct parent whose paragraph children delimit the cached result. |
| contentControlId? | string | |
| endParagraphId | string | |
| id | string | Enclosing control id when it identifies one TOC, otherwise the begin fldChar id. |
| instruction | TocInstruction | |
| resultParagraphIds | readonly string[] |
DocumentTrackingSettingsinterfaceSource ↗
What the document asks for. Every field defaults to "the document said nothing".
interface DocumentTrackingSettings| Member | Type | Summary |
|---|---|---|
| doNotTrackFormatting | boolean | `w:doNotTrackFormatting` — apply formatting without recording a `w:rPrChange`. |
| doNotTrackMoves | boolean | `w:doNotTrackMoves` — write a move as a delete and an insert. |
| restrictedToTrackedChanges | boolean | `w:documentProtection/@w:edit="trackedChanges"` — tracking may not be turned OFF. |
| trackRevisions | boolean | `w:trackRevisions` — the document asks for edits to be tracked. |
DrawingLocksinterfaceSource ↗
What a drawing refuses: selection, movement, resizing, aspect change.
Read and honoured rather than advisory — chrome that offered a handle the store will refuse would promise an edit that cannot happen.
interface DrawingLocks| Member | Type | Summary |
|---|---|---|
| changeAspect | boolean | |
| move | boolean | |
| resize | boolean | |
| select | boolean |
DrawingPositionInputinterfaceSource ↗
An anchored drawing's position: offsets, and the frames they are relative to.
The relative-to bases matter as much as the offsets. Writing an offset without preserving its base re-anchors the drawing against a different reference and moves it somewhere nobody asked.
interface DrawingPositionInput| Member | Type | Summary |
|---|---|---|
| horizontalEmu? | number | |
| mode? | 'frame' | 'simple' | `'simple'` when `@simplePos="1"`: `horizontalEmu` / `verticalEmu` are authoritative `wp:simplePos` x/y. `'frame'` (default) uses positionH/V relative frames. |
| relativeToH? | DrawingHorizontalReferenceFrame | |
| relativeToV? | DrawingVerticalReferenceFrame | |
| verticalEmu? | number |
EditOptionsinterfaceSource ↗
How an edit primitive validates its result.
By default every primitive runs the full-part invariant validation before handing its result back — the safe reading for an isolated call. A TRANSACTION applying many ops pays that full-tree walk once per primitive, which is what made a hundred-paragraph paste quadratic; it defers instead, and runs the same validation ONCE on the final tree before anything is published. Deferring is only sound for a caller that owns a commit boundary: nothing may escape between the unvalidated intermediate and the validated result.
interface EditOptions| Member | Type | Summary |
|---|---|---|
| deferValidation? | boolean |
EmbeddedFontinterfaceSource ↗
One font whose bytes travel inside the package.
The family name is the DOCUMENT's and is not validated — it is attacker-controlled, so it is escaped into CSS and never registered globally on document.fonts, where it would shadow the host application's own fonts.
interface EmbeddedFont| Member | Type | Summary |
|---|---|---|
| bytes | Uint8Array | Deobfuscated bytes, ready to be offered to a font validator. |
| family | string | The family as the document names it. Not validated against anything. |
| partName | string | The part they came from, for diagnostics. |
| style | FontStyleKey |
EncodedEnvelopeinterfaceSource ↗
Opaque encoded backend bytes (snapshot or replication update).
interface EncodedEnvelope| Member | Type | Summary |
|---|---|---|
| byteLength | number | |
| bytesHex | string | Hex-encoded opaque bytes; length MUST equal byteLength. |
| documentId | string | |
| kind | 'snapshot' | 'update' | |
| protocolVersion | number | |
| schemaVersion | number |
EnsuredHyperlinkRelationshipinterfaceSource ↗
The package with a hyperlink relationship guaranteed present, and that relationship's id.
interface EnsuredHyperlinkRelationship| Member | Type | Summary |
|---|---|---|
| pkg | OoxmlPackage | |
| relationshipId | string |
ExternalResourceConsentPortinterfaceSource ↗
Explicit consent gate for any remote/external resource (no zero-click fetch).
interface ExternalResourceConsentPort| Member | Type | Summary |
|---|---|---|
| requestConsent | |
FeatureBundleinterfaceSource ↗
A unit of engine functionality: its identity, version, dependencies, conflicts, required ports, and contributions.
The registry's whole input. Everything a bundle needs and everything it offers is DECLARED, so resolution can be deterministic and order-independent.
interface FeatureBundle| Member | Type | Summary |
|---|---|---|
| conflicts? | readonly string[] | |
| contributions | readonly Contribution[] | |
| dependencies? | readonly string[] | |
| id | string | |
| requiredPorts? | readonly string[] | |
| version | string |
FixtureExpectationinterfaceSource ↗
What one step must produce: its outcome, its change summary, and its authored-state hash.
interface FixtureExpectation| Member | Type | Summary |
|---|---|---|
| anchors? | readonly AnchorSnapshot[] | |
| authoredStateHash? | string | 16-hex authored-state fingerprint (comparator 0.4). |
| committedRevision? | number | Present iff outcome === 'applied'; MUST be baseRevision. |
| modelChange? | ModelChangeSummary | |
| outcome | FixtureOutcome | |
| outputHash? | string |
FixtureStepinterfaceSource ↗
One recorded operation and what it was expected to do.
interface FixtureStep| Member | Type | Summary |
|---|---|---|
| baseRevision | number | |
| expect | FixtureExpectation | |
| ops | readonly unknown[] | Opaque DocOp payloads (schema owned by section 4). |
| origin | string |
FontPortinterfaceSource ↗
Where font bytes come from. Opaque marker until its milestone.
interface FontPort| Member | Type | Summary |
|---|---|---|
| kind | 'font' |
HeaderFooterPartsinterfaceSource ↗
A section's resolved header and footer parts, by variant.
The even variant is only honoured when w:evenAndOddHeaders is set in settings.xml — without it Word ignores an authored even header, and so does this.
interface HeaderFooterParts| Member | Type | Summary |
|---|---|---|
| evenAndOddHeaders | boolean | `w:evenAndOddHeaders` in settings.xml — without it the `even` variant is ignored. |
| footers | ReadonlyMap<HeaderFooterVariant, OoxmlPart> | |
| headers | ReadonlyMap<HeaderFooterVariant, OoxmlPart> | |
| titlePage | boolean | Whether this section enables first-page header/footer furniture (`w:titlePg`). |
HeaderFooterSectionResolutioninterfaceSource ↗
Per-section resolution including declared-vs-inherited metadata.
interface HeaderFooterSectionResolution| Member | Type | Summary |
|---|---|---|
| evenAndOddHeaders | boolean | |
| footers | ReadonlyMap<HeaderFooterVariant, HeaderFooterSlotMeta> | |
| headers | ReadonlyMap<HeaderFooterVariant, HeaderFooterSlotMeta> | |
| titlePage | boolean |
HeaderFooterSlotMetainterfaceSource ↗
One resolved furniture slot with enough metadata for "Same as previous" chrome.
inherited: true means this section has no declared reference for the slot and the part comes from a predecessor. The first section never reports inherited — omitting a ref there is blank furniture, not inheritance from a later section.
interface HeaderFooterSlotMeta| Member | Type | Summary |
|---|---|---|
| inherited | boolean | |
| part | OoxmlPart | |
| partName | string | |
| rId | string |
HyperlinkTargetinterfaceSource ↗
A resolved hyperlink: its kind, its target, and the tooltip Word shows on hover.
interface HyperlinkTarget| Member | Type | Summary |
|---|---|---|
| anchor? | string | `w:anchor`, for an internal link. |
| authored | string | The authored target, verbatim: the relationship's `Target` for an `r:id` link, the anchor name for an internal one. Save re-emits from the tree, never from this — it is here so a UI can show what the document actually says. |
| href | string | null | The sanitized runtime projection, or `null` when there is nothing safe to navigate to. The ONLY value permitted in a DOM `href`, `window.open`, or a copied link. |
| kind | HyperlinkKind | |
| relationshipId? | string | The authored `r:id`, so an edit can rewrite the relationship it names. |
| tooltip? | string | `w:tooltip` — Word's hover text; paint puts it on the anchor's `title`. |
IdentityPortinterfaceSource ↗
Stable id minting for sessions, commits, and allocator seeds.
interface IdentityPort| Member | Type | Summary |
|---|---|---|
| newId | |
ImageDecodePortinterfaceSource ↗
The injected image decoder.
A port rather than a direct Image/createImageBitmap call, so a worker or server runtime supplies its own and the engine never reaches for a browser global.
interface ImageDecodePort| Member | Type | Summary |
|---|---|---|
| convertPreserved | | Optional conversion of media an `<img>` cannot render (EMF/WMF metafiles, TIFF) into a renderable raster. The returned bytes are untrusted and re-enter the full raster validation path (sniff, header, pixel caps, decode) before they can become a ready resource. A null return declines the format and keeps the labelled placeholder; so does a throw, as `decode-failed`. |
| decode | |
ImagePortinterfaceSource ↗
How image bytes are decoded. Opaque marker until its milestone.
interface ImagePort| Member | Type | Summary |
|---|---|---|
| kind | 'image' |
ImageResourceLimitsinterfaceSource ↗
Trust-boundary caps specific to image decoding and embedding.
interface ImageResourceLimits| Member | Type | Summary |
|---|---|---|
| maxDecodedBytes | number | |
| maxDimension | number | |
| maxEncodedBytes | number | |
| maxExternalRedirects | number | |
| maxPixels | number | |
| maxPolygonPoints | number |
ImageResourceLookupinterfaceSource ↗
Resolves a relationship id to a validated image resource, or reports why it could not.
interface ImageResourceLookup| Member | Type | Summary |
|---|---|---|
| dispose | () => void | |
| liveReferenceCount | (partName: string) => number | |
| resolveEmbedded | (ownerPartName: string, relationshipId: string) => Promise<ImageResourceState> | |
| resolveForProjection | (projection: DrawingProjection) => Promise<ImageResourceState> | |
| resolveLinked | (ownerPartName: string, relationshipId: string) => ImageResourceState |
InlineControlSpaninterfaceSource ↗
One inline content control's identity and the UTF-16 span its content covers.
interface InlineControlSpan| Member | Type | Summary |
|---|---|---|
| controlId | string | |
| end | number | |
| start | number |
InsertCustomNodeWriteinterfaceSource ↗
Where the control goes, what it says, and the payload it carries.
interface InsertCustomNodeWrite| Member | Type | Summary |
|---|---|---|
| alias? | string | |
| lock? | 'sdtLocked' | 'sdtContentLocked' | 'contentLocked' | Defaults to none. Callers that want Word's own "cannot type into it" pass `contentLocked`. |
| offset | number | |
| paragraphId | string | |
| payload? | CustomNodePayloadWrite | Omitted authors an ordinary tagged control with no store — the pre-payload behaviour. |
| replaceControlId? | string | Rewrite an existing control: it and the payload it bound go first, in this transaction. |
| replaceUntil? | number | Wrap rather than insert: the text from `offset` to here is removed first. |
| tag | string | |
| text | string |
LimitSpecinterfaceSource ↗
One limit's unit and enforcement phase — the metadata that makes limits testable uniformly.
interface LimitSpec| Member | Type | Summary |
|---|---|---|
| phase | EnforcementPhase | |
| unit | LimitUnit |
LinkableReviewIteminterfaceSource ↗
The shape [linkRevisionReplies](linkRevisionReplies) needs, stated STRUCTURALLY.
The store's queue is revisions and comments; the layout lane's adds a third kind for custom nodes, and neither union is assignable to the other. Both lanes have to run this pass — the store on the full derivation, the session on the locally patched list — so the pass is written against the fields it actually reads rather than against either union, and hands back the caller's own item type.
interface LinkableReviewItem| Member | Type | Summary |
|---|---|---|
| id | string | |
| kind | string | |
| orphaned? | boolean | |
| parentId? | string | |
| parentRevisionId? | string | |
| range? | ReviewRange | null | |
| ranges? | readonly ReviewRange[] | |
| replyIds? | readonly string[] |
ModelChangeSummaryinterfaceSource ↗
The change one step produced, summarized to what a fixture can compare across runtimes.
interface ModelChangeSummary| Member | Type | Summary |
|---|---|---|
| dependencyKeys | readonly string[] | |
| dirty | readonly string[] | |
| fromRevision | number | |
| origin | string | |
| toRevision | number |
NoteLifecycleOptionsinterfaceSource ↗
Attribution and limits applied to one note lifecycle op.
interface NoteLifecycleOptions| Member | Type | Summary |
|---|---|---|
| scanBudget? | NoteReferenceScanBudget | Shared part + visited-node budget for reference scans. When omitted a fresh default budget is used. Truncation rejects the op with the original package unchanged. |
NoteReferenceHitinterfaceSource ↗
One note reference found in a story, with where it sits.
interface NoteReferenceHit| Member | Type | Summary |
|---|---|---|
| atomOffset | number | Canonical UTF-16 atom offset within [paragraphId](paragraphId) (U+FFFC model). |
| customMarkFollows | boolean | |
| nodeId | string | |
| noteId | number | |
| noteKind | NoteKind | |
| paragraphId | string | |
| partName | string | Canonical part name that owns this reference. |
NoteReferenceScanBudgetinterfaceSource ↗
Mutable visited-node + part budget shared across parts / package snapshots.
interface NoteReferenceScanBudget| Member | Type | Summary |
|---|---|---|
| maxParts | number | |
| maxVisited | number | |
| parts | number | |
| truncated | boolean | Set when a walk stops before finishing because a cap was hit. |
| visited | number |
OffsetSpaninterfaceSource ↗
Half-open [start, end) of one node in its paragraph's model offset space.
interface OffsetSpan| Member | Type | Summary |
|---|---|---|
| end | number | |
| start | number |
OoxmlBodyNodeinterfaceSource ↗
w:body — the main story's block content.
interface OoxmlBodyNode extends OoxmlElementBase<readonly (OoxmlParagraphNode | OoxmlTableNode | OoxmlContentControlNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'body' | |
| localName | 'body' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlBookmarkEndNodeinterfaceSource ↗
w:bookmarkEnd — the closing point anchor (@w:id), zero-length like its start.
interface OoxmlBookmarkEndNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'bookmarkEnd' | |
| localName | 'bookmarkEnd' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlBookmarkStartNodeinterfaceSource ↗
w:bookmarkStart — a ZERO-LENGTH point anchor (@w:id, @w:name).
It takes no text offset and paints nothing; it only marks a position, which is what an internal hyperlink's w:anchor names. Split and join place it by that position, the behaviour tree-op-split-anchors.test.ts pins.
interface OoxmlBookmarkStartNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'bookmarkStart' | |
| localName | 'bookmarkStart' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlCalendarNodeinterfaceSource ↗
w:calendar — which calendar system a date picker uses (Gregorian, Hijri, …).
interface OoxmlContentControlCalendarNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlCalendar' | |
| localName | 'calendar' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlCheckboxNodeinterfaceSource ↗
w14:checkbox — Microsoft extension, not an ECMA-376 type choice. Distinguishable from untyped rich-text controls that merely wrap a w:sym.
interface OoxmlContentControlCheckboxNode extends OoxmlElementBase<readonly (OoxmlContentControlCheckedNode | OoxmlContentControlCheckedStateNode | OoxmlContentControlUncheckedStateNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlCheckbox' | |
| localName | 'checkbox' | |
| namespaceUri | typeof W14_NAMESPACE_URI |
OoxmlContentControlCheckedNodeinterfaceSource ↗
w14:checked — a checkbox's recorded state, independent of the glyph drawn for it.
interface OoxmlContentControlCheckedNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlChecked' | |
| localName | 'checked' | |
| namespaceUri | typeof W14_NAMESPACE_URI |
OoxmlContentControlCheckedStateNodeinterfaceSource ↗
w14:checkedState — the font and code point drawn when a checkbox is checked.
interface OoxmlContentControlCheckedStateNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlCheckedState' | |
| localName | 'checkedState' | |
| namespaceUri | typeof W14_NAMESPACE_URI |
OoxmlContentControlComboBoxNodeinterfaceSource ↗
w:comboBox — same payload shape as dropdown; free entry is an editing concern.
interface OoxmlContentControlComboBoxNode extends OoxmlElementBase<readonly (OoxmlContentControlListItemNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlComboBox' | |
| localName | 'comboBox' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlContentNodeinterfaceSource ↗
w:sdtContent — control contents for every placement. Block content is paragraphs/tables; inline content is runs/hyperlinks; row/cell content is rows/cells. Nested controls stay typed.
interface OoxmlContentControlContentNode extends OoxmlElementBase<readonly OoxmlNode[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlContent' | |
| localName | 'sdtContent' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlDataBindingNodeinterfaceSource ↗
w:dataBinding — xpath / storeItemID / prefixMappings preserved as attributes. This tree never resolves or fetches the binding target.
interface OoxmlContentControlDataBindingNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlDataBinding' | |
| localName | 'dataBinding' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlDateFormatNodeinterfaceSource ↗
w:dateFormat — the picture string a date picker formats its value with.
interface OoxmlContentControlDateFormatNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlDateFormat' | |
| localName | 'dateFormat' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlDateNodeinterfaceSource ↗
w:date — @w:fullDate plus typed dateFormat/lid/storeMappedDataAs/calendar leaves. Those leaves allow w:val (the only known kinds that do) so they are not demoted.
interface OoxmlContentControlDateNode extends OoxmlElementBase<readonly (OoxmlContentControlDateFormatNode | OoxmlContentControlLidNode | OoxmlContentControlStoreMappedDataAsNode | OoxmlContentControlCalendarNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlDate' | |
| localName | 'date' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlDropDownListNodeinterfaceSource ↗
w:dropDownList — @w:lastValue plus typed w:listItem children.
interface OoxmlContentControlDropDownListNode extends OoxmlElementBase<readonly (OoxmlContentControlListItemNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlDropDownList' | |
| localName | 'dropDownList' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlEndPropertiesNodeinterfaceSource ↗
w:sdtEndPr — end-character properties; children are w:rPr or generic.
interface OoxmlContentControlEndPropertiesNode extends OoxmlElementBase<readonly (OoxmlRunPropertiesNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlEndProperties' | |
| localName | 'sdtEndPr' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlLidNodeinterfaceSource ↗
w:lid — the language id a date picker parses and formats under.
interface OoxmlContentControlLidNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlLid' | |
| localName | 'lid' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlListItemNodeinterfaceSource ↗
w:listItem — @w:displayText / @w:value as preserved attributes (not w:val).
interface OoxmlContentControlListItemNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlListItem' | |
| localName | 'listItem' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlNodeinterfaceSource ↗
w:sdt — structured document tag (content control) at block, inline, row, or cell level.
Placement is not a separate kind: the same element name appears in every EG_*Content group. Child shape is the union of those placements; parents admit the control wherever generic was previously accepted (see isPreservedChild). Identity is the node id — w:id inside w:sdtPr is optional, preserved when present, never fabricated here.
interface OoxmlContentControlNode extends OoxmlElementBase<readonly (OoxmlContentControlPropertiesNode | OoxmlContentControlEndPropertiesNode | OoxmlContentControlContentNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControl' | |
| localName | 'sdt' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlPropertiesNodeinterfaceSource ↗
w:sdtPr (CT_SdtPr) — schema-ordered properties. Unmodelled children (alias/tag/id/lock leaves with w:val, w15:*, empty type markers) stay generic in position. Typed payloads: dropdown/combo/listItem, date (+ leaves), text, dataBinding, w14:checkbox.
interface OoxmlContentControlPropertiesNode extends OoxmlElementBase<readonly (OoxmlRunPropertiesNode | OoxmlContentControlDataBindingNode | OoxmlContentControlDropDownListNode | OoxmlContentControlComboBoxNode | OoxmlContentControlDateNode | OoxmlContentControlTextNode | OoxmlContentControlCheckboxNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlProperties' | |
| localName | 'sdtPr' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlStoreMappedDataAsNodeinterfaceSource ↗
w:storeMappedDataAs — which representation a bound date is written to its XML part as.
interface OoxmlContentControlStoreMappedDataAsNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlStoreMappedDataAs' | |
| localName | 'storeMappedDataAs' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlTextNodeinterfaceSource ↗
w:text (CT_SdtText) — distinct from w:t (kind: 'text'). @w:multiLine preserved.
interface OoxmlContentControlTextNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlText' | |
| localName | 'text' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlContentControlUncheckedStateNodeinterfaceSource ↗
w14:uncheckedState — the font and code point drawn when a checkbox is not checked.
interface OoxmlContentControlUncheckedStateNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'contentControlUncheckedState' | |
| localName | 'uncheckedState' | |
| namespaceUri | typeof W14_NAMESPACE_URI |
OoxmlContinuationSeparatorNodeinterfaceSource ↗
Run-inner continuation separator (w:continuationSeparator). One UTF-16 atom.
interface OoxmlContinuationSeparatorNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'continuationSeparator' | |
| localName | 'continuationSeparator' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlDocumentNodeinterfaceSource ↗
w:document — the root of a main document part.
interface OoxmlDocumentNode extends OoxmlElementBase<readonly (OoxmlBodyNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'document' | |
| localName | 'document' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlEndnotesNodeinterfaceSource ↗
Endnotes part root (w:endnotes). Same content model as [OoxmlFootnotesNode](OoxmlFootnotesNode).
interface OoxmlEndnotesNode extends OoxmlElementBase<readonly (OoxmlNoteNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'endnotes' | |
| localName | 'endnotes' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlExternalTargetinterfaceSource ↗
An external relationship target. Retained verbatim as authored evidence, with the sink-safety verdict alongside it. Never resolved against the package, never fetched.
interface OoxmlExternalTarget| Member | Type | Summary |
|---|---|---|
| id | string | |
| ownerPart | string | |
| rawTarget | string | |
| sinkSafe | boolean | False when the target is not a safe sink (javascript:, file:, ...). Still not fetched. |
| type | string |
OoxmlFldCharNodeinterfaceSource ↗
Complex-field character (w:fldChar).
Children stay generic so w:ffData (legacy form fields / macros) round-trips as inert payload and is never promoted to an executable surface. @w:fldCharType, @w:dirty, and @w:fldLock are preserved on attributes.
interface OoxmlFldCharNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'fldChar' | |
| localName | 'fldChar' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlFldSimpleNodeinterfaceSource ↗
Simple field (w:fldSimple) at paragraph content level.
@w:instr, @w:dirty, and @w:fldLock round-trip on attributes. Cached result children stay structurally preserved; the field is one atomic addressable unit.
interface OoxmlFldSimpleNode extends OoxmlElementBase<readonly (OoxmlRunNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'fldSimple' | |
| localName | 'fldSimple' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlFootnotesNodeinterfaceSource ↗
Footnotes part root (w:footnotes). Children are typed notes or preserved generics. Never a story root itself — each note body is its own story for layout.
interface OoxmlFootnotesNode extends OoxmlElementBase<readonly (OoxmlNoteNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'footnotes' | |
| localName | 'footnotes' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlGenericElementNodeinterfaceSource ↗
Any element the typed vocabulary does not cover — the other half of the preservation model.
Also where a KNOWN element lands when it appears somewhere invalid: an element is demoted to generic rather than rejected, so malformed or unfamiliar content is carried losslessly and never locks editing.
interface OoxmlGenericElementNode extends OoxmlElementBase<readonly OoxmlNode[]>| Member | Type | Summary |
|---|---|---|
| kind | 'generic' |
OoxmlGenericExtensionAttributeinterfaceSource ↗
Any attribute outside the typed vocabulary, carried verbatim.
Where losslessness actually happens: an attribute this engine has no model for is preserved exactly rather than dropped, so a save re-emits what the file said.
interface OoxmlGenericExtensionAttribute extends OoxmlAttributeBase| Member | Type | Summary |
|---|---|---|
| kind | 'genericExtension' |
OoxmlHardBreakNodeinterfaceSource ↗
w:br — a line, column or page break inside a run.
interface OoxmlHardBreakNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'hardBreak' | |
| localName | 'br' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlHyperlinkNodeinterfaceSource ↗
CT_Hyperlink (ECMA-376 §17.16.22) — a RUN CONTAINER, not a leaf.
Its runs are part of the paragraph's inline sequence: they measure, paint, select and take offsets exactly like a run written directly under the w:p. Typing the element is what lets them in; while it was generic, its runs never reached the token stream and the words inside every link simply did not paint.
Targets live in the ATTRIBUTES, and §17.16.22 declares exactly six. They divide into two groups, and the difference is load-bearing:
MODELED r:id (a relationship, resolved against the owning part's rels), w:anchor (a bookmark name in this document) and w:tooltip. These are the three the ops read and write — setHyperlinkTarget sets one target attribute and CLEARS the other, so a link never carries both and resolves by the wrong one.
PRESERVED w:tgtFrame, w:docLocation and w:history. Nothing in this engine interprets them and no op names them; they survive because attributes are carried verbatim, and setHyperlinkTarget must leave them exactly as authored. That is a REQUIREMENT, not an incidental property of the current applier: w:docLocation names a location inside the target document, so silently dropping it on a retarget would change where a link goes. hyperlink-lossless-editing.test.ts pins both against a retarget.
Nothing here is a runtime URL — the sanitized projection is computed separately (see hyperlinkTargetOf), and only that reaches a DOM or navigation sink.
Bookmark markers are admitted as children because Word writes them inside links; anything else it can carry (a drawing, a field, a nested SDT) stays generic at its position, so a link around a picture keeps both the picture and the link.
A link may contain ANOTHER link: §17.16.22's content model is EG_PContent, which lists w:hyperlink among its own members. That is why this child union is self-referential rather than bottoming out at runs. Demoting the inner one to generic would have been the easier type, and it would have reintroduced exactly the bug typing this element fixed — a generic link's runs never reach the token stream, so the words inside it stop painting. Every walk that descends a link therefore recurses (segmentsOf, runsUnder, runPropertyEdits) instead of descending one level.
interface OoxmlHyperlinkNode extends OoxmlElementBase<readonly (OoxmlRunNode | OoxmlHyperlinkNode | OoxmlContentControlNode | OoxmlBookmarkStartNode | OoxmlBookmarkEndNode | OoxmlRevisionContentNode | OoxmlRangeMarkerNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'hyperlink' | |
| localName | 'hyperlink' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlIndexesinterfaceSource ↗
The derived lookups over a part: paragraphs, stories and styles by id.
Diff-patched on commit rather than rebuilt — rebuilding every index per keystroke is what made typing scale with document length.
interface OoxmlIndexes| Member | Type | Summary |
|---|---|---|
| paragraphs | ReadonlyMap<string, ParagraphIndexEntry> | Every paragraph across every story, keyed by node id. |
| relationships | ReadonlyMap<string, readonly RelationshipRecord[]> | |
| revision | number | The tree revision these projections were derived from. |
| stories | ReadonlyMap<string, StoryIndexEntry> | Body story first, then any other story parts, keyed by part name. |
| styles | ReadonlyMap<string, StyleIndexEntry> |
OoxmlInstrTextNodeinterfaceSource ↗
Field instruction text (w:instrText), same text-carrier shape as w:t.
Instruction strings are never executed; layout may recognize allowlisted page-number keywords only.
interface OoxmlInstrTextNode extends OoxmlElementBase<readonly OoxmlTextNode[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'instrText' | |
| localName | 'instrText' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlInvariantIssueinterfaceSource ↗
One invariant violation, located by structural path and node id.
interface OoxmlInvariantIssue| Member | Type | Summary |
|---|---|---|
| code | OoxmlInvariantIssueCode | |
| nodeId? | string | |
| path | string |
OoxmlNamespaceBindinginterfaceSource ↗
One xmlns: declaration carried on a node.
Preserved rather than normalized away: a document that binds w14 at the root and a document that binds it on a paragraph are different bytes, and re-emitting the wrong one is a fidelity loss even though the semantics match.
interface OoxmlNamespaceBinding| Member | Type | Summary |
|---|---|---|
| namespaceUri | string | |
| prefix | string |
OoxmlNodeIdentityRulesinterfaceSource ↗
The node-identity contract, written down as a type so it is checkable rather than merely documented.
Ids are deterministic from a normalized parse, retained through structural sharing, explicit on replacement, and unique within a part. Everything that addresses nodes — ops, the caret, the paraId bimap — depends on all four holding.
interface OoxmlNodeIdentityRules| Member | Type | Summary |
|---|---|---|
| initial | 'deterministic-structural-path-after-normalized-parse' | |
| replacement | 'explicitly-retain-or-allocate' | |
| unchanged | 'retain-id-through-structural-sharing' | |
| uniqueness | 'unique-within-part' |
OoxmlNoteNodeinterfaceSource ↗
One footnote or endnote (w:footnote / w:endnote).
Discriminated by localName. @w:id and optional @w:type (ST_FtnEdn, including authored normal) live on attributes. Children are ordinary block content.
interface OoxmlNoteNode extends OoxmlElementBase<readonly (OoxmlParagraphNode | OoxmlTableNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'note' | |
| localName | 'footnote' | 'endnote' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlNoteReferenceNodeinterfaceSource ↗
Body citation (w:footnoteReference / w:endnoteReference) as a typed run child. Display mark is derived — never stored as text. One UTF-16 atom in addressing.
interface OoxmlNoteReferenceNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'noteReference' | |
| localName | 'footnoteReference' | 'endnoteReference' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlNoteRefNodeinterfaceSource ↗
Auto mark inside a note body (w:footnoteRef / w:endnoteRef). One UTF-16 atom; display digit is derived at paint time.
interface OoxmlNoteRefNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'noteRef' | |
| localName | 'footnoteRef' | 'endnoteRef' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlPackageinterfaceSource ↗
A loaded package: every XML part as a canonical tree, plus the non-XML parts kept verbatim.
The preservation model in one value. Modelled parts re-emit normalized; everything else is byte-identical, which is why an unrecognized part never costs a document anything.
interface OoxmlPackage| Member | Type | Summary |
|---|---|---|
| contentTypes | ContentTypeIndex | |
| externalTargets | readonly OoxmlExternalTarget[] | |
| mainDocumentPart | string | Canonical name of the part the root `officeDocument` relationship points at. |
| partBytes | ReadonlyMap<string, Uint8Array> | Raw bytes of every entry, including the non-XML parts that have no tree. |
| parts | ReadonlyMap<string, OoxmlPart> | Canonical trees, keyed by canonical part name. Non-XML parts are absent by design. |
| relationships | ReadonlyMap<string, readonly RelationshipRecord[]> | Internal relationships by owner part, in authored order. |
OoxmlPackageLimitsinterfaceSource ↗
Caps applied while loading a package: zip, XML, part count and relationship count.
interface OoxmlPackageLimits| Member | Type | Summary |
|---|---|---|
| maxRelationships? | number | Cap on relationship records across every rels part. |
| maxXmlParts? | number | Cap on parts converted into canonical trees (N/N+1 gate, not a soft target). |
| xml? | XmlLimits | |
| zip? | ZipLimits |
OoxmlParagraphNodeinterfaceSource ↗
w:p — a paragraph, and the unit every offset in this engine is relative to.
Positions are addressed as this node's id plus a UTF-16 offset, which is what makes a paragraph inside a table cell no different from one at the top level.
interface OoxmlParagraphNode extends OoxmlElementBase<readonly (OoxmlParagraphPropertiesNode | OoxmlRunNode | OoxmlHyperlinkNode | OoxmlContentControlNode | OoxmlBookmarkStartNode | OoxmlBookmarkEndNode | OoxmlRevisionContentNode | OoxmlRangeMarkerNode | OoxmlFldSimpleNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'paragraph' | |
| localName | 'p' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlParagraphPropertiesNodeinterfaceSource ↗
w:pPr — a paragraph's properties. Children stay generic, like w:rPr's.
interface OoxmlParagraphPropertiesNode extends OoxmlElementBase<readonly (OoxmlRunPropertiesNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'paragraphProperties' | |
| localName | 'pPr' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlPartinterfaceSource ↗
One XML part of the package, parsed into a canonical tree.
interface OoxmlPart| Member | Type | Summary |
|---|---|---|
| contentType | string | |
| id | string | |
| name | string | Canonical part name, e.g. `/word/document.xml`. |
| root | OoxmlElement |
OoxmlPartMetadatainterfaceSource ↗
A part's identity without its tree — enough to enumerate a package cheaply.
interface OoxmlPartMetadata| Member | Type | Summary |
|---|---|---|
| contentType | string | |
| name | string |
OoxmlPropertyinterfaceSource ↗
One property an op writes, as a name plus attributes.
Deliberately structural rather than a typed union: the accepted property lists bound WHICH properties may be written, so the shape itself does not need to enumerate them.
interface OoxmlProperty| Member | Type | Summary |
|---|---|---|
| attributes? | Readonly<Record<string, string>> | |
| localName | string |
OoxmlRunNodeinterfaceSource ↗
w:r — a run: text and atoms sharing one set of character properties.
interface OoxmlRunNode extends OoxmlElementBase<readonly (OoxmlRunPropertiesNode | OoxmlTextElementNode | OoxmlDeletedTextNode | OoxmlTabNode | OoxmlHardBreakNode | OoxmlCommentReferenceNode | OoxmlFldCharNode | OoxmlInstrTextNode | OoxmlNoteReferenceNode | OoxmlNoteRefNode | OoxmlSeparatorNode | OoxmlContinuationSeparatorNode | OoxmlDrawingNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'run' | |
| localName | 'r' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlRunPropertiesNodeinterfaceSource ↗
w:rPr — a run's character properties, whose children stay GENERIC.
Deliberately unmodelled below this point: the property vocabulary is large and mostly uninteresting to layout, so carrying it verbatim preserves everything without the engine having to know what each element means.
interface OoxmlRunPropertiesNode extends OoxmlElementBase<readonly OoxmlGenericElementNode[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'runProperties' | |
| localName | 'rPr' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlSeparatorNodeinterfaceSource ↗
Run-inner separator rule (w:separator). One UTF-16 atom.
interface OoxmlSeparatorNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'separator' | |
| localName | 'separator' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlStoryRootinterfaceSource ↗
One story root and the blocks under it, with block-level SDTs already flattened.
interface OoxmlStoryRoot| Member | Type | Summary |
|---|---|---|
| kind | OoxmlStoryKind | |
| root | OoxmlNode | The `w:body` / `w:hdr` / `w:ftr` / `w:footnote` element that holds the blocks. |
OoxmlTabNodeinterfaceSource ↗
w:tab inside a run — one tab character as its own element.
interface OoxmlTabNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'tab' | |
| localName | 'tab' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlTextElementNodeinterfaceSource ↗
w:t — the element holding a run's literal characters.
interface OoxmlTextElementNode extends OoxmlElementBase<readonly OoxmlTextNode[], readonly OoxmlKnownNodeAttribute[]>| Member | Type | Summary |
|---|---|---|
| kind | 'text' | |
| localName | 't' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlTextNodeinterfaceSource ↗
A literal text value. The only node kind with no children and no attributes.
interface OoxmlTextNode| Member | Type | Summary |
|---|---|---|
| id | OoxmlNodeId | |
| kind | 'textValue' | |
| value | string |
OoxmlWmlValAttributeinterfaceSource ↗
w:val — the attribute nearly every WordprocessingML property carries its value in.
interface OoxmlWmlValAttribute extends OoxmlAttributeBase| Member | Type | Summary |
|---|---|---|
| kind | 'wmlVal' | |
| localName | 'val' | |
| namespaceUri | typeof WML_NAMESPACE_URI |
OoxmlXmlSpaceAttributeinterfaceSource ↗
xml:space, which decides whether a run's leading and trailing whitespace survives.
interface OoxmlXmlSpaceAttribute extends OoxmlAttributeBase| Member | Type | Summary |
|---|---|---|
| kind | 'xmlSpace' | |
| localName | 'space' | |
| namespaceUri | typeof XML_NAMESPACE_URI | |
| prefix | 'xml' | |
| value | 'default' | 'preserve' |
OperationContextinterfaceSource ↗
The frozen environment of one operation: its limits, config, ports, root budget and cancellation controller.
IMMUTABLE for the operation's lifetime, which is what lets cache reuse and replica agreement key on it. A new operation always gets a fresh snapshot rather than observing a mutated one.
interface OperationContext| Member | Type | Summary |
|---|---|---|
| budget | Budget | |
| cancellation | CancellationController | |
| config | Readonly<Record<string, unknown>> | |
| id | string | |
| limits | ResourceLimits | |
| ports | PortRegistry |
OperationInitinterfaceSource ↗
What one operation is started with. Only ports is required.
interface OperationInit| Member | Type | Summary |
|---|---|---|
| capacity? | number | Root budget capacity in abstract units (default: the byte decompression limit). |
| config? | Readonly<Record<string, unknown>> | |
| id? | string | Operation identity (from IdentityPort in production); defaulted for tests. |
| limits? | Partial<ResourceLimits> | |
| ports | PortRegistry |
OverrideRecordinterfaceSource ↗
One <Override>: a specific part name mapped to a content type. Beats any Default.
interface OverrideRecord| Member | Type | Summary |
|---|---|---|
| contentType | string | |
| order | number | |
| partName | string |
PackageInvariantIssueinterfaceSource ↗
One package invariant violation, located by part name and relationship id.
interface PackageInvariantIssue| Member | Type | Summary |
|---|---|---|
| code | PackageInvariantCode | |
| ownerPart? | string | For a dangling relationship, the owner that points at nothing. |
| partName | string | The part the issue is about: the missing target, or the part with no type. |
ParagraphDigestinterfaceSource ↗
One paragraph's meaning, independent of how it was spelled in XML.
interface ParagraphDigest| Member | Type | Summary |
|---|---|---|
| genericStructure | readonly string[] | Fingerprints of every generic (unknown) subtree, in document order. |
| ordinal | number | Ordinal identity within its story. Node ids are NOT used: a reopened package legitimately re-derives them, and requiring them to match would test the id scheme rather than the content. |
| paragraphProperties | readonly string[] | Accepted paragraph properties, as sorted tokens including nested children. |
| paraId | string | null | `w14:paraId`, uppercase-normalized (matching is case-insensitive), or null. This is MANAGED identity — the agent contract anchors on it and comment threading references it — so a serializer silently dropping it must be a digest difference. Other paragraph attributes (`w:rsidR` …) stay deliberately undigested: they are revision noise. |
| path | string | Where the paragraph SITS: the element path from the story root, so a paragraph that moves out of the table cell it was written in is a difference rather than a paragraph with the same ordinal and the same text. |
| runProperties | readonly (readonly string[])[] | Per-run accepted properties, in run order. |
| text | string | Text content, including tabs and hard breaks as their characters. |
ParagraphIndexEntryinterfaceSource ↗
One paragraph in the index: its node id, its story, and its position.
interface ParagraphIndexEntry| Member | Type | Summary |
|---|---|---|
| nodeId | string | Canonical tree node id — the stable identity operations address. |
| ordinal | number | Position among the story's paragraphs, in document order. |
| runIds | readonly string[] | Node ids of the paragraph's runs, in order. |
| text | string | Concatenated text content, with tabs and breaks mapped as the model reads them. |
ParagraphOffsetIndexinterfaceSource ↗
Every node's place in the paragraph's model offset space, from the SAME walk segmentsOf uses.
The offset model has exactly one authority, and this is how a caller borrows it. Three private walkers used to re-derive it — one in the tracked-change writer, one in the comment anchor reader, one in the review queue — and all three disagreed with segmentsOf and with each other: none gave a note reference or an atomic field its length of one, one counted a field's instruction text as visible characters, and one never descended into w:hyperlink at all. The consequences were an anchor short by a link's length, two unrelated comments threaded onto one zero-width offset, and a tracked insert landing a character out in any paragraph carrying a footnote. Patching each walker only resets the clock on the next drift.
A node the walk never reaches — content under a generic container, or past the nesting cap — has NO span, and [ParagraphOffsetIndex.lengthOf](ParagraphOffsetIndex.lengthOf) reports zero for it. That is the same answer segmentsOf gives: it contributes no addressable characters.
interface ParagraphOffsetIndex| Member | Type | Summary |
|---|---|---|
| length | number | The paragraph's own length, identical to [paragraphLength](paragraphLength). |
| lengthOf | | A node's model length: `end - start` of its span, and 0 when it has none. |
| segments | readonly Segment[] | |
| spanOf | | Where a node sits, or null when the offset walk never reached it. |
PersistencePortinterfaceSource ↗
Where documents are stored and retrieved. Opaque marker until its milestone.
interface PersistencePort| Member | Type | Summary |
|---|---|---|
| kind | 'persistence' |
ReadEmbeddedFontsOptionsinterfaceSource ↗
Limits and instrumentation for reading embedded fonts out of a package.
interface ReadEmbeddedFontsOptions| Member | Type | Summary |
|---|---|---|
| maxFontBytes? | number | Refuse a font part larger than this. Defaults to 16 MB. |
| maxFonts? | number | Refuse more than this many fonts. Defaults to 64. |
RelationshipRecordinterfaceSource ↗
One authored relationship, with nothing materialized away: owner part, id, type, raw target lexical form, mode, and position.
interface RelationshipRecord| Member | Type | Summary |
|---|---|---|
| id | string | |
| order | number | |
| ownerPart | string | |
| rawTarget | string | |
| targetMode | TargetMode | |
| type | string |
ReplayOutcomeinterfaceSource ↗
The outcome a store reports for one replayed step.
interface ReplayOutcome| Member | Type | Summary |
|---|---|---|
| authoredState? | unknown | Canonical authored-state value AFTER the step (hashed via comparator 0.4). |
| committedRevision? | number | |
| outcome | FixtureOutcome |
ReplayReportinterfaceSource ↗
What replaying a fixture produced: per-step outcomes and where they diverged.
interface ReplayReport| Member | Type | Summary |
|---|---|---|
| mismatches | readonly string[] | |
| ok | boolean |
ReplayStoreinterfaceSource ↗
The interface a conformance runtime implements so one fixture can drive every backend.
interface ReplayStore| Member | Type | Summary |
|---|---|---|
| applyStep | | Apply one step and report what happened. |
| init | | Initialize from the fixture source; return the initial revision (0 for create). |
ReservationinterfaceSource ↗
Capacity claimed BEFORE it is allocated.
Reserve-then-allocate rather than allocate-then-check: discovering the overrun after the allocation has already happened defeats the point of having a budget.
interface Reservation| Member | Type | Summary |
|---|---|---|
| amount | number | |
| release | | |
| released | boolean |
ResolvedEndnotePropertiesinterfaceSource ↗
Fully resolved endnote properties (defaults filled).
interface ResolvedEndnoteProperties| Member | Type | Summary |
|---|---|---|
| numFmt | string | |
| numRestart | NoteNumRestart | |
| numStart | number | |
| pos | EndnotePosition |
ResolvedFootnotePropertiesinterfaceSource ↗
Fully resolved footnote properties (defaults filled).
interface ResolvedFootnoteProperties| Member | Type | Summary |
|---|---|---|
| numFmt | string | |
| numRestart | NoteNumRestart | |
| numStart | number | |
| pos | FootnotePosition |
ResolvedRegistryinterfaceSource ↗
The resolved result: every contribution selected, indexed by (kind, id).
interface ResolvedRegistry| Member | Type | Summary |
|---|---|---|
| contributions | ReadonlyMap<string, Contribution> | |
| extensions | ReadonlyMap<string, FeatureBundle> | |
| get | |
ResolveOptionsinterfaceSource ↗
How resolution treats optional bundles and replacement policies.
interface ResolveOptions| Member | Type | Summary |
|---|---|---|
| availablePorts? | readonly string[] | Runtime port ids available in this environment (design D9 / task 0.3). |
ResourceAccountingPortinterfaceSource ↗
Where resource consumption is reported. Opaque marker until its milestone.
interface ResourceAccountingPort| Member | Type | Summary |
|---|---|---|
| kind | 'resource-accounting' |
ResourceLimitsinterfaceSource ↗
The engine's trust-boundary caps: recursion depth, element counts, and the rest.
A caller may LOWER any of these but never raise or disable one — an override of Infinity, zero, a negative or NaN clamps into (0, ceiling] rather than turning the limit off. These are security ceilings, not performance budgets.
interface ResourceLimits| Member | Type | Summary |
|---|---|---|
| maxChunkBytes | number | In-memory chunk budget for streaming/spooling. |
| maxCompressedBytes | number | Max total compressed input bytes. |
| maxCompressionRatio | number | Max decompressed:compressed ratio per entry. |
| maxDecompressedBytes | number | Max total decompressed bytes (zip-bomb guard). |
| maxElementCount | number | Max total parsed element count. |
| maxPaginationPasses | number | Max pagination passes before non-convergence is declared. |
| maxPartCount | number | Max package part count. |
| maxQueueDepth | number | Max queued items in any bounded work queue. |
| maxRecursionDepth | number | Max nested-structure recursion (tables/shapes/SDT/groups). |
ReviewCommentIteminterfaceSource ↗
One comment as the store derives it, with its thread links resolved.
interface ReviewCommentItem| Member | Type | Summary |
|---|---|---|
| comment | CommentRecord | |
| id | string | |
| kind | 'comment' | |
| orphaned | boolean | True when the file gave this comment no usable range. |
| parentId? | string | The comment this replies to, absent for a top-level comment. |
| parentRevisionId? | string | The REVISION this comment answers, when it covers exactly that change's characters. |
| range | ReviewRange | null | |
| replyIds | readonly string[] | Replies to this comment, in document order. Empty for a reply or a childless comment. |
| resolved | boolean |
ReviewModelInputinterfaceSource ↗
What review derivation reads: one story part plus its comment parts.
interface ReviewModelInput| Member | Type | Summary |
|---|---|---|
| commentsExtendedPart? | OoxmlPart | undefined | `word/commentsExtended.xml`, absent when the package has none. |
| commentsPart? | OoxmlPart | undefined | `word/comments.xml`, absent when the package has none. |
| furnitureParts? | readonly OoxmlPart[] | undefined | Header/footer story parts, in section order. Their revisions and comment anchors join the queue: a tracked change in a header is a pending decision like any other, and a queue that only walked the body silently hid it from the rail AND from Accept All. |
| storyPart | OoxmlPart | The story the ranges live in — the main document, a header, a note. |
ReviewPositioninterfaceSource ↗
A position in the model offset space of one story.
interface ReviewPosition| Member | Type | Summary |
|---|---|---|
| offset | number | |
| paragraphId | string |
ReviewRangeinterfaceSource ↗
Where an item is anchored: a range in one story.
interface ReviewRange| Member | Type | Summary |
|---|---|---|
| end | ReviewPosition | |
| partName | string | |
| start | ReviewPosition |
ReviewRevisionIteminterfaceSource ↗
One tracked change as the store derives it, keyed per decision rather than per site.
interface ReviewRevisionItem| Member | Type | Summary |
|---|---|---|
| address | RevisionAddress | The payload `acceptRevision` / `rejectRevision` take. |
| addresses | readonly RevisionAddress[] | EVERY address this decision covers, `address` first. |
| author | string | |
| date? | string | |
| id | string | Stable across renders and unique per DECISION, not per site. |
| kind | 'revision' | |
| pairedWith? | string | The other half of a move, or the other side of a delete/insert replacement. |
| ranges | readonly ReviewRange[] | Every site this decision touches, in document order. |
| readOnly | boolean | True when the engine cannot resolve this kind, so accept and reject must not be offered. |
| replacedRangeCount? | number | How many leading `ranges` are the STRUCK half of a replacement. |
| replacedText | string | The words a replacement removes. Empty for every other kind. |
| replyIds | readonly string[] | Comments answering this change, in document order. |
| revisionKind | ReviewRevisionKind | |
| text | string | Text the revision covers, for the card summary. Empty for changes with no characters. |
RevisionAddressinterfaceSource ↗
How a tracked change is addressed: its numeric id plus the PART it lives in.
Both, always — @w:id is unique only within a part, so an id alone names two revisions in any package with a header or a comments part.
interface RevisionAddress| Member | Type | Summary |
|---|---|---|
| author | string | |
| date? | string | Absent when the file wrote no `@w:date`; part of the identity either way. |
| id | string |
RunPropertyEditinterfaceSource ↗
One run's share of a range edit: the slice it covers and the properties to write there.
interface RunPropertyEdit| Member | Type | Summary |
|---|---|---|
| end | number | |
| properties | readonly OoxmlProperty[] | |
| start | number | |
| targetRunIds? | readonly string[] | When set, `setRunProperties` formats only these runs (field result ownership). Needed when several result runs share one atom offset so each keeps its own merged bag. |
SchedulingPortinterfaceSource ↗
Cooperative scheduling of deferred work.
interface SchedulingPort| Member | Type | Summary |
|---|---|---|
| schedule | |
ScrubResultinterfaceSource ↗
What an explicit scrub removed.
A scrub DECLARES ITSELF non-lossless: removing executable content changes the file, which is a choice a caller makes deliberately rather than a default the engine applies.
interface ScrubResult| Member | Type | Summary |
|---|---|---|
| kept | readonly ContentItem[] | |
| nonLossless | boolean | A scrub that removes anything is non-lossless by definition. |
| removed | readonly ContentItem[] |
SegmentinterfaceSource ↗
One addressable unit of paragraph text: text, tab, hard break, or atomic field.
interface Segment| Member | Type | Summary |
|---|---|---|
| end | number | |
| formatRunIds? | readonly string[] | When set, run formatting for this atom targets these runs (field result ownership), not necessarily `runId`. Absent for ordinary text/tab/break segments. |
| node | OoxmlNode | |
| removeNodeIds? | readonly string[] | When set, deleting this segment removes every listed node id in one step (atomic field begin→end or `fldSimple`). Absent for ordinary text/tab/break segments. |
| runId | string | |
| start | number |
SelectionMarkinterfaceSource ↗
A selection captured with a transaction, so undo restores where the caret was.
interface SelectionMark| Member | Type | Summary |
|---|---|---|
| end | number | |
| paragraphId | string | |
| start | number |
SemanticDigestinterfaceSource ↗
The whole document's semantic content — one of the D9 losslessness oracles.
What a save/reopen round-trip is compared on. Byte identity applies only to non-XML parts; modelled parts re-emit normalized, so equality is asserted HERE rather than on bytes.
interface SemanticDigest| Member | Type | Summary |
|---|---|---|
| stories | readonly StoryDigest[] |
SemVerinterfaceSource ↗
A parsed semantic version. Only the three numeric components — no pre-release or build.
interface SemVer| Member | Type | Summary |
|---|---|---|
| major | number | |
| minor | number | |
| patch | number |
ShapingPortinterfaceSource ↗
Which shaping backend measures text. Opaque marker until its milestone.
interface ShapingPort| Member | Type | Summary |
|---|---|---|
| kind | 'shaping' |
SourceCropinterfaceSource ↗
a:srcRect — how much of each edge of the source image is cropped away, as fractions.
interface SourceCrop| Member | Type | Summary |
|---|---|---|
| bottom | number | |
| left | number | |
| right | number | |
| top | number |
StoryDigestinterfaceSource ↗
One story reduced to its semantic content, ignoring everything a normalized re-emit changes.
interface StoryDigest| Member | Type | Summary |
|---|---|---|
| paragraphs | readonly ParagraphDigest[] | |
| partName | string | |
| structure | readonly string[] | Every block-level element of the part OUTSIDE a paragraph, in document order, as `path name(attributes)` — the tables, rows, cells, sections, content controls and their property children, each at the position that says what contains it. |
StoryIndexEntryinterfaceSource ↗
One story root — body, a header/footer variant, or a note part.
interface StoryIndexEntry| Member | Type | Summary |
|---|---|---|
| paragraphs | readonly ParagraphIndexEntry[] | |
| partName | string | The part the story lives in. |
| rootId | string | The `w:body` (or story root) node id. |
StyleIndexEntryinterfaceSource ↗
One style definition, indexed by the id content references it under.
interface StyleIndexEntry| Member | Type | Summary |
|---|---|---|
| basedOn | string | null | |
| isDefault | boolean | Whether the part marks this the default style for its type (`w:default="1"`). |
| name | string | null | |
| nodeId | string | |
| styleId | string | |
| type | string |
TextMatchOptionsinterfaceSource ↗
How a text search is narrowed. Options the engine cannot honour are refused, never ignored.
interface TextMatchOptions| Member | Type | Summary |
|---|---|---|
| from? | number | Report only matches lying wholly inside `[from, to)`. |
| matchCase? | boolean | |
| to? | number | |
| wholeWord? | boolean |
TextOccurrenceinterfaceSource ↗
One occurrence, as UTF-16 offsets into the text that was scanned.
interface TextOccurrence| Member | Type | Summary |
|---|---|---|
| length | number | |
| start | number |
TextOccurrencesinterfaceSource ↗
Where a phrase occurs in a story, as paragraph-plus-offset ranges.
interface TextOccurrences| Member | Type | Summary |
|---|---|---|
| matches | readonly TextOccurrence[] | |
| truncated | boolean | The scan stopped at `limit` with occurrences still ahead of it. |
TocEntryPlaninterfaceSource ↗
One planned TOC entry: its level, its text, and the heading it points at.
interface TocEntryPlan| Member | Type | Summary |
|---|---|---|
| bookmarkName | string | |
| headingParagraphId | string | |
| level | number | |
| pageNumberText | string | |
| text | string |
TocInstructioninterfaceSource ↗
Parsed TOC instruction. Unknown switches are ignored for generation but left on the wire.
interface TocInstruction| Member | Type | Summary |
|---|---|---|
| hyperlink | boolean | Include hyperlinks (`\\h`). |
| keyword | 'TOC' | |
| omitPageNumbers | boolean | Omit page numbers (`\\n`). |
| outlineEnd | number | |
| outlineStart | number | Inclusive 1-based outline levels from `\\o "n-m"`. Defaults 1–9. |
| raw | string |
TocOutlineHeadinginterfaceSource ↗
Outline heading shape consumed by TOC planning (mirrors DocumentOutlineEntry).
interface TocOutlineHeading| Member | Type | Summary |
|---|---|---|
| blockId | string | |
| level | number | |
| text | string |
TransportPortinterfaceSource ↗
How the engine talks to a remote peer. Opaque marker until its milestone.
interface TransportPort| Member | Type | Summary |
|---|---|---|
| kind | 'transport' |
TreeDocumentStoreOptionsinterfaceSource ↗
How a store is constructed: its limits, its history depth, and its identity source.
interface TreeDocumentStoreOptions| Member | Type | Summary |
|---|---|---|
| historyLimit? | number | Bound on retained history entries. Oldest entries drop first. |
TreeModelChangeinterfaceSource ↗
What one committed transaction changed: the revision, the ids touched, and the impact class.
The ids are what let layout and paint re-do only the affected blocks instead of the document.
interface TreeModelChange| Member | Type | Summary |
|---|---|---|
| caret? | SelectionMark | Committed collapsed caret for this transaction, when one exists. Matches history `selectionAfter` when that mark is collapsed; absent for explicit null, non-collapsed explicit selection, or when no caret was committed. |
| change | 'model-change' | |
| commitId | string | |
| created | readonly string[] | |
| deleted | readonly string[] | |
| dependencyKeys | readonly string[] | |
| dirty | readonly string[] | |
| fromRevision | number | |
| impact | ImpactClass | The widest impact among the transaction's ops — what layout must scope to. |
| origin | string | |
| splitJoin | readonly ({
readonly split: {
readonly from: string;
readonly tail: string;
};
} | {
readonly join: {
readonly kept: string;
readonly removed: string;
};
})[] | |
| story? | TreeStoryRef | Story that published this change. Absent on body-only store publishes that predate package-aware targeting; `TreePackageStore` always sets it. |
| toRevision | number |
TreeOpEffectinterfaceSource ↗
What one applied op changed: the ids dirtied, created and deleted.
These ids are what let layout and paint re-do only what moved instead of the whole document.
interface TreeOpEffect| Member | Type | Summary |
|---|---|---|
| caret? | {
readonly paragraphId: string;
} | First post-edit caret paragraph for table column structural ops. |
| created | readonly string[] | |
| deleted | readonly string[] | |
| dependencyKeys | readonly string[] | |
| dirty | readonly string[] | |
| impact | ImpactClass | |
| join? | {
readonly kept: string;
readonly removed: string;
} | |
| split? | {
readonly from: string;
readonly tail: string;
} | |
| splits? | readonly {
readonly from: string;
readonly tail: string;
}[] | One entry per boundary of a many-way split, in document order. |
TreePackageStoreOptionsinterfaceSource ↗
How a package store is constructed: limits, history depth, and review contributions.
interface TreePackageStoreOptions| Member | Type | Summary |
|---|---|---|
| cascadeDeletedNoteReferences? | NoteCascadeFn | Test seam for note-reference cascade after `deleteText` / `deleteBlock`. Production uses [cascadeDeletedNoteReferences](cascadeDeletedNoteReferences). |
| historyLimit? | number | |
| maxEditableStoryParts? | number | Bound on opened story stores; defaults to [DEFAULT_MAX_EDITABLE_STORY_PARTS](DEFAULT_MAX_EDITABLE_STORY_PARTS). |
TreeTransactionContextinterface
What a transaction body is handed: the working tree, and the means to stage ops against it.
interface TransactionContext| Member | Type | Summary |
|---|---|---|
| apply | | Stage one op against the STORY part. Returns false once the transaction has failed. |
| applyPackage | | Stage a whole-package edit: a new part, a relationship, a content-type override. |
| applyTo | | Stage one op against a named part. |
| selectionAfter | | The selection to restore when this entry is redone. |
| selectionBefore | | The selection to restore when this entry is undone. |
TreeTransactOptionsinterface
How one transaction behaves: its story scope, its attribution, and its selection marks.
interface TransactOptions| Member | Type | Summary |
|---|---|---|
| minimumImpact? | ImpactClass | Floor on the published impact. Header/footer story edits use `global` so every page sharing the part invalidates rather than keeping stale furniture. |
| origin? | string | |
| scope? | 'transaction' | 'command' | A COMMAND is one user intent that may need several ops (a toolbar click applying a property across a multi-run selection). It is still exactly one history entry, which is the same rule a plain transaction follows — the option exists to say so explicitly at the call site rather than leaving it implied. |
| story? | TreeStoryRef | Story identity stamped onto the published ModelChange (package-aware targeting). |
ValidatedRasterHeaderinterfaceSource ↗
A raster header that passed structural validation: its real MIME type and pixel extent.
interface ValidatedRasterHeader| Member | Type | Summary |
|---|---|---|
| pixelHeight | number | |
| pixelWidth | number |
ValidationResultinterfaceSource ↗
Whether a fixture is well-formed, listing every structural violation.
interface ValidationResult| Member | Type | Summary |
|---|---|---|
| errors | readonly string[] | |
| valid | boolean |
XmlLimitsinterfaceSource ↗
Per-part caps on size, element count and depth. Clamped into the hard ceilings.
interface XmlLimits| Member | Type | Summary |
|---|---|---|
| maxBytes | number | |
| maxElements? | number |
ZipLimitsinterfaceSource ↗
Archive caps: entry count, total decompressed bytes, and the decompression ratio.
interface ZipLimits| Member | Type | Summary |
|---|---|---|
| maxEntries | number | |
| maxRatio? | number | Max per-entry uncompressed:compressed ratio (zip-bomb guard). |
| maxTotalBytes | number | Max total UNCOMPRESSED bytes across the archive. |
Type aliases (100)
AddCommentResulttypeSource ↗
The new comment's id and the story change, or the reason the write was refused.
type AddCommentResult = {
readonly ok: true;
readonly commentId: string;
readonly change: TreeModelChange | null;
} | {
readonly ok: false;
readonly reason: TreeOpRejection | 'invalid-author';
};BookmarkIndextypeSource ↗
Bookmarks by name. A name the document declares twice resolves to the first in order.
type BookmarkIndex = ReadonlyMap<string, BookmarkAnchor>;CancellationPhasetypeSource ↗
Which side of the point of no return an operation is on.
Canonical publication is that point. Cancelling BEFORE it rolls the whole operation back; cancelling after it leaves the commit standing and cancels only derived work — layout, export, caches.
type CancellationPhase = 'pre-publication' | 'post-publication';ComparatorModetypeSource ↗
How one artifact class is compared.
Frozen per artifact: nothing here invents a tolerance for an artifact the spec requires to match exactly.
type ComparatorMode = 'canonical-exact' | 'exact' | 'tolerance' | 'sync-optimization-only';ComparatorNametypeSource ↗
Which frozen comparator to use.
type ComparatorName = keyof typeof COMPARATORS;ContentControlKindtypeSource ↗
Which kind of control a w:sdt is, and therefore what a written value must look like.
type ContentControlKind = 'richText' | 'plainText' | 'checkbox' | 'dropDownList' | 'comboBox' | 'date' | 'picture' | 'docPartObj' | 'docPartList' | 'group' | 'citation' | 'bibliography' | 'equation' | 'untyped';ContentControlLeveltypeSource ↗
Where a control sits, read off what its content holds.
type ContentControlLevel = 'block' | 'inline' | 'row' | 'cell' | 'empty';ContentControlLocktypeSource ↗
w:lock — what a control refuses.
sdtLocked protects the wrapper, contentLocked the text inside it, and sdtContentLocked both. A control inside a locked one is locked in effect regardless of its own value.
type ContentControlLock = 'unlocked' | 'sdtLocked' | 'contentLocked' | 'sdtContentLocked';ContentTypeErrortypeSource ↗
Why content-type records could not be indexed.
All fail CLOSED: conflicting Defaults on one extension, duplicate normalized Override names, or invalid MIME syntax are refused rather than resolved by picking one.
type ContentTypeError = {
readonly code: 'invalid-mime';
readonly value: string;
} | {
readonly code: 'conflicting-default';
readonly extension: string;
} | {
readonly code: 'duplicate-override';
readonly partName: string;
} | {
readonly code: 'invalid-override-name';
readonly partName: string;
} | {
readonly code: 'too-many-records';
readonly limit: number;
};CustomNodeExportPolicytypeSource ↗
What happens to one control when the document is exported.
type CustomNodeExportPolicy = 'keep' | 'text' | 'remove';CustomNodeExportResulttypeSource ↗
The export, or the reason there is no export.
A refusal answers no package on purpose. "Stripping failed, here is the document anyway" is the one outcome that must not be possible: a caller would ship the markup it asked to remove and have been told the export succeeded.
type CustomNodeExportResult = {
readonly ok: true;
readonly pkg: OoxmlPackage;
readonly unwrapped: number;
readonly removed: number;
} | {
readonly ok: false;
readonly reason: string;
};CustomNodeSweepOutcometypeSource ↗
What the session answers for a sweep: the ids collected, or the reason none were.
Narrower than [CustomNodeSweepResult](CustomNodeSweepResult), which also carries the rewritten package — the session has already installed that, and handing it back would invite a caller to install it twice.
type CustomNodeSweepOutcome = {
readonly ok: true;
readonly removed: readonly string[];
} | {
readonly ok: false;
readonly reason: string;
};CustomNodeSweepResulttypeSource ↗
What one sweep collected, or why it collected nothing.
ok: false is NOT "the document was already tidy" — that is ok: true with an empty removed. It means a store this sweep was asked to tidy refused the rewrite, which a caller that keeps saving into the same document should know about rather than silently retry forever.
type CustomNodeSweepResult = {
readonly ok: true;
readonly pkg: OoxmlPackage;
readonly removed: readonly string[];
} | {
readonly ok: false;
readonly reason: string;
};CustomNodeWriteRejectiontypeSource ↗
Why a payload write was refused.
The tree rejections pass through unchanged, so a locked paragraph refuses a bound insert for the same named reason it refuses a plain one. The three added here are the payload's own.
type CustomNodeWriteRejection = TreeOpRejection
/** The id, root name or namespace cannot be spelled in an XPath, so no binding could name it. */
| 'unaddressable-payload'
/** The store could not be authored — see `withCustomXmlDataPart` for every way that happens. */
| 'store-not-authored'
/** The payload or the label is past the cap. */
| 'payload-too-large';CustomNodeWriteResulttypeSource ↗
type CustomNodeWriteResult = {
readonly ok: true;
readonly change: TreeModelChange | null;
readonly nodeId?: string;
} | {
readonly ok: false;
readonly reason: CustomNodeWriteRejection;
readonly detail?: string;
};DigestDifferencetypeSource ↗
Where two digests diverge — the diagnostic when a round-trip loses something.
type DigestDifference = {
readonly path: string;
readonly before: string;
readonly after: string;
};DrawingKindtypeSource ↗
Whether a drawing sits in the text flow or is positioned against a frame.
The distinction that decides everything downstream: an inline drawing occupies a character position, while an anchored one has offsets relative to a page, margin or column.
type DrawingKind = 'inline' | 'anchored';DrawingPropertyIdResulttypeSource ↗
A freshly allocated drawing property id, or the reason one could not be minted.
type DrawingPropertyIdResult = {
readonly ok: true;
readonly id: number;
} | {
readonly ok: false;
readonly reason: 'invalidArgs';
};DrawingTreeDocOptypeSource ↗
Drawing mutation ops from typed-drawings-and-images task 11.
type DrawingTreeDocOp = Extract<TreeDocOp, {
readonly op: 'insertDrawing' | 'replaceDrawingResource' | 'deleteDrawing' | 'resizeDrawing' | 'cropDrawing' | 'positionDrawing' | 'setDrawingWrap' | 'setDrawingMetadata' | 'setDrawingLocks' | 'transformDrawing';
}>;EndnotePositiontypeSource ↗
w:pos for endnotes — only the two document-level placements are legal.
type EndnotePosition = 'sectEnd' | 'docEnd';EnforcementPhasetypeSource ↗
Where a limit is enforced.
Declared per limit so enforcement happens at the boundary that can still refuse cheaply — a zip cap checked during layout has already let the bomb decompress.
type EnforcementPhase = 'package-read' | 'xml-parse' | 'layout' | 'output';FixtureOutcometypeSource ↗
Whether a recorded conformance step was expected to commit or be refused.
type FixtureOutcome = 'applied' | 'aborted' | 'validation' | 'conflict' | 'resource' | 'authorization';FixtureSourcetypeSource ↗
Which implementation recorded a fixture — local store, Yjs, or a binding.
type FixtureSource = {
readonly kind: 'create';
} | {
readonly kind: 'docx';
readonly sha256: string;
readonly bytesRef: string;
};FldCharTypetypeSource ↗
Which part of a complex field a w:fldChar marks.
A complex field spans many runs: begin, the instruction, separate, the cached result, then end — which is why a field is one logical unit across several nodes.
type FldCharType = 'begin' | 'separate' | 'end';FontStyleKeytypeSource ↗
Which of a family's four faces an embedded font relationship supplies.
type FontStyleKey = 'regular' | 'bold' | 'italic' | 'boldItalic';FootnotePositiontypeSource ↗
w:pos — where a section's footnotes are laid out.
type FootnotePosition = 'pageBottom' | 'beneathText' | 'sectEnd' | 'docEnd';HardBreakKindtypeSource ↗
What a w:br breaks. other covers values this engine does not model, kept losslessly.
type HardBreakKind = 'line' | 'page' | 'column' | 'other';HeaderFooterKindtypeSource ↗
Header vs footer region kind for chrome and lifecycle ops.
type HeaderFooterKind = 'header' | 'footer';HeaderFooterLifecycleImpacttypeSource ↗
Lifecycle impact — furniture always reaches multiple pages; never narrower than flow-structural.
type HeaderFooterLifecycleImpact = 'flow-structural' | 'global';HeaderFooterLifecycleOptypeSource ↗
A header/footer lifecycle mutation: create, remove, or relink a variant.
Package-level, like note lifecycle: each touches the document, the header/footer part, the relationships and [Content_Types].xml together.
type HeaderFooterLifecycleOp = {
readonly op: 'createHeaderFooter';
readonly sectionIndex: number;
readonly kind: HeaderFooterKind;
readonly variant: HeaderFooterVariant;
readonly titlePage?: boolean;
readonly evenAndOddHeaders?: boolean;
} | {
readonly op: 'deleteHeaderFooter';
readonly sectionIndex: number;
readonly kind: HeaderFooterKind;
readonly variant: HeaderFooterVariant;
} | {
readonly op: 'linkToPrevious';
readonly sectionIndex: number;
readonly kind: HeaderFooterKind;
readonly variant: HeaderFooterVariant;
} | {
readonly op: 'unlinkFromPrevious';
readonly sectionIndex: number;
readonly kind: HeaderFooterKind;
readonly variant: HeaderFooterVariant;
} | {
readonly op: 'setSectionFurnitureOptions';
readonly sectionIndex?: number;
readonly titlePage?: boolean;
readonly evenAndOddHeaders?: boolean;
readonly headerDistanceTwips?: number;
readonly footerDistanceTwips?: number;
};HeaderFooterLifecycleRejectiontypeSource ↗
Why a header/footer lifecycle op was refused.
type HeaderFooterLifecycleRejection = 'invalidArgs' | 'tree-invariant';HeaderFooterLifecycleResulttypeSource ↗
A new package, or a typed rejection. Pure and all-or-nothing — no partial writes.
type HeaderFooterLifecycleResult = {
readonly ok: true;
readonly package: OoxmlPackage;
readonly impact: HeaderFooterLifecycleImpact;
readonly createdRId?: string;
readonly createdPartName?: string;
} | {
readonly ok: false;
readonly reason: HeaderFooterLifecycleRejection;
readonly detail?: string;
};HeaderFooterVarianttypeSource ↗
w:headerReference w:type vocabulary (ECMA-376 §17.10.5): default, first page, even pages.
type HeaderFooterVariant = 'default' | 'first' | 'even';HrefProjectiontypeSource ↗
A hyperlink target projected for a RUNTIME sink, or the reason it was withheld.
The authored target stays authored — the record layer keeps it verbatim and escapes it into owned OOXML, which is not a runtime sink. Only this allowlist-sanitized projection reaches DOM, CSS, navigation or fetch, so javascript:, data: and vbscript: never leave the boundary.
type HrefProjection = {
readonly ok: true;
readonly href: string;
} | {
readonly ok: false;
readonly inert: true;
};HyperlinkKindtypeSource ↗
What a hyperlink points at, which decides what activating it may do.
The security-relevant split: an external link goes through sanitizeHref and opens only on explicit user action, while an anchor merely scrolls and never navigates.
type HyperlinkKind =
/** `r:id` → a relationship with `TargetMode="External"`. Opens somewhere else. */
'external'
/** `w:anchor` → a bookmark in this document. Scrolls, never navigates. */
| 'internal'
/**
* `r:id` naming a relationship the part does not declare, or one that is not external.
*
* The link keeps its runs — the text is never lost twice — but there is nothing to
* activate, so it paints inert exactly like a refused scheme.
*/
| 'unresolved';IdKindtypeSource ↗
One of [ID_KINDS](ID_KINDS) — which sort of thing an identifier names.
type IdKind = (typeof ID_KINDS)[number];ImageRelationshipResolutiontypeSource ↗
An image relationship resolved to package bytes, or why it was refused.
External-mode image rels are refused rather than fetched — the no-zero-click-external-fetch rule applies to images exactly as it does to links.
type ImageRelationshipResolution = {
readonly mode: 'internal';
readonly partName: string;
readonly raw: string;
} | {
readonly mode: 'external';
readonly sinkSafe: boolean;
readonly raw: string;
} | {
readonly mode: 'missing';
};ImageResourceStatetypeSource ↗
What is known about one embedded image: validated, refused, or still decoding.
Content type is a CLAIM. Signature sniffing, structural header validation and the decode port are authoritative, and bytes that fail them never enter public state.
type ImageResourceState = {
readonly kind: 'ready';
readonly partName: string;
readonly contentId: string;
readonly resourceKey: string;
readonly validatedHandle: ValidatedImageBytesHandle;
readonly mime: RenderableImageMime;
readonly pixelWidth: number;
readonly pixelHeight: number;
readonly dpiX: number;
readonly dpiY: number;
} | {
readonly kind: 'unrenderable';
readonly partName: string | null;
readonly mime: RenderableImageMime | PreservedImageMime | 'unknown';
readonly reason: 'unsupported-format' | 'non-picture-graphic' | 'signature-mismatch' | 'decode-failed' | 'resource-limit';
} | {
readonly kind: 'external';
readonly relationshipId: string;
readonly sinkSafe: boolean;
} | {
readonly kind: 'missing';
readonly relationshipId: string;
} | {
readonly kind: 'pending';
readonly resourceKey: string;
};ImageWrapTargettypeSource ↗
Nine Word wrap menu targets (inline plus eight floating modes).
type ImageWrapTarget = 'inline' | 'square' | 'squareLeft' | 'squareRight' | 'tight' | 'through' | 'topAndBottom' | 'behind' | 'inFront';ImpactClasstypeSource ↗
How far an op's effects reach — what layout must re-do after it.
The knob incremental layout turns: a text-local edit re-breaks one paragraph, while a global one invalidates the document.
type ImpactClass = 'text-local' | 'paragraph-local' | 'flow-structural' | 'global';IndexResulttypeSource ↗
The built index, or the conflict that made it impossible.
type IndexResult = {
readonly ok: true;
readonly index: ContentTypeIndex;
} | {
readonly ok: false;
readonly error: ContentTypeError;
};InertExecutableKindtypeSource ↗
One of [INERT_EXECUTABLE_KINDS](INERT_EXECUTABLE_KINDS) — content carried but never executed.
type InertExecutableKind = (typeof INERT_EXECUTABLE_KINDS)[number];JsontypeSource ↗
Any JSON value. The domain canonicalization and stable hashing operate over.
type Json = null | boolean | number | string | Json[] | {
[k: string]: Json;
};LimitUnittypeSource ↗
What a limit counts. Typed so a byte cap and a depth cap cannot be compared by accident.
type LimitUnit = 'bytes' | 'count' | 'depth' | 'ratio' | 'passes';ListKindtypeSource ↗
The two list kinds a toolbar offers.
type ListKind = 'bullet' | 'ordered';NameRejectiontypeSource ↗
Why a part or relationship name was refused.
Path traversal is the reason this exists: a name with .. or a leading / is refused rather than normalized, because normalizing is how a crafted package reaches outside itself.
type NameRejection = 'empty' | 'control-char' | 'backslash' | 'drive-or-unc' | 'encoded-separator' | 'encoded-dot' | 'bad-encoding' | 'empty-segment' | 'dot-segment' | 'unsafe-key' | 'segment-trailing-dot' | 'traversal-escape' | 'not-absolute-uri' | 'unsafe-scheme';NameResulttypeSource ↗
A validated OPC name, or the typed reason it was refused.
type NameResult = {
readonly ok: true;
readonly partName: string;
} | {
readonly ok: false;
readonly reason: NameRejection;
};NoteDiagnostictypeSource ↗
Load-time note diagnostics. Array API preserved; truncation is signaled as a typed entry rather than by throwing or rejecting the package.
type NoteDiagnostic = {
readonly code: 'dangling-note-reference';
readonly noteKind: NoteKind;
readonly noteId: number;
readonly sourceNodeId?: string;
} | {
readonly code: 'note-reference-scan-truncated';
};NoteDiagnosticCodetypeSource ↗
A load-time note problem worth reporting.
dangling-note-reference is a citation pointing at no note; note-reference-scan-truncated says the scan hit its budget, so absence of further diagnostics is not proof of correctness.
type NoteDiagnosticCode = 'dangling-note-reference' | 'note-reference-scan-truncated';NoteKindtypeSource ↗
Which notes part a note lives in. Decides both placement and numbering rules.
type NoteKind = 'footnote' | 'endnote';NoteLifecycleImpacttypeSource ↗
How far a note lifecycle op reaches — which parts a caller must expect to have changed.
type NoteLifecycleImpact = 'flow-structural' | 'global';NoteLifecycleOptypeSource ↗
A note lifecycle mutation: insert, delete, convert, or set properties.
Package-level rather than story-level, because every one of these touches the main document, the notes part, the document relationships AND [Content_Types].xml together.
type NoteLifecycleOp = {
readonly op: 'insertNote';
readonly noteKind: NoteKind;
readonly paragraphId: string;
readonly offset: number;
} | {
readonly op: 'deleteNote';
readonly noteKind: NoteKind;
readonly noteId: number;
} | {
readonly op: 'convertNote';
readonly fromKind: NoteKind;
readonly noteId: number;
} | {
readonly op: 'convertAllNotes';
readonly fromKind: NoteKind;
} | {
readonly op: 'setNoteProperties';
readonly scope: 'document' | 'section';
readonly sectionIndex?: number;
readonly footnote?: {
readonly numFmt?: string;
readonly numRestart?: string;
readonly position?: string;
readonly numStart?: number;
};
readonly endnote?: {
readonly numFmt?: string;
readonly numRestart?: string;
readonly position?: string;
readonly numStart?: number;
};
};NoteLifecycleRejectiontypeSource ↗
Why a note lifecycle op was refused.
type NoteLifecycleRejection = 'invalidArgs' | 'tree-invariant';NoteLifecycleResulttypeSource ↗
A new package, or a typed rejection.
Application is PURE and all-or-nothing: there are no partial writes, so a refused op leaves the caller's package untouched rather than half-migrated across four parts.
type NoteLifecycleResult = {
readonly ok: true;
readonly package: OoxmlPackage;
readonly impact: NoteLifecycleImpact;
readonly noteId?: number;
readonly noteKind?: NoteKind;
readonly createdPartName?: string;
} | {
readonly ok: false;
readonly reason: NoteLifecycleRejection;
readonly detail?: string;
};NoteNumRestarttypeSource ↗
w:numRestart — when note numbering starts over. eachPage needs the reference's page.
type NoteNumRestart = 'continuous' | 'eachSect' | 'eachPage';NoteTypetypeSource ↗
What a note entry IS.
Only normal is a note a reader sees. The others are the furniture Word stores in the same part — the rules and notices drawn around the note area — reached by reserved ids.
type NoteType = 'normal' | 'separator' | 'continuationSeparator' | 'continuationNotice';OoxmlAttributetypeSource ↗
Any attribute on any node: the two typed ones, plus the verbatim catch-all.
type OoxmlAttribute = OoxmlXmlSpaceAttribute | OoxmlWmlValAttribute | OoxmlGenericExtensionAttribute;OoxmlEditResulttypeSource ↗
An edited part, or the invariant violations that rejected the edit.
type OoxmlEditResult = {
readonly ok: true;
readonly part: OoxmlPart;
} | {
readonly ok: false;
readonly issues: readonly OoxmlInvariantIssue[];
};OoxmlElementtypeSource ↗
Every element node kind: the typed vocabulary plus the generic catch-all.
type OoxmlElement = OoxmlDocumentNode | OoxmlBodyNode | OoxmlParagraphNode | OoxmlRunNode | OoxmlHyperlinkNode | OoxmlBookmarkStartNode | OoxmlBookmarkEndNode | OoxmlRunPropertiesNode | OoxmlTextElementNode | OoxmlDeletedTextNode | OoxmlParagraphPropertiesNode | OoxmlTabNode | OoxmlHardBreakNode | OoxmlFldCharNode | OoxmlInstrTextNode | OoxmlFldSimpleNode | OoxmlFootnotesNode | OoxmlEndnotesNode | OoxmlNoteNode | OoxmlNoteReferenceNode | OoxmlNoteRefNode | OoxmlSeparatorNode | OoxmlContinuationSeparatorNode | OoxmlTableNode | OoxmlTableRowNode | OoxmlTableCellNode | OoxmlTableGridNode | OoxmlTablePropertiesNode | OoxmlRevisionContentNode | OoxmlRangeMarkerNode | OoxmlCommentReferenceNode | OoxmlCommentsNode | OoxmlCommentNode | OoxmlContentControlNode | OoxmlContentControlPropertiesNode | OoxmlContentControlEndPropertiesNode | OoxmlContentControlContentNode | OoxmlContentControlDropDownListNode | OoxmlContentControlComboBoxNode | OoxmlContentControlListItemNode | OoxmlContentControlDateNode | OoxmlContentControlDateFormatNode | OoxmlContentControlLidNode | OoxmlContentControlStoreMappedDataAsNode | OoxmlContentControlCalendarNode | OoxmlContentControlTextNode | OoxmlContentControlDataBindingNode | OoxmlContentControlCheckboxNode | OoxmlContentControlCheckedNode | OoxmlContentControlCheckedStateNode | OoxmlContentControlUncheckedStateNode | OoxmlDrawingNode | OoxmlInlineDrawingNode | OoxmlAnchoredDrawingNode | OoxmlDrawingExtentNode | OoxmlDrawingEffectExtentNode | OoxmlDrawingDocPrNode | OoxmlDrawingGraphicFramePrNode | OoxmlDrawingGraphicNode | OoxmlDrawingGraphicDataNode | OoxmlDrawingSimplePosNode | OoxmlDrawingPositionHNode | OoxmlDrawingPositionVNode | OoxmlDrawingPositionAlignNode | OoxmlDrawingPositionOffsetNode | OoxmlDrawingWrapNoneNode | OoxmlDrawingWrapSquareNode | OoxmlDrawingWrapTightNode | OoxmlDrawingWrapThroughNode | OoxmlDrawingWrapTopBottomNode | OoxmlDrawingWrapPolygonNode | OoxmlDrawingWrapPolygonStartNode | OoxmlDrawingWrapPolygonLineToNode | OoxmlPictureNode | OoxmlPictureNvPicPrNode | OoxmlPictureBlipFillNode | OoxmlPictureBlipNode | OoxmlPictureSrcRectNode | OoxmlPictureStretchNode | OoxmlPictureTileNode | OoxmlPictureShapePropertiesNode | OoxmlPictureTransformNode | OoxmlPictureTransformOffsetNode | OoxmlPictureTransformExtentNode | OoxmlPicturePresetGeometryNode | OoxmlGenericElementNode;OoxmlInvariantIssueCodetypeSource ↗
What a tree invariant walk found wrong. Each names a rule the canonical tree must satisfy.
type OoxmlInvariantIssueCode = 'invalid-id' | 'duplicate-id' | 'invalid-name' | 'invalid-namespace' | 'invalid-qname' | 'duplicate-expanded-attribute' | 'invalid-xml-value' | 'known-node-invariant';OoxmlInvariantResulttypeSource ↗
Whether a tree satisfies its invariants, listing every violation when it does not.
type OoxmlInvariantResult = {
readonly ok: true;
} | {
readonly ok: false;
readonly issues: readonly OoxmlInvariantIssue[];
};OoxmlKnownNodeAttributetypeSource ↗
Attributes a TYPED node may carry.
Excludes w:val on purpose: a node the engine models keeps its value in typed fields, and allowing a stray w:val alongside them would create two sources of truth for one property.
type OoxmlKnownNodeAttribute = OoxmlXmlSpaceAttribute | OoxmlGenericExtensionAttribute;OoxmlNodetypeSource ↗
Any node in the canonical tree.
Typed where layout needs structure, generic everywhere else — one tree carries a whole document whether or not the engine understands every part of it.
type OoxmlNode = OoxmlElement | OoxmlTextNode;OoxmlNodeIdtypeSource ↗
A node's stable identity within its part.
Minted deterministically from the structural path at parse, then RETAINED through structural sharing — the same bytes always produce the same ids, and an edit elsewhere in the document does not renumber untouched nodes. Every tree op addresses nodes by these.
type OoxmlNodeId = string;OoxmlPackageRejectiontypeSource ↗
Why a package could not be loaded. Every code describes the FILE, not the caller.
type OoxmlPackageRejection = ZipRejection | OoxmlReadRejection | 'no-content-types' | 'bad-content-types' | 'no-main-document' | 'bad-relationship-target' | 'duplicate-relationship-id' | 'too-many-relationships' | 'too-many-xml-parts';OoxmlPackageResulttypeSource ↗
A loaded package, or a typed refusal. Never throws.
type OoxmlPackageResult = {
readonly ok: true;
readonly package: OoxmlPackage;
} | {
readonly ok: false;
readonly reason: OoxmlPackageRejection;
readonly detail?: string;
};OoxmlReadRejectiontypeSource ↗
Why a part could not be read into a tree.
Widens the XML-level rejections with the tree-level ones. All of them describe the FILE, which is why reading returns a result rather than throwing.
type OoxmlReadRejection = XmlRejection | 'missing-root' | 'multiple-roots' | 'invalid-name' | 'invalid-namespace' | 'undeclared-prefix' | 'duplicate-expanded-attribute';OoxmlReadResulttypeSource ↗
A parsed part, or a typed refusal. Never throws — the input is untrusted by definition.
type OoxmlReadResult = {
readonly ok: true;
readonly part: OoxmlPart;
} | {
readonly ok: false;
readonly reason: OoxmlReadRejection;
};OoxmlStoryKindtypeSource ↗
Which kind of story a root is. Layout walks all four the same way.
type OoxmlStoryKind = 'body' | 'header' | 'footer' | 'note';PackageInvariantCodetypeSource ↗
What a package-level invariant walk found wrong.
Package invariants are cross-PART: a relationship pointing at a part that does not exist, or a part no content-type record covers. Neither is visible from inside a single part's tree.
type PackageInvariantCode = 'dangling-relationship' | 'missing-content-type'
/** A part occupies a name OPC reserves for package infrastructure. */
| 'reserved-part-name'
/** Two parts whose names differ only by case, which OPC treats as one part. */
| 'duplicate-part-name'
/** A part name the OPC screens refuse; `writeZip` would throw on save. */
| 'unsafe-part-name';PackageInvariantResulttypeSource ↗
Whether a package satisfies its cross-part invariants, listing every violation otherwise.
type PackageInvariantResult = {
readonly ok: true;
} | {
readonly ok: false;
readonly issues: readonly PackageInvariantIssue[];
};PackageTransactResulttypeSource ↗
Whether a package-level transaction committed, or why it was refused.
type PackageTransactResult = {
readonly ok: true;
readonly change: TreeModelChange | null;
} | {
readonly ok: false;
readonly reason: StoryTargetRejection | TreeOpRejection;
readonly detail?: string;
};PreservedImageMimetypeSource ↗
Media kept in the package byte-for-byte that the painter cannot hand to an <img>. A decode port may rasterize it; without one it paints as a labelled placeholder.
type PreservedImageMime = 'image/tiff' | 'image/x-emf' | 'image/x-wmf';RegistryErrorCodetypeSource ↗
Why registry resolution failed.
Every code names a declaration conflict a bundle author can fix — a missing dependency, an unsatisfied version range, a duplicate contribution with no replacement policy.
type RegistryErrorCode = 'invalid-id' | 'invalid-version' | 'duplicate-extension' | 'id-collision' | 'replacement-target-missing' | 'unauthorized-replacement' | 'replacement-version-mismatch' | 'ambiguous-replacement' | 'missing-dependency' | 'dependency-cycle' | 'conflict' | 'missing-port';RelationshipErrortypeSource ↗
Why a relationship set is invalid. Duplicate ids within one owner fail closed.
type RelationshipError = {
readonly code: 'duplicate-id';
readonly ownerPart: string;
readonly id: string;
};RelationshipSetResulttypeSource ↗
The validated relationship set, or the conflict that rejected it.
type RelationshipSetResult = {
readonly ok: true;
readonly byOwner: ReadonlyMap<string, readonly RelationshipRecord[]>;
} | {
readonly ok: false;
readonly error: RelationshipError;
};RelationshipTargetResolvertypeSource ↗
What a part's relationships answer for one r:id: the authored target and whether the package declared it external. null for an id the part does not declare — a DANGLING relationship, which is a real thing in real documents.
type RelationshipTargetResolver = (relationshipId: string) => {
readonly target: string;
readonly external: boolean;
readonly sinkSafe?: boolean;
} | null;ReplacementPolicytypeSource ↗
How a base contribution permits replacement by other bundles.
type ReplacementPolicy = {
readonly kind: 'none';
} | {
readonly kind: 'single';
} | {
readonly kind: 'priority';
};ResolvedRelationshiptypeSource ↗
A relationship resolved to a part, or the reason it could not be.
External targets resolve to a refusal by design: they are never followed from a file.
type ResolvedRelationship = {
readonly mode: 'Internal';
readonly target: NameResult;
readonly raw: string;
} | {
readonly mode: 'External';
readonly sinkSafe: NameResult;
readonly raw: string;
};ResolveResulttypeSource ↗
A part's content type, or why it has none.
An orphan record never determines a part's type — a Default with no matching part is preserved inertly rather than applied.
type ResolveResult = {
readonly ok: true;
readonly contentType: string;
readonly source: 'override' | 'default';
} | {
readonly ok: false;
readonly reason: 'unknown';
};ReviewItemtypeSource ↗
One pending decision as the STORE derives it: a tracked change or a comment. Discriminate on kind.
The layout layer's own ReviewItem widens this with the pro custom-node card, which has no store representation.
type ReviewItem = ReviewRevisionItem | ReviewCommentItem;ReviewRevisionKindtypeSource ↗
What kind of decision a revision card represents.
Wider than the four content wrappers, because a reviewer has to be shown every pending decision, including the ones that decorate no characters. A card the surface cannot show is a change the reviewer never learns about — and acceptAllRevisions refuses if ANY revision in the document is one the engine cannot resolve, so an invisible one makes Accept All fail for a reason nothing on screen explains.
type ReviewRevisionKind = 'insert' | 'delete'
/**
* A deletion and an insertion that are one edit: text typed over a selection.
*
* Word shows these as a single `Replaced "x" with "y"` card, and resolving one half
* without the other is never what the reviewer meant — accepting the deletion alone
* leaves the replacement text unproposed, rejecting it alone leaves both.
*/
| 'replace' | 'moveFrom' | 'moveTo'
/** `w:rPrChange` / `w:pPrChange` — the words are unchanged, their formatting is not. */
| 'format'
/** `w:pPr/w:rPr/w:ins|w:del` — a paragraph split or merge. */
| 'paragraphMark'
/** A row, cell, section or grid revision. Supported row revisions are resolvable. */
| 'structural';SetCommentResolvedResulttypeSource ↗
Whether resolving a thread applied. Marks the comment AND every reply to it, as Word does.
type SetCommentResolvedResult = {
readonly ok: true;
readonly changed: boolean;
readonly change: TreeModelChange | null;
} | {
readonly ok: false;
readonly reason: TreeOpRejection | 'unknown-comment';
};StoryResolveResulttypeSource ↗
A story scope resolved to a part, or the typed reason it could not be.
type StoryResolveResult = {
readonly ok: true;
readonly story: TreeStoryRef;
readonly store: TreeDocumentStore;
} | {
readonly ok: false;
readonly reason: StoryTargetRejection;
readonly detail?: string;
};StoryScopetypeSource ↗
Editable story target.
Body and headerFooter mirror EditorScope. Notes use one lazy store per notes part (notesPart) — not one store per note — resolved through safe document relationships.
type StoryScope = {
readonly kind: 'body';
} | {
readonly kind: 'headerFooter';
readonly rId: string;
} | {
readonly kind: 'notesPart';
readonly noteKind: NoteKind;
};StoryTargetRejectiontypeSource ↗
Why a story scope could not be resolved to a part.
Several of these are FILE-hostile shapes rather than caller mistakes: external-relationship and bad-relationship-target are how a crafted document tries to point a story at something outside the package, and both are refused rather than followed.
type StoryTargetRejection = 'unknown-scope' | 'dangling-relationship' | 'wrong-relationship-type' | 'external-relationship' | 'bad-relationship-target' | 'missing-part' | 'not-a-story-part' | 'too-many-story-stores';SupportedImageMimetypeSource ↗
Raster media the decode port measures and any authoring path may write.
BMP and WebP are here for the same reason the other three are: an <img> decodes them natively, so they need a signature and a structural header and nothing else. BMP is what older documents carry; WebP is what current Word writes.
type SupportedImageMime = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/bmp' | 'image/webp';TableBorderStyletypeSource ↗
One of the border line styles this engine draws.
An ALLOWLIST, not the full ST_Border enumeration: a file may name any of the seventy-odd OOXML border styles, and anything outside this set falls back rather than being passed through to paint.
type TableBorderStyle = (typeof TABLE_BORDER_STYLES)[number];TargetModetypeSource ↗
Whether a relationship points inside the package or out of it.
The security-relevant distinction: an External target is retained VERBATIM and never owner-resolved or fetched, because auto-loading a file-supplied remote target is a zero-click external fetch.
type TargetMode = 'Internal' | 'External';TreeDocOptypeSource ↗
Every mutation the store accepts, as one JSON-safe discriminated union.
The ONLY write path into a document. Each op addresses nodes by id plus UTF-16 offset, which is what makes editing a paragraph inside a table cell no different from editing one at the top level. Declarative and serializable, so the same op crosses a worker or transport boundary unchanged.
type TreeDocOp = {
readonly op: 'insertToc';
readonly beforeParagraphId: string;
readonly instruction: string;
readonly alias: string;
readonly entries: readonly {
readonly level: number;
readonly text: string;
readonly headingParagraphId: string;
readonly bookmarkName: string;
readonly pageNumberText: string;
}[];
readonly bookmarksToCreate: readonly {
readonly paragraphId: string;
readonly name: string;
}[];
} | {
readonly op: 'insertText';
readonly paragraphId: string;
readonly offset: number;
readonly text: string;
readonly revision?: RevisionAttributionInput;
readonly inside?: string;
readonly bias?: 'left' | 'right';
} | {
readonly op: 'deleteText';
readonly paragraphId: string;
readonly start: number;
readonly end: number;
readonly revision?: RevisionAttributionInput;
} | {
readonly op: 'setParagraphMarkRevision';
readonly paragraphId: string;
readonly kind: 'ins' | 'del';
readonly revision: RevisionAttributionInput;
} | {
readonly op: 'proposeParagraphMerge';
readonly paragraphId: string;
readonly revision: RevisionAttributionInput;
} | {
readonly op: 'insertCommentMarker';
readonly paragraphId: string;
readonly offset: number;
readonly commentId: string;
readonly marker: 'start' | 'end' | 'reference';
} | {
readonly op: 'acceptRevision';
readonly revision: RevisionAddress;
readonly localName?: string;
} | {
readonly op: 'rejectRevision';
readonly revision: RevisionAddress;
readonly localName?: string;
} | {
readonly op: 'acceptAllRevisions';
} | {
readonly op: 'rejectAllRevisions';
} | {
readonly op: 'insertTab';
readonly paragraphId: string;
readonly offset: number;
} | {
readonly op: 'insertHardBreak';
readonly paragraphId: string;
readonly offset: number;
} | {
readonly op: 'insertPageBreak';
readonly paragraphId: string;
readonly offset: number;
} | {
readonly op: 'insertPageField';
readonly paragraphId: string;
readonly offset: number;
readonly field: 'PAGE' | 'NUMPAGES' | 'SECTIONPAGES' | 'PAGE_X_OF_Y';
} | {
readonly op: 'setListLevel';
readonly paragraphId: string;
readonly level: number;
} | {
readonly op: 'setParagraphMarkProperties';
readonly paragraphId: string;
readonly properties: readonly OoxmlProperty[];
} | {
readonly op: 'setListNumbering';
readonly paragraphId: string;
readonly numId: string | null;
readonly level?: number;
} | {
readonly op: 'splitParagraph';
readonly paragraphId: string;
readonly offset: number;
} | {
readonly op: 'splitParagraphMany';
readonly paragraphId: string;
readonly offsets: readonly number[];
} | {
readonly op: 'joinParagraphs';
readonly firstId: string;
readonly secondId: string;
} | {
readonly op: 'setRunProperties';
readonly paragraphId: string;
readonly start: number;
readonly end: number;
readonly properties: readonly OoxmlProperty[];
readonly targetRunIds?: readonly string[];
} | {
readonly op: 'setParagraphProperties';
readonly paragraphId: string;
readonly properties: readonly OoxmlProperty[];
} | {
readonly op: 'setSectionProperties';
readonly pageWidthTwips?: number;
readonly pageHeightTwips?: number;
readonly orientation?: 'portrait' | 'landscape';
readonly marginTopTwips?: number;
readonly marginRightTwips?: number;
readonly marginBottomTwips?: number;
readonly marginLeftTwips?: number;
readonly anchorParagraphId?: string;
} | {
readonly op: 'setSectionMark';
readonly paragraphId: string;
} | {
readonly op: 'insertHyperlink';
readonly paragraphId: string;
readonly start: number;
readonly end: number;
readonly relationshipId?: string;
readonly anchor?: string;
readonly tooltip?: string;
readonly styleId?: string;
} | {
readonly op: 'setHyperlinkTarget';
readonly linkId: string;
readonly relationshipId?: string;
readonly anchor?: string;
readonly tooltip?: string;
} | {
readonly op: 'removeHyperlink';
readonly linkId: string;
} | {
readonly op: 'insertInlineContentControl';
readonly paragraphId: string;
readonly offset: number;
readonly tag: string;
readonly text: string;
readonly alias?: string;
readonly lock?: 'sdtLocked' | 'sdtContentLocked' | 'contentLocked';
readonly dataBinding?: {
readonly prefixMappings: string;
readonly xpath: string;
readonly storeItemId: string;
};
} | {
readonly op: 'addRepeatingSectionItem';
readonly controlId: string;
readonly index?: number;
} | {
readonly op: 'removeRepeatingSectionItem';
readonly controlId: string;
readonly index: number;
} | {
readonly op: 'deleteBlock';
readonly blockId: string;
} | {
readonly op: 'insertTable';
readonly beforeParagraphId: string;
readonly rows: number;
readonly cols: number;
readonly columnWidthTwips: number;
} | {
readonly op: 'insertTableRow';
readonly tableId: string;
readonly rowId: string;
readonly where: 'above' | 'below';
readonly revision?: RevisionAttributionInput;
} | {
readonly op: 'deleteTableRow';
readonly tableId: string;
readonly rowId: string;
readonly referenceCellId?: string;
readonly revision?: RevisionAttributionInput;
} | {
readonly op: 'insertTableColumn';
readonly tableId: string;
readonly where: 'left' | 'right';
readonly gridColumnId: string;
} | {
readonly op: 'insertTableColumn';
readonly tableId: string;
readonly where: 'left' | 'right';
readonly referenceCellId: string;
} | {
readonly op: 'deleteTableColumn';
readonly tableId: string;
readonly gridColumnId: string;
} | {
readonly op: 'setTableColumnWidths';
readonly tableId: string;
readonly leftGridColumnId: string;
readonly rightGridColumnId: string;
readonly leftWidthTwips: number;
readonly rightWidthTwips: number;
} | {
readonly op: 'setTableRightEdgeWidth';
readonly tableId: string;
readonly gridColumnId: string;
readonly columnWidthTwips: number;
readonly tableWidthTwips: number;
} | {
readonly op: 'setTableRowHeight';
readonly tableId: string;
readonly rowId: string;
readonly heightTwips: number;
} | {
readonly op: 'setTableCellBorders';
readonly tableId: string;
readonly cellIds: readonly string[];
readonly scope: 'none';
readonly target: TableBorderEdgeTarget;
} | {
readonly op: 'setTableCellBorders';
readonly tableId: string;
readonly cellIds: readonly string[];
readonly scope: TableBorderEdgeTarget;
readonly spec: TableBorderSpecInput;
} | {
readonly op: 'setTableCellFill';
readonly tableId: string;
readonly cellIds: readonly string[];
readonly color: TreeDocColorValue | null;
} | {
readonly op: 'setTableCellVerticalAlignment';
readonly tableId: string;
readonly cellIds: readonly string[];
readonly alignment: 'top' | 'center' | 'bottom';
} | {
readonly op: 'createHeaderFooter';
readonly sectionIndex: number;
readonly kind: 'header' | 'footer';
readonly variant: 'default' | 'first' | 'even';
readonly titlePage?: boolean;
readonly evenAndOddHeaders?: boolean;
} | {
readonly op: 'deleteHeaderFooter';
readonly sectionIndex: number;
readonly kind: 'header' | 'footer';
readonly variant: 'default' | 'first' | 'even';
} | {
readonly op: 'linkToPrevious';
readonly sectionIndex: number;
readonly kind: 'header' | 'footer';
readonly variant: 'default' | 'first' | 'even';
} | {
readonly op: 'unlinkFromPrevious';
readonly sectionIndex: number;
readonly kind: 'header' | 'footer';
readonly variant: 'default' | 'first' | 'even';
} | {
readonly op: 'setSectionFurnitureOptions';
readonly sectionIndex?: number;
readonly titlePage?: boolean;
readonly evenAndOddHeaders?: boolean;
readonly headerDistanceTwips?: number;
readonly footerDistanceTwips?: number;
} | {
readonly op: 'insertNote';
readonly noteKind: 'footnote' | 'endnote';
readonly paragraphId: string;
readonly offset: number;
} | {
readonly op: 'deleteNote';
readonly noteKind: 'footnote' | 'endnote';
readonly noteId: number;
} | {
readonly op: 'convertNote';
readonly fromKind: 'footnote' | 'endnote';
readonly noteId: number;
} | {
readonly op: 'convertAllNotes';
readonly fromKind: 'footnote' | 'endnote';
} | {
readonly op: 'setContentControlValue';
readonly controlId: string;
readonly value: string | ContentControlValueInput;
} | {
readonly op: 'setContentControlProperties';
readonly controlId: string;
readonly tag?: string | null;
readonly alias?: string | null;
readonly lock?: ContentControlLock;
} | {
readonly op: 'removeContentControl';
readonly controlId: string;
readonly keepContent?: boolean;
} | {
readonly op: 'insertContentControl';
readonly paragraphId: string;
readonly start: number;
readonly end: number;
readonly type: InsertableContentControlType;
readonly tag?: string;
readonly alias?: string;
readonly lock?: ContentControlLock;
} | {
readonly op: 'setNoteProperties';
readonly scope: 'document' | 'section';
readonly sectionIndex?: number;
readonly footnote?: {
readonly numFmt?: string;
readonly numRestart?: string;
readonly position?: string;
readonly numStart?: number;
};
readonly endnote?: {
readonly numFmt?: string;
readonly numRestart?: string;
readonly position?: string;
readonly numStart?: number;
};
} | {
readonly op: 'insertDrawing';
readonly paragraphId: string;
readonly offset: number;
readonly drawing: OoxmlDrawingNode;
} | {
readonly op: 'replaceDrawingResource';
readonly drawingNodeId: string;
readonly relationshipId: string;
} | {
readonly op: 'deleteDrawing';
readonly drawingNodeId: string;
readonly revision?: RevisionAttributionInput;
} | {
readonly op: 'resizeDrawing';
readonly drawingNodeId: string;
readonly extentEmu: {
readonly cx: number;
readonly cy: number;
};
} | {
readonly op: 'cropDrawing';
readonly drawingNodeId: string;
readonly crop: SourceCrop;
} | {
readonly op: 'positionDrawing';
readonly drawingNodeId: string;
readonly position: DrawingPositionInput;
} | {
readonly op: 'setDrawingWrap';
readonly drawingNodeId: string;
readonly wrap: ImageWrapTarget;
} | {
readonly op: 'setDrawingMetadata';
readonly drawingNodeId: string;
readonly title: string;
readonly description: string;
readonly hyperlink?: string | null;
} | {
readonly op: 'setDrawingLocks';
readonly drawingNodeId: string;
readonly locks: DrawingLocksInput;
} | {
readonly op: 'transformDrawing';
readonly drawingNodeId: string;
readonly action: 'rotateCW' | 'rotateCCW' | 'flipH' | 'flipV';
} | {
readonly op: 'replaceTocResult';
readonly tocId: string;
readonly entries: readonly {
readonly level: number;
readonly text: string;
readonly headingParagraphId: string;
readonly bookmarkName: string;
readonly pageNumberText: string;
}[];
readonly bookmarksToCreate: readonly {
readonly paragraphId: string;
readonly name: string;
}[];
} | {
readonly op: 'rewriteTocPageNumbers';
readonly tocId: string;
readonly updates: readonly {
readonly paragraphId: string;
readonly pageNumberText: string;
}[];
};TreeDocOpKindtypeSource ↗
Just the op discriminants, for dispatch tables and validation.
type TreeDocOpKind = TreeDocOp['op'];TreeOpRejectiontypeSource ↗
Why an op was refused.
not-adjacent-siblings is the notable one: a join across table cells is refused rather than silently merging content out of the cell that owned it.
type TreeOpRejection = 'unknown-op' | 'unknown-paragraph' | 'not-a-paragraph' | 'offset-out-of-range' | 'invalid-range' | 'not-a-list-paragraph' | 'splits-surrogate-pair' | 'invalid-text' | 'unsupported-property' | 'invalid-property-value' | 'not-adjacent-siblings' | 'unknown-block' | 'not-a-block' | 'block-required' | 'carries-section-mark'
/** The transaction named a part the package does not hold. */
| 'unknown-part'
/**
* The transaction would have published a package that does not open: a relationship
* pointing at a part nobody created, or a part with no declared content type.
*/
| 'package-invariant'
/** No revision in this part carries the addressed `(id, author, date)` triple. */
| 'unknown-revision'
/**
* A matched revision is a kind whose accept/reject semantics are structural and not
* implemented. Refusing is deliberate: removing the markup alone would report the decision
* applied while leaving the row, cell, or section it describes untouched.
*/
| 'unsupported-revision' | 'tree-invariant'
/** No content control in this part carries the addressed node id. */
| 'unknown-content-control'
/** The addressed node exists and is not a `w:sdt`. */
| 'not-a-content-control'
/**
* A content control's `w:lock` — or one an enclosing control imposes — forbids this.
*
* The same code for an edit inside `contentLocked` content and for the removal of an
* `sdtLocked` control: both are "the document says no", and the two halves are already
* distinguished by which operation was refused.
*/
| 'locked'
/** The control declares `w:dataBinding`; its value belongs to a custom XML part. */
| 'bound'
/** The value offered is not one this control's type accepts. */
| 'typeMismatch' | 'unknown-control' | 'unsupported'
/** Malformed lifecycle args / first-section link — mirrors Editor `invalidArgs`. */
| 'invalidArgs'
/** The addressed table id is missing, duplicated, or not a typed table. */
| 'unknown-table'
/** The addressed row id is missing or not a direct child of the table. */
| 'unknown-row'
/** A table property container appears more than once on a typed node. */
| 'duplicate-property-container'
/** Row insertion would split an active vertical-merge chain. */
| 'vertical-merge-crossing'
/** Column edit refused because the table carries horizontal or vertical merges. */
| 'table-has-merge'
/** The addressed grid column id is missing or ambiguous without `w:tblGrid`. */
| 'unknown-grid-column'
/** The operation would exceed bounded table topology limits. */
| 'resource-limit'
/** The addressed node is not a top-level `w:drawing`. */
| 'not-a-drawing'
/** No `w:drawing` with this id exists in the part. */
| 'unknown-drawing'
/** The drawing's graphic payload is not a supported picture. */
| 'not-a-picture-drawing'
/** A lock flag or `@locked` forbids this mutation. */
| 'drawing-locked'
/** Finite EMU extent, crop, or position value is out of range. */
| 'invalid-drawing-value'
/** Insertion would cross a table-cell boundary or wrong story container. */
| 'cross-cell-drawing'
/** Suggesting-mode drawing deletion is not implemented in this change. */
| 'trackedDrawingDeletionUnsupported'
/** Hyperlink target creation or change needs an OPC relationship in a package transaction. */
| 'packageTransactionRequired';TreeOpResulttypeSource ↗
Whether an op applied, with the effect it produced or the reason it was refused.
type TreeOpResult = {
readonly ok: true;
readonly part: OoxmlPart;
readonly effect: TreeOpEffect;
} | {
readonly ok: false;
readonly reason: TreeOpRejection;
readonly detail?: string;
};TreeStoryReftypeSource ↗
Which story a transaction targets: the body, a header/footer part, or a notes part.
type TreeStoryRef = {
readonly kind: 'body';
readonly partName: string;
} | {
readonly kind: 'headerFooter';
readonly partName: string;
readonly rId: string;
} | {
readonly kind: 'notesPart';
readonly partName: string;
readonly noteKind: 'footnote' | 'endnote';
};TreeTransactResulttype
Whether a transaction committed, or the typed reason it was refused.
type TransactResult = {
readonly ok: true;
readonly change: TreeModelChange | null;
} | {
readonly ok: false;
readonly reason: TreeOpRejection;
readonly detail?: string;
};XmlNodetypeSource ↗
One parsed XML node, preserving significant order, whitespace and raw lexical values.
Attribute records have a NULL prototype: attribute names come from a file and become object keys, so __proto__ must be inert by construction rather than by filtering.
type XmlNode = {
readonly type: 'element';
readonly name: string;
readonly attributes: Readonly<Record<string, string>>;
readonly children: readonly XmlNode[];
} | {
readonly type: 'text';
readonly value: string;
};XmlRejectiontypeSource ↗
Why XML was refused at the trust boundary.
DTDs, entity declarations and external-entity references are PRE-rejected before parsing — blocking XXE and billion-laughs by never handing the parser the construct, rather than by trusting it to be configured safely.
type XmlRejection = 'too-large' | 'dtd-forbidden' | 'entity-forbidden' | 'too-deep' | 'too-many-elements' | 'invalid-limits' | 'parse-error';XmlResulttypeSource ↗
A parsed document, or a typed refusal. Never throws — the input is untrusted.
type XmlResult = {
readonly ok: true;
readonly nodes: readonly XmlNode[];
} | {
readonly ok: false;
readonly reason: XmlRejection;
};ZipReadResulttypeSource ↗
The read entries, or the typed refusal. Never throws — the bytes are untrusted.
type ZipReadResult = {
readonly ok: true;
readonly entries: ReadonlyMap<string, Uint8Array>;
} | {
readonly ok: false;
readonly reason: ZipRejection;
readonly detail?: string;
};ZipRejectiontypeSource ↗
Why a zip was refused at the trust boundary.
too-large and too-many-entries are the zip-bomb guards; bad-name catches path traversal — an entry with .. or a leading / is rejected rather than normalized.
type ZipRejection = 'too-many-entries' | 'too-large' | 'bad-name' | 'inflate-error';Variables (69)
ACCEPTED_PARAGRAPH_PROPERTIESconstSource ↗
The accepted PARAGRAPH property boundary (design D8).
ACCEPTED_PARAGRAPH_PROPERTIES: readonly ["pStyle", "jc", "spacing", "ind", "tabs", "numPr", "keepNext", "keepLines", "widowControl", "pageBreakBefore", "shd"]ACCEPTED_RUN_PROPERTIESconstSource ↗
The accepted RUN property boundary (design D8), as the OOXML element names that carry it.
An explicit allowlist rather than "any w:rPr child": a property outside D8 has no resolver, no layout behavior and no support claim, so accepting it here would let an operation assert support the engine does not have. Unknown properties still ROUND-TRIP — they are generic nodes in the tree — they simply cannot be authored by an op.
ACCEPTED_RUN_PROPERTIES: readonly ["rFonts", "sz", "szCs", "color", "b", "bCs", "i", "iCs", "u", "strike", "dstrike", "highlight", "vertAlign", "position", "caps", "smallCaps", "spacing", "w", "kern"]ALL_FROZEN_IDSconstSource ↗
Every frozen id as a flat list, for the immutability / uniqueness gate.
ALL_FROZEN_IDS: readonly string[]AUTHORABLE_PARAGRAPH_PROPERTIESconstSource ↗
The D8 paragraph op vocabulary.
AUTHORABLE_PARAGRAPH_PROPERTIES: ReadonlySet<string>AUTHORABLE_RUN_PROPERTIESconstSource ↗
The D8 run op vocabulary, for w:rPr on a run and on the paragraph mark alike.
AUTHORABLE_RUN_PROPERTIES: ReadonlySet<string>CANONICAL_MUTATION_ORIGINSconstSource ↗
Canonical writes carry a mutation origin; these are the undoable-eligibility inputs.
CANONICAL_MUTATION_ORIGINS: readonly string[]COMPARATORSconstSource ↗
The frozen artifact comparator set.
COMPARATORS: {
readonly authoredState: {
readonly id: "dev.docx-editor.core.comparator.authored-state";
readonly mode: "canonical-exact";
readonly ephemera: readonly ["revision", "provenance", "producedAt", "commitId"];
readonly note: "canonical normalized authored records; ephemera excluded";
};
readonly anchor: {
readonly id: "dev.docx-editor.core.comparator.anchor";
readonly mode: "exact";
readonly ephemera: readonly [];
readonly note: "internal anchor identity/affinity compares exactly";
};
readonly yjsStateVector: {
readonly id: "dev.docx-editor.core.comparator.yjs-state-vector";
readonly mode: "sync-optimization-only";
readonly ephemera: readonly [];
readonly note: "exchange optimization only; never proves update or delete-set coverage";
};
readonly shapedRun: {
readonly id: "dev.docx-editor.core.comparator.shaped-run";
readonly mode: "exact";
readonly ephemera: readonly [];
readonly note: "glyph ids, clusters, and fixed-point advances compare exactly";
};
readonly paginationFingerprint: {
readonly id: "dev.docx-editor.core.comparator.pagination-fingerprint";
readonly mode: "exact";
readonly ephemera: readonly [];
readonly note: "page/column boundaries, break causes, fixed-point geometry compare exactly";
};
readonly semanticTree: {
readonly id: "dev.docx-editor.core.comparator.semantic-tree";
readonly mode: "exact";
readonly ephemera: readonly [];
readonly note: "reading order, roles, headings, alt text compare exactly";
};
readonly hitTest: {
readonly id: "dev.docx-editor.core.comparator.hit-test";
readonly mode: "exact";
readonly ephemera: readonly [];
readonly note: "resolved hit target and cluster affinity compare exactly";
};
readonly pdfSemantics: {
readonly id: "dev.docx-editor.core.comparator.pdf-semantics";
readonly mode: "canonical-exact";
readonly ephemera: readonly ["objectNumber", "producer", "creationDate", "modDate", "subsetTag"];
readonly note: "canonical semantic PDF objects; container ephemera excluded";
};
readonly rasterCheckpoint: {
readonly id: "dev.docx-editor.core.comparator.raster-checkpoint";
readonly mode: "tolerance";
readonly ephemera: readonly [];
readonly note: "documented unavoidable raster comparison; explicit tolerance only";
};
readonly benchmarkEvidence: {
readonly id: "dev.docx-editor.core.comparator.benchmark-evidence";
readonly mode: "sync-optimization-only";
readonly ephemera: readonly [];
readonly note: "diagnostic evidence, not an equivalence basis";
};
}CONTENT_CONTROL_ID_MAXconstSource ↗
CT_SdtPr/w:id is ST_DecimalNumber; Word treats it as a signed 32-bit integer.
CONTENT_CONTROL_ID_MAX = 2147483647CONTENT_CONTROL_PROPERTY_ORDERconstSource ↗
CT_SdtPr's declared child order (§17.5.2.38), followed by the type choice.
Serialization re-emits children in tree order, so the ONLY way a write keeps the sequence valid is to place the child it authors at its schema position — which is what [orderedContentControlProperties](orderedContentControlProperties) does.
CONTENT_CONTROL_PROPERTY_ORDER: readonly string[]CUSTOM_NODE_XPATH_PREFIXconstSource ↗
The prefix every binding this library authors declares and quotes.
CUSTOM_NODE_XPATH_PREFIX = "ns0"CUSTOM_XML_PROPS_RELconstSource ↗
Relationship from a data part to the properties that carry its ds:itemID.
CUSTOM_XML_PROPS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps"CUSTOM_XML_PROPS_TYPEconstSource ↗
itemPropsN.xml needs an Override; itemN.xml rides the package's xml default.
CUSTOM_XML_PROPS_TYPE = "application/vnd.openxmlformats-officedocument.customXmlProperties+xml"CUSTOM_XML_RELconstSource ↗
Relationship from the story to one data part.
CUSTOM_XML_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml"DANGEROUS_KEYSconstSource ↗
Keys that must never be assigned from file data.
XML attribute names become object keys, and a document controls those names — assigning __proto__ into an ordinary object is the prototype-pollution hazard this engine audits for.
DANGEROUS_KEYS: readonly string[]DATASTORE_NAMESPACE_URIconstSource ↗
The datastore namespace ds:datastoreItem lives in.
DATASTORE_NAMESPACE_URI = "http://schemas.openxmlformats.org/officeDocument/2006/customXml"DEFAULT_ENDNOTE_PROPERTIESconstSource ↗
Word-compatible defaults. ECMA-376 says omitted endnote numFmt is decimal; MS-OE376 / MS-OI29500 document that Word’s default is lowerRoman instead. Resolved (not authored) — unedited packages still invent nothing on save.
DEFAULT_ENDNOTE_PROPERTIES: ResolvedEndnotePropertiesDEFAULT_FOOTNOTE_PROPERTIESconstSource ↗
Word's own footnote defaults, applied where a section declares no w:footnotePr.
DEFAULT_FOOTNOTE_PROPERTIES: ResolvedFootnotePropertiesDEFAULT_IMAGE_RESOURCE_LIMITSconstSource ↗
The image caps in force when a host configures none. Conservative and finite.
DEFAULT_IMAGE_RESOURCE_LIMITS: ImageResourceLimitsDEFAULT_LIMITSconstSource ↗
Finite defaults, all = their hard ceiling.
DEFAULT_LIMITS: ResourceLimitsDEFAULT_MAX_EDITABLE_STORY_PARTSconstSource ↗
Cap on simultaneously opened editable story stores (body + HF parts). Fail closed.
DEFAULT_MAX_EDITABLE_STORY_PARTS = 64DEFAULT_OOXML_PACKAGE_LIMITSconstSource ↗
The limits in force when a host configures none. Conservative and finite.
DEFAULT_OOXML_PACKAGE_LIMITS: Required<Pick<OoxmlPackageLimits, 'maxXmlParts' | 'maxRelationships'>>DEFAULT_ZIP_LIMITSconstSource ↗
The archive caps in force when a host configures none. Conservative and finite.
DEFAULT_ZIP_LIMITS: ZipLimitsDEPENDENCY_KEY_IDSconstSource ↗
Layout dependency keys (design D6 / task 8.2).
DEPENDENCY_KEY_IDS: {
readonly style: "dev.docx-editor.core.dep.style";
readonly numbering: "dev.docx-editor.core.dep.numbering";
readonly section: "dev.docx-editor.core.dep.section";
readonly story: "dev.docx-editor.core.dep.story";
readonly font: "dev.docx-editor.core.dep.font";
readonly image: "dev.docx-editor.core.dep.image";
readonly table: "dev.docx-editor.core.dep.table";
readonly field: "dev.docx-editor.core.dep.field";
readonly note: "dev.docx-editor.core.dep.note";
readonly headerFooter: "dev.docx-editor.core.dep.header-footer";
readonly annotation: "dev.docx-editor.core.dep.annotation";
}FIELD_ATOM_CHARconstSource ↗
UTF-16 placeholder for one atomic field unit in paragraphTextOf / segments.
FIELD_ATOM_CHAR = "\uFFFC"HARD_CEILINGSconstSource ↗
Non-disableable hard ceilings: no resolved limit may exceed these.
HARD_CEILINGS: ResourceLimitsHYPERLINK_RELATIONSHIP_TYPEconstSource ↗
The Type a hyperlink relationship declares.
HYPERLINK_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"ID_KINDSconstSource ↗
Every kind of thing the registry gives a stable identity to.
Identity is (kind, id) plus version and NEVER registration order, so two bundles contributing the same command resolve deterministically regardless of which loaded first.
ID_KINDS: readonly ["extension", "capability", "command", "query", "schema", "dependencyKey", "runtimePort", "result", "origin"]IMAGE_RELATIONSHIP_TYPEconstSource ↗
OOXML image relationship type for embedded or linked media parts.
IMAGE_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"IMAGE_RESOURCE_HARD_CEILINGSconstSource ↗
Image caps nothing can raise past. A caller's override clamps into these.
IMAGE_RESOURCE_HARD_CEILINGS: ImageResourceLimitsIMAGE_WRAP_TARGETSconstSource ↗
Every text-wrap mode a drawing may be set to, including inline.
IMAGE_WRAP_TARGETS: readonly ImageWrapTarget[]INERT_EXECUTABLE_KINDSconstSource ↗
Content that must never execute or auto-resolve: OLE objects, macros, DDE and INCLUDE* field instructions.
Rendered INERT by default rather than stripped — removing it would be a lossless-preservation failure, so it is carried and never acted on.
INERT_EXECUTABLE_KINDS: readonly ["field-dde", "field-include", "macro", "activex", "ole", "embedded-object", "executable-relationship"]LIMIT_KEYSconstSource ↗
Every limit name, for iterating the specs and asserting each has a unit and phase.
LIMIT_KEYS: (keyof ResourceLimits)[]LIMIT_SPECSconstSource ↗
Unit + enforcement phase for every resource limit.
LIMIT_SPECS: Readonly<Record<keyof ResourceLimits, LimitSpec>>MAX_CONTENT_CONTROL_NESTINGconstSource ↗
How deep controls may nest before a walk stops descending. Shared by every lane.
MAX_CONTENT_CONTROL_NESTING = 32MAX_CONTENT_CONTROLS_PER_PARTconstSource ↗
Cap on controls one walk reports, so a hostile file cannot make a read unbounded.
MAX_CONTENT_CONTROLS_PER_PART = 10000MAX_CUSTOM_NODE_LABEL_LENGTHconstSource ↗
The longest label a binding may paint. Word renders it as the control's whole content.
MAX_CUSTOM_NODE_LABEL_LENGTH = 4096MAX_CUSTOM_NODE_PAYLOAD_LENGTHconstSource ↗
The largest payload one node may carry, in UTF-16 code units.
Same figure as the read side's (parseCustomNodeData) and for the same reason: far past any legitimate chip, far short of anything that hurts. Checked on the WRITE too, so a document cannot be authored here holding a payload the reader will later refuse to parse.
MAX_CUSTOM_NODE_PAYLOAD_LENGTH: numberMAX_NOTE_REFERENCE_PARTSconstSource ↗
Cap on XML parts walked in one package-wide note-reference scan (N/N+1 gate). Soft targets are not allowed: exceeding this marks the shared budget truncated.
MAX_NOTE_REFERENCE_PARTS = 256MAX_NOTE_REFERENCE_SCANconstSource ↗
Cap on nodes visited while scanning for note references across stories.
MAX_NOTE_REFERENCE_SCAN = 20000MAX_NOTES_PER_PARTconstSource ↗
Cap on notes scanned when allocating / indexing a notes part.
MAX_NOTES_PER_PART = 10000MAX_STORY_SDT_NESTINGconstSource ↗
How deep block-level content controls may nest before the walk stops descending.
MAX_STORY_SDT_NESTING = 32MAX_SVG_SNIFF_BYTESconstSource ↗
Maximum prefix inspected for SVG root detection (exported for bounded-scan tests).
MAX_SVG_SNIFF_BYTES = 512NO_TRACKING_SETTINGSconstSource ↗
The frozen "nothing is tracked" settings — what a document with no w:trackChanges gets.
NO_TRACKING_SETTINGS: DocumentTrackingSettingsNON_CANONICAL_ORIGINSconstSource ↗
Origins that never enter authored state / history / audit / snapshot / replication.
NON_CANONICAL_ORIGINS: readonly string[]NOTE_ATOM_CHARconstSource ↗
UTF-16 placeholder for one atomic note unit in paragraphTextOf / segments.
NOTE_ATOM_CHAR = "\uFFFC"NOTE_CONTINUATION_SEPARATOR_IDconstSource ↗
Reserved id of the continuation-separator entry. Never allocated to a real note.
NOTE_CONTINUATION_SEPARATOR_ID = 0NOTE_ID_MAXconstSource ↗
Largest note id Word accepts — signed 32-bit.
NOTE_ID_MAX = 2147483647NOTE_ID_MINconstSource ↗
Signed 32-bit Word-compatible note id range (positive allocation only).
NOTE_ID_MIN = 1NOTE_SEPARATOR_IDconstSource ↗
Reserved separator / continuation ids — never allocated for normal notes.
NOTE_SEPARATOR_ID = -1OFFICE_RELATIONSHIP_NAMESPACE_URIconstSource ↗
The relationship namespace r:id lives in.
OFFICE_RELATIONSHIP_NAMESPACE_URI = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"OOXML_NODE_IDENTITY_RULESconstSource ↗
Identity policy for future immutable tree edits. This defines the boundary without implementing task 2.4 edit primitives.
OOXML_NODE_IDENTITY_RULES: OoxmlNodeIdentityRulesORIGIN_IDSconstSource ↗
Typed-origin domains (design D5 / ADR-S5). mutation.* are the canonical write origins; projection and awareness MUST NOT enter history, audit, snapshots, or replication.
ORIGIN_IDS: {
readonly mutationHuman: "dev.docx-editor.core.origin.mutation.human";
readonly mutationAgent: "dev.docx-editor.core.origin.mutation.agent";
readonly mutationRemote: "dev.docx-editor.core.origin.mutation.remote";
readonly mutationUndo: "dev.docx-editor.core.origin.mutation.undo";
readonly mutationRedo: "dev.docx-editor.core.origin.mutation.redo";
readonly mutationMigration: "dev.docx-editor.core.origin.mutation.migration";
readonly mutationRepair: "dev.docx-editor.core.origin.mutation.repair";
readonly mutationServer: "dev.docx-editor.core.origin.mutation.server";
readonly projection: "dev.docx-editor.core.origin.projection";
readonly awareness: "dev.docx-editor.core.origin.awareness";
}PAGE_BREAK_CHARconstSource ↗
UTF-16 placeholder for a page break in paragraph text projections.
PAGE_BREAK_CHAR = "\f"RESULT_IDSconstSource ↗
Result taxonomy (design D8 / task 7.8). A transport/protocol failure that prevents a valid envelope is a typed exception, not a member here.
RESULT_IDS: {
readonly applied: "dev.docx-editor.core.result.applied";
readonly validation: "dev.docx-editor.core.result.validation";
readonly conflict: "dev.docx-editor.core.result.conflict";
readonly resource: "dev.docx-editor.core.result.resource";
readonly authorization: "dev.docx-editor.core.result.authorization";
readonly aborted: "dev.docx-editor.core.result.aborted";
}RUNTIME_PORT_IDSconstSource ↗
Runtime ports (extensions-and-runtime-ports spec; design D9).
RUNTIME_PORT_IDS: {
readonly fonts: "dev.docx-editor.core.port.fonts";
readonly shaping: "dev.docx-editor.core.port.shaping";
readonly images: "dev.docx-editor.core.port.images";
readonly clock: "dev.docx-editor.core.port.clock";
readonly identity: "dev.docx-editor.core.port.identity";
readonly persistence: "dev.docx-editor.core.port.persistence";
readonly transport: "dev.docx-editor.core.port.transport";
readonly scheduling: "dev.docx-editor.core.port.scheduling";
readonly audit: "dev.docx-editor.core.port.audit";
readonly authorization: "dev.docx-editor.core.port.authorization";
readonly resourceAccounting: "dev.docx-editor.core.port.resource-accounting";
readonly cancellation: "dev.docx-editor.core.port.cancellation";
readonly externalResourceConsent: "dev.docx-editor.core.port.external-resource-consent";
}SEARCH_MATCH_LIMITconstSource ↗
Most matches one search returns. A single-character query against a long document would otherwise allocate an entry per character; the scan stops here instead. A caller showing a count treats a full result as "at least this many".
SEARCH_MATCH_LIMIT = 2000SEARCH_QUERY_MAXconstSource ↗
Longest accepted query. A query is host input rather than file content, but the scan is proportional to it and there is no legitimate find phrase this long.
SEARCH_QUERY_MAX = 256TABLE_BORDER_STYLESconstSource ↗
Allowlisted OOXML table border line styles — store/layout authority.
TABLE_BORDER_STYLES: readonly ["single", "dashed", "dotted", "double", "triple", "thick"]TOC_LEVEL_INDENT_TWIPSconstSource ↗
Left-indent step between TOC levels, in twips (matches scripts/demo-doc/toc-block.xml).
TOC_LEVEL_INDENT_TWIPS = 240TOC_MAX_BOOKMARKS_PER_REFRESHconstSource ↗
Most bookmarks minted during one TOC refresh.
TOC_MAX_BOOKMARKS_PER_REFRESH = 512TOC_MAX_ENTRIESconstSource ↗
Most entries one generated table of contents may hold.
TOC_MAX_ENTRIES = 512TOC_MAX_FIELD_NESTINGconstSource ↗
Deepest nested field instruction followed. Caps recursion on file-supplied structure.
TOC_MAX_FIELD_NESTING = 4TOC_MAX_INSTRUCTION_CHARSconstSource ↗
Longest TOC field instruction read. Instructions come from a file; the parse is bounded.
TOC_MAX_INSTRUCTION_CHARS = 256TOC_MAX_PAGE_PASSESconstSource ↗
Most layout passes a TOC refresh runs before settling.
Page numbers change the TOC's own height, which changes page numbers — bounded so a non-converging document stops rather than looping.
TOC_MAX_PAGE_PASSES = 3TREE_DOC_OP_KINDSconstSource ↗
Every [TreeDocOpKind](TreeDocOpKind), for validation and exhaustiveness checks.
TREE_DOC_OP_KINDS: readonly ["insertText", "deleteText", "setParagraphMarkRevision", "proposeParagraphMerge", "insertCommentMarker", "acceptRevision", "rejectRevision", "acceptAllRevisions", "rejectAllRevisions", "insertTab", "insertHardBreak", "insertPageBreak", "insertPageField", "setListLevel", "setListNumbering", "setParagraphMarkProperties", "splitParagraph", "splitParagraphMany", "joinParagraphs", "setRunProperties", "setParagraphProperties", "setSectionProperties", "setSectionMark", "insertHyperlink", "setHyperlinkTarget", "removeHyperlink", "setContentControlValue", "removeContentControl", "insertInlineContentControl", "addRepeatingSectionItem", "removeRepeatingSectionItem", "deleteBlock", "insertTable", "insertTableRow", "deleteTableRow", "insertTableColumn", "deleteTableColumn", "setTableColumnWidths", "setTableRightEdgeWidth", "setTableRowHeight", "setTableCellBorders", "setTableCellFill", "setTableCellVerticalAlignment", "createHeaderFooter", "deleteHeaderFooter", "linkToPrevious", "unlinkFromPrevious", "setSectionFurnitureOptions", "insertNote", "deleteNote", "convertNote", "convertAllNotes", "setNoteProperties", "setContentControlProperties", "insertContentControl", "insertDrawing", "replaceDrawingResource", "deleteDrawing", "resizeDrawing", "cropDrawing", "positionDrawing", "setDrawingWrap", "setDrawingMetadata", "setDrawingLocks", "transformDrawing", "insertToc", "replaceTocResult", "rewriteTocPageNumbers"]W15_NAMESPACE_URIconstSource ↗
The w15 namespace: commentsExtended.xml — thread parent and resolved state.
W15_NAMESPACE_URI = "http://schemas.microsoft.com/office/word/2012/wordml"WML_NAMESPACE_URIconstSource ↗
The WordprocessingML main namespace — the w: prefix in every word/document.xml.
WML_NAMESPACE_URI = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"XML_NAMESPACE_URIconstSource ↗
The reserved xml: namespace, which carries xml:space.
XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace"XMLNS_NAMESPACE_URIconstSource ↗
The reserved xmlns: namespace that namespace declarations themselves live in.
XMLNS_NAMESPACE_URI = "http://www.w3.org/2000/xmlns/"