@markuplint/astro-parser 5.0.0-dev.5 → 5.0.0-rc.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 +24 -57
- package/ARCHITECTURE.md +32 -65
- package/CHANGELOG.md +4 -0
- package/SKILL.md +6 -6
- package/docs/maintenance.ja.md +10 -21
- package/docs/maintenance.md +10 -21
- package/package.json +5 -5
package/ARCHITECTURE.ja.md
CHANGED
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## 概要
|
|
4
4
|
|
|
5
|
-
`@markuplint/astro-parser` は markuplint における Astro コンポーネントファイル(`.astro`)のパーサーです。`astro-eslint-parser`(`@astrojs/compiler` をラップ)を使用して Astro ソースコードをトークン化し、その結果の AST を markuplint の統一 AST 形式(`MLASTDocument`)に変換します。フロントマターブロック(`---...---`)、式コンテナ(`{expression}`)、テンプレートディレクティブ(例: `class:list`、`set:html`)、ショートハンド属性(`{prop}
|
|
5
|
+
`@markuplint/astro-parser` は markuplint における Astro コンポーネントファイル(`.astro`)のパーサーです。`astro-eslint-parser`(`@astrojs/compiler` をラップ)を使用して Astro ソースコードをトークン化し、その結果の AST を markuplint の統一 AST 形式(`MLASTDocument`)に変換します。フロントマターブロック(`---...---`)、式コンテナ(`{expression}`)、テンプレートディレクティブ(例: `class:list`、`set:html`、`client:load`)、ショートハンド属性(`{prop}`)など、Astro 固有の構文を処理します。
|
|
6
6
|
|
|
7
7
|
## ディレクトリ構成
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
src/
|
|
11
|
-
├── index.ts
|
|
12
|
-
├── parser.ts
|
|
13
|
-
├── astro-parser.ts
|
|
14
|
-
├──
|
|
15
|
-
|
|
11
|
+
├── index.ts — parser インスタンスを再エクスポート
|
|
12
|
+
├── parser.ts — Parser<Node> を拡張する AstroParser クラス
|
|
13
|
+
├── astro-parser.ts — astro-eslint-parser ラッパーと型の再エクスポート
|
|
14
|
+
├── detect-block-behavior.ts — .map()/.filter() のブロック動作検出
|
|
15
|
+
├── parser.spec.ts — AstroParser 統合テスト
|
|
16
|
+
└── astro-parser.spec.ts — astro-eslint-parser ラッパーテスト
|
|
16
17
|
```
|
|
17
18
|
|
|
18
19
|
## アーキテクチャ図
|
|
@@ -27,8 +28,9 @@ flowchart TD
|
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
subgraph pkg ["@markuplint/astro-parser"]
|
|
30
|
-
astroParser["AstroParser\nextends Parser‹Node
|
|
31
|
+
astroParser["AstroParser\nextends Parser‹Node›"]
|
|
31
32
|
astroParseFn["astroParse()\nastro-eslint-parser ラッパー"]
|
|
33
|
+
detectBlock["detectBlockBehavior()\n.map()/.filter() 検出"]
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
subgraph downstream ["下流"]
|
|
@@ -40,6 +42,7 @@ flowchart TD
|
|
|
40
42
|
astroEslintParser -->|"parseTemplate()"| astroParseFn
|
|
41
43
|
astroCompiler -->|"Node 型"| astroParseFn
|
|
42
44
|
astroParseFn -->|"RootNode.children"| astroParser
|
|
45
|
+
detectBlock -->|"blockBehavior"| astroParser
|
|
43
46
|
astroParser -->|"MLASTDocument を生成"| mlCore
|
|
44
47
|
```
|
|
45
48
|
|
|
@@ -48,7 +51,7 @@ flowchart TD
|
|
|
48
51
|
### 継承関係
|
|
49
52
|
|
|
50
53
|
```
|
|
51
|
-
Parser<Node
|
|
54
|
+
Parser<Node> (@markuplint/parser-utils)
|
|
52
55
|
└── AstroParser (このパッケージ)
|
|
53
56
|
```
|
|
54
57
|
|
|
@@ -62,16 +65,6 @@ Parser<Node, State> (@markuplint/parser-utils)
|
|
|
62
65
|
| `selfCloseType` | `'html+xml'` | HTML void 要素と XML スタイルの自己閉じ(`<Component />`)の両方を受け入れる |
|
|
63
66
|
| `tagNameCaseSensitive` | `true` | コンポーネント(`<MyComp>`)と HTML 要素(`<div>`)を区別 |
|
|
64
67
|
|
|
65
|
-
### State 型
|
|
66
|
-
|
|
67
|
-
パーサーは `State` 型を通じて内部状態を管理します:
|
|
68
|
-
|
|
69
|
-
| フィールド | 型 | 用途 |
|
|
70
|
-
| ---------- | -------- | --------------------------------------------------------------- |
|
|
71
|
-
| `scopeNS` | `string` | 現在の名前空間 URI、デフォルトは `http://www.w3.org/1999/xhtml` |
|
|
72
|
-
|
|
73
|
-
`scopeNS` 状態は `#updateScopeNS()` によってパーサーが要素を走査する際に更新され、`<svg>` 要素内で SVG 名前空間に切り替わり、`<foreignObject>` 内で XHTML に戻ります。
|
|
74
|
-
|
|
75
68
|
### オーバーライドメソッド
|
|
76
69
|
|
|
77
70
|
| メソッド | 用途 |
|
|
@@ -79,7 +72,7 @@ Parser<Node, State> (@markuplint/parser-utils)
|
|
|
79
72
|
| `tokenize()` | `astroParse()` を呼び出して Astro AST を取得し、`{ ast: rootNode.children, isFragment: true }` を返す |
|
|
80
73
|
| `nodeize()` | Astro AST ノードを markuplint ノードに変換。ノードタイプ(frontmatter, doctype, text, comment, element, expression)で振り分け |
|
|
81
74
|
| `afterFlattenNodes()` | `{ exposeInvalidNode: false }` で親に委譲 |
|
|
82
|
-
| `visitElement()` | `parseCodeFragment()` で `namelessFragment: true` として生の HTML
|
|
75
|
+
| `visitElement()` | `parseCodeFragment()` で `namelessFragment: true` として生の HTML フラグメントをパースし、終了タグ処理で親に委譲 |
|
|
83
76
|
| `visitChildren()` | 親に委譲した後、予期しない兄弟ノードが残っていないことをアサート |
|
|
84
77
|
| `visitAttr()` | 波括弧式の値、ショートハンド属性、テンプレートディレクティブを処理 |
|
|
85
78
|
| `detectElementType()` | `/^[A-Z]/` パターンでコンポーネントと HTML 要素を検出(大文字始まりの名前はコンポーネント) |
|
|
@@ -119,35 +112,6 @@ Astro の式(`{expression}`)は Astro AST で `type: 'expression'` ノード
|
|
|
119
112
|
- 最後の子の開始から式の終了までの領域が終了フラグメントになる
|
|
120
113
|
- 間の子は開始フラグメントの psblock 内で通常通り訪問される
|
|
121
114
|
|
|
122
|
-
## 名前空間スコーピング
|
|
123
|
-
|
|
124
|
-
`#updateScopeNS()` プライベートメソッドは、パーサーが要素を走査する際に名前空間コンテキストを管理します:
|
|
125
|
-
|
|
126
|
-
| 条件 | アクション |
|
|
127
|
-
| ----------------------------------------------------- | ---------------------------------------------------- |
|
|
128
|
-
| 現在の名前空間が XHTML で、ノードが `<svg>` 要素 | `scopeNS` を `http://www.w3.org/2000/svg` に切り替え |
|
|
129
|
-
| 現在の名前空間が SVG で、親ノードが `<foreignObject>` | `scopeNS` を `http://www.w3.org/1999/xhtml` に戻す |
|
|
130
|
-
|
|
131
|
-
これは `nodeize()` のノードタイプ switch の前に呼び出されるため、すべての子ノードが正しい名前空間を継承します。名前空間は `visitElement()` 内で `overwriteProps: { namespace: this.state.scopeNS }` を通じて要素に適用されます。
|
|
132
|
-
|
|
133
|
-
名前空間解決の例:
|
|
134
|
-
|
|
135
|
-
```html
|
|
136
|
-
<div>
|
|
137
|
-
<!-- XHTML -->
|
|
138
|
-
<svg>
|
|
139
|
-
<!-- SVG -->
|
|
140
|
-
<text />
|
|
141
|
-
<!-- SVG -->
|
|
142
|
-
<foreignObject>
|
|
143
|
-
<!-- SVG -->
|
|
144
|
-
<div />
|
|
145
|
-
<!-- XHTML(リセット) -->
|
|
146
|
-
</foreignObject>
|
|
147
|
-
</svg>
|
|
148
|
-
</div>
|
|
149
|
-
```
|
|
150
|
-
|
|
151
115
|
## 属性処理
|
|
152
116
|
|
|
153
117
|
### クォートセット
|
|
@@ -173,15 +137,18 @@ Astro の式(`{expression}`)は Astro AST で `type: 'expression'` ノード
|
|
|
173
137
|
|
|
174
138
|
Astro テンプレートディレクティブは `name:modifier` 構文を使用します。パーサーは正規表現 `/^([^:]+):([^:]+)$/` でこれらを検出します:
|
|
175
139
|
|
|
176
|
-
|
|
|
177
|
-
|
|
|
178
|
-
| `class
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
140
|
+
| ディレクティブプレフィックス | `potentialName` | `isDirective` | 動作 |
|
|
141
|
+
| ---------------------------- | --------------- | ------------- | ----------------------------------------------------- |
|
|
142
|
+
| `class:` | `'class'` | `false` | 標準の `class` 属性にマッピング |
|
|
143
|
+
| `client:` | — | `true` | Astro クライアントディレクティブ(load, idle 等) |
|
|
144
|
+
| `server:` | — | `true` | Astro サーバーディレクティブ(defer) |
|
|
145
|
+
| `set:` | — | `true` | コンテンツディレクティブ(html, text) |
|
|
146
|
+
| `is:` | — | `true` | プロパティディレクティブ(inline, raw) |
|
|
147
|
+
| `define:` | — | `true` | スタイルディレクティブ(vars) |
|
|
148
|
+
| `transition:` | — | `true` | View Transition ディレクティブ(animate, name) |
|
|
149
|
+
| _(その他すべて)_ | — | `true` | キャッチオール: すべての `prefix:name` パターンに適用 |
|
|
183
150
|
|
|
184
|
-
`class
|
|
151
|
+
`class:` プレフィックスは特別扱いで、`potentialName: 'class'` を取得するため、`class` 属性に対する markuplint ルールが適用されます。その他のコロン区切りプレフィックスは `default` ケースに該当し `isDirective: true` を取得します。これはフレームワーク固有であり標準 HTML 属性として検証すべきでないことを markuplint に伝えます。
|
|
185
152
|
|
|
186
153
|
### 動的な値
|
|
187
154
|
|
|
@@ -199,7 +166,7 @@ Astro テンプレートディレクティブは `name:modifier` 構文を使用
|
|
|
199
166
|
| **フロントマター** | サポート(`---...---` psblock) | 該当なし |
|
|
200
167
|
| **式の構文** | `{expr}` を MustacheTag psblock として | `{expr}` を JSXExpressionContainer psblock として |
|
|
201
168
|
| **テンプレートディレクティブ** | `class:list`、`set:html` 等 | 該当なし |
|
|
202
|
-
| **名前空間管理** |
|
|
169
|
+
| **名前空間管理** | 基底 `Parser` に委譲 | html-parser の `getNamespace()` に委譲 |
|
|
203
170
|
| **コンポーネント検出** | `/^[A-Z]/` パターン | `/^[A-Z]/` パターン |
|
|
204
171
|
| **自己閉じタイプ** | `html+xml` | デフォルト(XML のみ) |
|
|
205
172
|
| **booleanish 属性** | 未設定 | `booleanish: true` |
|
package/ARCHITECTURE.md
CHANGED
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
`@markuplint/astro-parser` is a parser for Astro component files (`.astro`) in markuplint. It uses `astro-eslint-parser` (which wraps `@astrojs/compiler`) to tokenize Astro source code, then converts the resulting AST into markuplint's unified AST format (`MLASTDocument`). The parser handles Astro-specific syntax including frontmatter blocks (`---...---`), expression containers (`{expression}`), template directives (e.g., `class:list`, `set:html`), shorthand attributes (`{prop}`)
|
|
5
|
+
`@markuplint/astro-parser` is a parser for Astro component files (`.astro`) in markuplint. It uses `astro-eslint-parser` (which wraps `@astrojs/compiler`) to tokenize Astro source code, then converts the resulting AST into markuplint's unified AST format (`MLASTDocument`). The parser handles Astro-specific syntax including frontmatter blocks (`---...---`), expression containers (`{expression}`), template directives (e.g., `class:list`, `set:html`, `client:load`), and shorthand attributes (`{prop}`).
|
|
6
6
|
|
|
7
7
|
## Directory Structure
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
src/
|
|
11
|
-
├── index.ts
|
|
12
|
-
├── parser.ts
|
|
13
|
-
├── astro-parser.ts
|
|
14
|
-
├──
|
|
15
|
-
|
|
11
|
+
├── index.ts — Re-exports parser instance
|
|
12
|
+
├── parser.ts — AstroParser class extending Parser<Node>
|
|
13
|
+
├── astro-parser.ts — astro-eslint-parser wrapper and type re-exports
|
|
14
|
+
├── detect-block-behavior.ts — Detects .map()/.filter() for block behavior
|
|
15
|
+
├── parser.spec.ts — AstroParser integration tests
|
|
16
|
+
└── astro-parser.spec.ts — astro-eslint-parser wrapper tests
|
|
16
17
|
```
|
|
17
18
|
|
|
18
19
|
## Architecture Diagram
|
|
@@ -27,8 +28,9 @@ flowchart TD
|
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
subgraph pkg ["@markuplint/astro-parser"]
|
|
30
|
-
astroParser["AstroParser\nextends Parser‹Node
|
|
31
|
+
astroParser["AstroParser\nextends Parser‹Node›"]
|
|
31
32
|
astroParseFn["astroParse()\nastro-eslint-parser wrapper"]
|
|
33
|
+
detectBlock["detectBlockBehavior()\n.map()/.filter() detection"]
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
subgraph downstream ["Downstream"]
|
|
@@ -40,6 +42,7 @@ flowchart TD
|
|
|
40
42
|
astroEslintParser -->|"parseTemplate()"| astroParseFn
|
|
41
43
|
astroCompiler -->|"Node types"| astroParseFn
|
|
42
44
|
astroParseFn -->|"RootNode.children"| astroParser
|
|
45
|
+
detectBlock -->|"blockBehavior"| astroParser
|
|
43
46
|
astroParser -->|"produces MLASTDocument"| mlCore
|
|
44
47
|
```
|
|
45
48
|
|
|
@@ -48,7 +51,7 @@ flowchart TD
|
|
|
48
51
|
### Inheritance
|
|
49
52
|
|
|
50
53
|
```
|
|
51
|
-
Parser<Node
|
|
54
|
+
Parser<Node> (from @markuplint/parser-utils)
|
|
52
55
|
└── AstroParser (this package)
|
|
53
56
|
```
|
|
54
57
|
|
|
@@ -62,27 +65,17 @@ The constructor configures the base `Parser` with Astro-specific options:
|
|
|
62
65
|
| `selfCloseType` | `'html+xml'` | Accepts both HTML void elements and XML-style self-closing (`<Component />`) |
|
|
63
66
|
| `tagNameCaseSensitive` | `true` | Distinguishes components (`<MyComp>`) from HTML elements (`<div>`) |
|
|
64
67
|
|
|
65
|
-
### State Type
|
|
66
|
-
|
|
67
|
-
The parser maintains internal state through the `State` type:
|
|
68
|
-
|
|
69
|
-
| Field | Type | Purpose |
|
|
70
|
-
| --------- | -------- | ----------------------------------------------------------------- |
|
|
71
|
-
| `scopeNS` | `string` | Current namespace URI, defaults to `http://www.w3.org/1999/xhtml` |
|
|
72
|
-
|
|
73
|
-
The `scopeNS` state is updated by `#updateScopeNS()` as the parser traverses elements, switching to SVG namespace inside `<svg>` elements and back to XHTML inside `<foreignObject>`.
|
|
74
|
-
|
|
75
68
|
### Override Methods
|
|
76
69
|
|
|
77
|
-
| Method | Purpose
|
|
78
|
-
| --------------------- |
|
|
79
|
-
| `tokenize()` | Calls `astroParse()` to get the Astro AST, returns `{ ast: rootNode.children, isFragment: true }`
|
|
80
|
-
| `nodeize()` | Converts Astro AST nodes to markuplint nodes, dispatching by node type (frontmatter, doctype, text, comment, element, expression)
|
|
81
|
-
| `afterFlattenNodes()` | Delegates to parent with `{ exposeInvalidNode: false }`
|
|
82
|
-
| `visitElement()` | Parses the raw HTML fragment via `parseCodeFragment()` with `namelessFragment: true`, then delegates to parent with
|
|
83
|
-
| `visitChildren()` | Delegates to parent, then asserts no unexpected sibling nodes remain
|
|
84
|
-
| `visitAttr()` | Handles curly-brace expression values, shorthand attributes, and template directives
|
|
85
|
-
| `detectElementType()` | Detects component vs HTML element using `/^[A-Z]/` pattern (capitalized names are components)
|
|
70
|
+
| Method | Purpose |
|
|
71
|
+
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
72
|
+
| `tokenize()` | Calls `astroParse()` to get the Astro AST, returns `{ ast: rootNode.children, isFragment: true }` |
|
|
73
|
+
| `nodeize()` | Converts Astro AST nodes to markuplint nodes, dispatching by node type (frontmatter, doctype, text, comment, element, expression) |
|
|
74
|
+
| `afterFlattenNodes()` | Delegates to parent with `{ exposeInvalidNode: false }` |
|
|
75
|
+
| `visitElement()` | Parses the raw HTML fragment via `parseCodeFragment()` with `namelessFragment: true`, then delegates to parent with end tag handling |
|
|
76
|
+
| `visitChildren()` | Delegates to parent, then asserts no unexpected sibling nodes remain |
|
|
77
|
+
| `visitAttr()` | Handles curly-brace expression values, shorthand attributes, and template directives |
|
|
78
|
+
| `detectElementType()` | Detects component vs HTML element using `/^[A-Z]/` pattern (capitalized names are components) |
|
|
86
79
|
|
|
87
80
|
## Frontmatter Handling
|
|
88
81
|
|
|
@@ -119,35 +112,6 @@ The splitting logic checks whether `firstChild !== lastChild` in the expression'
|
|
|
119
112
|
- The region from the last child's start to the expression end becomes the closing fragment
|
|
120
113
|
- The children between are visited normally within the opening fragment's psblock
|
|
121
114
|
|
|
122
|
-
## Namespace Scoping
|
|
123
|
-
|
|
124
|
-
The `#updateScopeNS()` private method manages namespace context as the parser traverses elements:
|
|
125
|
-
|
|
126
|
-
| Condition | Action |
|
|
127
|
-
| ------------------------------------------------------------- | ------------------------------------------------------- |
|
|
128
|
-
| Current namespace is XHTML and node is `<svg>` element | Switch `scopeNS` to `http://www.w3.org/2000/svg` |
|
|
129
|
-
| Current namespace is SVG and parent node is `<foreignObject>` | Switch `scopeNS` back to `http://www.w3.org/1999/xhtml` |
|
|
130
|
-
|
|
131
|
-
This is called at the beginning of `nodeize()` before the node type switch, so all child nodes inherit the correct namespace. The namespace is applied to elements via `overwriteProps: { namespace: this.state.scopeNS }` in `visitElement()`.
|
|
132
|
-
|
|
133
|
-
Example namespace resolution:
|
|
134
|
-
|
|
135
|
-
```html
|
|
136
|
-
<div>
|
|
137
|
-
<!-- XHTML -->
|
|
138
|
-
<svg>
|
|
139
|
-
<!-- SVG -->
|
|
140
|
-
<text />
|
|
141
|
-
<!-- SVG -->
|
|
142
|
-
<foreignObject>
|
|
143
|
-
<!-- SVG -->
|
|
144
|
-
<div />
|
|
145
|
-
<!-- XHTML (reset) -->
|
|
146
|
-
</foreignObject>
|
|
147
|
-
</svg>
|
|
148
|
-
</div>
|
|
149
|
-
```
|
|
150
|
-
|
|
151
115
|
## Attribute Processing
|
|
152
116
|
|
|
153
117
|
### Quote Set
|
|
@@ -173,15 +137,18 @@ When an attribute token starts with `{` (e.g., `{prop}`), the parser sets `start
|
|
|
173
137
|
|
|
174
138
|
Astro template directives use the `name:modifier` syntax. The parser detects these with the regex `/^([^:]+):([^:]+)$/`:
|
|
175
139
|
|
|
176
|
-
| Directive
|
|
177
|
-
|
|
|
178
|
-
| `class
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
140
|
+
| Directive prefix | `potentialName` | `isDirective` | Behavior |
|
|
141
|
+
| ---------------- | --------------- | ------------- | ----------------------------------------------- |
|
|
142
|
+
| `class:` | `'class'` | `false` | Maps to standard `class` attribute |
|
|
143
|
+
| `client:` | — | `true` | Astro client directive (load, idle, visible...) |
|
|
144
|
+
| `server:` | — | `true` | Astro server directive (defer) |
|
|
145
|
+
| `set:` | — | `true` | Content directive (html, text) |
|
|
146
|
+
| `is:` | — | `true` | Property directive (inline, raw) |
|
|
147
|
+
| `define:` | — | `true` | Style directive (vars) |
|
|
148
|
+
| `transition:` | — | `true` | View Transition directive (animate, name) |
|
|
149
|
+
| _(any other)_ | — | `true` | Catch-all: any `prefix:name` pattern |
|
|
183
150
|
|
|
184
|
-
The `class
|
|
151
|
+
The `class:` prefix is special-cased: it gets `potentialName: 'class'` so markuplint rules for the `class` attribute apply. All other colon-separated prefixes hit the `default` case and get `isDirective: true`, which tells markuplint they are framework-specific and should not be validated as standard HTML attributes.
|
|
185
152
|
|
|
186
153
|
### Dynamic Values
|
|
187
154
|
|
|
@@ -199,7 +166,7 @@ Any attribute whose start quote is `{` gets `isDynamicValue: true`. This applies
|
|
|
199
166
|
| **Frontmatter** | Supported (`---...---` psblock) | Not applicable |
|
|
200
167
|
| **Expression syntax** | `{expr}` as MustacheTag psblock | `{expr}` as JSXExpressionContainer psblock |
|
|
201
168
|
| **Template directives** | `class:list`, `set:html`, etc. | Not applicable |
|
|
202
|
-
| **Namespace management** |
|
|
169
|
+
| **Namespace management** | Delegates to base `Parser` | Delegates to `getNamespace()` from html-parser |
|
|
203
170
|
| **Component detection** | `/^[A-Z]/` pattern | `/^[A-Z]/` pattern |
|
|
204
171
|
| **Self-close type** | `html+xml` | Default (XML-only) |
|
|
205
172
|
| **Booleanish attributes** | Not configured | `booleanish: true` |
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
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-rc.0](https://github.com/markuplint/markuplint/compare/v5.0.0-alpha.3...v5.0.0-rc.0) (2026-03-12)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @markuplint/astro-parser
|
|
9
|
+
|
|
6
10
|
# [5.0.0-alpha.3](https://github.com/markuplint/markuplint/compare/v5.0.0-alpha.2...v5.0.0-alpha.3) (2026-02-26)
|
|
7
11
|
|
|
8
12
|
**Note:** Version bump only for package @markuplint/astro-parser
|
package/SKILL.md
CHANGED
|
@@ -29,7 +29,7 @@ for the full guide. The recipes there are the source of truth for procedures.
|
|
|
29
29
|
|
|
30
30
|
Also read:
|
|
31
31
|
|
|
32
|
-
- `ARCHITECTURE.md` -- Package overview, attribute processing,
|
|
32
|
+
- `ARCHITECTURE.md` -- Package overview, attribute processing, directive handling
|
|
33
33
|
- `src/parser.ts` -- AstroParser class (source of truth for override methods)
|
|
34
34
|
- `src/astro-parser.ts` -- astro-eslint-parser wrapper
|
|
35
35
|
|
|
@@ -62,14 +62,14 @@ Modify the SVG/XHTML namespace scoping logic. Follow recipe #2 in `docs/maintena
|
|
|
62
62
|
|
|
63
63
|
### Step 1: Understand the current logic
|
|
64
64
|
|
|
65
|
-
1.
|
|
66
|
-
2.
|
|
67
|
-
3.
|
|
65
|
+
1. Namespace resolution is handled by the base `Parser` class from `@markuplint/parser-utils`
|
|
66
|
+
2. The Astro parser does **not** override namespace logic — there is no `#updateScopeNS()` method
|
|
67
|
+
3. Any namespace changes require modifications in the base `Parser` class or adding an override in `AstroParser`
|
|
68
68
|
|
|
69
69
|
### Step 2: Make the change
|
|
70
70
|
|
|
71
|
-
1.
|
|
72
|
-
2. For new namespaces (e.g., MathML), add a
|
|
71
|
+
1. If adding namespace handling to the Astro parser, override the relevant method from the base `Parser`
|
|
72
|
+
2. For new namespaces (e.g., MathML), add a condition checking `originNode.name`
|
|
73
73
|
3. Ensure the namespace URI constant is correct
|
|
74
74
|
|
|
75
75
|
### Step 3: Verify
|
package/docs/maintenance.ja.md
CHANGED
|
@@ -61,22 +61,12 @@ expect(debugMaps).toStrictEqual([
|
|
|
61
61
|
|
|
62
62
|
### 2. 名前空間スコーピングの変更
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
3.
|
|
69
|
-
|
|
70
|
-
if (
|
|
71
|
-
parentNS === 'http://www.w3.org/1999/xhtml' &&
|
|
72
|
-
originNode.type === 'element' &&
|
|
73
|
-
originNode.name?.toLowerCase() === 'math'
|
|
74
|
-
) {
|
|
75
|
-
this.state.scopeNS = 'http://www.w3.org/1998/Math/MathML';
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
4. ビルドとテスト: `yarn build --scope @markuplint/astro-parser && yarn test --scope @markuplint/astro-parser`
|
|
79
|
-
5. `src/parser.spec.ts` に名前空間テストケースを追加:
|
|
64
|
+
名前空間の解決は現在 `@markuplint/parser-utils` の基底 `Parser` クラスが処理しています。Astro パーサーは名前空間ロジックをオーバーライドしていません。
|
|
65
|
+
|
|
66
|
+
1. カスタム名前空間処理が必要な場合は、`src/parser.ts` の `AstroParser` で該当メソッドをオーバーライド
|
|
67
|
+
2. 新しい名前空間(例: MathML)の場合、要素名を検出して名前空間を切り替えるオーバーライドが必要
|
|
68
|
+
3. ビルドとテスト: `yarn build --scope @markuplint/astro-parser && yarn test --scope @markuplint/astro-parser`
|
|
69
|
+
4. `src/parser.spec.ts` に名前空間テストケースを追加:
|
|
80
70
|
```ts
|
|
81
71
|
test('MathML namespace', () => {
|
|
82
72
|
const doc = parse('<div><math><mi>x</mi></math></div>');
|
|
@@ -161,14 +151,13 @@ yarn build --scope @markuplint/astro-parser && yarn test --scope @markuplint/ast
|
|
|
161
151
|
|
|
162
152
|
**症状:** `<svg>` 内の要素が XHTML 名前空間を持つ、または `<foreignObject>` 内の要素が SVG 名前空間を持つ。
|
|
163
153
|
|
|
164
|
-
**原因:**
|
|
154
|
+
**原因:** 名前空間の解決は `@markuplint/parser-utils` の基底 `Parser` クラスが処理します。Astro パーサーは名前空間ロジックをオーバーライドしていません。
|
|
165
155
|
|
|
166
156
|
**解決策:**
|
|
167
157
|
|
|
168
|
-
1. `
|
|
169
|
-
2. `
|
|
170
|
-
3.
|
|
171
|
-
4. 特定のネストパターンのテストケースを `src/parser.spec.ts` に追加
|
|
158
|
+
1. 問題が `@markuplint/parser-utils` の基底 `Parser` クラスにあるかどうかを確認
|
|
159
|
+
2. 特定のネストパターンのテストケースを `src/parser.spec.ts` に追加して期待される動作を確認
|
|
160
|
+
3. 問題が上流にある場合は、基底 `Parser` の名前空間処理を調査
|
|
172
161
|
|
|
173
162
|
### テンプレートディレクティブが検出されない
|
|
174
163
|
|
package/docs/maintenance.md
CHANGED
|
@@ -61,22 +61,12 @@ The second argument `true` to `nodeListToDebugMaps` includes attribute details i
|
|
|
61
61
|
|
|
62
62
|
### 2. Modifying Namespace Scoping
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
3.
|
|
69
|
-
|
|
70
|
-
if (
|
|
71
|
-
parentNS === 'http://www.w3.org/1999/xhtml' &&
|
|
72
|
-
originNode.type === 'element' &&
|
|
73
|
-
originNode.name?.toLowerCase() === 'math'
|
|
74
|
-
) {
|
|
75
|
-
this.state.scopeNS = 'http://www.w3.org/1998/Math/MathML';
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
4. Build and test: `yarn build --scope @markuplint/astro-parser && yarn test --scope @markuplint/astro-parser`
|
|
79
|
-
5. Add namespace test cases to `src/parser.spec.ts`:
|
|
64
|
+
Namespace resolution is currently handled by the base `Parser` class from `@markuplint/parser-utils`. The Astro parser does not override namespace logic.
|
|
65
|
+
|
|
66
|
+
1. If you need to add custom namespace handling, you would override the relevant method in `AstroParser` in `src/parser.ts`
|
|
67
|
+
2. For new namespaces (e.g., MathML), the override would need to detect the element name and switch the namespace
|
|
68
|
+
3. Build and test: `yarn build --scope @markuplint/astro-parser && yarn test --scope @markuplint/astro-parser`
|
|
69
|
+
4. Add namespace test cases to `src/parser.spec.ts`:
|
|
80
70
|
```ts
|
|
81
71
|
test('MathML namespace', () => {
|
|
82
72
|
const doc = parse('<div><math><mi>x</mi></math></div>');
|
|
@@ -161,14 +151,13 @@ yarn build --scope @markuplint/astro-parser && yarn test --scope @markuplint/ast
|
|
|
161
151
|
|
|
162
152
|
**Symptom:** Elements inside `<svg>` have XHTML namespace, or elements inside `<foreignObject>` have SVG namespace.
|
|
163
153
|
|
|
164
|
-
**Cause:**
|
|
154
|
+
**Cause:** Namespace resolution is handled by the base `Parser` class from `@markuplint/parser-utils`. The Astro parser does not override namespace logic.
|
|
165
155
|
|
|
166
156
|
**Solution:**
|
|
167
157
|
|
|
168
|
-
1. Check
|
|
169
|
-
2.
|
|
170
|
-
3.
|
|
171
|
-
4. Add a test case with the specific nesting pattern to `src/parser.spec.ts`
|
|
158
|
+
1. Check whether the issue is in the base `Parser` class in `@markuplint/parser-utils`
|
|
159
|
+
2. Add a test case with the specific nesting pattern to `src/parser.spec.ts` to confirm expected behavior
|
|
160
|
+
3. If the issue is upstream, investigate the base `Parser` namespace handling
|
|
172
161
|
|
|
173
162
|
### Template directive not detected
|
|
174
163
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/astro-parser",
|
|
3
|
-
"version": "5.0.0-
|
|
3
|
+
"version": "5.0.0-rc.0",
|
|
4
4
|
"description": "astro parser for markuplint",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"clean": "tsc --build --clean tsconfig.build.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@markuplint/ml-ast": "5.0.0-
|
|
28
|
-
"@markuplint/parser-utils": "5.0.0-
|
|
27
|
+
"@markuplint/ml-ast": "5.0.0-rc.0",
|
|
28
|
+
"@markuplint/parser-utils": "5.0.0-rc.0",
|
|
29
29
|
"astro-eslint-parser": "1.3.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@astrojs/compiler": "
|
|
32
|
+
"@astrojs/compiler": "3.0.0"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "ebf4d7cfca0c259aead3b292c6b8a202db4cd802"
|
|
35
35
|
}
|