@docx-editor.dev/core/editor
@docx-editor.dev/core/editor — the editor facade and its chrome vocabulary.
createDocxEditor implements the full Editor contract over a paginated surface, and the chrome registry (CHROME_GROUPS, ChromeSlotId) is the toolbar taxonomy both adapters derive their default arrangement from. Enabled state has exactly one source — toolbarCommandState, which asks the engine — so a control and the engine can never disagree.
Functions (91)
applyTableChromePickfunctionSource ↗
Build the engine command for one table chrome pick and the draft state after it. Target picks apply the current complete spec; none clears the active target only.
declare function applyTableChromePick(draft: TableChromeDraft, slot: TableChromeSlotId, value: unknown): TableChromePick | null;applyThemeShadefunctionSource ↗
Blend toward black. keep is the fraction of the base colour retained (OOXML themeShade byte).
declare function applyThemeShade(hex: string, keep: number): string;applyThemeTintfunctionSource ↗
Blend toward white. keep is the fraction of the base colour retained (OOXML themeTint byte).
declare function applyThemeTint(hex: string, keep: number): string;blankDocumentBytesfunctionSource ↗
A Word-faithful blank document, freshly zipped per call (the caller may hand the bytes to a loader that takes ownership). Calibri 11pt and Word's Normal paragraph spacing are authored in w:docDefaults, Word's built-in style gallery in styles.xml, US Letter geometry in the section — a New document behaves like Word's, and saving it produces a file Word opens identically.
declare function blankDocumentBytes(): Uint8Array;canExecuteImageCommandfunctionSource ↗
Whether an insert or replace would be accepted — the can half of the can-before-exec pair.
Refuses in suggesting mode, since an image property edit has no tracked-change representation.
declare function canExecuteImageCommand(command: Extract<EditorCommand, {
type: 'insertImage' | 'replaceImage';
}>, surface: PaginatedSurface | null): CanResult;captureImageMutationPreconditionsfunctionSource ↗
Snapshot the state an image mutation was planned against: mount generation, package revision, and the selection anchor.
Taken at the START of a drag so the commit can be checked against it with [isStaleImageInteractionCommit](isStaleImageInteractionCommit). A pointer gesture spans many frames, and a document that moved underneath it must not have the gesture's final coordinates applied to it.
declare function captureImageMutationPreconditions(editor: Pick<DocxEditorInstance, 'surface' | 'mountGeneration'>): ImageMutationPreconditions | null;chromeControlCountfunctionSource ↗
Total controls, so a parity test can assert none were dropped.
declare function chromeControlCount(): number;chromeMenuSlotsfunctionSource ↗
Every slot a menu places, in menu order, submenus flattened. What a parity test asserts against, and what a host enumerates to know which capabilities the menu bar reaches.
declare function chromeMenuSlots(): readonly ChromeSlotId[];chromeProbeForSlotfunctionSource ↗
The probe a slot uses to ask "would the engine honour this right now?" when its real command needs an argument the slot itself cannot supply.
text.link is the case: whether this selection could become a link is the engine's question, but WHICH link is a URL field's. Chrome that owns a link UI (React's ToolbarLink) asks with this and dispatches through that UI.
DELIBERATELY NOT in SLOT_COMMANDS. Enabled state has one source, and putting the probe there would enable the control in EVERY adapter — including Vue, which has grown no link UI, where the result is an enabled button whose click can only be refused. A dead button is the worse lie: file.save was a disabled control for a capability that works, and this would be an enabled control for one that is not reachable. Vue's slot therefore keeps reporting the honest "not wired to an editor command" until its popover lands.
declare function chromeProbeForSlot(slotId: ChromeSlotId): EditorCommand | null;chromeSlotIdfunctionSource ↗
The slot id of one control within its group. Only meaningful for entries of CHROME_GROUPS — the cast is sound because every group/control pair in the registry is, by construction, a member of the ChromeSlotId union.
declare function chromeSlotId(group: {
readonly id: string;
}, control: {
readonly id: string;
}): ChromeSlotId;chromeSlotIsTogglefunctionSource ↗
Whether a slot's control renders as a TOGGLE — pressed or not — so it carries aria-pressed.
Shared rather than derived per adapter, because it is not derivable from the command table alone: the format painter has no fixed command (a press captures, arms, locks or stands down, which no single EditorCommand describes), so a rule that only read commandForSlot left it announcing nothing at all to a screen reader while it was armed.
declare function chromeSlotIsToggle(slotId: ChromeSlotId): boolean;commandForSlotfunctionSource ↗
The public editor command behind one chrome slot, or null when the slot is not wired to a command yet (parity-only chrome, or save — which is not a command). The single source of command truth for both adapters.
declare function commandForSlot(slotId: ChromeSlotId): EditorCommand | null;commandForSlotValuefunctionSource ↗
The engine command for a VALUE-TYPED slot carrying the picked value, or null for a slot that does not take a value.
Two families: the run-property pickers (font.family, font.size, text.color, text.highlight) resolve to setMarkAttr, and styles.style resolves to setParagraphStyle — a paragraph styleId, not a mark. Either way the value is validated by the engine's own gate (can refuses a malformed one with invalidArgs; a styleId the document does not define is refused at exec), so a host can pass user input through unmodified.
declare function commandForSlotValue(slotId: ChromeSlotId, value: unknown): EditorCommand | null;commandForTableChromeSlotValuefunctionSource ↗
Build an engine command for one table chrome slot using the caller's draft state.
declare function commandForTableChromeSlotValue(slotId: TableChromeSlotId, value: unknown, draft: TableChromeDraft): EditorCommand | null;composeFontConfigurationfunctionSource ↗
Merge a base and any number of fragments into one frozen FontConfiguration.
A bare fragment IS a valid base, so the single-origin case is one argument: composeFontConfiguration(await loadDefaultFonts()). Pass extra fragments to layer origins, and set epoch/maxFontBytes/defaultFont on the base only when you need something other than the documented defaults.
- Sources dedupe first-wins by (family, weight, style), in argument order — base before fragments, earlier fragments before later ones. - Substitutions dedupe first-wins by their from face, in the same order, and every substitution whose from face has a direct source anywhere in the composition is dropped: a real face always beats a stand-in. - The result is frozen (arrays included); the byte arrays themselves are the callers' and are not copied here — the resource snapshot takes its own defensive copy.
declare function composeFontConfiguration(base: FontConfigurationBase, ...fragments: readonly FontConfigurationFragment[]): FontConfiguration;composeFontOriginsfunctionSource ↗
Resolve a list of [FontOrigin](FontOrigin)s against one document's needs and merge them, first-wins in list order.
Origins resolve IN ORDER, one after another, and each is told which faces the ones before it can already paint ([FontResolutionRequest.resolvedFaces](FontResolutionRequest.resolvedFaces)). Sequential rather than a Promise.all, and that is a real cost — one extra origin's latency on the critical path — bought deliberately: composition is first-wins, so a later origin's copy of a face an earlier one supplied can never be used, and fetching it anyway spends the bytes twice and tells a font host which families the document uses for a result that gets thrown away. Order origins cheapest-first.
A resolver that ignores resolvedFaces still composes correctly; it just spends more.
ONE ORIGIN CANNOT SINK THE REST. An origin that throws, answers null, or answers something malformed is reported and skipped whole, and the origins around it still compose — an app that listed a flaky network origin behind a bundled one keeps the bundled faces. Skipped WHOLE: an answer is read completely before any of it is committed, so a half-ingested origin can never reach composition.
The result carries NO epoch: it is a fragment for the engine to stamp with the load sequence. A fixed epoch from here would label every document's byte set as the same one. undefined means no origin contributed anything, which is a normal answer — the document stays on the fixed measurer.
declare function composeFontOrigins(origins: readonly FontOrigin[], request: FontResolutionRequest, options?: ComposeFontOriginsOptions): Promise<FontConfigurationFragment | undefined>;computeImageResizeResultfunctionSource ↗
Resolve one resize frame from the pointer's current position.
Handles rotation and flips by mapping the SCREEN-space handle back to the drawing's local axes first: dragging the visually-right handle of a 90°-rotated image must change its stored height, and a flipped image's handles move in the opposite direction from where they appear.
declare function computeImageResizeResult(options: {
readonly handle: ImageResizeHandle;
readonly startWidthEmu: number;
readonly startHeightEmu: number;
readonly startBounds: {
readonly x: number;
readonly y: number;
readonly width: number;
readonly height: number;
};
readonly startPosition: DrawingPositionInput | null;
readonly anchorFrameOrigin?: AnchorFrameOrigin | null;
readonly deltaXPt: number;
readonly deltaYPt: number;
readonly transform: DrawingTransform;
readonly preserveAspect: boolean;
readonly kind: 'inline' | 'anchored';
}): ImageResizeResult;computeMovedImagePositionfunctionSource ↗
The position a move drag produces, preserving the anchoring the file already used.
A frame-mode position keeps its relativeToH/relativeToV bases and only shifts the offsets it actually had — writing an offset the file omitted would re-anchor the drawing to a different reference and move it somewhere the drag never pointed.
declare function computeMovedImagePosition(start: DrawingPositionInput, deltaXPt: number, deltaYPt: number): DrawingPositionInput;computeResizedImageExtentEmufunctionSource ↗
The extent a resize drag produces, in EMU.
Computed from the drag's START extent rather than the previous frame's, so a drag that reverses direction lands exactly where it began instead of accumulating rounding error.
preserveAspect behaves the way Word's handles do: a corner handle scales by whichever axis moved further, while an edge handle drives the other axis from the original ratio. Both axes are floored at one point, so a drag past the opposite edge cannot invert the image.
declare function computeResizedImageExtentEmu(startWidthEmu: number, startHeightEmu: number, handle: ImageResizeHandle, deltaWidthPt: number, deltaHeightPt: number, preserveAspect: boolean): {
readonly cx: number;
readonly cy: number;
};createBrowserAutomationHostfunctionSource ↗
An automation host over a live editor.
The editor keeps its own lifetime: dispose() on the returned host releases the change subscription this adapter took and leaves the editor mounted and editable.
save() validates pending form input. Invalid values and saves during an active edit return transaction-refused. For autosaving from change callbacks, use the asynchronous editor.save(), which waits for the active edit to finish.
declare function createBrowserAutomationHost(editor: DocxEditorInstance): AutomationHost;createDocxEditorfunctionSource ↗
Build an editor: the full Editor contract over a paginated surface.
Construction is separate from mounting. Pass a container and the document mounts immediately; omit it and nothing touches the DOM until attach(el) — the provider-first shape. detach() remounts from the saved bytes, which resets undo and the caret.
snapshot() is version-cached: the same reference until state actually moves, with reference-stable sub-objects, so it is safe as a useSyncExternalStore source.
declare function createDocxEditor(config: DocxEditorConfig): DocxEditorInstance;```ts
const editor = createDocxEditor({ document: bytes, modules: [reviewModule()] });
editor.attach(element);
editor.on('change', () => setDirty(true));
```createFontSourcefunctionSource ↗
Turn font bytes you ALREADY hold into a FontSource — a file input, IndexedDB, a bundler import. loadFonts covers URLs; this covers everything else, so no caller has to hand-assemble the record or reach for a hashing helper.
Returns a typed failure instead of throwing when the descriptor or the bytes are unusable, matching loadFonts: one bad face degrades itself, never its neighbours.
declare function createFontSource(bytes: Uint8Array, request: FontFaceRequest & {
readonly faceIndex?: number;
}, options?: {
readonly id?: string;
readonly maxFontBytes?: number;
}): {
readonly source: FontSource;
} | {
readonly failure: FontLoadFailure;
};createImageOverlayScrollPortfunctionSource ↗
An [ImageOverlayScrollPort](ImageOverlayScrollPort) over a real scroll container.
Reports the delta the element ACTUALLY scrolled, converted back to points — at the end of the document that is less than asked for, and the overlay must not move the image further than the page travelled.
declare function createImageOverlayScrollPort(scroller: HTMLElement, paintScale: number): {
scrollBy(deltaYPoints: number): number;
};createLayoutShapingfunctionSource ↗
declare function createLayoutShaping(configuration: FontConfiguration, instrumentation?: LayoutShapingInstrumentation): Promise<LayoutShapingOptions>;cropPercentFromCropPermillefunctionSource ↗
Permille crop → UI percent.
declare function cropPercentFromCropPermille(crop: ImageCropPermille): ImageCropPercent;cropPercentFromPermillefunctionSource ↗
OOXML permille → UI percent.
declare function cropPercentFromPermille(permille: number): number;cropPercentFromSourceCropfunctionSource ↗
Projection fraction (0–1) → UI percent (0–100).
declare function cropPercentFromSourceCrop(crop: SourceCrop): ImageCropPercent;cropPermilleFromCropPercentfunctionSource ↗
UI percent crop → permille for tree ops / a:srcRect.
declare function cropPermilleFromCropPercent(crop: ImageCropPercent): ImageCropPermille;cropPermilleFromPercentfunctionSource ↗
UI percent → OOXML permille.
declare function cropPermilleFromPercent(percent: number): number;cssPixelsToLayoutPointsfunctionSource ↗
CSS pixels back to layout points — what a pointer event's coordinates must go through.
declare function cssPixelsToLayoutPoints(pixels: number, paintScale: number): number;defaultChromeGroupsfunctionSource ↗
The groups of the DEFAULT toolbar arrangement, in bar order: every group that is not contextual. This is the registry's default bar — undo/redo through the editing-mode picker — and what both adapters render when the host composes nothing. Contextual slots (image.*, table.insert, file.save) remain available for explicit composition.
declare function defaultChromeGroups(): readonly ChromeGroup[];defaultTableLabelfunctionSource ↗
The English label for a furniture-insertion control.
The FALLBACK, for a host that has not wired its own translator — adapters pass their useTranslation result instead so the control follows the app's locale.
declare function defaultTableLabel(key: TableInteractionLabelKey): string;defineFontResolverfunctionSource ↗
Mark a function as an on-demand [FontResolver](FontResolver).
Wrap every resolver you put in a fonts list — useFonts(...), useDocxSource's fonts option, composeFontOrigins. The fonts PROP needs no marking, because a function there is always a resolver; a list also accepts the older zero-argument loader form ({ fonts: defaultFonts }), and this is what keeps the two apart.
Returns the same function object, mutated, so the mark survives being passed around and a marked resolver stays === to itself. It does NOT survive .bind() or being wrapped: both make a new function object. Re-mark the result.
ts
const brandFonts = defineFontResolver(async ({ families }) => ({
sources: await loadMine(families),
}));
Throws a TypeError on a frozen or sealed function, which cannot take the mark. That is deliberate: returning it unmarked would compile — the return TYPE says marked — and then lose every font at runtime.
declare function defineFontResolver<T extends FontResolver>(resolve: T): MarkedFontResolver<T>;disposeLayoutShapingfunctionSource ↗
Release native resources held by a shaping environment.
declare function disposeLayoutShaping(shaping: LayoutShapingOptions): void;dragIndentfunctionSource ↗
The indent a drag of handle to positionTwips produces.
Clamps differ from the MARGIN drags this ruler also carries, and deliberately:
- Indents may go NEGATIVE, pulling text into the margin, which Word allows. The floor is the sheet edge, not the margin. - There is no minimum text width. The 720-twip floor the margin drags use mirrors an engine refusal that does not exist for indents, and enforcing one here would make a narrow pull-quote unreachable. Left and right markers may MEET; they may not cross. - The left box needs a first-line clamp of its own. It does not move firstLine, so on a hanging paragraph dragging the box left can push the first-line marker off the sheet while the box itself is still in range. The drag stops when the LEADING marker lands.
declare function dragIndent(handle: RulerIndentHandle, positionTwips: number, indent: RulerIndent, page: RulerPageMetrics, options?: RulerDragOptions): RulerIndent;emuToOverlayPointsfunctionSource ↗
EMU to points. Unrounded, so overlay geometry keeps sub-point precision during a drag.
declare function emuToOverlayPoints(emu: number): number;equationAtPositionfunctionSource ↗
Boundary-inclusive lookup, matching the hyperlink and field atom popovers.
declare function equationAtPosition(equations: readonly SurfaceEquation[], position: SemanticPosition): SurfaceEquation | null;executeImageCommandfunctionSource ↗
Run an insert or replace, re-checking the same gates [canExecuteImageCommand](canExecuteImageCommand) applies.
Async because image bytes must be decoded to derive their natural extent before the drawing can be projected — the one editor command that cannot complete synchronously.
declare function executeImageCommand(editor: DocxEditorInstance, command: Extract<EditorCommand, {
type: 'insertImage' | 'replaceImage';
}>): Promise<ExecResult>;finalizeImageOverlayInteractionfunctionSource ↗
Recompute the committed overlay result from release pointer coordinates.
declare function finalizeImageOverlayInteraction(options: {
readonly session: ImageInteractionSession;
readonly deltaXPt: number;
readonly deltaYPt: number;
readonly accumulatedScrollPt: number;
readonly aspectLocked: boolean;
readonly shiftKey: boolean;
readonly anchorFrameOrigin: AnchorFrameOrigin | null;
}): FinalizedImageOverlayInteraction;formattingBarChromeGroupsfunctionSource ↗
The formatting-bar groups for one editor snapshot: the default bar, plus the contextual image group when a drawing is selected. Insertion without a selection lives in the packaged Insert menu (CHROME_MENUS), not in the bar — a host that wants a bar button places DocxEditor.Toolbar.ImageInsert itself.
declare function formattingBarChromeGroups(image: ImageContext | null): readonly ChromeGroup[];generateRulerTicksfunctionSource ↗
Ticks across one page dimension, matching the legacy cadence: eighth-inch minors with labelled inches, or millimetre minors with labelled centimetres.
declare function generateRulerTicks(lengthPx: number, unit: RulerUnit): RulerTick[];handlePositionfunctionSource ↗
Where a handle sits, in twips from the page's LEFT SHEET EDGE (not the margin).
declare function handlePosition(handle: RulerIndentHandle, indent: RulerIndent, page: RulerPageMetrics): number;isFontResolverfunctionSource ↗
Whether a value is a function marked by [defineFontResolver](defineFontResolver).
False for an unmarked function, which callers read as a zero-argument loader. Calling a resolver that way reads request.defaultFamily off undefined and throws, so the callers that make this choice say so rather than swallowing it — and the type-level mark on [MarkedFontResolver](MarkedFontResolver) is there to stop it reaching runtime at all.
declare function isFontResolver(value: unknown): value is MarkedFontResolver;isStaleImageInteractionCommitfunctionSource ↗
Whether a drag's commit should be refused because the document moved under it — the refusal to return, or null when the commit is still valid.
Checks the mount generation and both revisions captured by [captureImageMutationPreconditions](captureImageMutationPreconditions). A gesture spans many frames, so this is the one place that decides its coordinates still describe the document they were measured against.
declare function isStaleImageInteractionCommit(editor: Pick<DocxEditorInstance, 'surface' | 'mountGeneration'>, session: ImageInteractionSession): ExecResult | null;isTableChromeSlotfunctionSource ↗
Whether a chrome slot is one of the table-only ones. Narrows the type.
declare function isTableChromeSlot(slot: ChromeSlotId): slot is TableChromeSlotId;layoutPointsToCssPixelsfunctionSource ↗
Layout points to CSS pixels. Pair with [surfacePaintScale](surfacePaintScale) for the current zoom.
declare function layoutPointsToCssPixels(points: number, paintScale: number): number;loadFontsfunctionSource ↗
Fetch app-specified font URLs into verified, cache-backed FontSources.
Fetches ONLY the URLs listed — never a default host or engine-chosen CDN — and never rejects for a per-source failure: the result carries every admitted source and a typed entry for every drop. Compose the result with composeFontConfiguration.
declare function loadFonts(request: LoadFontsRequest): Promise<LoadFontsResult>;lowerColorValueForBorderfunctionSource ↗
Lower a public colour for table border ops. Theme colours require a resolved literal for paint; auto preserves OOXML automatic semantics with a black render fallback.
declare function lowerColorValueForBorder(color: ColorValue, themeColors: readonly DocumentThemeColorEntry[]): ColorLowerResult;lowerColorValueForFillfunctionSource ↗
Lower a public colour for cell fill. auto refuses because the cascade literal cannot be named honestly at commit time.
declare function lowerColorValueForFill(color: ColorValue, themeColors: readonly DocumentThemeColorEntry[]): ColorLowerResult;mountPaginatedSurfacefunctionSource ↗
Mount a paginated surface over DOCX bytes.
Returns a typed rejection rather than throwing: a failure here is a property of the file, and a host must be able to tell "not a package" from "no body" without parsing an error message.
declare function mountPaginatedSurface(container: HTMLElement, bytes: Uint8Array, options?: PaginatedSurfaceOptions): OpenPaginatedResult;overlayFrameToSheetCssPixelsfunctionSource ↗
Page-content frame → sheet-space CSS pixels (matches paintSelectionOverlay).
declare function overlayFrameToSheetCssPixels(layout: SemanticLayout, frame: OverlayFrameRect, coordinates: SurfaceOverlayCoordinates): {
readonly left: number;
readonly top: number;
readonly width: number;
readonly height: number;
};overlayHostOriginfunctionSource ↗
Where the painted surface's box begins inside overlay chrome's containing block, in CSS pixels.
[overlayFrameToSheetCssPixels](overlayFrameToSheetCssPixels) produces coordinates relative to the surface element — the box the pages paint into — but overlay chrome portals OUTSIDE that element, and its absolutely positioned pieces resolve against the nearest positioned ancestor. The surface centres itself inside that ancestor with a stylesheet margin, so a frame placed without this origin lands at the far left of the viewport, one full centring margin off the image it rings. offsetLeft/offsetTop measure against the same positioned ancestor the chrome resolves against — every element between the two is static — which is what makes the two spaces agree.
declare function overlayHostOrigin(surfaceElement: HTMLElement | null): {
readonly left: number;
readonly top: number;
};partOfNodeIdfunctionSource ↗
The part a NODE lives in, WITHOUT opening a story store.
session.partFor(scope) resolves a scope by opening that story's store, and an open store is retained for as long as its part is in the package. The cap is 64. So routing a pure READ — "is this control locked", "what is its tab index" — through partFor spent a permanent slot per part touched, and an id naming no node at all still spent one, because the part name is matched from the id's prefix before anything is looked up. Sixty-four such reads and no further header could be opened for the rest of the session, silently.
Read straight from the live package instead. Ids carry the canonical part name, so this is a map lookup.
declare function partOfNodeId(session: Pick<TreeDocxSessionView, 'currentPackage' | 'part'>, nodeId: string | undefined): OoxmlPart | null;pointsToEmufunctionSource ↗
Points to EMU, rounded — EMUs are integral in the file.
declare function pointsToEmu(points: number): number;positionInputFromPropertiesCommandfunctionSource ↗
Extract the position input from an image-properties command, or null when it carries none.
declare function positionInputFromPropertiesCommand(command: {
readonly horizontalEmu?: number;
readonly verticalEmu?: number;
readonly relativeToH?: string;
readonly relativeToV?: string;
}, selected: {
readonly position?: DrawingPositionInput | null;
} | null): DrawingPositionInput;probeTableChromeCommandfunctionSource ↗
Probe command for Editor.can — uses the draft's active target and a well-formed value.
declare function probeTableChromeCommand(slot: TableChromeSlotId, draft?: TableChromeDraft): EditorCommand | null;propertiesCommandHasPositionFieldsfunctionSource ↗
Whether an image-properties command carries any positioning fields at all.
declare function propertiesCommandHasPositionFields(command: {
readonly horizontalEmu?: number;
readonly verticalEmu?: number;
readonly relativeToH?: string;
readonly relativeToV?: string;
}): boolean;resizePreservesAspectfunctionSource ↗
Whether this handle drag should preserve aspect ratio.
declare function resizePreservesAspect(handle: ImageResizeHandle, aspectLocked: boolean, shiftKey: boolean): boolean;resolveColorValueToCssfunctionSource ↗
Resolve any public colour to a CSS #RRGGBB string for chrome display.
declare function resolveColorValueToCss(color: ColorValue | undefined | null, themeColors: readonly DocumentThemeColorEntry[], defaultHex?: string): string;resolveEditorModulesfunctionSource ↗
Resolve construction-time modules into the registry the instance dispatches over.
declare function resolveEditorModules(modules: readonly EditorModule[] | undefined): EditorModuleRegistry;resolveImageResourceLimitsfunctionSource ↗
Resolve caller overrides into frozen image limits; hard ceilings cannot be raised.
declare function resolveImageResourceLimits(overrides?: Partial<ImageResourceLimits>): ImageResourceLimits;resolveSvgIntrinsicSizefunctionSource ↗
Intrinsic size of an SVG, resolved the way a browser sizes one: absolute width/height first, then viewBox for the missing axis or ratio, then the CSS 300x150 default.
This is metadata for insert and reset-to-natural-size only. Layout uses the authored wp:extent and the browser rasterizes into that box, so nothing here sizes an allocation and an out-of-range value is clamped rather than refused.
declare function resolveSvgIntrinsicSize(bytes: Uint8Array, limits: ImageResourceLimits): ValidatedRasterHeader | null;resolveThemeColorHexfunctionSource ↗
Resolve a theme colour to literal hex. When both tint and shade are present, ECMA-376 §17.3.2.6 / §17.3.4 / §17.3.5 require tint precedence — shade is ignored for paint.
declare function resolveThemeColorHex(color: Extract<ColorValue, {
kind: 'theme';
}>, themeColors: readonly DocumentThemeColorEntry[]): {
ok: true;
hex: string;
} | {
ok: false;
reason: string;
};resolveZoomModefunctionSource ↗
Normalize the 'auto' shorthand a host may pass anywhere a [ZoomMode](ZoomMode) is accepted.
Returns null for a value that is neither, so callers refuse rather than silently substituting a mode the caller did not ask for.
declare function resolveZoomMode(mode: ZoomMode | 'auto'): ZoomMode | null;rulerPageBoxfunctionSource ↗
The first page's box, which the rulers measure against.
declare function rulerPageBox(pages: readonly {
readonly index: number;
readonly box: {
width: number;
height: number;
};
}[]): {
width: number;
height: number;
} | null;runSavefunctionSource ↗
Save goes straight to Editor.save() — it is not a command.
declare function runSave(editor: Editor | null): Promise<ArrayBuffer>;runTableChromeCommandfunctionSource ↗
Run one table chrome pick with explicit draft state; returns the post-pick draft on success.
declare function runTableChromeCommand(editor: Editor | null, slot: TableChromeSlotId, value: unknown, draft: TableChromeDraft): RunTableChromeCommandResult;runTableCommandfunctionSource ↗
Run a table command: planner-backed can first, then exec only when allowed.
declare function runTableCommand(editor: Editor | null, command: EditorCommand): ExecResult;runToolbarCommandfunctionSource ↗
Run a toolbar control: can first, then exec only if it said yes. Returns the engine's refusal untouched when it said no, so a caller cannot mistake a declined command for a no-op.
declare function runToolbarCommand(editor: Editor | null, id: ChromeSlotId,
value?: unknown): ExecResult;sameZoomModefunctionSource ↗
Whether two modes say the same thing.
snapshotsEqual compares zoomMode by IDENTITY, and a host's zoomMode prop is an object — <DocxEditor zoomMode={{ type: 'fit', fit: 'pageWidth' }} /> is a fresh literal on every render, which is the spelling the docs show. Without a value comparison somewhere, each of those renders reinstalled the observer, refitted, bumped the tick, and re-rendered every useEditorState consumer in the tree — including the page selector that the slice memoization exists to keep asleep. The lane holds its object and compares by value here.
declare function sameZoomMode(a: ZoomMode, b: ZoomMode): boolean;selectedDrawingOverlayTargetOffunctionSource ↗
The painted geometry of the selected drawing, for the resize/move overlay — or null.
Stricter than [selectedImageStateOf](selectedImageStateOf): it also requires a COLLAPSED selection, because a range that merely contains a drawing is a text selection, and drawing handles over it would claim an object the user did not single out.
declare function selectedDrawingOverlayTargetOf(surface: PaginatedSurface | null): SelectedDrawingOverlayTarget | null;selectedImageStateOffunctionSource ↗
The selected image and what may be done to it, or null when nothing image-like is selected.
Null covers more than "no selection": a placeholder graphic, a drawing the file marks hidden, and one whose select lock is set all read as no selection, because chrome that offered resize handles on them would promise an edit the store is about to refuse.
declare function selectedImageStateOf(surface: PaginatedSurface | null): SelectedImageState | null;snapTwipsfunctionSource ↗
Round to the ruler's grid, or to the twip when the drag is precise.
declare function snapTwips(value: number, unit: RulerUnit, precise: boolean): number;sniffImageMimefunctionSource ↗
Signature sniffing — authoritative over declared content type.
declare function sniffImageMime(bytes: Uint8Array): RenderableImageMime | PreservedImageMime | 'unknown';sourceCropFromCropPercentfunctionSource ↗
UI percent (0–100) → projection fraction (0–1).
declare function sourceCropFromCropPercent(crop: ImageCropPercent): SourceCrop;surfaceExtentfunctionSource ↗
declare function surfaceExtent(layout: SemanticLayout, materialize: ReadonlySet<number> | undefined): SurfaceExtent;surfacePaintScalefunctionSource ↗
Points → CSS pixels at the given zoom (matches mountPaginatedSurface / semantic paint).
declare function surfacePaintScale(zoom: number): number;tableChromeIconPathsfunctionSource ↗
Material Symbol paths for one table chrome icon name.
declare function tableChromeIconPaths(name: keyof typeof GENERATED_ICON_PATHS): readonly string[];tableChromeLabelKeyForTargetfunctionSource ↗
The i18n key naming one border target, for a trigger that shows the active scope.
Falls back to the "all" key rather than throwing: a label is chrome, and a missing one should not take the toolbar down.
declare function tableChromeLabelKeyForTarget(target: TableBorderEdgeTarget): string;tableChromeToolbarStatefunctionSource ↗
Enabled state for one table chrome slot using explicit draft state.
declare function tableChromeToolbarState(editor: Editor | null, slot: TableChromeSlotId, draft?: TableChromeDraft): ToolbarCommandState;tableChromeVisiblefunctionSource ↗
Contextual table chrome is visible when the engine reports table context.
declare function tableChromeVisible(table: TableContext | null | undefined): boolean;tableCommandStatefunctionSource ↗
Planner-backed can/plan pair — production gate for table commands. Task 9 maps chrome slots.
declare function tableCommandState(command: EditorCommand, surface: PaginatedSurface): {
readonly can: CanResult;
readonly plan: TableCommandPlan;
};tableCommandToolbarStatefunctionSource ↗
Enabled state for a table command when the caller holds the paginated surface.
Uses the same planner-backed tableCommandState as Editor.can/gateTableCommand. Chrome slot mapping for table controls is Task 9 — this helper is the shared can-before-exec seam for arbitrary table commands.
declare function tableCommandToolbarState(surface: PaginatedSurface | null, command: EditorCommand): Pick<ToolbarCommandState, 'enabled' | 'disabledReason'>;toEditorFontErrorfunctionSource ↗
declare function toEditorFontError(error: unknown): EditorFontError;toolbarCommandStatefunctionSource ↗
Ask the engine whether one control should be enabled.
declare function toolbarCommandState(editor: Editor | null, id: ChromeSlotId): ToolbarCommandState;toolbarCommandStatesfunctionSource ↗
Enabled state for several controls in one pass.
declare function toolbarCommandStates(editor: Editor | null, ids: readonly ChromeSlotId[]): readonly ToolbarCommandState[];validateDrawingPositionInputfunctionSource ↗
Validate a position input, refusing offsets or bases outside what OOXML allows.
declare function validateDrawingPositionInput(position: DrawingPositionInput): boolean;validateImageCropPercentfunctionSource ↗
Whether a crop is expressible: every edge finite and in range, and opposite edges not overlapping.
Opposite edges matter — a left plus right crop summing past 100% describes a negative width, which DrawingML has no way to store.
declare function validateImageCropPercent(crop: ImageCropPercent): boolean;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;validateSetImagePositionCommandfunctionSource ↗
Validate a set-position command before it reaches the store.
declare function validateSetImagePositionCommand(command: {
readonly horizontalEmu?: number;
readonly verticalEmu?: number;
readonly relativeToH?: string;
readonly relativeToV?: string;
}, mode: 'frame' | 'simple'): boolean;validateThemeModifierfunctionSource ↗
Clamp and validate an OOXML theme modifier fraction (0, 1].
declare function validateThemeModifier(value: unknown): value is number;Interfaces (78)
AnchorFrameOrigininterfaceSource ↗
Where an anchored drawing's positioning frame begins, in layout points.
An anchored drawing's offsets are relative to a base the file names (page, margin, column, …), so a move drag needs that base's origin to turn a pointer delta into a stored offset.
interface AnchorFrameOrigin| Member | Type | Summary |
|---|---|---|
| x | number | |
| y | number |
ChromeControlinterfaceSource ↗
One toolbar control as the registry describes it — what it renders as, never whether it is enabled.
Enabled state has exactly ONE source, toolbarCommandState, which asks the engine. A descriptor carrying its own disabled flag would be a second answer that goes stale the moment the engine wires the slot.
interface ChromeControl<Id extends string = string>| Member | Type | Summary |
|---|---|---|
| defaultToolbar? | false | `false` keeps this public slot composable but omits it from the default toolbar. |
| id | Id | Stable control id, unique WITHIN its group. Public API; renames are breaking. |
| labelKey | string | i18n key for the accessible name and tooltip. Never hardcoded English. |
| paths | readonly string[] | null | Material Symbols path data, or null for a non-icon control (a picker). |
| shape? | ChromeControlShape | How it renders. Defaults to `icon`. |
| state | ChromeControlState | |
| swatch? | string | Swatch colour for a `colorSplit` control. |
| valueKey? | string | For pickers: the i18n key of the placeholder value shown. |
| valueText? | string | Displayed value for a stepper or dropdown (an i18n key, or a literal for numbers). |
ChromeGroupinterfaceSource ↗
One toolbar group: the taxonomy both adapters derive their default arrangement FROM.
Never hand-list controls in an adapter — a default toolbar is built by walking CHROME_GROUPS, so a slot added here appears in React and Vue without either being edited.
interface ChromeGroup<Id extends string = string, ControlId extends string = string>| Member | Type | Summary |
|---|---|---|
| contextual? | true | Not part of the DEFAULT toolbar arrangement. The chrome spec shows these controls only in a context the engine does not model yet (an image or table selection), or not at all (save belongs in the host's File menu, never in the bar). Their slots stay public for composition — a host can still place `image.insert` or `file.save` explicitly — but the default chrome is the registry's default bar, which ends at the editing-mode picker. |
| controls | readonly ChromeControl<ControlId>[] | |
| id | Id | Stable group id. Public API; renames are breaking. |
| labelKey | string |
ChromeMenuinterfaceSource ↗
One menu of the menu bar.
interface ChromeMenu| Member | Type | Summary |
|---|---|---|
| entries | readonly ChromeMenuEntry[] | |
| id | ChromeMenuId | |
| labelKey | string |
ChromeMenuItemEntryinterfaceSource ↗
A row that runs one chrome slot.
interface ChromeMenuItemEntry| Member | Type | Summary |
|---|---|---|
| kind | 'item' | |
| labelKey? | string | Plain-label override for this row. |
| picker? | 'tableGrid' | The row opens a size PICKER instead of firing on click — Word's insert-table grid. The slot still owns the label, the icon and the enabled state; only the dispatch differs, and the picked size is what the host sends. |
| shortcutKey? | string | i18n key of the shortcut shown right-aligned on the row (`toolbar.saveShortcut`). |
| slot | ChromeSlotId |
ChromeMenuSeparatorEntryinterfaceSource ↗
A horizontal rule between groups of rows.
interface ChromeMenuSeparatorEntry| Member | Type | Summary |
|---|---|---|
| kind | 'separator' |
ChromeMenuSubmenuEntryinterfaceSource ↗
A row that opens a nested panel of rows (Insert › Break).
It carries its own label and icon rather than a slot, because a submenu PARENT has no command: clicking it opens the panel. Giving it a slot would mint a public id for a control that can never be enabled, and toolbarCommandState would have to invent an answer about it.
interface ChromeMenuSubmenuEntry| Member | Type | Summary |
|---|---|---|
| items | readonly ChromeMenuEntry[] | |
| kind | 'submenu' | |
| labelKey | string | |
| paths | readonly string[] | null |
CollaborationModuleContributioninterfaceSource ↗
What a collaboration module contributes: the replica the surface attaches.
interface CollaborationModuleContribution| Member | Type | Summary |
|---|---|---|
| session | EditorCollaborationSession | A ready session. The host creates the Yjs room, then wraps it with `collaborationModule({ session })`. |
ComposeFontOriginsOptionsinterfaceSource ↗
Diagnostics hook for ordered font-origin composition.
interface ComposeFontOriginsOptions| Member | Type | Summary |
|---|---|---|
| onOriginFailure? | (failure: FontOriginFailure) => void | Fire-and-forget diagnostics; returned promises are observed but do not delay resolution. |
DocxEditorConfiginterfaceSource ↗
Everything [createDocxEditor](createDocxEditor) accepts. Every field is optional.
container is the one that changes the shape of the whole lifecycle: omitting it produces an instance that does no DOM work until attach(el), which is what lets a provider own the editor before any component has rendered a mount point.
interface DocxEditorConfig| Member | Type | Summary |
|---|---|---|
| author? | string | |
| container? | HTMLElement | The element the paginated surface mounts into. The surface owns this subtree. |
| document? | DocumentSource | A document to load at construction: DOCX bytes, or `'blank'` for Word's blank template. A `DocumentHandle` cannot be re-opened (the handle is identity, not content), so passing one emits a typed `error` event rather than silently loading nothing. Omitting this mounts NO document, which is not the same as an empty one. |
| fonts? | FontConfiguration | FontConfigurationFragment | FontResolver | Font bytes for Word-accurate (HarfBuzz-shaped) line wrap and pagination. Omitted, layout falls back to a fixed-width estimate; fonts embedded in the document are wired in automatically either way. For Word's default faces (Calibri, Times New Roman, …) pass `await loadDefaultFonts()` from `@docx-editor.dev/fonts` — a bare fragment (`{ sources, substitutions }`) is accepted and composed with defaults, or merge several origins yourself with `composeFontConfiguration`. Sampled per load; failures degrade to the fixed measurer and report through `onFontError`. |
| imageDecodePort? | ImageDecodePort | Override raster decode for insert/replace image commands; defaults to browser/headless. |
| locale? | string | BCP-47 locale for regional date input and generated labels; defaults to en-US. |
| mode? | 'edit' | 'view' | 'suggesting' | The mode the editor opens in — one prop, matching the toolbar's three-state pill. |
| modules? | readonly EditorModule[] | Capability modules to register — the seam `@docx-editor.dev/pro` plugs in through. Omitted, the editor runs the free tier: lossless round-trip, final-state revision rendering, review chrome disabled with the engine's reason. See [EditorModule](EditorModule). |
| onFontError? | (error: EditorFontError) => void | |
| revisionStyles? | RevisionStyles | How painted tracked changes are coloured. Presentation only — nothing is serialised. |
| tableInteractionLabel? | (key: 'table.insertRowBelow' | 'table.insertColumnRight') => string | Localized labels for table insertion furniture on the painted surface. |
| translate? | (key: string, params?: Record<string, string | number>) => string | Drawing and form-control UI labels; defaults to English when omitted. |
| zoom? | number | The scale to open at, as a fixed number. |
| zoomMode? | ZoomMode | 'auto' | Where the scale comes from. Defaults to `'auto'` — fit the page width, between 50% and 100% — unless [DocxEditorConfig.zoom](DocxEditorConfig.zoom) is supplied, which means fixed. |
DocxEditorInstanceinterfaceSource ↗
The concrete facade type: the full Editor contract plus the instance-only surface.
surface, stateVersion, attach and detach live HERE rather than on Editor: they are what a store binding and a mounting host need, not what document commands need. Production adapters program against Editor for everything else.
interface DocxEditorInstance extends Editor| Member | Type | Summary |
|---|---|---|
| attach | | Mount into `el`. If the instance holds pending document bytes (created without a container, or previously detached), they mount now — under the shaped measurer when fonts have resolved in the meantime. Attaching while already mounted elsewhere moves the live content via `session.save()`. |
| collaborationSession | | The live collaboration replica, or null when this editor is not in a room. |
| detach | | Tear down the painted surface, stashing the CURRENT document bytes (`session.save()`) so a later `attach` restores the content — but not the undo stack or the caret. No-op when already detached or destroyed. |
| fontMeasurement | | Which measurer the current document's layout runs on, and whether shaped resolution is still in flight — the honest "are wrap points Word-accurate yet?" readout a host shows instead of guessing. `fixed` with `resolving: false` is the steady state for a document with no usable font source (the documented zero-config fallback); `shaped` means HarfBuzz measurement over real font bytes. Changes bump `stateVersion()`. |
| getReviewAuthors | | Every author the review surface DRAWS, in Word's slot order, with the colour the review chrome draws them in. The discovery surface a legend or colour picker builds on — authors depend on the loaded file, so they cannot be known at configuration time. |
| isReviewAuthorVisible | | Whether this author's revisions and comments are shown in the current review view. |
| mountGeneration | number | Bumps on mount, detach, destroy, and document reload — guards async image intents. |
| presenceColorFor | | The presence colour the engine paints for one display name — the answer the remote caret label takes, so chrome built on this cannot disagree with the painted caret. |
| setAllReviewAuthorsVisible | | Show or hide every reviewer in one layout pass. |
| setAuthor | | Set the author for runtime editor state. |
| setEquationChrome | | Wire the host equation popover to painted equation clicks. |
| setHyperlinkChrome | | Wire the host's hyperlink chrome to the engine's gestures — a click on an external link, and Ctrl/Cmd+K. Returns an unsubscribe that restores whatever was registered before, so a popover component can register in an effect and clean up in its teardown. |
| setLocale | | Set regional date input and generated labels without rebuilding the editor. Stored dates are preserved; an in-progress field edit retains its starting locale. Omitted, invalid, and unsupported locales use en-US. Translation catalogues fall back by language. |
| setMode | | Set the host editing mode without rebuilding the editor. |
| setRemoteCaretLabelHost | | Render the host's own component as the remote-caret label, or restore the default collaborator-name label with `null`. The engine keeps owning label geometry, class, and presence colour; the host owns the content of each published element. |
| setReviewAuthorVisible | | Show one author's markup, or render their revisions as accepted and hide their comments. This changes view state only. It does not apply tree operations or change saved bytes. |
| setRevisionStyles | | Replace how tracked changes are coloured, live. Paint-level: pages repaint without a layout pass, and the caret, selection and undo history stay where they are. Pass `'author'` to restore the default, or `'kind'` to opt out to the green/red rendering. Survives a document reload. |
| setTranslate | | Set the drawing and form-control label resolver without rebuilding the editor. Open dialogs preserve their controls and input; later surface mounts use the same resolver. |
| showAllReviewAuthors | | Restore every reviewer to the shown state. |
| stateVersion | | Monotonic version of the observable editor state. Bumps whenever anything `snapshot()` reports could have moved — a committed change, a selection move, zoom, load success or failure, attach/detach, destroy. An external store (React's `useSyncExternalStore`) uses it as a cheap "did anything change" signal; `snapshot()` itself is cached per version and returns a stable reference between bumps. |
| surface | PaginatedSurface | null | The underlying paginated surface for harnesses and tests that need capabilities the contract does not carry yet (select-all, node-id addressed selection). |
DrawingPositionInputinterfaceSource ↗
An anchored drawing's position: offsets, and the frames they are relative to.
The relative-to bases matter as much as the offsets. Writing an offset without preserving its base re-anchors the drawing against a different reference and moves it somewhere nobody asked.
interface DrawingPositionInput| Member | Type | Summary |
|---|---|---|
| horizontalEmu? | number | |
| mode? | 'frame' | 'simple' | `'simple'` when `@simplePos="1"`: `horizontalEmu` / `verticalEmu` are authoritative `wp:simplePos` x/y. `'frame'` (default) uses positionH/V relative frames. |
| relativeToH? | DrawingHorizontalReferenceFrame | |
| relativeToV? | DrawingVerticalReferenceFrame | |
| verticalEmu? | number |
EditorModuleinterfaceSource ↗
One registered capability module. Registration is construction-time (createDocxEditor({ modules })) and immutable for the instance's lifetime.
interface EditorModule| Member | Type | Summary |
|---|---|---|
| collaboration? | CollaborationModuleContribution | Collaboration replica. Absent, the editor stays single-user: local undo stays the authority, and `snapshot().collaborationStatus` is `'inactive'`. |
| customNodePayloadNamespaces? | readonly string[] | customXml payload namespaces this module OWNS, swept for orphans when a document opens. |
| customNodes? | readonly unknown[] | Custom inline node definitions. Reserved: the definition shape lands with the custom-nodes lane; the registry carries them opaquely until then. |
| id | string | Diagnostic identity (`'review'`, `'custom-nodes'`); not a dispatch key. |
| onCustomNodeDiagnostic? | (diagnostic: unknown) => void | Told when the recognition pass finds something wrong with a node in THIS editor's document. |
| review? | ReviewModuleContribution | Review capability: queue derivation, commands gate, display modes. |
EditorModuleRegistryinterfaceSource ↗
The resolved registry the editor instance holds: at most one review contribution and at most one collaboration contribution (first registration wins for each), all custom node definitions in registration order.
interface EditorModuleRegistry| Member | Type | Summary |
|---|---|---|
| collaboration | CollaborationModuleContribution | null | |
| customNodeDiagnostics | readonly ((diagnostic: unknown) => void)[] | Every registered diagnostic listener, in registration order. |
| customNodePayloadNamespaces | readonly string[] | Every claimed payload namespace, deduplicated, in registration order. |
| customNodes | readonly unknown[] | |
| review | ReviewModuleContribution | null |
EquationActivationinterfaceSource ↗
A user click on one painted equation.
interface EquationActivation| Member | Type | Summary |
|---|---|---|
| equation | SurfaceEquation | |
| rect | {
readonly left: number;
readonly top: number;
readonly right: number;
readonly bottom: number;
} |
EquationChromeHandlersinterfaceSource ↗
Host chrome that edits a clicked Office Math equation.
interface EquationChromeHandlers| Member | Type | Summary |
|---|---|---|
| onPopover? | (activation: EquationActivation) => void |
EquationOpsinterfaceSource ↗
Surface equation reads and atomic replace/remove writes.
interface EquationOps| Member | Type | Summary |
|---|---|---|
| applyEquation | | |
| can | | Whether equation chrome can run an action, with the engine-owned refusal reason. |
| equationAtCaret | | |
| equationById | | |
| equationsInCaretParagraph | | |
| removeEquation | |
FinalizedImageOverlayInteractioninterfaceSource ↗
The committed result of a whole drag, recomputed from the release coordinates.
Recomputed rather than accumulated from the per-frame previews, so rounding applied once per frame cannot add up into a final extent that differs from where the pointer actually stopped.
interface FinalizedImageOverlayInteraction extends ImageResizeResult| Member | Type | Summary |
|---|---|---|
| position | DrawingPositionInput | null |
FontConfigurationBaseinterfaceSource ↗
The base of a composition: everything a FontConfiguration carries, all optional. Omitted fields take the documented defaults (epoch 0, maxFontBytes at the engine hard maximum, defaultFont Calibri at 11pt — Word's own default face and size).
interface FontConfigurationBase extends FontConfigurationFragment| Member | Type | Summary |
|---|---|---|
| defaultFont? | FontConfiguration['defaultFont'] | The face used when a run names no font. Defaults to Word's own: Calibri at 11pt. |
| epoch? | number | Identity of this configuration's byte set. The engine uses it to tell one resolved font set from another; leave it unset and the editor supplies the load sequence. |
| language? | string | BCP-47 tag passed to the shaper for language-sensitive shaping. |
| maxFontBytes? | number | Per-face byte ceiling. Defaults to the engine hard maximum; lower it to tighten intake. |
FontConfigurationFragmentinterfaceSource ↗
A partial font configuration one origin contributes: sources, substitutions, or both. loadDefaultFonts() (the substitute package) and loadFonts() (the fetch helper) both return this shape, so every origin composes through composeFontConfiguration the same way.
interface FontConfigurationFragment| Member | Type | Summary |
|---|---|---|
| sources? | readonly FontSource[] | |
| substitutions? | readonly FontSourceSubstitution[] |
FontLoadFailureinterfaceSource ↗
One face that did not load, with whatever evidence the failure produced.
Non-fatal: [LoadFontsResult](LoadFontsResult) still carries every source that succeeded, and the affected family falls back to the engine's fixed measurement.
interface FontLoadFailure| Member | Type | Summary |
|---|---|---|
| actualHash? | string | |
| diagnostic? | string | |
| expectedHash? | string | |
| reason | FontLoadFailureReason | |
| request | FontFaceRequest | |
| status? | number | HTTP status for `httpError`; hashes for `hashMismatch`. |
| url | string |
FontMeasurementStateinterfaceSource ↗
Which measurer the current document's layout runs on, and whether shaped resolution is still in flight. Returned by [DocxEditorInstance.fontMeasurement](DocxEditorInstance.fontMeasurement).
interface FontMeasurementState| Member | Type | Summary |
|---|---|---|
| measurer | 'fixed' | 'shaped' | `fixed` estimates advance widths; `shaped` measures real font bytes with HarfBuzz. |
| producer? | string | The shaped measurer's identity (admitted face hashes); absent while fixed. |
| resolving | boolean | True while font resolution for the current document is still running. |
FontOriginFailureinterfaceSource ↗
A failed font origin or a partial failure in an otherwise usable fragment.
interface FontOriginFailure| Member | Type | Summary |
|---|---|---|
| cause | unknown | |
| originIndex | number | Zero-based position in the first-wins origin list. |
| originName? | string | Resolver function name when one is safely available. |
FontResolutionRequestinterfaceSource ↗
What the document turned out to need, handed to an on-demand resolver.
The families are the ones the file actually names — already name-validated and capped, so a resolver may treat them as a list to look up, never as URLs or paths to build.
interface FontResolutionRequest| Member | Type | Summary |
|---|---|---|
| defaultFamily | string | The face a run naming no font resolves to, so a resolver can cover it too. |
| families | readonly string[] | Families needed by the document, deduped and capped at [MAX_RESOLVER_FAMILIES](MAX_RESOLVER_FAMILIES). Order is deterministic but may express host priority; do not sort it before resolving. |
| resolvedFaces? | readonly FontFaceRequest[] | Faces an EARLIER origin in the same composition can already PAINT — either because it supplied the bytes, or because it mapped that face onto one it did supply. |
| signal? | AbortSignal | Cancels document-scoped resolution; network-backed resolvers should pass it to fetch. |
FontResolverMarkinterfaceSource ↗
The type-level half of the mark: what [defineFontResolver](defineFontResolver) adds to a function's type so a FontOrigin list can REQUIRE it.
Declared with a string key so @docx-editor.dev/fonts can declare an identical interface and have the two unify without importing anything from the engine. Set at runtime as well as in the type — non-enumerable, so it stays out of Object.keys and out of a host's own spread.
interface FontResolverMark| Member | Type | Summary |
|---|---|---|
| "docx-editor.dev/font-resolver" | true | Always `true`. Set non-enumerably by [defineFontResolver](defineFontResolver). |
FontUrlSourceinterfaceSource ↗
One URL to fetch and the face it claims to be.
interface FontUrlSource| Member | Type | Summary |
|---|---|---|
| faceIndex? | number | |
| family | string | |
| hash? | string | Expected `sha256:` content hash. When present, mismatching bytes are REFUSED — pin this for any URL not under the app's sole control. |
| style | 'normal' | 'italic' | |
| url | string | |
| weight | number |
HyperlinkActivationinterfaceSource ↗
A click on a painted link, after native navigation was refused.
interface HyperlinkActivation| Member | Type | Summary |
|---|---|---|
| link | SurfaceHyperlink | |
| rect | {
readonly left: number;
readonly top: number;
readonly bottom: number;
readonly right: number;
} | The clicked line fragment's viewport rect, so a popover can be placed under it. |
HyperlinkChromeHandlersinterfaceSource ↗
The host chrome that answers the engine's hyperlink gestures.
A CLICK on an external link and Ctrl/Cmd+K both mean "the user wants the link UI", and the engine deliberately does not know what that looks like. Registered rather than passed at construction because the chrome mounts after the editor does, and it survives a document reload — the surface is rebuilt, the handlers are not.
interface HyperlinkChromeHandlers| Member | Type | Summary |
|---|---|---|
| onPopover? | (activation: HyperlinkActivation) => void | A plain click on an external or inert link: show the popover at `activation.rect`. |
| onRequest? | () => void | Ctrl/Cmd+K: open insert-or-edit for the selection. |
HyperlinkOpsinterfaceSource ↗
Reading and writing hyperlinks on the surface.
Every href that leaves here has already been through sanitizeHref — targets come from files, so javascript:, data: and vbscript: are dropped at the parse boundary rather than trusted to be filtered by whoever renders them.
interface HyperlinkOps| Member | Type | Summary |
|---|---|---|
| applyHyperlink | | Apply a link to the selection, or retarget the one the caret is already in. |
| fieldLinkAtCaret | | The FIELD link whose painted atom the caret sits on, or null. |
| linkAtCaret | | The link the caret sits in, or null. |
| linkById | | The link with this node id, or null. |
| linksInCaretParagraph | | Every link in the paragraph the caret is in. |
| removeHyperlink | | Take the link off the one at the caret (or a named one). Returns whether it committed. |
ImageCropPercentinterfaceSource ↗
Crop edge in UI percent (0–100).
interface ImageCropPercent| Member | Type | Summary |
|---|---|---|
| bottom | number | |
| left | number | |
| right | number | |
| top | number |
ImageCropPermilleinterfaceSource ↗
Crop edge in OOXML permille (0–100000).
interface ImageCropPermille| Member | Type | Summary |
|---|---|---|
| bottom | number | |
| left | number | |
| right | number | |
| top | number |
ImageDecodePortinterfaceSource ↗
The injected image decoder.
A port rather than a direct Image/createImageBitmap call, so a worker or server runtime supplies its own and the engine never reaches for a browser global.
interface ImageDecodePort| Member | Type | Summary |
|---|---|---|
| convertPreserved | | Optional conversion of media an `<img>` cannot render (EMF/WMF metafiles, TIFF) into a renderable raster. The returned bytes are untrusted and re-enter the full raster validation path (sniff, header, pixel caps, decode) before they can become a ready resource. A null return declines the format and keeps the labelled placeholder; so does a throw, as `decode-failed`. |
| decode | |
ImageInteractionSessioninterfaceSource ↗
One in-flight image drag: where it started, and everything needed to decide at commit time whether the document still describes what the gesture was planned against.
Both revisions are captured because they move independently — layout can re-flow without the package changing, and vice versa.
interface ImageInteractionSession| Member | Type | Summary |
|---|---|---|
| anchorFrameOrigin | {
readonly x: number;
readonly y: number;
} | null | |
| drawingNodeId | string | |
| handle | ImageResizeHandle | null | |
| kind | 'inline' | 'anchored' | |
| layoutRevision | number | |
| mode | 'move' | 'resize' | |
| packageRevision | number | |
| preconditions | ImageMutationPreconditions | |
| startBounds | {
readonly x: number;
readonly y: number;
readonly width: number;
readonly height: number;
} | |
| startHeightEmu | number | |
| startPosition | DrawingPositionInput | null | |
| startWidthEmu | number | |
| transform | DrawingTransform |
ImageOverlayScrollPortinterfaceSource ↗
How an image drag scrolls the page when it reaches the viewport edge.
Returns the delta ACTUALLY applied rather than the one requested, because a drag at the end of the document cannot scroll further and the overlay must not move the image by a distance the page did not travel.
interface ImageOverlayScrollPort| Member | Type | Summary |
|---|---|---|
| scrollBy | | Scroll by a preview delta and return the actual applied document-space delta in points. |
ImageResizeResultinterfaceSource ↗
One resize frame: the extent to store, and the box to draw while the pointer is still down.
Both, because they are different spaces — the extent is EMU for the file, the preview is points for the overlay — and computing them separately would let the handle drift from the rectangle it is dragging.
interface ImageResizeResult| Member | Type | Summary |
|---|---|---|
| heightEmu | number | |
| position | DrawingPositionInput | null | |
| previewBounds | {
readonly x: number;
readonly y: number;
readonly width: number;
readonly height: number;
} | |
| widthEmu | number |
ImageResourceLimitsinterfaceSource ↗
Trust-boundary caps specific to image decoding and embedding.
interface ImageResourceLimits| Member | Type | Summary |
|---|---|---|
| maxDecodedBytes | number | |
| maxDimension | number | |
| maxEncodedBytes | number | |
| maxExternalRedirects | number | |
| maxPixels | number | |
| maxPolygonPoints | number |
LoadFontsRequestinterfaceSource ↗
What to fetch, and under what limits.
Only sources is required. Each carries its own expected hash, so bytes are trusted by CONTENT rather than by origin — a swapped asset fails admission even from a trusted host.
interface LoadFontsRequest| Member | Type | Summary |
|---|---|---|
| cacheName? | string | Cache API bucket name; default `docx-editor-fonts`. |
| fetcher? | typeof fetch | Injectable for tests and CSP-constrained hosts; defaults to global `fetch`. |
| maxFontBytes? | number | Per-font byte ceiling; defaults to the engine hard maximum. |
| sources | readonly FontUrlSource[] |
LoadFontsResultinterfaceSource ↗
What one loadFonts call produced: the faces that arrived, plus the ones that did not.
A FontConfigurationFragment, so it composes straight into composeFontConfiguration alongside other font sources. Partial success is the normal case — compose it even with failures present.
interface LoadFontsResult extends FontConfigurationFragment| Member | Type | Summary |
|---|---|---|
| failures | readonly FontLoadFailure[] | |
| sources | readonly FontSource[] |
OverlayFrameRectinterfaceSource ↗
A rectangle in one page's content frame, in layout points.
interface OverlayFrameRect| Member | Type | Summary |
|---|---|---|
| height | number | |
| pageIndex | number | |
| width | number | |
| x | number | |
| y | number |
PaginatedSurfaceinterfaceSource ↗
The mounted, painted, editable document — the layer createDocxEditor builds its contract on.
The painted pages ARE the editable surface: they are contenteditable, but the DOM is a picture. Browser mutations are prevented and re-expressed as tree ops, and selection maps only through data-paragraph-id/data-start, never through DOM node identity.
Every write goes through the guarded mutation path on this object. Reaching past it into session to apply ops directly bypasses the layout invalidation and the caret bookkeeping.
interface PaginatedSurface| Member | Type | Summary |
|---|---|---|
| activatedReviewKey | | The key [activateReview](activateReview) pinned, or null once its selection is no longer live. |
| activateReview | | Open THIS item, named by key, for as long as `selection` stays the live one. |
| activeReviewKey | | The comment or tracked change the caret is in, as the painted bands report it. |
| activeScope | | Active editing view — body, or an open header/footer story by rId. |
| adjustIndent | | Word's Increase/Decrease Indent, over every paragraph the selection touches. |
| applyAutomationOps | | Commit ops that came from automation, through the gate a keystroke goes through. |
| applyDrawingOps | | |
| applyHeaderFooterLifecycle | | Commit one package-level furniture lifecycle op (create/delete/link/unlink/options). Flushes layout so the next enter/rebind sees the new resolution. |
| applyImageProperties | | |
| applyTableCommandPlan | | Commit one table-command plan as a single store transaction. |
| armForcePlainPaste | | The next paste routes plain, whatever its payload carries (Cmd+Shift+V). |
| bookmarks | | `bookmarkName -> position` over the current revision, for resolving an internal link. First in document order wins a duplicate name, matching Word. |
| canAdjustIndent | | Whether Increase/Decrease Indent would do anything right now. |
| canEditTextFormField | | Refresh cached TOC entries and/or page numbers through the two-pass layout pipeline. |
| canInsertTable | | Whether a `rows`×`cols` table can be inserted at the caret. |
| canInsertToc | | Whether a generated body TOC can be inserted before the caret paragraph. |
| canRefreshToc | | Whether the addressed (or caret-local) body TOC can be refreshed. |
| clearFormatting | | Word's Clear All Formatting: direct run properties off the selected text, and every paragraph the selection touches back to the default style with its direct paragraph properties and mark dropped. |
| collaborationSession | | The collaboration replica a `collaborationModule` attached, or null. |
| commitReviewOps | | Commit review ops — accept, reject, a new comment — through the SAME path a keystroke takes: layout, paint, and a caret clamped to what the document now holds. |
| contentControls | ContentControlOps | Content-control chrome, form-fill navigation, and value / remove verbs. |
| convertAllNotes | | |
| convertNote | | |
| copyFlavours | | Every clipboard flavour for the current selection: plain text, and the interop HTML carrying the embedded fragment when the selection is a body-story range. A cell rectangle answers grid text plus a flattened table; `html` is null where only plain text should be written. |
| currentPage | | One-based page at the caret, or at the centre of the mounted viewport. |
| deleteBackward | | |
| deleteForward | | Delete forward — the Delete key, and `deleteContentForward` from an IME. |
| deleteImage | | |
| deleteNote | | |
| deleteSelection | | Remove the selection, if any. Returns whether anything was deleted. |
| deleteWordBackward | | Delete to the previous word boundary — Alt/Ctrl+Backspace. |
| deleteWordForward | | Delete to the next word boundary — Alt/Ctrl+Delete. |
| destroy | | |
| dismissActiveReview | | Close the open item until the caret next moves. |
| drawingSelectionIntent | | How the current selection came to address a drawing, if it does at all. |
| editingMode | | How edits are written right now. |
| editTextFormField | | |
| enqueueType | | Queue plain typed text for a batched commit at the caret. |
| enterHeaderFooter | | Open a header/footer story for editing on the painted surface. Refuses dangling / unknown relationship ids. |
| enterNote | | |
| equations | EquationOps | |
| exitHeaderFooter | | Leave furniture editing and restore the prior body selection. |
| exitListOnEmptyItem | | Enter on an empty list item: outdent a level, or leave the list at level 0. |
| exitNote | | |
| flushPendingInput | | Land any queued typed text now, as its own transaction, AND publish any layout pass a commit deferred under input pressure — so the caller reads current text and current geometry at one seam. Both halves are no-ops when nothing is pending, which is the common case: an isolated commit lays out synchronously in its own tail, and deferral only happens when the browser reports queued input behind an expensive pass. |
| focus | | |
| formatPainter | FormatPainterOps | Word's Format Painter: capture, apply, and the transient armed mode. |
| formatting | | Formatting as it stands at the selection, for a toolbar to reflect. |
| headerFooterState | | Chrome read-model for the open furniture scope, or null when editing the body. |
| hyperlinks | HyperlinkOps | The hyperlink lane: what link the caret is in, and the insert / retarget / unlink verbs. |
| imageDecodePort | | |
| insertImage | | |
| insertLineBreak | | A `w:br` — Shift+Enter, a line break inside the same paragraph. |
| insertNote | | Insert a footnote/endnote at the body caret. |
| insertPageBreak | | A `w:br w:type="page"` — Ctrl+Enter, a hard page break inside the paragraph. |
| insertPageField | | Insert an allowlisted page field at the caret in the open HF story. |
| insertPlainText | | Insert text whose newlines are PARAGRAPH BOUNDARIES, in one commit. |
| insertSectionBreak | | Insert a section break at the caret: the paragraph splits, and the head ends a new section cloning the governing section's page setup — Word's Layout Breaks. One undoable step. Returns whether the break committed. |
| insertTab | | A tab character as a `w:tab` element, not a literal tab in the run text. |
| insertTable | | Insert an empty `rows`×`cols` table at the caret, columns evenly dividing the content width of the caret's section, and leave the caret in the first cell. |
| insertToc | | Insert and populate a generated body TOC before the caret paragraph. |
| isInsideToc | | Whether a body paragraph belongs to a detected TOC boundary or cached result. |
| isListActive | | Whether every paragraph the selection touches is already a list of `kind`. |
| isListParagraph | | Whether the paragraph at the caret is a list item, for Tab's Word-like fallback. |
| layout | | |
| layoutSession | | The layout session, so a host or a test can see how much work a pass actually did. |
| navigate | | |
| navigation | SurfaceNavigation | Bookmark jumps and the ONE external-activation gate. A host's popover "open" action calls `openExternal`; nothing else in the engine may call `window.open`. |
| notePreviewText | | Plain-text preview for hover chrome — never returns markup. |
| notePropertiesState | | Resolved/authored note properties for the caret section — chrome read-model. |
| overlayCoordinates | | Paint-scale coordinate context for overlay chrome. |
| pasteRich | | Route one paste payload by fidelity: embedded fragment, then external HTML, then plain text — degrading on decode, read, or apply refusal. Suggesting mode, non-body stories and an armed force-plain all land on the plain lane. False when the payload landed on no lane at all (nothing to insert). |
| proposeTextChange | | Author one explicit tracked text change without changing the editing mode. |
| publishedLayout | | The layout as last PUBLISHED, without forcing pending work. |
| redo | | |
| refreshRefFieldResults | | Rewrite stale REF field results in the body, footnote and endnote stories so a save exports what the pages paint. Fresh results commit nothing (no transaction, no revision bump, no undo entry); a rewrite is ONE transaction and ONE undo unit across every stale part. Viewing, a non-editable session, and a collaborative session write nothing — the collaboration gate cannot journal the rewrite, so those saves export cached results and the call returns false. |
| refreshTableInteractionLabels | | Refresh table insertion furniture labels without remounting or relayout. |
| refreshToc | | |
| releaseSelection | | Drop one owned pin. Another owner's pin remains visible. |
| remotePresenceColor | | The presence colour the caret paints for `name`, sanitized as the paint sink is. |
| replaceImage | | |
| replacementLanding | | Where a replacement for `[start, end)` of a paragraph lands, or null when the edit would not be tracked. |
| retainedSelection | | The pinned range, or null once it was released or escaped. |
| retainSelection | | Pin the current selection so it stays VISIBLY selected while focus is elsewhere. |
| revealPage | | Scroll a page, or the page a paragraph sits on, into view. Returns whether it scrolled — false when the target is not laid out, or the surface is not inside a scroll container, so a caller can tell "no such target" from "done". |
| revealParagraph | | |
| revealPosition | | Scroll an exact position into view — `revealParagraph` for a caret that is not at offset 0. Focus-independent and virtualization-safe like every reveal: geometry comes from the layout and the target page is materialized on the way. Defaults to `block: 'nearest'`, so an already-visible target never yanks the viewport. |
| revisionAuthors | | Every author with a revision in the CURRENT layout, mapped to Word's colour slot by order of first appearance. One map instance per layout, so a caller can key caches on its identity. |
| revisionDisplayMode | | Which revision halves this surface is SHOWING. |
| save | | Commit pending form input, refresh REF results, and serialize the document. Throws an error with code `invalidArgs` for invalid form values, or `invalidState` during an active edit. Retry after the edit finishes. A destroyed surface throws with code `destroyed`. Does not change focus. |
| sectionAnchorParagraphAt | | How a section-addressed op should name the section `paragraphId` is in. |
| sectionAtPage | | The section a painted page belongs to, and the page that section starts on. |
| sectionBreakRefusal | | Why [insertSectionBreak](insertSectionBreak) would refuse this kind right now, or `null`. |
| sectionProperties | | The section the document declares: page size, margins, columns, orientation. |
| sectionPropertiesAt | | The section GOVERNING one paragraph — what a ruler or dialog reflects when the caret sits in a multi-section document. |
| selectAll | | Select the whole document. |
| selectDrawing | | Select one painted drawing at its host paragraph, as a pointer press would. |
| selectedText | | The selected text, for copy and cut. |
| session | TreeDocxSessionView | |
| setActiveScope | | Activate a view scope. Returns false when a header/footer rId cannot be opened. |
| setAllRevisionAuthorsVisible | | Show or hide every reviewer in one layout pass. |
| setAuthor | | Set the ambient author after buffered text commits under the previous author. |
| setCellSelection | | Select a rectangle of table cells, or clear one with null. |
| setDrawingStrings | | Replace localized drawing labels and repaint materialized pages. |
| setEditable | | Turn the browser's editing affordance on the pages layer on or off. |
| setEditingMode | | |
| setIndent | | Set indent to exact values on every paragraph the selection touches — what a ruler drag and an indent spinner both need, where [adjustIndent](adjustIndent) only steps. |
| setLocale | | Set regional conventions for subsequent date input without reformatting stored values. |
| setNoteProperties | | |
| setParagraphFormat | | The Paragraph dialog as ONE write: alignment, indents, spacing, line spacing and the five paragraph flags, over every paragraph the selection touches. |
| setParagraphProperties | | Several paragraph properties in ONE transaction, so a dialog is one undo step. |
| setParagraphProperty | | Set a property on every paragraph the selection touches — alignment, style, spacing. |
| setRemoteCaretLabelHost | | Hand remote-caret label content to the host, or take it back with `null`. |
| setReviewActivationExclusions | | Revision kinds the CARET must not activate, or null for none. |
| setRevisionAuthorVisible | | Show one reviewer's markup, or render that reviewer's changes as accepted. |
| setRevisionStyles | | Replace how tracked changes are coloured, live. Paint-level: the pages repaint without remeasuring a line, and the caret, selection and undo history stay where they are. |
| setRunProperty | | SET a run property over the selection, rather than toggling it. |
| setSectionProperties | | Write section page-setup fields — size, orientation, margins — as ONE undoable transaction. Twips throughout; omitted fields are left as authored. With `anchorParagraphId` only that paragraph's governing section is written (Word's "Apply to: This section"); without it, every section. Returns whether the write committed (a hostile value is refused by the op layer). |
| setSelection | | Set the selection directly, for a host driving the surface programmatically. |
| setTableInteractionLabel | | Refresh table insertion furniture labels without remounting the surface. |
| setTocLabels | | Replace the localized title used by later TOC insertions. |
| setTrackedChangesFilter | | Apply a view-time predicate over complete tracked-change items. |
| setTranslate | | Update shared form-control labels without replacing open dialogs. |
| showAllRevisionAuthors | | Clear the reviewer filter in one layout pass. |
| splitParagraph | | |
| state | | |
| storyScope | | |
| toggleList | | Word's Bullets and Numbering buttons. |
| toggleRunProperty | | Toggle a run property over the selection, e.g. `b`, `i`, `u`. |
| type | | |
| undo | | Reverse the last history entry and put the caret back where it was made. |
PaginatedSurfaceOptionsinterfaceSource ↗
How a paginated surface opens. Every field is optional.
measurer is the injection seam that keeps layout DOM-free — supply one to lay a document out on a server, or leave it off in a browser to get the canvas measurer.
interface PaginatedSurfaceOptions| Member | Type | Summary |
|---|---|---|
| author? | string | Ambient author for tracked edits. Required before suggesting can write anything. |
| collaborationModel? | CollaborationModuleContribution | The collaboration module's replica for this surface's session. Absent, the surface does not attach, and local store history remains the undo authority. |
| defaultFontFamily? | string | The family a run with no authored font is reported as by `formatting()` AND painted in — the face the measurer falls back to. Absent, such a run reports `fontFamily: null` and paints in whatever font the page inherits, which the measurer did not measure: visible glyphs drift from wrap points and caret geometry. |
| drawingStrings? | DrawingPaintStrings | Localized drawing refusal labels; defaults to English when omitted. |
| editingMode? | SurfaceEditingMode | Opening mode; changeable at runtime with `setEditingMode`. |
| fieldShading? | FieldShadingMode | When a field's result wears Word's grey shading. Omitted keeps Word's own default, `when-selected`. |
| fontAlias? | (family: string) => string | undefined | Maps a document-declared font family to the alias its registered bytes live under, so painted runs can use embedded glyphs without the file's family name entering the page-global CSS font namespace. |
| imageDecodePort? | ImageDecodePort | Override raster decode for package image intents; defaults to browser/headless. |
| locale? | string | Regional conventions for new date input; defaults to en-US. |
| measurer? | TextMeasurer | |
| onChange? | (state: PaginatedSurfaceState) => void | |
| onEquationPopover? | (activation: EquationActivation) => void | |
| onHyperlinkPopover? | (activation: HyperlinkActivation) => void | A plain click on an external (or inert) hyperlink, for a host to open its popover with. |
| onRequestHyperlink? | () => void | Ctrl/Cmd+K — Word's Insert Hyperlink. The engine reports the request; the host's chrome decides what a link dialog looks like. A host that passes nothing leaves the key alone rather than doing something surprising with it. |
| pointer? | 'engine' | 'native' | Who resolves a pointer to a caret. |
| producer? | string | Identifies the measurer for cache invalidation. |
| reviewModel? | ReviewModuleContribution | The review module's derivation hooks for this surface's session. Absent, `session.reviewItems()` is the typed empty queue and every review affordance built on it stays inert. |
| revisionDisplayMode? | RevisionDisplayMode | How revisions project into layout and paint. Omitted keeps the layout default (`all-markup`). The editor facade passes `proposed` when no review module is registered — the free tier's final-state rendering; the machinery below this option is shared either way. |
| revisionStyles? | RevisionStyles | How tracked changes are coloured: by AUTHOR (the default), by kind, or by author with host-pinned colours. A paint-level option like [fieldShading](fieldShading): it changes no geometry, so switching it repaints without remeasuring a line. Applies wherever revision markup paints, whatever the [revisionDisplayMode](revisionDisplayMode) leaves visible. |
| scale? | number | Points to CSS pixels. |
| tableInteractionLabel? | (key: 'table.insertRowBelow' | 'table.insertColumnRight') => string | Localized accessible names for core-owned table insertion furniture. Defaults to English from `@docx-editor.dev/i18n` when omitted. |
| tocLabels? | {
readonly title: string;
} | Localized name for a generated TOC, written as the control's `w:alias` on insert. |
| translate? | (key: string, params?: Record<string, string | number>) => string | UI labels for shared form controls; omitted keys fall back to English. |
PaginatedSurfaceStateinterfaceSource ↗
Everything observable about the surface right now, as one immutable value.
revision is the change token: it moves whenever anything else here does, which is what lets snapshot() hand back the same reference until state actually changes.
interface PaginatedSurfaceState| Member | Type | Summary |
|---|---|---|
| canRedo | boolean | |
| canUndo | boolean | |
| cellSelection | CellSelection | null | The rectangle of table cells a drag across cells selected, or null. |
| collaborationStatus | CollaborationStatus | 'inactive' | Lifecycle of the attached replica, or `'inactive'` when no collaboration module is registered on this surface. |
| contentControls | ContentControlSurfaceState | Content-control chrome and form-fill mode. |
| contextTocId | string | null | The TOC the last right-click landed on, or null. |
| formatPainter | FormatPainterSurfaceState | Format painter arming, and the level of what it holds. |
| lastRejection | string | null | |
| pageCount | number | |
| pendingFormat | readonly {
readonly localName: string;
}[] | null | The typing format armed at the caret (Word's stored marks), or null. |
| perf | PaginatedSurfacePerf | Timing and reuse counters for the last pass. Diagnostics, not document state. |
| revision | number | |
| selection | SemanticSelection |
ParagraphFlagsinterfaceSource ↗
The five paragraph flags a Paragraph dialog shows as checkboxes.
contextualSpacing is Word's "Don't add space between paragraphs of the same style"; the rest are its Pagination block. null means the selection disagrees.
interface ParagraphFlags| Member | Type | Summary |
|---|---|---|
| contextualSpacing | boolean | null | |
| keepLines | boolean | null | |
| keepNext | boolean | null | |
| pageBreakBefore | boolean | null | |
| widowControl | boolean | null |
ParagraphPropertyEditinterfaceSource ↗
One property in a batched paragraph write.
interface ParagraphPropertyEdit| Member | Type | Summary |
|---|---|---|
| attributes? | Record<string, string | null> | A null-valued attribute REMOVES that attribute; see `setParagraphProperty`. |
| localName | string | |
| mergeAttributes? | boolean | Keep the attributes this entry does not name, for multi-setting elements. |
ParagraphTabStopinterfaceSource ↗
One custom tab stop, as a command states it.
interface ParagraphTabStop| Member | Type | Summary |
|---|---|---|
| alignment | 'left' | 'center' | 'right' | 'decimal' | 'bar' | |
| leader? | 'none' | 'dot' | 'hyphen' | 'underscore' | 'heavy' | 'middleDot' | |
| positionTwips | number |
RemoteCaretLabelAnchorinterfaceSource ↗
One live remote-caret label the engine positioned. The host owns its content; the engine still owns the label's geometry, class, and presence colour, and rebuilds the labels wholesale on every repaint that moves them.
interface RemoteCaretLabelAnchor| Member | Type | Summary |
|---|---|---|
| element | HTMLElement | |
| selection | CollaborationRemoteSelection |
RemoteCaretLabelHostinterfaceSource ↗
A host that renders its own content inside the engine's remote-caret labels.
interface RemoteCaretLabelHost| Member | Type | Summary |
|---|---|---|
| publish | | Called after every paint that rebuilt the labels, with the current anchors. |
ReviewAuthorInfointerfaceSource ↗
One document author, resolved: who, which ramp slot, and what they draw in.
interface ReviewAuthorInfo| Member | Type | Summary |
|---|---|---|
| author | string | The `w:author` string, exactly as the file carries it. |
| color | string | The colour this author is DRAWN IN by the review chrome — their declared colour, or their ramp slot's token. |
| slot | number | Stable session rank, seeded by order of first appearance — an UNBOUNDED index. |
| style? | RevisionAuthorStyle | The host-supplied style, normalised; absent when the author rides the ramp. |
ReviewModelInputinterfaceSource ↗
What the review queue derivation reads: one story part plus its comment parts.
interface ReviewModelInput| Member | Type | Summary |
|---|---|---|
| commentsExtendedPart? | OoxmlPart | undefined | `word/commentsExtended.xml`, absent when the package has none. |
| commentsPart? | OoxmlPart | undefined | `word/comments.xml`, absent when the package has none. |
| customNodePayloads? | ReadonlyMap<string, {
readonly nodeId: string;
readonly label: string;
readonly data: string;
}> | undefined | The payload each of the story's controls binds to, keyed by the control's node id. |
| customNodes? | readonly unknown[] | undefined | Custom node definitions from the module registry, forwarded OPAQUELY. |
| furnitureParts? | readonly OoxmlPart[] | undefined | Header/footer story parts, in section order. Their revisions and comment anchors join the queue: a tracked change in a header is a pending decision like any other, and a queue that only walked the body silently hid it from the rail AND from Accept All. |
| reportCustomNodeDiagnostic? | ((diagnostic: unknown) => void) | undefined | Where a capability package reports a node it could not read. Supplied per editor, so a page with two of them keeps their diagnostics apart. |
| storyPart | OoxmlPart | The story the ranges live in — the main document, a header, a note. |
ReviewModuleContributioninterfaceSource ↗
What a review module contributes: the queue derivation, and the revision display modes the editor may enter beyond the free tier's final-state projection.
interface ReviewModuleContribution| Member | Type | Summary |
|---|---|---|
| collectReviewItems | CollectReviewItems | The review queue derivation. |
| displayModes | readonly RevisionDisplayMode[] | Display modes this module unlocks (the free engine renders `proposed` only). |
| revisionItemsOfParagraph | (part: OoxmlPart, paragraphId: string) => readonly ReviewRevisionItem[] | Revisions wholly inside one paragraph — for the conservative local review patch after a text-local body edit. |
RevisionAuthorAssignmentsinterfaceSource ↗
Per-author style assignments.
Keys match w:author exactly; a value is a CSS colour or a full [RevisionAuthorStyle](RevisionAuthorStyle). others says what authors WITHOUT an entry take: the --doc-review-author-N ramp by default, or 'kind' to leave them on the kind colours — which is how "highlight these reviewers, leave everyone else green and red" is said.
interface RevisionAuthorAssignments| Member | Type | Summary |
|---|---|---|
| authors | Readonly<Record<string, string | RevisionAuthorStyle>> | |
| others? | 'kind' | 'author' | Authors without an entry: the ramp (default), or the `'kind'` colours. |
RevisionAuthorStyleinterfaceSource ↗
Everything a host can say about ONE author's presentation. Every field is optional and every field is presentation-only — nothing here is ever serialised into the document.
Deliberately about the PAINTED DOCUMENT (which only the painter can style) plus the author's identity data. Review-card DESIGN is not configured here: the review chrome follows color as its accent automatically, and everything further is composition — a custom card reading this style through the review surface's useReviewAuthor, or CSS on the cards' data-review-author/data-review-author-slot hooks.
interface RevisionAuthorStyle| Member | Type | Summary |
|---|---|---|
| avatarUrl? | string | Avatar image for this author; the packaged card renders it in place of initials. |
| background? | string | Background wash behind this author's changes in the document. |
| color? | string | Ink and decoration colour of this author's changes in the document — and the accent the review chrome keys on (avatar disc, card variable, marker). |
| spanClassName? | string | Class names added to every painted span of this author's changes, for styling the typed fields do not cover. Keep the rules metric-safe (outlines, shadows, accents): the engine measures the text it paints, and a class that resizes glyphs drifts the page from its layout. |
RulerDragOptionsinterfaceSource ↗
How a ruler drag resolves: which grid it snaps to, and whether it snaps at all.
interface RulerDragOptions| Member | Type | Summary |
|---|---|---|
| precise? | boolean | Alt held: continuous, twip-precision drag, bypassing the snap grid — as in Word. |
| unit? | RulerUnit | Which snap grid applies. Defaults to inches. |
RulerIndentinterfaceSource ↗
A paragraph's indent as the ruler works with it. Twips; firstLine signed.
interface RulerIndent| Member | Type | Summary |
|---|---|---|
| firstLine | number | |
| left | number | |
| right | number |
RulerPageMetricsinterfaceSource ↗
The page the handles are placed against. Twips.
interface RulerPageMetrics| Member | Type | Summary |
|---|---|---|
| leftMargin | number | |
| pageWidth | number | |
| rightMargin | number |
RulerTickinterfaceSource ↗
One tick on the ruler: where it sits, how tall it is, and its label if it carries one.
interface RulerTick| Member | Type | Summary |
|---|---|---|
| height | number | |
| label? | string | Whole-unit label, omitted at the origin and on minor ticks. |
| position | number | Offset along the ruler in content pixels. |
RunTableChromeCommandResultinterfaceSource ↗
Result of [runTableChromeCommand](runTableChromeCommand): engine outcome plus post-pick draft on success.
interface RunTableChromeCommandResult| Member | Type | Summary |
|---|---|---|
| nextDraft | TableChromeDraft | null | |
| result | ExecResult |
SectionPropertiesinterfaceSource ↗
One section's resolved w:sectPr, as layout needs it.
Resolved, not raw: defaults the file omitted are filled in here (an absent w:type is nextPage), so layout never has to know which attributes were authored and which were inherited.
interface SectionProperties| Member | Type | Summary |
|---|---|---|
| breakType | SectionBreakType | Absent `w:type` defaults to `nextPage`. |
| columns | SectionColumns | |
| landscape | boolean | |
| margins | SectionMargins | |
| pageNumbering? | SectionPageNumbering | Authored page-number type. Absent when `w:pgNumType` is missing; empty object when the element is present with no attributes (comprehensive-fixture shape). |
| pageSize | {
readonly widthTwips: number;
readonly heightTwips: number;
} | |
| titlePage | boolean |
SelectedDrawingOverlayTargetinterfaceSource ↗
The painted geometry of the selected drawing, plus what the overlay is allowed to do to it.
Carries BOTH the painted rect (points, for hit-testing and handle placement) and the stored extent (EMU, for writing back), so the overlay never has to convert between the two spaces to decide what it is looking at.
interface SelectedDrawingOverlayTarget| Member | Type | Summary |
|---|---|---|
| anchorFrameOrigin | {
readonly x: number;
readonly y: number;
} | null | |
| aspectLocked | boolean | Hard lock from `noChangeAspect` — never overridden by Shift. |
| canMove | boolean | |
| canResize | boolean | |
| height | number | |
| heightEmu | number | |
| id | string | |
| kind | 'inline' | 'anchored' | |
| pageIndex | number | |
| position | DrawingPositionInput | null | |
| transform | DrawingTransform | |
| width | number | |
| widthEmu | number | |
| x | number | |
| y | number |
SelectedImageStateinterfaceSource ↗
Canonical selected-image read model shared by [EditorSnapshot.image](EditorSnapshot.image) and [Editor.getSelectedImage](Editor.getSelectedImage).
interface SelectedImageState| Member | Type | Summary |
|---|---|---|
| canChangeWrap | boolean | |
| canCrop | boolean | |
| canMove | boolean | |
| canResize | boolean | |
| crop | ImageCropPercent | Crop inset per edge in UI percent (0–100); OOXML stores permille (×1000). |
| description | string | |
| heightEmu | number | |
| hyperlink | string | null | |
| id | string | |
| intrinsic | Readonly<{
readonly pixelWidth: number;
readonly pixelHeight: number;
readonly dpiX: number;
readonly dpiY: number;
}> | null | |
| kind | DrawingKind | |
| locks | DrawingLocks | |
| name | string | |
| position | DrawingPositionInput | null | |
| resourceStatus | ImageResourceState['kind'] | |
| rotationDegrees | number | |
| title | string | |
| widthEmu | number | |
| wrap | ImageWrapTarget |
SemanticPositioninterfaceSource ↗
A caret position in the model.
interface SemanticPosition| Member | Type | Summary |
|---|---|---|
| offset | number | |
| paragraphId | string |
SemanticSelectioninterfaceSource ↗
A selection as two semantic positions — never as DOM nodes.
anchor is where the selection started and head is where it currently ends, so head before anchor is an ordinary backwards selection rather than an error. Collapsed when the two are equal, which is what a caret is.
interface SemanticSelection| Member | Type | Summary |
|---|---|---|
| anchor | SemanticPosition | |
| head | SemanticPosition |
SurfaceEquationinterfaceSource ↗
One addressable inline equation and its compact editable projection.
interface SurfaceEquation| Member | Type | Summary |
|---|---|---|
| end | number | |
| fallbackText | string | |
| id | string | |
| linear | string | |
| paragraphId | string | |
| start | number | |
| supported | boolean | True when every source construct belongs to the editable subset. |
SurfaceExtentinterfaceSource ↗
interface SurfaceExtent| Member | Type | Summary |
|---|---|---|
| height | number | |
| pageOffsetX | ReadonlyMap<number, number> | |
| width | number |
SurfaceFormattinginterfaceSource ↗
What the selection is currently formatted as.
A value is present only when EVERY span in the selection agrees on it: a selection running from 11pt into 14pt has no font size, and a toolbar should show a blank rather than pick one of the two and imply the whole selection is that.
interface SurfaceFormatting| Member | Type | Summary |
|---|---|---|
| alignment | 'left' | 'center' | 'right' | 'both' | null | |
| bold | boolean | |
| color | string | null | |
| disagrees | ParagraphDisagreements | Which of the paragraph-level reads above are `null` because the selection DISAGREES, as opposed to because nothing states them. See [ParagraphDisagreements](ParagraphDisagreements). |
| fontFamily | string | null | |
| fontSizeHalfPoints | number | null | Half-points, the unit OOXML stores and the picker expects. |
| highlight | string | null | |
| indent | IndentFormatting | null | Effective indent at the selection, in twips, or null with no selection or inside a table. |
| italic | boolean | |
| lineSpacing | {
readonly rule: 'multiple' | 'exact' | 'atLeast';
readonly value: number;
} | null | `w:spacing`'s line rule and its value: LINES for `multiple`, points for the other two (`w:line` is 240ths of a line under `auto` and twentieths of a point otherwise). Null when the selection's paragraphs disagree, or state no line spacing at all. |
| paragraphFlags | ParagraphFlags | The paragraph flags the Paragraph dialog shows as checkboxes, or null when the selection's paragraphs disagree about that one. |
| spaceAfterPt | number | null | |
| spaceBeforePt | number | null | `w:spacing/@w:before` and `@w:after` in points, null when the selection disagrees. |
| strikethrough | boolean | |
| styleId | string | null | |
| subscript | boolean | |
| superscript | boolean | |
| tabStops | readonly ParagraphTabStop[] | null | The paragraph's resolved custom tab stops, cascade included, or null when the selection disagrees or nothing is loaded. Positions in TWIPS, like every other measurement a control writes back. |
| underline | boolean |
SurfaceHyperlinkinterfaceSource ↗
A hyperlink as the surface reports it: its identity, where it sits, and the SANITIZED target. href: null is an inert link — a refused scheme or a dangling relationship — which a UI shows and offers to edit but must never offer to open.
interface SurfaceHyperlink| Member | Type | Summary |
|---|---|---|
| anchor? | string | |
| authored | string | The authored target, for an editor to seed its input with. |
| end | number | |
| href | string | null | Sanitized projection: an absolute URL, `#anchor`, or null when inert. |
| id | string | Canonical node id of the `w:hyperlink`. |
| kind | 'external' | 'internal' | 'unresolved' | |
| paragraphId | string | |
| start | number | UTF-16 range of the link's display text within its paragraph. |
| text | string | |
| tooltip? | string |
SurfaceNavigationinterfaceSource ↗
Moving the caret and the viewport: to a position, to a bookmark, or out to an external target.
[SurfaceNavigation.openExternal](SurfaceNavigation.openExternal) is THE external-activation call site, and it refuses anything but an already-sanitized href. Routing an authored target through some other path is how a document gets to choose where a click goes.
interface SurfaceNavigation| Member | Type | Summary |
|---|---|---|
| destroy | | |
| goToBookmark | | Scroll a bookmark into view and place the caret at it. Answers false for a name no bookmark declares — an inert click, which is what Word does with a dangling anchor. |
| goToPosition | | Snap to a semantic position using layout geometry, then place the caret there. |
| openExternal | | THE external-activation call site. Refuses anything but a sanitized projection, so a caller cannot route an authored target through it by mistake. |
SurfaceOverlayCoordinatesinterfaceSource ↗
What an overlay needs to place itself over the painted pages: the zoom scale, and where each page sits horizontally.
Per-page X offsets rather than one origin, because pages are centred independently and a narrower page in a mixed-size document does not start where its neighbours do.
interface SurfaceOverlayCoordinates| Member | Type | Summary |
|---|---|---|
| pageOffsetX | ReadonlyMap<number, number> | |
| paintScale | number |
SurfaceParagraphFormatinterfaceSource ↗
Every field of the Paragraph dialog, in the units the rest of this contract uses: points for spacing, TWIPS for indents.
An omitted field is left as authored. Where null is allowed it REMOVES the setting, which is not the same as writing a zero — a zero blocks the cascade, a removal lets the style through again.
interface SurfaceParagraphFormat| Member | Type | Summary |
|---|---|---|
| alignment? | 'left' | 'center' | 'right' | 'both' | |
| contextualSpacing? | boolean | |
| indentFirstLineTwips? | number | null | ONE signed first-line offset: negative is a hanging indent (§17.3.1.12). |
| indentLeftTwips? | number | null | |
| indentRightTwips? | number | null | |
| keepLines? | boolean | |
| keepNext? | boolean | |
| lineSpacing? | {
readonly rule: 'multiple' | 'exact' | 'atLeast';
readonly value: number;
} | null | |
| pageBreakBefore? | boolean | |
| spaceAfterPt? | number | null | |
| spaceBeforePt? | number | null | |
| tabStops? | readonly ParagraphTabStop[] | Replace the paragraph's custom tab stops. An empty list CLEARS them, which is what Word's "Clear All" does; omit the field to leave them as authored. |
| widowControl? | boolean |
TableBorderStyleOptioninterfaceSource ↗
One entry in the border-style picker, with the CSS class that draws its preview line.
interface TableBorderStyleOption| Member | Type | Summary |
|---|---|---|
| labelKey | string | |
| previewClass | string | Class on the preview swatch. Defined in the core stylesheet, which both adapters import. |
| value | TableBorderStyle |
TableBorderTargetOptioninterfaceSource ↗
One entry in the border-target picker: which edges it addresses, its icon, and its label key.
interface TableBorderTargetOption| Member | Type | Summary |
|---|---|---|
| icon | keyof typeof GENERATED_ICON_PATHS | |
| labelKey | string | i18n key, never a literal string — both adapters translate it themselves. |
| value | TableBorderTargetValue |
TableBorderWidthOptioninterfaceSource ↗
One entry in the border-width picker.
interface TableBorderWidthOption| Member | Type | Summary |
|---|---|---|
| labelKey | string | |
| previewThickness | number | Points, for drawing the preview swatch. `size / 8`. |
| size | number | `w:sz` — eighths of a point, as OOXML stores border widths. |
TableChromeDraftinterfaceSource ↗
UI draft: last active edge scope and the complete border spec to reapply.
interface TableChromeDraft| Member | Type | Summary |
|---|---|---|
| activeTarget | TableBorderEdgeTarget | |
| spec | TableBorderSpec |
TableChromePickinterfaceSource ↗
What one table-chrome selection produced: the command to run, and the draft to remember.
Both halves matter. A border picker is stateful — choosing "dashed" and then "outside" must apply a dashed outside border — so each pick returns the COMPLETE spec to execute alongside the draft the next pick builds on.
interface TableChromePick| Member | Type | Summary |
|---|---|---|
| command | EditorCommand | |
| nextDraft | TableChromeDraft |
TextMeasurerinterfaceSource ↗
Text measurement, injected.
A real implementation shapes with the resolved font; the tests supply a deterministic one. Layout never reads the DOM, so this is the only way width and height enter it.
interface TextMeasurer| Member | Type | Summary |
|---|---|---|
| lineMetrics | | Line height and baseline for the resolved style. |
| measure | | Advance width of `text` in the resolved style. |
ToolbarCommandStateinterfaceSource ↗
Whether one control is enabled, and the engine's reason when it is not.
interface ToolbarCommandState| Member | Type | Summary |
|---|---|---|
| active | boolean | Whether the command is currently APPLIED at the selection, from `Editor.isActive` — derived in the engine for marks and alignment, honest-false elsewhere. |
| disabledReason | string | null | The engine's reason when disabled — surfaced as a tooltip, never invented. |
| enabled | boolean | |
| id | ChromeSlotId | |
| value? | string | What the control currently SHOWS, for the slots whose answer is a value rather than a pressed state — the editing-mode pill, and image wrap when it lands. |
TreeApplyResultinterfaceSource ↗
What applying ops produced: whether it committed, and why not when it did not.
committed and rejected are separate flags because they are not opposites — a batch of zero ops neither commits nor is rejected.
interface TreeApplyResult| Member | Type | Summary |
|---|---|---|
| committed | boolean | |
| opCount | number | |
| reason? | TreeBindingRejection | StoryTargetRejection | string | Present when the edit was refused, so a host can report WHY rather than a silent no-op. |
| rejected | boolean |
TreeDocxSessionViewinterfaceSource ↗
One open document: the canonical tree, and the only write path into it.
applyTreeOps is that path. Every mutation is a TreeDocOp addressed by node id plus UTF-16 offset, applied in one transaction, which is what makes cell and nested paragraphs ordinary rather than special cases.
Holds the whole package, not just the body — headers, footers, notes, comments and styles are all reachable through it, and parts the engine does not model are preserved verbatim.
interface TreeDocxSessionView extends HeadlessDocumentView| Member | Type | Summary |
|---|---|---|
| applyFragmentPaste | | Land a clipboard fragment (resource merge + blocks) as one package undo unit. |
| applyImageProperties | | Apply image property tree ops plus hyperlink relationship wiring atomically. |
| applyTreeOps | | Commit typed tree ops directly, as ONE transaction. |
| applyTreeOpsAtomic | | Commit several stories' ops as ONE transaction and ONE undo unit. |
| beginComposition | | |
| bodyText | | Body text, paragraphs joined by newlines, read from the CANONICAL tree. |
| bookmarks | | `bookmarkName -> { paragraphId, offset }` over the main part, memoized per revision. |
| canRedo | | |
| canUndo | | |
| collaborationPort | | Narrow provider-neutral attachment over this session's canonical package store. |
| currentPackage | | The current package with every opened story store merged in. Authority for layout resolution and save — never a swapped single-part view. |
| deleteComment | | Delete a comment thread outright — body, thread state and story markers. |
| deleteComments | | Delete several comment objects as one package transaction and one undo unit. |
| deleteImage | | Delete a picture drawing and collect orphaned media in one package undo unit. |
| deleteImageTracked | | Propose the drawing's deletion as a tracked change (`w:del`); media stays untouched. |
| documentFonts | | Font family names the document uses, from every `w:rFonts` in the CURRENT main part plus the styles and header/footer parts — validated, deduplicated, sorted. Memoized per package revision. |
| documentOutline | | The heading outline of the BODY story, in document order: paragraphs whose `w:pStyle` resolves to a heading through the styles part (built-in `heading N` name, or the style's own `w:outlineLvl` 0..8). Memoized per main-part revision — an edit can retitle, add or remove a heading, but the styles part cannot change in-session. |
| documentProperties | | The document's own metadata from `docProps/core.xml` and `docProps/app.xml`, for document-property fields (TITLE, AUTHOR, SUBJECT, KEYWORDS, LASTSAVEDBY, COMMENTS). Read once per package revision; an empty object when the parts are absent. |
| documentStyles | | Validated style-picker projection. A document without styles answers `[]`. |
| documentThemeColors | | The theme's ten picker colours (`a:clrScheme`), in Word's column order, or `[]` when the package has no complete scheme. Memoized once: the theme part is immutable for the session's lifetime. |
| documentThemeFonts | | The theme part's Latin typefaces, for resolving `w:rFonts` theme references in layout. |
| editable | boolean | Whether the body holds at least one editable paragraph. |
| effectiveRunDefaults | | The run formatting a paragraph's content INHERITS when it authors none: the paragraph style's `basedOn` chain, then `w:docDefaults`, with theme `rFonts` attributes resolved through the font scheme. `runProperties` (the span's own authored properties) lets a theme-only run-level `w:rFonts` resolve too. This is what lets a toolbar always show the effective font, the way Word does. |
| embeddedFonts | | The faces the package EMBEDS (`word/fontTable.xml` embed relationships), deobfuscated — the only font source that needs neither a substitute nor a network. Extraction asserts nothing about validity; admitting a face is the font resource lane's job. Memoized once: the font table and font parts are immutable in-session. |
| endComposition | | |
| ensureHyperlinkRelationship | | The relationship id for an external hyperlink target on the part owning `scope` (default: body), minting one if that part has none, or `null` when the URL is refused or the scoped part cannot be resolved. |
| ensureListDefinition | | |
| ensureNumberingLevel | | Declare `level` in the list definition `numId` names, with Word's default format for that depth, or answer false. |
| findText | | Every occurrence of `query` across editable stories, in navigation order. Each match uses the same offset vocabulary as tree operations and surface selections. |
| hasReviewContent | | Whether the document carries review content — tracked changes or comment anchors — regardless of any review module. Derived from store vocabulary only (never the review model), memoized per revision: it is the free tier's honest "this document has more than you are seeing" signal. |
| headerFooterParts | | The resolved header/footer parts of the section, by variant (phase 2). |
| headerFooterPartsBySection | | Per-section header/footer parts after OOXML inheritance, index-aligned with `enumerateDocumentSections`. |
| headerFooterResolutionBySection | | Per-section resolution with declared-vs-inherited metadata for "Same as previous" chrome. Index-aligned with `headerFooterPartsBySection`. |
| insertCustomNode | | `scope` names the story the paragraph is in, and defaults to the body. |
| insertImage | | Insert a validated raster image as one package undo unit (task 12). |
| nodeIdOf | | Canonical node id for a `w14:paraId`, matched case-insensitively, or null. |
| numberingRoot | | Root of the numbering part tree (`w:numbering`), for list layout. Memoized once; `null` when the package has no numbering part. Numbering editing is a later slice. |
| packageRevision | | Package-wide revision — bumps on any story commit (body or HF). |
| paragraphAnchors | | The `w14:paraId` ↔ node-id index over the full editable set of the MAIN part, memoized per revision. Every editable paragraph carries a valid, part-unique id (established at open, maintained by the split appliers), so every paragraph is mapped. Header/footer paragraphs become addressable through `partFor` once their story store is open. |
| paragraphIds | | Canonical node ids of the body paragraphs, in order. |
| paragraphIdsIn | | Canonical node ids of paragraphs in a story scope. Defaults to the body. Header/footer scopes address the part `EditorScope { kind: 'headerFooter'; rId }` names. |
| paraIdOf | | `w14:paraId` of a canonical paragraph node id, verbatim, or null. |
| part | | The current canonical BODY part — what layout reads for the main story. |
| partFor | | The current part for a story scope, or null when the target is refused. |
| redo | | |
| relationshipTarget | | What the owning part's relationships answer for one `r:id` under `scope` (default: body): the authored target and whether it is external. `null` for an id the part does not declare, or when the scoped part is not open. |
| removeCustomNode | | Remove a custom node and the payload it bound. `scope` names the story holding it and defaults to the body; a chip in a header is refused against the body store. |
| renderedFontFamilies | | Font families the document's RENDERED text resolves to, over the story roots only: direct run `w:rFonts` of text-bearing runs plus the style chains those runs, paragraphs and tables actually reference — never a declaration in an unused style. Memoized per package revision. |
| rendersText | | Whether the document puts any literal character on a page, over the same roots [TreeDocxSessionView.documentFonts](TreeDocxSessionView.documentFonts) reads. Memoized per package revision. |
| replaceImage | | Replace a picture drawing's embedded media in one package undo unit. |
| replyToComment | | Reply to a comment, or add one over a revision's range. Returns the new comment's id. |
| reviewItems | | Every pending review decision in the document, memoized per revision. |
| revision | | Body-store revision (independent of header/footer store revisions). |
| revisionFor | | Per-story revision, or null when the target is refused. |
| save | | Serialize the whole package back to DOCX bytes. |
| setCommentResolved | | Resolve a comment thread, or reopen it. False when the document holds no such comment. |
| settingsRoot | | Root of the settings part tree (`w:settings`), for document-wide layout constants such as `w:defaultTabStop`. Memoized once; `null` when the package has no settings part. Settings editing is a later slice, so this is immutable for the session. |
| storyParts | | Every part that holds a story, body first, then headers, footers and note parts. |
| storyText | | Text of a story scope, paragraphs joined by newlines. |
| stylesRoot | | Current styles root for layout, or `null` when the package has no styles part. |
| subscribe | | |
| sweepCustomNodePayloads | | Drop every payload no control binds, in the stores whose namespaces a module claims. |
| symbolFontFamilies | | Font families named by a `w:sym/@w:font`, over the same roots [TreeDocxSessionView.documentFonts](TreeDocxSessionView.documentFonts) reads. Memoized per package revision. |
| trackingSettings | | What `settings.xml` says about tracking — `w:trackRevisions`, the tracked-changes protection, and the two do-not-track switches. |
| undo | | Undo the last entry, returning the selection to restore. |
Type aliases (34)
ChromeControlIdtypeSource ↗
Every control id in the chrome, as a literal union. Unique WITHIN a group, not globally (image.insert / table.insert) — key consumers on [ChromeSlotId](ChromeSlotId).
type ChromeControlId = ChromeSlotId extends `${string}.${infer C}` ? C : never;ChromeControlStatetypeSource ↗
HOW a control reaches the engine — never WHETHER it is enabled.
Enabled state has exactly one source: toolbarCommandState(editor, slot), which asks Editor.can. The registry is static data and cannot know what the engine will honour at this selection, in this document, at this moment.
There used to be a fourth member, parityOnly, meaning "visible but permanently disabled". It was a second, static answer to the question Editor.can already answers, and it went stale the moment the engine wired underline, strike, the four alignments, the list commands and the four value slots: the registry still said parity-only, React ignored it and ran them, and Vue believed it and rendered twelve WORKING commands permanently disabled. A slot the engine has not wired needs no registry flag — commandForSlot answers null and toolbarCommandState disables the control with the engine's own words ("not wired to an editor command").
type ChromeControlState =
/**
* Dispatched as one fixed engine command: enabled when
* `Editor.can(commandForSlot(slot))` succeeds, a click runs
* `runToolbarCommand(editor, slot)`. The command is resolved from the SLOT id
* through `commandForSlot` in toolbar-commands.ts — the one command table both
* adapters share. A slot with no row there is simply not wired YET, and says so
* through the engine rather than through this descriptor.
*/
{
readonly kind: 'command';
}
/**
* Dispatched with a PICKED value: `commandForSlotValue(slot, value)`. Enabled when
* the engine would honour a well-formed value right now (`toolbarCommandState`
* probes for exactly that), so the control needs chrome that produces a value — a
* font list, a size, a colour — before a click means anything.
*
* A distinct kind because 'command' cannot describe it: there is no fixed command
* to hand `Editor.can`, and a bare click has nothing to send.
*/
| {
readonly kind: 'value';
}
/** `Editor.save()` — not a command (see `runSave`). */
| {
readonly kind: 'save';
}
/**
* `Editor.load()` — not a command either, and the exact twin of `save`: bytes cross the
* boundary between the host and the engine, and only the host can produce them. The
* control needs chrome that reads a file (a picker, a drop target) before a click means
* anything, so a bare click has nothing to send — the same reason `save` is not `command`.
*
* A fourth kind rather than reusing `save` because the two dispatch in opposite
* directions, and an adapter branching on `kind` must be able to tell them apart. Unlike
* the deleted `parityOnly`, this one IS named by a control (`file.open`).
*/
| {
readonly kind: 'load';
};ChromeGroupIdtypeSource ↗
Every group id in the chrome, as a literal union. Stable public API; renaming a group id is a breaking change.
type ChromeGroupId = 'history' | 'zoom' | 'styles' | 'font' | 'text' | 'script' | 'alignment' | 'list' | 'format' | 'review' | 'contentControl' | 'image' | 'table' | 'paragraph' | 'file' | 'insert';ChromeMenuEntrytypeSource ↗
One row of a chrome menu.
type ChromeMenuEntry = ChromeMenuItemEntry | ChromeMenuSubmenuEntry | ChromeMenuSeparatorEntry;ChromeMenuIdtypeSource ↗
Every menu id, as a literal union. Stable public API; renaming one is a breaking change, exactly like a group or slot id.
type ChromeMenuId = 'file' | 'format' | 'insert' | 'review' | 'help';ChromeSlotIdtypeSource ↗
The public slot vocabulary: ${groupId}.${controlId} for every control that actually exists — text.bold, font.family, alignment.left. THE stable contract a host composes against and commandForSlot resolves; renaming a slot is a breaking change.
type ChromeSlotId = 'history.undo' | 'history.redo' | 'zoom.level' | 'styles.style' | 'font.family' | 'font.size' | 'text.bold' | 'text.italic' | 'text.underline' | 'text.strike' | 'text.color' | 'text.highlight' | 'text.link' | 'script.super' | 'script.sub' | 'alignment.left' | 'alignment.center' | 'alignment.right' | 'alignment.justify' | 'list.bullet' | 'list.numbered' | 'list.outdent' | 'list.indent' | 'list.lineSpacing' | 'format.painter' | 'format.clear' | 'review.comments' | 'review.authors' | 'review.editingMode' | 'contentControl.showAll' | 'contentControl.formFill' | 'contentControl.inspector' | 'contentControl.remove' | 'image.insert' | 'image.properties' | 'image.wrap' | 'image.altText' | 'table.insert' | 'table.borderTarget' | 'table.borderColor' | 'table.borderStyle' | 'table.borderWidth' | 'table.cellFill' | 'file.open' | 'file.save' | 'paragraph.dialog' | 'file.pageSetup' | 'insert.footnote' | 'insert.endnote' | 'insert.pageNumber' | 'insert.totalPages' | 'insert.sectionPages' | 'insert.pageXofY' | 'insert.pageBreak' | 'insert.sectionBreakNextPage' | 'insert.sectionBreakContinuous' | 'insert.toc';CollectReviewItemstypeSource ↗
Derives the review queue — every pending revision decision and comment thread — from one story part plus its comment parts. Implemented by the pro review module; the free engine has no implementation and reports an empty queue.
type CollectReviewItems = (input: ReviewModelInput) => readonly ReviewItem[];ColorLowerResulttypeSource ↗
A public colour lowered for a border or fill op, or the reason it could not be.
Refusals happen because paint needs a literal: a theme colour the document's theme does not define has no hex to draw, and inventing one would show a border in a colour the file never named.
type ColorLowerResult = {
readonly ok: true;
readonly color: TreeDocColorValue;
} | ColorLowerRefusal;DrawingSelectionIntenttypeSource ↗
How the current selection came to address a drawing — see [PaginatedSurface.drawingSelectionIntent](PaginatedSurface.drawingSelectionIntent).
type DrawingSelectionIntent = {
readonly kind: 'none';
} | {
readonly kind: 'pointer';
readonly drawingNodeId: string;
} | {
readonly kind: 'programmatic';
};FieldShadingModetypeSource ↗
When a field's result is drawn on its grey block, following Word's own View option.
when-selected is Word's default and the reason the option exists at all: a document dense with cross-references turns largely grey under always, and under never a reader cannot tell computed text from typed text at all.
type FieldShadingMode = 'never' | 'when-selected' | 'always';FontLoadFailureReasontypeSource ↗
Why one font did not load.
Distinguished rather than collapsed to "failed" because the responses differ: networkError and httpError are worth retrying, while hashMismatch and malformed mean the bytes were not what the source claimed and retrying will fetch the same wrong thing.
type FontLoadFailureReason = 'networkError' | 'httpError' | 'hashMismatch' | 'overLimit' | 'emptyResponse'
/** The declared face itself is unusable (empty family, out-of-range weight); nothing was fetched. */
| 'invalidRequest'
/** The bytes are not a font at all — most often an HTML error page served with 200. */
| 'malformed';FontOrigintypeSource ↗
ONE font origin, in the one shape every origin takes: a finished configuration, a fragment, a promise for either, or a marked resolver that answers per document.
The point of the union is that packagedFonts(), googleFonts(), await defaultFonts() and a hand-built { sources } are all the same kind of thing, so a list of them needs no ordering rule beyond "first wins".
The resolver arm is [MarkedFontResolver](MarkedFontResolver), not bare FontResolver: a list may also hold a zero-argument loader, and only the mark separates the two.
type FontOrigin = FontConfiguration | FontConfigurationFragment | MarkedFontResolver | Promise<FontConfiguration | FontConfigurationFragment | undefined> | undefined;FontResolvertypeSource ↗
Resolve fonts once the document's needs are known, instead of ahead of them.
Called once per load, AFTER the file is parsed and mounted, with the families it declares; whatever it returns composes exactly like a statically supplied fragment. Returning nothing is a valid answer — it means "I cover none of this", and the document stays on the fixed measurer.
A resolver that fetches makes opening a document perform network requests. That is a real change in posture and it must stay the APP's decision: the engine never supplies one, and the families here are file-derived, so a resolver must look them up in a set it shipped rather than interpolate them into a URL.
type FontResolver = (request: FontResolutionRequest) => FontConfiguration | FontConfigurationFragment | undefined | Promise<FontConfiguration | FontConfigurationFragment | undefined>;ImageContexttypeSource ↗
The selected image and what may be done to it — the imageContext query's answer.
An alias of SelectedImageState, kept as its own name because it is the query's result type and chrome is written against it.
type ImageContext = SelectedImageState;ImageResizeHandletypeSource ↗
Which of the eight resize handles a drag started from, by compass direction.
type ImageResizeHandle = 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw';ImageWrapTargettypeSource ↗
Nine Word wrap menu targets (inline plus eight floating modes).
type ImageWrapTarget = 'inline' | 'square' | 'squareLeft' | 'squareRight' | 'tight' | 'through' | 'topAndBottom' | 'behind' | 'inFront';MarkedFontResolvertypeSource ↗
A [FontResolver](FontResolver) that has been through [defineFontResolver](defineFontResolver).
This, not bare FontResolver, is what a FontOrigin list accepts. The mark is the only thing separating a resolver from a zero-argument loader, and getting that wrong loses every font silently, so the type asks for it up front.
type MarkedFontResolver<T extends FontResolver = FontResolver> = T & FontResolverMark;NavigationCommandtypeSource ↗
One caret movement, in Word's own vocabulary.
Visual rather than logical where the two differ: left means left on screen, which in right-to-left text is forward through the string.
type NavigationCommand = 'left' | 'right' | 'up' | 'down' | 'wordLeft' | 'wordRight' | 'lineStart' | 'lineEnd' | 'documentStart' | 'documentEnd' | 'pageUp' | 'pageDown';OpenPaginatedResulttypeSource ↗
What opening a document produced: a mounted surface, or a refusal.
A result rather than a throw, because every refusal here comes from FILE input — a package the bounded reader rejected, a part that exceeded a limit — and a malformed upload should surface as a message the host can show rather than an exception it has to catch.
type OpenPaginatedResult = {
readonly ok: true;
readonly surface: PaginatedSurface;
} | {
readonly ok: false;
readonly reason: string;
readonly detail?: string;
};RenderableImageMimetypeSource ↗
Every mime the painter can hand to an <img>.
type RenderableImageMime = SupportedImageMime | VectorImageMime;ReviewWriteIntenttypeSource ↗
Which review write is being committed through commitReviewOps.
The callback that performs the write is opaque, so a lane deciding whether to allow it cannot tell an Accept from a comment delete. That mattered once a replica was attached: these paths reach the store directly rather than through applyTreeOps, and the ones that graft a package and swap the shell record no primitive effects — they replicate as NOTHING, leaving the peer a commentReference naming a comment it never received. Naming the write lets each be admitted only once a two-replica test proves it arrives whole.
type ReviewWriteIntent = 'revision-resolve' | 'comment-add' | 'comment-reply' | 'comment-resolve' | 'comment-delete' | 'package-scoped';RevisionStylestypeSource ↗
How painted tracked changes are coloured.
- 'author' (the DEFAULT) — every change takes its author's colour from the --doc-review-author-N ramp. An attached document seeds slots by order of first appearance, then keeps those assignments stable for that session. Word's own default, and the reason it is this engine's: a paragraph three people edited has to read as three people. Restyle a slot under .docx-editor to change the ramp. - 'kind' — insertions and deletions take the two kind colours (--doc-revision-insertion / --doc-revision-deletion), so "added" and "removed" are what a reader tells apart at a glance, whoever proposed them. - [RevisionAuthorAssignments](RevisionAuthorAssignments) — style the named authors; others decides whether the rest take the ramp (the default) or the kind colours.
Presentation only: nothing here is ever serialised into the document.
type RevisionStyles = 'kind' | 'author' | RevisionAuthorAssignments;RulerIndentHandletypeSource ↗
The four handles Word's ruler carries.
hanging and left sit at the SAME position and differ only in what a drag takes with them — the box moves the whole paragraph, the triangle leaves the first line where it is.
type RulerIndentHandle = 'firstLine' | 'hanging' | 'left' | 'right';RulerUnittypeSource ↗
Which measurement system the ruler shows. Drives both tick cadence and drag snapping.
type RulerUnit = 'inch' | 'cm';SectionAnchortypeSource ↗
How a section-addressed op should name the section a caret is in.
w:sectPr lives on the body story, so the op can only name BODY content — and a caret in a header or a note is not body content. The three answers are genuinely different, and collapsing them to "a paragraph or null" is what let an unaddressable section quietly become a document-wide write.
type SectionAnchor =
/** Name this body paragraph. Its section is the one the caret is in. */
{
readonly kind: 'anchor';
readonly paragraphId: string;
}
/** One section: an anchor names nothing extra, so the op may omit it. */
| {
readonly kind: 'whole-document';
}
/**
* Several sections, and the caret's holds no paragraph to name.
*
* An omitted anchor here would write EVERY section, which is what `scope: 'document'` is
* for — so answering it to a `scope: 'section'` request changes sections nobody asked
* about. There is no anchor that reaches an empty final section: one exists only when every
* paragraph already closes an earlier section, so nothing sits at or after it.
*/
| {
readonly kind: 'unaddressable';
};SectionBreakInsertTypetypeSource ↗
Where the section after an inserted break begins — Word's Layout Breaks menu.
The two the engine paginates. evenPage / oddPage are readable in a file but not offered here, because layout does not skip the blank sheet they need yet, and a menu entry that silently behaves like nextPage is the lie this vocabulary exists to avoid.
type SectionBreakInsertType = 'nextPage' | 'continuous';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';SurfaceInsertImageInputtypeSource ↗
What a host may set on a surface image insert.
The decode port and the collaboration actor are the SURFACE's to supply. An actor a host could pass would be a second identity for the same mint, which is the thing actor-scoped allocation exists to prevent.
type SurfaceInsertImageInput = Omit<InsertImageInput, 'decodePort' | 'actorId'>;TableBorderTargetValuetypeSource ↗
Border target picker value — concrete scopes plus clear (none).
type TableBorderTargetValue = TableBorderEdgeTarget | 'none';TableChromeSlotIdtypeSource ↗
The chrome slots that only exist while the caret is inside a table.
A subset of ChromeSlotId, so these names are public API on the same terms — renaming one is a breaking change.
type TableChromeSlotId = 'table.borderTarget' | 'table.borderColor' | 'table.borderStyle' | 'table.borderWidth' | 'table.cellFill';TableInteractionLabelKeytypeSource ↗
Furniture insertion controls (Task 8) share this label seam.
type TableInteractionLabelKey = 'table.insertRowBelow' | 'table.insertColumnRight';TrackedChangeFilterModetypeSource ↗
How revisions excluded by a tracked-changes predicate project into the view.
type TrackedChangeFilterMode = 'accept' | 'reject';TrackedChangePredicatetypeSource ↗
Decides whether one tracked change renders as markup.
Return true to keep the revision visible as tracked markup. Return false to render it with the selected [TrackedChangeFilterMode](TrackedChangeFilterMode) without changing the document. The callback receives the complete revision item, including its author, date, kind, text, ranges, nesting, and resolution metadata.
type TrackedChangePredicate = (revision: ReviewRevisionItem) => boolean;VectorImageMimetypeSource ↗
Vector media painted straight from validated bytes. An <img> renders SVG in the browser's secure static mode — no script, no external subresource loads — so there is no decode step and no raster buffer sized by a file-supplied number.
type VectorImageMime = 'image/svg+xml';Variables (31)
AUTO_ZOOM_MODEconstSource ↗
Fit the page width, but never magnify and never shrink past legibility: the default.
A wide container keeps the 100% it has always had, and only one too narrow to hold the sheet shrinks. Uncapped fitting would render a Letter page at 183% on a 1600px monitor, which is a reader app, not Word; unfloored fitting would render it at 20% beside an open comments rail on a phone.
AUTO_ZOOM_MODE: ZoomModeBROWSER_AUTOMATION_CAPABILITIESconstSource ↗
What a browser host can do.
selection, scrolling and layout are true because a mounted editor genuinely has a caret, a scroll container and paginated layout — a consumer may branch on them. The DOCUMENT operations behave identically to the headless host regardless; the extra capabilities widen what may be asked later, never what an existing operation means.
BROWSER_AUTOMATION_CAPABILITIES: AutomationCapabilitiesCHROME_GROUPSconstSource ↗
The complete chrome, in bar order. Literal-typed (as const) so the slot-id vocabulary below is derived from the data and cannot drift from it.
Taxonomy taste: ids are short, lowercaseCamel, and never repeat their group's name (alignment.left, not alignment.alignLeft; font.family, not font.fontFamily).
CHROME_GROUPS: readonly [{
readonly id: "history";
readonly labelKey: "formattingBar.groups.history";
readonly controls: readonly [{
readonly id: "undo";
readonly labelKey: "formattingBar.undoShortcut";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "redo";
readonly labelKey: "formattingBar.redoShortcut";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "zoom";
readonly labelKey: "formattingBar.groups.zoom";
readonly controls: readonly [{
readonly id: "level";
readonly shape: "stepper";
readonly valueText: "100%";
readonly labelKey: "formattingBar.groups.zoom";
readonly paths: null;
readonly valueKey: "zoom.zoomLevel";
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "styles";
readonly labelKey: "formattingBar.groups.styles";
readonly controls: readonly [{
readonly id: "style";
readonly shape: "dropdown";
readonly labelKey: "styles.selectAriaLabel";
readonly paths: null;
readonly valueKey: "styles.normalText";
readonly state: {
readonly kind: "value";
};
}];
}, {
readonly id: "font";
readonly labelKey: "formattingBar.groups.font";
readonly controls: readonly [{
readonly id: "family";
readonly shape: "dropdown";
readonly labelKey: "font.selectAriaLabel";
readonly paths: null;
readonly valueKey: "font.sansSerif";
readonly state: {
readonly kind: "value";
};
}, {
readonly id: "size";
readonly shape: "stepper";
readonly valueText: "11";
readonly labelKey: "fontSize.listLabel";
readonly paths: null;
readonly valueKey: "fontSize.label";
readonly state: {
readonly kind: "value";
};
}];
}, {
readonly id: "text";
readonly labelKey: "formattingBar.groups.textFormatting";
readonly controls: readonly [{
readonly id: "bold";
readonly labelKey: "formattingBar.boldShortcut";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "italic";
readonly labelKey: "formattingBar.italicShortcut";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "underline";
readonly labelKey: "formattingBar.underlineShortcut";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "strike";
readonly labelKey: "formattingBar.strikethrough";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "color";
readonly shape: "colorSplit";
readonly swatch: "#ff0000";
readonly labelKey: "formattingBar.fontColor";
readonly paths: readonly string[];
readonly state: {
readonly kind: "value";
};
}, {
readonly id: "highlight";
readonly shape: "colorSplit";
readonly swatch: "#ffff00";
readonly labelKey: "formattingBar.highlightColor";
readonly paths: readonly string[];
readonly state: {
readonly kind: "value";
};
}, {
readonly id: "link";
readonly labelKey: "formattingBar.insertLinkShortcut";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "script";
readonly labelKey: "formattingBar.groups.script";
readonly controls: readonly [{
readonly id: "super";
readonly labelKey: "formattingBar.superscript";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "sub";
readonly labelKey: "formattingBar.subscript";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "alignment";
readonly labelKey: "formattingBar.groups.alignment";
readonly controls: readonly [{
readonly id: "left";
readonly labelKey: "alignment.alignLeft";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "center";
readonly labelKey: "alignment.center";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "right";
readonly labelKey: "alignment.alignRight";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "justify";
readonly labelKey: "alignment.justify";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "list";
readonly labelKey: "formattingBar.groups.listFormatting";
readonly controls: readonly [{
readonly id: "bullet";
readonly labelKey: "lists.bulletList";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "numbered";
readonly labelKey: "lists.numberedList";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "outdent";
readonly labelKey: "lists.decreaseIndent";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "indent";
readonly labelKey: "lists.increaseIndent";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "lineSpacing";
readonly shape: "dropdown";
readonly labelKey: "lineSpacing.label";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "format";
readonly labelKey: "formattingBar.groups.format";
readonly controls: readonly [{
readonly id: "painter";
readonly labelKey: "formattingBar.formatPainterShortcut";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "clear";
readonly labelKey: "formattingBar.clearFormatting";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "review";
readonly labelKey: "formattingBar.commentsAndChanges";
readonly controls: readonly [{
readonly id: "comments";
readonly shape: "icon";
readonly labelKey: "formattingBar.commentsAndChanges";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "authors";
readonly shape: "dropdown";
readonly labelKey: "reviewers.label";
readonly paths: readonly string[];
readonly defaultToolbar: false;
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "editingMode";
readonly shape: "dropdown";
readonly labelKey: "editingMode.label";
readonly valueKey: "editingMode.editing";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "contentControl";
readonly labelKey: "contentControl.group";
readonly contextual: true;
readonly controls: readonly [{
readonly id: "showAll";
readonly labelKey: "contentControl.showAll";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "formFill";
readonly labelKey: "contentControl.formFill";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "inspector";
readonly labelKey: "contentControl.inspector";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "remove";
readonly labelKey: "contentControl.remove";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "image";
readonly labelKey: "formattingBar.groups.image";
readonly contextual: true;
readonly controls: readonly [{
readonly id: "insert";
readonly labelKey: "toolbar.image";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "properties";
readonly labelKey: "formattingBar.imagePropertiesShortcut";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "wrap";
readonly shape: "dropdown";
readonly labelKey: "formattingBar.imageWrap";
readonly paths: readonly string[];
readonly valueKey: "imageWrap.inline";
readonly state: {
readonly kind: "value";
};
}, {
readonly id: "altText";
readonly shape: "dropdown";
readonly labelKey: "formattingBar.altText";
readonly paths: null;
readonly valueKey: "imageProperties.altText";
readonly state: {
readonly kind: "value";
};
}];
}, {
readonly id: "table";
readonly labelKey: "formattingBar.groups.table";
readonly contextual: true;
readonly controls: readonly [{
readonly id: "insert";
readonly labelKey: "toolbar.table";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "borderTarget";
readonly shape: "dropdown";
readonly labelKey: "table.borders.tooltip";
readonly paths: readonly string[];
readonly state: {
readonly kind: "value";
};
}, {
readonly id: "borderColor";
readonly shape: "colorSplit";
readonly swatch: "#000000";
readonly labelKey: "table.borderColor";
readonly paths: readonly string[];
readonly state: {
readonly kind: "value";
};
}, {
readonly id: "borderStyle";
readonly shape: "dropdown";
readonly labelKey: "table.borders.styleAriaLabel";
readonly paths: readonly string[];
readonly state: {
readonly kind: "value";
};
}, {
readonly id: "borderWidth";
readonly shape: "dropdown";
readonly labelKey: "table.borderWidth";
readonly paths: readonly string[];
readonly state: {
readonly kind: "value";
};
}, {
readonly id: "cellFill";
readonly shape: "colorSplit";
readonly swatch: "#ffffff";
readonly labelKey: "table.cellFillColor";
readonly paths: readonly string[];
readonly state: {
readonly kind: "value";
};
}];
}, {
readonly id: "paragraph";
readonly labelKey: "dialogs.paragraph.title";
readonly contextual: true;
readonly controls: readonly [{
readonly id: "dialog";
readonly labelKey: "lineSpacing.options";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "file";
readonly labelKey: "toolbar.file";
readonly contextual: true;
readonly controls: readonly [{
readonly id: "open";
readonly labelKey: "toolbar.open";
readonly paths: readonly string[];
readonly state: {
readonly kind: "load";
};
}, {
readonly id: "save";
readonly labelKey: "toolbar.saveShortcut";
readonly paths: readonly string[];
readonly state: {
readonly kind: "save";
};
}, {
readonly id: "pageSetup";
readonly labelKey: "toolbar.pageSetup";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}, {
readonly id: "insert";
readonly labelKey: "toolbar.insert";
readonly contextual: true;
readonly controls: readonly [{
readonly id: "footnote";
readonly labelKey: "toolbar.insertFootnote";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "endnote";
readonly labelKey: "toolbar.insertEndnote";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "pageNumber";
readonly labelKey: "headerFooter.insertPageNumber";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "totalPages";
readonly labelKey: "headerFooter.insertTotalPages";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "sectionPages";
readonly labelKey: "headerFooter.insertSectionPages";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "pageXofY";
readonly labelKey: "headerFooter.insertPageXofY";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "pageBreak";
readonly labelKey: "toolbar.pageBreak";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "sectionBreakNextPage";
readonly labelKey: "toolbar.sectionBreakNextPage";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "sectionBreakContinuous";
readonly labelKey: "toolbar.sectionBreakContinuous";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}, {
readonly id: "toc";
readonly labelKey: "toolbar.tableOfContents";
readonly paths: readonly string[];
readonly state: {
readonly kind: "command";
};
}];
}]CHROME_MENUSconstSource ↗
The menu bar the chrome shows above the toolbar, in bar order: File, Format, Insert, Review, Help.
CHROME_MENUS: readonly ChromeMenu[]CHROME_UNAVAILABLE_KEYconstSource ↗
i18n key for the tooltip on a control an ADAPTER renders but cannot drive yet — a value slot in a toolbar that has grown no picker for it, say. It is never the reason a control is disabled: when the ENGINE refuses, the tooltip is the engine's own disabledReason, never an adapter paraphrase.
CHROME_UNAVAILABLE_KEY = "formattingBar.unavailableInPreview"DEFAULT_IMAGE_RESOURCE_LIMITSconstSource ↗
The image caps in force when a host configures none. Conservative and finite.
DEFAULT_IMAGE_RESOURCE_LIMITS: ImageResourceLimitsDEFAULT_TABLE_CHROME_DRAFTconstSource ↗
The draft a table's border chrome starts from: a 1pt black single border on every edge.
DEFAULT_TABLE_CHROME_DRAFT: TableChromeDraftDRAWING_REL_FROM_HconstSource ↗
Legal relativeFrom bases for a horizontal offset (page, margin, column, character, …).
DRAWING_REL_FROM_H: readonly string[]DRAWING_REL_FROM_VconstSource ↗
Legal relativeFrom bases for a vertical offset (page, margin, paragraph, line, …).
DRAWING_REL_FROM_V: readonly string[]EMU_PER_POINTconstSource ↗
EMUs per point. DrawingML stores extents in EMU; layout works in points.
EMU_PER_POINT = 12700FIT_WIDTH_ZOOM_MODEconstSource ↗
Fit the page width in BOTH directions — the uncapped fit, unlike 'auto'.
A shared constant rather than a literal per call site: modes are compared by value, but a control also has to render its own selected state, and two spellings of one mode in two files is how a menu ends up ticking a row the editor is not in.
FIT_WIDTH_ZOOM_MODE: ZoomModeFONT_RESOLVER_BRANDconstSource ↗
The runtime marker defineFontResolver sets and [isFontResolver](isFontResolver) reads.
Exported because a package mirroring the font contract structurally still has to mark the resolvers it builds. A package in that position sets Symbol.for('docx-editor.dev/font-resolver') itself; this constant is the same symbol, named, for everyone who can import it.
FONT_RESOLVER_BRAND: unique symbolFONT_RESOLVER_MARK_KEYconstSource ↗
The namespaced key carrying the type-level half of the mark, and the runtime property name that backs it.
A plain string rather than a symbol on purpose: @docx-editor.dev/fonts has no runtime or type dependency on the engine, so it declares the same mark itself, and two unique symbols in two packages would not unify. Two identical string keys do.
FONT_RESOLVER_MARK_KEY = "docx-editor.dev/font-resolver"IMAGE_OVERLAY_NUDGE_PTconstSource ↗
How far one arrow-key press nudges a selected image, in points.
IMAGE_OVERLAY_NUDGE_PT = 1IMAGE_OVERLAY_NUDGE_SHIFT_PTconstSource ↗
How far Shift+arrow nudges a selected image, in points.
IMAGE_OVERLAY_NUDGE_SHIFT_PT = 10IMAGE_WRAP_TARGETSconstSource ↗
Every text-wrap mode a drawing may be set to, including inline.
IMAGE_WRAP_TARGETS: readonly ImageWrapTarget[]LOADING_SNAPSHOTconstSource ↗
What snapshot() reports before an editor exists: loading, not editable, nothing selected, nothing undoable — never invented state.
LOADING_SNAPSHOT: EditorSnapshotMAX_RESOLVER_FAMILIESconstSource ↗
Ceiling on the families one document can put in front of a resolver.
A resolver typically turns each family into up to four faces, and the resource snapshot refuses more than HARD_MAX_FONT_SOURCES (256) sources — so 64 families is the point past which a document could no longer be served anyway. Capping here means a file declaring thousands of distinct w:rFonts cannot fan a resolver out across thousands of lookups (or fetches) before that limit is ever reached.
MAX_RESOLVER_FAMILIES = 64PX_PER_CMconstSource ↗
Painted pixels per centimetre, derived from [PX_PER_INCH](PX_PER_INCH).
PX_PER_CM: numberPX_PER_INCHconstSource ↗
The engine paints at 96 px per inch (twips / 15, 1440 twips per inch).
PX_PER_INCH = 96SNAP_TWIPS_CMconstSource ↗
The centimetre ruler's grid is the millimetre.
SNAP_TWIPS_CM: numberSNAP_TWIPS_INCHconstSource ↗
Word snaps ruler drags to the eighth-inch grid its ticks already draw.
SNAP_TWIPS_INCH: numberTABLE_BORDER_STYLE_OPTIONSconstSource ↗
The border-style picker's entries.
TABLE_BORDER_STYLE_OPTIONS: readonly TableBorderStyleOption[]TABLE_BORDER_TARGET_OPTIONSconstSource ↗
The border-target picker's entries, in Word's own order, ending with clear.
TABLE_BORDER_TARGET_OPTIONS: readonly TableBorderTargetOption[]TABLE_BORDER_WIDTH_OPTIONSconstSource ↗
Widths in eighths of a point — Word-like presets.
TABLE_BORDER_WIDTH_OPTIONS: readonly TableBorderWidthOption[]TABLE_CHROME_SLOT_IDSconstSource ↗
Every [TableChromeSlotId](TableChromeSlotId), for iteration and for [isTableChromeSlot](isTableChromeSlot).
TABLE_CHROME_SLOT_IDS: readonly TableChromeSlotId[]TWIPS_PER_CMconstSource ↗
Twips per centimetre, as Word rounds them.
TWIPS_PER_CM = 567TWIPS_PER_INCHconstSource ↗
Twips per inch, as OOXML defines them.
TWIPS_PER_INCH = 1440WORD_DEFAULT_FONTconstSource ↗
Word's document default when nothing else says otherwise: Calibri at 11pt.
WORD_DEFAULT_FONT: FontConfiguration['defaultFont']ZOOM_MAXconstSource ↗
The widest scale the editor contract accepts.
ZOOM_MAX = 5ZOOM_MINconstSource ↗
The narrowest scale the editor contract accepts. One definition, every user.
ZOOM_MIN = 0.1