Skip to Content

@stesura/docx

DOCX import and export, framework-free. The toolbar buttons are in @stesura/docx-react; behaviour and round-trip limits are in the DOCX guide.

Import

importDocx

Imports a DOCX as a ProseMirror document, with its list configs, images and warnings for anything the editor can’t represent. Throws DocxImportError when the file isn’t a readable DOCX (wrong format, too large, corrupt).

Parameters:
NameTypeDefault
fileFile | ArrayBuffer
schemaSchema<any, any>
optionsDocxImportOptions
Returns:
Promise<DocxImportResult>

DocxImportOptions

Options for importDocx.

NameTypeDefault
uploadImage(buffer: ArrayBuffer, contentType: string, filename: string, signal: AbortSignal) => Promise<string | undefined>

Uploads an embedded image and returns its URL. When provided, every supported image is uploaded in parallel and the doc’s srcs point at the returned URLs, keeping base64 out of the doc (it bloats the collab payload). filename is the media entry name (e.g. “image1.png”). signal aborts when another upload failed or uploadTimeoutMs elapsed; wire it to the request where possible.

uploadTimeoutMsnumber

How long the whole image-upload batch may take before the remaining uploads are abandoned (fallback applies). Default 10s.

inlineImageFallbackboolean

Whether an image may fall back to a base64 data URL when there is no uploadImage or its upload fails. Default true. Collab mounts pass false; such images are then dropped from the doc and raise a missing_image warning.

nodeTransform(node: Node) => Node | null

Replaces imported nodes outside the core vocabulary’s reach: called on every node, a non-null result takes its place (e.g. a picture tagged as a diagram back into the diagram node). Runs before images are uploaded, so a consumed picture is never uploaded.

statsboolean

Fills DocxImportResult.stats (one extra walk over the content parts).

DocxImportResult

Result of importDocx.

NameTypeDefault
docNode
numberingNumberingConfig[]
warningsImportWarning[]

Anything that could not be imported faithfully.

imagesImportedImage[]
commentsImportedThread[]

Comment threads. The doc’s comment_open/comment_close anchors carry each thread’s import-minted id: the caller creates the threads in its comments store and rewrites the anchors’ threadId to the store’s ids before mounting — or strips the anchors when there is no store.

statsDocxImportStats

With options.stats.

DocxImportStats

What the importer saw and what it consumed, for measuring loss across a corpus.

NameTypeDefault
elementsRecord<string, number>

Every w:/m:/wp:/v: element in the content parts, by qualified name.

unhandledRecord<string, number>

Of those, the ones no handler consumed: unwrapped to their children (w:sdt) or skipped. Silent drops inside a handler are not here; the export’s element delta catches those.

DocxImportError

Thrown by importDocx when the file isn’t a readable DOCX: wrong format, corrupt archive, or over the size limits (50 MB, 200 MB decompressed, 5,000 entries). Its message is written for end users.

ImportWarning

Something the importer could not represent faithfully.

NameTypeDefault
typeImportWarningType
messagestring
elementstring
positionnumber

ImportWarningType

export type ImportWarningType = | "unsupported_element" | "missing_image" | "image_upload_failed" /** Pictures dropped because the schema has no image node. */ | "images_excluded" | "style_fallback" | "numbering_mismatch" | "parse_error";

ImportedThread

A comment thread from the file. The doc’s comment anchors carry its id; create the thread in your comments store and remap the anchors before mounting (see Loading the result into an editor).

A comment thread: its root comment first, then the replies in file order.

NameTypeDefault
idstring

The id the document’s comment anchors carry — replace it with the store’s. The root comment’s durable id when the file has one, so the same thread gets the same id on every import.

resolvedboolean
commentsImportedComment[]

ImportedComment

One comment of an imported thread.

NameTypeDefault
idstring

The comment’s w:id in the file.

durableIdstring | null

w16cid:durableId from commentsIds.xml: Word keeps it across saves, where w:id is renumbered — what identifies the same comment in a later import. Null when the file has no commentsIds part.

authorstring | null
initialsstring | null
datestring | null

ISO date, or null when the file states none.

bodyJSONContent

The body as comment-schema JSON (doc of paragraphs, shared marks, links as href).

ImportedImage

An image extracted from the DOCX.

NameTypeDefault
originalIdstring

The drawing’s r:embed relationship id.

filenamestring

Media entry name, e.g. “image1.png”.

bufferArrayBuffer
contentTypestring

Guessed from the extension; replaced by the type sniffed from the bytes before upload.

placeholderSrcstring

The src image nodes carry until importDocx rewrites it to the resolved one.

srcstring

Uploaded URL or data URL; stays placeholderSrc when unresolved.

NumberingConfig

NumberingLevel.pStyle carries Word’s level→style back-link for style-linked numbering.

A list definition imported from numbering.xml.

NameTypeDefault
refstring

The editor listRef: the resolved abstractNumId (Word runs one counter per abstractNum), or ${abstractNumId}.${numId} for a w:num that redefines the abstract.

abstractNumIdstring
levelsNumberingLevel[]
base{ ref: string; levels: number[]; ifShared?: boolean; }

A fork counts on the counters of ref (its abstract’s config) and restarts the levels (0-based ilvls) it overrides on its first use (TC-213). ifShared: a fork that redefines a level needs the base only when another list counts on that abstract too.

NumberingLevel

One level of a numbering definition.

NameTypeDefault
levelnumber

w:ilvl, 0-based.

format"none" | "custom" | "decimal" | "upperRoman" | "lowerRoman" | "upperLetter" | "lowerLetter" | "ordinal" | "cardinalText" | "ordinalText" | "hex" | "chicago" | "ideographDigital" | ... 50 more ... | undefined
textstring

w:lvlText pattern, e.g. “%1.%2”.

startnumber
suffix"tab" | "space" | "nothing"

w:suff. Absent = tab.

alignment"end" | "center"

w:lvlJc. Absent = start (Word’s left).

isLegalNumberingStyleboolean

w:isLgl: this level’s text renders every number as a decimal.

tabStopnumber

Px from the number’s start, from the level’s explicit w:tabs and w:ind. Absent without an explicit tab.

indentIndentAttrs

w:lvl/w:pPr/w:ind, px: the lowest tier of the indent cascade, which most numbered paragraphs in real files rely on.

pStylestring

w:lvl/w:pStyle: the paragraph style linked to this level. Imported as the style’s numbering binding; the style’s own w:numPr wins on conflict.

Export

downloadDocx

generateDocxBuffer, then saves the file in the browser (outputFileName defaults to example.docx).

Parameters:
NameTypeDefault
stateEditorState
commentsCommentsDocx[]
outputFileNamestring
optionsDocxExportOptions
Returns:
Promise<{ warnings: string[]; issues: ExportIssue[]; }>

generateDocxBuffer

Serializes an editor state to final .docx bytes, plus warnings for content that was skipped or degraded. Throws rather than produce a file Word would refuse to open.

Parameters:
NameTypeDefault
stateEditorState
commentsCommentsDocx[]
optionsDocxExportOptions
Returns:
Promise<{ buffer: Uint8Array<ArrayBuffer>; warnings: string[]; issues: ExportIssue[]; }>

generateDocx

Returns the unpacked docx-js Document. It skips the post-pack stage: packing it yourself loses comment threads, endnote options, section direction, style→level links and validation. Prefer downloadDocx / generateDocxBuffer (details).

Serializes an editor state to a docx-js Document, without packing or post-processing it. comments come from threadsToDocx; options carries the handlers and preloaded bytes of nodes outside the core schema.

Parameters:
NameTypeDefault
sourceStateEditorState
commentsCommentsDocx[]
optionsDocxExportOptions
Returns:
Promise<GeneratedDocx>

GeneratedDocx

A serialized document, plus everything the serializer could not represent.

NameTypeDefault
docFile_2
warningsstring[]

Content the serializer skipped or degraded — surface these to the user.

issuesExportIssue[]

warnings with a code and the node each came from.

commentMetaCommentExportMeta[]

Thread structure per comment id, consumed by the post-pack stage.

sectionDirs("rtl" | null)[]

Per-section text direction in document order, consumed by the post-pack stage.

sectionWatermarks(WatermarkExport | null)[]

Per-section watermark in document order, written by the post-pack stage.

listForksListForkNum[]

Forks’ w:nums, repointed by the post-pack stage.

listOverridesListOverrideNum[]

Lists’ own follow-bys, written by the post-pack stage.

listStartNumsnumber[]
picturesPictureExtras[]

Pictures’ crop, effects and DOCX passthrough, written by the post-pack stage.

drawingsDrawingExport[]
bibliographyBibliographyParts | null

Sources and our bibliography record as custom XML, written by the post-pack stage.

redactionsReadonlyMap<string, RedactionAttrs>

Each redaction written as a content control, by id: our custom XML part, written by the post-pack stage.

pictureRegionsReadonlyMap<string, PictureRegionsRecord>

Pictures’ redacted areas by picture key, in the same part.

themeThemeExport

The theme part and the theme refs docx-js cannot write, for the post-pack stage.

docAttrsAttrs

The exported document’s attrs, after transformDoc: the post-pack stage writes its properties from these, never from the source state’s.

threadsToDocx

Flattens threads into the comment list the docx export takes. Soft-deleted comments are dropped before isReply is computed, so a deleted root’s first reply becomes the root.

Parameters:
NameTypeDefault
threadsThread[]
schemaSchema<any, any>
resolveUserNameResolveUserName

Display name for a mentioned user id. Optional: authors named in the same threads are the fallback, then the raw id.

Returns:
CommentsDocx[]

CommentsDocx

A comment as generateDocx writes it: one per comment, replies flagged with isReply.

NameTypeDefault
threadIdstring | number
childrenNode[]
authorstring
dateDate
isReplyboolean

True for every comment after the first in its thread — drives commentsExtended.xml reply linking.

resolvedboolean

Thread resolved state — becomes w15:done in commentsExtended.xml.

DocxExportOptions

Export support for nodes outside the core schema. A package exports one of these (e.g. mermaidDocx); a host combining several spreads them together.

NameTypeDefault
nodesNodeSerializer

Handlers merged over the defaults (same name replaces).

transformDoc(doc: Node) => Node

Rewrites the document before anything reads it (preload, pre-passes, rendering), e.g. to resolve content that must not reach Word. Same schema.

preloadExtra(doc: Node) => Promise<Map<string, Buffer<ArrayBufferLike>>>

Bytes added to the image preload pass, keyed as handlers will ask for them through state.options.getImageBuffer. Runs alongside preloadImages.

traceDocxExportTrace

Filled with where the export’s time and bytes went (createExportTrace()).

lastModifiedBystring

The saving user’s name, stamped as cp:lastModifiedBy as Word does on save.

removeDocumentPropertiesboolean

Leaves the document’s properties (title, author, custom properties) out of the file, as Word’s Inspect Document → “Document Properties” does: kept otherwise, they reach whoever receives it (SEC-98).

redactionReasonsRedactionTaxonomy

Labels and colors of redaction reasons (the host’s taxonomy), for the content controls’ titles and boxes.

NodeSerializer

Renders nodes outside the core schema, passed as DocxExportOptions.nodes. Each handler gets the DocxSerializerState, which renders child content and collects the export’s blocks; mermaidDocx from @stesura/mermaid is one.

export type NodeSerializer = Record< string, (state: DocxSerializerState, node: Node, parent: Node, index: number) => void >;

Per-node-type render functions, keyed by schema node name.

DocxExportError

Thrown by downloadDocx / generateDocxBuffer when a stage throws for a reason other than validation. stage and at say where, cause keeps the original error.

An export that threw outside the validator: which stage, and (for the serializer) the node it was on. cause keeps the original stack. DocxValidationError passes through unwrapped.

NameTypeDefault
stageExportStage
atExportLocation | undefined
namestring
messagestring
stackstring
causeunknown

ExportStage

export type ExportStage = "serialize" | "pack" | "post-pack";

The export stage a DocxExportError failed in.

ExportLocation

Where in the document an issue or a failure happened.

NameTypeDefault
nodeTypestring
pathnumber[]

Child indexes from the rendered root (the doc, a note body, a header) to the node.

ancestorsstring[]

Types from that root down to the node.

snippetstring

The node’s first 60 characters of text.

ExportIssue

Content an export skipped or degraded, with the node it came from.

NameTypeDefault
codeExportIssueCode
messagestring
atExportLocation

ExportIssueCode

export type ExportIssueCode = | "format-change-partial" | "comment-unmatched-close" | "comment-unclosed" | "comment-on-block" | "header-footer-failed" | "note-body-no-ref" | "note-anchor-no-ref" | "note-anchor-orphan" | "note-body-orphan" | "table-cell-failed" | "numbering-incomplete" | "numbering-unknown-list" | "image-failed" | "image-missing" | "image-passthrough-dropped" | "file-omitted" | "code-block-failed" | "node-unsupported" /** A text box's minimum height: Word's boxes are fixed or fit their text. */ | "text-box-min-height" /** A block a text box can't hold in Word's model (a callout) went out as its paragraphs. */ | "text-box-content-flattened" | "mark-unsupported" | "link-internal-dropped" | "link-unsafe-dropped" | "link-invalid-dropped";

What an export skipped or degraded, one code per kind so a corpus run can count them.

createExportTrace

An empty DocxExportTrace, to pass as options.trace.

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

DocxExportTrace

Filled by generateDocxBuffer when passed as options.trace: where an export’s time and bytes go. Durations in ms.

NameTypeDefault
stages{ preload?: number; serialize?: number; pack?: number; "post-pack"?: number; }
postPackRecord<string, number>

Each post-pack injector and validator.

bytesnumber

The final file.

partsRecord<string, { bytes: number; elements: number; }>

Each XML part of the final file: size and element count.

nodeTypes{ type: string; count: number; ms: number; }[]

Render self-time per node type (children excluded), slowest first.

DocxValidationError

Thrown by downloadDocx / generateDocxBuffer when the packed file breaks a rule Word enforces, instead of shipping a file Word would reject or repair. problems lists every violation as a DocxProblem. This points to a serializer bug, not bad input.

DocxProblem

One rule violation found by assertValidDocx.

NameTypeDefault
partstring

OPC part the violation was found in, e.g. word/document.xml.

rulestring

Rule id, e.g. foreign-element.

detailstring

What is wrong, in one clause.

contextstring

Whitespace-collapsed XML around the first offending offset.

Last updated on