# 读取 DOCX

parseDocx 的输入、选项、返回值、警告与错误，以及样式、编号、图片等数据在结果中的位置。

```ts
parseDocx(buffer: Uint8Array, options?: ParseOptions): Promise<ParseResult>
```

## 准备输入

`parseDocx` 只接收字节，自己不读文件，因此在任何环境里都由调用方负责拿到字节：

| 来源 | 写法 |
| --- | --- |
| Node 文件 | `new Uint8Array(await readFile(path))` |
| 浏览器 `<input type="file">` 或拖拽的 `File` | `new Uint8Array(await file.arrayBuffer())` |
| `fetch` 响应 | `new Uint8Array(await response.arrayBuffer())` |

`Blob` 和 `File` 不能直接传入，需要先转成字节。

## 返回值

`ParseResult` 只有两个字段：

- `ast`：文档树的根节点，`type` 为 `"document"`。正文块是它的 `children`，节点结构见 [LitAST 节点模型](/guide/litast)。
- `warnings`：非致命问题列表。每条有稳定的 `code`、可读的 `message`，以及可选的 `location`（出问题的 XML 位置）与 `element`（元素标签名）。

解析尽量不中断：某一处内容无法识别或处理出错时，会变成一条警告，其余内容照常读取。

### 数据在哪里

样式、编号、图片不会作为单独的返回字段出现：

- **图片**直接内嵌在 `image` 节点的 `attrs.src` 中，格式为 Data URL。写入前会校验图片类型和文件签名。
- **样式与编号**在解析时用于计算段落、文字和列表的格式，结果体现在各节点上。原始的 `styles.xml`、`numbering.xml` 保存在 `ast.meta.rawXmlFiles` 中，生成时写回。
- **批注、脚注、尾注、文档属性、设置**等包级数据放在 `ast.meta` 下。

## 解析选项

| 选项 | 默认值 | 作用 |
| --- | --- | --- |
| `preserveRawXml` | 保留 | 无法识别的元素保留为 `unknownBlock` / `unknownInline` 节点，原始 XML 存在 `rawXml` 中，生成时原样写回。只有显式传 `false` 才会丢弃它们 |
| `numberingMode` | `"nested-lists"` | `"nested-lists"` 把编号段落重建为嵌套的 `list` / `listItem`；`"flat-numbered-paragraphs"` 保持 Word 那样的扁平编号段落 |
| `malformedFieldMode` | `"best-effort"` | 遇到格式错误的复杂域时，`best-effort` 保留内容并给出警告，`strict` 拒绝当前文本流 |
| `plugins` | 无 | 追加自定义解析插件，在内置插件之后参与匹配 |
| `chartSourceLimits` | 内置上限 | 限制图表源数据的体积，超过上限时拒绝导入 |

## 错误

以下情况会在读取任何内容之前抛出 `DocxPackageError`，可以根据 `code` 区分：

| `code` | 含义 |
| --- | --- |
| `invalid-zip-container` | 字节不是 ZIP 包，例如传错了文件 |
| `unsupported-compound-file-container` | OLE 复合文件，常见于加密的 DOCX 或旧版 `.doc` |

```ts
try {
  const { ast } = await parseDocx(bytes);
} catch (error) {
  if (error instanceof DocxPackageError && error.code === "unsupported-compound-file-container") {
    // 提示用户：文件已加密，或者是旧版 .doc
  } else throw error;
}
```
