sveltejs/eslint-plugin-svelte

Repository tracker

Pull requests

feat(no-unnecessary-state-wrap): support string array in allowReassign, default to true and improve messages

#1202
Apr 24, 2025
close: https://github.com/sveltejs/eslint-plugin-svelte/issues/1154 close: https://github.com/sveltejs/eslint-plugin-svelte/issues/1180

chore: add windows CI

#1122
Mar 10, 2025
No description provided

feat: Add svelte/valid-context-access rule

#480
Jun 8, 2024
close: https://github.com/sveltejs/eslint-plugin-svelte/issues/448

Issues

New rule: svelte/prefer-derived-over-derived-by

#1246
21 days ago • Jun 10, 2025
Motivation From a consistency perspective, this rule reports unnecessary usage of $derived.by. There is no performance difference. It purely enforces a consistent coding style. Even if included in recommended config, a warning level should be sufficient. Description This rule reports unnecessary usage of $derived.by. It also provides a fixer to automatically convert $derived.by to $derived. Examples <script> // ✓ GOOD const foo = $derived(a.b); // ✗ BAD const bar = $derived.by(() => a.b); </script> Additional comments No response

new rule: prefer-attachments

#1216
May 15, 2025
Svelte action will be replaced by attachments. https://github.com/sveltejs/svelte/pull/15000

prefer-sveltekit-response-helpers

#1217
May 14, 2025
Motivation See https://github.com/lucia-auth/example-sveltekit-google-oauth/pull/1 for an example Description Prefer using error and redirect over using Response. There might be some advanced cases where Response is required, but it shouldn't be for simple ones Examples <!-- ✓ GOOD --> redirect(307, "/"); <!-- ✗ BAD --> return new Response(null, { status: 307, headers: { Location: "/" } }); Additional comments No response

disallow-reactive-vars-on-mount

#1205
Apr 24, 2025
Motivation onMount runs in the component lifecycle, while reactive variables operate within the reactivity lifecycle. Referencing reactive variables inside the component lifecycle can easily lead to bugs. Description You cannot access reactive variables inside the onMount function. Examples <script> import { onMount } from 'svelte'; let count = $state(0); // ✗ BAD onMount(() => { console.log(count); }); </script> <!-- ✓ GOOD --> {#if count > 0} <p>Count is positive</p> {/if} Additional comments No response

no-unnecessary-state-wrap triggers too often

#1154
Apr 19, 2025
Before You File a Bug Report Please Confirm You Have Done The Following... I have tried restarting my IDE and the issue persists. I have updated to the latest version of the packages. What version of ESLint are you using? 9 What version of eslint-plugin-svelte are you using? 3.3.3 What did you do? Tried to upgrade https://github.com/immich-app/immich/tree/main/web to 3.3.3 It triggered no-unnecessary-state-wrap in two places. One was helpful, but the other I consider to be a false positive What did you expect to happen? This shouldn't be $state and should be a const: https://github.com/immich-app/immich/blob/392ce7deb2683d2c66a821c617329b3641491016/web/src/lib/components/forms/tag-asset-form.svelte#L21 However, this one is pretty reasonable because you're creating a new SvelteSet and it's a lot more cumbersome to clear the set and then add each item: https://github.com/immich-app/immich/blob/90f21d9047aa33dcb8231ab61269e60a32aedd9f/web/src/lib/components/utilities-page/duplicates/duplicates-compare-control.svelte#L86 I think we should trigger the rule only when the variable is not being reassigned What actually happened? It said that I should not use $state in either location. Link to GitHub Repo with Minimal Reproducible Example The full repo is here: https://github.com/immich-app/immich/tree/main/web I can create a smaller version if needed Additional comments No response

⚠️ Read this about TS parsing errors before submitting an issue ⚠️

#1111
Apr 10, 2025
There have been reports of the error "Parsing error: Unexpected token {", which occurs due to missing configurations in eslint.config.js. Please refer to the documentation and ensure your settings are correct. If the error persists despite correct configuration, feel free to open an issue. https://github.com/sveltejs/eslint-plugin-svelte?tab=readme-ov-file#typescript-project

new rule: no-nested-style-tag

#1186
Apr 3, 2025
Motivation This rule prohibits the use of nested <style> tags to prevent unintended style application. https://svelte.dev/docs/svelte/nested-style-elements Description Nested <style> tags are not scoped, which may lead to unintended styles being applied. Examples <script> </script> <!-- ✓ GOOD --> <style>...</style> <!-- ✗ BAD --> <div> <style>...</style> </div> {@snippet} <style>...</style> {/snippet} Additional comments No response

New Rule: svelte/kit-parent-function-at-bottom rule

#438
Jan 3, 2025
Motivation I would like to recognize performance overhead regarding parent. /** @type {import('./$types').PageLoad} */ export async function load({ params, parent }) { const parentData = await parent(); // ^ `parent` function can execute later to avoid a waterfall const data = await getData(params); return { ...data meta: { ...parentData.meta, ...data.meta } }; } Description SvelteKit has parent function. And according to the document, parent should use at the bottom of load function as much as possible in terms of performance. https://kit.svelte.dev/docs/load#using-parent-data But it's too difficult to recognize by human code review, so I would like to recognize this automatically. Examples /** @type {import('./$types').PageLoad} */ export async function load({ params, parent }) { // NG const parentData = await parent(); const data = await getData(params); // OK const parentData = await parent(); // OK (Because `doSomething` needs to use the return value of `parent`.) const foo = await doSomething(parentData); return { ...data meta: { ...parentData.meta, ...data.meta } }; } Additional comments I need to think about better rule name.😅

New Rule: svelte/valid-context-access

#448
Jan 3, 2025
Motivation This is came from https://github.com/sveltejs/svelte/pull/7864 Description According to the docs, getContext needs to call during component initialization. Svelte team tried to implement this in the compiler, but this is a bit difficult, so I thought that we will implement this as ESLint rule. https://svelte.dev/docs#run-time-svelte-getcontext Retrieves the context that belongs to the closest parent component with the specified key. Must be called during component initialisation. Examples <script> import { getContext } from 'svelte'; let test = getContext('test'); </script> <!-- ✓ GOOD --> <a href={test}>xxx</a> <!-- ✗ BAD --> <a href={getContext('test')}>xxx</a> Additional comments No response

Svelte5: Add svelte/no-getter-setter rule

#616
Jan 2, 2025
Description Refer: https://github.com/sveltejs/svelte/issues/9416

Svelte5: Add svelte/no-string-event-attribute

#617
Jan 2, 2025
Description Add the rule to ensure a smooth migration from Svelte 4 to Svelte 5. refer: https://github.com/sveltejs/svelte/pull/9444

Migrate the docs to Svelte 5

#754
Jan 2, 2025
And at this time, can we move the docs directory under monorepo? I'm not sure about best practice for this but personally, monorepo is used in many cases.

Svelte5: Add svelte/no-legacy-svelte-ignore rule

#773
Jan 2, 2025
Motivation Svelte v5 changed the format of error codes to snake_case, but svelte-ignore still works for the previous kebab-case error codes. However, I expect support for the old format will be removed eventually. The new rule help with this migration. Description The new rule disallow svelte-ignore using old-style error codes. Note, however, that they will only be reported if you are using Svelte v5 or later. Examples <!-- ✓ GOOD --> <!-- svelte-ignore a11y_no_noninteractive_tabindex --> <span tabindex="0"> <span class="element"></span> </span> <div> <!-- svelte-ignore block_empty --> {#await Promise.resolve(foo)} {/await} </div> <!-- ✗ BAD --> <!-- svelte-ignore a11y-no-noninteractive-tabindex --> <span tabindex="0"> <span class="element"></span> </span> <div> <!-- svelte-ignore empty-block --> {#await Promise.resolve(foo)} {/await} </div> Additional comments No response

New Rule: invalid-attribute

#821
Jan 2, 2025
Motivation In the past (and apparently i'm not alone ) i had the need to prevent certain types of attributes to be used. It could be the need to prevent an onclick attribute like i asked months ago (well now it would actually be the opposite ironically) or something more general for some specific reasons i think having a way to specify a list of invalid attributes could be a good rule to have. Description The user can provide through rule options a list of invalid attributes/regex. Every component using such attribute will be reported. Examples Given a configuration like this { "rules": { "svelte/invalid-attribute": ["error", ["title"]] } } <!-- ✗ BAD --> <Foo title=""/> <Foo {title}/> <Foo bind:title/> <Foo title={somevar}/> we probably can also error on props named that way for in-repo components. Additional comments I got a very barebone version of this already and if interested i can work on it and submit a PR.

Svelte5: Add svelte/no-store rule

#615
Jan 1, 2025
Description Refer: https://github.com/sveltejs/svelte/issues/9416

Optionally use alphabetic ordering if numeric ordering is not present

#825
Jul 13, 2024
Description I think it'd be nice to just display these pages alphabetically: https://github.com/sveltejs/eslint-plugin-svelte/tree/main/docs/rules Rather than making them preprend all those pages with numbers as we've done in https://github.com/sveltejs/svelte/tree/main/documentation/docs we should just use the alphabetic ordering We should probably see if they can adopt the numeric ordering for https://github.com/sveltejs/eslint-plugin-svelte/tree/main/docs though

Publishing docs on svelte.dev or highlighting them there

#824
Jul 12, 2024
Description We're starting to put together plans to publish docs for all the various plugins directly on svelte.dev (e.g. vite-plugin-svelte, rollup-plugin-svelte, svelte-loader, svelte-preprocess, the VS code plugin, prettier-plugin-svelte, eslint-plugin-svelte, etc.) eslint-plugin-svelte is much different than the others because it has many more pages as well as an existing site and a playground. This raises several questions: Should we try to incorporate the playground into the main site? It's setup looks a little complicated. I also don't know if that would make things harder for you? Should we just have a single page with setup instructions and then link to the existing site? Or should move all the content over except for the playground? I've asked these questions of the other maintainers working on the site, but thought it would be good to get your input as well. We'd like to try to have the markdown continue to live in each individual repository and then the site's build and deploy process will check out each of those repositories and use the docs from there. We're working on prototyping that right now. The main change needed here would probably be to publish a bit of config stating what order the pages should show up in the sidebar (e.g. https://github.com/sveltejs/svelte/pull/12410)

Apply @typescript-eslint/no-misused-promises to Svelte components

#691
Feb 29, 2024
Motivation If you pass a function returning a promise to a component property not expecting a promise, eslint should error. Description I can configure eslint to detect this as an error: const promiseFunc: () => Promise<void> = async () => {}; // pnpm lint will identify this as an issue as it should const func: () => void = promiseFunc; But if I do the same thing with a Svelte component property I can't get it to detect it. Examples <!-- file: Child.svelte --> <script lang="ts"> export let func: () => void; func(); </script> <!-- file: +page.svelte --> <script lang="ts"> import Child from './Child.svelte'; const promiseFunc: () => Promise<void> = async () => {}; </script> <!-- ✗ BAD --> <Child func={promiseFunc} /> Additional comments I don't know if this should be considered a new rule or just apply @typescript-eslint/no-misused-promises somehow. See here for an example of the existing eslint rule and what I'd like eslint-plugin-svelte to catch: https://github.com/benmccann/promise-linting/blob/master/src/routes/%2Bpage.svelte I hit this issue a lot while trying to migrate a large project to Svelte 5 where I was replacing components events with component callback props and it became very hard to keep track of what should be asynchronous vs synchronous: https://github.com/immich-app/immich/pull/7187#discussion_r1504663631