GuidesView Markdown ↗
Reading DOCX
Inputs, options, results, warnings and errors of parseDocx, and where styles, numbering and images end up in the result.
ts
parseDocx(buffer: Uint8Array, options?: ParseOptions): Promise<ParseResult>
Preparing the input
parseDocx only accepts bytes and never reads files itself, so in every environment the caller obtains the bytes:
| Source | Code |
|---|---|
| A file in Node | new Uint8Array(await readFile(path)) |
A browser <input type="file"> or dropped File | new Uint8Array(await file.arrayBuffer()) |
A fetch response | new Uint8Array(await response.arrayBuffer()) |
Blob and File cannot be passed directly; convert them to bytes first.
The result
ParseResult has exactly two fields:
ast: the root of the document tree, withtype"document". Body blocks are itschildren; see The LitAST node model for their shape.warnings: non-fatal problems. Each has a stablecode, a readablemessage, and optionally alocation(where in the XML) and anelement(the tag name).
Parsing avoids stopping: when one piece of content cannot be recognized or fails to process, it becomes a warning and the rest of the document is still read.
Where the data lives
Styles, numbering and images are not returned as separate fields:
- Images are embedded in
imagenodes as a data URL inattrs.src. Image types and file signatures are checked before the URL is created. - Styles and numbering are used during parsing to compute the formatting of paragraphs, text and lists, and the results appear on those nodes. The original
styles.xmlandnumbering.xmlare kept inast.meta.rawXmlFilesand written back on generation. - Comments, footnotes, endnotes, document properties and settings are package-level data under
ast.meta.
Parse options
| Option | Default | Effect |
|---|---|---|
preserveRawXml | keep | Unrecognized elements become unknownBlock / unknownInline nodes with their original XML in rawXml, written back unchanged on generation. Only an explicit false drops them |
numberingMode | "nested-lists" | "nested-lists" rebuilds numbered paragraphs as nested list / listItem nodes; "flat-numbered-paragraphs" keeps Word's flat numbered paragraphs |
malformedFieldMode | "best-effort" | For malformed complex fields, best-effort keeps the content with a warning, strict rejects the current text story |
plugins | none | Extra parser plugins, consulted after the built-in ones |
chartSourceLimits | built-in limits | Bounds the size of chart source data; exceeding them rejects the import |
Errors
These cases throw DocxPackageError before any content is read; tell them apart by code:
code | Meaning |
|---|---|
invalid-zip-container | The bytes are not a ZIP package, for example the wrong file was passed |
unsupported-compound-file-container | An OLE compound file, typically an encrypted DOCX or a legacy .doc |
ts
try {
const { ast } = await parseDocx(bytes);
} catch (error) {
if (error instanceof DocxPackageError && error.code === "unsupported-compound-file-container") {
// Tell the user the file is encrypted or a legacy .doc
} else throw error;
}