New

docx-editor 1.x has shipped. Vue support, i18n, agents. Read the migration guide →

API Referencev1.0.2

@eigenpal/docx-editor-core/prosemirror

ProseMirror Integration for DOCX Editor

This module provides ProseMirror-based editing: - Schema for DOCX document structure - Bidirectional conversion between Document and PM - React wrapper component - Plugins for selection tracking - Commands for formatting - Extension system for schema, plugins, and keymaps

Functions(74)

declare function addColumnLeft(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function addColumnRight(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function addRowAbove(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function addRowBelow(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function addTabStop(position: number, alignment?: TabStopAlignment, leader?: TabLeader): Command;
declare function applyStyle(styleId: string, resolvedAttrs?: ResolvedStyleAttrs): Command;
declare function applyTableStyle(styleData: {
    styleId: string;
    tableBorders?: Record<string, unknown>;
    conditionals?: Record<string, unknown>;
    look?: Record<string, boolean>;
}): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function autoFitContents(): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;

Create an empty ProseMirror document

declare function createEmptyDoc(): Node;

Create selection tracker plugin

declare function createSelectionTrackerPlugin(onSelectionChange?: SelectionChangeCallback): Plugin;

Create a style resolver from document's style definitions

declare function createStyleResolver(styleDefinitions: StyleDefinitions | undefined): StyleResolver;
declare function decreaseIndent(amount?: number): Command;
declare function deleteColumn(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function deleteRow(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function deleteTable(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function distributeColumns(): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;

Extract selection context from editor state

declare function extractSelectionContext(state: EditorState): SelectionContext;

Extract selection state from editor state. Used by PagedEditor integration in DocxEditor for toolbar state.

declare function extractSelectionState(state: EditorState): SelectionState | null;

Resolve the hyperlink mark + contiguous range that surrounds the current cursor. Used by edit/remove popup actions in both adapters.

Resolution order for the mark itself: 1. `$from.marks()` — the normal active-marks lookup 2. `$from.nodeAfter`/`nodeBefore` marks — boundary positions don't report active marks via `marks()` 3. (optional) text-node search by `fallbackHref` — last resort when the popup knows the href but the cursor sits at a gap

The returned range walks the parent block grouping consecutive text nodes that share the same href, and returns whichever range contains the cursor.

declare function findHyperlinkRangeAt(state: EditorState, fallbackHref?: string): {
    mark: Mark;
    start: number;
    end: number;
} | null;
fn

findParagraphByParaId

packages/core/src/core.ts:139

ProseMirror position range for the paragraph (or any textblock) whose `paraId` attribute equals `paraId`. Returns the inclusive `from` and exclusive `to` positions, plus the node, so callers can both target the paragraph (e.g. addMark over its text range) and inspect it.

`from` is the position immediately before the textblock; `to` is `from + node.nodeSize`. The text content lives at `[from + 1, to - 1]`.

Returns null if no textblock with that paraId exists.

declare function findParagraphByParaId(doc: Node, paraId: string): {
    node: Node;
    from: number;
    to: number;
} | null;
fn

findStartPosForParaId

packages/core/src/core.ts:138

ProseMirror position immediately before the first textblock whose `paraId` attribute equals `paraId` (Word `w14:paraId` / OOXML paragraph id).

Match is strict string equality on `node.attrs.paraId`.

declare function findStartPosForParaId(doc: Node, paraId: string): number | null;

Convert footnote/endnote content (array of Paragraph/Table blocks) to a ProseMirror document. Mirrors `headerFooterToProseDoc` so footnotes flow through the same body pipeline (toFlowBlocks → measureBlocks → renderFragment) and inherit its block support — paragraph + table + image + textBox + fields. Pre-PR, footnoteLayout's `convertFootnoteToContent` re-implemented run/paragraph conversion by hand and silently dropped tables, images, and fields nested inside a footnote.

declare function footnoteToProseDoc(content: Array<Paragraph | Table>, options?: ToProseDocOptions & {
    theme?: Theme | null;
}): Node;

Convert a ProseMirror document to our Document type

declare function fromProseDoc(pmDoc: Node, baseDocument?: Document): Document;
declare function getHyperlinkAttrs(state: EditorState): {
    href: string;
    tooltip?: string;
} | null;
declare function getListInfo(state: EditorState): {
    numId: number;
    ilvl: number;
} | null;

Get the current value of a mark attribute

declare function getMarkAttr(state: EditorState, markType: MarkType, attr: string): unknown | null;
declare function getParagraphAlignment(state: EditorState): ParagraphAlignment | null;
declare function getParagraphBidi(state: EditorState): boolean;
declare function getSelectedText(state: EditorState): string;

Get current selection context from editor state

declare function getSelectionContext(state: EditorState): SelectionContext | null;
declare function getStyleId(state: EditorState): string | null;
declare function getTableContext(state: EditorState): TableContextInfo;

Convert HeaderFooter content (array of Paragraph/Table blocks) to a ProseMirror document. Used for editing headers/footers in their own ProseMirror editor and for the unified header/footer render pipeline. `theme` must be threaded for themeColor resolution in cell shading (`<w:shd w:themeFill=...>`) — without it, themed fills in HF tables fall back to the unresolved theme key.

declare function headerFooterToProseDoc(content: Array<Paragraph | Table>, options?: ToProseDocOptions & {
    theme?: Theme | null;
}): Node;
declare function increaseIndent(amount?: number): Command;
declare function insertTable(rows: number, cols: number): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function isHyperlinkActive(state: EditorState): boolean;
declare function isInList(state: EditorState): boolean;
declare function isInTableCell(state: EditorState): boolean;

Check if a mark is active in the current selection

declare function isMarkActive(state: EditorState, markType: MarkType, attrs?: Record<string, unknown>): boolean;
declare function mergeCells(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function removeTableBorders(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function removeTabStop(position: number): Command;
declare function selectColumn(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function selectRow(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function selectTable(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;

Paragraph Formatting Commands — thin re-exports from extension system

Alignment, line spacing, indentation, lists, paragraph styles. All implementations live in extensions/; this file re-exports for backward compatibility.

declare function setAlignment(alignment: ParagraphAlignment): Command;
declare function setAllTableBorders(state: EditorState, dispatch?: (tr: Transaction) => void, borderSpec?: {
    style: string;
    size: number;
    color: {
        rgb: string;
    };
}): boolean;
declare function setCellBorder(side: 'top' | 'bottom' | 'left' | 'right' | 'all', spec: {
    style: string;
    size?: number;
    color?: {
        rgb: string;
    };
} | null, clearOthers?: boolean): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function setCellFillColor(color: string | null): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function setCellMargins(margins: {
    top?: number;
    bottom?: number;
    left?: number;
    right?: number;
}): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function setCellTextDirection(direction: string | null): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function setCellVerticalAlign(align: 'top' | 'center' | 'bottom'): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function setFontFamily(fontName: string): Command;
declare function setFontSize(size: number): Command;
declare function setHighlight(color: string): Command;
declare function setIndentFirstLine(twips: number, hanging?: boolean): Command;
declare function setIndentLeft(twips: number): Command;
declare function setIndentRight(twips: number): Command;
declare function setInsideTableBorders(state: EditorState, dispatch?: (tr: Transaction) => void, borderSpec?: {
    style: string;
    size: number;
    color: {
        rgb: string;
    };
}): boolean;
declare function setLineSpacing(value: number, rule?: LineSpacingRule): Command;
declare function setOutsideTableBorders(state: EditorState, dispatch?: (tr: Transaction) => void, borderSpec?: {
    style: string;
    size: number;
    color: {
        rgb: string;
    };
}): boolean;
declare function setRowHeight(height: number | null, rule?: 'auto' | 'atLeast' | 'exact'): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function setTableBorderColor(color: string): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function setTableBorders(preset: BorderPreset, borderSpec?: {
    style: string;
    size: number;
    color: {
        rgb: string;
    };
}): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function setTableBorderWidth(size: number): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function setTableProperties(props: {
    width?: number | null;
    widthType?: string | null;
    justification?: 'left' | 'center' | 'right' | null;
}): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function setTextColor(attrs: TextColorAttrs): Command;
declare function splitCell(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
declare function toggleHeaderRow(): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;
declare function toggleNoWrap(): (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean;

Convert a Document to a ProseMirror document

declare function toProseDoc(document: Document, options?: ToProseDocOptions): Node;

Update a Document with content from a ProseMirror document Preserves all non-content parts of the original document

declare function updateDocumentContent(originalDocument: Document, pmDoc: Node): Document;

Classes(2)

LayoutSelectionGate coordinates the timing between document edits and layout reflow so that selection overlays are only painted against current DOM geometry.

Workflow: 1. Document changes → setStateSeq(++seq) 2. Layout starts → onLayoutStart() 3. Layout completes → onLayoutComplete(seq) 4. Selection update requested → requestRender() 5. If safe → callback is called

declare class LayoutSelectionGate
MemberTypeSummary
getDebugInfoGet debug info about current state.
getRenderSeqGet current layout render sequence.
getStateSeqGet current document state sequence.
incrementStateSeqIncrement document state sequence (convenience method). Returns the new sequence value.
isSafeToRenderCheck if it's safe to render selection. Safe when: layout is not updating AND render sequence = state sequence
onLayoutCompleteCalled when layout computation and DOM painting completes.
onLayoutStartCalled when layout computation starts.
onRenderRegister a callback to be called on render events.
requestRenderRequest a selection render. Will be executed when safe. If already safe, executes immediately.
resetReset the gate state (useful for testing or document reload).
setStateSeqSet the document state sequence (call when document changes). This should be called on every ProseMirror transaction that changes the doc.

StyleResolver provides efficient access to resolved style properties

declare class StyleResolver
MemberTypeSummary
(constructor)Constructs a new instance of the `StyleResolver` class
getDefaultCharacterStyleGet the default character style (the one marked `w:default="1"`).
getDefaultParagraphStyleGet default paragraph style (usually "Normal")
getDefaultTableStyleGet the default table style (the one marked `w:default="1"`).
getDocDefaultsGet document defaults
getParagraphStylesGet all available paragraph styles (for toolbar dropdown)
getRunStyleOwnPropertiesGet a character style's own properties WITHOUT docDefaults. Used when the caller already has docDefaults applied (e.g., from paragraph style resolution). This prevents docDefault fonts from incorrectly overriding paragraph style fonts.
getStyleGet a style by ID
getTableStylesGet all available table styles (for style gallery)
hasParagraphStyleWhether a paragraph style with the given id is defined in the document's `styles.xml`. Used by the agent toolkit to refuse `set_paragraph_style({ styleId: 'NoSuchStyle' })` instead of silently writing an invalid `<w:pStyle>` reference.
hasStyleCheck if a style exists
resolveParagraphStyleResolve paragraph style properties, including docDefaults cascade
resolveRunStyleResolve run (character) style properties

Interfaces(12)

Font family mark attributes

interface FontFamilyAttrs
MemberTypeSummary
ascii?string
asciiTheme?string
cs?string
csTheme?string
eastAsia?string
eastAsiaTheme?string
hAnsi?string
hAnsiTheme?string

Font size mark attributes

interface FontSizeAttrs
MemberTypeSummary
sizenumber

Hyperlink mark attributes

interface HyperlinkAttrs
MemberTypeSummary
hrefstring
rId?string
tooltip?string

Image node attributes

interface ImageAttrs
MemberTypeSummary
allowOverlap?boolean`wp:anchor allowOverlap`. Same tri-state convention as `layoutInCell`.
alt?string
borderColor?stringBorder color as CSS color string
borderStyle?stringBorder style (CSS border-style value)
borderWidth?numberBorder width in pixels
cropBottom?number
cropLeft?number
cropRight?number
cropTop?number`wp:srcRect` crop fractions in [0, 1]. Each side is the fraction of the source image that should be hidden. Renders as CSS `clip-path: inset(...)`.
cssFloat?'left' | 'right' | 'none'CSS float direction for floating images
displayMode?'inline' | 'float' | 'block'Display mode for CSS: inline (flows with text), float (left/right float), block (centered)
distBottom?numberDistance from text below (pixels)
distLeft?numberDistance from text left (pixels)
distRight?numberDistance from text right (pixels)
distTop?numberDistance from text above (pixels)
effectExtentBottom?number
effectExtentLeft?number
effectExtentRight?number
effectExtentTop?number`wp:effectExtent` padding (pixels) — extra space reserved around the image for shadows, glows, soft edges, etc. Applied as outer margin so the effect isn't clipped by surrounding content.
height?numberHeight in pixels (already converted from EMU)
hlinkHref?stringHyperlink URL for clickable image
layoutInCell?boolean`wp:anchor layoutInCell`. Tri-state: true / false / undefined (= Word's default "1"). Floating-only; round-tripped on save.
opacity?number`a:alphaModFix amt` mapped to CSS `opacity` in [0, 1].
position?ImagePositionAttrsPosition for floating images (horizontal and vertical alignment)
rId?string
srcstring
title?string
transform?stringCSS transform string (rotation, flip)
width?numberWidth in pixels (already converted from EMU)
wrapText?stringWrap text setting from DOCX (left, right, bothSides, largest) for round-trip
wrapType?WrapTypeWrap type from DOCX: inline, square, tight, through, topAndBottom, behind, inFront

Paragraph node attributes - maps to ParagraphFormatting

interface ParagraphAttrs
MemberTypeSummary
_originalFormatting?ParagraphFormattingOriginal inline paragraph formatting from DOCX (pre-style-resolution). Used by fromProseDoc for lossless round-trip serialization.
_sectionProperties?SectionPropertiesFull section properties for paragraphs that end a section. Used by layout engine for per-section column/page config and round-trip.
alignment?ParagraphAlignment
bidi?boolean
bookmarks?Array<{ id: number; name: string; }>
borders?{ top?: BorderSpec; bottom?: BorderSpec; left?: BorderSpec; right?: BorderSpec; between?: BorderSpec; bar?: BorderSpec; }
contextualSpacing?booleanContextual spacing — suppress space between same-style paragraphs
defaultTextFormatting?TextFormatting
hangingIndent?boolean
indentFirstLine?number
indentLeft?number
indentRight?number
keepLines?boolean
keepNext?boolean
lineSpacing?number
lineSpacingRule?LineSpacingRule
listAbstractNumId?numberSee ListRendering.abstractNumId.
listIsBullet?booleanWhether this is a bullet list
listLevelNumFmts?NumberFormat[]NumberFormat for each level 0..ilvl (inclusive). Lets toFlowBlocks resolve multi-level templates like "%1.%2." with the correct format per token.
listMarker?stringComputed list marker text (e.g., "1.", "1.1.", "•")
listMarkerFontFamily?stringMarker font family from numbering level rPr
listMarkerFontSize?numberMarker font size from numbering level rPr, in points
listMarkerHidden?booleanWhether the list marker is hidden (w:vanish on numbering level rPr)
listNumFmt?NumberFormatList number format (decimal, lowerRoman, upperRoman, etc.) for CSS counter styling
listStartOverride?numberSee ListRendering.startOverride.
numPr?{ numId?: number; ilvl?: number; }
outlineLevel?number
pageBreakBefore?boolean
paraId?string
renderedPageBreakBefore?booleanWord's cached layout marker (`<w:lastRenderedPageBreak/>`). Treated like `pageBreakBefore` for layout, kept as a separate attr so save+reload preserves the marker at the same position Word recorded.
sectionBreakType?'nextPage' | 'continuous' | 'oddPage' | 'evenPage'
shading?ShadingProperties
spaceAfter?number
spaceBefore?number
spacingExplicit?SpacingExplicitSee ParagraphFormatting.spacingExplicit.
styleId?string
tabs?TabStop[]
textId?string

Resolved style properties ready for rendering

interface ResolvedParagraphStyle
MemberTypeSummary
paragraphFormatting?ParagraphFormattingParagraph formatting (alignment, spacing, indentation, etc.)
runFormatting?TextFormattingDefault run formatting from the style

Selection context for toolbar state

interface SelectionContext
MemberTypeSummary
activeCommentIdsnumber[]Active comment IDs at cursor position
endParagraphIndexnumberEnd paragraph index
hasSelectionbooleanWhether there's a non-collapsed selection
inDeletionbooleanWhether cursor is inside a tracked deletion
inInsertionbooleanWhether cursor is inside a tracked insertion
inListbooleanWhether cursor is in a list
isMultiParagraphbooleanWhether selection spans multiple paragraphs
listLevel?numberList level (0-8)
listType?'bullet' | 'numbered'List type if in list
paragraphFormattingParagraphFormattingCurrent paragraph formatting
startParagraphIndexnumberStart paragraph index
textFormattingTextFormattingCurrent text formatting at cursor/selection

Selection state for toolbar integration

interface SelectionState
MemberTypeSummary
endParagraphIndexnumberEnd paragraph index
hasSelectionbooleanWhether there's an active selection (not just cursor)
isMultiParagraphbooleanWhether selection spans multiple paragraphs
paragraphFormattingParagraphFormattingCurrent paragraph formatting
startParagraphIndexnumberStart paragraph index
styleIdstring | nullCurrent paragraph style ID (e.g., 'Heading1', 'Normal')
textFormattingTextFormattingCurrent text formatting at selection/cursor

Table selection context + navigation helpers.

`getTableContext` walks the selection up from `$from` and reports which table / row / cell the cursor is in, plus the table's row/column counts, whether a multi-cell selection is active, and the current cell's border + fill colors (so the toolbar's color pickers can show the live values).

`goToNextCell` / `goToPrevCell` are tab-stop-style cell navigation commands registered by the plugin extension.

interface TableContextInfo
MemberTypeSummary
canSplitCell?boolean
cellBackgroundColor?stringCurrent cell's background/fill color (RGB hex without #), if any
cellBorderColor?ColorValueCurrent cell's dominant border color, if any
columnCount?number
columnIndex?number
hasMultiCellSelection?boolean
isInTableboolean
rowCount?number
rowIndex?number
table?Node
tablePos?number

Text color mark attributes

interface TextColorAttrs
MemberTypeSummary
rgb?string
themeColor?ThemeColorSlot
themeShade?string
themeTint?string

Options for document conversion

interface ToProseDocOptions
MemberTypeSummary
styles?StyleDefinitionsStyle definitions for resolving paragraph styles

Underline mark attributes

interface UnderlineAttrs
MemberTypeSummary
color?TextColorAttrs
style?UnderlineStyle

Type aliases(2)

Cell-border commands. Each command applies a preset / individual side / color / width to the cells targeted by the current selection (single cursor cell or active `CellSelection`).

All four commands use the shared `buildTableGrid` lookup to find each cell's neighbours in the grid, then sync the matching edge on the adjacent cell — Google-Docs style edge-symmetric border editing.

Schema-free: only attribute updates via `tr.setNodeMarkup`.

type BorderPreset = 'all' | 'outside' | 'inside' | 'none';

Callback type for selection changes

type SelectionChangeCallback = (context: SelectionContext) => void;

Variables(28)

alignCenter: Command
alignJustify: Command
alignLeft: Command
alignRight: Command
clearFontFamily: Command
clearFontSize: Command

Clear all text formatting (remove all marks)

clearFormatting: Command
clearHighlight: Command
clearStyle: Command
clearTextColor: Command
decreaseListLevel: Command
generateTOC: Command
increaseListLevel: Command

Insert a page break at the current cursor position. Always ensures a paragraph follows the page break and places the cursor there.

insertPageBreak: Command
removeList: Command
schema: prosemirror_model.Schema<any, any>

Plugin key for accessing selection tracker state

selectionTrackerKey: PluginKey<SelectionContext>
setLtr: Command
setRtl: Command
toggleBold: Command
toggleBulletList: Command
toggleItalic: Command
toggleNumberedList: Command
toggleStrike: Command
toggleSubscript: Command
toggleSuperscript: Command
toggleUnderline: Command