@markuplint/vue-parser 4.0.0-alpha.2 → 4.0.0-alpha.4
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/lib/attr.js +9 -7
- package/lib/parse.js +46 -11
- package/lib/vue-parser/index.d.ts +1 -0
- package/package.json +5 -6
package/lib/attr.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const duplicatableAttrs = ['class', 'style'];
|
|
1
|
+
const duplicatableAttrs = new Set(['class', 'style']);
|
|
2
2
|
export function attr(
|
|
3
3
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
4
4
|
attr) {
|
|
5
5
|
if (attr.type !== 'html-attr') {
|
|
6
6
|
const name = attr.potentialName;
|
|
7
|
-
if (duplicatableAttrs.
|
|
7
|
+
if (duplicatableAttrs.has(name)) {
|
|
8
8
|
attr.isDuplicatable = true;
|
|
9
9
|
}
|
|
10
10
|
return attr;
|
|
@@ -30,7 +30,7 @@ attr) {
|
|
|
30
30
|
*/
|
|
31
31
|
const [, directive, potentialName, modifier] = attr.name.raw.match(/^(v-bind:|:)([^.]+)(?:\.([^.]+))?$/i) ?? [];
|
|
32
32
|
if (directive && potentialName) {
|
|
33
|
-
if (duplicatableAttrs.
|
|
33
|
+
if (duplicatableAttrs.has(potentialName.toLowerCase())) {
|
|
34
34
|
attr.isDuplicatable = true;
|
|
35
35
|
}
|
|
36
36
|
if (!modifier) {
|
|
@@ -50,6 +50,7 @@ attr) {
|
|
|
50
50
|
_modifier: modifier,
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
+
/* eslint-disable unicorn/no-useless-switch-case */
|
|
53
54
|
// TODO: Supporting for `prop` and `camel` https://github.com/markuplint/markuplint/pull/681
|
|
54
55
|
case '.prop':
|
|
55
56
|
case '.camel':
|
|
@@ -57,12 +58,13 @@ attr) {
|
|
|
57
58
|
const name = `v-bind:${potentialName}${modifier ?? ''}`;
|
|
58
59
|
return {
|
|
59
60
|
...attr,
|
|
60
|
-
potentialName: attr.name.raw
|
|
61
|
+
potentialName: attr.name.raw === name ? undefined : name,
|
|
61
62
|
isDirective: true,
|
|
62
63
|
// @ts-ignore
|
|
63
64
|
_modifier: modifier,
|
|
64
65
|
};
|
|
65
66
|
}
|
|
67
|
+
/* eslint-enable unicorn/no-useless-switch-case */
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
}
|
|
@@ -85,12 +87,12 @@ attr) {
|
|
|
85
87
|
/**
|
|
86
88
|
* `v-slot`
|
|
87
89
|
*/
|
|
88
|
-
const
|
|
90
|
+
const slotName = (attr.name.raw.match(/^(v-slot:|#)(.+)$/i) ?? [])[2];
|
|
89
91
|
const name = `v-slot:${slotName}`;
|
|
90
92
|
if (slotName) {
|
|
91
93
|
return {
|
|
92
94
|
...attr,
|
|
93
|
-
potentialName: attr.name.raw
|
|
95
|
+
potentialName: attr.name.raw === name ? undefined : name,
|
|
94
96
|
isDirective: true,
|
|
95
97
|
};
|
|
96
98
|
}
|
|
@@ -98,7 +100,7 @@ attr) {
|
|
|
98
100
|
/**
|
|
99
101
|
* If directives
|
|
100
102
|
*/
|
|
101
|
-
if (
|
|
103
|
+
if (attr.name.raw.startsWith('v-')) {
|
|
102
104
|
return {
|
|
103
105
|
...attr,
|
|
104
106
|
isDirective: true,
|
package/lib/parse.js
CHANGED
|
@@ -7,26 +7,26 @@ export const parse = (rawCode, options) => {
|
|
|
7
7
|
try {
|
|
8
8
|
ast = vueParse(rawCode);
|
|
9
9
|
}
|
|
10
|
-
catch (
|
|
11
|
-
if (
|
|
10
|
+
catch (error) {
|
|
11
|
+
if (error instanceof SyntaxError && 'lineNumber' in error && 'column' in error) {
|
|
12
12
|
throw new ParserError(
|
|
13
13
|
// @ts-ignore
|
|
14
|
-
|
|
14
|
+
error.message, {
|
|
15
15
|
// @ts-ignore
|
|
16
|
-
line:
|
|
16
|
+
line: error.lineNumber,
|
|
17
17
|
// @ts-ignore
|
|
18
|
-
col:
|
|
18
|
+
col: error.column,
|
|
19
19
|
raw: '',
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
22
|
return {
|
|
23
23
|
nodeList: [],
|
|
24
24
|
isFragment: true,
|
|
25
|
-
parseError:
|
|
25
|
+
parseError: error instanceof Error ? error.message : new Error(`${error}`).message,
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
const nodeList = ast.templateBody
|
|
29
|
-
? flattenNodes(traverse(ast.templateBody, null, rawCode, options), rawCode)
|
|
29
|
+
? flattenNodes(traverse(ast.templateBody, null, rawCode, ast.templateBody.comments, options), rawCode)
|
|
30
30
|
: [];
|
|
31
31
|
// Remove `</template>`
|
|
32
32
|
const templateEndTagIndex = nodeList.findIndex(node => /\s*<\/\s*template\s*>\s*/i.test(node.raw));
|
|
@@ -46,17 +46,50 @@ export const parse = (rawCode, options) => {
|
|
|
46
46
|
};
|
|
47
47
|
function traverse(
|
|
48
48
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
49
|
-
rootNode, parentNode = null, rawHtml,
|
|
49
|
+
rootNode, parentNode = null, rawHtml,
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
51
|
+
comments, options) {
|
|
50
52
|
const nodeList = [];
|
|
51
53
|
if (rootNode.type !== 'VElement') {
|
|
52
54
|
return [];
|
|
53
55
|
}
|
|
54
56
|
let prevNode = null;
|
|
55
57
|
for (const vNode of rootNode.children) {
|
|
56
|
-
const node = nodeize(vNode, prevNode, parentNode, rawHtml, options);
|
|
58
|
+
const node = nodeize(vNode, prevNode, parentNode, rawHtml, comments, options);
|
|
57
59
|
if (!node) {
|
|
58
60
|
continue;
|
|
59
61
|
}
|
|
62
|
+
const lastOffset = prevNode?.endOffset ?? parentNode?.endOffset ?? 0;
|
|
63
|
+
const betweenComment = comments.find(comment => {
|
|
64
|
+
return lastOffset <= comment.range[0] && comment.range[1] <= node.startOffset;
|
|
65
|
+
});
|
|
66
|
+
if (betweenComment) {
|
|
67
|
+
const comment = {
|
|
68
|
+
uuid: uuid(),
|
|
69
|
+
raw: `<!--${betweenComment.value}-->`,
|
|
70
|
+
startOffset: betweenComment.range[0],
|
|
71
|
+
endOffset: betweenComment.range[1],
|
|
72
|
+
startLine: betweenComment.loc.start.line,
|
|
73
|
+
endLine: betweenComment.loc.end.line,
|
|
74
|
+
startCol: betweenComment.loc.start.column + 1,
|
|
75
|
+
endCol: betweenComment.loc.end.column + 1,
|
|
76
|
+
nodeName: '#comment',
|
|
77
|
+
type: 'comment',
|
|
78
|
+
parentNode,
|
|
79
|
+
prevNode,
|
|
80
|
+
nextNode: node,
|
|
81
|
+
isFragment: false,
|
|
82
|
+
isGhost: false,
|
|
83
|
+
};
|
|
84
|
+
comment.parentNode = parentNode;
|
|
85
|
+
comment.prevNode = prevNode;
|
|
86
|
+
comment.nextNode = node;
|
|
87
|
+
if (prevNode) {
|
|
88
|
+
prevNode.nextNode = comment;
|
|
89
|
+
}
|
|
90
|
+
nodeList.push(comment);
|
|
91
|
+
prevNode = comment;
|
|
92
|
+
}
|
|
60
93
|
if (prevNode) {
|
|
61
94
|
if (node.type !== 'endtag') {
|
|
62
95
|
prevNode.nextNode = node;
|
|
@@ -74,7 +107,9 @@ originNode,
|
|
|
74
107
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
75
108
|
prevNode,
|
|
76
109
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
77
|
-
parentNode, rawHtml,
|
|
110
|
+
parentNode, rawHtml,
|
|
111
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
112
|
+
comments, options) {
|
|
78
113
|
const nextNode = null;
|
|
79
114
|
const startOffset = originNode.range[0];
|
|
80
115
|
const endOffset = originNode.range[1];
|
|
@@ -201,7 +236,7 @@ parentNode, rawHtml, options) {
|
|
|
201
236
|
if (endTag) {
|
|
202
237
|
endTag.pearNode = startTag;
|
|
203
238
|
}
|
|
204
|
-
startTag.childNodes = traverse(originNode, startTag, rawHtml, options);
|
|
239
|
+
startTag.childNodes = traverse(originNode, startTag, rawHtml, comments, options);
|
|
205
240
|
return startTag;
|
|
206
241
|
}
|
|
207
242
|
}
|
|
@@ -2,3 +2,4 @@ import * as VueESLintParser from 'vue-eslint-parser';
|
|
|
2
2
|
export type VueTokens = VueESLintParser.AST.ESLintProgram;
|
|
3
3
|
export default function vueParse(vueTemplate: string): VueTokens;
|
|
4
4
|
export type ASTNode = VueESLintParser.AST.VElement | VueESLintParser.AST.VText | VueESLintParser.AST.VExpressionContainer;
|
|
5
|
+
export type ASTComment = VueESLintParser.AST.Token & VueESLintParser.AST.HasLocation;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/vue-parser",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.4",
|
|
4
4
|
"description": "Vue parser for markuplint",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -21,11 +21,10 @@
|
|
|
21
21
|
"clean": "tsc --build --clean"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@markuplint/html-parser": "4.0.0-alpha.
|
|
25
|
-
"@markuplint/ml-ast": "4.0.0-alpha.
|
|
26
|
-
"@markuplint/parser-utils": "4.0.0-alpha.
|
|
27
|
-
"tslib": "^2.6.2",
|
|
24
|
+
"@markuplint/html-parser": "4.0.0-alpha.4",
|
|
25
|
+
"@markuplint/ml-ast": "4.0.0-alpha.4",
|
|
26
|
+
"@markuplint/parser-utils": "4.0.0-alpha.4",
|
|
28
27
|
"vue-eslint-parser": "^9.3.1"
|
|
29
28
|
},
|
|
30
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "991b3aef77fde42c79343ee8c807257a35c589d7"
|
|
31
30
|
}
|