@markuplint/vue-parser 4.0.0-dev.20 → 4.0.0-dev.23
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/index.d.ts +1 -2
- package/lib/index.js +1 -2
- package/lib/parser.d.ts +28 -0
- package/lib/parser.js +238 -0
- package/package.json +6 -6
- package/lib/attr.d.ts +0 -2
- package/lib/attr.js +0 -110
- package/lib/parse.d.ts +0 -2
- package/lib/parse.js +0 -242
package/LICENSE
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export declare const endTag = "xml";
|
|
1
|
+
export { parser } from './parser.js';
|
package/lib/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export const endTag = 'xml';
|
|
1
|
+
export { parser } from './parser.js';
|
package/lib/parser.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/// <reference types="vue-eslint-parser" />
|
|
2
|
+
import type { ASTNode, ASTComment } from './vue-parser/index.js';
|
|
3
|
+
import type { MLASTParentNode, MLASTNodeTreeItem } from '@markuplint/ml-ast';
|
|
4
|
+
import type { Token } from '@markuplint/parser-utils';
|
|
5
|
+
import { ParserError, Parser } from '@markuplint/parser-utils';
|
|
6
|
+
type State = {
|
|
7
|
+
comments: readonly ASTComment[];
|
|
8
|
+
};
|
|
9
|
+
declare class VueParser extends Parser<ASTNode, State> {
|
|
10
|
+
readonly duplicatableAttrs: Set<string>;
|
|
11
|
+
constructor();
|
|
12
|
+
tokenize(): {
|
|
13
|
+
ast: (import("vue-eslint-parser/ast/nodes").VElement | import("vue-eslint-parser/ast/nodes").VText | import("vue-eslint-parser/ast/nodes").VExpressionContainer)[];
|
|
14
|
+
isFragment: boolean;
|
|
15
|
+
};
|
|
16
|
+
parseError(error: any): ParserError;
|
|
17
|
+
nodeize(originNode: ASTNode, parentNode: MLASTParentNode | null, depth: number): readonly MLASTNodeTreeItem[];
|
|
18
|
+
flattenNodes(nodeTree: readonly MLASTNodeTreeItem[]): MLASTNodeTreeItem[];
|
|
19
|
+
afterFlattenNodes(nodeList: readonly MLASTNodeTreeItem[]): MLASTNodeTreeItem[];
|
|
20
|
+
visitAttr(token: Token): (import("@markuplint/ml-ast").MLASTHTMLAttr & {
|
|
21
|
+
__rightText?: string | undefined;
|
|
22
|
+
}) | (import("@markuplint/ml-ast").MLASTSpreadAttr & {
|
|
23
|
+
__rightText?: string | undefined;
|
|
24
|
+
});
|
|
25
|
+
detectElementType(nodeName: string): import("@markuplint/ml-ast").ElementType;
|
|
26
|
+
}
|
|
27
|
+
export declare const parser: VueParser;
|
|
28
|
+
export {};
|
package/lib/parser.js
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { ParserError, Parser } from '@markuplint/parser-utils';
|
|
2
|
+
import { vueParse } from './vue-parser/index.js';
|
|
3
|
+
class VueParser extends Parser {
|
|
4
|
+
constructor() {
|
|
5
|
+
super({
|
|
6
|
+
endTagType: 'xml',
|
|
7
|
+
}, {
|
|
8
|
+
comments: [],
|
|
9
|
+
});
|
|
10
|
+
this.duplicatableAttrs = new Set(['class', 'style']);
|
|
11
|
+
}
|
|
12
|
+
tokenize() {
|
|
13
|
+
const ast = vueParse(this.rawCode);
|
|
14
|
+
if (ast.templateBody?.comments) {
|
|
15
|
+
this.state.comments = ast.templateBody.comments;
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
ast: ast.templateBody?.children ?? [],
|
|
19
|
+
isFragment: true,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
parseError(error) {
|
|
23
|
+
if (error instanceof SyntaxError && 'lineNumber' in error && 'column' in error) {
|
|
24
|
+
throw new ParserError(error.message, {
|
|
25
|
+
line: error.lineNumber,
|
|
26
|
+
col: error.column,
|
|
27
|
+
raw: '',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return super.parseError(error);
|
|
31
|
+
}
|
|
32
|
+
nodeize(
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
34
|
+
originNode, parentNode, depth) {
|
|
35
|
+
const token = this.sliceFragment(originNode.range[0], originNode.range[1]);
|
|
36
|
+
switch (originNode.type) {
|
|
37
|
+
case 'VText': {
|
|
38
|
+
return this.visitText({
|
|
39
|
+
...token,
|
|
40
|
+
depth,
|
|
41
|
+
parentNode,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
case 'VExpressionContainer': {
|
|
45
|
+
return this.visitPsBlock({
|
|
46
|
+
...token,
|
|
47
|
+
depth,
|
|
48
|
+
parentNode,
|
|
49
|
+
nodeName: 'vue-expression-container',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
default: {
|
|
53
|
+
const token = this.sliceFragment(originNode.startTag.range[0], originNode.startTag.range[1]);
|
|
54
|
+
return this.visitElement({
|
|
55
|
+
...token,
|
|
56
|
+
depth,
|
|
57
|
+
parentNode,
|
|
58
|
+
nodeName: originNode.name,
|
|
59
|
+
namespace: originNode.namespace,
|
|
60
|
+
}, originNode.children, {
|
|
61
|
+
createEndTagToken: () => {
|
|
62
|
+
if (!originNode.endTag) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const token = this.sliceFragment(originNode.endTag.range[0], originNode.endTag.range[1]);
|
|
66
|
+
return {
|
|
67
|
+
...token,
|
|
68
|
+
depth,
|
|
69
|
+
parentNode,
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
flattenNodes(nodeTree) {
|
|
77
|
+
const nodeList = super.flattenNodes(nodeTree);
|
|
78
|
+
const newNodeList = [];
|
|
79
|
+
let prevNode = null;
|
|
80
|
+
for (const node of nodeList) {
|
|
81
|
+
const lastOffset = prevNode?.endOffset ?? node.parentNode?.endOffset ?? 0;
|
|
82
|
+
const betweenComment = this.state.comments.find(comment => {
|
|
83
|
+
return lastOffset <= comment.range[0] && comment.range[1] <= node.startOffset;
|
|
84
|
+
});
|
|
85
|
+
if (betweenComment) {
|
|
86
|
+
const token = this.sliceFragment(betweenComment.range[0], betweenComment.range[1]);
|
|
87
|
+
const comment = this.visitComment({
|
|
88
|
+
...token,
|
|
89
|
+
depth: node.depth,
|
|
90
|
+
parentNode: node.parentNode,
|
|
91
|
+
}, {
|
|
92
|
+
isBogus: betweenComment.type === 'HTMLBogusComment',
|
|
93
|
+
})[0];
|
|
94
|
+
if (comment && comment.type === 'comment') {
|
|
95
|
+
newNodeList.push(comment);
|
|
96
|
+
if (node.parentNode) {
|
|
97
|
+
this.appendChild(node.parentNode, comment);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
newNodeList.push(node);
|
|
102
|
+
prevNode = node;
|
|
103
|
+
}
|
|
104
|
+
return newNodeList;
|
|
105
|
+
}
|
|
106
|
+
afterFlattenNodes(nodeList) {
|
|
107
|
+
const optimizedNodeList = super.afterFlattenNodes(nodeList);
|
|
108
|
+
const newNodeList = [];
|
|
109
|
+
let openTemplateTag = false;
|
|
110
|
+
let closeTemplateTag = false;
|
|
111
|
+
for (const node of optimizedNodeList) {
|
|
112
|
+
if (!openTemplateTag && node.type === 'text') {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (node.type === 'starttag' && node.nodeName === 'template' && node.depth === 0) {
|
|
116
|
+
openTemplateTag = true;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (/^<\/template>$/i.test(node.raw) && node.depth === 0) {
|
|
120
|
+
closeTemplateTag = true;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (closeTemplateTag && node.type === 'text') {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
newNodeList.push(node);
|
|
127
|
+
}
|
|
128
|
+
return newNodeList;
|
|
129
|
+
}
|
|
130
|
+
visitAttr(token) {
|
|
131
|
+
const attr = super.visitAttr(token);
|
|
132
|
+
if (attr.type === 'spread') {
|
|
133
|
+
return attr;
|
|
134
|
+
}
|
|
135
|
+
{
|
|
136
|
+
/**
|
|
137
|
+
* `v-on`
|
|
138
|
+
*/
|
|
139
|
+
const [, directive, potentialName] = attr.name.raw.match(/^(v-on:|@)([^.]+)(?:\.([^.]+))?$/i) ?? [];
|
|
140
|
+
if (directive && potentialName) {
|
|
141
|
+
return {
|
|
142
|
+
...attr,
|
|
143
|
+
potentialName: `on${potentialName.toLowerCase()}`,
|
|
144
|
+
isDynamicValue: true,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
{
|
|
149
|
+
/**
|
|
150
|
+
* `v-bind`
|
|
151
|
+
*/
|
|
152
|
+
const [, directive, potentialName, modifier] = attr.name.raw.match(/^(v-bind:|:)([^.]+)(?:\.([^.]+))?$/i) ?? [];
|
|
153
|
+
if (directive && potentialName) {
|
|
154
|
+
if (this.duplicatableAttrs.has(potentialName.toLowerCase())) {
|
|
155
|
+
this.updateAttr(attr, { isDuplicatable: true });
|
|
156
|
+
}
|
|
157
|
+
if (!modifier) {
|
|
158
|
+
return {
|
|
159
|
+
...attr,
|
|
160
|
+
potentialName,
|
|
161
|
+
isDynamicValue: true,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
switch (modifier) {
|
|
165
|
+
case '.attr': {
|
|
166
|
+
return {
|
|
167
|
+
...attr,
|
|
168
|
+
potentialName,
|
|
169
|
+
isDynamicValue: true,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/* eslint-disable unicorn/no-useless-switch-case */
|
|
173
|
+
case '.prop':
|
|
174
|
+
case '.camel':
|
|
175
|
+
default: {
|
|
176
|
+
const name = `v-bind:${potentialName}${modifier ?? ''}`;
|
|
177
|
+
return {
|
|
178
|
+
...attr,
|
|
179
|
+
potentialName: attr.name.raw === name ? undefined : name,
|
|
180
|
+
isDirective: true,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/* eslint-enable unicorn/no-useless-switch-case */
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
{
|
|
188
|
+
/**
|
|
189
|
+
* `v-model`
|
|
190
|
+
*/
|
|
191
|
+
const [, directive] = attr.name.raw.match(/^(v-model)(?:\.([^.]+))?$/i) ?? [];
|
|
192
|
+
if (directive) {
|
|
193
|
+
return {
|
|
194
|
+
...attr,
|
|
195
|
+
isDirective: true,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
{
|
|
200
|
+
/**
|
|
201
|
+
* `v-slot`
|
|
202
|
+
*/
|
|
203
|
+
const slotName = (attr.name.raw.match(/^(v-slot:|#)(.+)$/i) ?? [])[2];
|
|
204
|
+
const name = `v-slot:${slotName}`;
|
|
205
|
+
if (slotName) {
|
|
206
|
+
return {
|
|
207
|
+
...attr,
|
|
208
|
+
potentialName: attr.name.raw === name ? undefined : name,
|
|
209
|
+
isDirective: true,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* If directives
|
|
215
|
+
*/
|
|
216
|
+
if (attr.name.raw.startsWith('v-')) {
|
|
217
|
+
return {
|
|
218
|
+
...attr,
|
|
219
|
+
isDirective: true,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
return attr;
|
|
223
|
+
}
|
|
224
|
+
detectElementType(nodeName) {
|
|
225
|
+
return super.detectElementType(nodeName, [
|
|
226
|
+
'component',
|
|
227
|
+
'slot',
|
|
228
|
+
'Transition',
|
|
229
|
+
'TransitionGroup',
|
|
230
|
+
'KeepAlive',
|
|
231
|
+
'Teleport',
|
|
232
|
+
'Suspense',
|
|
233
|
+
// Backward compatibility
|
|
234
|
+
/^[A-Z]/,
|
|
235
|
+
]);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
export const parser = new VueParser();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/vue-parser",
|
|
3
|
-
"version": "4.0.0-dev.
|
|
3
|
+
"version": "4.0.0-dev.23+d6f2aa9bc",
|
|
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,10 +21,10 @@
|
|
|
21
21
|
"clean": "tsc --build --clean"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@markuplint/html-parser": "4.0.0-dev.
|
|
25
|
-
"@markuplint/ml-ast": "4.0.0-dev.
|
|
26
|
-
"@markuplint/parser-utils": "4.0.0-dev.
|
|
27
|
-
"vue-eslint-parser": "^9.
|
|
24
|
+
"@markuplint/html-parser": "4.0.0-dev.23+d6f2aa9bc",
|
|
25
|
+
"@markuplint/ml-ast": "4.0.0-dev.23+d6f2aa9bc",
|
|
26
|
+
"@markuplint/parser-utils": "4.0.0-dev.23+d6f2aa9bc",
|
|
27
|
+
"vue-eslint-parser": "^9.4.1"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "d6f2aa9bc287768466f23b5340e4e0eecfa30d59"
|
|
30
30
|
}
|
package/lib/attr.d.ts
DELETED
package/lib/attr.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
const duplicatableAttrs = new Set(['class', 'style']);
|
|
2
|
-
export function attr(
|
|
3
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
4
|
-
attr) {
|
|
5
|
-
if (attr.type !== 'html-attr') {
|
|
6
|
-
const name = attr.potentialName;
|
|
7
|
-
if (duplicatableAttrs.has(name)) {
|
|
8
|
-
attr.isDuplicatable = true;
|
|
9
|
-
}
|
|
10
|
-
return attr;
|
|
11
|
-
}
|
|
12
|
-
{
|
|
13
|
-
/**
|
|
14
|
-
* `v-on`
|
|
15
|
-
*/
|
|
16
|
-
const [, directive, potentialName, modifier] = attr.name.raw.match(/^(v-on:|@)([^.]+)(?:\.([^.]+))?$/i) ?? [];
|
|
17
|
-
if (directive && potentialName) {
|
|
18
|
-
return {
|
|
19
|
-
...attr,
|
|
20
|
-
potentialName: `on${potentialName.toLowerCase()}`,
|
|
21
|
-
isDynamicValue: true,
|
|
22
|
-
// @ts-ignore
|
|
23
|
-
_modifier: modifier,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
{
|
|
28
|
-
/**
|
|
29
|
-
* `v-bind`
|
|
30
|
-
*/
|
|
31
|
-
const [, directive, potentialName, modifier] = attr.name.raw.match(/^(v-bind:|:)([^.]+)(?:\.([^.]+))?$/i) ?? [];
|
|
32
|
-
if (directive && potentialName) {
|
|
33
|
-
if (duplicatableAttrs.has(potentialName.toLowerCase())) {
|
|
34
|
-
attr.isDuplicatable = true;
|
|
35
|
-
}
|
|
36
|
-
if (!modifier) {
|
|
37
|
-
return {
|
|
38
|
-
...attr,
|
|
39
|
-
potentialName,
|
|
40
|
-
isDynamicValue: true,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
switch (modifier) {
|
|
44
|
-
case '.attr': {
|
|
45
|
-
return {
|
|
46
|
-
...attr,
|
|
47
|
-
potentialName,
|
|
48
|
-
isDynamicValue: true,
|
|
49
|
-
// @ts-ignore
|
|
50
|
-
_modifier: modifier,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/* eslint-disable unicorn/no-useless-switch-case */
|
|
54
|
-
// TODO: Supporting for `prop` and `camel` https://github.com/markuplint/markuplint/pull/681
|
|
55
|
-
case '.prop':
|
|
56
|
-
case '.camel':
|
|
57
|
-
default: {
|
|
58
|
-
const name = `v-bind:${potentialName}${modifier ?? ''}`;
|
|
59
|
-
return {
|
|
60
|
-
...attr,
|
|
61
|
-
potentialName: attr.name.raw === name ? undefined : name,
|
|
62
|
-
isDirective: true,
|
|
63
|
-
// @ts-ignore
|
|
64
|
-
_modifier: modifier,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
/* eslint-enable unicorn/no-useless-switch-case */
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
{
|
|
72
|
-
/**
|
|
73
|
-
* `v-model`
|
|
74
|
-
*/
|
|
75
|
-
const [, directive, modifier] = attr.name.raw.match(/^(v-model)(?:\.([^.]+))?$/i) ?? [];
|
|
76
|
-
if (directive) {
|
|
77
|
-
// TODO: Supporting for `v-model` https://github.com/markuplint/markuplint/pull/681
|
|
78
|
-
return {
|
|
79
|
-
...attr,
|
|
80
|
-
isDirective: true,
|
|
81
|
-
// @ts-ignore
|
|
82
|
-
_modifier: modifier,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
{
|
|
87
|
-
/**
|
|
88
|
-
* `v-slot`
|
|
89
|
-
*/
|
|
90
|
-
const slotName = (attr.name.raw.match(/^(v-slot:|#)(.+)$/i) ?? [])[2];
|
|
91
|
-
const name = `v-slot:${slotName}`;
|
|
92
|
-
if (slotName) {
|
|
93
|
-
return {
|
|
94
|
-
...attr,
|
|
95
|
-
potentialName: attr.name.raw === name ? undefined : name,
|
|
96
|
-
isDirective: true,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* If directives
|
|
102
|
-
*/
|
|
103
|
-
if (attr.name.raw.startsWith('v-')) {
|
|
104
|
-
return {
|
|
105
|
-
...attr,
|
|
106
|
-
isDirective: true,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
return attr;
|
|
110
|
-
}
|
package/lib/parse.d.ts
DELETED
package/lib/parse.js
DELETED
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
import { flattenNodes, getEndCol, getEndLine, uuid, ParserError, detectElementType, tagParser, } from '@markuplint/parser-utils';
|
|
2
|
-
import { attr } from './attr.js';
|
|
3
|
-
import { vueParse } from './vue-parser/index.js';
|
|
4
|
-
export const parse = (rawCode, options) => {
|
|
5
|
-
let ast;
|
|
6
|
-
try {
|
|
7
|
-
ast = vueParse(rawCode);
|
|
8
|
-
}
|
|
9
|
-
catch (error) {
|
|
10
|
-
if (error instanceof SyntaxError && 'lineNumber' in error && 'column' in error) {
|
|
11
|
-
throw new ParserError(
|
|
12
|
-
// @ts-ignore
|
|
13
|
-
error.message, {
|
|
14
|
-
// @ts-ignore
|
|
15
|
-
line: error.lineNumber,
|
|
16
|
-
// @ts-ignore
|
|
17
|
-
col: error.column,
|
|
18
|
-
raw: '',
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
nodeList: [],
|
|
23
|
-
isFragment: true,
|
|
24
|
-
parseError: error instanceof Error ? error.message : new Error(`${error}`).message,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
const nodeList = ast.templateBody
|
|
28
|
-
? flattenNodes(traverse(ast.templateBody, null, rawCode, ast.templateBody.comments, options), rawCode)
|
|
29
|
-
: [];
|
|
30
|
-
// Remove `</template>`
|
|
31
|
-
const templateEndTagIndex = nodeList.findIndex(node => /\s*<\/\s*template\s*>\s*/i.test(node.raw));
|
|
32
|
-
if (templateEndTagIndex !== -1) {
|
|
33
|
-
const templateEndTag = nodeList[templateEndTagIndex];
|
|
34
|
-
for (const node of nodeList) {
|
|
35
|
-
if (node.nextNode && node.nextNode.uuid === templateEndTag?.uuid) {
|
|
36
|
-
node.nextNode = null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
nodeList.splice(templateEndTagIndex, 1);
|
|
40
|
-
}
|
|
41
|
-
return {
|
|
42
|
-
nodeList,
|
|
43
|
-
isFragment: true,
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
function traverse(
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
48
|
-
rootNode, parentNode = null, rawHtml,
|
|
49
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
50
|
-
comments, options) {
|
|
51
|
-
const nodeList = [];
|
|
52
|
-
if (rootNode.type !== 'VElement') {
|
|
53
|
-
return [];
|
|
54
|
-
}
|
|
55
|
-
let prevNode = null;
|
|
56
|
-
for (const vNode of rootNode.children) {
|
|
57
|
-
const node = nodeize(vNode, prevNode, parentNode, rawHtml, comments, options);
|
|
58
|
-
if (!node) {
|
|
59
|
-
continue;
|
|
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
|
-
}
|
|
92
|
-
if (prevNode) {
|
|
93
|
-
if (node.type !== 'endtag') {
|
|
94
|
-
prevNode.nextNode = node;
|
|
95
|
-
}
|
|
96
|
-
node.prevNode = prevNode;
|
|
97
|
-
}
|
|
98
|
-
prevNode = node;
|
|
99
|
-
nodeList.push(node);
|
|
100
|
-
}
|
|
101
|
-
return nodeList;
|
|
102
|
-
}
|
|
103
|
-
function nodeize(
|
|
104
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
105
|
-
originNode,
|
|
106
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
107
|
-
prevNode,
|
|
108
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
109
|
-
parentNode, rawHtml,
|
|
110
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
111
|
-
comments, options) {
|
|
112
|
-
const nextNode = null;
|
|
113
|
-
const startOffset = originNode.range[0];
|
|
114
|
-
const endOffset = originNode.range[1];
|
|
115
|
-
const startLine = originNode.loc.start.line;
|
|
116
|
-
const endLine = originNode.loc.end.line;
|
|
117
|
-
const startCol = originNode.loc.start.column + 1;
|
|
118
|
-
const endCol = originNode.loc.end.column + 1;
|
|
119
|
-
const raw = rawHtml.slice(startOffset, endOffset ?? startOffset);
|
|
120
|
-
switch (originNode.type) {
|
|
121
|
-
case 'VText': {
|
|
122
|
-
const node = {
|
|
123
|
-
uuid: uuid(),
|
|
124
|
-
raw,
|
|
125
|
-
startOffset,
|
|
126
|
-
endOffset,
|
|
127
|
-
startLine,
|
|
128
|
-
endLine,
|
|
129
|
-
startCol,
|
|
130
|
-
endCol,
|
|
131
|
-
nodeName: '#text',
|
|
132
|
-
type: 'text',
|
|
133
|
-
parentNode,
|
|
134
|
-
prevNode,
|
|
135
|
-
nextNode,
|
|
136
|
-
isFragment: false,
|
|
137
|
-
isGhost: false,
|
|
138
|
-
};
|
|
139
|
-
return node;
|
|
140
|
-
}
|
|
141
|
-
case 'VExpressionContainer': {
|
|
142
|
-
return {
|
|
143
|
-
uuid: uuid(),
|
|
144
|
-
raw,
|
|
145
|
-
startOffset,
|
|
146
|
-
endOffset,
|
|
147
|
-
startLine,
|
|
148
|
-
endLine,
|
|
149
|
-
startCol,
|
|
150
|
-
endCol,
|
|
151
|
-
nodeName: '#vue-expression-container',
|
|
152
|
-
type: 'psblock',
|
|
153
|
-
parentNode,
|
|
154
|
-
prevNode,
|
|
155
|
-
nextNode,
|
|
156
|
-
isFragment: false,
|
|
157
|
-
isGhost: false,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
default: {
|
|
161
|
-
const tagLoc = originNode.startTag;
|
|
162
|
-
const startTagRaw = rawHtml.slice(tagLoc.range[0], tagLoc.range[1]);
|
|
163
|
-
const tagTokens = tagParser(startTagRaw, startLine, startCol, startOffset);
|
|
164
|
-
const tagName = tagTokens.tagName;
|
|
165
|
-
let endTag = null;
|
|
166
|
-
const endTagLoc = originNode.endTag;
|
|
167
|
-
if (endTagLoc) {
|
|
168
|
-
const endTagRaw = rawHtml.slice(endTagLoc.range[0], endTagLoc.range[1]);
|
|
169
|
-
const endTagTokens = tagParser(endTagRaw, endTagLoc.loc.start.line, endTagLoc.loc.start.column, endTagLoc.range[0]);
|
|
170
|
-
const endTagName = endTagTokens.tagName;
|
|
171
|
-
endTag = {
|
|
172
|
-
uuid: uuid(),
|
|
173
|
-
raw: endTagRaw,
|
|
174
|
-
startOffset: endTagLoc.range[0],
|
|
175
|
-
endOffset: endTagLoc.range[1],
|
|
176
|
-
startLine: endTagLoc.loc.start.line,
|
|
177
|
-
endLine: endTagLoc.loc.end.line,
|
|
178
|
-
startCol: endTagLoc.loc.start.column + 1,
|
|
179
|
-
endCol: endTagLoc.loc.end.column + 1,
|
|
180
|
-
nodeName: endTagName,
|
|
181
|
-
type: 'endtag',
|
|
182
|
-
namespace: originNode.namespace,
|
|
183
|
-
attributes: endTagTokens.attrs,
|
|
184
|
-
parentNode,
|
|
185
|
-
prevNode,
|
|
186
|
-
nextNode,
|
|
187
|
-
pearNode: null,
|
|
188
|
-
isFragment: false,
|
|
189
|
-
isGhost: false,
|
|
190
|
-
tagOpenChar: '</',
|
|
191
|
-
tagCloseChar: '>',
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
const startTag = {
|
|
195
|
-
uuid: uuid(),
|
|
196
|
-
raw: startTagRaw,
|
|
197
|
-
startOffset,
|
|
198
|
-
endOffset: startOffset + startTagRaw.length,
|
|
199
|
-
startLine,
|
|
200
|
-
endLine: getEndLine(startTagRaw, startLine),
|
|
201
|
-
startCol,
|
|
202
|
-
endCol: getEndCol(startTagRaw, startCol),
|
|
203
|
-
nodeName: tagName,
|
|
204
|
-
type: 'starttag',
|
|
205
|
-
namespace: originNode.namespace,
|
|
206
|
-
elementType: detectElementType(tagName, options?.authoredElementName,
|
|
207
|
-
/**
|
|
208
|
-
* @see https://vuejs.org/api/built-in-components.html
|
|
209
|
-
* @see https://vuejs.org/api/built-in-special-elements.html
|
|
210
|
-
*/
|
|
211
|
-
[
|
|
212
|
-
'component',
|
|
213
|
-
'slot',
|
|
214
|
-
'Transition',
|
|
215
|
-
'TransitionGroup',
|
|
216
|
-
'KeepAlive',
|
|
217
|
-
'Teleport',
|
|
218
|
-
'Suspense',
|
|
219
|
-
// Backward compatibility
|
|
220
|
-
/^[A-Z]/,
|
|
221
|
-
]),
|
|
222
|
-
attributes: tagTokens.attrs.map(attr),
|
|
223
|
-
hasSpreadAttr: false,
|
|
224
|
-
parentNode,
|
|
225
|
-
prevNode,
|
|
226
|
-
nextNode,
|
|
227
|
-
pearNode: endTag,
|
|
228
|
-
selfClosingSolidus: tagTokens.selfClosingSolidus,
|
|
229
|
-
endSpace: tagTokens.afterAttrSpaces,
|
|
230
|
-
isFragment: false,
|
|
231
|
-
isGhost: false,
|
|
232
|
-
tagOpenChar: '<',
|
|
233
|
-
tagCloseChar: '>',
|
|
234
|
-
};
|
|
235
|
-
if (endTag) {
|
|
236
|
-
endTag.pearNode = startTag;
|
|
237
|
-
}
|
|
238
|
-
startTag.childNodes = traverse(originNode, startTag, rawHtml, comments, options);
|
|
239
|
-
return startTag;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|