@markuplint/pug-parser 3.0.0-alpha.6 → 3.0.0-dev.176
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/README.md +4 -4
- package/lib/attr-tokenizer.js +13 -10
- package/lib/parse.js +22 -8
- package/lib/pug-parser/index.js +47 -20
- package/package.json +6 -6
- package/test/index.spec.js +556 -0
- package/test/pug-parser/index.spec.js +1752 -0
- package/test/utils/get-offset-from-line-and-col.spec.js +26 -0
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# @markuplint/pug-parser
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@markuplint/pug-parser)
|
|
4
|
-
|
|
5
|
-
[
|
|
4
|
+
|
|
5
|
+
Use **markuplint** with [**Pug**](https://pugjs.org/).
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
|
-
```
|
|
9
|
+
```shell
|
|
10
10
|
$ npm install -D @markuplint/pug-parser
|
|
11
11
|
|
|
12
12
|
$ yarn add -D @markuplint/pug-parser
|
|
@@ -14,7 +14,7 @@ $ yarn add -D @markuplint/pug-parser
|
|
|
14
14
|
|
|
15
15
|
## Usage
|
|
16
16
|
|
|
17
|
-
Add `parser` option
|
|
17
|
+
Add `parser` option to your [configuration](https://markuplint.dev/configuration/#properties/parser).
|
|
18
18
|
|
|
19
19
|
```json
|
|
20
20
|
{
|
package/lib/attr-tokenizer.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const parser_utils_1 = require("@markuplint/parser-utils");
|
|
4
|
-
function attrTokenizer(
|
|
4
|
+
function attrTokenizer(
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
6
|
+
attr) {
|
|
7
|
+
var _a, _b, _c;
|
|
5
8
|
if (attr.raw[0] === '#' || attr.raw[0] === '.') {
|
|
6
9
|
let value = '';
|
|
7
10
|
if (typeof attr.val === 'string') {
|
|
8
|
-
[, , value] = attr.val.match(/(['"`]?)([^\1]+)(\1)/)
|
|
11
|
+
[, , value] = (_a = attr.val.match(/(['"`]?)([^\1]+)(\1)/)) !== null && _a !== void 0 ? _a : ['', '', ''];
|
|
9
12
|
}
|
|
10
13
|
else {
|
|
11
14
|
value = `${attr.val}`;
|
|
@@ -21,7 +24,7 @@ function attrTokenizer(attr) {
|
|
|
21
24
|
startCol: attr.column,
|
|
22
25
|
endCol: attr.endColumn,
|
|
23
26
|
potentialName: attr.name,
|
|
24
|
-
potentialValue: value,
|
|
27
|
+
potentialValue: value !== null && value !== void 0 ? value : '',
|
|
25
28
|
valueType: 'string',
|
|
26
29
|
isDuplicatable: attr.raw[0] === '.',
|
|
27
30
|
nodeName: '#pug-special-attr',
|
|
@@ -51,13 +54,13 @@ function attrTokenizer(attr) {
|
|
|
51
54
|
const withoutName = attr.raw.slice(attr.name.length);
|
|
52
55
|
const valueOffset = withoutName.indexOf(attr.val);
|
|
53
56
|
const equalAndBeforeSpaceAfterSpace = withoutName.slice(0, valueOffset);
|
|
54
|
-
const [, before, equal, after] = equalAndBeforeSpaceAfterSpace.match(/^(\s*)(=)(\s*)$/)
|
|
55
|
-
const [, quote, coreValue] = attr.val.match(/(['"`]?)([^\1]+)(\1)/)
|
|
56
|
-
spacesBeforeEqualChars = before;
|
|
57
|
-
equalChars = equal;
|
|
58
|
-
spacesAfterEqualChars = after;
|
|
59
|
-
quoteChars = quote;
|
|
60
|
-
valueChars = coreValue;
|
|
57
|
+
const [, before, equal, after] = (_b = equalAndBeforeSpaceAfterSpace.match(/^(\s*)(=)(\s*)$/)) !== null && _b !== void 0 ? _b : ['', '', '', ''];
|
|
58
|
+
const [, quote, coreValue] = (_c = attr.val.match(/(['"`]?)([^\1]+)(\1)/)) !== null && _c !== void 0 ? _c : ['', '', ''];
|
|
59
|
+
spacesBeforeEqualChars = before !== null && before !== void 0 ? before : '';
|
|
60
|
+
equalChars = equal !== null && equal !== void 0 ? equal : '';
|
|
61
|
+
spacesAfterEqualChars = after !== null && after !== void 0 ? after : '';
|
|
62
|
+
quoteChars = quote !== null && quote !== void 0 ? quote : '';
|
|
63
|
+
valueChars = coreValue !== null && coreValue !== void 0 ? coreValue : '';
|
|
61
64
|
if (quote === '`' || quote === '') {
|
|
62
65
|
isDynamicValue = true;
|
|
63
66
|
}
|
package/lib/parse.js
CHANGED
|
@@ -46,19 +46,27 @@ class Parser {
|
|
|
46
46
|
tslib_1.__classPrivateFieldSet(this, _Parser_ast, (0, pug_parser_1.pugParse)(raw), "f");
|
|
47
47
|
// console.log(JSON.stringify(this.#ast, null, 2));
|
|
48
48
|
}
|
|
49
|
-
flattenNodes(
|
|
49
|
+
flattenNodes(
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
51
|
+
nodeTree) {
|
|
50
52
|
const nodeOrders = [];
|
|
51
53
|
(0, parser_utils_1.walk)(nodeTree, node => {
|
|
52
54
|
nodeOrders.push(node);
|
|
53
55
|
});
|
|
54
|
-
(0,
|
|
56
|
+
(0, parser_utils_1.removeDeprecatedNode)(nodeOrders);
|
|
55
57
|
return nodeOrders;
|
|
56
58
|
}
|
|
57
59
|
getNodeList() {
|
|
58
60
|
const nodeTree = this.traverse(tslib_1.__classPrivateFieldGet(this, _Parser_ast, "f").nodes, null);
|
|
59
61
|
return this.flattenNodes(nodeTree);
|
|
60
62
|
}
|
|
61
|
-
nodeize(
|
|
63
|
+
nodeize(
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
65
|
+
originNode,
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
67
|
+
prevNode,
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
69
|
+
parentNode) {
|
|
62
70
|
var _a;
|
|
63
71
|
const nextNode = null;
|
|
64
72
|
const startOffset = originNode.offset;
|
|
@@ -73,7 +81,7 @@ class Parser {
|
|
|
73
81
|
return {
|
|
74
82
|
uuid: (0, parser_utils_1.uuid)(),
|
|
75
83
|
raw: originNode.raw,
|
|
76
|
-
name: originNode.val
|
|
84
|
+
name: (_a = originNode.val) !== null && _a !== void 0 ? _a : '',
|
|
77
85
|
// TODO:
|
|
78
86
|
publicId: '',
|
|
79
87
|
// TODO:
|
|
@@ -174,7 +182,7 @@ class Parser {
|
|
|
174
182
|
tagOpenChar: '',
|
|
175
183
|
tagCloseChar: '',
|
|
176
184
|
};
|
|
177
|
-
if (originNode.block.nodes.length) {
|
|
185
|
+
if (originNode.block.nodes.length > 0) {
|
|
178
186
|
tag.childNodes = this.traverse(originNode.block.nodes, tag);
|
|
179
187
|
}
|
|
180
188
|
return tag;
|
|
@@ -197,14 +205,16 @@ class Parser {
|
|
|
197
205
|
isFragment: true,
|
|
198
206
|
isGhost: false,
|
|
199
207
|
};
|
|
200
|
-
if ('block' in originNode &&
|
|
208
|
+
if ('block' in originNode && originNode.block && originNode.block.nodes.length > 0) {
|
|
201
209
|
tag.childNodes = this.traverse(originNode.block.nodes, tag);
|
|
202
210
|
}
|
|
203
211
|
return tag;
|
|
204
212
|
}
|
|
205
213
|
}
|
|
206
214
|
}
|
|
207
|
-
traverse(
|
|
215
|
+
traverse(
|
|
216
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
217
|
+
astNodes, parentNode = null) {
|
|
208
218
|
const nodeList = [];
|
|
209
219
|
let prevNode = null;
|
|
210
220
|
for (const astNode of astNodes) {
|
|
@@ -214,7 +224,11 @@ class Parser {
|
|
|
214
224
|
}
|
|
215
225
|
let node;
|
|
216
226
|
if (Array.isArray(nodes)) {
|
|
217
|
-
|
|
227
|
+
const lastNode = nodes[nodes.length - 1];
|
|
228
|
+
if (!lastNode) {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
node = lastNode;
|
|
218
232
|
}
|
|
219
233
|
else {
|
|
220
234
|
node = nodes;
|
package/lib/pug-parser/index.js
CHANGED
|
@@ -26,10 +26,13 @@ function getOffsetsFromLines(pug) {
|
|
|
26
26
|
});
|
|
27
27
|
return result;
|
|
28
28
|
}
|
|
29
|
-
function mergeTextNode(
|
|
29
|
+
function mergeTextNode(
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
31
|
+
nodes, pug) {
|
|
32
|
+
var _a;
|
|
30
33
|
const baseNodes = [];
|
|
31
34
|
for (const node of nodes) {
|
|
32
|
-
const prevNode = baseNodes[baseNodes.length - 1]
|
|
35
|
+
const prevNode = (_a = baseNodes[baseNodes.length - 1]) !== null && _a !== void 0 ? _a : null;
|
|
33
36
|
if (prevNode && prevNode.type === 'Text' && node.type === 'Text') {
|
|
34
37
|
prevNode.raw = pug.slice(prevNode.offset, node.endOffset);
|
|
35
38
|
prevNode.endColumn = node.endColumn;
|
|
@@ -47,13 +50,18 @@ function mergeTextNode(nodes, pug) {
|
|
|
47
50
|
* @param tokens Lexed token list
|
|
48
51
|
* @param pug Raw code
|
|
49
52
|
*/
|
|
50
|
-
function optimizeAST(
|
|
53
|
+
function optimizeAST(
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
55
|
+
originalAST,
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
57
|
+
tokens, pug) {
|
|
58
|
+
var _a;
|
|
51
59
|
const nodes = [];
|
|
52
60
|
for (const node of originalAST.nodes) {
|
|
53
61
|
const line = node.line;
|
|
54
62
|
const column = node.column;
|
|
55
63
|
const offsets = getOffsetsFromLines(pug);
|
|
56
|
-
const lineOffset = Math.max(offsets[line - 2]
|
|
64
|
+
const lineOffset = Math.max((_a = offsets[line - 2]) !== null && _a !== void 0 ? _a : 0, 0);
|
|
57
65
|
const offset = lineOffset + column - 1;
|
|
58
66
|
const { endLine, endColumn, endOffset } = getLocationFromToken(offset, line, column, tokens);
|
|
59
67
|
const raw = pug.slice(offset, endOffset);
|
|
@@ -303,7 +311,12 @@ function optimizeAST(originalAST, tokens, pug) {
|
|
|
303
311
|
line: originalAST.line,
|
|
304
312
|
};
|
|
305
313
|
}
|
|
306
|
-
function optimizeASTOfConditionalNode(
|
|
314
|
+
function optimizeASTOfConditionalNode(
|
|
315
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
316
|
+
node,
|
|
317
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
318
|
+
tokens, pug, offsets, depth) {
|
|
319
|
+
var _a, _b;
|
|
307
320
|
const altNodes = [];
|
|
308
321
|
let tokenOfCurrentNode = null;
|
|
309
322
|
for (const token of tokens) {
|
|
@@ -314,7 +327,7 @@ function optimizeASTOfConditionalNode(node, tokens, pug, offsets, depth) {
|
|
|
314
327
|
}
|
|
315
328
|
if (tokenOfCurrentNode) {
|
|
316
329
|
// console.log(JSON.stringify(node, null, 2));
|
|
317
|
-
const lineOffset = Math.max(offsets[node.line - 2]
|
|
330
|
+
const lineOffset = Math.max((_a = offsets[node.line - 2]) !== null && _a !== void 0 ? _a : 0, 0);
|
|
318
331
|
const offset = lineOffset + node.column - 1;
|
|
319
332
|
const length = tokenOfCurrentNode.loc.end.column - tokenOfCurrentNode.loc.start.column;
|
|
320
333
|
const endOffset = offset + length;
|
|
@@ -346,7 +359,7 @@ function optimizeASTOfConditionalNode(node, tokens, pug, offsets, depth) {
|
|
|
346
359
|
if (!tokenOfCurrentNode) {
|
|
347
360
|
return [];
|
|
348
361
|
}
|
|
349
|
-
const lineOffset = Math.max(offsets[tokenOfCurrentNode.loc.start.line - 2]
|
|
362
|
+
const lineOffset = Math.max((_b = offsets[tokenOfCurrentNode.loc.start.line - 2]) !== null && _b !== void 0 ? _b : 0, 0);
|
|
350
363
|
const offset = lineOffset + tokenOfCurrentNode.loc.start.column - 1;
|
|
351
364
|
const length = tokenOfCurrentNode.loc.end.column - tokenOfCurrentNode.loc.start.column;
|
|
352
365
|
const endOffset = offset + length;
|
|
@@ -374,14 +387,13 @@ function optimizeASTOfConditionalNode(node, tokens, pug, offsets, depth) {
|
|
|
374
387
|
}
|
|
375
388
|
return altNodes;
|
|
376
389
|
}
|
|
377
|
-
function getLocationFromToken(offset, line, column,
|
|
390
|
+
function getLocationFromToken(offset, line, column,
|
|
391
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
392
|
+
tokens, tokenType) {
|
|
393
|
+
const tokenTypes = typeof tokenType === 'string' ? (tokenType !== '' ? [tokenType] : null) : tokenType !== null && tokenType !== void 0 ? tokenType : null;
|
|
378
394
|
let tokenOfCurrentNode = null;
|
|
379
395
|
for (const token of tokens) {
|
|
380
|
-
if ((
|
|
381
|
-
? Array.isArray(tokenType)
|
|
382
|
-
? tokenType.includes(token.type)
|
|
383
|
-
: tokenType === token.type
|
|
384
|
-
: true) &&
|
|
396
|
+
if ((tokenTypes == null || tokenTypes.includes(token.type)) &&
|
|
385
397
|
token.loc.start.line === line &&
|
|
386
398
|
token.loc.start.column === column) {
|
|
387
399
|
tokenOfCurrentNode = token;
|
|
@@ -399,10 +411,15 @@ function getLocationFromToken(offset, line, column, tokens, tokenType = '') {
|
|
|
399
411
|
length,
|
|
400
412
|
};
|
|
401
413
|
}
|
|
402
|
-
function getAttrs(
|
|
414
|
+
function getAttrs(
|
|
415
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
416
|
+
originalAttrs,
|
|
417
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
418
|
+
tokens, offsets, pug) {
|
|
419
|
+
var _a;
|
|
403
420
|
const attrs = [];
|
|
404
421
|
for (const attr of originalAttrs) {
|
|
405
|
-
const attrLineOffset = offsets[attr.line - 2]
|
|
422
|
+
const attrLineOffset = (_a = offsets[attr.line - 2]) !== null && _a !== void 0 ? _a : 0;
|
|
406
423
|
const attrOffset = attrLineOffset + attr.column - 1;
|
|
407
424
|
let tokenOfCurrentAttr = null;
|
|
408
425
|
for (const token of tokens) {
|
|
@@ -432,7 +449,10 @@ function getAttrs(originalAttrs, tokens, offsets, pug) {
|
|
|
432
449
|
}
|
|
433
450
|
return attrs;
|
|
434
451
|
}
|
|
435
|
-
function getEndAttributeLocation(nodeName, offset, line, column,
|
|
452
|
+
function getEndAttributeLocation(nodeName, offset, line, column,
|
|
453
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
454
|
+
tokens, offsets) {
|
|
455
|
+
var _a;
|
|
436
456
|
let beforeNewlineToken = null;
|
|
437
457
|
for (const token of tokens) {
|
|
438
458
|
// Searching token after the tag node.
|
|
@@ -443,7 +463,7 @@ function getEndAttributeLocation(nodeName, offset, line, column, tokens, offsets
|
|
|
443
463
|
token.type !== 'end-attributes' &&
|
|
444
464
|
token.type !== 'id' &&
|
|
445
465
|
token.type !== 'class') {
|
|
446
|
-
const endAttrLineOffset = Math.max(offsets[beforeNewlineToken.loc.end.line - 2]
|
|
466
|
+
const endAttrLineOffset = Math.max((_a = offsets[beforeNewlineToken.loc.end.line - 2]) !== null && _a !== void 0 ? _a : 0, 0);
|
|
447
467
|
const endAttrOffset = endAttrLineOffset + beforeNewlineToken.loc.end.column - 1;
|
|
448
468
|
return {
|
|
449
469
|
endOffset: endAttrOffset,
|
|
@@ -459,7 +479,11 @@ function getEndAttributeLocation(nodeName, offset, line, column, tokens, offsets
|
|
|
459
479
|
endColumn: column + nodeName.length,
|
|
460
480
|
};
|
|
461
481
|
}
|
|
462
|
-
function getPipelessText(
|
|
482
|
+
function getPipelessText(
|
|
483
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
484
|
+
node, pug,
|
|
485
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
486
|
+
tokens) {
|
|
463
487
|
let startPipelessText = null;
|
|
464
488
|
let endPipelessText = null;
|
|
465
489
|
for (const token of tokens) {
|
|
@@ -491,7 +515,10 @@ function getPipelessText(node, pug, tokens) {
|
|
|
491
515
|
}
|
|
492
516
|
return null;
|
|
493
517
|
}
|
|
494
|
-
function getRawTextAndLocationEnd(val, offset, line, column,
|
|
518
|
+
function getRawTextAndLocationEnd(val, offset, line, column,
|
|
519
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
520
|
+
tokens, offsets, pug) {
|
|
521
|
+
var _a;
|
|
495
522
|
let beforeNewlineToken = null;
|
|
496
523
|
for (const token of tokens) {
|
|
497
524
|
// Searching token after the text.
|
|
@@ -501,7 +528,7 @@ function getRawTextAndLocationEnd(val, offset, line, column, tokens, offsets, pu
|
|
|
501
528
|
token.type !== 'text-html' &&
|
|
502
529
|
token.type !== 'indent' &&
|
|
503
530
|
token.type !== 'outdent') {
|
|
504
|
-
const endAttrLineOffset = Math.max(offsets[beforeNewlineToken.loc.end.line - 2]
|
|
531
|
+
const endAttrLineOffset = Math.max((_a = offsets[beforeNewlineToken.loc.end.line - 2]) !== null && _a !== void 0 ? _a : 0, 0);
|
|
505
532
|
const endAttrOffset = endAttrLineOffset + beforeNewlineToken.loc.end.column - 1;
|
|
506
533
|
return {
|
|
507
534
|
endOffset: endAttrOffset,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/pug-parser",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-dev.176+f6ad62e9",
|
|
4
4
|
"description": "Pug parser for markuplint",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
"clean": "tsc --build --clean"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@markuplint/html-parser": "3.0.0-
|
|
20
|
-
"@markuplint/ml-ast": "3.0.0-
|
|
21
|
-
"@markuplint/parser-utils": "3.0.0-
|
|
19
|
+
"@markuplint/html-parser": "3.0.0-dev.176+f6ad62e9",
|
|
20
|
+
"@markuplint/ml-ast": "3.0.0-dev.176+f6ad62e9",
|
|
21
|
+
"@markuplint/parser-utils": "3.0.0-dev.176+f6ad62e9",
|
|
22
22
|
"pug-lexer": "^5.0.1",
|
|
23
23
|
"pug-parser": "^6.0.0",
|
|
24
|
-
"tslib": "^2.4.
|
|
24
|
+
"tslib": "^2.4.1"
|
|
25
25
|
},
|
|
26
|
-
"gitHead": "
|
|
26
|
+
"gitHead": "f6ad62e992e1569be4067f1e90d2d6017a658f57"
|
|
27
27
|
}
|