astro-eslint-parser 0.0.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/LICENSE +21 -0
- package/README.md +154 -0
- package/lib/ast.d.ts +42 -0
- package/lib/ast.js +2 -0
- package/lib/astro/index.d.ts +33 -0
- package/lib/astro/index.js +188 -0
- package/lib/context/index.d.ts +48 -0
- package/lib/context/index.js +201 -0
- package/lib/context/script.d.ts +29 -0
- package/lib/context/script.js +348 -0
- package/lib/debug.d.ts +2 -0
- package/lib/debug.js +8 -0
- package/lib/errors.d.ts +13 -0
- package/lib/errors.js +19 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +38 -0
- package/lib/parser/astro-parser/astrojs-compiler-service.d.ts +5 -0
- package/lib/parser/astro-parser/astrojs-compiler-service.js +22 -0
- package/lib/parser/astro-parser/parse.d.ts +5 -0
- package/lib/parser/astro-parser/parse.js +167 -0
- package/lib/parser/astro-parser/wasm_exec.d.ts +35 -0
- package/lib/parser/astro-parser/wasm_exec.js +470 -0
- package/lib/parser/espree.d.ts +6 -0
- package/lib/parser/espree.js +56 -0
- package/lib/parser/index.d.ts +34 -0
- package/lib/parser/index.js +96 -0
- package/lib/parser/resolve-parser.d.ts +16 -0
- package/lib/parser/resolve-parser.js +30 -0
- package/lib/parser/script.d.ts +6 -0
- package/lib/parser/script.js +41 -0
- package/lib/parser/sort.d.ts +6 -0
- package/lib/parser/sort.js +15 -0
- package/lib/traverse.d.ts +27 -0
- package/lib/traverse.js +93 -0
- package/lib/visitor-keys.d.ts +2 -0
- package/lib/visitor-keys.js +13 -0
- package/package.json +91 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ParseResult } from "@astrojs/compiler";
|
|
2
|
+
import type { Context } from ".";
|
|
3
|
+
import type { ESLintExtendedProgram } from "../parser";
|
|
4
|
+
import type { TSESTree } from "@typescript-eslint/types";
|
|
5
|
+
/**
|
|
6
|
+
* Process the template to generate a ScriptContext.
|
|
7
|
+
*/
|
|
8
|
+
export declare function processTemplate(ctx: Context, resultTemplate: ParseResult): ScriptContext;
|
|
9
|
+
export declare class ScriptContext {
|
|
10
|
+
private readonly ctx;
|
|
11
|
+
script: string;
|
|
12
|
+
private consumedIndex;
|
|
13
|
+
private readonly offsets;
|
|
14
|
+
private readonly fragments;
|
|
15
|
+
private readonly tokens;
|
|
16
|
+
private readonly restoreNodeProcesses;
|
|
17
|
+
constructor(ctx: Context);
|
|
18
|
+
skipOriginalOffset(offset: number): void;
|
|
19
|
+
appendOriginal(index: number): void;
|
|
20
|
+
appendScript(fragment: string): void;
|
|
21
|
+
addToken(type: TSESTree.Token["type"], range: TSESTree.Range): void;
|
|
22
|
+
addRestoreNodeProcess(process: (node: TSESTree.Node, result: ESLintExtendedProgram) => boolean): void;
|
|
23
|
+
/**
|
|
24
|
+
* Restore AST nodes
|
|
25
|
+
*/
|
|
26
|
+
restore(result: ESLintExtendedProgram): void;
|
|
27
|
+
private remapLocation;
|
|
28
|
+
private getRemapRange;
|
|
29
|
+
}
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScriptContext = exports.processTemplate = void 0;
|
|
4
|
+
const traverse_1 = require("../traverse");
|
|
5
|
+
const types_1 = require("@typescript-eslint/types");
|
|
6
|
+
const errors_1 = require("../errors");
|
|
7
|
+
const astro_1 = require("../astro");
|
|
8
|
+
/**
|
|
9
|
+
* Process the template to generate a ScriptContext.
|
|
10
|
+
*/
|
|
11
|
+
function processTemplate(ctx, resultTemplate) {
|
|
12
|
+
const script = new ScriptContext(ctx);
|
|
13
|
+
const frontmatter = resultTemplate.ast.children.find((n) => n.type === "frontmatter");
|
|
14
|
+
let fragmentOpened = false;
|
|
15
|
+
if (!frontmatter) {
|
|
16
|
+
script.appendScript("<>");
|
|
17
|
+
fragmentOpened = true;
|
|
18
|
+
}
|
|
19
|
+
(0, astro_1.walkElements)(resultTemplate.ast, (node, parent) => {
|
|
20
|
+
if (node.type === "frontmatter") {
|
|
21
|
+
const start = node.position.start.offset;
|
|
22
|
+
script.appendOriginal(start);
|
|
23
|
+
script.skipOriginalOffset(3);
|
|
24
|
+
const end = node.position.end.offset;
|
|
25
|
+
script.appendOriginal(end - 3);
|
|
26
|
+
script.appendScript(";<>");
|
|
27
|
+
fragmentOpened = true;
|
|
28
|
+
script.skipOriginalOffset(3);
|
|
29
|
+
script.addRestoreNodeProcess((_scriptNode, result) => {
|
|
30
|
+
for (let index = 0; index < result.ast.body.length; index++) {
|
|
31
|
+
const st = result.ast.body[index];
|
|
32
|
+
if (st.type === types_1.AST_NODE_TYPES.EmptyStatement) {
|
|
33
|
+
if (st.range[0] === end - 3 && st.range[1] === end) {
|
|
34
|
+
result.ast.body.splice(index, 1);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
});
|
|
41
|
+
script.addToken(types_1.AST_TOKEN_TYPES.Punctuator, [
|
|
42
|
+
node.position.start.offset,
|
|
43
|
+
node.position.start.offset + 3,
|
|
44
|
+
]);
|
|
45
|
+
script.addToken(types_1.AST_TOKEN_TYPES.Punctuator, [end - 3, end]);
|
|
46
|
+
}
|
|
47
|
+
else if ((0, astro_1.isTag)(node)) {
|
|
48
|
+
for (const attr of node.attributes) {
|
|
49
|
+
if (attr.kind === "shorthand") {
|
|
50
|
+
const start = attr.position.start.offset;
|
|
51
|
+
script.appendOriginal(start);
|
|
52
|
+
script.appendScript(`${attr.name}=`);
|
|
53
|
+
script.addRestoreNodeProcess((scriptNode) => {
|
|
54
|
+
if (scriptNode.type === types_1.AST_NODE_TYPES.JSXAttribute &&
|
|
55
|
+
scriptNode.range[0] === start) {
|
|
56
|
+
const attrNode = scriptNode;
|
|
57
|
+
attrNode.type = "AstroShorthandAttribute";
|
|
58
|
+
const locs = ctx.getLocations(...attrNode.value.expression.range);
|
|
59
|
+
attrNode.name.range = locs.range;
|
|
60
|
+
attrNode.name.loc = locs.loc;
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
else if (attr.kind === "template-literal") {
|
|
67
|
+
const start = (0, astro_1.getAttributeValueStartOffset)(attr, ctx.code);
|
|
68
|
+
const end = (0, astro_1.getAttributeEndOffset)(attr, ctx.code);
|
|
69
|
+
script.appendOriginal(start);
|
|
70
|
+
script.appendScript("{");
|
|
71
|
+
script.appendOriginal(end);
|
|
72
|
+
script.appendScript("}");
|
|
73
|
+
script.addRestoreNodeProcess((scriptNode) => {
|
|
74
|
+
if (scriptNode.type === types_1.AST_NODE_TYPES.JSXAttribute &&
|
|
75
|
+
scriptNode.range[0] === start) {
|
|
76
|
+
const attrNode = scriptNode;
|
|
77
|
+
attrNode.type = "AstroTemplateLiteralAttribute";
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const end = getVoidSelfClosingTag(node, parent, ctx);
|
|
85
|
+
if (end && end.end === ">") {
|
|
86
|
+
script.appendOriginal(end.offset - 1);
|
|
87
|
+
script.appendScript("/");
|
|
88
|
+
}
|
|
89
|
+
if (node.name === "script" || node.name === "style") {
|
|
90
|
+
const text = node.children[0];
|
|
91
|
+
if (text && text.type === "text") {
|
|
92
|
+
const styleNodeStart = node.position.start.offset;
|
|
93
|
+
const start = text.position.start.offset;
|
|
94
|
+
script.appendOriginal(start);
|
|
95
|
+
script.skipOriginalOffset(text.value.length);
|
|
96
|
+
script.addRestoreNodeProcess((scriptNode) => {
|
|
97
|
+
if (scriptNode.type === types_1.AST_NODE_TYPES.JSXElement &&
|
|
98
|
+
scriptNode.range[0] === styleNodeStart) {
|
|
99
|
+
const textNode = Object.assign({ type: types_1.AST_NODE_TYPES.JSXText, value: text.value, raw: text.value, parent: scriptNode }, ctx.getLocations(start, start + text.value.length));
|
|
100
|
+
scriptNode.children = [textNode];
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
});
|
|
105
|
+
script.addToken(types_1.AST_TOKEN_TYPES.JSXText, [
|
|
106
|
+
start,
|
|
107
|
+
start + text.value.length,
|
|
108
|
+
]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else if (node.type === "comment") {
|
|
113
|
+
const start = node.position.start.offset;
|
|
114
|
+
const length = 4 + node.value.length + 3;
|
|
115
|
+
script.appendOriginal(start);
|
|
116
|
+
let targetType;
|
|
117
|
+
if (fragmentOpened) {
|
|
118
|
+
script.appendScript(`<></>`);
|
|
119
|
+
targetType = types_1.AST_NODE_TYPES.JSXFragment;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
script.appendScript(`0;`);
|
|
123
|
+
targetType = types_1.AST_NODE_TYPES.ExpressionStatement;
|
|
124
|
+
}
|
|
125
|
+
script.skipOriginalOffset(length);
|
|
126
|
+
script.addRestoreNodeProcess((scriptNode) => {
|
|
127
|
+
if (scriptNode.range[0] === start &&
|
|
128
|
+
scriptNode.type === targetType) {
|
|
129
|
+
delete scriptNode.children;
|
|
130
|
+
delete scriptNode.openingFragment;
|
|
131
|
+
delete scriptNode.closingFragment;
|
|
132
|
+
delete scriptNode.expression;
|
|
133
|
+
const commentNode = scriptNode;
|
|
134
|
+
commentNode.type = "AstroHTMLComment";
|
|
135
|
+
commentNode.value = node.value;
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
});
|
|
140
|
+
script.addToken("HTMLComment", [
|
|
141
|
+
start,
|
|
142
|
+
start + length,
|
|
143
|
+
]);
|
|
144
|
+
}
|
|
145
|
+
else if (node.type === "doctype") {
|
|
146
|
+
const start = node.position.start.offset;
|
|
147
|
+
const end = node.position.end.offset;
|
|
148
|
+
script.appendOriginal(start);
|
|
149
|
+
let targetType;
|
|
150
|
+
if (fragmentOpened) {
|
|
151
|
+
script.appendScript(`<></>`);
|
|
152
|
+
targetType = types_1.AST_NODE_TYPES.JSXFragment;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
script.appendScript(`0;`);
|
|
156
|
+
targetType = types_1.AST_NODE_TYPES.ExpressionStatement;
|
|
157
|
+
}
|
|
158
|
+
script.skipOriginalOffset(end - start);
|
|
159
|
+
script.addRestoreNodeProcess((scriptNode) => {
|
|
160
|
+
if (scriptNode.range[0] === start &&
|
|
161
|
+
scriptNode.type === targetType) {
|
|
162
|
+
delete scriptNode.children;
|
|
163
|
+
delete scriptNode.openingFragment;
|
|
164
|
+
delete scriptNode.closingFragment;
|
|
165
|
+
delete scriptNode.expression;
|
|
166
|
+
const doctypeNode = scriptNode;
|
|
167
|
+
doctypeNode.type = "AstroDoctype";
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
return false;
|
|
171
|
+
});
|
|
172
|
+
script.addToken("HTMLDocType", [start, end]);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
script.appendOriginal(ctx.code.length);
|
|
176
|
+
script.appendScript("</>");
|
|
177
|
+
return script;
|
|
178
|
+
}
|
|
179
|
+
exports.processTemplate = processTemplate;
|
|
180
|
+
/**
|
|
181
|
+
* If the given tag is a void tag, get the self-closing tag.
|
|
182
|
+
*/
|
|
183
|
+
function getVoidSelfClosingTag(node, parent, ctx) {
|
|
184
|
+
if (node.type === "fragment") {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
if (node.children.length > 0) {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
const code = ctx.code;
|
|
191
|
+
let nextElementIndex = code.length;
|
|
192
|
+
const childIndex = parent.children.indexOf(node);
|
|
193
|
+
if (childIndex === parent.children.length - 1) {
|
|
194
|
+
// last
|
|
195
|
+
nextElementIndex = parent.position.end.offset;
|
|
196
|
+
nextElementIndex = code.lastIndexOf("</", nextElementIndex);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const next = parent.children[childIndex + 1];
|
|
200
|
+
nextElementIndex = next.position.start.offset;
|
|
201
|
+
}
|
|
202
|
+
const endOffset = (0, astro_1.getStartTagEndOffset)(node, code);
|
|
203
|
+
if (code.slice(endOffset, nextElementIndex).trim()) {
|
|
204
|
+
// has end tag
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
offset: endOffset,
|
|
209
|
+
end: code.slice(endOffset - 2, endOffset) === "/>" ? "/>" : ">",
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
class ScriptContext {
|
|
213
|
+
constructor(ctx) {
|
|
214
|
+
this.script = "";
|
|
215
|
+
this.consumedIndex = 0;
|
|
216
|
+
this.offsets = [];
|
|
217
|
+
this.fragments = [];
|
|
218
|
+
this.tokens = [];
|
|
219
|
+
this.restoreNodeProcesses = [];
|
|
220
|
+
this.ctx = ctx;
|
|
221
|
+
}
|
|
222
|
+
skipOriginalOffset(offset) {
|
|
223
|
+
this.consumedIndex += offset;
|
|
224
|
+
}
|
|
225
|
+
appendOriginal(index) {
|
|
226
|
+
this.offsets.push({
|
|
227
|
+
original: this.consumedIndex,
|
|
228
|
+
script: this.script.length,
|
|
229
|
+
});
|
|
230
|
+
this.script += this.ctx.code.slice(this.consumedIndex, index);
|
|
231
|
+
this.consumedIndex = index;
|
|
232
|
+
}
|
|
233
|
+
appendScript(fragment) {
|
|
234
|
+
const start = this.script.length;
|
|
235
|
+
this.script += fragment;
|
|
236
|
+
this.fragments.push({ start, end: this.script.length });
|
|
237
|
+
}
|
|
238
|
+
addToken(type, range) {
|
|
239
|
+
this.tokens.push(this.ctx.buildToken(type, range));
|
|
240
|
+
}
|
|
241
|
+
addRestoreNodeProcess(process) {
|
|
242
|
+
this.restoreNodeProcesses.push(process);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Restore AST nodes
|
|
246
|
+
*/
|
|
247
|
+
restore(result) {
|
|
248
|
+
const last = result.ast.body[result.ast.body.length - 1];
|
|
249
|
+
if (last.type !== "ExpressionStatement") {
|
|
250
|
+
throw new errors_1.ParseError("Unknown state error: Expected ExpressionStatement", last.range[0], this.ctx);
|
|
251
|
+
}
|
|
252
|
+
if (last.expression.type !== "JSXFragment") {
|
|
253
|
+
throw new errors_1.ParseError("Unknown state error: Expected JSXFragment", last.expression.range[0], this.ctx);
|
|
254
|
+
}
|
|
255
|
+
// remap locations
|
|
256
|
+
const traversed = new Set();
|
|
257
|
+
(0, traverse_1.traverseNodes)(result.ast, {
|
|
258
|
+
visitorKeys: result.visitorKeys,
|
|
259
|
+
enterNode: (node) => {
|
|
260
|
+
if (!traversed.has(node)) {
|
|
261
|
+
traversed.add(node);
|
|
262
|
+
this.remapLocation(node);
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
leaveNode: (_node) => {
|
|
266
|
+
// noop
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
const tokens = [...this.tokens];
|
|
270
|
+
for (const token of result.ast.tokens || []) {
|
|
271
|
+
if (this.fragments.some((f) => f.start <= token.range[0] && token.range[1] <= f.end)) {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
this.remapLocation(token);
|
|
275
|
+
tokens.push(token);
|
|
276
|
+
}
|
|
277
|
+
result.ast.tokens = tokens;
|
|
278
|
+
for (const token of result.ast.comments || []) {
|
|
279
|
+
this.remapLocation(token);
|
|
280
|
+
}
|
|
281
|
+
// Process for Astro
|
|
282
|
+
delete last.expression.closingFragment;
|
|
283
|
+
delete last.expression.openingFragment;
|
|
284
|
+
last.expression.type =
|
|
285
|
+
"AstroRootFragment";
|
|
286
|
+
let restoreNodeProcesses = this.restoreNodeProcesses;
|
|
287
|
+
for (const node of traversed) {
|
|
288
|
+
restoreNodeProcesses = restoreNodeProcesses.filter((proc) => !proc(node, result));
|
|
289
|
+
}
|
|
290
|
+
// Adjust program node location
|
|
291
|
+
const first = result.ast.body[0];
|
|
292
|
+
if (first.range[0] < result.ast.range[0]) {
|
|
293
|
+
result.ast.range[0] = first.range[0];
|
|
294
|
+
result.ast.loc.start = this.ctx.getLocFromIndex(result.ast.range[0]);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
remapLocation(node) {
|
|
298
|
+
let [start, end] = node.range;
|
|
299
|
+
const startFragment = this.fragments.find((f) => f.start <= start && start < f.end);
|
|
300
|
+
if (startFragment) {
|
|
301
|
+
start = startFragment.end;
|
|
302
|
+
}
|
|
303
|
+
const endFragment = this.fragments.find((f) => f.start < end && end <= f.end);
|
|
304
|
+
if (endFragment) {
|
|
305
|
+
end = endFragment.start;
|
|
306
|
+
}
|
|
307
|
+
if (end < start) {
|
|
308
|
+
const w = start;
|
|
309
|
+
start = end;
|
|
310
|
+
end = w;
|
|
311
|
+
}
|
|
312
|
+
const locs = this.ctx.getLocations(...this.getRemapRange(start, end));
|
|
313
|
+
node.loc = locs.loc;
|
|
314
|
+
node.range = locs.range;
|
|
315
|
+
if (node.start != null) {
|
|
316
|
+
delete node.start;
|
|
317
|
+
}
|
|
318
|
+
if (node.end != null) {
|
|
319
|
+
delete node.end;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
getRemapRange(start, end) {
|
|
323
|
+
let lastStart = this.offsets[0];
|
|
324
|
+
let lastEnd = this.offsets[0];
|
|
325
|
+
for (const offset of this.offsets) {
|
|
326
|
+
if (offset.script <= start) {
|
|
327
|
+
lastStart = offset;
|
|
328
|
+
}
|
|
329
|
+
if (offset.script < end) {
|
|
330
|
+
lastEnd = offset;
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
if (offset.script === end) {
|
|
334
|
+
const remapStart = lastStart.original + (start - lastStart.script);
|
|
335
|
+
if (this.tokens.some((t) => t.range[0] <= remapStart &&
|
|
336
|
+
offset.original <= t.range[1])) {
|
|
337
|
+
lastEnd = offset;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
const remapStart = lastStart.original + (start - lastStart.script);
|
|
344
|
+
const remapEnd = lastEnd.original + (end - lastEnd.script);
|
|
345
|
+
return [remapStart, remapEnd];
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
exports.ScriptContext = ScriptContext;
|
package/lib/debug.d.ts
ADDED
package/lib/debug.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.debug = void 0;
|
|
7
|
+
const debug_1 = __importDefault(require("debug"));
|
|
8
|
+
exports.debug = (0, debug_1.default)("astro-eslint-parser");
|
package/lib/errors.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Context } from "./context";
|
|
2
|
+
/**
|
|
3
|
+
* Astro parse errors.
|
|
4
|
+
*/
|
|
5
|
+
export declare class ParseError extends SyntaxError {
|
|
6
|
+
index: number;
|
|
7
|
+
lineNumber: number;
|
|
8
|
+
column: number;
|
|
9
|
+
/**
|
|
10
|
+
* Initialize this ParseError instance.
|
|
11
|
+
*/
|
|
12
|
+
constructor(message: string, offset: number, ctx: Context);
|
|
13
|
+
}
|
package/lib/errors.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ParseError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Astro parse errors.
|
|
6
|
+
*/
|
|
7
|
+
class ParseError extends SyntaxError {
|
|
8
|
+
/**
|
|
9
|
+
* Initialize this ParseError instance.
|
|
10
|
+
*/
|
|
11
|
+
constructor(message, offset, ctx) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.index = offset;
|
|
14
|
+
const loc = ctx.getLocFromIndex(offset);
|
|
15
|
+
this.lineNumber = loc.line;
|
|
16
|
+
this.column = loc.column;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.ParseError = ParseError;
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { parseForESLint } from "./parser";
|
|
2
|
+
import * as AST from "./ast";
|
|
3
|
+
import { traverseNodes } from "./traverse";
|
|
4
|
+
import { ParseError } from "./errors";
|
|
5
|
+
export { AST, ParseError };
|
|
6
|
+
export { parseForESLint };
|
|
7
|
+
export declare const VisitorKeys: import("eslint").SourceCode.VisitorKeys;
|
|
8
|
+
export { traverseNodes };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.traverseNodes = exports.VisitorKeys = exports.parseForESLint = exports.ParseError = exports.AST = void 0;
|
|
27
|
+
const parser_1 = require("./parser");
|
|
28
|
+
Object.defineProperty(exports, "parseForESLint", { enumerable: true, get: function () { return parser_1.parseForESLint; } });
|
|
29
|
+
const AST = __importStar(require("./ast"));
|
|
30
|
+
exports.AST = AST;
|
|
31
|
+
const traverse_1 = require("./traverse");
|
|
32
|
+
Object.defineProperty(exports, "traverseNodes", { enumerable: true, get: function () { return traverse_1.traverseNodes; } });
|
|
33
|
+
const visitor_keys_1 = require("./visitor-keys");
|
|
34
|
+
const errors_1 = require("./errors");
|
|
35
|
+
Object.defineProperty(exports, "ParseError", { enumerable: true, get: function () { return errors_1.ParseError; } });
|
|
36
|
+
// Keys
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- ignore
|
|
38
|
+
exports.VisitorKeys = visitor_keys_1.KEYS;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parse = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const wasm_exec_1 = __importDefault(require("./wasm_exec"));
|
|
9
|
+
const go = new wasm_exec_1.default();
|
|
10
|
+
const wasmBuffer = fs_1.default.readFileSync(require.resolve("@astrojs/compiler/astro.wasm"));
|
|
11
|
+
const mod = new WebAssembly.Module(wasmBuffer);
|
|
12
|
+
const instance = new WebAssembly.Instance(mod, go.importObject);
|
|
13
|
+
void go.run(instance);
|
|
14
|
+
const service = globalThis["@astrojs/compiler"];
|
|
15
|
+
/**
|
|
16
|
+
* Parse code by `@astrojs/compiler`
|
|
17
|
+
*/
|
|
18
|
+
function parse(code, options) {
|
|
19
|
+
const ast = JSON.parse(service.parse(code, options).ast);
|
|
20
|
+
return { ast };
|
|
21
|
+
}
|
|
22
|
+
exports.parse = parse;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.parse = void 0;
|
|
27
|
+
const service = __importStar(require("./astrojs-compiler-service"));
|
|
28
|
+
const astro_1 = require("../../astro");
|
|
29
|
+
/**
|
|
30
|
+
* Parse code by `@astrojs/compiler`
|
|
31
|
+
*/
|
|
32
|
+
function parse(code) {
|
|
33
|
+
const ast = service.parse(code, { position: true }).ast;
|
|
34
|
+
fixLocations(ast, code);
|
|
35
|
+
return { ast };
|
|
36
|
+
}
|
|
37
|
+
exports.parse = parse;
|
|
38
|
+
/**
|
|
39
|
+
* Fix locations
|
|
40
|
+
*/
|
|
41
|
+
function fixLocations(node, code) {
|
|
42
|
+
// FIXME: Adjust because the parser does not return the correct location.
|
|
43
|
+
let start = 0;
|
|
44
|
+
(0, astro_1.walk)(node,
|
|
45
|
+
// eslint-disable-next-line complexity -- ignore
|
|
46
|
+
(node) => {
|
|
47
|
+
if (node.type === "frontmatter") {
|
|
48
|
+
start = node.position.start.offset = tokenIndex(code, "---", start);
|
|
49
|
+
start = node.position.end.offset =
|
|
50
|
+
tokenIndex(code, "---", start + 3 + node.value.length) + 3;
|
|
51
|
+
}
|
|
52
|
+
else if (node.type === "fragment" ||
|
|
53
|
+
node.type === "element" ||
|
|
54
|
+
node.type === "component" ||
|
|
55
|
+
node.type === "custom-element") {
|
|
56
|
+
if (!node.position) {
|
|
57
|
+
node.position = { start: {}, end: {} };
|
|
58
|
+
}
|
|
59
|
+
start = node.position.start.offset = tokenIndex(code, "<", start);
|
|
60
|
+
start += 1;
|
|
61
|
+
if (node.type === "element" ||
|
|
62
|
+
node.type === "component" ||
|
|
63
|
+
node.type === "custom-element") {
|
|
64
|
+
start += node.name.length;
|
|
65
|
+
}
|
|
66
|
+
if (!node.attributes.length) {
|
|
67
|
+
start = (0, astro_1.getStartTagEndOffset)(node, code);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (node.type === "attribute") {
|
|
71
|
+
fixLocationForAttr(node, code, start);
|
|
72
|
+
start = (0, astro_1.getAttributeEndOffset)(node, code);
|
|
73
|
+
}
|
|
74
|
+
else if (node.type === "comment") {
|
|
75
|
+
node.position.start.offset = tokenIndex(code, "<!--", start);
|
|
76
|
+
start = (0, astro_1.getCommentEndOffset)(node, code);
|
|
77
|
+
}
|
|
78
|
+
else if (node.type === "text") {
|
|
79
|
+
start = node.position.start.offset = tokenIndex(code, node.value, start);
|
|
80
|
+
start += node.value.length;
|
|
81
|
+
}
|
|
82
|
+
else if (node.type === "expression") {
|
|
83
|
+
start = node.position.start.offset = tokenIndex(code, "{", start);
|
|
84
|
+
start += 1;
|
|
85
|
+
}
|
|
86
|
+
else if (node.type === "doctype") {
|
|
87
|
+
if (!node.position) {
|
|
88
|
+
node.position = { start: {}, end: {} };
|
|
89
|
+
}
|
|
90
|
+
start = node.position.start.offset = tokenIndex(code, "<!", start);
|
|
91
|
+
start += 2;
|
|
92
|
+
start = node.position.end.offset =
|
|
93
|
+
code.indexOf(">", start) + 1;
|
|
94
|
+
}
|
|
95
|
+
else if (node.type === "root") {
|
|
96
|
+
// noop
|
|
97
|
+
}
|
|
98
|
+
}, (node, parent) => {
|
|
99
|
+
if (node.type === "attribute") {
|
|
100
|
+
const attributes = parent.attributes;
|
|
101
|
+
if (attributes[attributes.length - 1] === node) {
|
|
102
|
+
start = (0, astro_1.getStartTagEndOffset)(parent, code);
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (node.type === "expression") {
|
|
107
|
+
start = tokenIndex(code, "}", start) + 1;
|
|
108
|
+
}
|
|
109
|
+
else if (node.type === "fragment") {
|
|
110
|
+
start = tokenIndex(code, "</>", start) + 3;
|
|
111
|
+
}
|
|
112
|
+
else if (node.type === "element" ||
|
|
113
|
+
node.type === "component" ||
|
|
114
|
+
node.type === "custom-element") {
|
|
115
|
+
if (!node.position.end) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
start =
|
|
119
|
+
tokenIndex(code, `</${node.name}`, start) +
|
|
120
|
+
2 +
|
|
121
|
+
node.name.length;
|
|
122
|
+
start = tokenIndex(code, ">", start) + 1;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (node.position.end) {
|
|
128
|
+
node.position.end.offset = start;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Fix locations
|
|
134
|
+
*/
|
|
135
|
+
function fixLocationForAttr(node, code, start) {
|
|
136
|
+
if (node.kind === "empty") {
|
|
137
|
+
node.position.start.offset = tokenIndex(code, node.name, start);
|
|
138
|
+
}
|
|
139
|
+
else if (node.kind === "quoted") {
|
|
140
|
+
node.position.start.offset = tokenIndex(code, node.name, start);
|
|
141
|
+
}
|
|
142
|
+
else if (node.kind === "expression") {
|
|
143
|
+
node.position.start.offset = tokenIndex(code, node.name, start);
|
|
144
|
+
}
|
|
145
|
+
else if (node.kind === "shorthand") {
|
|
146
|
+
node.position.start.offset = tokenIndex(code, "{", start);
|
|
147
|
+
}
|
|
148
|
+
else if (node.kind === "spread") {
|
|
149
|
+
node.position.start.offset = tokenIndex(code, "{", start);
|
|
150
|
+
}
|
|
151
|
+
else if (node.kind === "template-literal") {
|
|
152
|
+
node.position.start.offset = tokenIndex(code, node.name, start);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
throw new Error(`Unknown attr kind: ${node.kind}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get token index
|
|
160
|
+
*/
|
|
161
|
+
function tokenIndex(string, token, position) {
|
|
162
|
+
const index = token.trim() === token ? (0, astro_1.skipSpaces)(string, position) : position;
|
|
163
|
+
if (string.startsWith(token, index)) {
|
|
164
|
+
return index;
|
|
165
|
+
}
|
|
166
|
+
throw new Error(`Unknown token at ${index}, expected: ${JSON.stringify(token)}, actual: ${JSON.stringify(string.slice(index, index + 10))}`);
|
|
167
|
+
}
|