@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 (82)
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, 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;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;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.
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 ↗
Adapt the published byte-source contract to the private deterministic layout snapshot.
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;disposeLayoutShapingfunctionSource ↗
Release a shaping environment's native resources.
The shaper holds WASM memory that garbage collection cannot reclaim on its own, so a host that builds shaping options must dispose them when the editor goes away. Safe on a shaper that has no dispose.
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;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 is not in the packaged chrome at all — a host that wants it places image.insert itself, through DocxEditor.Toolbar.ImageInsert or DocxEditor.Menu.ImageInsert.
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;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;
};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;
};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;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 ↗
How wide and tall the paginated surface should be.
When materialize is set — virtualization is active — width follows only those pages so a distant landscape section does not stretch a portrait viewport. Without it (print, export, tests with no scroller) every page contributes, which is the safe reading.
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 ↗
Normalize anything thrown during font work into an [EditorFontError](EditorFontError).
One error type reaches consumers whether the failure came from resolution, admission or shaping, so a host branches on code rather than on which layer happened to throw.
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 (59)
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 |
|---|---|---|
| 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 |
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. Bytes only in practice: 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. |
| 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 | |
| mode? | 'edit' | 'view' | `'view'` refuses every mutating command through the facade; default `'edit'`. |
| 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 | |
| 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 | Localized drawing refusal labels; defaults to English when omitted. |
| zoom? | number |
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()`. |
| 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()`. |
| mountGeneration | number | Bumps on mount, detach, destroy, and document reload — guards async image intents. |
| 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. |
| 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 |
|---|---|---|
| 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 (first registration wins), all custom node definitions in registration order.
interface EditorModuleRegistry| Member | Type | Summary |
|---|---|---|
| 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 |
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. |
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 declared anywhere in the document (body, headers/footers, styles), deduped, sorted, and capped at [MAX_RESOLVER_FAMILIES](MAX_RESOLVER_FAMILIES). |
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. |
| 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 |
|---|---|---|
| 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. |
| 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. |
| 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. |
| 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 | | |
| 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. |
| editingMode | | How edits are written right now. |
| enterHeaderFooter | | Open a header/footer story for editing on the painted surface. Refuses dangling / unknown relationship ids. |
| enterNote | | |
| 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 | | |
| focus | | |
| 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 next-page 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 Next Page. 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. |
| publishedLayout | | The layout as last PUBLISHED, without forcing pending work. |
| redo | | |
| refreshTableInteractionLabels | | Refresh table insertion furniture labels without remounting or relayout. |
| refreshToc | | Refresh cached TOC entries and/or page numbers through the two-pass layout pipeline. |
| releaseSelection | | Drop the pin and stop drawing it, whether or not the caret ever left. |
| replaceImage | | |
| 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. |
| 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. Falls back to the body-level section for an unknown id. |
| selectAll | | Select the whole document. |
| selectedText | | The selected text, for copy and cut. |
| session | TreeDocxSession | |
| setActiveScope | | Activate a view scope. Returns false when a header/footer rId cannot be opened. |
| setCellSelection | | Select a rectangle of table cells, or clear one with null. |
| 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. |
| setNoteProperties | | |
| setParagraphProperty | | Set a property on every paragraph the selection touches — alignment, style, spacing. |
| setReviewActivationExclusions | | Revision kinds the CARET must not activate, or null for none. |
| 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. |
| 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. |
| 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`. |
| 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. |
| measurer? | TextMeasurer | |
| onChange? | (state: PaginatedSurfaceState) => 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. |
| 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. |
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. |
| contentControls | ContentControlSurfaceState | Content-control chrome and form-fill mode. |
| contextTocId | string | null | The TOC the last right-click landed on, or null. |
| 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 |
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 | |
| 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. |
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 |
SurfaceExtentinterfaceSource ↗
Surface sizing derived from layout records, in layout points (not CSS pixels).
interface SurfaceExtent| Member | Type | Summary |
|---|---|---|
| height | number | Total document height (always from every page, for scroll extent). |
| pageOffsetX | ReadonlyMap<number, number> | Extra horizontal offset per page, in layout points, so narrower sheets centre inside a mixed-width materialized window. Absent entries mean no offset beyond layout `box.x`. |
| width | number | Width the surface container should occupy. |
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 | |
| 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. |
| 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 | |
| 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 |
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. |
Type aliases (23)
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' | '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' | '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.clear' | 'review.comments' | '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' | '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;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';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';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;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';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';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';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 (24)
BROWSER_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.clearFormatting";
readonly controls: readonly [{
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: "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: "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, 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 = 12700IMAGE_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[]MAX_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']