# The LitAST node model

Common node fields, node and mark types, and how paragraphs, lists, sections and document metadata are represented.

LitAST is a tree of plain JSON objects. You can save it with `JSON.stringify` and later hand the `JSON.parse` result to `generateDocx`.

## Common fields

Any node may carry these fields:

| Field | Meaning |
| --- | --- |
| `type` | Node type, required |
| `children` | Child nodes |
| `attrs` | Node attributes, such as paragraph alignment, table column widths or image size |
| `marks` | Only on `text`: formatting such as bold or links |
| `text` | Only on `text`: the characters |
| `rawXml` | OOXML kept verbatim; see [Round trips and preservation](/en/guide/round-trip) |
| `meta` | Extra data; the root's `meta` holds package-level data |

`parseDocx` returns mutable `LitNode`s; `generateDocx` accepts read-only `LitAstNode`s. Both have the same structure.

Attributes starting with an underscore (such as `_pPrPreservation`) are internal data kept for writing the original file back. Ignore them when reading; keep them when editing so the original formatting is written back intact.

## An example

A paragraph with bold text:

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

## Node types

| Category | Types |
| --- | --- |
| Structure | `document`, `section`, `header`, `footer` |
| Blocks | `paragraph`, `heading`, `blockquote`, `codeBlock`, `horizontalRule`, `list`, `listItem`, `table`, `tableRow`, `tableCell` |
| Breaks | `pageBreak`, `columnBreak`, `lastRenderedPageBreak` |
| Inline | `text`, `image`, `textBox`, `field`, `sdt` (content control), `footnoteRef`, `endnoteRef`, `math`, `ruby`, `watermark`, `backgroundImage` |
| Range markers | `commentStart` / `commentEnd`, `bookmarkStart` / `bookmarkEnd`, `permStart` / `permEnd`, `revision` |
| Unrecognized | `unknownBlock`, `unknownInline` |

## Mark types

`bold`, `italic`, `underline`, `strike`, `doubleStrike`, `superscript`, `subscript`, `code`, `link`, `highlight`, `textStyle`, plus `insertion` / `deletion` for tracked changes.

Font size, color, font family and similar properties live in the `attrs` of a `textStyle` mark, for example:

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

## Paragraphs and headings

Paragraph formatting lives in `attrs`, for example `textAlign`, `spacing` and `indent`. A `heading` stores its level (1–6) in `attrs.level`.

## Lists

Lists are `list > listItem`, with `list.attrs.ordered` telling ordered from unordered. Each `listItem` is one numbered paragraph and holds inline nodes (`text`, `field` and so on) directly, without a wrapping `paragraph`. An item's depth is `listItem.attrs.level`, starting at 0. Items at different levels or with different numbering definitions are split into adjacent `list` nodes rather than nesting a `list` inside a `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"
```

Pass `numberingMode: "flat-numbered-paragraphs"` when parsing to keep Word's flat numbered paragraphs instead.

Use the same shape when generating. Do not put block nodes such as `paragraph` or `list` inside a `listItem`; that produces invalid nested paragraphs.

## Phonetic guides

`ruby` is an inline node: `children` holds the annotated base text and `attrs.rubyText` holds the annotation.
Both are arrays of inline nodes with their own text formatting. The other `attrs` are Word's guide
properties: `rubyAlign`, `hps` (annotation size), `hpsRaise` (raise), `hpsBaseText` (reference base size),
`lid` (language) and `dirty`; sizes and distances are in half-points:

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

lit-docx never infers pronunciation; it reads and writes the annotation stored in the file. See
[Generating DOCX](/en/guide/generating#phonetic-guides) to create one.

## Sections

A `section` is not a container around content but a sibling in `document.children`: it ends the section formed by the content **before** it and carries that section's page setup. Every Word document ends with at least one `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": []
}
```

The section's headers and footers are its `header` / `footer` children. For units, see [Generating DOCX](/en/guide/generating).

## Document metadata

The root's `meta` holds package-level data that is not body content. Common keys:

| Key | Contents |
| --- | --- |
| `rawXmlFiles` | Part XML kept verbatim, with keys such as `stylesXml`, `numberingXml`, `settingsXml` and `fontTableXml` |
| `coreProperties` | Core properties such as creator, last modifier, created and modified times, and revision |
| `settings` | Document settings |
| `fieldData` | Core properties, custom properties and document variables that fields can reference |
| `comments` | Comment contents |
| `footnotes` / `endnotes` | Footnote and endnote contents |

A key appears only when the document actually contains that data.
