astro-eslint-parser 0.0.18 → 0.2.1
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 +22 -11
- package/lib/ast/astro.d.ts +1 -1
- package/lib/ast/index.d.ts +6 -0
- package/lib/ast/jsx.d.ts +18 -18
- package/lib/astro/index.js +2 -4
- package/lib/astro-tools/index.d.ts +21 -0
- package/lib/astro-tools/index.js +26 -0
- package/lib/context/index.d.ts +13 -8
- package/lib/context/index.js +51 -100
- package/lib/context/parser-options.d.ts +8 -0
- package/lib/context/parser-options.js +71 -0
- package/lib/{parser → context/resolve-parser}/espree.d.ts +1 -1
- package/lib/{parser → context/resolve-parser}/espree.js +3 -18
- package/lib/context/resolve-parser/index.d.ts +5 -0
- package/lib/{parser/resolve-parser.js → context/resolve-parser/index.js} +0 -0
- package/lib/context/script.d.ts +1 -1
- package/lib/context/script.js +2 -3
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -1
- package/lib/parser/astro-parser/astrojs-compiler-service.d.ts +2 -4
- package/lib/parser/astro-parser/astrojs-compiler-service.js +3 -12
- package/lib/parser/astro-parser/astrojs-compiler-worker.d.ts +1 -0
- package/lib/parser/astro-parser/astrojs-compiler-worker.js +11 -0
- package/lib/parser/astro-parser/parse.js +7 -51
- package/lib/parser/index.d.ts +0 -17
- package/lib/parser/index.js +6 -31
- package/lib/parser/lru-cache.d.ts +7 -0
- package/lib/parser/lru-cache.js +32 -0
- package/lib/parser/process-template.js +24 -5
- package/lib/parser/script.d.ts +3 -2
- package/lib/parser/script.js +18 -19
- package/lib/parser/template.d.ts +10 -0
- package/lib/parser/template.js +102 -0
- package/lib/parser/ts-patch.d.ts +8 -0
- package/lib/parser/ts-patch.js +58 -0
- package/lib/types.d.ts +21 -0
- package/lib/types.js +2 -0
- package/package.json +8 -5
- package/lib/parser/astro-parser/wasm_exec.d.ts +0 -35
- package/lib/parser/astro-parser/wasm_exec.js +0 -470
- package/lib/parser/resolve-parser.d.ts +0 -16
package/lib/context/script.js
CHANGED
|
@@ -50,7 +50,6 @@ class ScriptContext {
|
|
|
50
50
|
* Restore AST nodes
|
|
51
51
|
*/
|
|
52
52
|
restore(result) {
|
|
53
|
-
var _a, _b;
|
|
54
53
|
// remap locations
|
|
55
54
|
const traversed = new Map();
|
|
56
55
|
(0, traverse_1.traverseNodes)(result.ast, {
|
|
@@ -102,8 +101,8 @@ class ScriptContext {
|
|
|
102
101
|
// Adjust program node location
|
|
103
102
|
const firstOffset = Math.min(...[
|
|
104
103
|
result.ast.body[0],
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
result.ast.tokens?.[0],
|
|
105
|
+
result.ast.comments?.[0],
|
|
107
106
|
]
|
|
108
107
|
.filter(Boolean)
|
|
109
108
|
.map((t) => t.range[0]));
|
package/lib/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { parseForESLint } from "./parser";
|
|
2
|
+
import { parseTemplate, ParseTemplateResult } from "./astro-tools";
|
|
2
3
|
import * as AST from "./ast";
|
|
3
4
|
import { traverseNodes } from "./traverse";
|
|
4
5
|
import { ParseError } from "./errors";
|
|
5
6
|
export { AST, ParseError };
|
|
6
7
|
export { parseForESLint };
|
|
7
8
|
export declare const VisitorKeys: import("eslint").SourceCode.VisitorKeys;
|
|
8
|
-
export { traverseNodes };
|
|
9
|
+
export { traverseNodes, parseTemplate, ParseTemplateResult };
|
package/lib/index.js
CHANGED
|
@@ -23,9 +23,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.traverseNodes = exports.VisitorKeys = exports.parseForESLint = exports.ParseError = exports.AST = void 0;
|
|
26
|
+
exports.parseTemplate = exports.traverseNodes = exports.VisitorKeys = exports.parseForESLint = exports.ParseError = exports.AST = void 0;
|
|
27
27
|
const parser_1 = require("./parser");
|
|
28
28
|
Object.defineProperty(exports, "parseForESLint", { enumerable: true, get: function () { return parser_1.parseForESLint; } });
|
|
29
|
+
const astro_tools_1 = require("./astro-tools");
|
|
30
|
+
Object.defineProperty(exports, "parseTemplate", { enumerable: true, get: function () { return astro_tools_1.parseTemplate; } });
|
|
29
31
|
const AST = __importStar(require("./ast"));
|
|
30
32
|
exports.AST = AST;
|
|
31
33
|
const traverse_1 = require("./traverse");
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import type { ParseOptions } from "@astrojs/compiler";
|
|
1
|
+
import type { ParseOptions, ParseResult } from "@astrojs/compiler";
|
|
2
2
|
/**
|
|
3
3
|
* Parse code by `@astrojs/compiler`
|
|
4
4
|
*/
|
|
5
|
-
export declare function parse(code: string, options: ParseOptions):
|
|
6
|
-
ast: string;
|
|
7
|
-
};
|
|
5
|
+
export declare function parse(code: string, options: ParseOptions): ParseResult;
|
|
@@ -1,21 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.parse = void 0;
|
|
7
|
-
const
|
|
8
|
-
const
|
|
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"];
|
|
4
|
+
const synckit_1 = require("synckit");
|
|
5
|
+
const parseSync = (0, synckit_1.createSyncFn)(require.resolve("./astrojs-compiler-worker"));
|
|
15
6
|
/**
|
|
16
7
|
* Parse code by `@astrojs/compiler`
|
|
17
8
|
*/
|
|
18
9
|
function parse(code, options) {
|
|
19
|
-
return
|
|
10
|
+
return parseSync(code, options);
|
|
20
11
|
}
|
|
21
12
|
exports.parse = parse;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const synckit_1 = require("synckit");
|
|
4
|
+
const dynamicImport = new Function("m", "return import(m)");
|
|
5
|
+
(0, synckit_1.runAsWorker)(async (source) => {
|
|
6
|
+
const { parse } = await dynamicImport("@astrojs/compiler");
|
|
7
|
+
// console.time("parse")
|
|
8
|
+
const result = parse(source);
|
|
9
|
+
// console.timeEnd("parse")
|
|
10
|
+
return result;
|
|
11
|
+
});
|
|
@@ -31,7 +31,7 @@ const errors_1 = require("../../errors");
|
|
|
31
31
|
* Parse code by `@astrojs/compiler`
|
|
32
32
|
*/
|
|
33
33
|
function parse(code, ctx) {
|
|
34
|
-
const ast =
|
|
34
|
+
const ast = service.parse(code, { position: true }).ast;
|
|
35
35
|
if (!ast.children) {
|
|
36
36
|
// If the source code is empty, the children property may not be available.
|
|
37
37
|
ast.children = [];
|
|
@@ -44,45 +44,17 @@ function parse(code, ctx) {
|
|
|
44
44
|
return { ast };
|
|
45
45
|
}
|
|
46
46
|
exports.parse = parse;
|
|
47
|
-
/**
|
|
48
|
-
* Parse code by `@astrojs/compiler`
|
|
49
|
-
*/
|
|
50
|
-
function parseByService(code, ctx) {
|
|
51
|
-
const jsonAst = service.parse(code, { position: true }).ast;
|
|
52
|
-
ctx.originalAST = jsonAst;
|
|
53
|
-
try {
|
|
54
|
-
const ast = JSON.parse(jsonAst);
|
|
55
|
-
ctx.originalAST = ast;
|
|
56
|
-
return { ast };
|
|
57
|
-
}
|
|
58
|
-
catch (_a) {
|
|
59
|
-
// FIXME: Workaround for escape bugs
|
|
60
|
-
// Adjust because may get the wrong escape as JSON.
|
|
61
|
-
const ast = JSON.parse(jsonAst.replace(/\\./gu, (m) => {
|
|
62
|
-
try {
|
|
63
|
-
JSON.parse(`"${m}"`);
|
|
64
|
-
return m;
|
|
65
|
-
}
|
|
66
|
-
catch (_a) {
|
|
67
|
-
return `\\${m}`;
|
|
68
|
-
}
|
|
69
|
-
}));
|
|
70
|
-
ctx.originalAST = ast;
|
|
71
|
-
return { ast };
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
47
|
/**
|
|
75
48
|
* Adjust <html> element node
|
|
76
49
|
*/
|
|
77
50
|
function adjustHTML(ast, htmlElement, ctx) {
|
|
78
|
-
var _a;
|
|
79
51
|
const htmlEnd = ctx.code.indexOf("</html");
|
|
80
52
|
if (htmlEnd == null) {
|
|
81
53
|
return;
|
|
82
54
|
}
|
|
83
55
|
const children = [...htmlElement.children];
|
|
84
56
|
for (const child of children) {
|
|
85
|
-
const offset =
|
|
57
|
+
const offset = child.position?.start.offset;
|
|
86
58
|
if (offset != null) {
|
|
87
59
|
if (htmlEnd <= offset) {
|
|
88
60
|
htmlElement.children.splice(htmlElement.children.indexOf(child), 1);
|
|
@@ -98,14 +70,13 @@ function adjustHTML(ast, htmlElement, ctx) {
|
|
|
98
70
|
* Adjust <body> element node
|
|
99
71
|
*/
|
|
100
72
|
function adjustHTMLBody(ast, htmlElement, htmlEnd, bodyElement, ctx) {
|
|
101
|
-
var _a;
|
|
102
73
|
const bodyEnd = ctx.code.indexOf("</body");
|
|
103
74
|
if (bodyEnd == null) {
|
|
104
75
|
return;
|
|
105
76
|
}
|
|
106
77
|
const children = [...bodyElement.children];
|
|
107
78
|
for (const child of children) {
|
|
108
|
-
const offset =
|
|
79
|
+
const offset = child.position?.start.offset;
|
|
109
80
|
if (offset != null) {
|
|
110
81
|
if (bodyEnd <= offset) {
|
|
111
82
|
bodyElement.children.splice(bodyElement.children.indexOf(child), 1);
|
|
@@ -169,8 +140,6 @@ function fixLocations(node, ctx) {
|
|
|
169
140
|
if (start < 0) {
|
|
170
141
|
start = ctx.code.length;
|
|
171
142
|
}
|
|
172
|
-
// FIXME: Workaround for escape bugs
|
|
173
|
-
node.value = ctx.code.slice(node.position.start.offset, start);
|
|
174
143
|
}
|
|
175
144
|
else {
|
|
176
145
|
const index = tokenIndexSafe(ctx.code, node.value, start);
|
|
@@ -179,25 +148,12 @@ function fixLocations(node, ctx) {
|
|
|
179
148
|
start += node.value.length;
|
|
180
149
|
}
|
|
181
150
|
else {
|
|
182
|
-
// FIXME:
|
|
151
|
+
// FIXME: Some white space may be removed.
|
|
183
152
|
node.position.start.offset = start;
|
|
184
153
|
const value = node.value.replace(/\s+/gu, "");
|
|
185
|
-
for (
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
if (index != null) {
|
|
189
|
-
start = index + 1;
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
start = (0, astro_1.skipSpaces)(ctx.code, start);
|
|
193
|
-
if (ctx.code.startsWith("\\", start)) {
|
|
194
|
-
const codeChar = JSON.parse(`"\\${ctx.code[start + 1]}"`);
|
|
195
|
-
start += 2;
|
|
196
|
-
if (codeChar === char) {
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
start = tokenIndex(ctx, char, start) + 1;
|
|
154
|
+
for (const char of value) {
|
|
155
|
+
const index = tokenIndex(ctx, char, start);
|
|
156
|
+
start = index + 1;
|
|
201
157
|
}
|
|
202
158
|
start = (0, astro_1.skipSpaces)(ctx.code, start);
|
|
203
159
|
node.value = ctx.code.slice(node.position.start.offset, start);
|
package/lib/parser/index.d.ts
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
|
-
import { Context } from "../context";
|
|
2
1
|
import type { AstroProgram } from "../ast";
|
|
3
|
-
import type { TSESTree } from "@typescript-eslint/types";
|
|
4
2
|
import type { ScopeManager } from "eslint-scope";
|
|
5
3
|
import type { ParseResult } from "@astrojs/compiler";
|
|
6
|
-
/**
|
|
7
|
-
* The parsing result of ESLint custom parsers.
|
|
8
|
-
*/
|
|
9
|
-
export interface ESLintExtendedProgram {
|
|
10
|
-
ast: TSESTree.Program;
|
|
11
|
-
services?: Record<string, any>;
|
|
12
|
-
visitorKeys?: {
|
|
13
|
-
[type: string]: string[];
|
|
14
|
-
};
|
|
15
|
-
scopeManager?: ScopeManager;
|
|
16
|
-
}
|
|
17
4
|
/**
|
|
18
5
|
* Parse source code
|
|
19
6
|
*/
|
|
@@ -28,7 +15,3 @@ export declare function parseForESLint(code: string, options?: any): {
|
|
|
28
15
|
};
|
|
29
16
|
scopeManager: ScopeManager;
|
|
30
17
|
};
|
|
31
|
-
/**
|
|
32
|
-
* Parse for template
|
|
33
|
-
*/
|
|
34
|
-
export declare function parseTemplate(code: string, ctx: Context): ParseResult;
|
package/lib/parser/index.js
CHANGED
|
@@ -1,28 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.parseForESLint = void 0;
|
|
4
4
|
const visitor_keys_1 = require("../visitor-keys");
|
|
5
|
-
const context_1 = require("../context");
|
|
6
5
|
const types_1 = require("@typescript-eslint/types");
|
|
7
6
|
const script_1 = require("./script");
|
|
8
7
|
const sort_1 = require("./sort");
|
|
9
|
-
const errors_1 = require("../errors");
|
|
10
|
-
const parse_1 = require("./astro-parser/parse");
|
|
11
8
|
const process_template_1 = require("./process-template");
|
|
9
|
+
const template_1 = require("./template");
|
|
10
|
+
const parser_options_1 = require("../context/parser-options");
|
|
12
11
|
/**
|
|
13
12
|
* Parse source code
|
|
14
13
|
*/
|
|
15
14
|
function parseForESLint(code, options) {
|
|
16
|
-
const
|
|
17
|
-
parserOptions.ecmaFeatures = Object.assign(Object.assign({}, (parserOptions.ecmaFeatures || {})), { jsx: true });
|
|
18
|
-
parserOptions.sourceType = "module";
|
|
19
|
-
if (parserOptions.ecmaVersion <= 5 || parserOptions.ecmaVersion == null) {
|
|
20
|
-
parserOptions.ecmaVersion = 2015;
|
|
21
|
-
}
|
|
22
|
-
const ctx = new context_1.Context(code, parserOptions);
|
|
23
|
-
const resultTemplate = parseTemplate(ctx.code, ctx);
|
|
15
|
+
const { result: resultTemplate, context: ctx } = (0, template_1.parseTemplate)(code);
|
|
24
16
|
const scriptContext = (0, process_template_1.processTemplate)(ctx, resultTemplate);
|
|
25
|
-
const
|
|
17
|
+
const parserOptions = new parser_options_1.ParserOptionsContext(options);
|
|
18
|
+
const resultScript = (0, script_1.parseScript)(scriptContext.script, ctx, parserOptions);
|
|
26
19
|
scriptContext.restore(resultScript);
|
|
27
20
|
(0, sort_1.sort)(resultScript.ast.comments);
|
|
28
21
|
(0, sort_1.sort)(resultScript.ast.tokens);
|
|
@@ -34,7 +27,6 @@ function parseForESLint(code, options) {
|
|
|
34
27
|
},
|
|
35
28
|
});
|
|
36
29
|
resultScript.visitorKeys = Object.assign({}, visitor_keys_1.KEYS, resultScript.visitorKeys);
|
|
37
|
-
ctx.remapCR(resultScript);
|
|
38
30
|
return resultScript;
|
|
39
31
|
}
|
|
40
32
|
exports.parseForESLint = parseForESLint;
|
|
@@ -77,20 +69,3 @@ function extractTokens(ast, ctx) {
|
|
|
77
69
|
return /^[^\w$]$/iu.test(c);
|
|
78
70
|
}
|
|
79
71
|
}
|
|
80
|
-
/**
|
|
81
|
-
* Parse for template
|
|
82
|
-
*/
|
|
83
|
-
function parseTemplate(code, ctx) {
|
|
84
|
-
try {
|
|
85
|
-
return (0, parse_1.parse)(code, ctx);
|
|
86
|
-
}
|
|
87
|
-
catch (e) {
|
|
88
|
-
if (typeof e.pos === "number") {
|
|
89
|
-
const err = new errors_1.ParseError(e.message, e.pos, ctx);
|
|
90
|
-
err.astroCompilerError = e;
|
|
91
|
-
throw err;
|
|
92
|
-
}
|
|
93
|
-
throw e;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
exports.parseTemplate = parseTemplate;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LruCache = void 0;
|
|
4
|
+
class LruCache extends Map {
|
|
5
|
+
constructor(capacity) {
|
|
6
|
+
super();
|
|
7
|
+
this.capacity = capacity;
|
|
8
|
+
}
|
|
9
|
+
get(key) {
|
|
10
|
+
if (!this.has(key)) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
const value = super.get(key);
|
|
14
|
+
this.set(key, value);
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
set(key, value) {
|
|
18
|
+
this.delete(key);
|
|
19
|
+
super.set(key, value);
|
|
20
|
+
if (this.size > this.capacity) {
|
|
21
|
+
this.deleteOldestEntry();
|
|
22
|
+
}
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
deleteOldestEntry() {
|
|
26
|
+
for (const entry of this) {
|
|
27
|
+
this.delete(entry[0]);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.LruCache = LruCache;
|
|
@@ -134,10 +134,23 @@ function processTemplate(ctx, resultTemplate) {
|
|
|
134
134
|
types_1.AST_NODE_TYPES.JSXAttribute &&
|
|
135
135
|
scriptNode.range[0] === start) {
|
|
136
136
|
const baseNameNode = scriptNode.name;
|
|
137
|
-
const nsn =
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
const nsn = {
|
|
138
|
+
...baseNameNode,
|
|
139
|
+
type: types_1.AST_NODE_TYPES.JSXNamespacedName,
|
|
140
|
+
namespace: {
|
|
141
|
+
type: types_1.AST_NODE_TYPES.JSXIdentifier,
|
|
142
|
+
name: attr.name.slice(0, colonIndex),
|
|
143
|
+
...ctx.getLocations(baseNameNode.range[0], baseNameNode.range[0] +
|
|
144
|
+
colonIndex),
|
|
145
|
+
},
|
|
146
|
+
name: {
|
|
147
|
+
type: types_1.AST_NODE_TYPES.JSXIdentifier,
|
|
148
|
+
name: attr.name.slice(colonIndex + 1),
|
|
149
|
+
...ctx.getLocations(baseNameNode.range[0] +
|
|
150
|
+
colonIndex +
|
|
151
|
+
1, baseNameNode.range[1]),
|
|
152
|
+
},
|
|
153
|
+
};
|
|
141
154
|
scriptNode.name = nsn;
|
|
142
155
|
nsn.namespace.parent = nsn;
|
|
143
156
|
nsn.name.parent = nsn;
|
|
@@ -212,7 +225,13 @@ function processTemplate(ctx, resultTemplate) {
|
|
|
212
225
|
script.addRestoreNodeProcess((scriptNode) => {
|
|
213
226
|
if (scriptNode.type === types_1.AST_NODE_TYPES.JSXElement &&
|
|
214
227
|
scriptNode.range[0] === styleNodeStart) {
|
|
215
|
-
const textNode =
|
|
228
|
+
const textNode = {
|
|
229
|
+
type: "AstroRawText",
|
|
230
|
+
value: text.value,
|
|
231
|
+
raw: text.value,
|
|
232
|
+
parent: scriptNode,
|
|
233
|
+
...ctx.getLocations(start, start + text.value.length),
|
|
234
|
+
};
|
|
216
235
|
scriptNode.children = [
|
|
217
236
|
textNode,
|
|
218
237
|
];
|
package/lib/parser/script.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { ESLintExtendedProgram } from ".";
|
|
2
1
|
import type { Context } from "../context";
|
|
2
|
+
import type { ParserOptionsContext } from "../context/parser-options";
|
|
3
|
+
import type { ESLintExtendedProgram } from "../types";
|
|
3
4
|
/**
|
|
4
5
|
* Parse for script
|
|
5
6
|
*/
|
|
6
|
-
export declare function parseScript(code: string,
|
|
7
|
+
export declare function parseScript(code: string, _ctx: Context, parserOptions: ParserOptionsContext): ESLintExtendedProgram;
|
package/lib/parser/script.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.parseScript = void 0;
|
|
7
|
-
const resolve_parser_1 = require("./resolve-parser");
|
|
8
|
-
const fs_1 = __importDefault(require("fs"));
|
|
9
4
|
const debug_1 = require("../debug");
|
|
5
|
+
const ts_patch_1 = require("./ts-patch");
|
|
10
6
|
/**
|
|
11
7
|
* Parse for script
|
|
12
8
|
*/
|
|
13
|
-
function parseScript(code,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let removeFile = null;
|
|
9
|
+
function parseScript(code, _ctx, parserOptions) {
|
|
10
|
+
const parser = parserOptions.getParser();
|
|
11
|
+
let patchResult;
|
|
17
12
|
try {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
const scriptParserOptions = {
|
|
14
|
+
...parserOptions.parserOptions,
|
|
15
|
+
};
|
|
16
|
+
scriptParserOptions.ecmaFeatures = {
|
|
17
|
+
...(scriptParserOptions.ecmaFeatures || {}),
|
|
18
|
+
jsx: true,
|
|
19
|
+
};
|
|
20
|
+
if (parserOptions.isTypeScript() &&
|
|
21
|
+
scriptParserOptions.filePath &&
|
|
22
|
+
scriptParserOptions.project) {
|
|
23
|
+
patchResult = (0, ts_patch_1.tsPatch)(scriptParserOptions);
|
|
25
24
|
}
|
|
26
|
-
const result =
|
|
25
|
+
const result = parser.parseForESLint?.(code, scriptParserOptions) ??
|
|
26
|
+
parser.parse?.(code, scriptParserOptions);
|
|
27
27
|
if ("ast" in result && result.ast != null) {
|
|
28
28
|
return result;
|
|
29
29
|
}
|
|
@@ -36,8 +36,7 @@ ${code}`);
|
|
|
36
36
|
throw e;
|
|
37
37
|
}
|
|
38
38
|
finally {
|
|
39
|
-
|
|
40
|
-
fs_1.default.unlinkSync(removeFile);
|
|
39
|
+
patchResult?.terminate();
|
|
41
40
|
}
|
|
42
41
|
}
|
|
43
42
|
exports.parseScript = parseScript;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ParseResult } from "@astrojs/compiler";
|
|
2
|
+
import { Context } from "../context";
|
|
3
|
+
export declare type TemplateResult = {
|
|
4
|
+
result: ParseResult;
|
|
5
|
+
context: Context;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Parse the astro component template.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseTemplate(code: string): TemplateResult;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseTemplate = void 0;
|
|
4
|
+
const astro_1 = require("../astro");
|
|
5
|
+
const context_1 = require("../context");
|
|
6
|
+
const errors_1 = require("../errors");
|
|
7
|
+
const parse_1 = require("./astro-parser/parse");
|
|
8
|
+
const lru_cache_1 = require("./lru-cache");
|
|
9
|
+
const lruCache = new lru_cache_1.LruCache(5);
|
|
10
|
+
/**
|
|
11
|
+
* Parse the astro component template.
|
|
12
|
+
*/
|
|
13
|
+
function parseTemplate(code) {
|
|
14
|
+
const cache = lruCache.get(code);
|
|
15
|
+
if (cache) {
|
|
16
|
+
return cache;
|
|
17
|
+
}
|
|
18
|
+
const ctx = new context_1.Context(code);
|
|
19
|
+
const normalized = ctx.locs.getNormalizedLineFeed();
|
|
20
|
+
const ctxForAstro = normalized.needRemap
|
|
21
|
+
? new context_1.Context(normalized.code)
|
|
22
|
+
: ctx;
|
|
23
|
+
try {
|
|
24
|
+
const result = (0, parse_1.parse)(normalized?.code ?? code, ctxForAstro);
|
|
25
|
+
if (normalized.needRemap) {
|
|
26
|
+
remap(result, normalized, code, ctxForAstro);
|
|
27
|
+
ctx.originalAST = ctxForAstro.originalAST;
|
|
28
|
+
}
|
|
29
|
+
const templateResult = {
|
|
30
|
+
result,
|
|
31
|
+
context: ctx,
|
|
32
|
+
};
|
|
33
|
+
lruCache.set(code, templateResult);
|
|
34
|
+
return templateResult;
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
if (typeof e.pos === "number") {
|
|
38
|
+
const err = new errors_1.ParseError(e.message, normalized?.remapIndex(e.pos), ctx);
|
|
39
|
+
err.astroCompilerError = e;
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
throw e;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.parseTemplate = parseTemplate;
|
|
46
|
+
/** Remap */
|
|
47
|
+
function remap(result, normalized, originalCode, ctxForAstro) {
|
|
48
|
+
const remapDataMap = new Map();
|
|
49
|
+
(0, astro_1.walk)(result.ast, normalized.code, (node) => {
|
|
50
|
+
const start = normalized.remapIndex(node.position.start.offset);
|
|
51
|
+
let end, value;
|
|
52
|
+
if (node.position.end) {
|
|
53
|
+
end = normalized.remapIndex(node.position.end.offset);
|
|
54
|
+
if (node.position.start.offset === start &&
|
|
55
|
+
node.position.end.offset === end) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (node.type === "text") {
|
|
60
|
+
value = originalCode.slice(start, normalized.remapIndex((0, astro_1.getEndOffset)(node, ctxForAstro)));
|
|
61
|
+
}
|
|
62
|
+
else if (node.type === "comment") {
|
|
63
|
+
value = originalCode.slice(start + 4, normalized.remapIndex((0, astro_1.getEndOffset)(node, ctxForAstro)) - 3);
|
|
64
|
+
}
|
|
65
|
+
else if (node.type === "attribute") {
|
|
66
|
+
if (node.kind !== "empty" &&
|
|
67
|
+
node.kind !== "shorthand" &&
|
|
68
|
+
node.kind !== "spread") {
|
|
69
|
+
let valueStart = normalized.remapIndex((0, astro_1.calcAttributeValueStartOffset)(node, ctxForAstro));
|
|
70
|
+
let valueEnd = normalized.remapIndex((0, astro_1.calcAttributeEndOffset)(node, ctxForAstro));
|
|
71
|
+
if (node.kind !== "quoted" ||
|
|
72
|
+
originalCode[valueStart] === '"' ||
|
|
73
|
+
originalCode[valueStart] === "'") {
|
|
74
|
+
valueStart++;
|
|
75
|
+
valueEnd--;
|
|
76
|
+
}
|
|
77
|
+
value = originalCode.slice(valueStart, valueEnd);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
remapDataMap.set(node, {
|
|
81
|
+
start,
|
|
82
|
+
end,
|
|
83
|
+
value,
|
|
84
|
+
});
|
|
85
|
+
}, (_node) => {
|
|
86
|
+
/* noop */
|
|
87
|
+
});
|
|
88
|
+
for (const [node, remapData] of remapDataMap) {
|
|
89
|
+
node.position.start.offset = remapData.start;
|
|
90
|
+
if (node.position.end) {
|
|
91
|
+
node.position.end.offset = remapData.end;
|
|
92
|
+
}
|
|
93
|
+
if (node.type === "text" ||
|
|
94
|
+
node.type === "comment" ||
|
|
95
|
+
(node.type === "attribute" &&
|
|
96
|
+
node.kind !== "empty" &&
|
|
97
|
+
node.kind !== "shorthand" &&
|
|
98
|
+
node.kind !== "spread")) {
|
|
99
|
+
node.value = remapData.value;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ParserOptions } from "@typescript-eslint/types";
|
|
2
|
+
export declare type PatchTerminate = {
|
|
3
|
+
terminate: () => void;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Apply a patch to parse .astro files as TSX.
|
|
7
|
+
*/
|
|
8
|
+
export declare function tsPatch(scriptParserOptions: ParserOptions): PatchTerminate | null;
|
|
@@ -0,0 +1,58 @@
|
|
|
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.tsPatch = void 0;
|
|
7
|
+
const module_1 = require("module");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
/**
|
|
11
|
+
* Apply a patch to parse .astro files as TSX.
|
|
12
|
+
*/
|
|
13
|
+
function tsPatch(scriptParserOptions) {
|
|
14
|
+
try {
|
|
15
|
+
// Apply a patch to parse .astro files as TSX.
|
|
16
|
+
const cwd = process.cwd();
|
|
17
|
+
const relativeTo = path_1.default.join(cwd, "__placeholder__.js");
|
|
18
|
+
const ts = (0, module_1.createRequire)(relativeTo)("typescript");
|
|
19
|
+
const { ensureScriptKind, getScriptKindFromFileName } = ts;
|
|
20
|
+
if (typeof ensureScriptKind === "function" &&
|
|
21
|
+
typeof getScriptKindFromFileName === "function") {
|
|
22
|
+
ts.ensureScriptKind = function (fileName, ...args) {
|
|
23
|
+
if (fileName.endsWith(".astro")) {
|
|
24
|
+
return ts.ScriptKind.TSX;
|
|
25
|
+
}
|
|
26
|
+
return ensureScriptKind.call(this, fileName, ...args);
|
|
27
|
+
};
|
|
28
|
+
ts.getScriptKindFromFileName = function (fileName, ...args) {
|
|
29
|
+
if (fileName.endsWith(".astro")) {
|
|
30
|
+
return ts.ScriptKind.TSX;
|
|
31
|
+
}
|
|
32
|
+
return getScriptKindFromFileName.call(this, fileName, ...args);
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
terminate() {
|
|
36
|
+
ts.ensureScriptKind = ensureScriptKind;
|
|
37
|
+
ts.getScriptKindFromFileName = getScriptKindFromFileName;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// ignore
|
|
44
|
+
}
|
|
45
|
+
// If the patch cannot be applied, create a tsx file and parse it.
|
|
46
|
+
const tsxFilePath = `${scriptParserOptions.filePath}.tsx`;
|
|
47
|
+
scriptParserOptions.filePath = tsxFilePath;
|
|
48
|
+
if (!fs_1.default.existsSync(tsxFilePath)) {
|
|
49
|
+
fs_1.default.writeFileSync(tsxFilePath, "/* temp for astro-eslint-parser */");
|
|
50
|
+
return {
|
|
51
|
+
terminate() {
|
|
52
|
+
fs_1.default.unlinkSync(tsxFilePath);
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
exports.tsPatch = tsPatch;
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { TSESTree } from "@typescript-eslint/types";
|
|
2
|
+
import type { ScopeManager } from "eslint-scope";
|
|
3
|
+
/**
|
|
4
|
+
* The parsing result of ESLint custom parsers.
|
|
5
|
+
*/
|
|
6
|
+
export interface ESLintExtendedProgram {
|
|
7
|
+
ast: TSESTree.Program;
|
|
8
|
+
services?: Record<string, any>;
|
|
9
|
+
visitorKeys?: {
|
|
10
|
+
[type: string]: string[];
|
|
11
|
+
};
|
|
12
|
+
scopeManager?: ScopeManager;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The interface of a result of ESLint custom parser.
|
|
16
|
+
*/
|
|
17
|
+
export declare type ESLintCustomParserResult = ESLintExtendedProgram["ast"] | ESLintExtendedProgram;
|
|
18
|
+
export interface ESLintCustomParser {
|
|
19
|
+
parse(code: string, options: any): ESLintCustomParserResult;
|
|
20
|
+
parseForESLint?(code: string, options: any): ESLintCustomParserResult;
|
|
21
|
+
}
|
package/lib/types.js
ADDED