@markuplint/pug-parser 4.6.23 → 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 +2 -0
- package/ARCHITECTURE.md +2 -0
- package/CHANGELOG.md +24 -0
- package/lib/parser.d.ts +1 -2
- package/lib/parser.js +21 -12
- package/package.json +8 -5
package/ARCHITECTURE.ja.md
CHANGED
|
@@ -181,6 +181,8 @@ case 'Doctype':
|
|
|
181
181
|
|
|
182
182
|
その他すべてのノードタイプ — `Conditional`、`Code`、`Each`、`Mixin`、`MixinBlock`、`Include`、`RawInclude`、`Extends`、`NamedBlock`、`Case`、`When`、`While`、`Filter`、`YieldBlock`、`InterpolatedTag`、`FileReference` — は `visitPsBlock()` を通じてプリプロセッサ固有ブロックにマッピングされます。
|
|
183
183
|
|
|
184
|
+
`Each` ノードでは、`blockBehavior` に `{ type: 'each', expression }` が設定されます。`expression` はイテレーション式(例: `i in obj`)です。これによりコアエンジンが Pug のループを認識できるようになります。
|
|
185
|
+
|
|
184
186
|
`file` プロパティを持つノード(例: `Include`、`Extends`)では、ノードの終了位置からファイル参照オフセットを計算して、生ソースにファイルパスを含むようトークンが拡張されます。
|
|
185
187
|
|
|
186
188
|
子ノードはノードタイプに応じて `block.nodes` または `nodes` から抽出されます。
|
package/ARCHITECTURE.md
CHANGED
|
@@ -181,6 +181,8 @@ Tag processing is the most complex path:
|
|
|
181
181
|
|
|
182
182
|
All other node types — `Conditional`, `Code`, `Each`, `Mixin`, `MixinBlock`, `Include`, `RawInclude`, `Extends`, `NamedBlock`, `Case`, `When`, `While`, `Filter`, `YieldBlock`, `InterpolatedTag`, `FileReference` — are mapped to preprocessor-specific blocks via `visitPsBlock()`.
|
|
183
183
|
|
|
184
|
+
For `Each` nodes, a `blockBehavior` of `{ type: 'each', expression }` is set, where `expression` is the iteration expression (e.g., `i in obj`). This enables the core engine to recognize Pug loops.
|
|
185
|
+
|
|
184
186
|
For nodes with a `file` property (e.g., `Include`, `Extends`), the token is extended to include the file path in the raw source by computing the file reference offset from the node's end position.
|
|
185
187
|
|
|
186
188
|
Child nodes are extracted from either `block.nodes` or `nodes`, depending on the node type.
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,30 @@
|
|
|
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
|
+
- refactor(pug-parser)!: update for simplified AST token properties ([7e0704e](https://github.com/markuplint/markuplint/commit/7e0704e32761f418a0c2e078557e797dae80b722))
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- **pug-parser:** support loop blocks ([1ed3ab8](https://github.com/markuplint/markuplint/commit/1ed3ab82203dbb32389c78a669a43412a8b407e2))
|
|
17
|
+
|
|
18
|
+
### BREAKING CHANGES
|
|
19
|
+
|
|
20
|
+
- Adapt to renamed token properties and add
|
|
21
|
+
blockBehavior to visitElement calls.
|
|
22
|
+
|
|
23
|
+
* Token property access: startOffset -> offset, startLine -> line,
|
|
24
|
+
startCol -> col
|
|
25
|
+
* Update test assertions for new property names
|
|
26
|
+
* Add blockBehavior: null to element creation
|
|
27
|
+
|
|
28
|
+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
29
|
+
|
|
6
30
|
## [4.6.23](https://github.com/markuplint/markuplint/compare/@markuplint/pug-parser@4.6.22...@markuplint/pug-parser@4.6.23) (2026-02-10)
|
|
7
31
|
|
|
8
32
|
**Note:** Version bump only for package @markuplint/pug-parser
|
package/lib/parser.d.ts
CHANGED
|
@@ -36,14 +36,13 @@ declare class PugParser extends Parser<ASTNode> {
|
|
|
36
36
|
* pre-parsed attributes (including `&attributes` spread syntax) and
|
|
37
37
|
* visiting child nodes within the Pug block.
|
|
38
38
|
*
|
|
39
|
-
* @param token - The child token with tag metadata
|
|
39
|
+
* @param token - The child token with tag metadata
|
|
40
40
|
* @param childNodes - The child Pug AST nodes within the tag's block
|
|
41
41
|
* @param options - Options containing pre-parsed attribute overrides
|
|
42
42
|
* @returns An array of markuplint node tree items for the element and its children
|
|
43
43
|
*/
|
|
44
44
|
visitElement(token: ChildToken & {
|
|
45
45
|
readonly nodeName: string;
|
|
46
|
-
readonly namespace: string;
|
|
47
46
|
readonly isFragment: false;
|
|
48
47
|
}, childNodes: readonly ASTNode[], options: {
|
|
49
48
|
readonly overwriteProps: {
|
package/lib/parser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { HtmlParser
|
|
2
|
-
import { ParserError, Parser, AttrState, scriptParser } from '@markuplint/parser-utils';
|
|
1
|
+
import { HtmlParser } from '@markuplint/html-parser';
|
|
2
|
+
import { ParserError, Parser, AttrState, scriptParser, getNamespace } from '@markuplint/parser-utils';
|
|
3
3
|
import { pugParse } from './pug-parser/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Internal HTML parser used for inline HTML content within Pug templates.
|
|
@@ -71,7 +71,6 @@ class PugParser extends Parser {
|
|
|
71
71
|
nodeize(
|
|
72
72
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
73
73
|
originNode, parentNode, depth) {
|
|
74
|
-
const parentNamespace = parentNode && 'namespace' in parentNode ? parentNode.namespace : 'http://www.w3.org/1999/xhtml';
|
|
75
74
|
const token = this.sliceFragment(originNode.offset, originNode.endOffset);
|
|
76
75
|
switch (originNode.type) {
|
|
77
76
|
case 'Doctype': {
|
|
@@ -98,7 +97,7 @@ class PugParser extends Parser {
|
|
|
98
97
|
const htmlDoc = new HtmlInPugParser().parse(originNode.raw, {
|
|
99
98
|
offsetOffset: originNode.offset,
|
|
100
99
|
offsetLine: originNode.line,
|
|
101
|
-
offsetColumn: originNode.column ?? parentNode?.
|
|
100
|
+
offsetColumn: originNode.column ?? parentNode?.col,
|
|
102
101
|
depth,
|
|
103
102
|
});
|
|
104
103
|
const newNodeList = [];
|
|
@@ -107,9 +106,9 @@ class PugParser extends Parser {
|
|
|
107
106
|
// Remove `#[` and `]`
|
|
108
107
|
const raw = node.raw.slice(2, -1);
|
|
109
108
|
const innerNodes = new PugParser().parse(raw, {
|
|
110
|
-
offsetOffset: node.
|
|
111
|
-
offsetLine: node.
|
|
112
|
-
offsetColumn: node.
|
|
109
|
+
offsetOffset: node.offset + 2,
|
|
110
|
+
offsetLine: node.line,
|
|
111
|
+
offsetColumn: node.col + 2,
|
|
113
112
|
depth: node.depth,
|
|
114
113
|
});
|
|
115
114
|
newNodeList.push(...innerNodes.nodeList);
|
|
@@ -141,7 +140,6 @@ class PugParser extends Parser {
|
|
|
141
140
|
});
|
|
142
141
|
}
|
|
143
142
|
case 'Tag': {
|
|
144
|
-
const namespace = getNamespace(originNode.name, parentNamespace);
|
|
145
143
|
const attrs = originNode.attrs.map(attr => {
|
|
146
144
|
// eslint-disable-next-line prefer-const
|
|
147
145
|
let { offset, endOffset } = this.getOffsetsFromCode(attr.line, attr.column, attr.endLine, attr.endColumn);
|
|
@@ -166,7 +164,7 @@ class PugParser extends Parser {
|
|
|
166
164
|
const blockLength = '&attributes('.length;
|
|
167
165
|
const { offset, endOffset } = this.getOffsetsFromCode(block.line, block.column + blockLength, block.line, block.column + blockLength + block.val.length);
|
|
168
166
|
const token = this.sliceFragment(offset, endOffset);
|
|
169
|
-
const node = this.createToken(token.raw, token.
|
|
167
|
+
const node = this.createToken(token.raw, token.offset, token.line, token.col);
|
|
170
168
|
return {
|
|
171
169
|
...node,
|
|
172
170
|
type: 'spread',
|
|
@@ -178,7 +176,6 @@ class PugParser extends Parser {
|
|
|
178
176
|
depth,
|
|
179
177
|
parentNode,
|
|
180
178
|
nodeName: originNode.name,
|
|
181
|
-
namespace,
|
|
182
179
|
isFragment: false,
|
|
183
180
|
}, originNode.block?.nodes ?? [], {
|
|
184
181
|
overwriteProps: {
|
|
@@ -194,6 +191,16 @@ class PugParser extends Parser {
|
|
|
194
191
|
const fileEndOffset = fileOffset + originNode.file.path.length;
|
|
195
192
|
tokenIncludesFile = this.sliceFragment(originNode.offset, fileEndOffset);
|
|
196
193
|
}
|
|
194
|
+
let blockBehavior = null;
|
|
195
|
+
switch (originNode.type) {
|
|
196
|
+
case 'Each': {
|
|
197
|
+
blockBehavior = {
|
|
198
|
+
type: 'each',
|
|
199
|
+
expression: originNode.val,
|
|
200
|
+
};
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
197
204
|
return this.visitPsBlock({
|
|
198
205
|
...tokenIncludesFile,
|
|
199
206
|
depth,
|
|
@@ -204,7 +211,7 @@ class PugParser extends Parser {
|
|
|
204
211
|
? originNode.block.nodes
|
|
205
212
|
: 'nodes' in originNode
|
|
206
213
|
? originNode.nodes
|
|
207
|
-
: []);
|
|
214
|
+
: [], blockBehavior);
|
|
208
215
|
}
|
|
209
216
|
}
|
|
210
217
|
}
|
|
@@ -219,7 +226,7 @@ class PugParser extends Parser {
|
|
|
219
226
|
* pre-parsed attributes (including `&attributes` spread syntax) and
|
|
220
227
|
* visiting child nodes within the Pug block.
|
|
221
228
|
*
|
|
222
|
-
* @param token - The child token with tag metadata
|
|
229
|
+
* @param token - The child token with tag metadata
|
|
223
230
|
* @param childNodes - The child Pug AST nodes within the tag's block
|
|
224
231
|
* @param options - Options containing pre-parsed attribute overrides
|
|
225
232
|
* @returns An array of markuplint node tree items for the element and its children
|
|
@@ -233,7 +240,9 @@ class PugParser extends Parser {
|
|
|
233
240
|
...options.overwriteProps,
|
|
234
241
|
type: 'starttag',
|
|
235
242
|
elementType: this.detectElementType(token.nodeName),
|
|
243
|
+
namespace: getNamespace(token.nodeName, token.parentNode),
|
|
236
244
|
childNodes: [],
|
|
245
|
+
blockBehavior: null,
|
|
237
246
|
pairNode: null,
|
|
238
247
|
tagOpenChar: '',
|
|
239
248
|
tagCloseChar: '',
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/pug-parser",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0-alpha.0",
|
|
4
4
|
"description": "Pug parser for markuplint",
|
|
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
|
".": {
|
|
@@ -21,11 +24,11 @@
|
|
|
21
24
|
"clean": "tsc --build --clean tsconfig.build.json"
|
|
22
25
|
},
|
|
23
26
|
"dependencies": {
|
|
24
|
-
"@markuplint/html-parser": "
|
|
25
|
-
"@markuplint/ml-ast": "
|
|
26
|
-
"@markuplint/parser-utils": "
|
|
27
|
+
"@markuplint/html-parser": "5.0.0-alpha.0",
|
|
28
|
+
"@markuplint/ml-ast": "5.0.0-alpha.0",
|
|
29
|
+
"@markuplint/parser-utils": "5.0.0-alpha.0",
|
|
27
30
|
"pug-lexer": "5.0.1",
|
|
28
31
|
"pug-parser": "6.0.0"
|
|
29
32
|
},
|
|
30
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "13dcfc84ec83d87360c720e253383b60767e1b56"
|
|
31
34
|
}
|