@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
MemberTypeSummary
(constructor)Constructs a new instance of the `BoundedCounter` class
addAdd `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.
canAddWhether adding `n` would be accepted, without mutating.
currentnumber
labelstring
limitnumber
release
remainingnumberRemaining 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
MemberTypeSummary
(constructor)Constructs a new instance of the `Budget` class
availablenumber
capacitynumber
childCarve a child budget of `capacity` out of this budget's headroom.
disposeRelease 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.
inUsenumber
isDisposedboolean
labelstring
onReleaseRegister cleanup for a spill file, worker, or queue tied to this budget.
reserveReserve `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
MemberTypeSummary
(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
MemberTypeSummary
cancel
derivedOnlybooleanCancelled after publication - full rollback is no longer possible.
isCancelledboolean
isPublishedboolean
markPublishedMark canonical publication — the point of no return.
phaseCancellationPhase
tokenCancellationToken

CancellationErrorclassSource ↗

Thrown from a checkpoint() when the operation has been cancelled.

declare class CancellationError extends Error
MemberTypeSummary
(constructor)Constructs a new instance of the `CancellationError` class
derivedOnlybooleanTrue 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
MemberTypeSummary
(constructor)Constructs a new instance of the `DangerousKeyError` class
keystring
pathstring

DeterministicClockclassSource ↗

Deterministic clock: starts at start and advances by step each call.

declare class DeterministicClock implements ClockPort
MemberTypeSummary
(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
MemberTypeSummary
(constructor)Constructs a new instance of the `DeterministicMemoryMeter` class
allocate
currentBytesnumber
free
peakBytesnumber
resetRelease 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
MemberTypeSummary
(constructor)Constructs a new instance of the `LimitExceededError` class
attemptednumber
labelstring
limitnumber

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
MemberTypeSummary
availablePortsThe provided port ids (for bridging to registry.resolve availablePorts).
clock
has
identity
missingAssert every id in `portIds` is present; returns the missing ones (empty if all present).
provide
resolveResolve 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
MemberTypeSummary
(constructor)Constructs a new instance of the `PortResolutionError` class
portIdstring

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
MemberTypeSummary
(constructor)Constructs a new instance of the `PrefixAllocator` class
bindingsThe 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
MemberTypeSummary
(constructor)Constructs a new instance of the `RegistryError` class
codeRegistryErrorCode
responsiblereadonly string[]Stable identities responsible for the failure (extensions, ids).

SequentialIdentityclassSource ↗

Sequential identity for tests and deterministic fixtures.

declare class SequentialIdentity implements IdentityPort
MemberTypeSummary
(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
MemberTypeSummary
(constructor)Open a store over a package, editing the named story part.
beginCompositionOpen one history entry for an IME composition.
cancelCompositionCancel 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.
canRedoboolean
canUndoboolean
checkpointSnapshot 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.
compositionActiveboolean
endCompositionClose the composition, recording its entry only if anything actually committed.
graftPackageReplace the package OUTSIDE the transaction and history lanes.
historyDepthnumberRetained entries — the unit `undo()` reverses, so tests can assert grouping.
packageOoxmlPackageEvery part, including the ones a multi-part transaction wrote.
partOoxmlPartThe story part being edited. Unchanged for every caller that predates the widening.
redo
replacePartReplace the current part without recording history, but advance the revision so revision-keyed projections cannot survive a package snapshot install.
restoreCheckpointFull restore — part, revision, history stacks, and composition.
restoreHistoryStacksRestore 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.
revisionnumber
selectionForRedoThe selection to restore for the entry `redo()` would reapply next.
selectionForUndoThe selection to restore for the entry `undo()` would reverse next.
setStoryRefStamp 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
transactRun 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
MemberTypeSummary
(constructor)Constructs a new instance of the `TreePackageStore` class
adoptPackageUnitRecord a write that spanned SEVERAL parts as one package undo unit.
applyImagePropertiesProperties batch with hyperlink relationship create/update/remove in one package unit.
applyLifecycleOpCommit one furniture or note lifecycle op as a single ModelChange / undo unit that restores the entire package atomically (parts, rels, content-types, settings).
beginComposition
bodyStoreBody store — independent revision/index from every HF store.
cancelComposition
canRedoboolean
canUndoboolean
compositionSessionOpenWhether a package-wide IME composition session is open on any story.
currentPackageThe current package with every opened story store's part merged in. Pure snapshot of authority; callers must not mutate.
deleteImageDelete a picture drawing and collect orphaned media in one package undo unit.
embedExternalImageFetch external bytes explicitly and embed them; no fetch on open/load.
endComposition
insertImageInsert a validated raster image as one package undo unit (task 12).
installPackageSnapshotInstall a full package snapshot (public seam for post-fetch cleanup).
lastModelChangeTreeModelChange | null
openedStoryCountHow many story stores are open (body counts as one).
packageRevisionnumber
partForCurrent part for a scope, or null when the target is refused.
promoteStoryTransactionToPackageUnitPromote a story transaction that wrote package bytes to one package undo pointer. Used by image intents and note-reference cascade.
publishStoryWritePublish a story transaction the coordinator did not run.
redo
replaceImageReplace a picture drawing's embedded media in one package undo unit.
replacePackageShellReplace the package shell while preserving opened stores. Used when numbering / content-types mutate the package outside story trees.
resolveStoryResolve 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.
revisionForPer-story revision, or null when the target is refused.
selectionForRedo
selectionForUndo
subscribe
transactCommit 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
MemberTypeSummary
anchorCommentAnchorRequest
authorstringRequired by `CT_TrackChange`. A comment without one writes invalid XML.
date?stringISO-8601. Absent writes no `@w:date`, because inventing one is a content change.
initials?string
replyToCommentId?stringThe comment this replies to. Its thread link is written to `commentsExtended.xml`.
textstring

AnchorSnapshotinterfaceSource ↗

Where anchors sat after a step — how a fixture proves positions survived an edit.

interface AnchorSnapshot
MemberTypeSummary
affinity'before' | 'after'
anchorIdstring
blockstring
storystring

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
MemberTypeSummary
formatRunIdsreadonly string[]Runs that own displayed result formatting (may differ from `runId`).
kind'complex' | 'simple'
nodeOoxmlNodeAddressable segment node (begin `fldChar` or `fldSimple`).
removeNodeIdsreadonly string[]
runIdstringRun 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
MemberTypeSummary
kind'noteReference' | 'noteRef' | 'separator' | 'continuationSeparator'
nodeOoxmlNode
removeNodeIdsreadonly string[]
runIdstring

AuditPortinterfaceSource ↗

Redacted observability sink (raw text never enters here — design D5).

interface AuditPort
MemberTypeSummary
record

AuthoredNotePropertiesinterfaceSource ↗

Authored subset — only keys present in the file appear.

interface AuthoredNoteProperties
MemberTypeSummary
numFmt?string
numRestart?string
numStart?number
pos?string

AuthorizationPortinterfaceSource ↗

Read/write/export authorization decisions.

interface AuthorizationPort
MemberTypeSummary
authorize

BookmarkAnchorinterfaceSource ↗

One bookmark's name and the range its marker pair currently encloses.

interface BookmarkAnchor
MemberTypeSummary
namestring
offsetnumberUTF-16 offset within that paragraph, in `paragraphTextOf`'s vocabulary.
paragraphIdstringCanonical node id of the paragraph the marker sits in.

CancellationPortinterfaceSource ↗

Cancellation source for the current operation.

interface CancellationPort
MemberTypeSummary
tokenCancellationToken

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
MemberTypeSummary
checkpointThrows CancellationError if cancelled; call at declared checkpoint intervals.
derivedOnlybooleanTrue only when cancelled AND the commit is already published.
isCancelledboolean
phaseCancellationPhase

CapabilityIdinterfaceSource ↗

A validated (kind, id, version) triple — the registry's unit of identity.

interface CapabilityId
MemberTypeSummary
idstring
kindIdKind
versionstring

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
MemberTypeSummary
afterBudget?NoteReferenceScanBudget
beforeBudget?NoteReferenceScanBudgetIndependent 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
MemberTypeSummary
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
MemberTypeSummary
commentIdstring
endCommentPosition
orphanedboolean
partNamestringCanonical name of the part the range lives in, so a header comment is attributable.
startCommentPosition

CommentAnchorRequestinterfaceSource ↗

Where a comment is anchored, in the model offset space of one story.

interface CommentAnchorRequest
MemberTypeSummary
endnumberMay sit in the same paragraph or a later one; `endParagraphId` names it when it differs.
endParagraphId?string
paragraphIdstring
startnumber

CommentPositioninterfaceSource ↗

A position in one story: a paragraph node id plus a UTF-16 offset inside it.

interface CommentPosition
MemberTypeSummary
offsetnumber
paragraphIdstring

CommentRecordinterfaceSource ↗

One comment as authored in word/comments.xml.

interface CommentRecord
MemberTypeSummary
authorstring
blocksreadonly OoxmlElement[]Body paragraphs, as tree nodes, so the surface renders measured text rather than a string.
date?string
idstring
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
MemberTypeSummary
doneboolean
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
MemberTypeSummary
ephemerareadonly string[]Object keys excluded from canonical-exact comparison (declared ephemera).
idstring
modeComparatorMode
notestring

ComparisonResultinterfaceSource ↗

Whether two artifacts matched, and where they diverged when they did not.

interface ComparisonResult
MemberTypeSummary
equalboolean
left?stringCanonical 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
MemberTypeSummary
documentIdstring
formatVersion1
snapshots?readonly EncodedEnvelope[]
sourceFixtureSource
stepsreadonly 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
MemberTypeSummary
checkedboolean
checkedState?ContentControlCheckboxState
uncheckedState?ContentControlCheckboxState

ContentControlCheckboxStateinterfaceSource ↗

One of a checkbox's two glyphs: the font and code point it is drawn with.

interface ContentControlCheckboxState
MemberTypeSummary
font?string
valuestringThe `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
MemberTypeSummary
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
MemberTypeSummary
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
MemberTypeSummary
ancestorsreadonly OoxmlContentControlNode[]Enclosing controls, outermost first. Empty at depth 0.
depthnumber0 for a top-level control; the nesting depth otherwise.
nodeOoxmlContentControlNode

ContentControlListIteminterfaceSource ↗

One declared option of a dropdown or combo box: its display text and its stored value.

interface ContentControlListItem
MemberTypeSummary
displayTextstring
valuestring

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
MemberTypeSummary
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
listItemsreadonly ContentControlListItem[]Items a dropdown or combo box offers. Empty for every other type.
lockContentControlLock
multiLine?boolean
placeholderDocPart?stringThe glossary entry named by `w:placeholder/w:docPart`. Preserved, never loaded.
showingPlaceholderboolean
tabIndex?number
tag?string
temporaryboolean
typeContentControlKind

ContentIteminterfaceSource ↗

One item a scrub pass considers: its kind, and where in the package it sits.

interface ContentItem
MemberTypeSummary
idstring
kindstring

ContentTypeIndexinterfaceSource ↗

The resolved lookup: Override by case-folded part name, Default by case-insensitive extension.

interface ContentTypeIndex
MemberTypeSummary
defaultsReadonlyMap<string, string>ext key - single MIME (identical duplicates collapsed).
overridesReadonlyMap<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
MemberTypeSummary
defaultsreadonly DefaultRecord[]
overridesreadonly OverrideRecord[]

ContributioninterfaceSource ↗

One thing a bundle contributes: a command, a query, a schema, a port, keyed by (kind, id).

interface Contribution
MemberTypeSummary
idstring
kindExclude<IdKind, 'extension' | 'origin' | 'result'>
payload?unknown
replaceable?ReplacementPolicyPolicy 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.
versionstring

CreateImageResourceCacheOptionsinterfaceSource ↗

How the image cache decodes, and what it will spend doing so.

interface CreateImageResourceCacheOptions
MemberTypeSummary
decodePortImageDecodePort
limits?Partial<ImageResourceLimits>

CustomNodeBindinginterfaceSource ↗

The three attributes a w:dataBinding carries.

interface CustomNodeBinding
MemberTypeSummary
prefixMappingsstring
storeItemIdstring
xpathstring

CustomNodeExportRequestinterfaceSource ↗

How [withExportedCustomNodes](withExportedCustomNodes) decides, and which stores it may tidy afterwards.

interface CustomNodeExportRequest
MemberTypeSummary
decide(tag: string) => CustomNodeExportPolicyThe fate of a control carrying this `w:tag`. A control with no tag is never touched.
namespacesreadonly string[]Payload namespaces the caller CLAIMS.
storyPartNamestringThe 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
MemberTypeSummary
datastringThe payload as authored. JSON by convention, unparsed here.
labelstringThe text Word paints the control from.
nodeIdstringThe 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
MemberTypeSummary
datastringThe payload, serialized. JSON by convention; never parsed here.
labelstringThe text the control shows. Word paints this from the store, so an empty one is an empty chip.
namespaceUristringNamespace of the store's root element — what identifies one store among several.
nodeIdstringThe node's own id, which the binding's xpath quotes.
rootLocalNamestringLocal 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
MemberTypeSummary
itemIdstring`ds:itemID`, braced and upper-case, as `w:storeItemID` must spell it.
namespaceUristringNamespace URI of the payload root, which is what identifies one store among several.
partNamestringCanonical part name, e.g. `/customXml/item1.xml`.
propsPartNamestringPart name of its properties, e.g. `/customXml/itemProps1.xml`.

CustomXmlDataPartResultinterfaceSource ↗

What [withCustomXmlDataPart](withCustomXmlDataPart) answers.

interface CustomXmlDataPartResult
MemberTypeSummary
partCustomXmlDataPart | nullNull when the part could not be authored; the package then comes back unchanged.
pkgOoxmlPackage

CustomXmlNodeinterfaceSource ↗

One node in a store: its id, the bound text, and the payload beside it.

interface CustomXmlNode
MemberTypeSummary
datastringPayload as authored, JSON by convention and unparsed here. Untrusted file input.
idstring
labelstringText a `w:dataBinding` resolves to. Untrusted file input.

DefaultRecordinterfaceSource ↗

One <Default>: a file extension mapped to a content type.

interface DefaultRecord
MemberTypeSummary
contentTypestring
extensionstring
ordernumber

DetectedTocinterfaceSource ↗

A table of contents found in a document, whether wrapped in an SDT or a bare field.

interface DetectedToc
MemberTypeSummary
beginNodeIdstring
beginParagraphIdstring
containerIdstringDirect parent whose paragraph children delimit the cached result.
contentControlId?string
endParagraphIdstring
idstringEnclosing control id when it identifies one TOC, otherwise the begin fldChar id.
instructionTocInstruction
resultParagraphIdsreadonly string[]

DocumentTrackingSettingsinterfaceSource ↗

What the document asks for. Every field defaults to "the document said nothing".

interface DocumentTrackingSettings
MemberTypeSummary
doNotTrackFormattingboolean`w:doNotTrackFormatting` — apply formatting without recording a `w:rPrChange`.
doNotTrackMovesboolean`w:doNotTrackMoves` — write a move as a delete and an insert.
restrictedToTrackedChangesboolean`w:documentProtection/@w:edit="trackedChanges"` — tracking may not be turned OFF.
trackRevisionsboolean`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
MemberTypeSummary
changeAspectboolean
moveboolean
resizeboolean
selectboolean

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
MemberTypeSummary
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
MemberTypeSummary
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
MemberTypeSummary
bytesUint8ArrayDeobfuscated bytes, ready to be offered to a font validator.
familystringThe family as the document names it. Not validated against anything.
partNamestringThe part they came from, for diagnostics.
styleFontStyleKey

EncodedEnvelopeinterfaceSource ↗

Opaque encoded backend bytes (snapshot or replication update).

interface EncodedEnvelope
MemberTypeSummary
byteLengthnumber
bytesHexstringHex-encoded opaque bytes; length MUST equal byteLength.
documentIdstring
kind'snapshot' | 'update'
protocolVersionnumber
schemaVersionnumber

EnsuredHyperlinkRelationshipinterfaceSource ↗

The package with a hyperlink relationship guaranteed present, and that relationship's id.

interface EnsuredHyperlinkRelationship
MemberTypeSummary
pkgOoxmlPackage
relationshipIdstring

ExternalResourceConsentPortinterfaceSource ↗

Explicit consent gate for any remote/external resource (no zero-click fetch).

interface ExternalResourceConsentPort
MemberTypeSummary
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
MemberTypeSummary
conflicts?readonly string[]
contributionsreadonly Contribution[]
dependencies?readonly string[]
idstring
requiredPorts?readonly string[]
versionstring

FixtureExpectationinterfaceSource ↗

What one step must produce: its outcome, its change summary, and its authored-state hash.

interface FixtureExpectation
MemberTypeSummary
anchors?readonly AnchorSnapshot[]
authoredStateHash?string16-hex authored-state fingerprint (comparator 0.4).
committedRevision?numberPresent iff outcome === 'applied'; MUST be baseRevision.
modelChange?ModelChangeSummary
outcomeFixtureOutcome
outputHash?string

FixtureStepinterfaceSource ↗

One recorded operation and what it was expected to do.

interface FixtureStep
MemberTypeSummary
baseRevisionnumber
expectFixtureExpectation
opsreadonly unknown[]Opaque DocOp payloads (schema owned by section 4).
originstring

FontPortinterfaceSource ↗

Where font bytes come from. Opaque marker until its milestone.

interface FontPort
MemberTypeSummary
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
MemberTypeSummary
evenAndOddHeadersboolean`w:evenAndOddHeaders` in settings.xml — without it the `even` variant is ignored.
footersReadonlyMap<HeaderFooterVariant, OoxmlPart>
headersReadonlyMap<HeaderFooterVariant, OoxmlPart>
titlePagebooleanWhether this section enables first-page header/footer furniture (`w:titlePg`).

HeaderFooterSectionResolutioninterfaceSource ↗

Per-section resolution including declared-vs-inherited metadata.

interface HeaderFooterSectionResolution
MemberTypeSummary
evenAndOddHeadersboolean
footersReadonlyMap<HeaderFooterVariant, HeaderFooterSlotMeta>
headersReadonlyMap<HeaderFooterVariant, HeaderFooterSlotMeta>
titlePageboolean

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
MemberTypeSummary
inheritedboolean
partOoxmlPart
partNamestring
rIdstring

HyperlinkTargetinterfaceSource ↗

A resolved hyperlink: its kind, its target, and the tooltip Word shows on hover.

interface HyperlinkTarget
MemberTypeSummary
anchor?string`w:anchor`, for an internal link.
authoredstringThe 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.
hrefstring | nullThe 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.
kindHyperlinkKind
relationshipId?stringThe 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
MemberTypeSummary
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
MemberTypeSummary
convertPreservedOptional 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
MemberTypeSummary
kind'image'

ImageResourceLimitsinterfaceSource ↗

Trust-boundary caps specific to image decoding and embedding.

interface ImageResourceLimits
MemberTypeSummary
maxDecodedBytesnumber
maxDimensionnumber
maxEncodedBytesnumber
maxExternalRedirectsnumber
maxPixelsnumber
maxPolygonPointsnumber

ImageResourceLookupinterfaceSource ↗

Resolves a relationship id to a validated image resource, or reports why it could not.

interface ImageResourceLookup
MemberTypeSummary
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
MemberTypeSummary
controlIdstring
endnumber
startnumber

InsertCustomNodeWriteinterfaceSource ↗

Where the control goes, what it says, and the payload it carries.

interface InsertCustomNodeWrite
MemberTypeSummary
alias?string
lock?'sdtLocked' | 'sdtContentLocked' | 'contentLocked'Defaults to none. Callers that want Word's own "cannot type into it" pass `contentLocked`.
offsetnumber
paragraphIdstring
payload?CustomNodePayloadWriteOmitted authors an ordinary tagged control with no store — the pre-payload behaviour.
replaceControlId?stringRewrite an existing control: it and the payload it bound go first, in this transaction.
replaceUntil?numberWrap rather than insert: the text from `offset` to here is removed first.
tagstring
textstring

LimitSpecinterfaceSource ↗

One limit's unit and enforcement phase — the metadata that makes limits testable uniformly.

interface LimitSpec
MemberTypeSummary
phaseEnforcementPhase
unitLimitUnit

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
MemberTypeSummary
idstring
kindstring
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
MemberTypeSummary
dependencyKeysreadonly string[]
dirtyreadonly string[]
fromRevisionnumber
originstring
toRevisionnumber

NoteLifecycleOptionsinterfaceSource ↗

Attribution and limits applied to one note lifecycle op.

interface NoteLifecycleOptions
MemberTypeSummary
scanBudget?NoteReferenceScanBudgetShared 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
MemberTypeSummary
atomOffsetnumberCanonical UTF-16 atom offset within [paragraphId](paragraphId) (U+FFFC model).
customMarkFollowsboolean
nodeIdstring
noteIdnumber
noteKindNoteKind
paragraphIdstring
partNamestringCanonical part name that owns this reference.

NoteReferenceScanBudgetinterfaceSource ↗

Mutable visited-node + part budget shared across parts / package snapshots.

interface NoteReferenceScanBudget
MemberTypeSummary
maxPartsnumber
maxVisitednumber
partsnumber
truncatedbooleanSet when a walk stops before finishing because a cap was hit.
visitednumber

OffsetSpaninterfaceSource ↗

Half-open [start, end) of one node in its paragraph's model offset space.

interface OffsetSpan
MemberTypeSummary
endnumber
startnumber

OoxmlBodyNodeinterfaceSource ↗

w:body — the main story's block content.

interface OoxmlBodyNode extends OoxmlElementBase<readonly (OoxmlParagraphNode | OoxmlTableNode | OoxmlContentControlNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'body'
localName'body'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlBookmarkEndNodeinterfaceSource ↗

w:bookmarkEnd — the closing point anchor (@w:id), zero-length like its start.

interface OoxmlBookmarkEndNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'bookmarkEnd'
localName'bookmarkEnd'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'bookmarkStart'
localName'bookmarkStart'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlContentControlCalendarNodeinterfaceSource ↗

w:calendar — which calendar system a date picker uses (Gregorian, Hijri, …).

interface OoxmlContentControlCalendarNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]>
MemberTypeSummary
kind'contentControlCalendar'
localName'calendar'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'contentControlCheckbox'
localName'checkbox'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'contentControlChecked'
localName'checked'
namespaceUritypeof W14_NAMESPACE_URI

OoxmlContentControlCheckedStateNodeinterfaceSource ↗

w14:checkedState — the font and code point drawn when a checkbox is checked.

interface OoxmlContentControlCheckedStateNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'contentControlCheckedState'
localName'checkedState'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'contentControlComboBox'
localName'comboBox'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'contentControlContent'
localName'sdtContent'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'contentControlDataBinding'
localName'dataBinding'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlContentControlDateFormatNodeinterfaceSource ↗

w:dateFormat — the picture string a date picker formats its value with.

interface OoxmlContentControlDateFormatNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]>
MemberTypeSummary
kind'contentControlDateFormat'
localName'dateFormat'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'contentControlDate'
localName'date'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlContentControlDropDownListNodeinterfaceSource ↗

w:dropDownList@w:lastValue plus typed w:listItem children.

interface OoxmlContentControlDropDownListNode extends OoxmlElementBase<readonly (OoxmlContentControlListItemNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'contentControlDropDownList'
localName'dropDownList'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlContentControlEndPropertiesNodeinterfaceSource ↗

w:sdtEndPr — end-character properties; children are w:rPr or generic.

interface OoxmlContentControlEndPropertiesNode extends OoxmlElementBase<readonly (OoxmlRunPropertiesNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'contentControlEndProperties'
localName'sdtEndPr'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlContentControlLidNodeinterfaceSource ↗

w:lid — the language id a date picker parses and formats under.

interface OoxmlContentControlLidNode extends OoxmlElementBase<readonly [], readonly (OoxmlKnownNodeAttribute | OoxmlWmlValAttribute)[]>
MemberTypeSummary
kind'contentControlLid'
localName'lid'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlContentControlListItemNodeinterfaceSource ↗

w:listItem@w:displayText / @w:value as preserved attributes (not w:val).

interface OoxmlContentControlListItemNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'contentControlListItem'
localName'listItem'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'contentControl'
localName'sdt'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'contentControlProperties'
localName'sdtPr'
namespaceUritypeof 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)[]>
MemberTypeSummary
kind'contentControlStoreMappedDataAs'
localName'storeMappedDataAs'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlContentControlTextNodeinterfaceSource ↗

w:text (CT_SdtText) — distinct from w:t (kind: 'text'). @w:multiLine preserved.

interface OoxmlContentControlTextNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'contentControlText'
localName'text'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'contentControlUncheckedState'
localName'uncheckedState'
namespaceUritypeof W14_NAMESPACE_URI

OoxmlContinuationSeparatorNodeinterfaceSource ↗

Run-inner continuation separator (w:continuationSeparator). One UTF-16 atom.

interface OoxmlContinuationSeparatorNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'continuationSeparator'
localName'continuationSeparator'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlDocumentNodeinterfaceSource ↗

w:document — the root of a main document part.

interface OoxmlDocumentNode extends OoxmlElementBase<readonly (OoxmlBodyNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'document'
localName'document'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlEndnotesNodeinterfaceSource ↗

Endnotes part root (w:endnotes). Same content model as [OoxmlFootnotesNode](OoxmlFootnotesNode).

interface OoxmlEndnotesNode extends OoxmlElementBase<readonly (OoxmlNoteNode | OoxmlGenericElementNode)[], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'endnotes'
localName'endnotes'
namespaceUritypeof 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
MemberTypeSummary
idstring
ownerPartstring
rawTargetstring
sinkSafebooleanFalse when the target is not a safe sink (javascript:, file:, ...). Still not fetched.
typestring

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[]>
MemberTypeSummary
kind'fldChar'
localName'fldChar'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'fldSimple'
localName'fldSimple'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'footnotes'
localName'footnotes'
namespaceUritypeof 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[]>
MemberTypeSummary
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
MemberTypeSummary
kind'genericExtension'

OoxmlHardBreakNodeinterfaceSource ↗

w:br — a line, column or page break inside a run.

interface OoxmlHardBreakNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'hardBreak'
localName'br'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'hyperlink'
localName'hyperlink'
namespaceUritypeof 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
MemberTypeSummary
paragraphsReadonlyMap<string, ParagraphIndexEntry>Every paragraph across every story, keyed by node id.
relationshipsReadonlyMap<string, readonly RelationshipRecord[]>
revisionnumberThe tree revision these projections were derived from.
storiesReadonlyMap<string, StoryIndexEntry>Body story first, then any other story parts, keyed by part name.
stylesReadonlyMap<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[]>
MemberTypeSummary
kind'instrText'
localName'instrText'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlInvariantIssueinterfaceSource ↗

One invariant violation, located by structural path and node id.

interface OoxmlInvariantIssue
MemberTypeSummary
codeOoxmlInvariantIssueCode
nodeId?string
pathstring

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
MemberTypeSummary
namespaceUristring
prefixstring

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
MemberTypeSummary
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[]>
MemberTypeSummary
kind'note'
localName'footnote' | 'endnote'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'noteReference'
localName'footnoteReference' | 'endnoteReference'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'noteRef'
localName'footnoteRef' | 'endnoteRef'
namespaceUritypeof 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
MemberTypeSummary
contentTypesContentTypeIndex
externalTargetsreadonly OoxmlExternalTarget[]
mainDocumentPartstringCanonical name of the part the root `officeDocument` relationship points at.
partBytesReadonlyMap<string, Uint8Array>Raw bytes of every entry, including the non-XML parts that have no tree.
partsReadonlyMap<string, OoxmlPart>Canonical trees, keyed by canonical part name. Non-XML parts are absent by design.
relationshipsReadonlyMap<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
MemberTypeSummary
maxRelationships?numberCap on relationship records across every rels part.
maxXmlParts?numberCap 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[]>
MemberTypeSummary
kind'paragraph'
localName'p'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'paragraphProperties'
localName'pPr'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlPartinterfaceSource ↗

One XML part of the package, parsed into a canonical tree.

interface OoxmlPart
MemberTypeSummary
contentTypestring
idstring
namestringCanonical part name, e.g. `/word/document.xml`.
rootOoxmlElement

OoxmlPartMetadatainterfaceSource ↗

A part's identity without its tree — enough to enumerate a package cheaply.

interface OoxmlPartMetadata
MemberTypeSummary
contentTypestring
namestring

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
MemberTypeSummary
attributes?Readonly<Record<string, string>>
localNamestring

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[]>
MemberTypeSummary
kind'run'
localName'r'
namespaceUritypeof 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[]>
MemberTypeSummary
kind'runProperties'
localName'rPr'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlSeparatorNodeinterfaceSource ↗

Run-inner separator rule (w:separator). One UTF-16 atom.

interface OoxmlSeparatorNode extends OoxmlElementBase<readonly [], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'separator'
localName'separator'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlStoryRootinterfaceSource ↗

One story root and the blocks under it, with block-level SDTs already flattened.

interface OoxmlStoryRoot
MemberTypeSummary
kindOoxmlStoryKind
rootOoxmlNodeThe `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[]>
MemberTypeSummary
kind'tab'
localName'tab'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlTextElementNodeinterfaceSource ↗

w:t — the element holding a run's literal characters.

interface OoxmlTextElementNode extends OoxmlElementBase<readonly OoxmlTextNode[], readonly OoxmlKnownNodeAttribute[]>
MemberTypeSummary
kind'text'
localName't'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlTextNodeinterfaceSource ↗

A literal text value. The only node kind with no children and no attributes.

interface OoxmlTextNode
MemberTypeSummary
idOoxmlNodeId
kind'textValue'
valuestring

OoxmlWmlValAttributeinterfaceSource ↗

w:val — the attribute nearly every WordprocessingML property carries its value in.

interface OoxmlWmlValAttribute extends OoxmlAttributeBase
MemberTypeSummary
kind'wmlVal'
localName'val'
namespaceUritypeof WML_NAMESPACE_URI

OoxmlXmlSpaceAttributeinterfaceSource ↗

xml:space, which decides whether a run's leading and trailing whitespace survives.

interface OoxmlXmlSpaceAttribute extends OoxmlAttributeBase
MemberTypeSummary
kind'xmlSpace'
localName'space'
namespaceUritypeof 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
MemberTypeSummary
budgetBudget
cancellationCancellationController
configReadonly<Record<string, unknown>>
idstring
limitsResourceLimits
portsPortRegistry

OperationInitinterfaceSource ↗

What one operation is started with. Only ports is required.

interface OperationInit
MemberTypeSummary
capacity?numberRoot budget capacity in abstract units (default: the byte decompression limit).
config?Readonly<Record<string, unknown>>
id?stringOperation identity (from IdentityPort in production); defaulted for tests.
limits?Partial<ResourceLimits>
portsPortRegistry

OverrideRecordinterfaceSource ↗

One <Override>: a specific part name mapped to a content type. Beats any Default.

interface OverrideRecord
MemberTypeSummary
contentTypestring
ordernumber
partNamestring

PackageInvariantIssueinterfaceSource ↗

One package invariant violation, located by part name and relationship id.

interface PackageInvariantIssue
MemberTypeSummary
codePackageInvariantCode
ownerPart?stringFor a dangling relationship, the owner that points at nothing.
partNamestringThe 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
MemberTypeSummary
genericStructurereadonly string[]Fingerprints of every generic (unknown) subtree, in document order.
ordinalnumberOrdinal 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.
paragraphPropertiesreadonly string[]Accepted paragraph properties, as sorted tokens including nested children.
paraIdstring | 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.
pathstringWhere 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.
runPropertiesreadonly (readonly string[])[]Per-run accepted properties, in run order.
textstringText 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
MemberTypeSummary
nodeIdstringCanonical tree node id — the stable identity operations address.
ordinalnumberPosition among the story's paragraphs, in document order.
runIdsreadonly string[]Node ids of the paragraph's runs, in order.
textstringConcatenated 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
MemberTypeSummary
lengthnumberThe paragraph's own length, identical to [paragraphLength](paragraphLength).
lengthOfA node's model length: `end - start` of its span, and 0 when it has none.
segmentsreadonly Segment[]
spanOfWhere 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
MemberTypeSummary
kind'persistence'

ReadEmbeddedFontsOptionsinterfaceSource ↗

Limits and instrumentation for reading embedded fonts out of a package.

interface ReadEmbeddedFontsOptions
MemberTypeSummary
maxFontBytes?numberRefuse a font part larger than this. Defaults to 16 MB.
maxFonts?numberRefuse 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
MemberTypeSummary
idstring
ordernumber
ownerPartstring
rawTargetstring
targetModeTargetMode
typestring

ReplayOutcomeinterfaceSource ↗

The outcome a store reports for one replayed step.

interface ReplayOutcome
MemberTypeSummary
authoredState?unknownCanonical authored-state value AFTER the step (hashed via comparator 0.4).
committedRevision?number
outcomeFixtureOutcome

ReplayReportinterfaceSource ↗

What replaying a fixture produced: per-step outcomes and where they diverged.

interface ReplayReport
MemberTypeSummary
mismatchesreadonly string[]
okboolean

ReplayStoreinterfaceSource ↗

The interface a conformance runtime implements so one fixture can drive every backend.

interface ReplayStore
MemberTypeSummary
applyStepApply one step and report what happened.
initInitialize 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
MemberTypeSummary
amountnumber
release
releasedboolean

ResolvedEndnotePropertiesinterfaceSource ↗

Fully resolved endnote properties (defaults filled).

interface ResolvedEndnoteProperties
MemberTypeSummary
numFmtstring
numRestartNoteNumRestart
numStartnumber
posEndnotePosition

ResolvedFootnotePropertiesinterfaceSource ↗

Fully resolved footnote properties (defaults filled).

interface ResolvedFootnoteProperties
MemberTypeSummary
numFmtstring
numRestartNoteNumRestart
numStartnumber
posFootnotePosition

ResolvedRegistryinterfaceSource ↗

The resolved result: every contribution selected, indexed by (kind, id).

interface ResolvedRegistry
MemberTypeSummary
contributionsReadonlyMap<string, Contribution>
extensionsReadonlyMap<string, FeatureBundle>
get

ResolveOptionsinterfaceSource ↗

How resolution treats optional bundles and replacement policies.

interface ResolveOptions
MemberTypeSummary
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
MemberTypeSummary
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
MemberTypeSummary
maxChunkBytesnumberIn-memory chunk budget for streaming/spooling.
maxCompressedBytesnumberMax total compressed input bytes.
maxCompressionRationumberMax decompressed:compressed ratio per entry.
maxDecompressedBytesnumberMax total decompressed bytes (zip-bomb guard).
maxElementCountnumberMax total parsed element count.
maxPaginationPassesnumberMax pagination passes before non-convergence is declared.
maxPartCountnumberMax package part count.
maxQueueDepthnumberMax queued items in any bounded work queue.
maxRecursionDepthnumberMax nested-structure recursion (tables/shapes/SDT/groups).

ReviewCommentIteminterfaceSource ↗

One comment as the store derives it, with its thread links resolved.

interface ReviewCommentItem
MemberTypeSummary
commentCommentRecord
idstring
kind'comment'
orphanedbooleanTrue when the file gave this comment no usable range.
parentId?stringThe comment this replies to, absent for a top-level comment.
parentRevisionId?stringThe REVISION this comment answers, when it covers exactly that change's characters.
rangeReviewRange | null
replyIdsreadonly string[]Replies to this comment, in document order. Empty for a reply or a childless comment.
resolvedboolean

ReviewModelInputinterfaceSource ↗

What review derivation reads: one story part plus its comment parts.

interface ReviewModelInput
MemberTypeSummary
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[] | undefinedHeader/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.
storyPartOoxmlPartThe 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
MemberTypeSummary
offsetnumber
paragraphIdstring

ReviewRangeinterfaceSource ↗

Where an item is anchored: a range in one story.

interface ReviewRange
MemberTypeSummary
endReviewPosition
partNamestring
startReviewPosition

ReviewRevisionIteminterfaceSource ↗

One tracked change as the store derives it, keyed per decision rather than per site.

interface ReviewRevisionItem
MemberTypeSummary
addressRevisionAddressThe payload `acceptRevision` / `rejectRevision` take.
addressesreadonly RevisionAddress[]EVERY address this decision covers, `address` first.
authorstring
date?string
idstringStable across renders and unique per DECISION, not per site.
kind'revision'
pairedWith?stringThe other half of a move, or the other side of a delete/insert replacement.
rangesreadonly ReviewRange[]Every site this decision touches, in document order.
readOnlybooleanTrue when the engine cannot resolve this kind, so accept and reject must not be offered.
replacedRangeCount?numberHow many leading `ranges` are the STRUCK half of a replacement.
replacedTextstringThe words a replacement removes. Empty for every other kind.
replyIdsreadonly string[]Comments answering this change, in document order.
revisionKindReviewRevisionKind
textstringText 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
MemberTypeSummary
authorstring
date?stringAbsent when the file wrote no `@w:date`; part of the identity either way.
idstring

RunPropertyEditinterfaceSource ↗

One run's share of a range edit: the slice it covers and the properties to write there.

interface RunPropertyEdit
MemberTypeSummary
endnumber
propertiesreadonly OoxmlProperty[]
startnumber
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
MemberTypeSummary
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
MemberTypeSummary
keptreadonly ContentItem[]
nonLosslessbooleanA scrub that removes anything is non-lossless by definition.
removedreadonly ContentItem[]

SegmentinterfaceSource ↗

One addressable unit of paragraph text: text, tab, hard break, or atomic field.

interface Segment
MemberTypeSummary
endnumber
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.
nodeOoxmlNode
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.
runIdstring
startnumber

SelectionMarkinterfaceSource ↗

A selection captured with a transaction, so undo restores where the caret was.

interface SelectionMark
MemberTypeSummary
endnumber
paragraphIdstring
startnumber

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
MemberTypeSummary
storiesreadonly StoryDigest[]

SemVerinterfaceSource ↗

A parsed semantic version. Only the three numeric components — no pre-release or build.

interface SemVer
MemberTypeSummary
majornumber
minornumber
patchnumber

ShapingPortinterfaceSource ↗

Which shaping backend measures text. Opaque marker until its milestone.

interface ShapingPort
MemberTypeSummary
kind'shaping'

SourceCropinterfaceSource ↗

a:srcRect — how much of each edge of the source image is cropped away, as fractions.

interface SourceCrop
MemberTypeSummary
bottomnumber
leftnumber
rightnumber
topnumber

StoryDigestinterfaceSource ↗

One story reduced to its semantic content, ignoring everything a normalized re-emit changes.

interface StoryDigest
MemberTypeSummary
paragraphsreadonly ParagraphDigest[]
partNamestring
structurereadonly 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
MemberTypeSummary
paragraphsreadonly ParagraphIndexEntry[]
partNamestringThe part the story lives in.
rootIdstringThe `w:body` (or story root) node id.

StyleIndexEntryinterfaceSource ↗

One style definition, indexed by the id content references it under.

interface StyleIndexEntry
MemberTypeSummary
basedOnstring | null
isDefaultbooleanWhether the part marks this the default style for its type (`w:default="1"`).
namestring | null
nodeIdstring
styleIdstring
typestring

TextMatchOptionsinterfaceSource ↗

How a text search is narrowed. Options the engine cannot honour are refused, never ignored.

interface TextMatchOptions
MemberTypeSummary
from?numberReport 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
MemberTypeSummary
lengthnumber
startnumber

TextOccurrencesinterfaceSource ↗

Where a phrase occurs in a story, as paragraph-plus-offset ranges.

interface TextOccurrences
MemberTypeSummary
matchesreadonly TextOccurrence[]
truncatedbooleanThe 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
MemberTypeSummary
bookmarkNamestring
headingParagraphIdstring
levelnumber
pageNumberTextstring
textstring

TocInstructioninterfaceSource ↗

Parsed TOC instruction. Unknown switches are ignored for generation but left on the wire.

interface TocInstruction
MemberTypeSummary
keyword'TOC'
omitPageNumbersbooleanOmit page numbers (`\\n`).
outlineEndnumber
outlineStartnumberInclusive 1-based outline levels from `\\o "n-m"`. Defaults 1–9.
rawstring

TocOutlineHeadinginterfaceSource ↗

Outline heading shape consumed by TOC planning (mirrors DocumentOutlineEntry).

interface TocOutlineHeading
MemberTypeSummary
blockIdstring
levelnumber
textstring

TransportPortinterfaceSource ↗

How the engine talks to a remote peer. Opaque marker until its milestone.

interface TransportPort
MemberTypeSummary
kind'transport'

TreeDocumentStoreOptionsinterfaceSource ↗

How a store is constructed: its limits, its history depth, and its identity source.

interface TreeDocumentStoreOptions
MemberTypeSummary
historyLimit?numberBound 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
MemberTypeSummary
caret?SelectionMarkCommitted 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'
commitIdstring
createdreadonly string[]
deletedreadonly string[]
dependencyKeysreadonly string[]
dirtyreadonly string[]
fromRevisionnumber
impactImpactClassThe widest impact among the transaction's ops — what layout must scope to.
originstring
splitJoinreadonly ({ readonly split: { readonly from: string; readonly tail: string; }; } | { readonly join: { readonly kept: string; readonly removed: string; }; })[]
story?TreeStoryRefStory that published this change. Absent on body-only store publishes that predate package-aware targeting; `TreePackageStore` always sets it.
toRevisionnumber

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
MemberTypeSummary
caret?{ readonly paragraphId: string; }First post-edit caret paragraph for table column structural ops.
createdreadonly string[]
deletedreadonly string[]
dependencyKeysreadonly string[]
dirtyreadonly string[]
impactImpactClass
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
MemberTypeSummary
cascadeDeletedNoteReferences?NoteCascadeFnTest seam for note-reference cascade after `deleteText` / `deleteBlock`. Production uses [cascadeDeletedNoteReferences](cascadeDeletedNoteReferences).
historyLimit?number
maxEditableStoryParts?numberBound 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
MemberTypeSummary
applyStage one op against the STORY part. Returns false once the transaction has failed.
applyPackageStage a whole-package edit: a new part, a relationship, a content-type override.
applyToStage one op against a named part.
selectionAfterThe selection to restore when this entry is redone.
selectionBeforeThe selection to restore when this entry is undone.

TreeTransactOptionsinterface

How one transaction behaves: its story scope, its attribution, and its selection marks.

interface TransactOptions
MemberTypeSummary
minimumImpact?ImpactClassFloor 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?TreeStoryRefStory 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
MemberTypeSummary
pixelHeightnumber
pixelWidthnumber

ValidationResultinterfaceSource ↗

Whether a fixture is well-formed, listing every structural violation.

interface ValidationResult
MemberTypeSummary
errorsreadonly string[]
validboolean

XmlLimitsinterfaceSource ↗

Per-part caps on size, element count and depth. Clamped into the hard ceilings.

interface XmlLimits
MemberTypeSummary
maxBytesnumber
maxElements?number

ZipLimitsinterfaceSource ↗

Archive caps: entry count, total decompressed bytes, and the decompression ratio.

interface ZipLimits
MemberTypeSummary
maxEntriesnumber
maxRatio?numberMax per-entry uncompressed:compressed ratio (zip-bomb guard).
maxTotalBytesnumberMax 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 = 2147483647

CONTENT_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: ResolvedEndnoteProperties

DEFAULT_FOOTNOTE_PROPERTIESconstSource ↗

Word's own footnote defaults, applied where a section declares no w:footnotePr.

DEFAULT_FOOTNOTE_PROPERTIES: ResolvedFootnoteProperties

DEFAULT_IMAGE_RESOURCE_LIMITSconstSource ↗

The image caps in force when a host configures none. Conservative and finite.

DEFAULT_IMAGE_RESOURCE_LIMITS: ImageResourceLimits

DEFAULT_LIMITSconstSource ↗

Finite defaults, all = their hard ceiling.

DEFAULT_LIMITS: ResourceLimits

DEFAULT_MAX_EDITABLE_STORY_PARTSconstSource ↗

Cap on simultaneously opened editable story stores (body + HF parts). Fail closed.

DEFAULT_MAX_EDITABLE_STORY_PARTS = 64

DEFAULT_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: ZipLimits

DEPENDENCY_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: ResourceLimits

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: ImageResourceLimits

IMAGE_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 = 32

MAX_CONTENT_CONTROLS_PER_PARTconstSource ↗

Cap on controls one walk reports, so a hostile file cannot make a read unbounded.

MAX_CONTENT_CONTROLS_PER_PART = 10000

MAX_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 = 4096

MAX_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: number

MAX_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 = 256

MAX_NOTE_REFERENCE_SCANconstSource ↗

Cap on nodes visited while scanning for note references across stories.

MAX_NOTE_REFERENCE_SCAN = 20000

MAX_NOTES_PER_PARTconstSource ↗

Cap on notes scanned when allocating / indexing a notes part.

MAX_NOTES_PER_PART = 10000

MAX_STORY_SDT_NESTINGconstSource ↗

How deep block-level content controls may nest before the walk stops descending.

MAX_STORY_SDT_NESTING = 32

MAX_SVG_SNIFF_BYTESconstSource ↗

Maximum prefix inspected for SVG root detection (exported for bounded-scan tests).

MAX_SVG_SNIFF_BYTES = 512

NO_TRACKING_SETTINGSconstSource ↗

The frozen "nothing is tracked" settings — what a document with no w:trackChanges gets.

NO_TRACKING_SETTINGS: DocumentTrackingSettings

NON_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 = 0

NOTE_ID_MAXconstSource ↗

Largest note id Word accepts — signed 32-bit.

NOTE_ID_MAX = 2147483647

NOTE_ID_MINconstSource ↗

Signed 32-bit Word-compatible note id range (positive allocation only).

NOTE_ID_MIN = 1

NOTE_SEPARATOR_IDconstSource ↗

Reserved separator / continuation ids — never allocated for normal notes.

NOTE_SEPARATOR_ID = -1

OFFICE_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: OoxmlNodeIdentityRules

ORIGIN_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 = 2000

SEARCH_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 = 256

TABLE_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 = 240

TOC_MAX_BOOKMARKS_PER_REFRESHconstSource ↗

Most bookmarks minted during one TOC refresh.

TOC_MAX_BOOKMARKS_PER_REFRESH = 512

TOC_MAX_ENTRIESconstSource ↗

Most entries one generated table of contents may hold.

TOC_MAX_ENTRIES = 512

TOC_MAX_FIELD_NESTINGconstSource ↗

Deepest nested field instruction followed. Caps recursion on file-supplied structure.

TOC_MAX_FIELD_NESTING = 4

TOC_MAX_INSTRUCTION_CHARSconstSource ↗

Longest TOC field instruction read. Instructions come from a file; the parse is bounded.

TOC_MAX_INSTRUCTION_CHARS = 256

TOC_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 = 3

TREE_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/"

On this page

FunctionsaddCommentallocateContentControlIdallocateDrawingPropertyIdallocateNoteIdapplyEditsapplyHeaderFooterLifecycleOpapplyNoteLifecycleOpapplyTreeOpasciiFoldassertLimitInvariantsassertValidIdassertValidQNameatomicFieldSpansOfatomicNoteSpansOfauthorableHyperlinkTargetauthoredDocumentEndnotePropertiesauthoredDocumentFootnotePropertiesauthoredEndnotePropertiesFromSectPrauthoredFootnotePropertiesFromSectPrauthoredPropertiesbeginOperationbodyStoryRootbookmarkPairNodesboundCustomXmlNodeIdOfboundCustomXmlNodeIdsboundCustomXmlNodeIdsInPackagebuildBookmarkIndexbuildContentTypeIndexbuildRelationshipSetbuildTocContentControlbuildTocEntryParagraphcanonicalizecanonicalOoxmlFingerprintcascadeDeletedNoteReferencescascadeEmptiedCommentschildElementscollectFlowBlockscollectNodeIdscollectNoteReferencescollectPackageNoteReferencescollectReviewItemscollectRevisionSitescollectSectionPropertyNodescollectStoryParagraphscommentAnchorsOfStorycommentBodyTextcommentInitialscommentItemsOfcommentPartNameOfcommentsExtendedPartNameOfcommentsOfPartcompareArtifactscompareSemVercontainsCssFetchcontentControlContentChildrencontentControlContentNodeOfcontentControlContentOfcontentControlEndPropertiesNodeOfcontentControlLevelOfcontentControlPropertiesNodeOfcontentControlPropertiesOfcontentControlsIncontentControlTextOfcontentTypesPartBytescreateImageResourceCachecreateNodeIdAllocatorcreateNoteReferenceScanBudgetcustomMarkFollowscustomNodeBindingcustomNodePayloadsByControlcustomNodePayloadsOfcustomXmlDataPartscustomXmlLabelXPathcustomXmlNodescustomXmlPrefixMappingsdatastoreItemIdFordeepParagraphOrderOfPartdeleteCommentThreaddeobfuscateFontderiveOoxmlIndexesdetectBodyTocsdetectDuplicateNamesdiagnoseNoteReferencesdiffSemanticDigestsdigestPartdirectParagraphMarkPropertiesdirectParagraphPropertiesdrawingOpImpactendOperationensureHyperlinkRelationshipensureListDefinitionensureNumberingLevelescapeCssStringescapeXmlextensionKeyfieldAtomTextfieldOnOffAttributefindContentControlfindCustomXmlDataPartfindDetectedTocfindElementfindNodefindNoteByIdfindOccurrencesfingerprintfirstReviewRangeflattenContentControlsfldCharTypefldSimpleInstrfnv1a32foldCaseformatNoteScopeIdformatOwnedRunIdshardBreakAttributeshardBreakKindhardBreakTexthasAnyCommenthasBoundedSvgRoothasCommentParthashAuthoredhasNodehyperlinkAnchorOfhyperlinkRelationshipIdOfhyperlinkTargetOfimageResourceLookupForindexStylesinlineControlEndingAtinlineControlStartingAtinsertChildreninsertCustomNodeWriteinstrTextValueisAuthorableRunPropertyisContentControlisContentControlContentisContentControlContentNodeisContentControlNodeisContentControlWrapperisContentRevisionKindisContinuationSeparatorNodeisDangerousKeyisDrawingTreeDocOpisEndnotesNodeisEvaluableFieldisFieldChromeisFldCharisFldCharNodeisFldSimpleisFldSimpleNodeisFootnotesNodeisHeaderFooterLifecycleOpisHyperlinkNodeisInertExecutableisInstrTextisInstrTextNodeisLegalEndnotePositionisLegalFldCharTypeisLegalFootnotePositionisLegalNumRestartisNormalNoteisNoteAtomNodeisNoteLifecycleOpisNoteNodeisNoteReferenceNodeisNoteRefNodeisPageBreakNodeisRangeMarkerKindisSearchableQueryisSeparatorNodeisValidIdisValidMimeisValidNCNameisValidParaIdisValidQNameisWholeWordlinkRevisionRepliesliveDrawingReferenceCountlocateSiteslockForbidsEditlockForbidsRemovalmakeLimitCountermergedPropertiesmintedParagraphIdentityAttributesmintParaIdnormalizeParagraphIdentitynormalizePartNamenormalNoteIdsnoteAtomTextnoteIdOfnoteKindOfnoteReferenceKindOfnoteRefKindOfnotesOfnotesPartHasIdnoteTypeOfnullRecordooxmlTreesEqualorderedContentControlPropertiesparagraphOffsetIndexparagraphOrderOfPartparagraphTextOfparaIdOfparentNodeOfparseAuthoredNotePropertiesparseContentControlIdparseNoteIdparseNoteScopeIdparseSemVerparseTocInstructionpartNameKeyplanTocEntriesprojectDrawingpropertyContainerreadCustomXmlNodereadEmbeddedFontsreadOnOffChildreadOoxmlPackagereadOoxmlPartreadTrackingSettingsreadXmlreadZiprelationshipsOfrelationshipTargetInrelsPartNameForremoveCustomNodeWriteremoveNodereplaceChildrenreplaceNodereplayFixtureresolveresolveContentControlLockresolveContentTyperesolveContentTypeOfresolveEndnotePropertiesresolveFootnotePropertiesresolveHeaderFooterPartsresolveHeaderFooterPartsBySectionresolveHeaderFooterResolutionBySectionresolveImageRelationshipresolveImageResourceLimitsresolveInternalTargetresolveLimitsresolveNotesPartresolveRelationshipresolveTocRowHeadingsreviewItemKeyreviewItemRangesrevisionItemsOfrunAddressRangesrunPropertyEditsrunsCoveringsanitizeHrefsatisfiesscrubExportsegmentsOfsemanticDigestserializeOoxmlPartsetCommentResolvedsettingsPartOfsniffImageMimestableHashstoryParagraphsstoryRootsOfstylesPartOfsweepCustomNodePayloadstextContentthreadStateOfParttocEntryTexttocLeftIndentTwipstoSafeRecordusedParaIdsvalidateDrawingOpvalidateExternalTargetvalidateFixturevalidateGifHeadervalidateJpegHeadervalidateOoxmlPartvalidatePackageInvariantsvalidatePngHeadervalidateRasterHeadervalidateTreeOpw14RootPrefixwalkAllStoryParagraphswalkParagraphInlinewalkStoryBlockswithBinaryPartwithContentTypeOverridewithCustomXmlDataPartwithCustomXmlNodewithEmbeddedImagewithExportedCustomNodeswithNewPartwithoutCustomXmlDataPartwithoutCustomXmlNodewithoutOrphanCustomXmlNodeswithoutUnreferencedImagePartwithPartwithRelationshipwrapTargetToAnchorSpecwriteOoxmlPackagewriteZipClassesBoundedCounterBudgetBudgetErrorCancellationControllerCancellationErrorDangerousKeyErrorDeterministicClockDeterministicMemoryMeterLimitExceededErrorPortRegistryPortResolutionErrorPrefixAllocatorRegistryErrorSequentialIdentityTreeDocumentStoreTreePackageStoreInterfacesAddCommentRequestAnchorSnapshotAtomicFieldSpanAtomicNoteSpanAuditPortAuthoredNotePropertiesAuthorizationPortBookmarkAnchorCancellationPortCancellationTokenCapabilityIdCascadeDeletedNoteReferencesOptionsClockPortCommentAnchorCommentAnchorRequestCommentPositionCommentRecordCommentThreadStateComparatorDescriptorComparisonResultConformanceFixtureContentControlCheckboxContentControlCheckboxStateContentControlDataBindingContentControlDateFormatContentControlEntryContentControlListItemContentControlPropertiesContentItemContentTypeIndexContentTypeRecordsContributionCreateImageResourceCacheOptionsCustomNodeBindingCustomNodeExportRequestCustomNodePayloadReadCustomNodePayloadWriteCustomXmlDataPartCustomXmlDataPartResultCustomXmlNodeDefaultRecordDetectedTocDocumentTrackingSettingsDrawingLocksDrawingPositionInputEditOptionsEmbeddedFontEncodedEnvelopeEnsuredHyperlinkRelationshipExternalResourceConsentPortFeatureBundleFixtureExpectationFixtureStepFontPortHeaderFooterPartsHeaderFooterSectionResolutionHeaderFooterSlotMetaHyperlinkTargetIdentityPortImageDecodePortImagePortImageResourceLimitsImageResourceLookupInlineControlSpanInsertCustomNodeWriteLimitSpecLinkableReviewItemModelChangeSummaryNoteLifecycleOptionsNoteReferenceHitNoteReferenceScanBudgetOffsetSpanOoxmlBodyNodeOoxmlBookmarkEndNodeOoxmlBookmarkStartNodeOoxmlContentControlCalendarNodeOoxmlContentControlCheckboxNodeOoxmlContentControlCheckedNodeOoxmlContentControlCheckedStateNodeOoxmlContentControlComboBoxNodeOoxmlContentControlContentNodeOoxmlContentControlDataBindingNodeOoxmlContentControlDateFormatNodeOoxmlContentControlDateNodeOoxmlContentControlDropDownListNodeOoxmlContentControlEndPropertiesNodeOoxmlContentControlLidNodeOoxmlContentControlListItemNodeOoxmlContentControlNodeOoxmlContentControlPropertiesNodeOoxmlContentControlStoreMappedDataAsNodeOoxmlContentControlTextNodeOoxmlContentControlUncheckedStateNodeOoxmlContinuationSeparatorNodeOoxmlDocumentNodeOoxmlEndnotesNodeOoxmlExternalTargetOoxmlFldCharNodeOoxmlFldSimpleNodeOoxmlFootnotesNodeOoxmlGenericElementNodeOoxmlGenericExtensionAttributeOoxmlHardBreakNodeOoxmlHyperlinkNodeOoxmlIndexesOoxmlInstrTextNodeOoxmlInvariantIssueOoxmlNamespaceBindingOoxmlNodeIdentityRulesOoxmlNoteNodeOoxmlNoteReferenceNodeOoxmlNoteRefNodeOoxmlPackageOoxmlPackageLimitsOoxmlParagraphNodeOoxmlParagraphPropertiesNodeOoxmlPartOoxmlPartMetadataOoxmlPropertyOoxmlRunNodeOoxmlRunPropertiesNodeOoxmlSeparatorNodeOoxmlStoryRootOoxmlTabNodeOoxmlTextElementNodeOoxmlTextNodeOoxmlWmlValAttributeOoxmlXmlSpaceAttributeOperationContextOperationInitOverrideRecordPackageInvariantIssueParagraphDigestParagraphIndexEntryParagraphOffsetIndexPersistencePortReadEmbeddedFontsOptionsRelationshipRecordReplayOutcomeReplayReportReplayStoreReservationResolvedEndnotePropertiesResolvedFootnotePropertiesResolvedRegistryResolveOptionsResourceAccountingPortResourceLimitsReviewCommentItemReviewModelInputReviewPositionReviewRangeReviewRevisionItemRevisionAddressRunPropertyEditSchedulingPortScrubResultSegmentSelectionMarkSemanticDigestSemVerShapingPortSourceCropStoryDigestStoryIndexEntryStyleIndexEntryTextMatchOptionsTextOccurrenceTextOccurrencesTocEntryPlanTocInstructionTocOutlineHeadingTransportPortTreeDocumentStoreOptionsTreeModelChangeTreeOpEffectTreePackageStoreOptionsTreeTransactionContextTreeTransactOptionsValidatedRasterHeaderValidationResultXmlLimitsZipLimitsType aliasesAddCommentResultBookmarkIndexCancellationPhaseComparatorModeComparatorNameContentControlKindContentControlLevelContentControlLockContentTypeErrorCustomNodeExportPolicyCustomNodeExportResultCustomNodeSweepOutcomeCustomNodeSweepResultCustomNodeWriteRejectionCustomNodeWriteResultDigestDifferenceDrawingKindDrawingPropertyIdResultDrawingTreeDocOpEndnotePositionEnforcementPhaseFixtureOutcomeFixtureSourceFldCharTypeFontStyleKeyFootnotePositionHardBreakKindHeaderFooterKindHeaderFooterLifecycleImpactHeaderFooterLifecycleOpHeaderFooterLifecycleRejectionHeaderFooterLifecycleResultHeaderFooterVariantHrefProjectionHyperlinkKindIdKindImageRelationshipResolutionImageResourceStateImageWrapTargetImpactClassIndexResultInertExecutableKindJsonLimitUnitListKindNameRejectionNameResultNoteDiagnosticNoteDiagnosticCodeNoteKindNoteLifecycleImpactNoteLifecycleOpNoteLifecycleRejectionNoteLifecycleResultNoteNumRestartNoteTypeOoxmlAttributeOoxmlEditResultOoxmlElementOoxmlInvariantIssueCodeOoxmlInvariantResultOoxmlKnownNodeAttributeOoxmlNodeOoxmlNodeIdOoxmlPackageRejectionOoxmlPackageResultOoxmlReadRejectionOoxmlReadResultOoxmlStoryKindPackageInvariantCodePackageInvariantResultPackageTransactResultPreservedImageMimeRegistryErrorCodeRelationshipErrorRelationshipSetResultRelationshipTargetResolverReplacementPolicyResolvedRelationshipResolveResultReviewItemReviewRevisionKindSetCommentResolvedResultStoryResolveResultStoryScopeStoryTargetRejectionSupportedImageMimeTableBorderStyleTargetModeTreeDocOpTreeDocOpKindTreeOpRejectionTreeOpResultTreeStoryRefTreeTransactResultXmlNodeXmlRejectionXmlResultZipReadResultZipRejectionVariablesACCEPTED_PARAGRAPH_PROPERTIESACCEPTED_RUN_PROPERTIESALL_FROZEN_IDSAUTHORABLE_PARAGRAPH_PROPERTIESAUTHORABLE_RUN_PROPERTIESCANONICAL_MUTATION_ORIGINSCOMPARATORSCONTENT_CONTROL_ID_MAXCONTENT_CONTROL_PROPERTY_ORDERCUSTOM_NODE_XPATH_PREFIXCUSTOM_XML_PROPS_RELCUSTOM_XML_PROPS_TYPECUSTOM_XML_RELDANGEROUS_KEYSDATASTORE_NAMESPACE_URIDEFAULT_ENDNOTE_PROPERTIESDEFAULT_FOOTNOTE_PROPERTIESDEFAULT_IMAGE_RESOURCE_LIMITSDEFAULT_LIMITSDEFAULT_MAX_EDITABLE_STORY_PARTSDEFAULT_OOXML_PACKAGE_LIMITSDEFAULT_ZIP_LIMITSDEPENDENCY_KEY_IDSFIELD_ATOM_CHARHARD_CEILINGSHYPERLINK_RELATIONSHIP_TYPEID_KINDSIMAGE_RELATIONSHIP_TYPEIMAGE_RESOURCE_HARD_CEILINGSIMAGE_WRAP_TARGETSINERT_EXECUTABLE_KINDSLIMIT_KEYSLIMIT_SPECSMAX_CONTENT_CONTROL_NESTINGMAX_CONTENT_CONTROLS_PER_PARTMAX_CUSTOM_NODE_LABEL_LENGTHMAX_CUSTOM_NODE_PAYLOAD_LENGTHMAX_NOTE_REFERENCE_PARTSMAX_NOTE_REFERENCE_SCANMAX_NOTES_PER_PARTMAX_STORY_SDT_NESTINGMAX_SVG_SNIFF_BYTESNO_TRACKING_SETTINGSNON_CANONICAL_ORIGINSNOTE_ATOM_CHARNOTE_CONTINUATION_SEPARATOR_IDNOTE_ID_MAXNOTE_ID_MINNOTE_SEPARATOR_IDOFFICE_RELATIONSHIP_NAMESPACE_URIOOXML_NODE_IDENTITY_RULESORIGIN_IDSPAGE_BREAK_CHARRESULT_IDSRUNTIME_PORT_IDSSEARCH_MATCH_LIMITSEARCH_QUERY_MAXTABLE_BORDER_STYLESTOC_LEVEL_INDENT_TWIPSTOC_MAX_BOOKMARKS_PER_REFRESHTOC_MAX_ENTRIESTOC_MAX_FIELD_NESTINGTOC_MAX_INSTRUCTION_CHARSTOC_MAX_PAGE_PASSESTREE_DOC_OP_KINDSW15_NAMESPACE_URIWML_NAMESPACE_URIXML_NAMESPACE_URIXMLNS_NAMESPACE_URI