@markuplint/ml-ast 4.4.11 → 5.0.0-alpha.0
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.
- package/ARCHITECTURE.ja.md +9 -13
- package/ARCHITECTURE.md +9 -13
- package/CHANGELOG.md +41 -0
- package/SKILL.md +0 -1
- package/docs/maintenance.ja.md +6 -8
- package/docs/maintenance.md +0 -1
- package/docs/node-reference.ja.md +63 -61
- package/docs/node-reference.md +65 -63
- package/lib/types.d.ts +25 -53
- package/package.json +5 -2
package/ARCHITECTURE.ja.md
CHANGED
|
@@ -53,12 +53,9 @@ classDiagram
|
|
|
53
53
|
<<interface>>
|
|
54
54
|
+uuid: string
|
|
55
55
|
+raw: string
|
|
56
|
-
+
|
|
57
|
-
+
|
|
58
|
-
+
|
|
59
|
-
+endLine: number
|
|
60
|
-
+startCol: number
|
|
61
|
-
+endCol: number
|
|
56
|
+
+offset: number
|
|
57
|
+
+line: number
|
|
58
|
+
+col: number
|
|
62
59
|
}
|
|
63
60
|
|
|
64
61
|
class MLASTAbstractNode {
|
|
@@ -85,6 +82,7 @@ classDiagram
|
|
|
85
82
|
+elementType: ElementType
|
|
86
83
|
+attributes: MLASTAttr[]
|
|
87
84
|
+childNodes: MLASTChildNode[]
|
|
85
|
+
+blockBehavior: MLASTBlockBehavior | null
|
|
88
86
|
+pairNode: MLASTElementCloseTag | null
|
|
89
87
|
+isGhost: boolean
|
|
90
88
|
+isFragment: boolean
|
|
@@ -114,7 +112,7 @@ classDiagram
|
|
|
114
112
|
class MLASTPreprocessorSpecificBlock {
|
|
115
113
|
<<interface>>
|
|
116
114
|
+type: "psblock"
|
|
117
|
-
+
|
|
115
|
+
+blockBehavior: MLASTBlockBehavior | null
|
|
118
116
|
+depth: number
|
|
119
117
|
+childNodes: MLASTChildNode[]
|
|
120
118
|
+isBogus: boolean
|
|
@@ -242,12 +240,10 @@ flowchart TD
|
|
|
242
240
|
|
|
243
241
|
## パーサーインターフェース
|
|
244
242
|
|
|
245
|
-
| 型
|
|
246
|
-
|
|
|
247
|
-
| `MLParser`
|
|
248
|
-
| `MLParserModule`
|
|
249
|
-
| `MLMarkupLanguageParser` | 非推奨(v5 で削除予定)。代わりに `MLParser` を使用 |
|
|
250
|
-
| `Parse` | 非推奨。パース関数シグネチャの型エイリアス |
|
|
243
|
+
| 型 | 説明 |
|
|
244
|
+
| ---------------- | -------------------------------------------------------- |
|
|
245
|
+
| `MLParser` | markuplint 互換パーサーのインターフェース |
|
|
246
|
+
| `MLParserModule` | パーサーインスタンスをエクスポートするモジュールラッパー |
|
|
251
247
|
|
|
252
248
|
`MLParser` は `MLASTDocument` を返す `parse(sourceCode, options?)` メソッドを必要とします。オプションフィールドには `endTag`(終了タグ処理戦略)、`booleanish`(ブール属性検出)、`tagNameCaseSensitive`(XHTML/JSX 用)があります。
|
|
253
249
|
|
package/ARCHITECTURE.md
CHANGED
|
@@ -53,12 +53,9 @@ classDiagram
|
|
|
53
53
|
<<interface>>
|
|
54
54
|
+uuid: string
|
|
55
55
|
+raw: string
|
|
56
|
-
+
|
|
57
|
-
+
|
|
58
|
-
+
|
|
59
|
-
+endLine: number
|
|
60
|
-
+startCol: number
|
|
61
|
-
+endCol: number
|
|
56
|
+
+offset: number
|
|
57
|
+
+line: number
|
|
58
|
+
+col: number
|
|
62
59
|
}
|
|
63
60
|
|
|
64
61
|
class MLASTAbstractNode {
|
|
@@ -85,6 +82,7 @@ classDiagram
|
|
|
85
82
|
+elementType: ElementType
|
|
86
83
|
+attributes: MLASTAttr[]
|
|
87
84
|
+childNodes: MLASTChildNode[]
|
|
85
|
+
+blockBehavior: MLASTBlockBehavior | null
|
|
88
86
|
+pairNode: MLASTElementCloseTag | null
|
|
89
87
|
+isGhost: boolean
|
|
90
88
|
+isFragment: boolean
|
|
@@ -114,7 +112,7 @@ classDiagram
|
|
|
114
112
|
class MLASTPreprocessorSpecificBlock {
|
|
115
113
|
<<interface>>
|
|
116
114
|
+type: "psblock"
|
|
117
|
-
+
|
|
115
|
+
+blockBehavior: MLASTBlockBehavior | null
|
|
118
116
|
+depth: number
|
|
119
117
|
+childNodes: MLASTChildNode[]
|
|
120
118
|
+isBogus: boolean
|
|
@@ -242,12 +240,10 @@ This enables lint rules to validate whitespace around `=`, quoting style, and at
|
|
|
242
240
|
|
|
243
241
|
## Parser Interface
|
|
244
242
|
|
|
245
|
-
| Type
|
|
246
|
-
|
|
|
247
|
-
| `MLParser`
|
|
248
|
-
| `MLParserModule`
|
|
249
|
-
| `MLMarkupLanguageParser` | Deprecated (v5 removal). Use `MLParser` instead |
|
|
250
|
-
| `Parse` | Deprecated type alias for the parse function signature |
|
|
243
|
+
| Type | Description |
|
|
244
|
+
| ---------------- | --------------------------------------------- |
|
|
245
|
+
| `MLParser` | Interface for a markuplint-compatible parser |
|
|
246
|
+
| `MLParserModule` | Module wrapper that exports a parser instance |
|
|
251
247
|
|
|
252
248
|
`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
249
|
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,47 @@
|
|
|
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
|
+
# [5.0.0-alpha.0](https://github.com/markuplint/markuplint/compare/v4.14.1...v5.0.0-alpha.0) (2026-02-20)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **ml-core:** improve detection of namespace ([5b507ad](https://github.com/markuplint/markuplint/commit/5b507ad7c19c5015b8ce587845d901e31dfa6518))
|
|
11
|
+
|
|
12
|
+
- feat(ml-ast)!: simplify AST token properties and restructure block types ([78f8a77](https://github.com/markuplint/markuplint/commit/78f8a77c76728df8090fcf54c7c5541bedb56f9d))
|
|
13
|
+
|
|
14
|
+
### BREAKING CHANGES
|
|
15
|
+
|
|
16
|
+
- Multiple breaking changes to AST interfaces:
|
|
17
|
+
|
|
18
|
+
Token property renames (MLASTToken):
|
|
19
|
+
|
|
20
|
+
- startOffset -> offset
|
|
21
|
+
- startLine -> line
|
|
22
|
+
- startCol -> col
|
|
23
|
+
- Remove endOffset, endLine, endCol (derive via helpers)
|
|
24
|
+
|
|
25
|
+
Element changes (MLASTElement):
|
|
26
|
+
|
|
27
|
+
- Remove selfClosingSolidus property
|
|
28
|
+
- Add blockBehavior: MLASTBlockBehavior | null
|
|
29
|
+
|
|
30
|
+
Block changes (MLASTPreprocessorSpecificBlock):
|
|
31
|
+
|
|
32
|
+
- Remove conditionalType property
|
|
33
|
+
- Add blockBehavior: MLASTBlockBehavior | null
|
|
34
|
+
|
|
35
|
+
New types:
|
|
36
|
+
|
|
37
|
+
- MLASTBlockBehavior interface (type + expression)
|
|
38
|
+
- MLASTBlockBehaviorType (replaces MLASTPreprocessorSpecificBlockConditionalType)
|
|
39
|
+
|
|
40
|
+
Removed deprecated types:
|
|
41
|
+
|
|
42
|
+
- MLMarkupLanguageParser interface
|
|
43
|
+
- Parse type alias
|
|
44
|
+
|
|
45
|
+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
46
|
+
|
|
6
47
|
## [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
48
|
|
|
8
49
|
**Note:** Version bump only for package @markuplint/ml-ast
|
package/SKILL.md
CHANGED
|
@@ -102,7 +102,6 @@ Modify the `MLParser` interface. Follow recipe #5 in `docs/maintenance.md`.
|
|
|
102
102
|
|
|
103
103
|
1. Read `src/types.ts` and find `MLParser`
|
|
104
104
|
2. Make changes (prefer adding optional fields for backward compatibility)
|
|
105
|
-
3. Update `MLMarkupLanguageParser` (deprecated) if needed for consistency
|
|
106
105
|
|
|
107
106
|
### Step 2: Update all parsers
|
|
108
107
|
|
package/docs/maintenance.ja.md
CHANGED
|
@@ -116,22 +116,21 @@ yarn build --scope @markuplint/ml-ast
|
|
|
116
116
|
|
|
117
117
|
5. **ビルドして検証**
|
|
118
118
|
|
|
119
|
-
### 4. `
|
|
119
|
+
### 4. `MLASTBlockBehaviorType` の値追加
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
プリプロセッサブロックの新しいブロック動作種別を追加する場合:
|
|
122
122
|
|
|
123
|
-
1. **`src/types.ts` の `
|
|
123
|
+
1. **`src/types.ts` の `MLASTBlockBehaviorType` に値を追加**:
|
|
124
124
|
|
|
125
125
|
```typescript
|
|
126
|
-
export type
|
|
126
|
+
export type MLASTBlockBehaviorType =
|
|
127
127
|
| 'if'
|
|
128
128
|
| 'if:elseif'
|
|
129
129
|
// ... 既存の値
|
|
130
|
-
| 'newvalue' // ここに追加
|
|
131
|
-
| null;
|
|
130
|
+
| 'newvalue'; // ここに追加
|
|
132
131
|
```
|
|
133
132
|
|
|
134
|
-
2.
|
|
133
|
+
2. **この動作種別で `blockBehavior` を設定するパーサーを更新**
|
|
135
134
|
|
|
136
135
|
3. **新しい値が DOM 作成時に特別な処理を必要とする場合は `ml-core` を更新**
|
|
137
136
|
|
|
@@ -149,7 +148,6 @@ yarn build --scope @markuplint/ml-ast
|
|
|
149
148
|
2. **後方互換性を考慮**:
|
|
150
149
|
- オプションフィールドの追加は安全
|
|
151
150
|
- 必須フィールドの追加やシグネチャの変更は破壊的変更
|
|
152
|
-
- 一貫性のため必要に応じて `MLMarkupLanguageParser`(非推奨)も更新
|
|
153
151
|
|
|
154
152
|
3. **すべてのパーサー実装を更新**:
|
|
155
153
|
- `@markuplint/html-parser`
|
package/docs/maintenance.md
CHANGED
|
@@ -149,7 +149,6 @@ When changing the parser interface:
|
|
|
149
149
|
2. **Consider backward compatibility**:
|
|
150
150
|
- Adding optional fields is safe
|
|
151
151
|
- Adding required fields or changing signatures is a breaking change
|
|
152
|
-
- Update `MLMarkupLanguageParser` (deprecated) if needed for consistency
|
|
153
152
|
|
|
154
153
|
3. **Update all parser implementations**:
|
|
155
154
|
- `@markuplint/html-parser`
|
|
@@ -61,16 +61,15 @@ function handle(node: MLASTNode) {
|
|
|
61
61
|
|
|
62
62
|
すべての位置情報の基盤となるインターフェースです。すべての AST ノードとサブトークンがこれを継承します。
|
|
63
63
|
|
|
64
|
-
| フィールド
|
|
65
|
-
|
|
|
66
|
-
| `uuid`
|
|
67
|
-
| `raw`
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
| `endCol` | `number` | トークン終了位置の1ベース列番号 |
|
|
64
|
+
| フィールド | 型 | 説明 |
|
|
65
|
+
| ---------- | -------- | ------------------------------------------ |
|
|
66
|
+
| `uuid` | `string` | このトークンインスタンスの一意識別子 |
|
|
67
|
+
| `raw` | `string` | 元のソーステキスト |
|
|
68
|
+
| `offset` | `number` | トークン開始位置のゼロベース文字オフセット |
|
|
69
|
+
| `line` | `number` | トークン開始位置の1ベース行番号 |
|
|
70
|
+
| `col` | `number` | トークン開始位置の1ベース列番号 |
|
|
71
|
+
|
|
72
|
+
**終了位置の導出:** 終了位置のプロパティはありません。終了位置は開始位置と `raw` から導出できます。ユーティリティ関数 `getEndLine()`、`getEndCol()`、`getEndPosition()`(`@markuplint/parser-utils` 提供)が利用可能です。
|
|
74
73
|
|
|
75
74
|
**座標系について:** オフセットはゼロベース(0から数える)、行と列は1ベース(1から数える)です。これはほとんどのテキストエディタやエラーレポーターの慣例に一致しています。
|
|
76
75
|
|
|
@@ -125,21 +124,21 @@ function handle(node: MLASTNode) {
|
|
|
125
124
|
|
|
126
125
|
**役割:** 開始タグ(例:`<div class="foo">`)を表します。AST における主要な要素表現であり、最も機能豊富なノード型です。子ノード、属性を所有し、対応する閉じタグへの参照を保持します。
|
|
127
126
|
|
|
128
|
-
| フィールド
|
|
129
|
-
|
|
|
130
|
-
| `type`
|
|
131
|
-
| `depth`
|
|
132
|
-
| `namespace`
|
|
133
|
-
| `elementType`
|
|
134
|
-
| `isFragment`
|
|
135
|
-
| `attributes`
|
|
136
|
-
| `hasSpreadAttr`
|
|
137
|
-
| `childNodes`
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `tagOpenChar`
|
|
141
|
-
| `tagCloseChar`
|
|
142
|
-
| `isGhost`
|
|
127
|
+
| フィールド | 型 | 説明 |
|
|
128
|
+
| --------------- | ------------------------------ | ---------------------------------------------------------------- |
|
|
129
|
+
| `type` | `'starttag'` | 判別タグ |
|
|
130
|
+
| `depth` | `number` | ドキュメントツリーでのネストの深さ |
|
|
131
|
+
| `namespace` | `string` | 名前空間 URI(例:`"http://www.w3.org/1999/xhtml"`) |
|
|
132
|
+
| `elementType` | `ElementType` | `'html'`、`'web-component'`、`'authored'` のいずれか |
|
|
133
|
+
| `isFragment` | `boolean` | フラグメントとして機能するか(例:React `<>`、Vue `<template>`) |
|
|
134
|
+
| `attributes` | `readonly MLASTAttr[]` | この要素の属性 |
|
|
135
|
+
| `hasSpreadAttr` | `boolean \| undefined` | スプレッド属性を持つかどうか |
|
|
136
|
+
| `childNodes` | `readonly MLASTChildNode[]` | この要素の直接の子ノード |
|
|
137
|
+
| `blockBehavior` | `MLASTBlockBehavior \| null` | この要素に関連するブロック動作(ある場合) |
|
|
138
|
+
| `pairNode` | `MLASTElementCloseTag \| null` | 対応する閉じタグ、void/自己閉じ要素の場合は `null` |
|
|
139
|
+
| `tagOpenChar` | `string` | タグを開く文字(通常 `"<"`) |
|
|
140
|
+
| `tagCloseChar` | `string` | タグを閉じる文字(通常 `">"`) |
|
|
141
|
+
| `isGhost` | `boolean` | ゴーストノード(パーサーが推定した省略タグ)かどうか |
|
|
143
142
|
|
|
144
143
|
### 要素タイプの分類
|
|
145
144
|
|
|
@@ -256,34 +255,37 @@ void 要素(`<br>`、`<img>` など)と自己閉じ要素の場合、`pairNo
|
|
|
256
255
|
|
|
257
256
|
**役割:** テンプレートエンジンやフレームワークの制御フロー・反復構文を表します。標準 HTML には存在しないが、Svelte、Vue、EJS、ERB などのプリプロセッサで使用される構文です。
|
|
258
257
|
|
|
259
|
-
| フィールド
|
|
260
|
-
|
|
|
261
|
-
| `type`
|
|
262
|
-
| `
|
|
263
|
-
| `depth`
|
|
264
|
-
| `nodeName`
|
|
265
|
-
| `isFragment`
|
|
266
|
-
| `childNodes`
|
|
267
|
-
| `isBogus`
|
|
268
|
-
|
|
269
|
-
###
|
|
270
|
-
|
|
271
|
-
`
|
|
272
|
-
|
|
273
|
-
|
|
|
274
|
-
|
|
|
275
|
-
| `'if'`
|
|
276
|
-
| `'if:elseif'`
|
|
277
|
-
| `'if:else'`
|
|
278
|
-
| `'switch:case'`
|
|
279
|
-
| `'switch:default'`
|
|
280
|
-
| `'each'`
|
|
281
|
-
| `'each:empty'`
|
|
282
|
-
| `'await'`
|
|
283
|
-
| `'await:then'`
|
|
284
|
-
| `'await:catch'`
|
|
285
|
-
| `'end'`
|
|
286
|
-
|
|
258
|
+
| フィールド | 型 | 説明 |
|
|
259
|
+
| --------------- | ---------------------------- | ---------------------------------------------------- |
|
|
260
|
+
| `type` | `'psblock'` | 判別タグ |
|
|
261
|
+
| `blockBehavior` | `MLASTBlockBehavior \| null` | ブロックの制御フロー構文の動作を記述する(ある場合) |
|
|
262
|
+
| `depth` | `number` | ドキュメントツリーでのネストの深さ |
|
|
263
|
+
| `nodeName` | `string` | パーサーが決定したブロック名 |
|
|
264
|
+
| `isFragment` | `boolean` | 透過的なフラグメントとして機能するか |
|
|
265
|
+
| `childNodes` | `readonly MLASTChildNode[]` | このブロック内の直接の子ノード |
|
|
266
|
+
| `isBogus` | `boolean` | ボーガス(パース不能・不正形式)かどうか |
|
|
267
|
+
|
|
268
|
+
### ブロック動作の種別
|
|
269
|
+
|
|
270
|
+
`blockBehavior` フィールドは `MLASTBlockBehavior` オブジェクト(制御フローセマンティクスを持たないブロックの場合は `null`)です。存在する場合、`blockBehavior.type` はブロックのセマンティックな役割を示し、`blockBehavior.expression` は構文を駆動するソース式を含みます:
|
|
271
|
+
|
|
272
|
+
| `blockBehavior.type` | 説明 | 例(Svelte) | 例(EJS/ERB) |
|
|
273
|
+
| -------------------- | -------------------------- | ----------------------- | ------------------- |
|
|
274
|
+
| `'if'` | 条件分岐(開始) | `{#if condition}` | `<% if (x) { %>` |
|
|
275
|
+
| `'if:elseif'` | 代替条件分岐 | `{:else if condition}` | `<% } else if { %>` |
|
|
276
|
+
| `'if:else'` | デフォルト(else)分岐 | `{:else}` | `<% } else { %>` |
|
|
277
|
+
| `'switch:case'` | switch case 分岐 | -- | -- |
|
|
278
|
+
| `'switch:default'` | switch default 分岐 | -- | -- |
|
|
279
|
+
| `'each'` | 反復(ループ)ブロック | `{#each items as item}` | `<% for (...) { %>` |
|
|
280
|
+
| `'each:empty'` | 反復ブロックの空状態 | `{:else}`(`#each` 内) | -- |
|
|
281
|
+
| `'await'` | 非同期ブロック(保留状態) | `{#await promise}` | -- |
|
|
282
|
+
| `'await:then'` | 非同期ブロックの解決状態 | `{:then value}` | -- |
|
|
283
|
+
| `'await:catch'` | 非同期ブロックの拒否状態 | `{:catch error}` | -- |
|
|
284
|
+
| `'end'` | 閉じブロック | `{/if}`, `{/each}` | `<% } %>` |
|
|
285
|
+
|
|
286
|
+
`blockBehavior` が `null` の場合、ブロックには特定の制御フローセマンティクスがありません(例:EJS の `<%= expr %>` は純粋な式出力です)。
|
|
287
|
+
|
|
288
|
+
`MLASTBlockBehavior` の `expression` フィールドには、ブロックに関連するソース式が格納されます(例:Svelte の if ブロックでは `'{#if loggedIn}'`)。
|
|
287
289
|
|
|
288
290
|
### フレームワーク固有の例
|
|
289
291
|
|
|
@@ -299,9 +301,9 @@ void 要素(`<br>`、`<img>` など)と自己閉じ要素の場合、`pairNo
|
|
|
299
301
|
|
|
300
302
|
3つの `psblock` ノードが生成されます:
|
|
301
303
|
|
|
302
|
-
1. `
|
|
303
|
-
2. `
|
|
304
|
-
3. `
|
|
304
|
+
1. `blockBehavior: { type: 'if', expression: '{#if loggedIn}' }`:`{#if loggedIn}`
|
|
305
|
+
2. `blockBehavior: { type: 'if:else', expression: '{:else}' }`:`{:else}`
|
|
306
|
+
3. `blockBehavior: { type: 'end', expression: '{/if}' }`:`{/if}`
|
|
305
307
|
|
|
306
308
|
**Vue(v-if ディレクティブは異なる方法で処理されます -- psblock ではなく要素属性経由)。**
|
|
307
309
|
|
|
@@ -315,9 +317,9 @@ void 要素(`<br>`、`<img>` など)と自己閉じ要素の場合、`pairNo
|
|
|
315
317
|
|
|
316
318
|
生成されるノード:
|
|
317
319
|
|
|
318
|
-
1. `
|
|
319
|
-
2. `
|
|
320
|
-
3. `
|
|
320
|
+
1. `blockBehavior: { type: 'if', expression: '<% if (user) { %>' }`:`<% if (user) { %>`
|
|
321
|
+
2. `blockBehavior: { type: 'end', expression: '<% } %>' }`:`<% } %>`
|
|
322
|
+
3. `blockBehavior: null`:`<%= user.name %>`(式出力、制御フローセマンティクスなし)
|
|
321
323
|
|
|
322
324
|
## MLASTInvalid
|
|
323
325
|
|
|
@@ -412,7 +414,7 @@ void 要素(`<br>`、`<img>` など)と自己閉じ要素の場合、`pairNo
|
|
|
412
414
|
| `type` | `'spread'` | 判別タグ |
|
|
413
415
|
| `nodeName` | `'#spread'` | 常に `'#spread'` |
|
|
414
416
|
|
|
415
|
-
`MLASTSpreadAttr` は `MLASTAbstractNode` ではなく `MLASTToken` を直接継承するため、位置情報(`uuid`、`raw`、`
|
|
417
|
+
`MLASTSpreadAttr` は `MLASTAbstractNode` ではなく `MLASTToken` を直接継承するため、位置情報(`uuid`、`raw`、`offset` など)はありますが、`parentNode` や `depth` はありません。
|
|
416
418
|
|
|
417
419
|
## 共用体型リファレンス
|
|
418
420
|
|
|
@@ -449,7 +451,7 @@ function processChild(node: MLASTChildNode) {
|
|
|
449
451
|
console.log(`コメント (bogus: ${node.isBogus})`);
|
|
450
452
|
break;
|
|
451
453
|
case 'psblock':
|
|
452
|
-
console.log(`ブロック: ${node.nodeName},
|
|
454
|
+
console.log(`ブロック: ${node.nodeName}, behavior: ${node.blockBehavior?.type ?? 'none'}`);
|
|
453
455
|
break;
|
|
454
456
|
case 'invalid':
|
|
455
457
|
console.log(`不正: kind=${node.kind}`);
|
package/docs/node-reference.md
CHANGED
|
@@ -61,18 +61,17 @@ The mapping is performed by `createNode()` in `ml-core`:
|
|
|
61
61
|
|
|
62
62
|
The foundational interface for all positional information. Every AST node and sub-token extends this.
|
|
63
63
|
|
|
64
|
-
| Field
|
|
65
|
-
|
|
|
66
|
-
| `uuid`
|
|
67
|
-
| `raw`
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
**Coordinate system:** Offsets are zero-based (counting from 0), while lines and columns are one-based (counting from 1). This matches the conventions used by most text editors and error reporters.
|
|
64
|
+
| Field | Type | Description |
|
|
65
|
+
| -------- | -------- | ---------------------------------------------- |
|
|
66
|
+
| `uuid` | `string` | Unique identifier for this token instance |
|
|
67
|
+
| `raw` | `string` | The original raw source text |
|
|
68
|
+
| `offset` | `number` | Zero-based character offset of the token start |
|
|
69
|
+
| `line` | `number` | One-based line number where the token starts |
|
|
70
|
+
| `col` | `number` | One-based column number where the token starts |
|
|
71
|
+
|
|
72
|
+
End positions can be derived: `endOffset = offset + raw.length`. For `endLine` and `endCol`, use the helper functions from `@markuplint/parser-utils`.
|
|
73
|
+
|
|
74
|
+
**Coordinate system:** `offset` is zero-based (counting from 0), while `line` and `col` are one-based (counting from 1).
|
|
76
75
|
|
|
77
76
|
### MLASTAbstractNode
|
|
78
77
|
|
|
@@ -125,21 +124,21 @@ Produces a node with `name: "html"`, `publicId: ""`, `systemId: ""`.
|
|
|
125
124
|
|
|
126
125
|
**Role:** Represents an opening element tag (e.g., `<div class="foo">`). This is the primary element representation in the AST and is the most feature-rich node type. It owns child nodes, attributes, and maintains a reference to its matching closing tag.
|
|
127
126
|
|
|
128
|
-
| Field
|
|
129
|
-
|
|
|
130
|
-
| `type`
|
|
131
|
-
| `depth`
|
|
132
|
-
| `namespace`
|
|
133
|
-
| `elementType`
|
|
134
|
-
| `isFragment`
|
|
135
|
-
| `attributes`
|
|
136
|
-
| `hasSpreadAttr`
|
|
137
|
-
| `childNodes`
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `tagOpenChar`
|
|
141
|
-
| `tagCloseChar`
|
|
142
|
-
| `isGhost`
|
|
127
|
+
| Field | Type | Description |
|
|
128
|
+
| --------------- | ------------------------------ | --------------------------------------------------------------------------- |
|
|
129
|
+
| `type` | `'starttag'` | Discriminant tag |
|
|
130
|
+
| `depth` | `number` | Nesting depth in the document tree |
|
|
131
|
+
| `namespace` | `string` | Namespace URI (e.g., `"http://www.w3.org/1999/xhtml"`) |
|
|
132
|
+
| `elementType` | `ElementType` | Whether the element is `'html'`, `'web-component'`, or `'authored'` |
|
|
133
|
+
| `isFragment` | `boolean` | Whether the element acts as a fragment (e.g., React `<>`, Vue `<template>`) |
|
|
134
|
+
| `attributes` | `readonly MLASTAttr[]` | Attributes on this element |
|
|
135
|
+
| `hasSpreadAttr` | `boolean \| undefined` | Whether the element has one or more spread attributes |
|
|
136
|
+
| `childNodes` | `readonly MLASTChildNode[]` | Direct child nodes of this element |
|
|
137
|
+
| `blockBehavior` | `MLASTBlockBehavior \| null` | Block behavior associated with this element, if any |
|
|
138
|
+
| `pairNode` | `MLASTElementCloseTag \| null` | The matching closing tag, or `null` for void/self-closing elements |
|
|
139
|
+
| `tagOpenChar` | `string` | The characters that open this tag (usually `"<"`) |
|
|
140
|
+
| `tagCloseChar` | `string` | The characters that close this tag (usually `">"`) |
|
|
141
|
+
| `isGhost` | `boolean` | Whether this is a ghost node (omitted tag inferred by the parser) |
|
|
143
142
|
|
|
144
143
|
### Element Type Classification
|
|
145
144
|
|
|
@@ -256,34 +255,37 @@ The text `Hello, world!` is represented as an `MLASTText` node with `raw: "Hello
|
|
|
256
255
|
|
|
257
256
|
**Role:** Represents control-flow and iteration constructs from template engines and frameworks. These are syntax constructs that do not exist in standard HTML but are used by preprocessors like Svelte, Vue, EJS, ERB, and others.
|
|
258
257
|
|
|
259
|
-
| Field
|
|
260
|
-
|
|
|
261
|
-
| `type`
|
|
262
|
-
| `
|
|
263
|
-
| `depth`
|
|
264
|
-
| `nodeName`
|
|
265
|
-
| `isFragment`
|
|
266
|
-
| `childNodes`
|
|
267
|
-
| `isBogus`
|
|
268
|
-
|
|
269
|
-
###
|
|
270
|
-
|
|
271
|
-
The `
|
|
272
|
-
|
|
273
|
-
|
|
|
274
|
-
|
|
|
275
|
-
| `'if'`
|
|
276
|
-
| `'if:elseif'`
|
|
277
|
-
| `'if:else'`
|
|
278
|
-
| `'switch:case'`
|
|
279
|
-
| `'switch:default'`
|
|
280
|
-
| `'each'`
|
|
281
|
-
| `'each:empty'`
|
|
282
|
-
| `'await'`
|
|
283
|
-
| `'await:then'`
|
|
284
|
-
| `'await:catch'`
|
|
285
|
-
| `'end'`
|
|
286
|
-
|
|
258
|
+
| Field | Type | Description |
|
|
259
|
+
| --------------- | ---------------------------- | ------------------------------------------------------------ |
|
|
260
|
+
| `type` | `'psblock'` | Discriminant tag |
|
|
261
|
+
| `blockBehavior` | `MLASTBlockBehavior \| null` | Block behavior describing the control-flow construct, if any |
|
|
262
|
+
| `depth` | `number` | Nesting depth in the document tree |
|
|
263
|
+
| `nodeName` | `string` | The block's name as determined by the parser |
|
|
264
|
+
| `isFragment` | `boolean` | Whether this block acts as a transparent fragment |
|
|
265
|
+
| `childNodes` | `readonly MLASTChildNode[]` | Direct child nodes within this block |
|
|
266
|
+
| `isBogus` | `boolean` | Whether this block is bogus (unparsable or malformed) |
|
|
267
|
+
|
|
268
|
+
### Block Behavior Types
|
|
269
|
+
|
|
270
|
+
The `blockBehavior` field is an `MLASTBlockBehavior` object (or `null` for blocks with no control-flow semantic). When present, `blockBehavior.type` indicates the semantic role of the block, and `blockBehavior.expression` contains the source expression that drives the construct:
|
|
271
|
+
|
|
272
|
+
| `blockBehavior.type` | Description | Example (Svelte) | Example (EJS/ERB) |
|
|
273
|
+
| -------------------- | ---------------------------------- | ----------------------- | ------------------- |
|
|
274
|
+
| `'if'` | Conditional branch (opening) | `{#if condition}` | `<% if (x) { %>` |
|
|
275
|
+
| `'if:elseif'` | Alternative conditional branch | `{:else if condition}` | `<% } else if { %>` |
|
|
276
|
+
| `'if:else'` | Default (else) branch | `{:else}` | `<% } else { %>` |
|
|
277
|
+
| `'switch:case'` | Switch case branch | -- | -- |
|
|
278
|
+
| `'switch:default'` | Switch default branch | -- | -- |
|
|
279
|
+
| `'each'` | Iteration (loop) block | `{#each items as item}` | `<% for (...) { %>` |
|
|
280
|
+
| `'each:empty'` | Empty state for an iteration block | `{:else}` (in `#each`) | -- |
|
|
281
|
+
| `'await'` | Asynchronous block (pending state) | `{#await promise}` | -- |
|
|
282
|
+
| `'await:then'` | Resolved state of an async block | `{:then value}` | -- |
|
|
283
|
+
| `'await:catch'` | Rejected state of an async block | `{:catch error}` | -- |
|
|
284
|
+
| `'end'` | Closing block | `{/if}`, `{/each}` | `<% } %>` |
|
|
285
|
+
|
|
286
|
+
When `blockBehavior` is `null`, the block has no specific control-flow semantic (e.g., `<%= expr %>` in EJS is a pure expression output).
|
|
287
|
+
|
|
288
|
+
The `expression` field in `MLASTBlockBehavior` contains the raw source expression associated with the block (e.g., `'{#if loggedIn}'` for a Svelte if-block).
|
|
287
289
|
|
|
288
290
|
### Framework-Specific Examples
|
|
289
291
|
|
|
@@ -299,9 +301,9 @@ The `conditionalType` field indicates the semantic role of the block:
|
|
|
299
301
|
|
|
300
302
|
Produces three `psblock` nodes:
|
|
301
303
|
|
|
302
|
-
1. `
|
|
303
|
-
2. `
|
|
304
|
-
3. `
|
|
304
|
+
1. `blockBehavior: { type: 'if', expression: '{#if loggedIn}' }` for `{#if loggedIn}`
|
|
305
|
+
2. `blockBehavior: { type: 'if:else', expression: '{:else}' }` for `{:else}`
|
|
306
|
+
3. `blockBehavior: { type: 'end', expression: '{/if}' }` for `{/if}`
|
|
305
307
|
|
|
306
308
|
**Vue (v-if directive is handled differently -- via element attributes, not psblock).**
|
|
307
309
|
|
|
@@ -315,9 +317,9 @@ Produces three `psblock` nodes:
|
|
|
315
317
|
|
|
316
318
|
Produces:
|
|
317
319
|
|
|
318
|
-
1. `
|
|
319
|
-
2. `
|
|
320
|
-
3. `
|
|
320
|
+
1. `blockBehavior: { type: 'if', expression: '<% if (user) { %>' }` for `<% if (user) { %>`
|
|
321
|
+
2. `blockBehavior: { type: 'end', expression: '<% } %>' }` for `<% } %>`
|
|
322
|
+
3. `blockBehavior: null` for `<%= user.name %>` (expression output, no control-flow semantic)
|
|
321
323
|
|
|
322
324
|
## MLASTInvalid
|
|
323
325
|
|
|
@@ -412,7 +414,7 @@ These fields are set by framework-specific parsers:
|
|
|
412
414
|
| `type` | `'spread'` | Discriminant tag |
|
|
413
415
|
| `nodeName` | `'#spread'` | Always `'#spread'` |
|
|
414
416
|
|
|
415
|
-
Note that `MLASTSpreadAttr` extends `MLASTToken` directly (not `MLASTAbstractNode`), so it has positional information (`uuid`, `raw`, `
|
|
417
|
+
Note that `MLASTSpreadAttr` extends `MLASTToken` directly (not `MLASTAbstractNode`), so it has positional information (`uuid`, `raw`, `offset`, etc.) but no `parentNode` or `depth`.
|
|
416
418
|
|
|
417
419
|
## Union Types Reference
|
|
418
420
|
|
|
@@ -449,7 +451,7 @@ function processChild(node: MLASTChildNode) {
|
|
|
449
451
|
console.log(`Comment (bogus: ${node.isBogus})`);
|
|
450
452
|
break;
|
|
451
453
|
case 'psblock':
|
|
452
|
-
console.log(`Block: ${node.nodeName},
|
|
454
|
+
console.log(`Block: ${node.nodeName}, behavior: ${node.blockBehavior?.type ?? 'none'}`);
|
|
453
455
|
break;
|
|
454
456
|
case 'invalid':
|
|
455
457
|
console.log(`Invalid: kind=${node.kind}`);
|
package/lib/types.d.ts
CHANGED
|
@@ -48,6 +48,10 @@ export type MLASTAttr = MLASTHTMLAttr | MLASTSpreadAttr;
|
|
|
48
48
|
/**
|
|
49
49
|
* Base token representing a span of source text with positional information.
|
|
50
50
|
* Every AST node ultimately extends this interface.
|
|
51
|
+
*
|
|
52
|
+
* End positions (`endOffset`, `endLine`, `endCol`) are not stored;
|
|
53
|
+
* they can be derived from `offset + raw.length`, or via helper utilities
|
|
54
|
+
* in `@markuplint/parser-utils`.
|
|
51
55
|
*/
|
|
52
56
|
export interface MLASTToken {
|
|
53
57
|
/** Unique identifier for this token instance */
|
|
@@ -55,17 +59,11 @@ export interface MLASTToken {
|
|
|
55
59
|
/** The original raw source text of this token */
|
|
56
60
|
readonly raw: string;
|
|
57
61
|
/** Zero-based character offset of the token start in the source */
|
|
58
|
-
readonly
|
|
59
|
-
/** Zero-based character offset of the token end in the source */
|
|
60
|
-
readonly endOffset: number;
|
|
62
|
+
readonly offset: number;
|
|
61
63
|
/** One-based line number where the token starts */
|
|
62
|
-
readonly
|
|
63
|
-
/** One-based line number where the token ends */
|
|
64
|
-
readonly endLine: number;
|
|
64
|
+
readonly line: number;
|
|
65
65
|
/** One-based column number where the token starts */
|
|
66
|
-
readonly
|
|
67
|
-
/** One-based column number where the token ends */
|
|
68
|
-
readonly endCol: number;
|
|
66
|
+
readonly col: number;
|
|
69
67
|
}
|
|
70
68
|
/**
|
|
71
69
|
* Abstract base for all AST nodes. Extends {@link MLASTToken} with
|
|
@@ -103,7 +101,7 @@ export interface MLASTElement extends MLASTAbstractNode {
|
|
|
103
101
|
/** Nesting depth in the document tree */
|
|
104
102
|
readonly depth: number;
|
|
105
103
|
/** Namespace URI of the element (e.g. `"http://www.w3.org/1999/xhtml"`) */
|
|
106
|
-
readonly namespace:
|
|
104
|
+
readonly namespace: NamespaceURI;
|
|
107
105
|
/** Whether the element is native HTML, a Web Component, or an authored component */
|
|
108
106
|
readonly elementType: ElementType;
|
|
109
107
|
/** Whether this element acts as a fragment (no actual DOM node) */
|
|
@@ -114,10 +112,10 @@ export interface MLASTElement extends MLASTAbstractNode {
|
|
|
114
112
|
readonly hasSpreadAttr?: boolean;
|
|
115
113
|
/** Direct child nodes of this element */
|
|
116
114
|
readonly childNodes: readonly MLASTChildNode[];
|
|
115
|
+
/** Block behavior associated with this element, if any */
|
|
116
|
+
readonly blockBehavior: MLASTBlockBehavior | null;
|
|
117
117
|
/** The matching closing tag, or `null` for void / self-closing elements */
|
|
118
118
|
readonly pairNode: MLASTElementCloseTag | null;
|
|
119
|
-
/** The self-closing solidus token (`/`), if present (e.g. `<br />`) */
|
|
120
|
-
readonly selfClosingSolidus?: MLASTToken;
|
|
121
119
|
/** The characters that open this tag (usually `"<"`) */
|
|
122
120
|
readonly tagOpenChar: string;
|
|
123
121
|
/** The characters that close this tag (usually `">"`) */
|
|
@@ -149,8 +147,6 @@ export interface MLASTElementCloseTag extends MLASTAbstractNode {
|
|
|
149
147
|
*/
|
|
150
148
|
export interface MLASTPreprocessorSpecificBlock extends MLASTAbstractNode {
|
|
151
149
|
readonly type: 'psblock';
|
|
152
|
-
/** The kind of conditional or iteration construct this block represents */
|
|
153
|
-
readonly conditionalType: MLASTPreprocessorSpecificBlockConditionalType;
|
|
154
150
|
/** Nesting depth in the document tree */
|
|
155
151
|
readonly depth: number;
|
|
156
152
|
/** The block's name as determined by the parser */
|
|
@@ -159,15 +155,26 @@ export interface MLASTPreprocessorSpecificBlock extends MLASTAbstractNode {
|
|
|
159
155
|
readonly isFragment: boolean;
|
|
160
156
|
/** Direct child nodes within this block */
|
|
161
157
|
readonly childNodes: readonly MLASTChildNode[];
|
|
158
|
+
/** Block behavior associated with this block, if any */
|
|
159
|
+
readonly blockBehavior: MLASTBlockBehavior | null;
|
|
162
160
|
/** Whether this block is bogus (unparsable or malformed) */
|
|
163
161
|
readonly isBogus: boolean;
|
|
164
162
|
}
|
|
165
163
|
/**
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
164
|
+
* Describes the behavior of a preprocessor block or element,
|
|
165
|
+
* capturing both the kind of control-flow construct and the
|
|
166
|
+
* source expression that drives it.
|
|
167
|
+
*/
|
|
168
|
+
export interface MLASTBlockBehavior {
|
|
169
|
+
/** The kind of block behavior (e.g. `'if'`, `'each'`, `'await'`) */
|
|
170
|
+
readonly type: MLASTBlockBehaviorType;
|
|
171
|
+
/** The source expression associated with this block */
|
|
172
|
+
readonly expression: string;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The type of control-flow construct represented by a block behavior.
|
|
169
176
|
*/
|
|
170
|
-
export type
|
|
177
|
+
export type MLASTBlockBehaviorType = 'if' | 'if:elseif' | 'if:else' | 'switch:case' | 'switch:default' | 'each' | 'each:empty' | 'await' | 'await:then' | 'await:catch' | 'end';
|
|
171
178
|
/**
|
|
172
179
|
* An HTML comment node (e.g. `<!-- ... -->`).
|
|
173
180
|
*/
|
|
@@ -262,37 +269,6 @@ export interface MLASTDocument {
|
|
|
262
269
|
/** A description of any unknown parse error that occurred, if any */
|
|
263
270
|
readonly unknownParseError?: string;
|
|
264
271
|
}
|
|
265
|
-
/**
|
|
266
|
-
* @deprecated Use `MLParser` instead. This will be dropped in v5.
|
|
267
|
-
*/
|
|
268
|
-
export interface MLMarkupLanguageParser {
|
|
269
|
-
/**
|
|
270
|
-
* @deprecated
|
|
271
|
-
*/
|
|
272
|
-
parse(sourceCode: string, options?: ParserOptions & {
|
|
273
|
-
readonly offsetOffset?: number;
|
|
274
|
-
readonly offsetLine?: number;
|
|
275
|
-
readonly offsetColumn?: number;
|
|
276
|
-
}): MLASTDocument;
|
|
277
|
-
/**
|
|
278
|
-
* @default "omittable"
|
|
279
|
-
* @deprecated
|
|
280
|
-
*/
|
|
281
|
-
endTag?: EndTagType;
|
|
282
|
-
/**
|
|
283
|
-
* Detect value as a true if its attribute is booleanish value and omitted.
|
|
284
|
-
*
|
|
285
|
-
* Ex:
|
|
286
|
-
* ```jsx
|
|
287
|
-
* <Component aria-hidden />
|
|
288
|
-
* ```
|
|
289
|
-
*
|
|
290
|
-
* In the above, the `aria-hidden` is `true`.
|
|
291
|
-
*
|
|
292
|
-
* @deprecated
|
|
293
|
-
*/
|
|
294
|
-
booleanish?: boolean;
|
|
295
|
-
}
|
|
296
272
|
/**
|
|
297
273
|
* Interface for a markuplint-compatible parser.
|
|
298
274
|
* Implementations parse markup source code and produce an {@link MLASTDocument}.
|
|
@@ -358,10 +334,6 @@ export type ParserAuthoredElementNameDistinguishing = string | Readonly<RegExp>
|
|
|
358
334
|
* @returns `true` if the name represents an authored element
|
|
359
335
|
*/
|
|
360
336
|
export type ParserAuthoredElementNameDistinguishingFunction = (name: string) => boolean;
|
|
361
|
-
/**
|
|
362
|
-
* @deprecated
|
|
363
|
-
*/
|
|
364
|
-
export type Parse = MLMarkupLanguageParser['parse'];
|
|
365
337
|
/**
|
|
366
338
|
* Callback function used for walking through AST nodes.
|
|
367
339
|
*
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/ml-ast",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0-alpha.0",
|
|
4
4
|
"description": "The markuplint AST types.",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
7
7
|
"license": "MIT",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=22"
|
|
10
|
+
},
|
|
8
11
|
"type": "module",
|
|
9
12
|
"exports": {
|
|
10
13
|
".": {
|
|
@@ -23,5 +26,5 @@
|
|
|
23
26
|
"dev": "tsc --watch --project tsconfig.build.json",
|
|
24
27
|
"clean": "tsc --build --clean tsconfig.build.json"
|
|
25
28
|
},
|
|
26
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "13dcfc84ec83d87360c720e253383b60767e1b56"
|
|
27
30
|
}
|