Skip to content

Commit 9793cb0

Browse files
authored
feat: apply runes to *.svelte.js and *.svelte.ts (#426)
1 parent 96d44b8 commit 9793cb0

32 files changed

+9092
-451
lines changed

.changeset/brown-cheetahs-greet.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte-eslint-parser": minor
3+
---
4+
5+
feat: apply runes to `*.svelte.js` and `*.svelte.ts`.

README.md

+38
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,44 @@ module.exports = {
169169
}
170170
```
171171

172+
### Runes support
173+
174+
***This is an experimental feature. It may be changed or removed in minor versions without notice.***
175+
176+
If you install Svelte v5 the parser will be able to parse runes, and will also be able to parse `*.js` and `*.ts` files.
177+
178+
When using this mode in an ESLint configuration, it is recommended to set it per file pattern as below.
179+
180+
```json
181+
{
182+
"overrides": [
183+
{
184+
"files": ["*.svelte"],
185+
"parser": "svelte-eslint-parser",
186+
"parserOptions": {
187+
"parser": "...",
188+
...
189+
}
190+
},
191+
{
192+
"files": ["*.svelte.js"],
193+
"parser": "svelte-eslint-parser",
194+
"parserOptions": {
195+
...
196+
}
197+
},
198+
{
199+
"files": ["*.svelte.ts"],
200+
"parser": "svelte-eslint-parser",
201+
"parserOptions": {
202+
"parser": "...(ts parser)...",
203+
...
204+
}
205+
}
206+
]
207+
}
208+
```
209+
172210
## :computer: Editor Integrations
173211

174212
### Visual Studio Code

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"release": "changeset publish",
4242
"test": "pnpm run mocha \"tests/src/**/*.ts\" --reporter dot --timeout 60000",
4343
"ts": "node -r esbuild-register",
44-
"update-fixtures": "pnpm i -D svelte@4 && pnpm run run-update-fixtures && git checkout package.json && pnpm i && pnpm run run-update-fixtures",
44+
"update-fixtures": "git add package.json && pnpm i -D svelte@4 && git checkout package.json && pnpm run run-update-fixtures && pnpm i && pnpm run run-update-fixtures",
4545
"run-update-fixtures": "pnpm run ts ./tools/update-fixtures.ts",
4646
"version:ci": "env-cmd -e version-ci pnpm run build:meta && changeset version"
4747
},

src/context/index.ts

+7-52
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import fs from "fs";
2-
import path from "path";
31
import type {
42
Comment,
53
Locations,
@@ -15,19 +13,13 @@ import type ESTree from "estree";
1513
import type * as SvAST from "../parser/svelte-ast-types";
1614
import { ScriptLetContext } from "./script-let";
1715
import { LetDirectiveCollections } from "./let-directive-collection";
18-
import { getParserForLang } from "../parser/resolve-parser";
1916
import type { AttributeToken } from "../parser/html";
2017
import { parseAttributes } from "../parser/html";
21-
import {
22-
isTSESLintParserObject,
23-
maybeTSESLintParserObject,
24-
} from "../parser/parser-object";
2518
import { sortedLastIndex } from "../utils";
26-
27-
const TS_PARSER_NAMES = [
28-
"@typescript-eslint/parser",
29-
"typescript-eslint-parser-for-extra-files",
30-
];
19+
import {
20+
isTypeScript,
21+
type NormalizedParserOptions,
22+
} from "../parser/parser-options";
3123

3224
export class ScriptsSourceCode {
3325
private raw: string;
@@ -116,7 +108,7 @@ export type ContextSourceCode = {
116108
export class Context {
117109
public readonly code: string;
118110

119-
public readonly parserOptions: any;
111+
public readonly parserOptions: NormalizedParserOptions;
120112

121113
// ----- Source Code ------
122114
public readonly sourceCode: ContextSourceCode;
@@ -155,7 +147,7 @@ export class Context {
155147

156148
private readonly blocks: Block[] = [];
157149

158-
public constructor(code: string, parserOptions: any) {
150+
public constructor(code: string, parserOptions: NormalizedParserOptions) {
159151
this.code = code;
160152
this.parserOptions = parserOptions;
161153
this.locs = new LinesAndColumns(code);
@@ -287,44 +279,7 @@ export class Context {
287279
return this.state.isTypeScript;
288280
}
289281
const lang = this.sourceCode.scripts.attrs.lang;
290-
if (!lang) {
291-
return (this.state.isTypeScript = false);
292-
}
293-
const parserValue = getParserForLang(
294-
this.sourceCode.scripts.attrs,
295-
this.parserOptions?.parser,
296-
);
297-
if (typeof parserValue !== "string") {
298-
return (this.state.isTypeScript =
299-
maybeTSESLintParserObject(parserValue) ||
300-
isTSESLintParserObject(parserValue));
301-
}
302-
const parserName = parserValue;
303-
if (TS_PARSER_NAMES.includes(parserName)) {
304-
return (this.state.isTypeScript = true);
305-
}
306-
if (TS_PARSER_NAMES.some((nm) => parserName.includes(nm))) {
307-
let targetPath = parserName;
308-
while (targetPath) {
309-
const pkgPath = path.join(targetPath, "package.json");
310-
if (fs.existsSync(pkgPath)) {
311-
try {
312-
return (this.state.isTypeScript = TS_PARSER_NAMES.includes(
313-
JSON.parse(fs.readFileSync(pkgPath, "utf-8"))?.name,
314-
));
315-
} catch {
316-
return (this.state.isTypeScript = false);
317-
}
318-
}
319-
const parent = path.dirname(targetPath);
320-
if (targetPath === parent) {
321-
break;
322-
}
323-
targetPath = parent;
324-
}
325-
}
326-
327-
return (this.state.isTypeScript = false);
282+
return (this.state.isTypeScript = isTypeScript(this.parserOptions, lang));
328283
}
329284

330285
public stripScriptCode(start: number, end: number): void {

src/parser/analyze-scope.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import { getFallbackKeys } from "../traverse";
55
import type { SvelteReactiveStatement, SvelteScriptElement } from "../ast";
66
import { addReference, addVariable } from "../scope";
77
import { addElementToSortedArray } from "../utils";
8+
import type { NormalizedParserOptions } from "./parser-options";
89
/**
910
* Analyze scope
1011
*/
1112
export function analyzeScope(
1213
node: ESTree.Node,
13-
parserOptions: any = {},
14+
parserOptions: NormalizedParserOptions,
1415
): ScopeManager {
1516
const ecmaVersion = parserOptions.ecmaVersion || 2020;
1617
const ecmaFeatures = parserOptions.ecmaFeatures || {};

src/parser/globals.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import { VERSION as SVELTE_VERSION } from "svelte/compiler";
1+
import { svelteVersion } from "./svelte-version";
22

3-
const globalsForSvelte4: Readonly<string[]> = [
4-
"$$slots",
5-
"$$props",
6-
"$$restProps",
7-
] as const;
8-
export const globalsForSvelte5 = [
3+
const globalsForSvelte4 = ["$$slots", "$$props", "$$restProps"] as const;
4+
export const globalsForRunes = [
95
"$state",
106
"$derived",
117
"$effect",
128
"$props",
139
] as const;
14-
export const globals = SVELTE_VERSION.startsWith("5")
15-
? [...globalsForSvelte4, ...globalsForSvelte5]
10+
const globalsForSvelte5 = [...globalsForSvelte4, ...globalsForRunes];
11+
export const globals = svelteVersion.gte(5)
12+
? globalsForSvelte5
1613
: globalsForSvelte4;
14+
export const globalsForSvelteScript = svelteVersion.gte(5)
15+
? globalsForRunes
16+
: [];

0 commit comments

Comments
 (0)