@markuplint/vue-parser 4.0.0-alpha.3 → 4.0.0-alpha.5
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/LICENSE +1 -1
- package/lib/attr.js +9 -7
- package/lib/parse.js +51 -17
- package/lib/vue-parser/index.d.ts +2 -1
- package/lib/vue-parser/index.js +1 -1
- package/package.json +5 -6
package/LICENSE
CHANGED
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
|
@@ -1,32 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { flattenNodes, getEndCol, getEndLine, uuid, ParserError, detectElementType } from '@markuplint/parser-utils';
|
|
1
|
+
import { flattenNodes, getEndCol, getEndLine, uuid, ParserError, detectElementType, tagParser, } from '@markuplint/parser-utils';
|
|
3
2
|
import { attr } from './attr.js';
|
|
4
|
-
import vueParse from './vue-parser/index.js';
|
|
3
|
+
import { vueParse } from './vue-parser/index.js';
|
|
5
4
|
export const parse = (rawCode, options) => {
|
|
6
5
|
let ast;
|
|
7
6
|
try {
|
|
8
7
|
ast = vueParse(rawCode);
|
|
9
8
|
}
|
|
10
|
-
catch (
|
|
11
|
-
if (
|
|
9
|
+
catch (error) {
|
|
10
|
+
if (error instanceof SyntaxError && 'lineNumber' in error && 'column' in error) {
|
|
12
11
|
throw new ParserError(
|
|
13
12
|
// @ts-ignore
|
|
14
|
-
|
|
13
|
+
error.message, {
|
|
15
14
|
// @ts-ignore
|
|
16
|
-
line:
|
|
15
|
+
line: error.lineNumber,
|
|
17
16
|
// @ts-ignore
|
|
18
|
-
col:
|
|
17
|
+
col: error.column,
|
|
19
18
|
raw: '',
|
|
20
19
|
});
|
|
21
20
|
}
|
|
22
21
|
return {
|
|
23
22
|
nodeList: [],
|
|
24
23
|
isFragment: true,
|
|
25
|
-
parseError:
|
|
24
|
+
parseError: error instanceof Error ? error.message : new Error(`${error}`).message,
|
|
26
25
|
};
|
|
27
26
|
}
|
|
28
27
|
const nodeList = ast.templateBody
|
|
29
|
-
? flattenNodes(traverse(ast.templateBody, null, rawCode, options), rawCode)
|
|
28
|
+
? flattenNodes(traverse(ast.templateBody, null, rawCode, ast.templateBody.comments, options), rawCode)
|
|
30
29
|
: [];
|
|
31
30
|
// Remove `</template>`
|
|
32
31
|
const templateEndTagIndex = nodeList.findIndex(node => /\s*<\/\s*template\s*>\s*/i.test(node.raw));
|
|
@@ -46,17 +45,50 @@ export const parse = (rawCode, options) => {
|
|
|
46
45
|
};
|
|
47
46
|
function traverse(
|
|
48
47
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
49
|
-
rootNode, parentNode = null, rawHtml,
|
|
48
|
+
rootNode, parentNode = null, rawHtml,
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
50
|
+
comments, options) {
|
|
50
51
|
const nodeList = [];
|
|
51
52
|
if (rootNode.type !== 'VElement') {
|
|
52
53
|
return [];
|
|
53
54
|
}
|
|
54
55
|
let prevNode = null;
|
|
55
56
|
for (const vNode of rootNode.children) {
|
|
56
|
-
const node = nodeize(vNode, prevNode, parentNode, rawHtml, options);
|
|
57
|
+
const node = nodeize(vNode, prevNode, parentNode, rawHtml, comments, options);
|
|
57
58
|
if (!node) {
|
|
58
59
|
continue;
|
|
59
60
|
}
|
|
61
|
+
const lastOffset = prevNode?.endOffset ?? parentNode?.endOffset ?? 0;
|
|
62
|
+
const betweenComment = comments.find(comment => {
|
|
63
|
+
return lastOffset <= comment.range[0] && comment.range[1] <= node.startOffset;
|
|
64
|
+
});
|
|
65
|
+
if (betweenComment) {
|
|
66
|
+
const comment = {
|
|
67
|
+
uuid: uuid(),
|
|
68
|
+
raw: `<!--${betweenComment.value}-->`,
|
|
69
|
+
startOffset: betweenComment.range[0],
|
|
70
|
+
endOffset: betweenComment.range[1],
|
|
71
|
+
startLine: betweenComment.loc.start.line,
|
|
72
|
+
endLine: betweenComment.loc.end.line,
|
|
73
|
+
startCol: betweenComment.loc.start.column + 1,
|
|
74
|
+
endCol: betweenComment.loc.end.column + 1,
|
|
75
|
+
nodeName: '#comment',
|
|
76
|
+
type: 'comment',
|
|
77
|
+
parentNode,
|
|
78
|
+
prevNode,
|
|
79
|
+
nextNode: node,
|
|
80
|
+
isFragment: false,
|
|
81
|
+
isGhost: false,
|
|
82
|
+
};
|
|
83
|
+
comment.parentNode = parentNode;
|
|
84
|
+
comment.prevNode = prevNode;
|
|
85
|
+
comment.nextNode = node;
|
|
86
|
+
if (prevNode) {
|
|
87
|
+
prevNode.nextNode = comment;
|
|
88
|
+
}
|
|
89
|
+
nodeList.push(comment);
|
|
90
|
+
prevNode = comment;
|
|
91
|
+
}
|
|
60
92
|
if (prevNode) {
|
|
61
93
|
if (node.type !== 'endtag') {
|
|
62
94
|
prevNode.nextNode = node;
|
|
@@ -74,7 +106,9 @@ originNode,
|
|
|
74
106
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
75
107
|
prevNode,
|
|
76
108
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
77
|
-
parentNode, rawHtml,
|
|
109
|
+
parentNode, rawHtml,
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
111
|
+
comments, options) {
|
|
78
112
|
const nextNode = null;
|
|
79
113
|
const startOffset = originNode.range[0];
|
|
80
114
|
const endOffset = originNode.range[1];
|
|
@@ -126,13 +160,13 @@ parentNode, rawHtml, options) {
|
|
|
126
160
|
default: {
|
|
127
161
|
const tagLoc = originNode.startTag;
|
|
128
162
|
const startTagRaw = rawHtml.slice(tagLoc.range[0], tagLoc.range[1]);
|
|
129
|
-
const tagTokens =
|
|
163
|
+
const tagTokens = tagParser(startTagRaw, startLine, startCol, startOffset);
|
|
130
164
|
const tagName = tagTokens.tagName;
|
|
131
165
|
let endTag = null;
|
|
132
166
|
const endTagLoc = originNode.endTag;
|
|
133
167
|
if (endTagLoc) {
|
|
134
168
|
const endTagRaw = rawHtml.slice(endTagLoc.range[0], endTagLoc.range[1]);
|
|
135
|
-
const endTagTokens =
|
|
169
|
+
const endTagTokens = tagParser(endTagRaw, endTagLoc.loc.start.line, endTagLoc.loc.start.column, endTagLoc.range[0]);
|
|
136
170
|
const endTagName = endTagTokens.tagName;
|
|
137
171
|
endTag = {
|
|
138
172
|
uuid: uuid(),
|
|
@@ -192,7 +226,7 @@ parentNode, rawHtml, options) {
|
|
|
192
226
|
nextNode,
|
|
193
227
|
pearNode: endTag,
|
|
194
228
|
selfClosingSolidus: tagTokens.selfClosingSolidus,
|
|
195
|
-
endSpace: tagTokens.
|
|
229
|
+
endSpace: tagTokens.afterAttrSpaces,
|
|
196
230
|
isFragment: false,
|
|
197
231
|
isGhost: false,
|
|
198
232
|
tagOpenChar: '<',
|
|
@@ -201,7 +235,7 @@ parentNode, rawHtml, options) {
|
|
|
201
235
|
if (endTag) {
|
|
202
236
|
endTag.pearNode = startTag;
|
|
203
237
|
}
|
|
204
|
-
startTag.childNodes = traverse(originNode, startTag, rawHtml, options);
|
|
238
|
+
startTag.childNodes = traverse(originNode, startTag, rawHtml, comments, options);
|
|
205
239
|
return startTag;
|
|
206
240
|
}
|
|
207
241
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as VueESLintParser from 'vue-eslint-parser';
|
|
2
2
|
export type VueTokens = VueESLintParser.AST.ESLintProgram;
|
|
3
|
-
export
|
|
3
|
+
export declare 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/lib/vue-parser/index.js
CHANGED
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.5",
|
|
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.5",
|
|
25
|
+
"@markuplint/ml-ast": "4.0.0-alpha.5",
|
|
26
|
+
"@markuplint/parser-utils": "4.0.0-alpha.5",
|
|
28
27
|
"vue-eslint-parser": "^9.3.1"
|
|
29
28
|
},
|
|
30
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "0c3e4690662edf1765bcc4b6411ec5507c1e2ea3"
|
|
31
30
|
}
|