astro-eslint-parser 0.1.0 → 0.2.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/README.md +18 -5
- package/lib/context/resolve-parser/espree.js +2 -17
- package/lib/parser/script.js +11 -13
- package/lib/parser/ts-patch.d.ts +8 -0
- package/lib/parser/ts-patch.js +58 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -21,14 +21,19 @@ At least it works fine with a [fork of the `astro.build` repository](https://git
|
|
|
21
21
|
|
|
22
22
|
[@astrojs/compiler]: https://github.com/withastro/compiler
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
## :checkered_flag: Motivation
|
|
25
|
+
|
|
26
|
+
This parser allows us to lint the script of `.astro` files.
|
|
27
|
+
|
|
28
|
+
> Note that this parser alone will not lint the scripts inside the `<script>` tag. Use [eslint-plugin-astro] to lint the script inside the `<script>` tag as well.
|
|
29
|
+
|
|
25
30
|
### ESLint Plugins Using astro-eslint-parser
|
|
26
31
|
|
|
27
|
-
#### [
|
|
32
|
+
#### [eslint-plugin-astro]
|
|
28
33
|
|
|
29
34
|
ESLint plugin for Astro component.
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
|
|
36
|
+
[eslint-plugin-astro]: https://ota-meshi.github.io/eslint-plugin-astro/
|
|
32
37
|
|
|
33
38
|
## 💿 Installation
|
|
34
39
|
|
|
@@ -60,7 +65,7 @@ npm install --save-dev eslint astro-eslint-parser
|
|
|
60
65
|
$ eslint src --ext .js,.astro
|
|
61
66
|
```
|
|
62
67
|
|
|
63
|
-
The commit diff [here](https://github.com/
|
|
68
|
+
The commit diff [here](https://github.com/withastro/astro.build/compare/main...ota-meshi:eslint) is an example of introducing this parser to the `astro.build` repository.
|
|
64
69
|
|
|
65
70
|
## 🔧 Options
|
|
66
71
|
|
|
@@ -152,6 +157,14 @@ For example, the [react/jsx-no-target-blank] rule works fine.
|
|
|
152
157
|
[eslint-plugin-react]: https://github.com/jsx-eslint/eslint-plugin-react/
|
|
153
158
|
[react/jsx-no-target-blank]: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md
|
|
154
159
|
|
|
160
|
+
## :ghost: Limitations
|
|
161
|
+
|
|
162
|
+
If this parser is used with `@typescript-eslint/parser` and `parserOptions.project` is set, it will temporarily create a `.tsx` file to parse the `.astro` file.
|
|
163
|
+
This parser works by converting the `.astro` file to JSX and letting the JavaScript parser parse it.
|
|
164
|
+
Since `@typescript-eslint/parser` can only parse files with the extension `.tsx` as JSX, it is necessary to temporarily create a `.tsx` file. Temporarily created files will try to be deleted after parses, but if the parsing takes a long time, the files may be visible to you.
|
|
165
|
+
|
|
166
|
+
See also [`@typescript-eslint/parser` readme](https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/parser#parseroptionsecmafeaturesjsx).
|
|
167
|
+
|
|
155
168
|
## :hammer_and_wrench: Usage for Custom Rules / Plugins
|
|
156
169
|
|
|
157
170
|
- TBA
|
|
@@ -4,23 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getEspree = void 0;
|
|
7
|
-
const module_1 =
|
|
7
|
+
const module_1 = require("module");
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const createRequire =
|
|
10
|
-
// Added in v12.2.0
|
|
11
|
-
module_1.default.createRequire ||
|
|
12
|
-
// Added in v10.12.0, but deprecated in v12.2.0.
|
|
13
|
-
// @ts-expect-error -- old type
|
|
14
|
-
module_1.default.createRequireFromPath ||
|
|
15
|
-
// Polyfill - This is not executed on the tests on node@>=10.
|
|
16
|
-
/* istanbul ignore next */
|
|
17
|
-
((modName) => {
|
|
18
|
-
const mod = new module_1.default(modName);
|
|
19
|
-
mod.filename = modName;
|
|
20
|
-
mod.paths = module_1.default._nodeModulePaths(path_1.default.dirname(modName));
|
|
21
|
-
mod._compile("module.exports = require;", modName);
|
|
22
|
-
return mod.exports;
|
|
23
|
-
});
|
|
24
9
|
let espreeCache = null;
|
|
25
10
|
/** Checks if given path is linter path */
|
|
26
11
|
function isLinterPath(p) {
|
|
@@ -40,7 +25,7 @@ function getEspree() {
|
|
|
40
25
|
const linterPath = Object.keys(require.cache || {}).find(isLinterPath);
|
|
41
26
|
if (linterPath) {
|
|
42
27
|
try {
|
|
43
|
-
espreeCache = createRequire(linterPath)("espree");
|
|
28
|
+
espreeCache = (0, module_1.createRequire)(linterPath)("espree");
|
|
44
29
|
}
|
|
45
30
|
catch {
|
|
46
31
|
// ignore
|
package/lib/parser/script.js
CHANGED
|
@@ -1,27 +1,26 @@
|
|
|
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 fs_1 = __importDefault(require("fs"));
|
|
8
4
|
const debug_1 = require("../debug");
|
|
5
|
+
const ts_patch_1 = require("./ts-patch");
|
|
9
6
|
/**
|
|
10
7
|
* Parse for script
|
|
11
8
|
*/
|
|
12
9
|
function parseScript(code, _ctx, parserOptions) {
|
|
13
10
|
const parser = parserOptions.getParser();
|
|
14
|
-
let
|
|
11
|
+
let patchResult;
|
|
15
12
|
try {
|
|
16
|
-
const scriptParserOptions = {
|
|
13
|
+
const scriptParserOptions = {
|
|
14
|
+
...parserOptions.parserOptions,
|
|
15
|
+
};
|
|
16
|
+
scriptParserOptions.ecmaFeatures = {
|
|
17
|
+
...(scriptParserOptions.ecmaFeatures || {}),
|
|
18
|
+
jsx: true,
|
|
19
|
+
};
|
|
17
20
|
if (parserOptions.isTypeScript() &&
|
|
18
21
|
scriptParserOptions.filePath &&
|
|
19
22
|
scriptParserOptions.project) {
|
|
20
|
-
|
|
21
|
-
if (!fs_1.default.existsSync(scriptParserOptions.filePath)) {
|
|
22
|
-
fs_1.default.writeFileSync(scriptParserOptions.filePath, "/* temp for astro-eslint-parser */");
|
|
23
|
-
removeFile = scriptParserOptions.filePath;
|
|
24
|
-
}
|
|
23
|
+
patchResult = (0, ts_patch_1.tsPatch)(scriptParserOptions);
|
|
25
24
|
}
|
|
26
25
|
const result = parser.parseForESLint?.(code, scriptParserOptions) ??
|
|
27
26
|
parser.parse?.(code, scriptParserOptions);
|
|
@@ -37,8 +36,7 @@ ${code}`);
|
|
|
37
36
|
throw e;
|
|
38
37
|
}
|
|
39
38
|
finally {
|
|
40
|
-
|
|
41
|
-
fs_1.default.unlinkSync(removeFile);
|
|
39
|
+
patchResult?.terminate();
|
|
42
40
|
}
|
|
43
41
|
}
|
|
44
42
|
exports.parseScript = parseScript;
|
|
@@ -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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-eslint-parser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Astro component parser for ESLint",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"homepage": "https://github.com/ota-meshi/astro-eslint-parser#readme",
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@astrojs/compiler": "^0.
|
|
45
|
+
"@astrojs/compiler": "^0.15.0",
|
|
46
46
|
"@typescript-eslint/types": "^5.25.0",
|
|
47
47
|
"debug": "^4.3.4",
|
|
48
48
|
"eslint-visitor-keys": "^3.0.0",
|
|
@@ -63,13 +63,14 @@
|
|
|
63
63
|
"@types/semver": "^7.3.9",
|
|
64
64
|
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
|
65
65
|
"@typescript-eslint/parser": "^5.4.0",
|
|
66
|
-
"astro-eslint-parser": ">=0.0
|
|
66
|
+
"astro-eslint-parser": ">=0.1.0",
|
|
67
67
|
"benchmark": "^2.1.4",
|
|
68
68
|
"chai": "^4.3.4",
|
|
69
69
|
"code-red": "^0.2.3",
|
|
70
70
|
"eslint": "^8.15.0",
|
|
71
71
|
"eslint-config-prettier": "^8.3.0",
|
|
72
72
|
"eslint-formatter-codeframe": "^7.32.1",
|
|
73
|
+
"eslint-plugin-astro": "^0.2.0",
|
|
73
74
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
74
75
|
"eslint-plugin-json-schema-validator": "^3.0.0",
|
|
75
76
|
"eslint-plugin-jsonc": "^2.0.0",
|
|
@@ -91,6 +92,6 @@
|
|
|
91
92
|
"string-replace-loader": "^3.0.3",
|
|
92
93
|
"svelte": "^3.48.0",
|
|
93
94
|
"ts-node": "^10.4.0",
|
|
94
|
-
"typescript": "~4.
|
|
95
|
+
"typescript": "~4.7.0"
|
|
95
96
|
}
|
|
96
97
|
}
|