Skip to Content
API Referencecorecore/helpers

@stesura/core/helpers

Helpers that read or derive editor state (document, selection, marks, styles, numbering, sections, tables) and convert attrs to CSS. None of them dispatch except clearContent, startImageUpload and unWrap.

Core ProseMirror utilities

applyTrForEachNodeType

Runs callback for every type (no short-circuit); true if any returned true.

Parameters:
NameTypeDefault
nodeTypesstring[]
callback(type: string) => boolean
Returns:
boolean

atLeastToMultiplier

Word’s “At least” pt as a line-height multiplier. Word lays each line at the larger of pt and the line’s single line (checked over COM); the paragraph’s main run (most characters) stands in for its lines. 1 when pt is within that run’s single line, the common case (corpus: ~80% of “At least” paragraphs).

Parameters:
NameTypeDefault
ptnumber
runsLineHeightRun[]
Returns:
number

attrAwareTokenEncoder

A ChangeSet token encoder that also distinguishes the given attrs.

The default encoder tokenizes a node by type name alone, so two same-type atoms with different attrs look identical. Pasting a copy of a range back over part of itself then diffs as unchanged and the replaced node is never reported (MT-16: a deleted comment_open went unreported, orphaning its close).

Use for atoms whose attrs ARE their identity. Nodes without any of these attrs set encode exactly as the default.

Parameters:
NameTypeDefault
attrNamesreadonly string[]
Returns:
TokenEncoder<string | number>

blockHasNoText

True when the block holds no text beyond whitespace or a lone zero-width space. Not an emptiness check: a block holding only an atom (image, page number) answers true, which is what numbering wants when skipping blank lines. Text carrying hidden (pending deletion) doesn’t count: accepted, it’s gone.

Parameters:
NameTypeDefault
nodeNode
hiddenMarkType
Returns:
boolean

canWrapInInlineNode

Whether the selection can be wrapped in an inline node: each range at one depth, no boundary nodes inside.

Parameters:
NameTypeDefault
selectionSelection
stateEditorState
Returns:
boolean

changedRanges

Ranges of after that may hold nodes differing from before: a superset, found by comparing the two trees instead of mapping steps, so its cost is independent of how many steps produced after (CORE-156).

ProseMirror nodes are persistent: an unchanged subtree is the same object in both docs. Per node pair:

  • same object: skipped;
  • different markup (type, attrs, marks): the whole new node, without recursing, since an attr-only change has identical content;
  • same markup: its children are compared, unless it is a textblock or a leaf, which is reported whole;
  • different doc attrs: the whole document.

Ranges are disjoint and in document order. An attr set to its current value still makes a new node and is reported; callers re-derive idempotently.

Parameters:
NameTypeDefault
beforeNode
afterNode
Returns:
DocRange[]

clearContent

Replaces the view’s document content with the schema’s minimal valid content.

Parameters:
NameTypeDefault
viewEditorView
Returns:
void

convertContentToSchema

Moves content into another Schema instance (e.g. main editor → sub-editor) via a JSON round trip.

Multi-node content converts PER NODE: a child the target schema rejects is dropped alone. All-or-nothing showed an empty sub-editor over a non-empty region, and every inner edit after that forwarded against divergent coordinates.

Parameters:
NameTypeDefault
contentNode | Node[] | Fragment
schemaSchema<any, any>
contentIfEmptyFragment

Returned (instead of Fragment.empty) when content is absent, an empty fragment, or converts to nothing.

optionsCreateNodeFromContentOptions

Forwarded to createNodeFromContent.

Returns:
Node | Fragment

createLoadState

A state over doc for running a derivation written against EditorState on a doc that isn’t loaded. It carries only the stylesheet plugin, whose state resolves doc’s own sheet; without an editor id, the other helpers read the doc instead of the editor’s stores.

Parameters:
NameTypeDefault
docNode
stateEditorState
Returns:
EditorState

createNodeFromContent

Builds a node or fragment from JSON or an HTML string. Node/Fragment input is returned as is. Invalid content warns and yields empty content, or throws when errorOnInvalidContent is set.

Parameters:
NameTypeDefault
contentstring | Node | JSONContent | Fragment | JSONContent[]
schemaSchema<any, any>
optionsCreateNodeFromContentOptions
Returns:
Node | Fragment

defaultBlockAt

Finds the first textblock node type in a content match that has no required attributes.

Parameters:
NameTypeDefault
matchContentMatch
Returns:
NodeType | null

DocRange

A range in the NEW document, from and to on node boundaries.

NameTypeDefault
fromnumber
tonumber

docChanged

Returns true if any of the transactions modified the document.

Parameters:
NameTypeDefault
__0AppendTransactionProps
Returns:
boolean

docIsEmpty

docNodeIsEmpty for state.doc.

Parameters:
NameTypeDefault
stateEditorState
Returns:
boolean

docNodeIsEmpty

Whether doc is missing, has no children, or holds a single empty textblock. Use when you hold a doc rather than a state, e.g. a submitted comment body.

Parameters:
NameTypeDefault
docNode
Returns:
boolean

elementFromString

Parses an HTML string into an HTMLElement, stripping excess whitespace.

Parameters:
NameTypeDefault
valuestring
Returns:
HTMLElement

emitProfile

Emit an event to the installed profiler; no-op when none is installed.

Parameters:
NameTypeDefault
eventProfilerEvent
Returns:
void

exceedsRangeBudget

Whether ranges are many enough, or cover enough of doc, that a whole-doc pass is cheaper than one pass per range: over 200 ranges or a quarter of the doc (measured on a 355-page document, docs/partially-executed/large-docx-import-perf-plan.md).

Parameters:
NameTypeDefault
rangesDocRange[]
docNode
Returns:
boolean

filterFragment

Returns a copy of fragment with shouldRemove nodes dropped (at any depth) and transform applied to every surviving node, parents included (MT-13). Children are processed first, so transform sees already-filtered content.

pos is the offset within the node’s OWN parent fragment, not a document position.

Parameters:
NameTypeDefault
fragmentFragment
shouldRemove(node: Node, pos: number) => boolean
transform(node: Node, pos: number) => Node
Returns:
Fragment

findChildrenInRange

Nodes matching predicate within range. A collapsed range checks only the node at from; otherwise the walk is nodesBetween, so ancestors overlapping the range are visited too.

Parameters:
NameTypeDefault
nodeNode
rangeRange
predicateFindPredicate
Returns:
NodeWithPos[]

findLineHeightOption

The LINE_HEIGHTS entry a line height shows as, or undefined (an off-list or “Xpt” value).

Parameters:
NameTypeDefault
lineHeightunknown
Returns:
{ label: string; value: number; } | undefined

findNode

Finds the first node matching a predicate in the document tree.

Parameters:
NameTypeDefault
nodeNode
predicate(node: Node) => boolean
Returns:
NodeWithPos | undefined

findNodes

Recursively finds all nodes in the document tree matching a predicate.

Parameters:
NameTypeDefault
nodeNode
predicate(node: Node) => boolean
Returns:
NodeWithPos[]

findWordBoundary

Steps from pos in direction while the adjacent character is a word character; returns where it stopped.

Parameters:
NameTypeDefault
docNode
posnumber
direction1 | -1
Returns:
number

forEachNode

Calls back with every node (descendants included) inside range and its ABSOLUTE document position.

Walks range.parent, not $from.node(): for a multi-block range the latter is the first block rather than the shared parent.

Parameters:
NameTypeDefault
rangeNodeRange
callback(node: Node, pos: number) => void
Returns:
void

getAddedAndRemovedNodes

Nodes added or removed across transactions, found by a ChangeSet diff. Exits early, without a ChangeSet, when no transaction changed the doc or (with skipSimpleTextTransactions, default true) all are plain typing.

Parameters:
NameTypeDefault
__0AddedAndRemovedNodeProps

Also report ancestors spanning a change. Default: only nodes starting inside it.

Returns:
{ removed: { node: Node; pos: number; }[] | undefined; added: { node: Node; pos: number; }[] | undefined; changes?: never; } | { removed: { node: Node; pos: number; }[] | undefined; added: { ...; }[] | undefined; changes: readonly Change<...>[]; }

removed (positions in oldState), added (positions in newState) and the ChangeSet changes, which are absent on the early exits.

getAttributes

Gets node or mark attributes by type or name at the current selection.

Parameters:
NameTypeDefault
stateEditorState
typeOrNamestring | NodeType | MarkType
Returns:
Attrs

getChangeDeletions

The changes that delete content (non-empty A side).

Parameters:
NameTypeDefault
changesreadonly Change<any>[] | Change<any>[]
Returns:
Change<any>[]

getChangeInsertions

The changes that insert content (non-empty B side).

Parameters:
NameTypeDefault
changesreadonly Change<any>[] | Change<any>[]
Returns:
Change<any>[]

getDomRangeFromSelection

DOM Range for a ProseMirror selection, for anchoring floating menus. A collapsed selection in an empty block or at the end of a textblock expands to the whole block so the range has non-zero size.

Parameters:
NameTypeDefault
viewEditorView
selectionSelection
Returns:
Range

getEditorId

The editor id from the config plugin, or undefined outside a Stesura editor.

Parameters:
NameTypeDefault
stateEditorState
Returns:
string | undefined

getMarkAttributes

Attributes of the first mark of that type in the selection (stored marks first when collapsed), or {}.

Parameters:
NameTypeDefault
stateEditorState
typeOrNamestring | MarkType
Returns:
Attrs

getMarkRange

Contiguous range of sibling nodes around $pos carrying a type mark with matching attributes (default: the attrs of the mark at $pos). Undefined when neither neighbour of $pos has the mark.

Parameters:
NameTypeDefault
$posResolvedPos
typeMarkType
attributesAttrs
Returns:
void | Range

getMarksBetween

Marks between from and to with their ranges. Collapsed: the full extent of each mark active at from. Otherwise one entry per mark per node, ancestors included, unmerged.

Parameters:
NameTypeDefault
fromnumber
tonumber
docNode
Returns:
MarkRange[]

getMarkType

Resolves a mark type from a name or MarkType instance, returning undefined if not found in the schema.

Parameters:
NameTypeDefault
nameOrTypestring | MarkType
schemaSchema<any, any>
Returns:
MarkType | undefined

getNodeAttributes

Attributes of the last node of that type touched by the selection (its ancestors included), or {}.

Parameters:
NameTypeDefault
stateEditorState
typeOrNamestring | NodeType
Returns:
Attrs

getNodeSpecAttrs

The attrs object of a node’s toDOM spec, or {} when it has none.

Parameters:
NameTypeDefault
nodeNode
childIndexnumber

Read the nested spec at this index instead (e.g. 2 is the first child of [tag, attrs, child]).

Returns:
Record<string, string>

getNodeSpecDataAttrs

getNodeSpecAttrs filtered to data-*, for nodeviews that mirror toDOM but manage attrs like src/width/height in component state.

Parameters:
NameTypeDefault
nodeNode
childIndexnumber
Returns:
Record<string, string>

getNodeSpecReactProps

getNodeSpecAttrs as React props: class → className, style parsed to CSSProperties, HTML names camelCased (colspan → colSpan, for → htmlFor, …); the rest passes through.

React nodeviews should spread this, not the raw attrs: withGlobalAttributes always injects class/style into toDOM, and raw HTML names make React warn.

Parameters:
NameTypeDefault
nodeNode
childIndexnumber
Returns:
NodeSpecReactProps

getNodeType

Resolves a node type from a name or NodeType instance, throwing if not found in the schema.

Parameters:
NameTypeDefault
nameOrTypestring | NodeType
schemaSchema<any, any>
Returns:
NodeType

getParagraphOrHeading

Finds the closest parent paragraph or heading node relative to the current selection.

Parameters:
NameTypeDefault
stateEditorState
Returns:
FindResult

getParentEditorId

For a sub-editor, the id of the editor that owns it; undefined for root editors.

Parameters:
NameTypeDefault
stateEditorState
Returns:
string | undefined

getProfilerHook

The installed hook, or undefined (production / profiler not loaded).

Parameters:
This function does not accept any parameters.
Returns:
StesuraProfilerHook | undefined

getRectFromCoords

Turns coordsAtPos-style edges into a DOMRect-shaped object, for anchoring floating UI.

Parameters:
NameTypeDefault
coords{ top: number; left: number; right: number; bottom: number; }
Returns:
{ x: number; y: number; width: number; height: number; top: number; right: number; bottom: number; left: number; }

getSchemaTypeByName

Tries to get a node or mark type by its name.

Parameters:
NameTypeDefault
namestring
schemaSchema<any, any>
Returns:
NodeType | MarkType | null

getSchemaTypeNameByName

Returns whether a schema item is a "node" or "mark", or null if it doesn’t exist.

Parameters:
NameTypeDefault
namestring
schemaSchema<any, any>
Returns:
"node" | "mark" | null

isAddMarkStep

Type guard that checks if a step is an AddMarkStep.

Parameters:
NameTypeDefault
stepStep
Returns:
boolean

isAddNodeMarkStep

Type guard that checks if a step is an AddNodeMarkStep.

Parameters:
NameTypeDefault
stepStep
Returns:
boolean

asAttrStep

step as the AttrStep it amounts to in doc (the doc it applies to), for code reading block attr writes: a LifecycleStep’s, an AttrStep itself, else null.

Parameters:
NameTypeDefault
stepStep
docNode
Returns:
AttrStep | null

LifecycleStep

A textblock’s lifecycle write (trackChanges), addressed by its ¶: the block’s content end, as Word keeps a paragraph’s revision on its mark. An AttrStep addresses the opening token, which a split leaves on the first half while the original ¶ goes to the last: mapped past a concurrent split (the server’s mapping, a rebase’s replay), it landed on the other client’s new half (TC-237). This step maps with the ¶, and fails (so is dropped) where no textblock ends: its ¶ was joined away.

NameTypeDefault
endnumber

The block’s content end: its position + size − 1.

valueTrackChangesAttrs
target(doc: Node) => { node: Node; pos: number; } | null

The textblock whose content ends at end in doc, with its position.

apply(doc: Node) => StepResult
getMap() => StepMap
invert(doc: Node) => Step
map(mapping: Mappable) => Step | null
toAttrStep(doc: Node) => AttrStep | null

The AttrStep this step amounts to in doc, the doc it applies to: for code reading block attr writes.

toJSON() => { stepType: string; end: number; value: TrackChangesAttrs | null; }
merge(other: Step) => Step | null

Try to merge this step with another one, to be applied directly after it. Returns the merged step when possible, null if the steps can’t be merged.

isAttrStep

Type guard that checks if a step is an AttrStep.

Parameters:
NameTypeDefault
stepStep
Returns:
boolean

isCollabOrHistoryTransaction

Checks if a transaction originates from history, or collaboration.

Parameters:
NameTypeDefault
trTransaction
Returns:
any

isCollabRebase

Whether a transaction is a collab-commit rebase: the client’s pending steps undone, a remote commit applied, the pending ones replayed (rebased counts them). The one client that sees both sides of a concurrent edit, so the one to repair what the merge broke (F4).

Parameters:
NameTypeDefault
trTransaction
Returns:
boolean

isCollabTransaction

Whether a transaction applies collab changes.

collab$ is new PluginKey("collab").key: core’s vendored collab-commit (src/collab-commit), the only “collab” key loaded. Remote applies carry it, and so do collab-commit’s rebases, which replay the client’s own pending steps over the remote ones (their rebased meta counts them). Read as a string so prosemirror-collab’s transactions count too.

Parameters:
NameTypeDefault
trTransaction
Returns:
any

isDocAttrStep

Type guard that checks if a step is a DocAttrStep.

Parameters:
NameTypeDefault
stepStep
Returns:
boolean

isMarkActive

Determines if a mark is active at the current selection (checks stored marks for empty selections).

Parameters:
NameTypeDefault
markMarkType
stateEditorState
Returns:
boolean

isNodeActive

Determines if a node type with optional matching attributes is active at the current selection.

Parameters:
NameTypeDefault
stateEditorState
typeOrNamestring | NodeType
attributesAttrs
Returns:
boolean

isRemoteCollabTransaction

Whether a transaction applies REMOTE collab changes. Same test as isCollabTransaction today; separate because read-only gating cares about remoteness, and a backend with local-origin collab meta would diverge here.

Parameters:
NameTypeDefault
trTransaction
Returns:
boolean

isRemoveMarkStep

Type guard that checks if a step is a RemoveMarkStep.

Parameters:
NameTypeDefault
stepStep
Returns:
boolean

isRemoveNodeMarkStep

Type guard that checks if a step is a RemoveNodeMarkStep.

Parameters:
NameTypeDefault
stepStep
Returns:
boolean

isReplaceAroundStep

Type guard that checks if a step is a ReplaceAroundStep.

Parameters:
NameTypeDefault
stepStep
Returns:
boolean

isReplaceStep

Type guard that checks if a step is a ReplaceStep.

Parameters:
NameTypeDefault
stepStep
Returns:
boolean

isSimpleTextTransaction

True when the doc is unchanged or the transaction is a single ReplaceStep that inserts only text and deletes only text within one textblock. Lets callers skip ChangeSet work for plain keystrokes.

Parameters:
NameTypeDefault
trTransaction
Returns:
boolean

isTextSelection

Type guard that checks if a value is a ProseMirror TextSelection instance.

Parameters:
NameTypeDefault
valueunknown
Returns:
boolean

LineHeightRun

A run of text: its font and how many characters it holds.

NameTypeDefault
fontSizenumber
fontFamilystring
charsnumber

nodeHasContent

True if node has any descendant other than an empty paragraph. Text nodes count too, so a whitespace-only paragraph is content.

Parameters:
NameTypeDefault
nodeNode
Returns:
boolean

nodeIsInOrAroundSelection

Whether a node matching callback is an ancestor of a collapsed selection, or touched by a non-empty one.

Parameters:
NameTypeDefault
stateEditorState
callback(node: Node) => boolean
Returns:
boolean

pmBench

Runs and returns fn, logging its duration when window.__pmBench is enabled.

Parameters:
NameTypeDefault
labelstring
fn() => T
Returns:
T

pmBenchEnd

Closes a pmBenchStart measurement and logs it, unindented. No-op when disabled.

Parameters:
NameTypeDefault
labelstring
startnumber
infoRecord<string, unknown>
Returns:
void

pmBenchStart

Starts a measurement for a region that isn’t a clean callback; close it with pmBenchEnd.

Parameters:
This function does not accept any parameters.
Returns:
number

posToDOMRect

Viewport bounding box of the coords at from and to (clamped to the doc), as a DOMRect-shaped object for positioning floating UI.

Parameters:
NameTypeDefault
viewEditorView
fromnumber
tonumber
Returns:
DOMRect

PrepareDoc

Load-time counterpart of a plugin’s appendTransaction: returns doc with the attrs and nodes the plugin would derive for it (ids, spacing, counters, …), or doc itself when it has nothing to add. state is the live editor’s, for its schema, config and stores; its doc is NOT the one being prepared.

Parameters:
NameTypeDefault
docNode
stateEditorState
Returns:
Node

prepareDocForLoad

Heals doc as createNormalizeTransaction would, then runs every plugin’s prepareDoc, in plugin order, until a round changes nothing. The heal comes first because the guard rewrites the load’s root transaction before any plugin sees it (clamped border widths feed spacing’s island borders). Plugin order is the order appendTransaction would derive in; the repeat covers derivations that read another’s output (cross-references read counters).

Mounting or dispatching the result instead of the raw doc turns a load into one transaction, or none: without it, the heal and the plugins emit one AttrStep per node per attr (CORE-156: ~25k steps for a 355-page import), and every consumer of those steps pays per step.

Parameters:
NameTypeDefault
stateEditorState
docNode
optionsPrepareDocForLoadOptions
Returns:
Node

privilegedDispatch

A dispatch that bypasses the read-only gate, for deliberate programmatic edits while mode is "view":

myCommand(view.state, privilegedDispatch(view));
Parameters:
NameTypeDefault
viewEditorView
Returns:
(tr: Transaction) => void

profilerActive

Whether a profiler is installed. One property read — safe on hot paths.

Parameters:
This function does not accept any parameters.
Returns:
boolean

ProfilerDispatchEvent

One dispatch through useEditorCore’s dispatchTransaction. Emitted AFTER the pluginHook events it encloses, so a collector groups everything since the previous dispatch event under it.

NameTypeDefault
type"dispatch"
editorIdstring
modifierMsnumber

Time spent in the transactionModifier (e.g. track changes), 0 if none.

applyMsnumber

Time spent in EditorState.apply (plugin state fields + appendTransaction rounds).

totalMsnumber

Wall-clock duration of the whole dispatch call, which includes the react-prosemirror render/commit and layout effects (flushSync). So totalMs − modifierMs − applyMs − react commit bounds the view update plus synchronous subscribers, which nothing else instruments.

stepsnumber
docChangedboolean
metaKeysstring[]

Keys of the transaction’s meta map — identifies the dispatch source.

atnumber

ProfilerEvent

NameTypeDefault
type"dispatch" | "pluginHook" | "reactCommit" | "paginationSession" | "diagnostic" | "paginationLayoutCheck"
editorIdstring
atnumber

performance.now() at the start of the hook.

ProfilerLayoutBlockDrift

One block of a pagination layout reconciliation. Layout px from the section top, at the block’s BOTTOM edge:

  • expected: where the engine computed it to end (page top + header + offset);
  • actual: where the DOM renders it ending;
  • drift = actual − expected, cumulative; positive renders LOWER;
  • step = drift − previous block’s drift. The FIRST non-zero step in document order is the root cause; later ones are usually cascade.
NameTypeDefault
nodeIdstring
typestring
pagenumber
expectednumber
actualnumber
driftnumber
stepnumber

ProfilerLayoutPageDrift

Drift at the first block of a page — the per-page view of the same series.

NameTypeDefault
pagenumber
nodeIdstring
driftnumber
stepnumber

ProfilerPaginationLayoutCheckEvent

A settled pagination verify pass (overflow invariant) for one section, with the block-level DOM reconciliation so the overlay shows WHERE computed and rendered layout diverge. Emitted on every settled check while installed.

NameTypeDefault
type"paginationLayoutCheck"
editorIdstring
sectionIdstring
status"ok" | "detected" | "recovered" | "unrecovered" | "gaveUp" | "tolerated"

Verify outcome; gaveUp = still failing after the one automatic recovery.

pageCountnumber
expectedHeightnumber
actualHeightnumber
overflownumber
checkednumber

Blocks compared / blocks the engine placed but the DOM lookup missed.

missingnumber
pagesProfilerLayoutPageDrift[]
divergencesProfilerLayoutBlockDrift[]

The first blocks (document order) whose |step| exceeds 1px — capped.

recheck() => void

Re-run the DOM reconciliation and emit a fresh event (no recompute).

recompute() => void

Wipe the section’s measurement cache and force a clean full rebuild, then re-verify.

reportstring

Markdown report for pasting into an AI session (failure mode, first divergent block and its predecessor, surrounding pages, drift series). Built at emit time: a failed check wipes the measurement cache right after.

atnumber

ProfilerReactCommitEvent

One React commit of the document subtree (a <React.Profiler> around ProseMirrorDoc), splitting reconciliation out of the dispatch window. Only fires in dev / profiling React builds.

NameTypeDefault
type"reactCommit"
editorIdstring
phase"mount" | "update" | "nested-update"
msnumber

React’s actualDuration: time spent rendering the committed update.

atnumber

renderStaticContent

Block content rendered outside the live editor so it lays out as the view would: paginated header and footer copies, a text box’s static render. Sanitized (painted from host toDOM specs too, SEC-77), ids stripped (the copy must not duplicate the live nodes’ ids, and the pagination margin rule keys on them), trailing breaks added. derived gives the derived values (counter labels, spacing) the live view renders (derivedResolverFor). Null without a DOM.

Parameters:
NameTypeDefault
contentFragment
schemaSchema<any, any>
tableStylesStaticTableStyles
derivedDerivedResolver
Returns:
DocumentFragment | null

StaticTableStyles

Table styles for a static render: the resolved sheet, and optionally the formats of a table rendered out of its context (the repeated header renders the header rows alone, but they resolve against the whole table).

NameTypeDefault
sheetStyleSheet
formatsOf(table: Node) => CellFormat[][]

selectionSpansEntireNode

Whether the selection runs exactly from the start to the end of the content of one styled block (its closest styled-block ancestor at both ends).

Parameters:
NameTypeDefault
selectionSelection | SelectionRange
Returns:
boolean

selectionToInsertionEnd

Puts the selection near the end of what the last step inserted. No-op unless steps were added after index startLen and the last is a replace step.

Parameters:
NameTypeDefault
trTransaction
startLennumber
biasnumber
Returns:
void

unWrap

Replaces the node at getPos() with its content and dispatches. No-op for a missing or childless node.

Parameters:
NameTypeDefault
stateEditorState
dispatch(tr: Transaction) => void
getPos() => number
Returns:
void

Accessibility

checkAccessibility

Runs every v1 rule over a document; findings come back in document order.

Parameters:
NameTypeDefault
docNode
Returns:
AccessibilityFinding[]

ACCESSIBILITY_CHECKER

The checker name the accessibility panel keeps ignored findings under, in doc.attrs.dismissedFindings. Dismiss and restore with dismissFindings and restoreFindings from @stesura/core/commands.

getDismissedFindings

The finding ids a checker (e.g. "accessibility") had dismissed on this document.

Parameters:
NameTypeDefault
stateOrDocEditorState | Node
checkerstring
Returns:
string[]

getAllDismissedFindings

doc.attrs.dismissedFindings, cleaned: checker name to the finding ids dismissed under it.

Parameters:
NameTypeDefault
stateOrDocEditorState | Node
Returns:
Record<string, string[]>

Borders

borderStyleToCSS

Word border style name to its CSS border-style keyword.

NameTypeDefault
nonestring
singlestring
doublestring
dottedstring
dashedstring
groovestring
ridgestring
insetstring
outsetstring

createDefaultBorderOptions

A 1px solid black border with no padding.

Parameters:
This function does not accept any parameters.
Returns:
Mutable<Omit<IBorderOptions, "style"> & { style: BorderStyle; }>

createDefaultBorders

All four outer sides set to createDefaultBorderOptions.

Parameters:
This function does not accept any parameters.
Returns:
Borders

deriveBorderOptions

The first side (in a fixed order) whose style isn’t none, else createDefaultBorderOptions.

Parameters:
NameTypeDefault
bordersBorders
Returns:
Mutable<Omit<IBorderOptions, "style"> & { style: BorderStyle; }>

generateTableBorderStyles

A table’s borders as the CSS custom properties its cells inherit (--table-border-outside-*, --table-border-inside-*). Cells fall back to these vars when they carry no border of their own.

Parameters:
NameTypeDefault
bordersTableBorders
showOutlineboolean
Returns:
CSSProperties

getBordersAndNodeType

The borders a border click would change, and the node type holding them:

  • whole table selected: the table’s;
  • inside a cell: the cell’s EFFECTIVE borders (getEffectiveCellBorders), since the cell writer wins over the block writer there;
  • partial range inside one block: the border MARK, which is what the click would write;
  • otherwise: the parent block’s.
Parameters:
NameTypeDefault
stateEditorState
Returns:
{ nodeType: string | undefined; borders: Borders | undefined; }

getEffectiveCellBorders

The borders a cell actually displays: its own attr per side, else the table’s outside border on the table boundary and inside border elsewhere. cellPos is table-relative, as in TableMap.

The toggle logic and borders menu need this, not the raw attr: a cell in a default-bordered table has borders: null yet draws four lines.

Parameters:
NameTypeDefault
tableNode
tableMapTableMap
cellPosnumber
formatCellFormat

The cell’s table-style format (getCellFormat): its sides hold the cell’s own, resolved against its neighbours’.

Returns:
Borders

parseBorderStyles

Parses border-<side> declarations out of a CSS string into a Borders attr. Accepts hex and rgb/rgba colors (pasted spans carry rgb); sides that don’t match are left absent.

Parameters:
NameTypeDefault
borderCSSValuestring
Returns:
Borders

returnAllBorderStyles

Every side of a Borders attr as CSS declarations, with an explicit border-<side>: none; for absent sides so nothing is inherited.

Parameters:
NameTypeDefault
bordersBorders
Returns:
string[]

returnAllBorderStylesObject

Every side of a Borders attr as a React style object.

Parameters:
NameTypeDefault
bordersBorders
showOutlineboolean
Returns:
CSSProperties

returnBorderClasses

Class names for a border-picker button, highlighting it when that side — or, for the all / outside composites, every side it covers — is active.

Parameters:
NameTypeDefault
border"none" | keyof SelectedBorders | "horizontalRule" | "inside"
currentBordersBorders
Returns:
string

returnBorderCSSValue

A border attr as the CSS shorthand VALUE it renders as (e.g. "1px solid #000000"), resolved like returnBorderStyles; an invisible border is the outline guide or "none".

Null when the attr is absent: the real cell border then cascades to a table-level var, which callers should fall back to as well. Used by the pagination cell view to copy a cell’s borders across page breaks.

Parameters:
NameTypeDefault
optionsMutable<Omit<IBorderOptions, "style"> & { style: BorderStyle; }>
showOutlineboolean
Returns:
string | null

returnBorderStyles

One side of a Borders attr as a CSS declaration (e.g. "border-top: 1px solid #000000;").

Parameters:
NameTypeDefault
positionBorderPosition
optionsMutable<Omit<IBorderOptions, "style"> & { style: BorderStyle; }>
showOutlineboolean

Render a none/transparent border as the dashed guide instead of omitting it.

Returns:
string

returnCellBorderStyles

A cell’s borders attr as CSS declarations for serialized HTML. Only the sides the cell sets are emitted: absent sides must keep cascading to the table-level --table-border-* vars, so no border-x: none filler. A side switched off carries its outline variable, so hosts showing the dashed guide get it on cells too.

Parameters:
NameTypeDefault
bordersCellBorders
Returns:
string[]

Canvas Gradient

CanvasGradient

NameTypeDefault
fromstring

Any CSS color; resolved to rgb() by the browser before it reaches here.

tostring
directionCanvasGradientDirection

canvasGradientCss

The CSS a themed gradient paints on the canvas.

Parameters:
NameTypeDefault
__0CanvasGradient
Returns:
string

CanvasVars

The theme’s canvas vars for one color scheme, already color-normalized.

NameTypeDefault
solidstring | null
fromstring | null
tostring | null
directionstring

colorAtFraction

Colour at fraction along the gradient, clamped to [0, 1] as CSS paints past the ends. Interpolates in sRGB like linear-gradient(from, to), so a gap’s slice matches the backdrop.

Parameters:
NameTypeDefault
fromRgb
toRgb
fractionnumber
Returns:
string

gapGradientCss

background for a gap rect inside a boxWidth × boxHeight gradient box that continues the backdrop seamlessly. All inputs share ONE space (visual px from the box’s top-left), unlike the clipped-copy approach this replaced; a stale rect costs a slightly-off shade, nothing more.

Emits an ANGLE, not the keyword: a corner keyword re-resolves against the box it’s painted on (on a wide flat gap, to bottom right runs nearly vertically). So the gap pins the backdrop’s resolved angle and samples colors at its own gradient-line endpoints (centre ± d·len/2, len = |w·sin α| + |h·cos α|). Both fields are linear along the same line, so every pixel matches.

Null when the colors can’t be parsed; callers fall back to the flat color.

Parameters:
NameTypeDefault
gradientCanvasGradient
rect{ x: number; y: number; width: number; height: number; }
boxWidthnumber
boxHeightnumber
Returns:
string | null

gradientAngleDeg

The CSS angle (degrees, clockwise from “to top”) that direction resolves to on a boxWidth × boxHeight box. Cardinal keywords are fixed; corner keywords depend on the aspect ratio — the gradient line runs perpendicular to the diagonal joining the two other corners, i.e. along (±height, ±width).

Parameters:
NameTypeDefault
directionCanvasGradientDirection
boxWidthnumber
boxHeightnumber
Returns:
number

gradientFractionAt

Progress along the gradient (0 at from, 1 at to) for point (x, y) in a width × height box, origin top-left. Points outside the box extrapolate past [0, 1]; colorAtFraction clamps, as CSS does.

For a corner keyword, CSS runs the gradient line perpendicular to the line joining the two OTHER corners (css-images-3 §3.1.1), so those corners sit at exactly 50% for any aspect ratio: the MEAN of the per-axis fractions, not a projection onto the diagonal, which only agrees on square boxes (verified in Chrome: bottom-left of a 1400×900 to bottom right black→white box paints 128; the diagonal projection predicts 100).

Parameters:
NameTypeDefault
directionCanvasGradientDirection
xnumber
ynumber
widthnumber
heightnumber
Returns:
number

isCanvasGradientDirection

Parameters:
NameTypeDefault
valuestring
Returns:
boolean

isDarkScheme

Whether el renders in the dark color scheme: a .dark ancestor wins, else the OS preference unless the root has .light. Must mirror index.css’s —stesura-canvas-surface rules, so the gradient never disagrees with its flat fallback.

Parameters:
NameTypeDefault
elElement
Returns:
boolean

parseColor

Parses rgb() / rgba() (what a computed style yields) or hex (read raw off an inline style). Anything else returns null, and the caller treats the gradient as unset; resolveColor in the DOM layer normalizes exotic formats through the browser first.

Parameters:
NameTypeDefault
valuestring
Returns:
Rgb | null

resolveCanvas

Resolves a theme’s canvas vars: a complete gradient wins, else the solid color, else nothing. Split from the DOM reader so the precedence is testable without a browser.

Parameters:
NameTypeDefault
__0CanvasVars
Returns:
ResolvedCanvas

ResolvedCanvas

What a theme resolves to for the active color scheme.

NameTypeDefault
gradientCanvasGradient | null

Set when both stops parsed and the direction is a valid keyword.

surfacestring | null

The canvas’s flat color: the solid color, or the gradient’s from stop. Null leaves the stylesheet default. Backs the gap underlay and sub-editor surfaces.

Rgb

NameTypeDefault
rnumber
gnumber
bnumber
anumber

Callout

CALLOUT_KINDS

The built-in kinds, in menu order, with the icon name the UI maps to an icon and the i18n key of their label (callout.kinds.<key>).

NameTypeDefault
warning{ icon: string; labelKey: BuiltInCalloutKind; }
note{ icon: string; labelKey: BuiltInCalloutKind; }
tip{ icon: string; labelKey: BuiltInCalloutKind; }
danger{ icon: string; labelKey: BuiltInCalloutKind; }
quote{ icon: string; labelKey: BuiltInCalloutKind; }

DEFAULT_CALLOUT_KIND

export const DEFAULT_CALLOUT_KIND: BuiltInCalloutKind = "note";

The kind a callout gets when none (or an invalid one) is given.

findSelectedCallout

The callout the selection is in (the innermost, for nested ones), or the selected callout itself.

Parameters:
NameTypeDefault
selectionSelection
Returns:
FoundCallout | null

FoundCallout

A callout and its position.

NameTypeDefault
nodeNode
posnumber
depthnumber

toCalloutKind

Coerces untrusted input (DOM, markdown, DOCX, collab JSON) to a kind: lowercased, [a-z][a-z0-9-]*, else the default.

Parameters:
NameTypeDefault
valueunknown
Returns:
CalloutKind

toCalloutTitle

Coerces untrusted input to a title: one trimmed line, capped, null when empty.

Parameters:
NameTypeDefault
valueunknown
Returns:
string | null

Code Block

isCodeBlockNode

Alias of isInCodeBlock, kept for the editor-react text menu; prefer isInCodeBlock.

Parameters:
NameTypeDefault
stateEditorState
Returns:
boolean

isInCodeBlock

Whether either end of the selection is inside a code block.

Parameters:
NameTypeDefault
stateEditorState
Returns:
boolean

toLanguage

Normalizes to a supported code language value; "" (with a warning) when unsupported.

Parameters:
NameTypeDefault
languagestring
Returns:
string

toTheme

Coerces a parsed value to a theme; anything but "light" is "dark".

Parameters:
NameTypeDefault
themestring
Returns:
"dark" | "light"

AI tools

The tool contract’s one helper (see AI tool contract).

defineAiTool

Ties execute’s input type to the schema and derives run, which validates raw model input through the schema’s Standard Schema validate and then executes. run does not catch: the dispatcher that calls it does, and logs.

A function with overloads, not an arrow: one name for both tool kinds, each keeping its own execute signature, without a cast.

Parameters:
NameTypeDefault
toolAiEditorTool<Input>
Returns:
DefinedAiEditorTool

Comments

Thread serialization helpers, for comment adapters (see Comments).

addReactionToComment

Returns a copy of comment with userId added to the emoji reaction group, creating the group if needed. Unchanged if the user already reacted.

Assumes a normalized blob — see normalizeSerializedThread.

Parameters:
NameTypeDefault
commentSerializedComment
emojistring
userIdstring
Returns:
SerializedComment

deserializeThread

Converts a persisted thread into a Thread. Never throws, whatever the input.

Parameters:
NameTypeDefault
rawSerializedThread
Returns:
Thread

normalizeSerializedThread

Drops malformed comments and reaction groups, keeping the persisted shape. Adapters must run it when reading a blob they are about to modify: the reaction helpers assume normalized input.

Parameters:
NameTypeDefault
threadSerializedThread
Returns:
SerializedThread

removeReactionFromComment

Returns a copy of comment without userId’s emoji reaction; emptied groups are dropped.

Assumes a normalized blob — see normalizeSerializedThread.

Parameters:
NameTypeDefault
commentSerializedComment
emojistring
userIdstring
Returns:
SerializedComment

AI comment suggestions

Comment changes an AI agent made (a new thread, a reply, a resolve) stay pending in the thread’s metadata until a person approves or rejects them.

AiCommentReviewAdapter

The comments-backend methods reviewing an agent’s comments needs: a structural subset of editor-react’s CommentAdapter.

NameTypeDefault
updateThreadMetadata(params: { threadId: string; update: (metadata: Record<string, unknown>) => Record<string, unknown>; }) => Promise<void>

Rewrites a thread’s metadata with update, applied to the backend’s latest copy: two changes to one thread in flight at once must both land.

deleteThread(threadId: string) => Promise<void>
deleteComment(params: { threadId: string; commentId: string; }) => void
unresolveThread(threadId: string) => Promise<void>

AiCommentSuggestionFilter

Which pending changes to resolve. Every given field must match.

NameTypeDefault
toolCallIdstring
authorIdstring
requestedByIdstring
threadIdstring
kindsreadonly ("thread" | "reply" | "resolve")[]
commentIdstring

findAiCommentSuggestions

Pending changes matching filter among live threads.

Parameters:
NameTypeDefault
threadsreadonly Thread[]
filterAiCommentSuggestionFilter
Returns:
{ thread: Thread; suggestion: AiCommentSuggestion; }[]

findThreadAnchorPos

Position of the first anchor of threadId: its opening boundary, or the node carrying it.

Parameters:
NameTypeDefault
docNode
threadIdstring
Returns:
number | null

getAiCommentSuggestions

The agent’s pending changes on thread. Metadata is any member’s to write, and a JS adapter may leave it out, so anything malformed reads as no suggestion.

Parameters:
NameTypeDefault
threadPick<Thread, "metadata">
Returns:
AiCommentSuggestion[]

resolveAiCommentSuggestions

Accepts (approve: the changes stay, the markers go) or rejects (reject: a created thread is deleted and its anchors removed in one undoable step, a reply deleted, a resolve reopened) the agent’s pending comment changes in threads that match filter. One thread failing doesn’t stop the others. Resolves to how many changes were resolved and how many failed.

Parameters:
NameTypeDefault
viewEditorView
adapterAiCommentReviewAdapter
threadsreadonly Thread[]
action"approve" | "reject"
filterAiCommentSuggestionFilter
Returns:
Promise<{ resolved: number; failed: number; }>

scrollToThreadAnchor

Selects the start of threadId’s anchor and scrolls to it. False when the thread has no anchor.

Parameters:
NameTypeDefault
viewEditorView
threadIdstring
Returns:
boolean

Config Plugin

getAllowedFileHosts

The mount’s allowedFileHosts (a ConfigPluginConfig field), or undefined when unset, which means no PDF previews at all (every PDF is a card).

Parameters:
NameTypeDefault
stateEditorState
Returns:
string[] | undefined

getToaster

The toast emitter for this mount. Emitters pass a ToastMessage key; the host’s onToast gets it with description localized (resolver installed by editor-react; a bare-core mount falls back to the key).

Without onToast the mount is warned ONCE, since the refusals that raise toasts can fire on every keystroke.

Parameters:
NameTypeDefault
stateEditorState
Returns:
(message: ToastMessage) => void

isPrintMount

Whether this mount renders for the PDF export rather than the screen, so screen-only chrome (handles, hover affordances, floating menus) can stay out of the capture.

Reads the printMount config (see ConfigPluginConfig), known from the first render. Pass the state when there is one: without it, or for states built without the flag (e.g. a sub-editor’s), it falls back to the data-stesura-print stamp ExportController puts on the root, which only exists once the export page has mounted.

Parameters:
NameTypeDefault
stateEditorState
Returns:
boolean

Cross-References

toCrossRefType

Coerces a parsed value to a CrossRefType; unknown values become "default".

Parameters:
NameTypeDefault
typestring
Returns:
CrossRefType

getClauseLabels

Every numbered block’s clause label by block id, derived from its number: { own: "(a)", tokens: ["5", "2", "a"], label: "5.2(a)" }. Bullets, empty levels and blocks pending deletion have none. Computed from the numbering store and memoized per document.

Parameters:
NameTypeDefault
stateEditorState
Returns:
ReadonlyMap<string, ClauseLabel>

paragraphNumberText

A paragraph number as a cross-reference shows it: without trailing full stops, as Word’s REF field shows it under its paragraph-number switches (“17.3.” reads “17.3”). Other punctuation stays: “(a)”, “1)”.

Parameters:
NameTypeDefault
textstring
Returns:
string

tokenizeReference

A reference’s numbering tokens, outermost first and folded, and its other words: “paragraph (b) of clause 5.2” → tokens 5, 2, b. Compare the tokens with a ClauseLabel’s tokens (the full path) or with tokenizeReference(label) (as cited).

Parameters:
NameTypeDefault
textstring
Returns:
{ tokens: string[]; words: string[]; }

foldReference

Accents folded, lower case: how references and labels are compared.

Parameters:
NameTypeDefault
textstring
Returns:
string

Document initialisation

compactDocJson

On a style-heavy DOCX import the compacted JSON is typically 2–3× smaller.

import { compactDocJson } from "@stesura/core/helpers"; const contentJson = JSON.stringify(compactDocJson(doc.toJSON(), schema));

See DOCX Import & Export → Persisting the imported document for the full pipeline.

Shrinks ProseMirror JSON by dropping every node/mark attr equal to its schema default. No DOM or EditorState, so it is safe on the server; live-doc callers pass doc.toJSON(). Use it before persisting or sending a doc: a style-heavy import writes ~12 mostly-default attrs on every textStyle mark.

Lossless: fromJSON fills absent keys with the spec default, so the result parses to a doc .eq() to the original. Attrs without a declared default, and attrs the schema does not declare, are kept.

One observable difference from expanded JSON: a compacted doc adopts future changes to a spec default instead of freezing today’s value.

Returns the input object when nothing was dropped.

Parameters:
NameTypeDefault
jsonJSONContent
schemaSchema<any, any>
Returns:
JSONContent

createDocContent

Builds a document from simple blocks without touching the DOM, so it is safe in server code — where HTML initialContent cannot be parsed (see createInitialDoc). For rich templates, seed from a published snapshot’s JSON instead of building blocks by hand.

Parameters:
NameTypeDefault
schemaSchema<any, any>
blocksDocContentBlock[]
Returns:
Node

createInitialDoc

The editor’s starting doc: initialContent converted to the schema, or a single empty section when absent. Throws on HTML content outside the browser.

Parameters:
NameTypeDefault
schemaSchema<any, any>
initialContentstring | Node | JSONContent | Fragment | JSONContent[]
Returns:
Node

DocContentBlock

NameTypeDefault
type"paragraph" | "heading"
textstring | DocContentRun[]

DocContentRun

A text run; marks are schema mark names (e.g. "strong", "em") with default attrs.

NameTypeDefault
textstring
marksstring[]

normalizeDocJsonIds

Fills missing node ids and regenerates duplicates in ProseMirror JSON. No DOM or EditorState, so it is safe on the server.

Run it before persisting seeded docs (e.g. createRoomDoc initialContent) so clients never mount an id-less doc and race each other to heal it.

Duplicate section ids are regenerated like any other, after the first occurrence: nothing is cached yet, and two sections sharing an id share every pagination store keyed by it. Each one is reported through onDuplicateSectionId, since only a bug upstream produces one.

Returns the input object when nothing changed.

Parameters:
NameTypeDefault
jsonJSONContent
schemaSchema<any, any>
onDuplicateSectionId(id: string) => void
Returns:
JSONContent

Formatting

formattingAttrsToCss

Indentation attrs as CSS declarations, for the stylesheet’s generated rules (the non-numbered geometry — formattingIndentDeclarations).

Parameters:
NameTypeDefault
formattingIndentAttrs
Returns:
string[]

getDocumentDirection

The document’s default direction, never null: the bottom of the direction chain, and what a host sets for an RTL-by-default editor.

Parameters:
NameTypeDefault
docNode
Returns:
TextDirection

getInheritedDirection

The direction the block at $pos INHERITS (its own dir ignored): the nearest ancestor declaring one, else the document default. Walks ancestors rather than finding the section so it works in sub-editors, whose wrapper (a section clone) is seeded with the owning section’s direction.

Parameters:
NameTypeDefault
$posResolvedPos
Returns:
TextDirection

getNodeAndStyleSheet

The formatted node at the selection together with its resolved style definition.

Parameters:
NameTypeDefault
stateEditorState
Returns:
{ node?: never; style?: never; } | { node: Node | undefined; style: StyleDefinition | undefined; }

getNodeFormattingFromNode

getNodeFormattingFromSelection for a node you already hold.

Parameters:
NameTypeDefault
nodeNode
stateEditorState
Returns:
NodeFormatting

getNodeFormattingFromSelection

The effective indent, spacing, lineHeight and textAlign of the formatted node at the cursor: node attr, then (indent only) the numbering- derived tier, then the style; lineHeight finally falls back to the default.

Parameters:
NameTypeDefault
stateEditorState
Returns:
NodeFormatting

getResolvedDirection

The effective text direction of a block: its own dir, else what it inherits at the selection (see getInheritedDirection).

Parameters:
NameTypeDefault
nodeNode
stateEditorState
Returns:
TextDirection

getSectionDirection

A section’s effective direction: its own dir, else the document default. Takes attrs rather than a node so a sub-editor’s wrapper attrs qualify too.

Parameters:
NameTypeDefault
sectionAttrsAttrs
docNode
Returns:
TextDirection

isTextDirection

Allowlist guard: dir is raw on the JSON/collab path, like textAlign.

Parameters:
NameTypeDefault
valueunknown
Returns:
boolean

parseLineHeight

Parses a line height to a multiplier, clamped to its range but not snapped to LINE_HEIGHTS (Word values like 1.08 survive a copy/paste). Null for an absent value (“inherit from the stylesheet”), the app default for an uninterpretable one.

An “Xpt” height passes through untouched: it is the attr’s other legal shape (DOCX exact/atLeast spacing), and snapping it would lose the fixed line box on every DOM round-trip.

Parameters:
NameTypeDefault
lineHeightstring | number
Returns:
string | number | null

parseSpecial

Coerces a parsed value to IndentationSpecials; unknown values become "none".

Parameters:
NameTypeDefault
specialstring
Returns:
IndentationSpecials

returnFormattingStyles

Indentation attrs as an inline CSS string (leading ;, for appending).

Numbering changes the result: the counter occupies the first-line indent, and followBy (tab, space or nothing) decides how the text after it lines up. --tabStop is emitted only when set, so it overrides the level config and the editor default through the CSS var cascade.

Parameters:
NameTypeDefault
optionsIndentAttrs
isNumberedboolean
followBy"tab" | "space" | "nothing"
tabStopnumber
Returns:
string

spacingAttrsToCss

Spacing attrs as the --spacing-before / --spacing-after CSS declarations.

Parameters:
NameTypeDefault
spacingSpacingAttrs
Returns:
string[]

spacingAttrsToReactStyle

spacingAttrsToCss as a React style object.

Parameters:
NameTypeDefault
spacingSpacingAttrs
Returns:
CSSProperties

spacingToDom

The style and data-* attributes a spaced node’s toDOM emits: the collapsed margins and paddings the spacing store computes (derived, by default the render context’s), plus the raw spacing values so a serialized document round-trips.

Parameters:
NameTypeDefault
nodeNode
derivedSpacingEntry
Returns:
{ style: string; "data-spacing-before": number | null; "data-spacing-after": number | null; "data-spacing-contextual": string | null; "data-margin-top": number | null; "data-padding-top": number | null; "data-padding-bottom": number | null; }

detectExistingVariants

Which non-default variants exist as header_footer_content nodes in the section’s header or footer (true if either has it).

Parameters:
NameTypeDefault
stateEditorState
sectionIdstring
Returns:
VariantPresence

findHeaderFooterContentInFragment

The header_footer_content node of variant at section > section_header|section_footer in fragment, e.g. a full-doc replace step’s slice. Sections must be top-level children of fragment.

Parameters:
NameTypeDefault
fragmentFragment
sectionIdstring
target"header" | "footer"
variantstring
Returns:
Node | null

findHeaderFooterContentPos

The header_footer_content node (and its position) for a section, target and variant in the main doc. Its position is the sub-editor’s step-mapping offset.

Parameters:
NameTypeDefault
stateEditorState
sectionIdstring
target"header" | "footer"
variantHeaderFooterVariant
Returns:
{ node: Node; pos: number; } | undefined

getHeaderFooterContent

Content of the header_footer_content node for a section, target and variant.

Parameters:
NameTypeDefault
stateEditorState
sectionIdstring
target"header" | "footer"
variantHeaderFooterVariant
Returns:
Fragment | undefined

Highlight

getHighlightPluginState

The highlighter plugin’s state — notably the armed color, if any.

Parameters:
NameTypeDefault
stateEditorState
Returns:
HighlightPluginState | undefined

isHighlightColor

Check if a background-color value is a highlight color

Parameters:
NameTypeDefault
valuestring
Returns:
boolean

Math

isMathNodeType

math_inline or math_display.

Parameters:
NameTypeDefault
typeNodeType
Returns:
boolean

marksToMathMarks

The storable form of a mark set, minus null and default-valued attrs (create fills them back in). Scalar comparison is enough: the only non-scalar attr (off) defaults to null.

Parameters:
NameTypeDefault
marksreadonly Mark[]
Returns:
MathMarkJSON[]

mathNodeMarks

An equation’s styling, hydrated from its mathMarks attr.

Parameters:
NameTypeDefault
nodeNode
Returns:
Mark[]

mathNodeStyle

The CSS (colour, size, background) an equation’s stored marks resolve to. For the React nodeview, which owns the math DOM and so bypasses toDOM.

Parameters:
NameTypeDefault
nodeNode
Returns:
MathStyle

selectedMathNode

The selected node, when the selection is exactly one math node.

Parameters:
NameTypeDefault
stateEditorState
Returns:
Node | null

Files

effectiveRotation

The angle a page is drawn at: the file node’s rotation ADDED to the page’s own. react-pdf’s Page.rotate and pdf-lib’s setRotation REPLACE the native angle, so preview and export both add it back through this one formula.

Parameters:
NameTypeDefault
nativeDegreesnumber
attrFileRotation
Returns:
FileRotation

fileDisplayName

The name shown for a file: the uploaded filename, else the URL’s last segment.

Parameters:
NameTypeDefault
attrsPick<FileAttrs, "name" | "src">
Returns:
string | null

fileKind

The behaviour class of a file node. pdf is the only kind with page semantics (previewable; under pagination it sits on the canvas between two pages; spliced into the PDF export). A null mimeType means the node predates the attr, and only PDFs could be uploaded then.

Parameters:
NameTypeDefault
attrsPick<FileAttrs, "mimeType">
Returns:
FileKind

isPdfFileNode

Parameters:
NameTypeDefault
nodeNode
Returns:
boolean

isPdfPreview

Whether a PDF file node is PREVIEWED on this mount: the one decision the node view, the pagination engine and the PDF export must agree on. All three read the same store entry, so a mount without the viewer package is a card everywhere.

Five conditions, all required:

  • the node is a PDF (fileKind);
  • the author left displayPreview on;
  • @stesura/pdf-viewer-react is mounted (ready);
  • the mount CONFIGURED allowedFileHosts — the renderer fetches the file from the viewer’s browser, so the integrator has to have named the hosts they trust to serve nothing but PDFs (SEC-70);
  • the src passes that allowlist and the never-allow class.
Parameters:
NameTypeDefault
nodeNode
configPdfPreviewConfig
Returns:
boolean

toFileRotation

Coerce anything (a parsed data-rotation, an API caller’s number) to one of the four storable angles. Out-of-range multiples of 90 wrap; everything else falls back to 0 rather than storing an angle the export cannot reproduce.

Parameters:
NameTypeDefault
valueunknown
Returns:
FileRotation

Floating objects

The floating attribute family: normalizers, defaults and the side a float sits on.

DEFAULT_FLOAT_POSITION

New objects sit at the right edge of their column, from the top of their paragraph.

NameTypeDefault
h{ relativeTo: FloatHorizontalRelativeTo; align: FloatHorizontalAlign | null; offset: number; }
v{ relativeTo: FloatVerticalRelativeTo; align: FloatVerticalAlign | null; offset: number; }

FLOAT_DISTANCE_MAX

export const FLOAT_DISTANCE_MAX = 1000;

Wrap gap per side, px.

FLOAT_OFFSET_MAX

export const FLOAT_OFFSET_MAX = 10_000;

Position offsets, px: a page and then some, either way.

FLOAT_Z_INDEX_MAX

export const FLOAT_Z_INDEX_MAX = 0xffffffff;

Word’s relativeHeight is an unsigned 32-bit value.

defaultFloatDistance

Word’s default gap for a wrap mode, px: ⅛” either side of a float, none above and below.

Parameters:
NameTypeDefault
wrapFloatWrap
Returns:
FloatDistance

floatDistanceOf

The gap actually used: the stored one, else the mode’s default.

Parameters:
NameTypeDefault
wrapFloatWrap
distanceFloatDistance
Returns:
FloatDistance

floatDistanceSides

The gaps a wrap mode lets the user set, as Word’s Layout dialog enables them: all four for square, left and right for tight (its top and bottom follow the contour), top and bottom for top and bottom, none where no text wraps (inline, front, behind).

Parameters:
NameTypeDefault
wrapFloatWrap
Returns:
readonly (keyof FloatDistance)[]

floatPositionForSide

The position that puts a float on side, keeping the vertical axis.

Parameters:
NameTypeDefault
positionFloatPosition
sideFloatSide
Returns:
FloatPosition

floatRole

The DOM role pagination and the column layout key on (data-float): a float band, an out-of-flow layer, or an inline box.

Parameters:
NameTypeDefault
wrapFloatWrap
Returns:
"inline" | "band" | "layer"

floatSideOf

Which side a float sits on: its horizontal alignment, else the column half its middle falls in (columnWidth and width known), else right.

Parameters:
NameTypeDefault
positionFloatPosition
widthnumber
columnWidthnumber
Returns:
FloatSide

isFloatBandNode

A child that floats beside the text, so its textblock must contain it.

Parameters:
NameTypeDefault
nodeNode
Returns:
boolean

isFloatBandWrap

Floated beside the text: the object and the lines next to it paginate as one band.

Parameters:
NameTypeDefault
wrapunknown
Returns:
boolean

isFloatingNode

Carries the floating family.

Parameters:
NameTypeDefault
nodeNode
Returns:
boolean

isFloatLayerWrap

Out of flow, in front of or behind the text.

Parameters:
NameTypeDefault
wrapunknown
Returns:
boolean

sameFloatDistance

Parameters:
NameTypeDefault
aFloatDistance
bFloatDistance
Returns:
boolean

sameFloatPosition

Structural equality, so normalizers can hand back the same object when nothing changed.

Parameters:
NameTypeDefault
aFloatPosition
bFloatPosition
Returns:
boolean

toFloatDistance

Wrap distances from untrusted data, or null when absent or malformed.

Parameters:
NameTypeDefault
rawunknown
Returns:
FloatDistance | null

toFloatPosition

A position from untrusted data; invalid parts fall back to the default’s.

Parameters:
NameTypeDefault
rawunknown
Returns:
FloatPosition

toFloatWrap

A wrap value from untrusted data; unknown values become “inline”.

Parameters:
NameTypeDefault
rawunknown
Returns:
FloatWrap

toFloatZIndex

A stacking order from untrusted data, or null.

Parameters:
NameTypeDefault
rawunknown
Returns:
number | null

Text boxes

The floating_box node’s own attrs: defaults, bounds, normalizers and its inline layout style.

DEFAULT_FLOATING_BOX_BORDER

A box’s outline; width in px.

NameTypeDefault
widthnumber
colorstring
styleFloatingBoxBorderStyle

DEFAULT_FLOATING_BOX_PADDING

Word’s default text box insets: 0.1” left and right, 0.05” top and bottom.

NameTypeDefault
topnumber
bottomnumber
leftnumber

DEFAULT_FLOATING_BOX_WIDTH

export const DEFAULT_FLOATING_BOX_WIDTH = 240;

FLOATING_BOX_BORDER_MAX

export const FLOATING_BOX_BORDER_MAX = 100;

FLOATING_BOX_BORDER_MIN

export const FLOATING_BOX_BORDER_MIN = 0.25;

Border width bounds, px.

FLOATING_BOX_DIM_MAX

export const FLOATING_BOX_DIM_MAX = 5000;

FLOATING_BOX_DIM_MIN

export const FLOATING_BOX_DIM_MIN = 1;

Box width/height bounds, px.

FLOATING_BOX_LABEL_MAX

export const FLOATING_BOX_LABEL_MAX = 500;

An accessible name, not a paragraph.

FLOATING_BOX_PADDING_MAX

export const FLOATING_BOX_PADDING_MAX = 1000;

Padding per side, px.

floatingBoxStyle

The box’s layout as inline CSS: size, padding, border width and style. The shadow measurer clones DOM, so these cannot live in a stylesheet. Colors go through custom properties that floating-box.css reads.

Parameters:
NameTypeDefault
attrsFloatingBoxOwnAttrs
Returns:
string

isFloatingBoxNode

Parameters:
NameTypeDefault
nodeNode
Returns:
boolean

toFloatingBoxAttrs

Every own attr through its coercer: the shape parseDOM and the commands hand the node.

Parameters:
NameTypeDefault
rawRecord<string, unknown>
Returns:
FloatingBoxOwnAttrs

toFloatingBoxBorder

An outline from untrusted data: the default when absent, null for none. An unusable color falls back to the default’s.

Parameters:
NameTypeDefault
rawunknown
Returns:
FloatingBoxBorder | null

toFloatingBoxFill

Parameters:
NameTypeDefault
rawunknown
Returns:
string | null

toFloatingBoxHeight

A fixed height, or null (grows with the content) when absent or malformed.

Parameters:
NameTypeDefault
rawunknown
Returns:
number | null

toFloatingBoxHeightRule

Parameters:
NameTypeDefault
rawunknown
Returns:
FloatingBoxHeightRule

toFloatingBoxLabel

One trimmed line, capped; null when empty.

Parameters:
NameTypeDefault
rawunknown
Returns:
string | null

toFloatingBoxOrigin

Parameters:
NameTypeDefault
rawunknown
Returns:
FloatingBoxOrigin

toFloatingBoxPadding

Padding from untrusted data; Word’s insets when absent or malformed.

Parameters:
NameTypeDefault
rawunknown
Returns:
FloatingBoxPadding

toFloatingBoxWidth

Parameters:
NameTypeDefault
rawunknown
Returns:
number

Images

dataURIToFile

Turns a data URI into a File, for handing pasted image data to the uploader. Handles both base64 and URL-encoded (RFC 2397) payloads; returns null for malformed input instead of throwing (CORE-97).

Parameters:
NameTypeDefault
dataURIstring
namestring
Returns:
File | null

getImageWrap

Coerces a parsed value to an ImageWrap; anything but "square" is "top-bottom".

Parameters:
NameTypeDefault
wrapstring
Returns:
ImageWrap

imageAltFromDom

Reads the three-state alt back off an <img>. Uses the raw attribute: img.alt returns "" for a MISSING one, turning undeclared into decorative.

Parameters:
NameTypeDefault
imgElement
Returns:
ImageAltState

imageAltToDom

The alt attribute for the three-state alt model:

  • decorative → alt="" (assistive tech skips it)
  • meaningful → the text
  • undeclared → null, i.e. no attribute, so automated checks flag it instead of reading it as decorative.

toDOM skips null attrs; React call sites map it to undefined.

Parameters:
NameTypeDefault
stateImageAltState
Returns:
string | null

imageCropLayout

Where the full bitmap sits inside a cropped picture’s box: its size and its (negative) offset, so a clipping box of width×height shows exactly the uncropped part. Null when nothing is cropped.

Parameters:
NameTypeDefault
widthnumber
heightnumber
cropImageCrop
Returns:
{ imgWidth: number; imgHeight: number; offsetLeft: number; offsetTop: number; } | null

imageTransformCss

A picture’s rotation and mirroring as a CSS transform — mirroring first, as in Word.

Parameters:
NameTypeDefault
transformImageTransform
Returns:
string | undefined

ImageUploadReturn

NameTypeDefault
urlstring
altstring

rotatedBounds

The box a width×height picture turned by rotation degrees occupies, from its uppermost corner to its lowermost and leftmost to rightmost. What the page reserves for it: pagination measures it, and DOCX’s wp:effectExtent is the overhang past the unturned size.

Parameters:
NameTypeDefault
widthnumber
heightnumber
rotationnumber
Returns:
{ width: number; height: number; }

sanitizeImageSrc

A safe image src, or null. RASTER data: URIs pass (the default upload strategy stores them); everything else goes through safeNormalizeUrl, so javascript: and friends never reach the doc or get loaded for measurement. The scheme is kept: upload storage may be plain http.

data:image/svg+xml is excluded, as in the markdown parser (SEC-2) and the upload sniffer (SEC-9): SVG can carry scripts, inert in <img>, but a stored attr must not depend on where it is later rendered.

Parameters:
NameTypeDefault
srcstring
Returns:
string | null

setImageUploadStrategy

Installs the app’s image uploader (pass null to uninstall). Without one, images are stored inline as data URIs — fine for local-only documents, not for docs that sync or persist (see imageUploadPolicy for the guard).

Parameters:
NameTypeDefault
strategyImageUploadStrategy
Returns:
void

startImageUpload

Inserts a placeholder at pos (or replacing the selection), uploads the file or loads the URL, then swaps in an image node sized to fit the section. The placeholder is removed on failure; srcs are sanitized before reaching the doc. A file is refused up front when the mount disallows inline images and no upload strategy is installed.

Parameters:
NameTypeDefault
viewEditorView
fileOrUrlstring | File
altstring
schemaSchema<any, any>
posnumber
Returns:
void

toImageAlign

Coerces a parsed value (left/right accepted) to an ImageAlign; unknown values become "center".

Parameters:
NameTypeDefault
alignstring
Returns:
ImageAlign

toImageCrop

A crop from untrusted data (a pasted data-crop, a collab step), or null: each edge a percent, and something left visible on both axes.

Parameters:
NameTypeDefault
rawunknown
Returns:
ImageCrop | null

toImageTransform

A transform from untrusted data, or null when it turns nothing.

Parameters:
NameTypeDefault
rawunknown
Returns:
ImageTransform | null

uploadImageFile

An image file’s src, stored as image insertion stores it (the upload strategy, else inline), for srcs that aren’t an image node’s: a picture watermark. Null when the file isn’t an image the policy accepts, the mount refuses inline images without a strategy, or the resulting src isn’t safe.

Parameters:
NameTypeDefault
stateEditorState
fileFile
Returns:
Promise<string | null>

Sanitized DOM

Headers, footers and the cross-reference preview paint toDOM output outside the editor, through DOMPurify. A security extension point: register the non-standard tags and attributes your schema extensions need there, once at startup (see Extending the schema).

extendSerializedDomAllowlist

Lets host schema extensions keep non-standard tags/attributes on the sanitized surfaces. Additive only: the forbidden tags, event handlers and srcdoc/formaction cannot be registered, and invalid names are ignored.

Parameters:
NameTypeDefault
__0{ tags?: string[]; attrs?: string[]; }
Returns:
void

Tab Stops

computeTabWidths

Each tab’s width, Word’s way: a tab advances to the first stop past where it starts (custom stops, then the default interval past the last one), and the text after it aligns against that stop. A hanging indent’s text position is an implicit stop, which lines up “1.1⇥Text”.

A stop past lineEnd (the text area’s end edge) acts as if it were on it, so the tab never wraps. A wrapped tab was measured on the next line, which changed its width, which unwrapped it: a measure loop that never settled.

Parameters:
NameTypeDefault
__0{ tabs: MeasuredTab[]; stops: TabStop[] | null; defaultInterval?: number; hangingStop?: number | null; lineEnd?: number | null; }
Returns:
TabLayout[]

hangingTabStop

The implicit stop a hanging indent sets: its text position, px from the start edge.

Parameters:
NameTypeDefault
indentIndentAttrs
Returns:
number | null

MeasuredTab

One tab of a line, as measured: the text after it up to the next tab.

NameTypeDefault
startnumber

Where the tab begins, px from the text area’s start edge, when measured: the first tab of a line, or one after text that wrapped. Absent, it begins where the previous tab’s text ends.

followingnumber

Width of the text after this tab, up to the next tab or the line’s end.

beforeDecimalnumber

Width of that text up to its first ”.”, for a decimal stop.

parseTabStops

A tabStops value from untrusted data (pasted HTML, a stored document) as valid stops sorted by position; invalid entries are dropped. An empty input stays [] (“no stops”, overriding the style’s); null means inherit.

Parameters:
NameTypeDefault
valueunknown
Returns:
TabStop[] | null

resolveTabStops

A block’s tab stops: its own, else its paragraph style’s. Whole-list override, like Word’s resolved set.

Parameters:
NameTypeDefault
nodeNode
styleSheetStyleSheet
Returns:
TabStop[] | null

TabLayout

A laid-out tab: its width and the leader that fills it.

NameTypeDefault
widthnumber
leaderTabStopLeader

Invisible Characters

isShowingInvisibleCharacters

Whether the pilcrow / space / tab markers are currently shown.

Parameters:
NameTypeDefault
stateEditorState
Returns:
boolean

Language

getDocumentLanguage

The document default, guaranteed to be a value rather than null.

Parameters:
NameTypeDefault
docNode
Returns:
string

getLanguageFromSelection

The effective proofing language of the current selection, or undefined when the selection spans several. See getSelectionLanguage for the explicit-vs-inherited flag.

Parameters:
NameTypeDefault
stateEditorState
Returns:
string | undefined

getSelectionLanguage

The EFFECTIVE proofing language of the selection’s proofread blocks, plus whether it is explicit or inherited. Resolved per block before the mixed check, so an inherited-French and an explicit-French paragraph read as French.

Parameters:
NameTypeDefault
stateEditorState
Returns:
SelectionLanguage

getStyleLanguage

The language a paragraph style supplies (the middle level of the chain), or null when it states none. Unknown ids fall back to Normal, as in the CSS: a block with a dangling style renders, and so proofs, as Normal.

Pass the RESOLVED sheet (getResolvedStyleSheet or getResolvedStyleSheetFromDoc) so basedOn is already applied.

Parameters:
NameTypeDefault
styleSheetStyleSheet
styleSheetIdstring
Returns:
string | null

resolveBlockLanguage

The effective language of one proofread block: proofingLanguage ?? style.language ?? doc.language. Walking consumers resolve the sheet once and call this per block.

Parameters:
NameTypeDefault
nodeNode
styleSheetStyleSheet
documentLanguagestring
Returns:
string

resolveLanguageAtPos

The effective language at pos, resolved via the nearest proofread ancestor (or the block right after pos); the doc language when there is none.

Parameters:
NameTypeDefault
stateEditorState
posnumber
Returns:
string

SelectionLanguage

What the selection’s proofread blocks resolve to, and whether they say so.

NameTypeDefault
languagestring | undefined

The effective language, or undefined when the selection mixes several.

isExplicitboolean

true only when every block in the selection carries an explicit proofingLanguage. Inherited selections show the resolved language but let the UI mark it as following the style/document.

toLangTag

Normalizes a proofing language or UI locale to a BCP 47 tag for the DOM lang attribute (screen readers switch voice on it). Values come from DOCX, pasted HTML and host config, so malformed ones return null: no lang beats a junk one that makes a reader announce in the wrong voice.

Parameters:
NameTypeDefault
valuestring
Returns:
string | null

Numbering

buildTabStopCss

CSS for the per-level config tabStops, one rule per level that sets one, keyed on the paragraph’s numbering data attributes. It beats the inherited editor-root default and loses to the paragraph’s inline var. Deliberately not editor-scoped: pagination measurement clones live under document.body.

Parameters:
NameTypeDefault
listConfigsRecord<string, ILevelsOptions[]>
Returns:
string

createListFormatOptions

Every list format option for a language and grammatical gender. lang is a free-form proofingLanguage, normalised to a supported locale first; memoized per locale + gender.

Parameters:
NameTypeDefault
langstring
genderNumberGender
Returns:
readonly ListFormatOption[]

createPickableListFormatOptions

The formats the level-format picker offers — the eight the editor has always had. Everything else in createListFormatOptions is render-only.

Parameters:
NameTypeDefault
langstring
genderNumberGender
Returns:
readonly ListFormatOption[]

findNextNumberedNode

findNextNumberedBlock’s numbering attr.

Parameters:
NameTypeDefault
docNode
currentPosnumber
Returns:
NumberingAttrs | undefined

findPreviousNumberedNode

findPreviousNumberedBlock’s numbering attr.

Parameters:
NameTypeDefault
docNode
currentPosnumber
Returns:
NumberingAttrs | undefined

getDocListConfigs

The list configs stored ON THE DOCUMENT (the layer getListConfigs spreads over the defaults, shadowing entries included). What the save/remove commands edit. A null-prototype copy, for the same reason as getListConfigs.

Parameters:
NameTypeDefault
stateEditorState
Returns:
Record<string, ILevelsOptions[]>

getEffectiveNumbering

resolveEffectiveNumbering against the editor’s resolved stylesheet.

Parameters:
NameTypeDefault
stateEditorState
nodeNode
Returns:
EffectiveNumbering | null

getEffectiveNumberingAtSelection

The effective numbering of the numbered textblock at the selection’s $from.

Parameters:
NameTypeDefault
stateEditorState
Returns:
EffectiveNumbering | null

getEffectiveNumberingAtSelectionAnchor

Like getEffectiveNumberingAtSelection, but at $anchor rather than $from.

Parameters:
NameTypeDefault
stateEditorState
Returns:
EffectiveNumbering | null

getFormatOptionLabel

The dropdown label for a list format option: its first three rendered values — “1, 2, 3, …” / “I, II, III, …”. Falls back to the option’s static label when it has no transform.

Parameters:
NameTypeDefault
optionListFormatOption
Returns:
string

getFormatPreviewLabel

Preview of a single format at number: only %1 is substituted, e.g. { text: "%1.", format: "decimal" } at 1 is "1.".

Parameters:
NameTypeDefault
__0{ format: LevelFormat; number: number; lang?: string; }
Returns:
string

getLevelPreviewLabel

Preview of a level’s text, rendering each %N token with its own level’s config (at 1, unless count says otherwise).

Parameters:
NameTypeDefault
__0{ text?: string; levels: ILevelsOptions[]; lang?: string; count?: { level: number; number: number; }; }
Returns:
string

getListConfig

The level configs of listRef, built-ins included.

Parameters:
NameTypeDefault
stateEditorState
listRefstring
Returns:
ILevelsOptions[] | undefined

getListConfigCustom

The list configs under refs the document owns (the library’s “in this document” half). Entries SHADOWING a built-in are excluded: they belong under their default name.

Parameters:
NameTypeDefault
stateEditorState
Returns:
Record<string, ILevelsOptions[]>

getListConfigs

Every list config: the built-in defaults with the doc’s own configs on top.

Parameters:
NameTypeDefault
stateEditorState
Returns:
Record<string, ILevelsOptions[]>

getNumberingAttrsAtSelectionAnchor

The numbering attributes of the numbered block containing the selection anchor.

Parameters:
NameTypeDefault
stateEditorState
Returns:
NumberingAttrs | undefined

getStyleForListLevel

The style bound to (listRef, level), if any.

Parameters:
NameTypeDefault
resolvedSheetStyleSheet
listRefstring
levelnumber
Returns:
string | undefined

getStyleNumbering

The numbering binding a style carries, from a RESOLVED stylesheet (basedOn already merged). Returns null for unnumbered styles, unknown ids, and styles that explicitly reset numbering to null.

Parameters:
NameTypeDefault
resolvedSheetStyleSheet
styleIdstring
Returns:
StyleNumbering | null

getStyleNumberingBinding

Memoized against the resolved-sheet object identity.

Parameters:
NameTypeDefault
resolvedSheetStyleSheet
Returns:
StyleNumberingBinding

indentsAreEqual

Field-wise indent compare, absent === zero/none: a level stating nothing renders like one stating the defaults, and telling them apart would fork a config on every no-op edit.

Parameters:
NameTypeDefault
aIndentAttrs
bIndentAttrs
Returns:
boolean

isInheritedListRef

Whether a numbering attr value defers its list to the paragraph’s style.

Parameters:
NameTypeDefault
listRefunknown
Returns:
boolean

listLevelsAreEqual

Compares two level lists field-wise, matching entries by level (configs may be sparse, so positional comparison would call [1,3] and [1,2] equal). False when either is undefined.

Parameters:
NameTypeDefault
levelsILevelsOptions[]
otherLevelsILevelsOptions[]
Returns:
boolean

localeHasNumberGenderVariants

Whether picking a gender would change anything for a document written in lang — most languages inflect numbers in one gender only. Takes a raw proofingLanguage; resolution to a supported locale happens here.

Parameters:
NameTypeDefault
langstring
Returns:
boolean

nodeIsInInstance

Whether node belongs to the given list stream. The instance match is a deliberate WILDCARD when either side is falsy:

  • no instanceId (caller): every node of the listRef. Style streams are addressed this way, having no single instance to name.
  • no node instance id: an unstamped node (imported, hand-authored) joins its ref’s stream and still renders as part of the list.

Hence a caller holding a real instanceId cannot exclude unstamped nodes; callers that need that (restartNumbering) compare ids directly.

Parameters:
NameTypeDefault
nodeNode
listRefstring
instanceIdstring
entriesDerivedEntries<NumberingEntry>
Returns:
boolean

nodeIsNumbered

Whether attrs (full node attrs or the numbering attrs alone) carry a listRef.

The ATTR-level answer, not the effective one: true for INHERIT_LIST_REF, false for the off-sentinel and for a null attr, so a style-numbered paragraph reads as unnumbered until the plugin stamps it. Rendering and export must use resolveEffectiveNumbering.

Parameters:
NameTypeDefault
attrsAttrs
Returns:
boolean

numberingListRef

The real listConfigs key behind a numbering attr: the list the style cascade resolved (the numbering store’s) when the attr defers to the style, the attr’s own listRef otherwise.

Parameters:
NameTypeDefault
numberingNumberingAttrs
resolvedResolvedNumbering
Returns:
string | null | undefined

renderLevelNumber

One %N substitution, per Word semantics. Never returns the raw token: an echoed %1 in the running text is the one outcome that is always wrong.

  • none (and bullet) → "". The placeholder is nothing; literal characters in lvlText still render around it.
  • a level the config doesn’t define, or one past this path’s depth → "".
  • a format outside the table → the decimal transform, which is ST_NumberFormat’s own fallback for formats a consumer can’t render.
Parameters:
NameTypeDefault
levelConfigPick<ILevelsOptions, "format" | "gender" | "casing">
valuenumber
langstring
Returns:
string

resolveEffectiveNumbering

Resolves a textblock’s numbering through the style cascade; the only place the four attr states are interpreted. A real listRef wins; INHERIT_LIST_REF takes the style’s list with the attr’s overrides on top; the off-sentinel (no listRef) is never numbered; null falls through to the style.

Null when not numbered, including a dangling INHERIT_LIST_REF whose style stopped numbering (the plugin heals those attrs back to null).

Parameters:
NameTypeDefault
resolvedSheetStyleSheet
nodeNode
Returns:
EffectiveNumbering | null

resolveTabStopAtSelection

The effective tabStop (px) of the numbered block at the selection anchor: paragraph override ?? level config. Undefined when neither sets one (the caller falls back to the editor default) or the block is not numbered.

Parameters:
NameTypeDefault
stateEditorState
Returns:
number | undefined

returnComputedListRef

The listRef to store after editing a list’s levels:

  • a style-bound prevListRef is kept, so the style binding survives;
  • else the ref of an existing config with identical levels;
  • else a new ref when there is no prevListRef, it is a built-in, or other instances share it (so they are unaffected);
  • else prevListRef.
Parameters:
NameTypeDefault
__0{ state: EditorState; levels: ILevelsOptions[]; prevListRef: string | undefined; numbering: DerivedEntries<NumberingEntry>; }
Returns:
string

StyleNumberingBinding

export type StyleNumberingBinding = Map<string, Map<number, string>>;

Inverse of the style bindings: listRef → level → styleId. Commands use it to turn a promote/demote or toggle-on into a style switch.

At most one style per (listRef, level) is enforced by the stylesheet form and normalize; if a sheet still violates it, the lowest-sorting id wins.

styleNumbersNode

Whether the node’s resolved style numbers it, regardless of its own attrs.

Parameters:
NameTypeDefault
resolvedSheetStyleSheet
nodeNode
Returns:
boolean

Page Number

collectPageNumbering

Every section’s own pageNumbering, for the sections that set one.

Parameters:
NameTypeDefault
docNode
Returns:
Map<string, PageNumberingAttrs>

formatPageNumber

A page number as a section prints it.

Parameters:
NameTypeDefault
nnumber
formatPageNumberFormat
Returns:
string

sectionFirstPageNumbers

The number each section’s first page prints, and the format it prints in, walking the sections in document order: a section restarts at its own start, and otherwise continues from the page before it — Word’s model.

Parameters:
NameTypeDefault
pageCountsMap<string, number>
pageNumberingMap<string, PageNumberingAttrs>
Returns:
Map<string, { first: number; format: PageNumberFormat; }>

toPageType

Coerces a parsed value to a PageNumberType; anything but "currentPage" is "totalPages".

Parameters:
NameTypeDefault
pageTypestring
Returns:
PageNumberType

Recreate Transform

recreateTransform

Builds a Transform that turns fromDoc into toDoc, for changes whose real steps were never captured (DOCX import, external rewrites), so history, collab and track changes see an ordinary edit rather than a document swap.

Parameters:
NameTypeDefault
fromDocNode
toDocNode
optionsOptions

complexSteps (default true) emits markup and mark steps instead of plain replacements; wordDiffs (default false) diffs text by word rather than by character; simplifyDiff (default true) merges adjacent steps afterwards.

Returns:
Transform

RecreateTransformOptions

NameTypeDefault
complexStepsboolean
wordDiffsboolean
simplifyDiffboolean

pairChildren

Which elements of input become which of output (CMP-7): unchanged ones first, then ones that differ by ids only, then by content similarity (pairBySimilarity). References are never compared: remapPairedIds rewrites them after pairing, and the diff then pairing a copy instead changed an id untracked (vtiilw). Never by position alone: a deleted block isn’t rewritten into the next changed one. Arrays of other values (marks, colwidths) pair by position in the gaps. columns is the alignment of the table (tableColumns) when input and output are the cells of two of its paired rows.

The pairing the visual compare (createDiffState) and recreateTransform use, so a caller that classifies blocks with it counts what the redline shows. A textblock may pair with a dissimilar one (as Word keeps a rewritten paragraph’s mark): callers that report “modified” should apply their own similarity floor. Deterministic.

Parameters:
NameTypeDefault
schemaSchema<any, any>

The schema both sides were serialised with.

inputunknown[]

The old children, in doc-JSON form.

outputunknown[]

The new children, in doc-JSON form.

columnsColumns
Returns:
Pair[]

[i, j] pairs, increasing in both indices; an index in no pair was deleted (i) or inserted (j).

similarity

Dice similarity of two word bags (see nodeWords): twice the words they share, counted with multiplicity, over their total length. 1 for equal bags and for two empty ones, 0 when one side is empty or nothing is shared. Order-blind: a reordered sentence scores 1.

Parameters:
NameTypeDefault
astring[]
bstring[]
Returns:
number

nodeWords

The word bag pairChildren weighs a node by: its text split on whitespace, plus a <type> token for each inline leaf (an image, a field) and each empty non-paragraph block. Feed two bags to similarity.

Parameters:
NameTypeDefault
jsonunknown

A node in doc-JSON form (node.toJSON()); anything else has no words.

Returns:
string[]

ChildPair

Indices of an element of the old array and the element of the new one it becomes.

NameTypeDefault
0number
1number
length2
toString() => string
toLocaleString{ (): string; (locales: string | string[], options?: (NumberFormatOptions & DateTimeFormatOptions) | undefined): string; }
pop() => number | undefined
push(...items: number[]) => number
concat{ (...items: ConcatArray<number>[]): number[]; (...items: (number | ConcatArray<number>)[]): number[]; }
join(separator?: string | undefined) => string
reverse() => number[]
shift() => number | undefined
slice(start?: number | undefined, end?: number | undefined) => number[]
sort(compareFn?: ((a: number, b: number) => number) | undefined) => Pair
splice{ (start: number, deleteCount?: number | undefined): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }
unshift(...items: number[]) => number
indexOf(searchElement: number, fromIndex?: number | undefined) => number
lastIndexOf(searchElement: number, fromIndex?: number | undefined) => number
every{ <S extends number>(predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }
some(predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean
forEach(callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
map<U>(callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]
filter{ <S extends number>(predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }
reduce{ (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; <U>(callbackfn: (previousValue: U, currentValue: number, ...
reduceRight{ (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; <U>(callbackfn: (previousValue: U, currentValue: number, ...
find{ <S extends number>(predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S | undefined; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number | undefined; }
findIndex(predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number
fill(value: number, start?: number | undefined, end?: number | undefined) => Pair
copyWithin(target: number, start: number, end?: number | undefined) => Pair
entries() => ArrayIterator<[number, number]>
keys() => ArrayIterator<number>
values() => ArrayIterator<number>
includes(searchElement: number, fromIndex?: number | undefined) => boolean
flatMap<U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This | undefined) => U[]
flat<A, D extends number = 1>(this: A, depth?: D | undefined) => FlatArray<A, D>[]
at(index: number) => number | undefined
__@iterator@6565() => ArrayIterator<number>
__@unscopables@6567{ [x: number]: boolean | undefined; length?: boolean; toString?: boolean; toLocaleString?: boolean; pop?: boolean; push?: boolean; concat?: boolean; join?: boolean; reverse?: boolean; shift?: boolean; slice?: boolean; ... 24 more ...; readonly [Symbol.unscopables]?: boolean; }

classifySearchMatch

The region containing pos. Anything not inside a note body or header/footer content is body, including malformed cases (a note body without a ref, header/footer content outside a section) and out-of-range positions.

Parameters:
NameTypeDefault
statePick<EditorState, "doc">
posnumber
Returns:
SearchMatchRegion

CommentSearchMatch

NameTypeDefault
threadIdstring
commentIdstring
startnumber

First occurrence range in the comment’s flattened text.

endnumber
distancenumber

With approximate, the edits between this match and the query: 0 or missing when exact.

CommentSearchQueryConfig

Mirrors the string branch of the doc SearchQuery (plugins/search/query.ts): optional \n/\r/\t unquoting, case-insensitive matching, and \p{L} word boundaries for whole-word mode. Comment bodies are adapter-owned JSONContent, not part of any live doc, so they are matched as flattened text.

NameTypeDefault
caseSensitiveboolean
wholeWordboolean
literalboolean

When true, don’t unquote \n/\r/\t in the search string.

approximateboolean

When true, near misses match too, as the doc search’s approximate.

findCommentMatches

Comments matching the query: one result per comment (its first occurrence), in the adapter’s thread order. Deleted threads and deleted/empty comments are skipped.

Parameters:
NameTypeDefault
threadsreadonly Thread[]
configCommentSearchQueryConfig
Returns:
CommentSearchMatch[]

flattenCommentBody

A comment body as plain text. Top-level blocks are joined with newlines so a match can’t span two blocks, as with the doc search’s per-textblock scan.

Parameters:
NameTypeDefault
bodyJSONContent
Returns:
string

getMatchHighlights

The current search matches, in document order: find reads like a DecorationSet’s. Past HIGHLIGHT_LIMIT only the active one is decorated.

Parameters:
NameTypeDefault
stateEditorState
Returns:
MatchSet

getSearchState

The search plugin’s state (query, range, decorations, enabled flag); undefined without the plugin.

Parameters:
NameTypeDefault
stateEditorState
Returns:
SearchState | undefined

SearchMatchRegion

Where a search match lives. Note bodies, header/footer content and text boxes are hidden or painted statically in the main editor DOM and edited through sub-editors, so navigation UIs use this to open the right one.

classifySearchMatch never produces comment: comment bodies live in the comment adapter, and the SearchBar builds those regions from findCommentMatches.

NameTypeDefault
kind"body" | "headerFooter" | "floatingBox" | "footnote" | "endnote" | "comment"

setSearchState

Adds meta to tr that sets the search query and range, and enables search, once dispatched.

Parameters:
NameTypeDefault
trTransaction
querySearchQuery
range{ from: number; to: number; }
Returns:
Transaction

Plugins

filterPlugins

Drops plugins whose key label is in excluded — used to trim the sub-editor plugin set.

Parameters:
NameTypeDefault
pluginsPlugin<any>[]
excludePluginsstring[]
Returns:
Plugin<any>[]

getPluginKeyLabel

A plugin’s key label (the string it was constructed with), or undefined.

Parameters:
NameTypeDefault
pPlugin<any>
Returns:
string | undefined

Section

createHeaderFooterContent

A header_footer_content node for a variant, seeded with one empty paragraph.

Parameters:
NameTypeDefault
schemaSchema<any, any>
variantHeaderFooterVariant
Returns:
Node | undefined

createSection

Builds a section (new id) around the given content, or an empty paragraph. With currentSection, copies its attrs (minus a page-number restart) and header/footer content. False when the schema lacks a required node type.

Parameters:
NameTypeDefault
schemaSchema<any, any>
contentToInsertSlice
currentSectionNode
Returns:
false | Node

findParentSection

The section containing the selection, with its position.

Parameters:
NameTypeDefault
stateEditorState
Returns:
FindResult

findParentSectionAtPos

The section containing a resolved position, with its position.

Parameters:
NameTypeDefault
stateEditorState
posnumber
Returns:
FindResult

findSectionById

Finds a top-level section node (with its pos) by its id attr.

Parameters:
NameTypeDefault
stateEditorState
sectionIdstring
Returns:
{ node: Node; pos: number; } | undefined

getDefaultSectionContentWidth

Content width (px) of a default-sized page, for callers with no section in hand.

Parameters:
This function does not accept any parameters.
Returns:
number

getSectionAttrsById

A section’s attrs looked up by its id.

Parameters:
NameTypeDefault
stateEditorState
sectionIdstring
Returns:
(SectionAttrs & { id: string; }) | undefined

getSectionContentHeight

Content height (px) of a section: its page height minus its top/bottom margins. A header or footer taller than its margin takes more on the pages it’s on.

Parameters:
NameTypeDefault
sectionAttrsAttrs
Returns:
number | undefined

getSectionContentWidth

Content width (px) of a section: its page width minus its left/right margins.

Parameters:
NameTypeDefault
sectionAttrsAttrs
Returns:
number | undefined

getSectionContentWidthAtPos

getSectionContentWidth for the section containing a given position.

Parameters:
NameTypeDefault
stateEditorState
posnumber
Returns:
number | undefined

getSectionRangesAndWidth

Each top-level section’s range and page width, computed once so per-position lookups don’t re-resolve.

Parameters:
NameTypeDefault
stateEditorState
Returns:
SectionRange[]

getWidthOfSectionAtPos

Page width of the section range containing pos; the default page width when none does.

Parameters:
NameTypeDefault
sectionRangesSectionRange[]
posnumber
Returns:
number

docHasSections

Whether doc is laid out in sections (a sub-editor’s doc isn’t).

Parameters:
NameTypeDefault
docNode
Returns:
boolean

sectionCount

Number of top-level sections in doc (0 for a sub-editor doc).

Parameters:
NameTypeDefault
docNode
Returns:
number

sectionIndexAt

Index of the top-level section holding $pos, or -1 at doc level or outside a section.

Parameters:
NameTypeDefault
$posResolvedPos
Returns:
number

getColumnWidthAt

The width of the column holding pos, as rendered here: one column’s in a column section, else the content width. For content landing at pos (inserts); an existing block spanning the columns needs getBlockWidthAt. Undefined outside a section.

Parameters:
NameTypeDefault
stateEditorState
posnumber
Returns:
number | undefined

getBlockWidthAt

The width the block starting at pos lays out in: getColumnWidthAt, or the content width when it spans the columns.

Parameters:
NameTypeDefault
stateEditorState
posnumber
Returns:
number | undefined

getSectionColumnWidth

The column width a section’s document asks for: one column’s when it has columns, else the content width, whatever this client renders. For sizing from the document alone (DOCX import); editors use getBlockWidthAt. Undefined without a page size.

Parameters:
NameTypeDefault
attrsAttrs
Returns:
number | undefined

Document integrity

Repairs and refusals of a broken section structure, for telemetry.

addDocIntegrityHandler

Handlers are additive and isolated: one throwing doesn’t stop the others. Returns an unsubscribe function.

Parameters:
NameTypeDefault
handlerDocIntegrityHandler
Returns:
() => void

DocIntegrityHandler

Receives every DocIntegrityReport; register one with addDocIntegrityHandler.

Parameters:
NameTypeDefault
reportDocIntegrityReport
Returns:
void

The report types, DocIntegrityReport and DocIntegrityIssueKind, are in core/types.

Drag and drop

For a custom drop handler: where dropped content may land without breaking the section structure.

resolveDropTarget

Where content dropped at pos lands, or null when it can’t land anywhere near: the single answer both the drop cursor and every drop path use.

  1. Snap section-level and doc-level positions to a body edge (snapDropPos).
  2. Fit the slice there with dropPoint, else drop at the snapped position.
  3. Accept only a target inside a section body whose dry-run replace keeps every section, header and footer as they were. That rules out the replace fitter wrapping the drop in a new footer and splitting the section.

slice null (content not known until drop, e.g. external files) checks the position only.

Parameters:
NameTypeDefault
docNode
posnumber
sliceSlice
bias1 | -1
Returns:
number | null

resolveDropTargetAtCoords

resolveDropTarget for the pointer at coords in view.

Parameters:
NameTypeDefault
viewEditorView
coords{ left: number; top: number; }
sliceSlice
Returns:
number | null

GalleryStyle

A style plus the id it lives under, ready to render in a gallery.

NameTypeDefault
idstring
styleStyleDefinition

getGalleryStyles

Every style a BLOCK can take, ordered the Word way: the full “more” list behind the gallery’s chevron. Character styles are excluded (they format runs).

semiHidden deliberately filters nothing here: it means “not in the quick strip”, not “unreachable”. Hiding the default sheet’s semiHidden + unhideWhenUsed styles (TOC 1–9) everywhere made them impossible to apply, since a style only becomes “used” by being picked.

Parameters:
NameTypeDefault
styleSheetStyleSheet
Returns:
GalleryStyle[]

getQuickStyles

The ribbon’s quick-style strip: promoted quickFormat styles. Falls back to the full list when none qualify, so the gallery is never an empty box.

Parameters:
NameTypeDefault
styleSheetStyleSheet
usedStyleIdsSet<string>
activeStyleIdstring
Returns:
GalleryStyle[]

getUsedStyleIds

The style ids referenced by nodes in the doc; drives unhideWhenUsed.

Parameters:
NameTypeDefault
stateOrDocEditorState | Node
Returns:
Set<string>

Style Sheet

generateStyleSheetCSS

Renders a resolved stylesheet to CSS, scoped to one editor instance. Mounted into a style element by the stylesheet plugin.

Parameters:
NameTypeDefault
styleSheetStyleSheet
editorIdstring
Returns:
string

getResolvedStyleDefinition

One fully resolved style by id, from getResolvedStyleSheet; Normal (with a warning) for unknown ids.

Parameters:
NameTypeDefault
stateEditorState
styleDefinitionIdstring
Returns:
StyleDefinition | undefined

getResolvedStyleSheet

The editor’s fully resolved stylesheet, from the stylesheet plugin’s state. Sub-editors don’t mount that plugin, so they read the root editor’s store.

Parameters:
NameTypeDefault
stateEditorState
Returns:
StyleSheet | undefined

getResolvedStyleSheetFromDoc

The resolved stylesheet of a DOC, for consumers without a state (a plugin apply, a walk callback, an export pass). Memoized on the styleSheet doc-attr object, which every edit replaces wholesale. Prefer getResolvedStyleSheet when a state is at hand.

Parameters:
NameTypeDefault
docNode
Returns:
StyleSheet

getSelectionCharacterStyleId

The character style covering the selection (Hyperlink in a link, HTMLCode in a code run), or undefined when no such mark spans all of it. Blocks never carry these ids (MT-10), so this is how the UI names a run’s style.

Parameters:
NameTypeDefault
stateEditorState
Returns:
string | undefined

getStyleOutlineLevel

Outline level (1–9) of a style, inherited through basedOn as in Word (a style based on Heading 2 is a level-2 heading unless it overrides; null resets to body text). Null for body-text, character and unknown styles.

Parameters:
NameTypeDefault
styleSheetStyleSheet
styleSheetIdstring
Returns:
number | null

getStylePaginationProps

Pagination props of a RESOLVED style, with fallbacks when the chain sets none: keepWithNext false, widowOrphan true, pageBreakBefore false, keepLines false. Read by the pagination engine (the node’s own pagination attr wins) and the Formatting panel.

Parameters:
NameTypeDefault
resolvedStyleStyleDefinition
Returns:
StylePaginationProps

getStyleSheet

Effective stylesheet: DEFAULT_STYLE_SHEET and the table style gallery merged with the doc’s overrides. basedOn chain is NOT walked here — use getResolvedStyleSheet for that.

Parameters:
NameTypeDefault
stateOrDocEditorState | Node
Returns:
StyleSheet

getStyleSheetOverrides

The doc’s raw, sparse stylesheet overrides: what writers persist, without defaults baked in. Takes a doc too, so multi-step transforms can read tr.doc instead of a stale state.

Parameters:
NameTypeDefault
stateOrDocEditorState | Node
Returns:
StyleSheet

isChangingHeadingLevel

Whether applying newLevel changes the TAG a heading renders as. Levels 7–9 all serialize as <p role="heading">, so moving between them needs no node replacement (the level attr is updated separately, see syncHeadingLevelsTr). True when newLevel is absent; false for non-headings.

Parameters:
NameTypeDefault
nodeNode
newLevelnumber
Returns:
boolean

isCharacterStyle

Whether a definition is a character style (HTMLCode, Hyperlink) rather than a paragraph style. Absent type means paragraph.

Parameters:
NameTypeDefault
styleStyleDefinition
Returns:
boolean

isParagraphStyle

A paragraph style: neither a character nor a table style. False for a missing one.

Parameters:
NameTypeDefault
styleStyleDefinition
Returns:
boolean

mergeStyleDefinition

Deep-merges a partial style definition onto a base one. paragraphStyle and characterStyle merge per field; spacing, indent and pagination one level deeper so partial edits compose; borders is replaced whole.

Parameters:
NameTypeDefault
baseStyleDefinition
overlayPartial<StyleDefinition>
Returns:
StyleDefinition

mergeStyleSheets

Merges an overlay stylesheet onto a base one: new ids are copied as-is, shared ids deep-merged via mergeStyleDefinition.

Parameters:
NameTypeDefault
baseStyleSheet
overlayStyleSheet
Returns:
StyleSheet

normalizeStyleDefinition

Normalizes a partial style definition before storage. On a built-in non-Normal style, basedOn: null resolves like its default basedOn, so it is coerced to that value and prune can collapse it.

Parameters:
NameTypeDefault
styleIdstring
styleDefPartial<StyleDefinition>
Returns:
Partial<StyleDefinition>

paragraphStyleIds

The ids of styleSheet a block may legally carry — paragraph styles only.

Parameters:
NameTypeDefault
styleSheetStyleSheet
Returns:
string[]

paragraphStylesToCss

A style’s paragraph-level properties as CSS declarations.

Parameters:
NameTypeDefault
paragraphStyleParagraphStyle
Returns:
string[]

pruneStyleAgainstBase

pruneStyleAgainstDefault against an arbitrary base. The DOCX import uses it so only real deltas from the resolved default reach doc.attrs.styleSheet. Undefined when nothing is left.

Parameters:
NameTypeDefault
overridePartial<StyleDefinition>
basePartial<StyleDefinition> | undefined
Returns:
Partial<StyleDefinition> | undefined

pruneStyleAgainstDefault

Drops fields of override that match DEFAULT_STYLE_SHEET[styleId]. Undefined when nothing is left (the caller should delete the key); custom styles (no default) come back unchanged.

Parameters:
NameTypeDefault
styleIdstring
overridePartial<StyleDefinition>
Returns:
Partial<StyleDefinition> | undefined

resolveStyleDefinition

Fully resolves one style by merging its basedOn chain underneath it. Unknown ids and circular chains fall back to Normal (logged); throws when the sheet has no Normal.

Parameters:
NameTypeDefault
styleSheetStyleSheet
styleNamestring
prevBasedOnstring[]
Returns:
StyleDefinition

resolveStyleSheet

resolveStyleDefinition applied to every style in the sheet.

Parameters:
NameTypeDefault
styleSheetStyleSheet
Returns:
StyleSheet

shouldReplaceEntireNode

Whether switching a node to a style needs a full node retype (paragraph ↔ heading, or a heading level change) rather than just an attr update.

Parameters:
NameTypeDefault
nodeNode
newElementTypestring
newLevelnumber
Returns:
boolean

styleIsHeading

Whether a style renders as a heading node. Heading-ness is the resolved outlineLevel, not the style id — custom and imported styles based on a heading are headings too.

Parameters:
NameTypeDefault
styleSheetStyleSheet
styleSheetIdstring
Returns:
boolean

textStyleToCss

A style’s character-level properties as CSS declarations. Sub/superscript text renders at 80% of the style’s own size.

Parameters:
NameTypeDefault
textStyleTextStyle
Returns:
string[]

Tables

completeGrid

Fills a partial grid and sizes it against blockWidth, the width the table lays out in. Unknown columns take the average known width, or an even split of the block when none is known. The result then fills the block when it is within 10% of it or wider (full-width intent, absorbing page-width differences between the source and the editor), else keeps its natural size. Columns are floored at minWidth; filling the block, the floors’ excess comes off the widest column. Floats; fitTableColumns rounds them.

Parameters:
NameTypeDefault
grid(number | null)[]
blockWidthnumber
minWidthnumber
Returns:
number[]

findTable

Find the closest table node for a given position.

Parameters:
NameTypeDefault
$posResolvedPos
Returns:
FindNodeResult | null

fitTableColumns

A table’s per-column widths (px), its unknown columns filled and the whole sized against availableWidth (completeGrid), rounded: the one-shot fit for tables arriving with partial or missing widths (paste, Markdown, AI).

Parameters:
NameTypeDefault
tableNode
availableWidthnumber

the width the table lays out in.

minWidthnumber

floor for every column, px.

Returns:
number[]

one px width per grid column (length = TableMap.width).

syncTableWidthToGrid

After an edit in tr that changed a fixed or pct table’s overall width (an outer-edge drag, a typed column width), restates the width at the new sum in the same mode, as Word does (D9): a fixed table’s px, a pct table’s share of the width it lays out in (dragged past it, where no share fits, it becomes fixed). previousSum is the grid sum before the edit; an edit that only traded width between columns changes nothing.

Parameters:
NameTypeDefault
trTransaction
stateEditorState
tablePosnumber
previousSumnumber
Returns:
void

getColumnsWidths

Per-column px widths, read from the first row’s cells; null where a cell has no colwidth.

Parameters:
NameTypeDefault
tableMapTableMap
tableNode
Returns:
(number | null)[]

getColumnsWidthsFromSelection

Px widths of the selected columns (unset widths dropped). Outside a CellSelection, the current cell’s colwidth; undefined for a single column.

Parameters:
NameTypeDefault
stateEditorState
Returns:
number[] | undefined

getRowHeightFromSelection

The height attr of the row at the selection, or undefined when unset.

Parameters:
NameTypeDefault
stateEditorState
Returns:
number | undefined

getRowHeightRuleFromSelection

Word’s height rule of the row at the selection: auto without a height, exact for an exact row, else atLeast (a null rule with a height is a minimum). Undefined outside a table.

Parameters:
NameTypeDefault
stateEditorState
Returns:
"auto" | "atLeast" | "exact" | undefined

getHeaderRowCount

The table’s header rows (headerRowCount), clamped to its row count.

Parameters:
NameTypeDefault
tableNode
Returns:
number

getRepeatedHeaderRows

Header rows painted again on every page the table continues onto: the header rows when repeatHeaderRows is on and a body row follows them, else 0.

Parameters:
NameTypeDefault
tableNode
Returns:
number

getRowKeepTogetherFromSelection

Whether every row the selection covers keeps together; false outside a table.

Parameters:
NameTypeDefault
stateEditorState
Returns:
boolean

getSelectedColumIndexes

Grid indexes of the columns the selected rect covers (rect.right is exclusive).

Parameters:
NameTypeDefault
stateEditorState
Returns:
number[]

getTableBlockWidth

The width a table at pos lays out in, px: its host cell’s when nested; the section’s content width in a header or footer (they span the page whatever the body’s columns, D10) and in flow layout (the measured width); in the body its column’s, or the content width for a table spanning the columns; less the inline chrome of the callouts around it. A position inside a block (an insertion point) takes the column. Undefined outside a section and inside a cell without widths.

state answers layout config only; positions resolve in doc, which defaults to state.doc (the sizing plugin passes its transaction’s).

Parameters:
NameTypeDefault
stateEditorState
posnumber
docNode
Returns:
number | undefined

getTableWidth

Sum of the set column widths, px.

Parameters:
NameTypeDefault
columnWidths(number | null)[]
Returns:
number | null

gridNeedsFit

Whether any grid column of table has no width: the sizing plugin fits it (I2).

Parameters:
NameTypeDefault
tableNode
Returns:
boolean

isInTable

Parameters:
NameTypeDefault
stateEditorState
Returns:
boolean

isWholeTableSelected

Whether the selection is a CellSelection covering every column and row of its table.

Parameters:
NameTypeDefault
stateEditorState
testOnlyboolean

Short-circuits to “the selection is a CellSelection inside a table”, skipping the coverage check. For callers that only need to know a table is involved.

Returns:
boolean

loopThroughCells

Visits each cell once in row-major grid order, with its table-relative position and column/row index. Rowspan continuations are skipped, and a colspan’d cell is visited at its FIRST column only.

Returning false suppresses that colspan skip (the walk steps into the covered columns); it does not stop the loop, nothing does.

Parameters:
NameTypeDefault
tableFindNodeResult
tableMapTableMap
callBack({ node, pos, colIndex, rowIndex, }: { node: Node; pos: number; colIndex: number; rowIndex: number; }) => boolean | void
Returns:
void

rescaleGrid

scaleGrid floored at COLWIDTH_MIN by default.

Parameters:
NameTypeDefault
gridnumber[]
targetnumber
minWidthnumber
Returns:
number[]

resolveTableWidth

The px width a table’s grid must sum to: the columns’ own sum for auto, the stated px for fixed, the share of blockWidth (the width the table lays out in) for pct.

Parameters:
NameTypeDefault
widthTableWidth
blockWidthnumber
gridSumnumber
Returns:
number

rowHasMergedCellsVertically

Whether any cell in the row is part of a vertical merge: it continues from the row above or extends into the row below (a spanning cell occupies the same position in several TableMap slots).

Parameters:
NameTypeDefault
tableMapTableMap
rowIndexnumber
Returns:
boolean

setTableColumnWidths

A copy of table with each cell’s colwidth set from per-grid-column px widths (span aware), for rebuilding from an external source such as DOCX w:tblGrid. Cells whose columns fall outside columns or resolve to 0 keep their widths; an invalid table is returned as is.

Parameters:
NameTypeDefault
tableNode
columnsnumber[]
Returns:
Node

tableGridSumAt

The grid sum of the table at tablePos, for syncTableWidthToGrid; null when incomplete.

Parameters:
NameTypeDefault
docNode
tablePosnumber
Returns:
number | null

tableWidthAs

The table at tablePos re-expressed as a width of type at its current size: fixed at its grid’s sum, pct as that sum’s share of the width it lays out in. Null when the grid is incomplete or, for pct, no width is known or the table is wider than it (no share past 100%).

Parameters:
NameTypeDefault
stateEditorState
tablePosnumber
type"auto" | "fixed" | "pct"
Returns:
TableWidth | null

Table styles

Table styles are type: "table" style definitions resolved at render time: a table names a style and a look, and each cell’s format is computed from the regions it falls in.

DEFAULT_TABLE_LOOK

export const DEFAULT_TABLE_LOOK: TableLook = { firstRow: true, lastRow: false, firstColumn: true, lastColumn: false, bandedRows: true, bandedColumns: false, };

Word’s Insert Table look (w:tblLook w:val="04A0").

DEFAULT_TABLE_STYLE_ID

export const DEFAULT_TABLE_STYLE_ID = "TableNormal";

The style with no formatting a table without tableStyle uses (Word’s).

getCellFormat

A cell’s table-style format by cell id, from tableStylesPlugin: one lookup. Null without one (the plugin absent, an id-less cell).

Parameters:
NameTypeDefault
stateEditorState
cellIdunknown
Returns:
CellFormat | null

isTableStyle

A type: "table" definition.

Parameters:
NameTypeDefault
styleStyleDefinition
Returns:
boolean

tableCellFormats

Every cell’s format, by row and by cell in the row (the node’s order), for a table under a RESOLVED sheet. Cached per table node and sheet: an edit elsewhere keeps the table node and so the result.

Parameters:
NameTypeDefault
tableNode
sheetStyleSheet
Returns:
CellFormat[][]

tableStyleGallery

Word’s built-in table styles under theme, keyed by style id: generated, merged under the overrides by getStyleSheet, never stored. Ids and names are Word’s (en-US ids, English names), so Word’s gallery recognises them.

Parameters:
NameTypeDefault
themeDocumentTheme
Returns:
StyleSheet

tableStyleOf

The resolved table style a table renders with: its own, else TableNormal’s.

Parameters:
NameTypeDefault
tableNode
sheetStyleSheet
Returns:
TableStyle

toTableLook

A look attr as stored, filled from the default where a field is missing or not boolean.

Parameters:
NameTypeDefault
valueunknown
Returns:
TableLook

Text Style

capsFromCss

Reads the two declarations capsToCss writes, except "none": every browser copy stamps the computed text-transform: none on its elements, so the resets say nothing. "none" travels in data-caps instead.

"small" wins over "all" when a span carries both: they share one slot, and font-variant is the narrower of the two — that span came from a small-caps run inside an all-caps style. CSS lowercase / capitalize have no caps value: Word rewrites text for those, so they are dropped rather than stored as a format that would fight the stored text.

Parameters:
NameTypeDefault
textTransformstring
fontVariantstring
Returns:
"all" | "small" | null

capsToCss

The CSS a caps value renders as. One value, two properties: "all" is a text-transform, "small" a font-variant, and "none" has to reset both — it exists precisely to beat an inherited caps of either kind.

Parameters:
NameTypeDefault
capsCaps
Returns:
string[]

EffectiveFontFamily

NameTypeDefault
valuestring | null

The font family the selection effectively renders with; null only while mixed.

mixedboolean

True when a ranged selection spans runs with different effective fonts.

source"style" | "mark" | "partial"

Where the value comes from: “mark” = an explicit textStyle mark on every run (pinned — survives stylesheet edits), “style” = the paragraph style / default on every run (follows stylesheet edits), “partial” = a ranged selection mixing both sources (even when they resolve to the same font).

getEffectiveFontFamily

The font family the selection effectively renders with: stored marks ?? run mark ?? paragraph style ?? DEFAULT_TEXT_STYLE. Unlike getTextStyles it walks every text run of a ranged selection, so mixed fonts report mixed.

Parameters:
NameTypeDefault
stateEditorState
Returns:
EffectiveFontFamily

getEffectiveFontSize

The font size the selection effectively renders at, or mixed when a ranged selection spans more than one. Mirrors getEffectiveFontFamily. mixed blanks the size box as in Word, so typing into it can’t re-apply a size the user never chose.

Parameters:
NameTypeDefault
stateEditorState
Returns:
EffectiveFontSize

getNodeBackgroundColor

The bgColor attr of the styled block at the selection (else the first one in the selected range, "transparent" when unset); null when there is none.

Parameters:
NameTypeDefault
stateEditorState
Returns:
string | null

getNodeBackgroundColorTheme

The theme ref beside getNodeBackgroundColor’s colour, null when it has none.

Parameters:
NameTypeDefault
stateEditorState
Returns:
string | null

getStyleSheetBackgroundColor

The block’s stylesheet paragraphStyle.backgroundColor, i.e. what it shows without direct formatting. Null when the style paints nothing, so callers can tell whether “use stylesheet value” would restore anything.

Parameters:
NameTypeDefault
stateEditorState
Returns:
string | null

getTextStyles

The text styling in effect at the selection start (stored marks, then marks, then the paragraph style). Drives the toolbar’s active states. Reads a single position, so it never reports mixed values; see getEffectiveFontFamily and getEffectiveFontSize for that.

Parameters:
NameTypeDefault
stateEditorState
Returns:
GetTextStylesResult

isInheritedOrDefault

Whether a CSS value is one of the “no explicit value” keywords (inherit, initial, …).

Parameters:
NameTypeDefault
valuestring
Returns:
boolean

isOff

Whether name is negated by these textStyle attrs.

Parameters:
NameTypeDefault
attrs{ off?: readonly TextStyleOff[] | null; }
namestring
Returns:
boolean

resolveFontFamily

Resolves a raw font name or CSS list (internal value, MS name, label, SpaceDot variant, var(--space-font) wrapper) to its internal FONT_FAMILIES value via findFontFamily (../fonts). Null when unknown, and also for the default font, which needs no mark.

Parameters:
NameTypeDefault
rawstring
Returns:
string | null

withOff

attrs with name negated (on: false) or un-negated (on: true), re-sorted into TEXT_STYLE_OFF order. An empty result is null, never [], so compaction drops it and Mark.eq sees one shape for “nothing off”.

Parameters:
NameTypeDefault
attrsT
nameTextStyleOff
onboolean
Returns:
T & { off: TextStyleOff[] | null; }

Document themes

A document’s colour theme, and the theme colour refs ("accent1:tint=BF") colours store beside their hex so a theme switch can recompute them.

formatThemeColorRef

The reverse of parseThemeColorRef: a ref in Word’s spelling.

Parameters:
NameTypeDefault
__0ParsedThemeColorRef
Returns:
string

getDocumentTheme

The document’s colour theme. A sub-editor’s doc (header, footnote) carries none of its own, so it reads the root doc the numbering plugin publishes.

Parameters:
NameTypeDefault
stateEditorState
Returns:
DocumentTheme

isThemeColorName

Whether value is one of THEME_COLOR_NAMES.

Parameters:
NameTypeDefault
valuestring
Returns:
boolean

ParsedThemeColorRef

A ref’s parts; tint/shade are Word’s two uppercase hex digits.

NameTypeDefault
nameThemeColorName
tintstring
shadestring

parseThemeColorRef

A ref (“accent1:tint=BF”) split into its name and tint or shade, else null. Hex digits come back uppercase.

Parameters:
NameTypeDefault
refstring
Returns:
ParsedThemeColorRef | null

resolveThemeColor

The hex a ref stands for under theme: the slot through the mapping, then Word’s tint (L' = L·t + 1 − t) or shade (L' = L·s) in HSL, t, s = byte / 255. Null when the ref is malformed.

Parameters:
NameTypeDefault
themeDocumentTheme
refstring
Returns:
string | null

sameThemeColors

Whether two themes paint the same colours (names aside).

Parameters:
NameTypeDefault
aDocumentTheme
bDocumentTheme
Returns:
boolean

STANDARD_COLORS

export const STANDARD_COLORS = [ "#C00000", "#FF0000", "#FFC000", "#FFFF00", "#92D050", "#00B050", "#00B0F0", "#0070C0", "#002060", "#7030A0", ] as const;

Word’s ten Standard Colors.

THEME_COLOR_NAMES

export const THEME_COLOR_NAMES = [ "dark1", "light1", "dark2", "light2", "accent1", "accent2", "accent3", "accent4", "accent5", "accent6", "hyperlink", "followedHyperlink", "background1", "text1", "background2", "text2", ] as const satisfies readonly ThemeColorName[];

Every name a theme colour ref may start with: Word’s slots and their mapped aliases.

THEME_SWATCH_COLUMNS

export const THEME_SWATCH_COLUMNS = [ "background1", "text1", "background2", "text2", "accent1", "accent2", "accent3", "accent4", "accent5", "accent6", ] as const satisfies readonly ThemeSwatchColumn[];

The columns of Word’s theme colour grid, in order.

themeSwatches

Word’s theme grid as rows: the ten base colours, then five variant rows. Each swatch carries its column and variant so a picker can label it. Cached per theme object, hence read-only.

Parameters:
NameTypeDefault
themeDocumentTheme
Returns:
readonly (readonly ThemeSwatch[])[]

themeSwatchForHex

The grid swatch hex is, base colours before variants, else null. A swatch one step off per channel still matches: Word’s w:val and our computed hex differ by that much (see hslToHex), so a fixed copy of Word’s value is one off ours.

Parameters:
NameTypeDefault
themeDocumentTheme
hexstring
Returns:
ThemeSwatch | null

toThemeColorRef

value as a well-formed ref in Word’s spelling (“accent1:tint=BF”), else null: the parse-side guard for DOM, JSON and DOCX input. Normalised so a ref compares equal to the swatch it came from.

Parameters:
NameTypeDefault
valueunknown
Returns:
string | null

Bibliography

CSL_ITEM_TYPES

export const CSL_ITEM_TYPES = [ "article", "article-journal", "article-magazine", "article-newspaper", "bill", "book", "broadcast", "chapter", "classic", "collection", "dataset", "document", "entry", "entry-dictionary", "entry-encyclopedia", "event", "figure", "graphic", "hearing", "interview", "legal_case", "legislation", "manuscript", "map", "motion_picture", "musical_score", "pamphlet", "paper-conference", "patent", "performance", "periodical", "personal_communication", "post", "post-weblog", "regulation", "report", "review", "review-book", "software", "song", "speech", "standard", "thesis", "treaty", "webpage", ] as const satisfies readonly CslItemType[];

Every CSL item type (CslItemType) a bibliography source may have.

isCslItemType

Parameters:
NameTypeDefault
valueunknown
Returns:
boolean

Other exports

ExportTypeDescription
CanvasGradientDirection"to bottom" | "to top" | "to right" | "to left" | "to bottom right" | "to bottom left" | "to top right" | "to top left"Directions a theme may declare. Mirrors the CSS to … keywords.
CASED_LIST_FORMATSreadonly LevelFormatValue[]The spelled-out formats whose output depends on casing.
CellSelectionclassRe-exported from prosemirror-tables.
cssStyleToBorderRecord<string, BorderStyle>Inverse of borderStyleToCSS, for parsing pasted CSS.
DEFAULT_FILE_HEIGHT600Preview height (px) of an unpaginated file node whose height is unset or zero.
FILE_ROTATIONSreadonly FileRotation[][0, 90, 180, 270], in the order the chrome steps through them.
GENDERED_LIST_FORMATSreadonly LevelFormatValue[]The formats whose output depends on gender.
ProfilerPluginHookKind"stateApply" | "appendTr" | "filterTr"Which plugin hook a pluginHook timing was measured on.
RecreateTransformclass (type-only export)Implementation behind recreateTransform.
TableMapclassRe-exported from prosemirror-tables.
TEXT_STYLE_OFFreadonly TextStyleOff[]Canonical order of textStyle.off; write it through withOff.

Redaction

The redaction mark and attribute’s helpers (the feature is in Redaction). REDACTION is the mark and attribute name; redactionMarkOf(marks) finds the mark; carriesRedactionAttr(type) tells a block leaf that takes the attribute, redactionAttrOf(node) reads it; readRedactionAttrs(attrs) reads mark or attribute data field by field (doc data is not trusted). fullRedactionReason(node) is the derived rule (a block whose content is all redacted under one reason, a container whose blocks all are), isFullyRedacted(node) its yes or no. toRedactionFragments(value) validates a final mark’s measured fragments, each drawn REDACTION_FRAGMENT_EPSILON narrower so a full line never wraps. REDACTION_REGIONS is the picture attribute holding redacted areas, toRedactionRegions(value) reads it field by field (clamped to the picture), redactionRegionsOf(node) a node’s areas.

Last updated on