|
| 1 | +<p> |
| 2 | + <img width="100%" src="https://assets.solidjs.com/banner?type=ESLint%20Plugin&background=tiles&project=%20" alt="Solid ESLint Extension"> |
| 3 | +</p> |
| 4 | + |
| 5 | +# Solid ESLint Plugin |
| 6 | + |
| 7 | +[](https://npmjs.com/package/eslint-plugin-solid) |
| 8 | +[](https://github.com/solidjs-community/eslint-plugin-solid) |
| 9 | + |
| 10 | +[](https://github.com/solidjs-community/eslint-plugin-solid/actions/workflows/ci.yml) |
| 11 | + |
| 12 | +This package contains [Solid](https://www.solidjs.com/)-specific linting rules for ESLint. It can |
| 13 | +ease Solid's learning curve by finding and fixing problems around Solid's reactivity system, and can |
| 14 | +migrate some React patterns to Solid code. |
| 15 | + |
| 16 | +It's approaching a `1.0.0` release, and it's well tested and should be helpful in Solid projects |
| 17 | +today. |
| 18 | + |
| 19 | +<!-- doc-gen TOC --> |
| 20 | +- [Installation](#installation) |
| 21 | +- [Configuration](#configuration) |
| 22 | + - [TypeScript](#typescript) |
| 23 | + - [Manual Configuration](#manual-configuration) |
| 24 | + - [Flat Configuration](#flat-configuration) |
| 25 | +- [Rules](#rules) |
| 26 | +- [Troubleshooting](#troubleshooting) |
| 27 | +- [Versioning](#versioning) |
| 28 | +<!-- end-doc-gen --> |
| 29 | + |
| 30 | +## Installation |
| 31 | + |
| 32 | +Install `eslint` and `eslint-plugin-solid` locally. |
| 33 | + |
| 34 | +```sh |
| 35 | +npm install --save-dev eslint eslint-plugin-solid |
| 36 | +# or |
| 37 | +pnpm add --save-dev eslint eslint-plugin-solid |
| 38 | +yarn add --dev eslint eslint-plugin-solid |
| 39 | + |
| 40 | +# optional, to create an ESLint config file |
| 41 | +npx eslint --init |
| 42 | +# or |
| 43 | +pnpm eslint --init |
| 44 | +yarn eslint --init |
| 45 | +``` |
| 46 | + |
| 47 | +If you're using VSCode, you'll want to install the [ESLint |
| 48 | +extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint). You're |
| 49 | +encouraged to enable auto-fixing problems on save by adding the following to your `settings.json` |
| 50 | +file. |
| 51 | + |
| 52 | +```json |
| 53 | +{ |
| 54 | + "editor.codeActionsOnSave": { |
| 55 | + "source.fixAll": true |
| 56 | + } |
| 57 | +} |
| 58 | +``` |
| 59 | + |
| 60 | +If you're using Vite, you may want to install |
| 61 | +[vite-plugin-eslint](https://github.com/gxmari007/vite-plugin-eslint). |
| 62 | + |
| 63 | +You may also want to check out |
| 64 | +[eslint-plugin-jsx-a11y](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y), which provides |
| 65 | +useful rules for writing accessible HTML. |
| 66 | + |
| 67 | +## Configuration |
| 68 | + |
| 69 | +Use the `"plugin:solid/recommended"` configuration to get reasonable defaults as shown [below](#rules). |
| 70 | + |
| 71 | +```json |
| 72 | +{ |
| 73 | + "plugins": ["solid"], |
| 74 | + "extends": ["eslint:recommended", "plugin:solid/recommended"] |
| 75 | +} |
| 76 | +``` |
| 77 | + |
| 78 | +### TypeScript |
| 79 | + |
| 80 | +If you're using TypeScript, use the `"plugin:solid/typescript"` configuration instead. |
| 81 | +This disables some features that overlap with type checking. |
| 82 | + |
| 83 | +```json |
| 84 | +{ |
| 85 | + "parser": "@typescript-eslint/parser", |
| 86 | + "plugins": ["solid"], |
| 87 | + "extends": ["eslint:recommended", "plugin:solid/typescript"] |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +### Manual Configuration |
| 92 | + |
| 93 | +If you don't want to use a preset, you can configure rules individually. Add the `"solid"` plugin, |
| 94 | +enable JSX with the parser options (or use the equivalent options for `@typescript-eslint/parser` or |
| 95 | +`@babel/eslint-parser`), and configure the rules you would like to use. Some rules have additional |
| 96 | +options you can set. |
| 97 | + |
| 98 | +```json |
| 99 | +{ |
| 100 | + "plugins": ["solid"], |
| 101 | + "parserOptions": { |
| 102 | + "ecmaFeatures": { |
| 103 | + "jsx": true |
| 104 | + } |
| 105 | + }, |
| 106 | + "rules": { |
| 107 | + "solid/reactivity": "warn", |
| 108 | + "solid/no-destructure": "warn", |
| 109 | + "solid/jsx-no-undef": "error" |
| 110 | + } |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +### Flat Configuration |
| 115 | + |
| 116 | +ESLint's new configuration system, [Flat |
| 117 | +Configuration](https://eslint.org/docs/latest/use/configure/configuration-files-new#using-configurations-included-in-plugins), |
| 118 | +is available starting in ESLint [v8.23.0](https://github.com/eslint/eslint/releases/tag/v8.23.0). To |
| 119 | +use it, create an `eslint.config.js` file at the root of your project, instead of `.eslintrc.*` |
| 120 | +and/or `.eslintignore`. |
| 121 | + |
| 122 | +```js |
| 123 | +import js from "@eslint/js"; |
| 124 | +import solid from "eslint-plugin-solid/configs/recommended"; |
| 125 | + |
| 126 | +export default [ |
| 127 | + js.configs.recommended, // replaces eslint:recommended |
| 128 | + solid, |
| 129 | +]; |
| 130 | +``` |
| 131 | + |
| 132 | +For TypeScript: |
| 133 | + |
| 134 | +```js |
| 135 | +import js from "@eslint/js"; |
| 136 | +import solid from "eslint-plugin-solid/configs/typescript"; |
| 137 | +import * as tsParser from "@typescript-eslint/parser"; |
| 138 | + |
| 139 | +export default [ |
| 140 | + js.configs.recommended, |
| 141 | + { |
| 142 | + files: ["**/*.{ts,tsx}"], |
| 143 | + ...solid, |
| 144 | + languageOptions: { |
| 145 | + parser: tsParser, |
| 146 | + parserOptions: { |
| 147 | + project: "tsconfig.json", |
| 148 | + }, |
| 149 | + }, |
| 150 | + }, |
| 151 | +]; |
| 152 | +``` |
| 153 | + |
| 154 | +These configurations do not configure global variables in ESLint. You can do this yourself manually |
| 155 | +or with a package like [globals](https://www.npmjs.com/package/globals) by creating a configuration |
| 156 | +with a `languageOptions.globals` object. We recommend setting up global variables for Browser APIs |
| 157 | +as well as at least ES2015. |
| 158 | + |
| 159 | +Note for the ESLint VSCode Extension: Enable the "Use Flat Config" setting for your workspace to |
| 160 | +enable Flat Config support. |
| 161 | + |
| 162 | +Flat configs are also available as `plugin.configs['flat/recommended']` and `plugin.configs['flat/typescript']`, after using `import plugin from 'eslint-plugin-solid'`. |
| 163 | + |
| 164 | +## Rules |
| 165 | + |
| 166 | +✔: Enabled in the `recommended` configuration. |
| 167 | + |
| 168 | +🔧: Fixable with [`eslint --fix`](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems)/IDE auto-fix. |
| 169 | + |
| 170 | +<!-- doc-gen RULES --> |
| 171 | +| ✔ | 🔧 | Rule | Description | |
| 172 | +| :---: | :---: | :--- | :--- | |
| 173 | +| ✔ | 🔧 | [solid/components-return-once](docs/components-return-once.md) | Disallow early returns in components. Solid components only run once, and so conditionals should be inside JSX. | |
| 174 | +| ✔ | 🔧 | [solid/event-handlers](docs/event-handlers.md) | Enforce naming DOM element event handlers consistently and prevent Solid's analysis from misunderstanding whether a prop should be an event handler. | |
| 175 | +| ✔ | 🔧 | [solid/imports](docs/imports.md) | Enforce consistent imports from "solid-js", "solid-js/web", and "solid-js/store". | |
| 176 | +| ✔ | | [solid/jsx-no-duplicate-props](docs/jsx-no-duplicate-props.md) | Disallow passing the same prop twice in JSX. | |
| 177 | +| ✔ | | [solid/jsx-no-script-url](docs/jsx-no-script-url.md) | Disallow javascript: URLs. | |
| 178 | +| ✔ | 🔧 | [solid/jsx-no-undef](docs/jsx-no-undef.md) | Disallow references to undefined variables in JSX. Handles custom directives. | |
| 179 | +| ✔ | | [solid/jsx-uses-vars](docs/jsx-uses-vars.md) | Prevent variables used in JSX from being marked as unused. | |
| 180 | +| | | [solid/no-array-handlers](docs/no-array-handlers.md) | Disallow usage of type-unsafe event handlers. | |
| 181 | +| ✔ | 🔧 | [solid/no-destructure](docs/no-destructure.md) | Disallow destructuring props. In Solid, props must be used with property accesses (`props.foo`) to preserve reactivity. This rule only tracks destructuring in the parameter list. | |
| 182 | +| ✔ | 🔧 | [solid/no-innerhtml](docs/no-innerhtml.md) | Disallow usage of the innerHTML attribute, which can often lead to security vulnerabilities. | |
| 183 | +| | | [solid/no-proxy-apis](docs/no-proxy-apis.md) | Disallow usage of APIs that use ES6 Proxies, only to target environments that don't support them. | |
| 184 | +| ✔ | 🔧 | [solid/no-react-deps](docs/no-react-deps.md) | Disallow usage of dependency arrays in `createEffect` and `createMemo`. | |
| 185 | +| ✔ | 🔧 | [solid/no-react-specific-props](docs/no-react-specific-props.md) | Disallow usage of React-specific `className`/`htmlFor` props, which were deprecated in v1.4.0. | |
| 186 | +| ✔ | | [solid/no-unknown-namespaces](docs/no-unknown-namespaces.md) | Enforce using only Solid-specific namespaced attribute names (i.e. `'on:'` in `<div on:click={...} />`). | |
| 187 | +| | 🔧 | [solid/prefer-classlist](docs/prefer-classlist.md) | Enforce using the classlist prop over importing a classnames helper. The classlist prop accepts an object `{ [class: string]: boolean }` just like classnames. | |
| 188 | +| ✔ | 🔧 | [solid/prefer-for](docs/prefer-for.md) | Enforce using Solid's `<For />` component for mapping an array to JSX elements. | |
| 189 | +| | 🔧 | [solid/prefer-show](docs/prefer-show.md) | Enforce using Solid's `<Show />` component for conditionally showing content. Solid's compiler covers this case, so it's a stylistic rule only. | |
| 190 | +| ✔ | | [solid/reactivity](docs/reactivity.md) | Enforce that reactivity (props, signals, memos, etc.) is properly used, so changes in those values will be tracked and update the view as expected. | |
| 191 | +| ✔ | 🔧 | [solid/self-closing-comp](docs/self-closing-comp.md) | Disallow extra closing tags for components without children. | |
| 192 | +| ✔ | 🔧 | [solid/style-prop](docs/style-prop.md) | Require CSS properties in the `style` prop to be valid and kebab-cased (ex. 'font-size'), not camel-cased (ex. 'fontSize') like in React, and that property values with dimensions are strings, not numbers with implicit 'px' units. | |
| 193 | +<!-- end-doc-gen --> |
| 194 | + |
| 195 | +## Troubleshooting |
| 196 | + |
| 197 | +The rules in this plugin provide sensible guidelines as well as possible, but there may be times |
| 198 | +where you know better than the rule and want to ignore a warning. To do that, [add a |
| 199 | +comment](https://eslint.org/docs/latest/user-guide/configuring/rules#disabling-rules) like the |
| 200 | +following: |
| 201 | + |
| 202 | +```jsx |
| 203 | +// eslint-disable-next-line solid/reactivity |
| 204 | +const [editedValue, setEditedValue] = createSignal(props.value); |
| 205 | +``` |
| 206 | + |
| 207 | +_Please note_: there may also be times where a rule correctly warns about a subtle problem, |
| 208 | +even if it looks like a false positive at first. With `solid/reactivity`, please look at the |
| 209 | +[reactivity docs](./docs/reactivity.md#troubleshooting) before deciding to disable the rule. |
| 210 | + |
| 211 | +When in doubt, feel free to [file an |
| 212 | +issue](https://github.com/solidjs-community/eslint-plugin-solid/issues/new/choose). |
| 213 | + |
| 214 | +## Versioning |
| 215 | + |
| 216 | +Pre-1.0.0, the rules and the `recommended` and `typescript` configuations will be |
| 217 | +stable across patch (`0.0.x`) versions, but may change across minor (`0.x`) versions. |
| 218 | +If you want to pin a minor version, use a tilde in your `package.json`. |
| 219 | + |
| 220 | +<!-- doc-gen TILDE --> |
| 221 | +```diff |
| 222 | +- "eslint-plugin-solid": "^0.14.2" |
| 223 | ++ "eslint-plugin-solid": "~0.14.2" |
| 224 | +``` |
| 225 | +<!-- end-doc-gen --> |
0 commit comments