eslint-plugin-svelte

repository·main·Indexed 19 days ago

https://github.com/sveltejs/eslint-plugin-svelte

The official ESLint plugin for Svelte. It utilizes svelte-eslint-parser to analyze Svelte files via AST, providing custom linting rules for best practices, security vulnerabilities, and possible errors in Svelte components. It includes pre-defined configurations such as base, recommended, prettier, and all, and provides specific support for SvelteKit projects and TypeScript integration.

Tokens
54.4K
Snippets
144
Records
196
Agent score
62%

What's inside eslint-plugin-svelte

  1. Introduction to eslint-plugin-svelte

    main

    eslint-plugin-svelte is the official ESLint plugin for Svelte. It uses the AST generated by svelte-eslint-parser to provide custom linting rules specifically for Svelte files.

    Important Compatibility Note: eslint-plugin-svelte and svelte-eslint-parser are incompatible with eslint-plugin-svelte3. You cannot use them in the same project.

  2. Understand the svelte/require-optimized-style-attribute rule

    main

    The svelte/require-optimized-style-attribute rule ensures that style attributes are written in a format that allows Svelte to perform granular updates.

    When Svelte can parse and optimize a style attribute, it uses element.style.setProperty() to update only the specific properties that changed. This minimizes re-renders. If the attribute is written in a way that Svelte cannot parse (e.g., using a reactive string variable or including comments), Svelte falls back to element.setAttribute('style', ...) which forces the entire style string to be re-evaluated and re-applied whenever any variable within that string changes.

    To avoid performance issues, avoid using reactive variables that contain entire CSS strings or using complex logic inside the style attribute.

    <!-- ✓ GOOD: Granular updates via setProperty -->
    <div style="font-size: 12px; color: {color}; transform: translate({x}px, {y}px);" />
    <div style:pointer-events={pointerEvents ? null : 'none'} />
    
    <!-- ✗ BAD: Full attribute re-render via setAttribute -->
    <div style="font-size: 12px; color: {color}; {transformStyle}" />
    <div style={pointerEvents === false ? 'pointer-events:none;' : ''} />
  3. Use svelte/max-lines-per-block to limit block sizes

    main

    The svelte/max-lines-per-block rule enforces a maximum number of lines within specific Svelte component blocks (<script>, <style>, or the template markup).

    This rule is a more granular alternative to ESLint's core max-lines rule. While max-lines counts every line in a .svelte file (including CSS), svelte/max-lines-per-block allows you to set independent limits for logic, markup, and styles. This prevents large <style> blocks from triggering complexity errors intended for your script or template logic.

    {
      // Only checks script and template, ignores style
      "svelte/max-lines-per-block": [
        "error",
        {
          "script": 300,
          "template": 200,
          "skipBlankLines": true,
          "skipComments": true
        }
      ]
    }
  4. Understand the `svelte/no-dom-manipulating` rule

    main

    The svelte/no-dom-manipulating rule disallows direct DOM manipulation to prevent conflicts between the actual DOM and the Svelte runtime's internal state. Direct manipulation can cause the Svelte runtime to become confused about the state of the DOM.

    How it works

    The rule specifically tracks and checks variables that have been assigned to an element via the bind:this={} directive.

    What is NOT reported

    • Function arguments passed to directives like transition: are not tracked by this rule. These are considered safe as they are typically used for well-tested, controlled purposes (like custom transitions).

    How to handle reports

    If you are intentionally manipulating the DOM and understand the risks, you can ignore the ESLint report using an eslint-disable comment.

    <script>
      /* eslint svelte/no-dom-manipulating: "error" */
      let foo, bar, show;
    
      /* ✓ GOOD: Delegating to Svelte state */
      const toggle = () => (show = !show);
    
      /* ✗ BAD: Direct DOM manipulation on bound elements */
      const remove = () => foo.remove();
      const update = () => (bar.textContent = 'Update!');
    </script>
    
    {#if show}
      <div bind:this={foo}>Foo</div>
    {/if}
    <div bind:this={bar}>
      {#if show}
        Bar
      {/if}
    </div>
    
    <button on:click={() => toggle()}>Click Me (Good)</button>
    <button on:click={() => remove()}>Click Me (Bad)</button>
    <button on:click={() => update()}>Click Me (Bad)</button>
  5. Understand the svelte/no-target-blank rule

    main

    The svelte/no-target-blank rule disallows using the target="_blank" attribute on anchor tags without accompanying rel="noopener noreferrer" attributes. This prevents security vulnerabilities in legacy browsers where a newly opened page could potentially control the original page via the window.opener property.

    Examples

    Good:

    <a href="http://example.com" target="_blank" rel="noopener noreferrer">link</a>

    Bad:

    <a href="http://example.com" target="_blank">link</a>
  6. How svelte/consistent-selector-style works

    main

    This rule compares your current CSS selectors against a list of preferred styles. It reports situations where a selector can be rewritten using a more preferred style from your configuration.

    Note on selector capabilities:

    • Class selectors (.link) can be used in almost any situation.
    • ID selectors (#link) can only be used to select a single element.
    • Type selectors (a) are only applicable when selecting all elements of that specific type.

    Because of these constraints, the rule only suggests rewrites that are functionally equivalent.

    Usage Example

    Given the preference ["type", "id", "class"]:

    <a class="link" id="firstLink">Click me!</a>
    <b class="bold cross">Text one</b>
    <i id="italic">Text three</i>
    
    <style>
      /* ✓ GOOD: Matches preferred order */
      a { color: green; }
      #firstLink { color: green; }
      .cross { color: green; }
    
      /* ✗ BAD: Can be rewritten to a more preferred style */
      
      /* Can use a type selector instead of a class */
      .link { color: red; }
    
      /* Can use an ID selector instead of a class */
      .bold { color: red; }
    
      /* Can use a type selector instead of an ID */
      #italic { color: red; }
    </style>
    <style>
      /* ✓ GOOD */
      a { color: green; }
      #firstLink { color: green; }
      .cross { color: green; }
    
      /* ✗ BAD */
      .link { color: red; } /* Can use a type selector */
      .bold { color: red; } /* Can use an ID selector */
      #italic { color: red; } /* Can use a type selector */
    </style>
  7. Use the svelte/no-unused-props rule

    main

    The svelte/no-unused-props rule warns about properties defined in Svelte $props() that are never utilized within the component code. This helps detect dead code and improves component clarity.

    It detects usage through:

    • Direct property access
    • Destructuring assignment
    • Method calls
    • Computed property access
    • Object spread
    • Constructor calls (new expressions)
    • Assignment to other variables
    • Index signatures (e.g. [key: string]: unknown)

    Note: Properties of class types are not checked for usage, as they might be used in other parts of the application.

    <!-- ✗ Bad Example: Unused property 'b' -->
    <script lang="ts">
      /* eslint svelte/no-unused-props: "error" */
      const props: { a: string; b: number } = $props();
      console.log(props.a);
    </script>
  8. Ensure the svelte/system rule is enabled

    main

    The svelte/system rule is a mandatory system rule required for eslint-plugin-svelte to function correctly. While this rule does not report any linting errors or warnings to the user, it must be active for the plugin's internal logic to operate.

    This rule is automatically included when you use the following ESLint configurations:

    • plugin:svelte/base
    • plugin:svelte/recommended
  9. Understand the svelte/no-add-event-listener rule

    main

    The svelte/no-add-event-listener rule warns against using the native addEventListener method inside Svelte components.

    Svelte uses event delegation for better performance and to ensure predictable handler execution order. When you call addEventListener directly, you bypass Svelte's event delegation mechanism. To fix this, you should use the on() helper provided by svelte/events instead of the native browser API.

    <!-- ✓ GOOD -->
    <script>
      /* eslint svelte/no-add-event-listener: "error" */
      on(window, 'resize', handler);
    </script>
    
    <!-- ✗ BAD -->
    <script>
      /* eslint svelte/no-add-event-listener: "error" */
      window.addEventListener('resize', handler);
    </script>
  10. Understand ESLint rule indicators

    main

    The eslint-plugin-svelte rules use specific icons to indicate their capabilities:

    • 🔧 Fixable: The rule can be automatically fixed using the --fix option in the ESLint command line.
    • 💡 Suggestions: Some problems reported by the rule can be manually fixed using editor suggestions.
    • Recommended: The rule is included in the plugin:svelte/recommended configuration preset.
  11. Understand the svelte/valid-style-parse rule

    main

    The svelte/valid-style-parse rule ensures that the content within <style> elements in Svelte components can be successfully parsed by the svelte-eslint-parser. It catches syntax errors in CSS or issues where an unsupported lang attribute is used, which would prevent the parser from correctly interpreting the styles.

    <!-- ✓ GOOD: Standard CSS -->
    <style>
      .class {
        font-weight: bold;
      }
    </style>
    
    <!-- ✓ GOOD: Supported preprocessor (e.g., SCSS) -->
    <style lang="scss">
      .class {
        font-weight: bold;
      }
    </style>
    
    <!-- ✗ BAD: Invalid CSS syntax -->
    <style>
      .class
        font-weight: bold;
    </style>
    
    <!-- ✗ BAD: Unsupported lang attribute -->
    <style lang="unknown">
      .class {
        font-weight: bold;
      }
    </style>
  12. Understand the versioning policy for eslint-plugin-svelte

    main

    This project follows Semantic Versioning (SemVer).

    Note on Rule Updates: Unlike ESLint's own versioning policy, eslint-plugin-svelte may add new rules to its recommended configuration during minor releases. If these new rules introduce unwanted warnings in your project, you can disable them individually in your ESLint configuration.