@markuplint/ml-ast 4.4.10-dev.350 → 4.4.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,314 @@
1
+ # @markuplint/ml-ast
2
+
3
+ ## 概要
4
+
5
+ `@markuplint/ml-ast` は、markuplint の言語非依存な抽象構文木(AST)中間表現を定義する純粋な型定義パッケージです。**ランタイムコードはゼロ**、**依存関係もゼロ**で、すべてのパーサーが生成し、すべての下流パッケージが消費する TypeScript 型定義のみを含みます。
6
+
7
+ すべてのマークアップ言語パーサー(HTML、JSX、Vue、Svelte、Astro、Pug など)はソースコードをここで定義された型にパースし、markuplint のコアとルールがソース言語に関係なく統一された AST 上で動作できるようにします。
8
+
9
+ ## ディレクトリ構成
10
+
11
+ ```
12
+ src/
13
+ ├── index.ts — types.ts からすべての型を再エクスポート
14
+ └── types.ts — すべての型定義(約470行)
15
+ ```
16
+
17
+ ## アーキテクチャ図
18
+
19
+ ```mermaid
20
+ flowchart TD
21
+ subgraph parsers ["パーサー(上流)"]
22
+ html["@markuplint/html-parser"]
23
+ jsx["@markuplint/jsx-parser"]
24
+ vue["@markuplint/vue-parser"]
25
+ svelte["@markuplint/svelte-parser"]
26
+ astro["@markuplint/astro-parser"]
27
+ pug["@markuplint/pug-parser"]
28
+ parserUtils["@markuplint/parser-utils"]
29
+ end
30
+
31
+ subgraph ast ["@markuplint/ml-ast"]
32
+ types["型定義\n(MLASTDocument, MLASTElement,\nMLASTComment, MLASTText, ...)"]
33
+ end
34
+
35
+ subgraph downstream ["下流"]
36
+ mlCore["@markuplint/ml-core\n(AST → DOM マッピング)"]
37
+ mlConfig["@markuplint/ml-config"]
38
+ mlSpec["@markuplint/ml-spec"]
39
+ rules["@markuplint/rules"]
40
+ fileResolver["@markuplint/file-resolver"]
41
+ end
42
+
43
+ parsers -->|"生成"| types
44
+ types -->|"消費"| downstream
45
+ mlCore -->|"DOM ノードを作成"| types
46
+ ```
47
+
48
+ ## 型継承図
49
+
50
+ ```mermaid
51
+ classDiagram
52
+ class MLASTToken {
53
+ <<interface>>
54
+ +uuid: string
55
+ +raw: string
56
+ +startOffset: number
57
+ +endOffset: number
58
+ +startLine: number
59
+ +endLine: number
60
+ +startCol: number
61
+ +endCol: number
62
+ }
63
+
64
+ class MLASTAbstractNode {
65
+ <<interface>>
66
+ +type: MLASTNodeType
67
+ +nodeName: string
68
+ +parentNode: MLASTParentNode | null
69
+ }
70
+
71
+ class MLASTDoctype {
72
+ <<interface>>
73
+ +type: "doctype"
74
+ +depth: number
75
+ +name: string
76
+ +publicId: string
77
+ +systemId: string
78
+ }
79
+
80
+ class MLASTElement {
81
+ <<interface>>
82
+ +type: "starttag"
83
+ +depth: number
84
+ +namespace: string
85
+ +elementType: ElementType
86
+ +attributes: MLASTAttr[]
87
+ +childNodes: MLASTChildNode[]
88
+ +pairNode: MLASTElementCloseTag | null
89
+ +isGhost: boolean
90
+ +isFragment: boolean
91
+ }
92
+
93
+ class MLASTElementCloseTag {
94
+ <<interface>>
95
+ +type: "endtag"
96
+ +depth: number
97
+ +parentNode: null
98
+ +pairNode: MLASTElement
99
+ }
100
+
101
+ class MLASTComment {
102
+ <<interface>>
103
+ +type: "comment"
104
+ +depth: number
105
+ +isBogus: boolean
106
+ }
107
+
108
+ class MLASTText {
109
+ <<interface>>
110
+ +type: "text"
111
+ +depth: number
112
+ }
113
+
114
+ class MLASTPreprocessorSpecificBlock {
115
+ <<interface>>
116
+ +type: "psblock"
117
+ +conditionalType: ...ConditionalType
118
+ +depth: number
119
+ +childNodes: MLASTChildNode[]
120
+ +isBogus: boolean
121
+ }
122
+
123
+ class MLASTInvalid {
124
+ <<interface>>
125
+ +type: "invalid"
126
+ +depth: number
127
+ +kind: MLASTChildNode type
128
+ +isBogus: true
129
+ }
130
+
131
+ class MLASTHTMLAttr {
132
+ <<interface>>
133
+ +type: "attr"
134
+ +name: MLASTToken
135
+ +value: MLASTToken
136
+ +isDynamicValue: boolean
137
+ +isDirective: boolean
138
+ }
139
+
140
+ class MLASTSpreadAttr {
141
+ <<interface>>
142
+ +type: "spread"
143
+ }
144
+
145
+ MLASTToken <|-- MLASTAbstractNode
146
+ MLASTAbstractNode <|-- MLASTDoctype
147
+ MLASTAbstractNode <|-- MLASTElement
148
+ MLASTAbstractNode <|-- MLASTElementCloseTag
149
+ MLASTAbstractNode <|-- MLASTComment
150
+ MLASTAbstractNode <|-- MLASTText
151
+ MLASTAbstractNode <|-- MLASTPreprocessorSpecificBlock
152
+ MLASTAbstractNode <|-- MLASTInvalid
153
+ MLASTToken <|-- MLASTHTMLAttr
154
+ MLASTToken <|-- MLASTSpreadAttr
155
+ ```
156
+
157
+ ## 共用体型
158
+
159
+ ```mermaid
160
+ flowchart TD
161
+ subgraph MLASTNode ["MLASTNode(全ノード型)"]
162
+ subgraph MLASTNodeTreeItem ["MLASTNodeTreeItem"]
163
+ MLASTDoctype["MLASTDoctype"]
164
+ subgraph MLASTChildNode ["MLASTChildNode"]
165
+ subgraph MLASTTag ["MLASTTag"]
166
+ MLASTElement["MLASTElement"]
167
+ MLASTElementCloseTag["MLASTElementCloseTag"]
168
+ end
169
+ MLASTText["MLASTText"]
170
+ MLASTComment["MLASTComment"]
171
+ MLASTPreprocessorSpecificBlock["MLASTPreprocessorSpecificBlock"]
172
+ MLASTInvalid["MLASTInvalid"]
173
+ end
174
+ end
175
+ subgraph MLASTAttr ["MLASTAttr"]
176
+ MLASTHTMLAttr["MLASTHTMLAttr"]
177
+ MLASTSpreadAttr["MLASTSpreadAttr"]
178
+ end
179
+ end
180
+
181
+ style MLASTElement fill:#e1f5fe
182
+ style MLASTPreprocessorSpecificBlock fill:#e1f5fe
183
+
184
+ note1["MLASTParentNode = MLASTElement | MLASTPreprocessorSpecificBlock\n(青でハイライト)"]
185
+ ```
186
+
187
+ ## ノード型一覧
188
+
189
+ | 型 | `type` 値 | 代表例 | 説明 |
190
+ | -------------------------------- | ------------ | ---------------------- | ---------------------------------------- |
191
+ | `MLASTDoctype` | `'doctype'` | `<!DOCTYPE html>` | DOCTYPE 宣言 |
192
+ | `MLASTElement` | `'starttag'` | `<div class="foo">` | 開始タグ。属性・子ノード・名前空間を保持 |
193
+ | `MLASTElementCloseTag` | `'endtag'` | `</div>` | 閉じタグ。開始タグとペア |
194
+ | `MLASTComment` | `'comment'` | `<!-- ... -->` | HTML コメント。bogus フラグ付き |
195
+ | `MLASTText` | `'text'` | テキスト内容 | 要素間の文字データ |
196
+ | `MLASTPreprocessorSpecificBlock` | `'psblock'` | `{#if}`, `<% %>` | テンプレートエンジン構文 |
197
+ | `MLASTInvalid` | `'invalid'` | パース不能マークアップ | 不正ノード。意図された種別のヒント付き |
198
+ | `MLASTHTMLAttr` | `'attr'` | `class="foo"` | 完全分解された HTML 属性 |
199
+ | `MLASTSpreadAttr` | `'spread'` | `{...props}` | JSX スプレッド属性 |
200
+
201
+ 各型の詳細は[ノードリファレンス](docs/node-reference.ja.md)を参照してください。
202
+
203
+ ## AST から MLDOM へのマッピング
204
+
205
+ 各 AST ノードは、最終的に `@markuplint/ml-core` によって **MLDOM** ノードに変換されます。MLDOM は [DOM Standard](https://dom.spec.whatwg.org/) に準拠しており、各クラスは対応する DOM インターフェース(`Node`、`Element`、`DocumentType`、`Comment`、`Text` など)を実装しているため、リントルールは標準 DOM API を使って検査できます。
206
+
207
+ | AST 型(`ml-ast`) | MLDOM クラス(`ml-core`) | DOM インターフェース | `nodeType` |
208
+ | ------------------------------------ | -------------------------- | ------------------------ | ---------- |
209
+ | `MLASTDoctype` | `MLDocumentType` | `DocumentType` | `10` |
210
+ | `MLASTElement` | `MLElement` | `Element`, `HTMLElement` | `1` |
211
+ | `MLASTComment` | `MLComment` | `Comment` | `8` |
212
+ | `MLASTText` | `MLText` | `Text` | `3` |
213
+ | `MLASTPreprocessorSpecificBlock` | `MLBlock` | _(markuplint 独自)_ | `101` |
214
+ | `MLASTInvalid`(`kind: 'starttag'`) | `MLElement`(`x-invalid`) | `Element`, `HTMLElement` | `1` |
215
+ | `MLASTInvalid`(その他) | `MLText` | `Text` | `3` |
216
+ | `MLASTHTMLAttr` / `MLASTSpreadAttr` | `MLAttr` | `Attr` | `2` |
217
+
218
+ **特殊なノード:**
219
+
220
+ - **`MLBlock`**(`nodeType: 101`)は DOM Standard に相当するものがない markuplint 独自の拡張です。透過的なコンテナとして機能し、子ノードはツリー走査時に親に属するものとして扱われます。
221
+ - **`MLElementCloseTag`** は `createNode()` で生成されません。代わりに `MLElement` が内部で `pairNode` 参照から生成します。ペアとなる要素の付属物としてのみ存在し、DOM ツリー走査の対象ではありません。
222
+ - **`MLASTInvalid`** はリカバリノードです。MLDOM にそのまま保持されることはなく、`kind` フィールドに応じて `MLElement`(タグ名 `x-invalid`)または `MLText` に変換されます。
223
+
224
+ 詳細は[ノードリファレンス -- AST から MLDOM へのマッピング](docs/node-reference.ja.md#ast-から-mldom-へのマッピング)を参照してください。
225
+
226
+ ## 属性分解モデル
227
+
228
+ `MLASTHTMLAttr` は各属性を完全な位置情報を持つ個別のトークンに分解します:
229
+
230
+ ```
231
+ ·class="container"
232
+ ↑ ↑↑ ↑
233
+ │ ││ └─ endQuote
234
+ │ │└─ value
235
+ │ └─ startQuote
236
+ │ equal
237
+ └─ spacesBeforeName
238
+ name
239
+ ```
240
+
241
+ これにより、リントルールは `=` 前後のホワイトスペース、引用符スタイル、属性命名規則を正確なソース位置で検証できます。完全なフィールドドキュメントは[ノードリファレンス](docs/node-reference.ja.md#mlasthtmlattr)を参照してください。
242
+
243
+ ## パーサーインターフェース
244
+
245
+ | 型 | 説明 |
246
+ | ------------------------ | -------------------------------------------------------- |
247
+ | `MLParser` | markuplint 互換パーサーのインターフェース |
248
+ | `MLParserModule` | パーサーインスタンスをエクスポートするモジュールラッパー |
249
+ | `MLMarkupLanguageParser` | 非推奨(v5 で削除予定)。代わりに `MLParser` を使用 |
250
+ | `Parse` | 非推奨。パース関数シグネチャの型エイリアス |
251
+
252
+ `MLParser` は `MLASTDocument` を返す `parse(sourceCode, options?)` メソッドを必要とします。オプションフィールドには `endTag`(終了タグ処理戦略)、`booleanish`(ブール属性検出)、`tagNameCaseSensitive`(XHTML/JSX 用)があります。
253
+
254
+ ## 設定型
255
+
256
+ | 型 | 説明 |
257
+ | ----------------------------------------- | ---------------------------------------------------------------------- |
258
+ | `MLASTNodeType` | ノード種別の判別共用体タグ |
259
+ | `ElementType` | 要素分類:`'html' \| 'web-component' \| 'authored'` |
260
+ | `EndTagType` | 終了タグ戦略:`'xml' \| 'omittable' \| 'never'` |
261
+ | `Namespace` | 短い名前空間識別子:`'html' \| 'svg' \| 'mml' \| 'xlink'` |
262
+ | `NamespaceURI` | HTML、SVG、MathML、XLink の完全な名前空間 URI |
263
+ | `ParserOptions` | パーサーに渡すオプション(`ignoreFrontMatter`、`authoredElementName`) |
264
+ | `ParserAuthoredElementNameDistinguishing` | 著者定義要素を区別するための設定 |
265
+ | `Walker<Node>` | AST ノードを走査するコールバック |
266
+
267
+ ## 外部依存関係
268
+
269
+ なし。このパッケージはランタイム依存関係がゼロです。TypeScript の型定義のみをエクスポートします。
270
+
271
+ ## 統合ポイント
272
+
273
+ ```mermaid
274
+ flowchart TD
275
+ subgraph upstream ["上流(パーサー)"]
276
+ htmlParser["@markuplint/html-parser"]
277
+ parserUtils["@markuplint/parser-utils"]
278
+ jsxParser["@markuplint/jsx-parser"]
279
+ astroParser["@markuplint/astro-parser"]
280
+ vueParser["@markuplint/vue-parser"]
281
+ svelteParser["@markuplint/svelte-parser"]
282
+ pugParser["@markuplint/pug-parser"]
283
+ end
284
+
285
+ subgraph pkg ["@markuplint/ml-ast"]
286
+ astTypes["型定義"]
287
+ end
288
+
289
+ subgraph downstream ["下流"]
290
+ mlCore["@markuplint/ml-core"]
291
+ mlConfig["@markuplint/ml-config"]
292
+ mlSpec["@markuplint/ml-spec"]
293
+ fileResolver["@markuplint/file-resolver"]
294
+ end
295
+
296
+ upstream -->|"MLParser を実装\nMLASTDocument を生成"| astTypes
297
+ astTypes -->|"MLASTNode 型\nMLParser インターフェース"| downstream
298
+ ```
299
+
300
+ ### 上流
301
+
302
+ すべてのパーサーは `MLParser` インターフェースを実装し、このパッケージで定義された AST ノード型を含む `MLASTDocument` インスタンスを生成します。
303
+
304
+ ### 下流
305
+
306
+ - **`@markuplint/ml-core`** は AST ノードを消費し、`createNode()` を通じて DOM ノードにマッピングします。`MLASTElement` が `MLElement` に、`MLASTText` が `MLText` になるなど、主要な統合ポイントです。
307
+ - **`@markuplint/ml-config`** は設定スキーマ定義で AST 型を参照します。
308
+ - **`@markuplint/ml-spec`** は名前空間と要素型の定義を使用します。
309
+ - **`@markuplint/file-resolver`** はパーサー関連の型を参照します。
310
+
311
+ ## ドキュメントマップ
312
+
313
+ - [ノードリファレンス](docs/node-reference.ja.md) -- 各 AST ノード型の詳細ドキュメント
314
+ - [メンテナンスガイド](docs/maintenance.ja.md) -- コマンド、レシピ、トラブルシューティング
@@ -0,0 +1,314 @@
1
+ # @markuplint/ml-ast
2
+
3
+ ## Overview
4
+
5
+ `@markuplint/ml-ast` is a pure type-definition package that defines the language-independent Abstract Syntax Tree (AST) intermediate representation for markuplint. It contains **zero runtime code** and **zero dependencies** -- only TypeScript type definitions that all parsers must produce and all downstream packages consume.
6
+
7
+ Every markup language parser (HTML, JSX, Vue, Svelte, Astro, Pug, etc.) parses source code into the types defined here, enabling markuplint's core and rules to operate on a unified AST regardless of the source language.
8
+
9
+ ## Directory Structure
10
+
11
+ ```
12
+ src/
13
+ ├── index.ts — Re-exports all types from types.ts
14
+ └── types.ts — All type definitions (~470 lines)
15
+ ```
16
+
17
+ ## Architecture Diagram
18
+
19
+ ```mermaid
20
+ flowchart TD
21
+ subgraph parsers ["Parsers (upstream)"]
22
+ html["@markuplint/html-parser"]
23
+ jsx["@markuplint/jsx-parser"]
24
+ vue["@markuplint/vue-parser"]
25
+ svelte["@markuplint/svelte-parser"]
26
+ astro["@markuplint/astro-parser"]
27
+ pug["@markuplint/pug-parser"]
28
+ parserUtils["@markuplint/parser-utils"]
29
+ end
30
+
31
+ subgraph ast ["@markuplint/ml-ast"]
32
+ types["Type Definitions\n(MLASTDocument, MLASTElement,\nMLASTComment, MLASTText, ...)"]
33
+ end
34
+
35
+ subgraph downstream ["Downstream"]
36
+ mlCore["@markuplint/ml-core\n(AST → DOM mapping)"]
37
+ mlConfig["@markuplint/ml-config"]
38
+ mlSpec["@markuplint/ml-spec"]
39
+ rules["@markuplint/rules"]
40
+ fileResolver["@markuplint/file-resolver"]
41
+ end
42
+
43
+ parsers -->|"produce"| types
44
+ types -->|"consumed by"| downstream
45
+ mlCore -->|"creates DOM nodes from"| types
46
+ ```
47
+
48
+ ## Type Inheritance Diagram
49
+
50
+ ```mermaid
51
+ classDiagram
52
+ class MLASTToken {
53
+ <<interface>>
54
+ +uuid: string
55
+ +raw: string
56
+ +startOffset: number
57
+ +endOffset: number
58
+ +startLine: number
59
+ +endLine: number
60
+ +startCol: number
61
+ +endCol: number
62
+ }
63
+
64
+ class MLASTAbstractNode {
65
+ <<interface>>
66
+ +type: MLASTNodeType
67
+ +nodeName: string
68
+ +parentNode: MLASTParentNode | null
69
+ }
70
+
71
+ class MLASTDoctype {
72
+ <<interface>>
73
+ +type: "doctype"
74
+ +depth: number
75
+ +name: string
76
+ +publicId: string
77
+ +systemId: string
78
+ }
79
+
80
+ class MLASTElement {
81
+ <<interface>>
82
+ +type: "starttag"
83
+ +depth: number
84
+ +namespace: string
85
+ +elementType: ElementType
86
+ +attributes: MLASTAttr[]
87
+ +childNodes: MLASTChildNode[]
88
+ +pairNode: MLASTElementCloseTag | null
89
+ +isGhost: boolean
90
+ +isFragment: boolean
91
+ }
92
+
93
+ class MLASTElementCloseTag {
94
+ <<interface>>
95
+ +type: "endtag"
96
+ +depth: number
97
+ +parentNode: null
98
+ +pairNode: MLASTElement
99
+ }
100
+
101
+ class MLASTComment {
102
+ <<interface>>
103
+ +type: "comment"
104
+ +depth: number
105
+ +isBogus: boolean
106
+ }
107
+
108
+ class MLASTText {
109
+ <<interface>>
110
+ +type: "text"
111
+ +depth: number
112
+ }
113
+
114
+ class MLASTPreprocessorSpecificBlock {
115
+ <<interface>>
116
+ +type: "psblock"
117
+ +conditionalType: ...ConditionalType
118
+ +depth: number
119
+ +childNodes: MLASTChildNode[]
120
+ +isBogus: boolean
121
+ }
122
+
123
+ class MLASTInvalid {
124
+ <<interface>>
125
+ +type: "invalid"
126
+ +depth: number
127
+ +kind: MLASTChildNode type
128
+ +isBogus: true
129
+ }
130
+
131
+ class MLASTHTMLAttr {
132
+ <<interface>>
133
+ +type: "attr"
134
+ +name: MLASTToken
135
+ +value: MLASTToken
136
+ +isDynamicValue: boolean
137
+ +isDirective: boolean
138
+ }
139
+
140
+ class MLASTSpreadAttr {
141
+ <<interface>>
142
+ +type: "spread"
143
+ }
144
+
145
+ MLASTToken <|-- MLASTAbstractNode
146
+ MLASTAbstractNode <|-- MLASTDoctype
147
+ MLASTAbstractNode <|-- MLASTElement
148
+ MLASTAbstractNode <|-- MLASTElementCloseTag
149
+ MLASTAbstractNode <|-- MLASTComment
150
+ MLASTAbstractNode <|-- MLASTText
151
+ MLASTAbstractNode <|-- MLASTPreprocessorSpecificBlock
152
+ MLASTAbstractNode <|-- MLASTInvalid
153
+ MLASTToken <|-- MLASTHTMLAttr
154
+ MLASTToken <|-- MLASTSpreadAttr
155
+ ```
156
+
157
+ ## Union Types
158
+
159
+ ```mermaid
160
+ flowchart TD
161
+ subgraph MLASTNode ["MLASTNode (all node types)"]
162
+ subgraph MLASTNodeTreeItem ["MLASTNodeTreeItem"]
163
+ MLASTDoctype["MLASTDoctype"]
164
+ subgraph MLASTChildNode ["MLASTChildNode"]
165
+ subgraph MLASTTag ["MLASTTag"]
166
+ MLASTElement["MLASTElement"]
167
+ MLASTElementCloseTag["MLASTElementCloseTag"]
168
+ end
169
+ MLASTText["MLASTText"]
170
+ MLASTComment["MLASTComment"]
171
+ MLASTPreprocessorSpecificBlock["MLASTPreprocessorSpecificBlock"]
172
+ MLASTInvalid["MLASTInvalid"]
173
+ end
174
+ end
175
+ subgraph MLASTAttr ["MLASTAttr"]
176
+ MLASTHTMLAttr["MLASTHTMLAttr"]
177
+ MLASTSpreadAttr["MLASTSpreadAttr"]
178
+ end
179
+ end
180
+
181
+ style MLASTElement fill:#e1f5fe
182
+ style MLASTPreprocessorSpecificBlock fill:#e1f5fe
183
+
184
+ note1["MLASTParentNode = MLASTElement | MLASTPreprocessorSpecificBlock\n(highlighted in blue)"]
185
+ ```
186
+
187
+ ## Node Types at a Glance
188
+
189
+ | Type | `type` Value | Example | Description |
190
+ | -------------------------------- | ------------ | ------------------- | -------------------------------------------------------- |
191
+ | `MLASTDoctype` | `'doctype'` | `<!DOCTYPE html>` | DOCTYPE declaration |
192
+ | `MLASTElement` | `'starttag'` | `<div class="foo">` | Opening element tag with attributes, children, namespace |
193
+ | `MLASTElementCloseTag` | `'endtag'` | `</div>` | Closing element tag, paired with its opening tag |
194
+ | `MLASTComment` | `'comment'` | `<!-- ... -->` | HTML comment, with bogus flag |
195
+ | `MLASTText` | `'text'` | text content | Character data between elements |
196
+ | `MLASTPreprocessorSpecificBlock` | `'psblock'` | `{#if}`, `<% %>` | Template engine constructs |
197
+ | `MLASTInvalid` | `'invalid'` | unparsable markup | Invalid node with intended kind hint |
198
+ | `MLASTHTMLAttr` | `'attr'` | `class="foo"` | Fully decomposed HTML attribute |
199
+ | `MLASTSpreadAttr` | `'spread'` | `{...props}` | JSX spread attribute |
200
+
201
+ See [Node Reference](docs/node-reference.md) for detailed documentation of each type.
202
+
203
+ ## AST to MLDOM Mapping
204
+
205
+ Each AST node is ultimately converted into an **MLDOM** node by `@markuplint/ml-core`. MLDOM conforms to the [DOM Standard](https://dom.spec.whatwg.org/) -- each class implements the corresponding DOM interface (`Node`, `Element`, `DocumentType`, `Comment`, `Text`, etc.), so lint rules can use standard DOM APIs for inspection.
206
+
207
+ | AST Type (`ml-ast`) | MLDOM Class (`ml-core`) | DOM Interface | `nodeType` |
208
+ | ----------------------------------- | ------------------------- | ------------------------ | ---------- |
209
+ | `MLASTDoctype` | `MLDocumentType` | `DocumentType` | `10` |
210
+ | `MLASTElement` | `MLElement` | `Element`, `HTMLElement` | `1` |
211
+ | `MLASTComment` | `MLComment` | `Comment` | `8` |
212
+ | `MLASTText` | `MLText` | `Text` | `3` |
213
+ | `MLASTPreprocessorSpecificBlock` | `MLBlock` | _(markuplint-specific)_ | `101` |
214
+ | `MLASTInvalid` (`kind: 'starttag'`) | `MLElement` (`x-invalid`) | `Element`, `HTMLElement` | `1` |
215
+ | `MLASTInvalid` (other) | `MLText` | `Text` | `3` |
216
+ | `MLASTHTMLAttr` / `MLASTSpreadAttr` | `MLAttr` | `Attr` | `2` |
217
+
218
+ **Special nodes:**
219
+
220
+ - **`MLBlock`** (`nodeType: 101`) is a markuplint-specific extension with no DOM Standard equivalent. It acts as a transparent container -- its children are treated as belonging to the parent for tree traversal.
221
+ - **`MLElementCloseTag`** is not created by `createNode()`. Instead, `MLElement` internally creates it from its `pairNode` reference. It exists only as a satellite of its paired element and is not part of the DOM tree traversal.
222
+ - **`MLASTInvalid`** is a recovery node -- it is never preserved as-is in MLDOM, but converted to either an `MLElement` (with tag name `x-invalid`) or an `MLText`, depending on its `kind` field.
223
+
224
+ See [Node Reference -- AST to MLDOM Mapping](docs/node-reference.md#ast-to-mldom-mapping) for details.
225
+
226
+ ## Attribute Decomposition Model
227
+
228
+ `MLASTHTMLAttr` decomposes each attribute into individual tokens with full positional information:
229
+
230
+ ```
231
+ ·class="container"
232
+ ↑ ↑↑ ↑
233
+ │ ││ └─ endQuote
234
+ │ │└─ value
235
+ │ └─ startQuote
236
+ │ equal
237
+ └─ spacesBeforeName
238
+ name
239
+ ```
240
+
241
+ This enables lint rules to validate whitespace around `=`, quoting style, and attribute naming conventions with precise source locations. See [Node Reference](docs/node-reference.md#mlasthtmlattr) for complete field documentation.
242
+
243
+ ## Parser Interface
244
+
245
+ | Type | Description |
246
+ | ------------------------ | ------------------------------------------------------ |
247
+ | `MLParser` | Interface for a markuplint-compatible parser |
248
+ | `MLParserModule` | Module wrapper that exports a parser instance |
249
+ | `MLMarkupLanguageParser` | Deprecated (v5 removal). Use `MLParser` instead |
250
+ | `Parse` | Deprecated type alias for the parse function signature |
251
+
252
+ `MLParser` requires a `parse(sourceCode, options?)` method that returns an `MLASTDocument`. Optional fields include `endTag` (end tag handling strategy), `booleanish` (boolean attribute detection), and `tagNameCaseSensitive` (for XHTML/JSX).
253
+
254
+ ## Configuration Types
255
+
256
+ | Type | Description |
257
+ | ----------------------------------------- | ---------------------------------------------------------------------- |
258
+ | `MLASTNodeType` | Discriminant union tag for node kinds |
259
+ | `ElementType` | Element classification: `'html' \| 'web-component' \| 'authored'` |
260
+ | `EndTagType` | End tag strategy: `'xml' \| 'omittable' \| 'never'` |
261
+ | `Namespace` | Short namespace identifiers: `'html' \| 'svg' \| 'mml' \| 'xlink'` |
262
+ | `NamespaceURI` | Full namespace URIs for HTML, SVG, MathML, XLink |
263
+ | `ParserOptions` | Options passed to parsers (`ignoreFrontMatter`, `authoredElementName`) |
264
+ | `ParserAuthoredElementNameDistinguishing` | Configuration for distinguishing authored elements |
265
+ | `Walker<Node>` | Callback for walking AST nodes |
266
+
267
+ ## External Dependencies
268
+
269
+ None. This package has zero runtime dependencies. It exports only TypeScript type definitions.
270
+
271
+ ## Integration Points
272
+
273
+ ```mermaid
274
+ flowchart TD
275
+ subgraph upstream ["Upstream (Parsers)"]
276
+ htmlParser["@markuplint/html-parser"]
277
+ parserUtils["@markuplint/parser-utils"]
278
+ jsxParser["@markuplint/jsx-parser"]
279
+ astroParser["@markuplint/astro-parser"]
280
+ vueParser["@markuplint/vue-parser"]
281
+ svelteParser["@markuplint/svelte-parser"]
282
+ pugParser["@markuplint/pug-parser"]
283
+ end
284
+
285
+ subgraph pkg ["@markuplint/ml-ast"]
286
+ astTypes["Type Definitions"]
287
+ end
288
+
289
+ subgraph downstream ["Downstream"]
290
+ mlCore["@markuplint/ml-core"]
291
+ mlConfig["@markuplint/ml-config"]
292
+ mlSpec["@markuplint/ml-spec"]
293
+ fileResolver["@markuplint/file-resolver"]
294
+ end
295
+
296
+ upstream -->|"implement MLParser\nproduce MLASTDocument"| astTypes
297
+ astTypes -->|"MLASTNode types\nMLParser interface"| downstream
298
+ ```
299
+
300
+ ### Upstream
301
+
302
+ All parsers implement the `MLParser` interface and produce `MLASTDocument` instances containing the AST node types defined in this package.
303
+
304
+ ### Downstream
305
+
306
+ - **`@markuplint/ml-core`** consumes AST nodes and maps them to DOM nodes via `createNode()`. This is the primary integration point where `MLASTElement` becomes `MLElement`, `MLASTText` becomes `MLText`, etc.
307
+ - **`@markuplint/ml-config`** references AST types in configuration schema definitions.
308
+ - **`@markuplint/ml-spec`** uses namespace and element type definitions.
309
+ - **`@markuplint/file-resolver`** references parser-related types.
310
+
311
+ ## Documentation Map
312
+
313
+ - [Node Reference](docs/node-reference.md) -- Detailed documentation of each AST node type
314
+ - [Maintenance Guide](docs/maintenance.md) -- Commands, recipes, and troubleshooting
package/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [4.4.11](https://github.com/markuplint/markuplint/compare/@markuplint/ml-ast@4.4.10...@markuplint/ml-ast@4.4.11) (2026-02-10)
7
+
8
+ **Note:** Version bump only for package @markuplint/ml-ast
9
+
10
+ ## [4.4.10](https://github.com/markuplint/markuplint/compare/@markuplint/ml-ast@4.4.9...@markuplint/ml-ast@4.4.10) (2025-08-13)
11
+
12
+ ### Bug Fixes
13
+
14
+ - ensure that each `clean` command correctly removes build files ([110b78e](https://github.com/markuplint/markuplint/commit/110b78e85379d29a84ca68325127344a87a570b6))
15
+
6
16
  ## [4.4.9](https://github.com/markuplint/markuplint/compare/@markuplint/ml-ast@4.4.8...@markuplint/ml-ast@4.4.9) (2024-11-17)
7
17
 
8
18
  **Note:** Version bump only for package @markuplint/ml-ast
package/README.md CHANGED
@@ -16,3 +16,9 @@ $ yarn add @markuplint/ml-ast
16
16
  ```
17
17
 
18
18
  </details>
19
+
20
+ ## Documentation
21
+
22
+ - [Architecture](ARCHITECTURE.md) -- Package overview, type hierarchy diagrams, and integration points
23
+ - [Node Reference](docs/node-reference.md) -- Detailed documentation of each AST node type
24
+ - [Maintenance Guide](docs/maintenance.md) -- Commands, recipes, and troubleshooting