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

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

DocxImportOptions

NameTypeDefault
uploadImage(buffer: ArrayBuffer, contentType: string, filename: string) => 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”).

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 then keep their placeholder src and raise a missing_image warning.

DocxImportResult

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.

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

NameTypeDefault
typeImportWarningType
messagestring
elementstring
positionnumber

ImportWarningType

NameTypeDefault
toString() => string
charAt(pos: number) => string
charCodeAt(index: number) => number
concat(...strings: string[]) => string
indexOf(searchString: string, position?: number | undefined) => number
lastIndexOf(searchString: string, position?: number | undefined) => number
localeCompare{ (that: string): number; (that: string, locales?: string | string[] | undefined, options?: CollatorOptions | undefined): number; (that: string, locales?: LocalesArgument, options?: CollatorOptions | undefined): number; }
match{ (regexp: string | RegExp): RegExpMatchArray | null; (matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null; }
replace{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: { ...; }, replaceValue: string): string; (searchValue: { ...; }, replacer: (substring: string, ...args: any[]) => string): string; }
slice(start?: number | undefined, end?: number | undefined) => string
split{ (separator: string | RegExp, limit?: number | undefined): string[]; (splitter: { [Symbol.split](string: string, limit?: number | undefined): string[]; }, limit?: number | undefined): string[]; }
substring(start: number, end?: number | undefined) => string
toLowerCase() => string
toLocaleLowerCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
toUpperCase() => string
toLocaleUpperCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
trim() => string
lengthnumber
substr(from: number, length?: number | undefined) => string
valueOf() => string
codePointAt(pos: number) => number | undefined
includes(searchString: string, position?: number | undefined) => boolean
endsWith(searchString: string, endPosition?: number | undefined) => boolean
normalize{ (form: "NFC" | "NFD" | "NFKC" | "NFKD"): string; (form?: string | undefined): string; }
repeat(count: number) => string
startsWith(searchString: string, position?: number | undefined) => boolean
anchor(name: string) => string
big() => string
bold() => string
fixed() => string
fontcolor(color: string) => string
fontsize{ (size: number): string; (size: string): string; }
italics() => string
small() => string
strike() => string
sub() => string
sup() => string
padStart(maxLength: number, fillString?: string | undefined) => string
padEnd(maxLength: number, fillString?: string | undefined) => string
trimEnd() => string
trimStart() => string
trimLeft() => string
trimRight() => string
matchAll(regexp: RegExp) => RegExpStringIterator<RegExpExecArray>
replaceAll{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
at(index: number) => string | undefined
__@iterator@36() => StringIterator<string>

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).

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

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

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.

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[]

NumberingLevel

NameTypeDefault
levelnumber

w:ilvl, 0-based.

format"decimal" | "upperRoman" | "lowerRoman" | "upperLetter" | "lowerLetter" | "ordinal" | "cardinalText" | "ordinalText" | "hex" | "chicago" | "ideographDigital" | "japaneseCounting" | ... 51 more ... | undefined
textstring

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

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

w:suff. Absent = tab.

alignment"center" | "end"

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

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

generateDocxBuffer

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

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).

Parameters:
NameTypeDefault
stateEditorState
commentsCommentsDocx[]
Returns:
Promise<GeneratedDocx>

GeneratedDocx

NameTypeDefault
docFile_2
warningsstring[]

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

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.

threadsToDocx

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

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.

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

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