From 6d50e003d01096ca2bde6abf70c66d82b6c7b8d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Sun, 23 Mar 2025 18:29:34 +0100 Subject: [PATCH 1/4] chore(prefer-svelte-reactivity): added tests --- .../invalid/_requirements.json | 3 +++ .../invalid/date01-errors.yaml | 4 ++++ .../invalid/date01-input.svelte | 5 +++++ .../invalid/map01-errors.yaml | 4 ++++ .../invalid/map01-input.svelte | 5 +++++ .../invalid/set01-errors.yaml | 4 ++++ .../invalid/set01-input.svelte | 5 +++++ .../invalid/url-search-params01-errors.yaml | 5 +++++ .../invalid/url-search-params01-input.svelte | 5 +++++ .../invalid/url01-errors.yaml | 4 ++++ .../invalid/url01-input.svelte | 5 +++++ .../valid/_requirements.json | 3 +++ .../valid/aliased-date01-input.svelte | 7 +++++++ .../valid/aliased-map01-input.svelte | 7 +++++++ .../valid/aliased-set01-input.svelte | 7 +++++++ .../valid/aliased-url-search-params01-input.svelte | 7 +++++++ .../valid/aliased-url01-input.svelte | 7 +++++++ .../valid/svelte-date01-input.svelte | 7 +++++++ .../valid/svelte-map01-input.svelte | 7 +++++++ .../valid/svelte-set01-input.svelte | 7 +++++++ .../valid/svelte-url-search-params01-input.svelte | 7 +++++++ .../valid/svelte-url01-input.svelte | 7 +++++++ .../valid/unrelated-date01-input.svelte | 7 +++++++ .../valid/unrelated-map01-input.svelte | 7 +++++++ .../valid/unrelated-set01-input.svelte | 7 +++++++ .../valid/unrelated-url-search-params01-input.svelte | 7 +++++++ .../valid/unrelated-url01-input.svelte | 7 +++++++ .../tests/src/rules/prefer-svelte-reactivity.ts | 12 ++++++++++++ 28 files changed, 169 insertions(+) create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/_requirements.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/date01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/date01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/map01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/map01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/set01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/set01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url-search-params01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url-search-params01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/_requirements.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-date01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-map01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-set01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-url-search-params01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-url01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-date01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-map01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-set01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-url-search-params01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-url01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-date01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-map01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-set01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-url-search-params01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-url01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/src/rules/prefer-svelte-reactivity.ts diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/_requirements.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/_requirements.json new file mode 100644 index 000000000..498661308 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/_requirements.json @@ -0,0 +1,3 @@ +{ + "svelte": ">=5.0.0" +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/date01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/date01-errors.yaml new file mode 100644 index 000000000..19a7e23f8 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/date01-errors.yaml @@ -0,0 +1,4 @@ +- message: Found a usage of the built-in Date class. Use a SvelteDate instead. + line: 2 + column: 20 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/date01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/date01-input.svelte new file mode 100644 index 000000000..3d0b6ce89 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/date01-input.svelte @@ -0,0 +1,5 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/map01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/map01-errors.yaml new file mode 100644 index 000000000..ba38fb4da --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/map01-errors.yaml @@ -0,0 +1,4 @@ +- message: Found a usage of the built-in Map class. Use a SvelteMap instead. + line: 2 + column: 20 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/map01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/map01-input.svelte new file mode 100644 index 000000000..5403fc3ea --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/map01-input.svelte @@ -0,0 +1,5 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/set01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/set01-errors.yaml new file mode 100644 index 000000000..5feb53d9d --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/set01-errors.yaml @@ -0,0 +1,4 @@ +- message: Found a usage of the built-in Set class. Use a SvelteSet instead. + line: 2 + column: 20 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/set01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/set01-input.svelte new file mode 100644 index 000000000..7a1ad366b --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/set01-input.svelte @@ -0,0 +1,5 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url-search-params01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url-search-params01-errors.yaml new file mode 100644 index 000000000..d95a70e76 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url-search-params01-errors.yaml @@ -0,0 +1,5 @@ +- message: Found a usage of the built-in URLSearchParams class. Use a + SvelteURLSearchParams instead. + line: 2 + column: 20 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url-search-params01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url-search-params01-input.svelte new file mode 100644 index 000000000..2423d7960 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url-search-params01-input.svelte @@ -0,0 +1,5 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url01-errors.yaml new file mode 100644 index 000000000..5df8eb34f --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url01-errors.yaml @@ -0,0 +1,4 @@ +- message: Found a usage of the built-in URL class. Use a SvelteURL instead. + line: 2 + column: 20 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url01-input.svelte new file mode 100644 index 000000000..9851e3103 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/invalid/url01-input.svelte @@ -0,0 +1,5 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/_requirements.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/_requirements.json new file mode 100644 index 000000000..498661308 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/_requirements.json @@ -0,0 +1,3 @@ +{ + "svelte": ">=5.0.0" +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-date01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-date01-input.svelte new file mode 100644 index 000000000..0ab09e823 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-date01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-map01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-map01-input.svelte new file mode 100644 index 000000000..5f431b8b1 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-map01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-set01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-set01-input.svelte new file mode 100644 index 000000000..bf3379c3c --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-set01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-url-search-params01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-url-search-params01-input.svelte new file mode 100644 index 000000000..8d3d4d2d2 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-url-search-params01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-url01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-url01-input.svelte new file mode 100644 index 000000000..ea960e9fd --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/aliased-url01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-date01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-date01-input.svelte new file mode 100644 index 000000000..911cb5461 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-date01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-map01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-map01-input.svelte new file mode 100644 index 000000000..43ff00a06 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-map01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-set01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-set01-input.svelte new file mode 100644 index 000000000..6c6728c53 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-set01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-url-search-params01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-url-search-params01-input.svelte new file mode 100644 index 000000000..0f66db767 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-url-search-params01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-url01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-url01-input.svelte new file mode 100644 index 000000000..014046937 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/svelte-url01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-date01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-date01-input.svelte new file mode 100644 index 000000000..851db5e63 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-date01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-map01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-map01-input.svelte new file mode 100644 index 000000000..32eab3dc7 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-map01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-set01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-set01-input.svelte new file mode 100644 index 000000000..fc378f046 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-set01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-url-search-params01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-url-search-params01-input.svelte new file mode 100644 index 000000000..de69ce09e --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-url-search-params01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-url01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-url01-input.svelte new file mode 100644 index 000000000..eab451693 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-svelte-reactivity/valid/unrelated-url01-input.svelte @@ -0,0 +1,7 @@ + + +{variable} diff --git a/packages/eslint-plugin-svelte/tests/src/rules/prefer-svelte-reactivity.ts b/packages/eslint-plugin-svelte/tests/src/rules/prefer-svelte-reactivity.ts new file mode 100644 index 000000000..da146b317 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/src/rules/prefer-svelte-reactivity.ts @@ -0,0 +1,12 @@ +import { RuleTester } from '../../utils/eslint-compat.js'; +import rule from '../../../src/rules/prefer-svelte-reactivity.js'; +import { loadTestCases } from '../../utils/utils.js'; + +const tester = new RuleTester({ + languageOptions: { + ecmaVersion: 2020, + sourceType: 'module' + } +}); + +tester.run('prefer-svelte-reactivity', rule as any, loadTestCases('prefer-svelte-reactivity')); From ebd62bdc5dab6e36eeb673abaf7d980c278697eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Mon, 24 Mar 2025 10:01:51 +0100 Subject: [PATCH 2/4] feat(prefer-svelte-reactivity): added rule implementation --- .changeset/rich-colts-nail.md | 5 ++ README.md | 15 +++-- docs/README.md | 4 +- docs/rules.md | 1 + docs/user-guide.md | 4 +- .../src/configs/flat/recommended.ts | 1 + .../eslint-plugin-svelte/src/rule-types.ts | 5 ++ .../src/rules/prefer-svelte-reactivity.ts | 65 +++++++++++++++++++ .../eslint-plugin-svelte/src/utils/rules.ts | 2 + 9 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 .changeset/rich-colts-nail.md create mode 100644 packages/eslint-plugin-svelte/src/rules/prefer-svelte-reactivity.ts diff --git a/.changeset/rich-colts-nail.md b/.changeset/rich-colts-nail.md new file mode 100644 index 000000000..51c8eea60 --- /dev/null +++ b/.changeset/rich-colts-nail.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-svelte': minor +--- + +feat: added the `prefer-svelte-reactivity` rule diff --git a/README.md b/README.md index edc472b33..dc5f50167 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,8 @@ ## Introduction -`eslint-plugin-svelte` is the official [ESLint](https://eslint.org/) plugin for [Svelte](https://svelte.dev/). -It leverages the AST generated by [svelte-eslint-parser](https://github.com/sveltejs/svelte-eslint-parser) to provide custom linting for Svelte. +`eslint-plugin-svelte` is the official [ESLint](https://eslint.org/) plugin for [Svelte](https://svelte.dev/). +It leverages the AST generated by [svelte-eslint-parser](https://github.com/sveltejs/svelte-eslint-parser) to provide custom linting for Svelte. Note that `eslint-plugin-svelte` and `svelte-eslint-parser` cannot be used alongside [eslint-plugin-svelte3](https://github.com/sveltejs/eslint-plugin-svelte3). @@ -219,8 +219,8 @@ export default [ ## Editor Integrations -**Visual Studio Code** -Install [dbaeumer.vscode-eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint). +**Visual Studio Code** +Install [dbaeumer.vscode-eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint). Configure `.svelte` files in `.vscode/settings.json`: ```json @@ -247,8 +247,8 @@ This project follows [Semantic Versioning](https://semver.org/). Unlike [ESLint -:wrench: Indicates that the rule is fixable, and using `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the reported problems. -:bulb: Indicates that some problems reported by the rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions). +:wrench: Indicates that the rule is fixable, and using `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the reported problems. +:bulb: Indicates that some problems reported by the rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions). :star: Indicates that the rule is included in the `plugin:svelte/recommended` config. @@ -272,6 +272,7 @@ These rules relate to possible syntax or logic errors in Svelte code: | [svelte/no-shorthand-style-property-overrides](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-shorthand-style-property-overrides/) | disallow shorthand style properties that override related longhand properties | :star: | | [svelte/no-store-async](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-store-async/) | disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features | :star: | | [svelte/no-unknown-style-directive-property](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unknown-style-directive-property/) | disallow unknown `style:property` | :star: | +| [svelte/prefer-svelte-reactivity](https://sveltejs.github.io/eslint-plugin-svelte/rules/prefer-svelte-reactivity/) | disallow using built-in classes where a reactive alternative is provided by svelte/reactivity | :star: | | [svelte/require-store-callbacks-use-set-param](https://sveltejs.github.io/eslint-plugin-svelte/rules/require-store-callbacks-use-set-param/) | store callbacks must use `set` param | :bulb: | | [svelte/require-store-reactive-access](https://sveltejs.github.io/eslint-plugin-svelte/rules/require-store-reactive-access/) | disallow to use of the store itself as an operand. Need to use $ prefix or get function. | :star::wrench: | | [svelte/valid-compile](https://sveltejs.github.io/eslint-plugin-svelte/rules/valid-compile/) | disallow warnings when compiling. | | @@ -400,7 +401,7 @@ These rules relate to this plugin works: ## Contributing -Contributions are welcome! Please open an issue or submit a PR. For more details, see [CONTRIBUTING.md](./CONTRIBUTING.md). +Contributions are welcome! Please open an issue or submit a PR. For more details, see [CONTRIBUTING.md](./CONTRIBUTING.md). Refer to [svelte-eslint-parser](https://github.com/sveltejs/svelte-eslint-parser) for AST details. diff --git a/docs/README.md b/docs/README.md index 9f765d50e..85b864f71 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,8 +4,8 @@ title: 'eslint-plugin-svelte' ## Introduction -`eslint-plugin-svelte` is the official [ESLint](https://eslint.org/) plugin for [Svelte](https://svelte.dev/). -It leverages the AST generated by [svelte-eslint-parser](https://github.com/sveltejs/svelte-eslint-parser) to provide custom linting for Svelte. +`eslint-plugin-svelte` is the official [ESLint](https://eslint.org/) plugin for [Svelte](https://svelte.dev/). +It leverages the AST generated by [svelte-eslint-parser](https://github.com/sveltejs/svelte-eslint-parser) to provide custom linting for Svelte. Note that `eslint-plugin-svelte` and `svelte-eslint-parser` cannot be used alongside [eslint-plugin-svelte3](https://github.com/sveltejs/eslint-plugin-svelte3). See [User Guide](./user-guide.md). diff --git a/docs/rules.md b/docs/rules.md index 75dd5ed5e..e0a5c7474 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -29,6 +29,7 @@ These rules relate to possible syntax or logic errors in Svelte code: | [svelte/no-shorthand-style-property-overrides](./rules/no-shorthand-style-property-overrides.md) | disallow shorthand style properties that override related longhand properties | :star: | | [svelte/no-store-async](./rules/no-store-async.md) | disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features | :star: | | [svelte/no-unknown-style-directive-property](./rules/no-unknown-style-directive-property.md) | disallow unknown `style:property` | :star: | +| [svelte/prefer-svelte-reactivity](./rules/prefer-svelte-reactivity.md) | disallow using built-in classes where a reactive alternative is provided by svelte/reactivity | :star: | | [svelte/require-store-callbacks-use-set-param](./rules/require-store-callbacks-use-set-param.md) | store callbacks must use `set` param | :bulb: | | [svelte/require-store-reactive-access](./rules/require-store-reactive-access.md) | disallow to use of the store itself as an operand. Need to use $ prefix or get function. | :star::wrench: | | [svelte/valid-compile](./rules/valid-compile.md) | disallow warnings when compiling. | | diff --git a/docs/user-guide.md b/docs/user-guide.md index babec87fa..379c16490 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -184,8 +184,8 @@ export default [ ## Editor Integrations -**Visual Studio Code** -Install [dbaeumer.vscode-eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint). +**Visual Studio Code** +Install [dbaeumer.vscode-eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint). Configure `.svelte` files in `.vscode/settings.json`: ```json diff --git a/packages/eslint-plugin-svelte/src/configs/flat/recommended.ts b/packages/eslint-plugin-svelte/src/configs/flat/recommended.ts index 7a08befc8..1f950a90f 100644 --- a/packages/eslint-plugin-svelte/src/configs/flat/recommended.ts +++ b/packages/eslint-plugin-svelte/src/configs/flat/recommended.ts @@ -37,6 +37,7 @@ const config: Linter.Config[] = [ 'svelte/no-unused-svelte-ignore': 'error', 'svelte/no-useless-children-snippet': 'error', 'svelte/no-useless-mustaches': 'error', + 'svelte/prefer-svelte-reactivity': 'error', 'svelte/prefer-writable-derived': 'error', 'svelte/require-each-key': 'error', 'svelte/require-event-dispatcher-types': 'error', diff --git a/packages/eslint-plugin-svelte/src/rule-types.ts b/packages/eslint-plugin-svelte/src/rule-types.ts index ac9f2a94f..3def13190 100644 --- a/packages/eslint-plugin-svelte/src/rule-types.ts +++ b/packages/eslint-plugin-svelte/src/rule-types.ts @@ -306,6 +306,11 @@ export interface RuleOptions { * @see https://sveltejs.github.io/eslint-plugin-svelte/rules/prefer-style-directive/ */ 'svelte/prefer-style-directive'?: Linter.RuleEntry<[]> + /** + * disallow using built-in classes where a reactive alternative is provided by svelte/reactivity + * @see https://sveltejs.github.io/eslint-plugin-svelte/rules/prefer-svelte-reactivity/ + */ + 'svelte/prefer-svelte-reactivity'?: Linter.RuleEntry<[]> /** * Prefer using writable $derived instead of $state and $effect * @see https://sveltejs.github.io/eslint-plugin-svelte/rules/prefer-writable-derived/ diff --git a/packages/eslint-plugin-svelte/src/rules/prefer-svelte-reactivity.ts b/packages/eslint-plugin-svelte/src/rules/prefer-svelte-reactivity.ts new file mode 100644 index 000000000..2fb532a3d --- /dev/null +++ b/packages/eslint-plugin-svelte/src/rules/prefer-svelte-reactivity.ts @@ -0,0 +1,65 @@ +import { ReferenceTracker } from '@eslint-community/eslint-utils'; +import { createRule } from '../utils/index.js'; + +export default createRule('prefer-svelte-reactivity', { + meta: { + docs: { + description: + 'disallow using built-in classes where a reactive alternative is provided by svelte/reactivity', + category: 'Possible Errors', + recommended: true + }, + schema: [], + messages: { + dateUsed: 'Found a usage of the built-in Date class. Use a SvelteDate instead.', + mapUsed: 'Found a usage of the built-in Map class. Use a SvelteMap instead.', + setUsed: 'Found a usage of the built-in Set class. Use a SvelteSet instead.', + urlUsed: 'Found a usage of the built-in URL class. Use a SvelteURL instead.', + urlSearchParamsUsed: + 'Found a usage of the built-in URLSearchParams class. Use a SvelteURLSearchParams instead.' + }, + type: 'problem', // 'problem', or 'layout', + conditions: [ + { + svelteVersions: ['5'], + svelteFileTypes: ['.svelte', '.svelte.[js|ts]'] + } + ] + }, + create(context) { + return { + Program() { + const referenceTracker = new ReferenceTracker(context.sourceCode.scopeManager.globalScope!); + for (const { node, path } of referenceTracker.iterateGlobalReferences({ + Date: { + [ReferenceTracker.CONSTRUCT]: true + }, + Map: { + [ReferenceTracker.CONSTRUCT]: true + }, + Set: { + [ReferenceTracker.CONSTRUCT]: true + }, + URL: { + [ReferenceTracker.CONSTRUCT]: true + }, + URLSearchParams: { + [ReferenceTracker.CONSTRUCT]: true + } + })) { + const typeToMessageId: Record = { + Date: 'dateUsed', + Map: 'mapUsed', + Set: 'setUsed', + URL: 'urlUsed', + URLSearchParams: 'urlSearchParamsUsed' + }; + context.report({ + messageId: typeToMessageId[path[0]], + node + }); + } + } + }; + } +}); diff --git a/packages/eslint-plugin-svelte/src/utils/rules.ts b/packages/eslint-plugin-svelte/src/utils/rules.ts index e79cd969a..d62e9bc26 100644 --- a/packages/eslint-plugin-svelte/src/utils/rules.ts +++ b/packages/eslint-plugin-svelte/src/utils/rules.ts @@ -60,6 +60,7 @@ import preferClassDirective from '../rules/prefer-class-directive.js'; import preferConst from '../rules/prefer-const.js'; import preferDestructuredStoreProps from '../rules/prefer-destructured-store-props.js'; import preferStyleDirective from '../rules/prefer-style-directive.js'; +import preferSvelteReactivity from '../rules/prefer-svelte-reactivity.js'; import preferWritableDerived from '../rules/prefer-writable-derived.js'; import requireEachKey from '../rules/require-each-key.js'; import requireEventDispatcherTypes from '../rules/require-event-dispatcher-types.js'; @@ -137,6 +138,7 @@ export const rules = [ preferConst, preferDestructuredStoreProps, preferStyleDirective, + preferSvelteReactivity, preferWritableDerived, requireEachKey, requireEventDispatcherTypes, From 3a67345e616c15cc4264e627478096931dfb1d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Mon, 24 Mar 2025 10:23:19 +0100 Subject: [PATCH 3/4] docs(prefer-svelte-reactivity): added rule docs --- docs/rules/prefer-svelte-reactivity.md | 68 ++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 docs/rules/prefer-svelte-reactivity.md diff --git a/docs/rules/prefer-svelte-reactivity.md b/docs/rules/prefer-svelte-reactivity.md new file mode 100644 index 000000000..9688d00e5 --- /dev/null +++ b/docs/rules/prefer-svelte-reactivity.md @@ -0,0 +1,68 @@ +--- +pageClass: 'rule-details' +sidebarDepth: 0 +title: 'svelte/prefer-svelte-reactivity' +description: 'disallow using built-in classes where a reactive alternative is provided by svelte/reactivity' +--- + +# svelte/prefer-svelte-reactivity + +> disallow using built-in classes where a reactive alternative is provided by svelte/reactivity + +- :exclamation: **_This rule has not been released yet._** +- :gear: This rule is included in `"plugin:svelte/recommended"`. + +## :book: Rule Details + +The built-in `Date`, `Map`, `Set`, `URL` and `URLSearchParams` classes are often used in frontend code, however, their properties and methods are not reactive. Because of that, Svelte provides reactive versions of these 5 builtins as part of the "svelte/reactivity" package. This rule reports usage of the built-in versions in Svelte code. + + + +```svelte + +``` + +## :wrench: Options + +Nothing. + +## :books: Further Reading + +- [svelte/reactivity documentation](https://svelte.dev/docs/svelte/svelte-reactivity) + +## :mag: Implementation + +- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/src/rules/prefer-svelte-reactivity.ts) +- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/tests/src/rules/prefer-svelte-reactivity.ts) From dcf3e34be062ab30458a0d02ed6eedc9ef0db481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Thu, 8 May 2025 15:49:07 +0200 Subject: [PATCH 4/4] Added URL and URLSearchParams to test globals --- packages/eslint-plugin-svelte/tests/utils/utils.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin-svelte/tests/utils/utils.ts b/packages/eslint-plugin-svelte/tests/utils/utils.ts index 845ea656f..dbf127ed0 100644 --- a/packages/eslint-plugin-svelte/tests/utils/utils.ts +++ b/packages/eslint-plugin-svelte/tests/utils/utils.ts @@ -21,7 +21,9 @@ const globals = { setInterval: 'readonly', queueMicrotask: 'readonly', window: 'readonly', - globalThis: 'readonly' + globalThis: 'readonly', + URL: 'readonly', + URLSearchParams: 'readonly' }; /** * Prevents leading spaces in a multiline template literal from appearing in the resulting string