# LitAST 节点模型

LitAST 节点的通用字段、节点与标记类型，以及段落、列表、分节、文档元数据的表示方式。

LitAST 是一棵普通 JSON 对象组成的树，可以直接 `JSON.stringify` 保存，再 `JSON.parse` 回来交给 `generateDocx`。

## 通用字段

每个节点都可能带有以下字段：

| 字段 | 含义 |
| --- | --- |
| `type` | 节点类型，必填 |
| `children` | 子节点 |
| `attrs` | 节点属性，例如段落对齐、表格列宽、图片尺寸 |
| `marks` | 只出现在 `text` 上，表示加粗、链接等文字格式 |
| `text` | 只出现在 `text` 上，文字内容 |
| `rawXml` | 原样保留的 OOXML，见[往返与保留](/guide/round-trip) |
| `meta` | 附加数据；根节点的 `meta` 存放包级数据 |

`parseDocx` 返回可修改的 `LitNode`；`generateDocx` 接收只读的 `LitAstNode`，两者结构相同。

以下划线开头的属性（如 `_pPrPreservation`）是为了写回原文件而保存的内部数据。读取时可以忽略；修改文档时保留它们，原有格式才能完整写回。

## 一个例子

一段含加粗文字的段落：

```json
{
  "type": "document",
  "attrs": { "version": 1 },
  "children": [
    {
      "type": "paragraph",
      "children": [
        { "type": "text", "text": "Hello " },
        { "type": "text", "text": "world", "marks": [{ "type": "bold" }] }
      ]
    }
  ]
}
```

## 节点类型

| 类别 | 类型 |
| --- | --- |
| 结构 | `document`、`section`、`header`、`footer` |
| 块 | `paragraph`、`heading`、`blockquote`、`codeBlock`、`horizontalRule`、`list`、`listItem`、`table`、`tableRow`、`tableCell` |
| 分隔 | `pageBreak`、`columnBreak`、`lastRenderedPageBreak` |
| 行内 | `text`、`image`、`textBox`、`field`、`sdt`（内容控件）、`footnoteRef`、`endnoteRef`、`math`、`ruby`、`watermark`、`backgroundImage` |
| 范围标记 | `commentStart` / `commentEnd`、`bookmarkStart` / `bookmarkEnd`、`permStart` / `permEnd`、`revision` |
| 无法识别 | `unknownBlock`、`unknownInline` |

## 标记类型

`bold`、`italic`、`underline`、`strike`、`doubleStrike`、`superscript`、`subscript`、`code`、`link`、`highlight`、`textStyle`，以及修订用的 `insertion` / `deletion`。

字号、颜色、字体等都放在 `textStyle` 标记的 `attrs` 中，例如：

```json
{ "type": "textStyle", "attrs": { "fontSize": "14pt", "color": "#C00000" } }
```

## 段落与标题

段落格式放在 `attrs` 中，例如 `textAlign`、`spacing`、`indent`。`heading` 用 `attrs.level`（1–6）表示级别。

## 列表

列表是 `list > listItem`，`list.attrs.ordered` 区分有序和无序。每个 `listItem` 就是一个带编号的段落，直接包含行内节点（`text`、`field` 等），不再包一层 `paragraph`。列表项的层级记在 `listItem.attrs.level` 上（从 0 开始）；不同层级或不同编号定义的项会拆成多个相邻的 `list`，而不是把 `list` 嵌套在 `listItem` 内部：

```text
list {"ordered":true}
  listItem {"level":0} > text "one"
list {"ordered":false}
  listItem {"level":1} > text "nested"
list {"ordered":true}
  listItem {"level":0} > text "two"
```

解析时传入 `numberingMode: "flat-numbered-paragraphs"` 可以改为保留 Word 原本的扁平编号段落。

生成时也按这个形状书写。`listItem` 里不能放 `paragraph`、`list` 等块级节点，否则会生成非法的嵌套段落。

## 拼音指南

`ruby` 是行内节点：`children` 是被注音的正文，`attrs.rubyText` 是注音，两者都是行内节点数组，各自带文字格式。
其余 `attrs` 是 Word 的注音属性：`rubyAlign`（对齐）、`hps`（注音字号）、`hpsRaise`（抬升量）、
`hpsBaseText`（正文参考字号）、`lid`（语言）与 `dirty`，字号与距离的单位是半磅：

```text
ruby {"rubyAlign":"center","hps":12,"hpsRaise":24,"hpsBaseText":24,"lid":"zh-CN","rubyText":[text "hàn"]}
  text "汉"
```

读音不会自动生成，lit-docx 只读写文件中已有的注音。新建方式见[生成 DOCX](/guide/generating#拼音指南)。

## 分节

`section` 不是包住内容的容器，而是 `document.children` 中的一个兄弟节点：它表示**之前**的内容到此结束一节，并携带这一节的页面设置。每个 Word 文档至少以一个 `section` 结尾：

```json
{
  "type": "section",
  "attrs": {
    "pageWidth": 11906, "pageHeight": 16838, "orientation": "portrait", "paperSize": "A4",
    "margins": { "top": 1440, "right": 1440, "bottom": 1440, "left": 1440, "header": 708, "footer": 708, "gutter": 0 }
  },
  "children": []
}
```

这一节的页眉页脚是它的 `header` / `footer` 子节点。尺寸单位见[生成 DOCX](/guide/generating)。

## 文档元数据

根节点的 `meta` 存放不属于正文的包级数据，常见的键有：

| 键 | 内容 |
| --- | --- |
| `rawXmlFiles` | 原样保留的部件 XML，键名如 `stylesXml`、`numberingXml`、`settingsXml`、`fontTableXml` |
| `coreProperties` | 创建者、最后修改者、创建与修改时间、修订号等核心属性 |
| `settings` | 文档设置 |
| `fieldData` | 域可以引用的核心属性、自定义属性与文档变量 |
| `comments` | 批注内容 |
| `footnotes` / `endnotes` | 脚注与尾注内容 |

只有文档里实际存在的数据才会出现对应的键。
