@shayanthenerd/eslint-config 0.17.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +498 -342
- package/dist/configs/astro.mjs +1 -3
- package/dist/configs/base.mjs +4 -5
- package/dist/configs/css.mjs +1 -3
- package/dist/configs/cypress.mjs +1 -3
- package/dist/configs/html.mjs +2 -5
- package/dist/configs/importX.mjs +6 -11
- package/dist/configs/markdown.mjs +24 -0
- package/dist/configs/packageJson.mjs +20 -0
- package/dist/configs/perfectionist.mjs +3 -4
- package/dist/configs/playwright.mjs +1 -3
- package/dist/configs/promise.mjs +24 -0
- package/dist/configs/restrictedExports.mjs +1 -3
- package/dist/configs/storybook.mjs +1 -3
- package/dist/configs/stylistic.mjs +3 -4
- package/dist/configs/tailwind.mjs +33 -21
- package/dist/configs/typescript.mjs +4 -5
- package/dist/configs/vitest.mjs +1 -3
- package/dist/configs/vue.mjs +5 -10
- package/dist/configs/vueComponentNames.mjs +1 -3
- package/dist/configs/vueServerComponents.mjs +1 -3
- package/dist/configs/zod.mjs +9 -9
- package/dist/helpers/globs.mjs +6 -6
- package/dist/helpers/ignores/defaultIgnorePatterns.mjs +1 -2
- package/dist/helpers/ignores/getIgnorePatterns.mjs +1 -3
- package/dist/helpers/ignores/resolveGitignorePatterns.mjs +3 -5
- package/dist/helpers/isPackageDetected.mjs +5 -7
- package/dist/helpers/options/defaultOptions.mjs +102 -94
- package/dist/helpers/options/enableDetectedConfigs.mjs +4 -3
- package/dist/helpers/options/mergeWithDefaults.mjs +1 -3
- package/dist/helpers/vue/getRestrictedVueElements.mjs +1 -2
- package/dist/helpers/vue/getRestrictedVueInputs.mjs +1 -2
- package/dist/index.d.mts +34 -7
- package/dist/index.mjs +57 -26
- package/dist/prettier.config.mjs +21 -23
- package/dist/rules/astro.mjs +58 -57
- package/dist/rules/css.mjs +1 -3
- package/dist/rules/cypress.mjs +14 -14
- package/dist/rules/html.mjs +13 -6
- package/dist/rules/importX.mjs +2 -8
- package/dist/rules/javascript.mjs +49 -37
- package/dist/rules/markdown.mjs +52 -0
- package/dist/rules/packageJson.mjs +133 -0
- package/dist/rules/perfectionist.mjs +1 -3
- package/dist/rules/playwright.mjs +4 -3
- package/dist/rules/promise.mjs +26 -0
- package/dist/rules/storybook.mjs +1 -3
- package/dist/rules/stylistic.mjs +5 -6
- package/dist/rules/tailwind.mjs +9 -15
- package/dist/rules/typescript.mjs +15 -45
- package/dist/rules/vitest.mjs +2 -2
- package/dist/rules/vue.mjs +25 -14
- package/dist/rules/vueAccessibility.mjs +1 -5
- package/dist/rules/zod.mjs +54 -16
- package/dist/types/eslint-schema.d.mts +5145 -2020
- package/dist/types/eslintRules.d.mts +8 -2
- package/dist/types/helpers.d.mts +2 -2
- package/dist/types/index.d.mts +131 -163
- package/dist/types/{configOptions → options}/base.d.mts +20 -23
- package/dist/types/{configOptions → options}/css.d.mts +13 -13
- package/dist/types/{configOptions → options}/html.d.mts +13 -13
- package/dist/types/options/markdown.d.mts +42 -0
- package/dist/types/{configOptions → options}/nuxt.d.mts +12 -14
- package/dist/types/{configOptions → options}/perfectionist.d.mts +5 -4
- package/dist/types/{configOptions → options}/stylistic.d.mts +58 -65
- package/dist/types/{configOptions → options}/tailwind.d.mts +29 -19
- package/dist/types/{configOptions → options}/test.d.mts +32 -33
- package/dist/types/{configOptions → options}/typescript.d.mts +16 -7
- package/dist/types/{configOptions → options}/vue.d.mts +92 -106
- package/dist/types/{configOptions → options}/vueAccessibility.d.mts +14 -16
- package/dist/types/options/zod.d.mts +27 -0
- package/dist/utils/isEmptyString.mjs +1 -2
- package/dist/utils/isEnabled.mjs +1 -2
- package/dist/utils/isTruthy.mjs +6 -0
- package/package.json +97 -101
- package/dist/configs/oxlintOverrides.mjs +0 -52
- package/dist/oxlint.config.jsonc +0 -122
- package/dist/types/configOptions/importX.d.mts +0 -15
package/README.md
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
# @shayanthenerd/eslint-config  
|
|
1
|
+
# @shayanthenerd/eslint-config [![license-badge]][license] [![npm-version-badge]][npmx] [![jsr-version-badge]][jsr]
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
ESLint configuration for enforcing best practices and maintaining a consistent coding style. [Explore configurations][online-preview]!
|
|
4
4
|
|
|
5
|
-
- **
|
|
6
|
-
- **
|
|
7
|
-
- **Comprehensive**:
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **Developer-friendly**: Easy to use and well-documented with JSDoc
|
|
11
|
-
- **Modern**: Requires Node.js v20.12.0+ and ESLint v9.28.0+ (ESM-only)
|
|
12
|
-
|
|
13
|
-
> [!NOTE]
|
|
14
|
-
> This configuration is designed with a flexible API for easy customization. However, it remains a **personal config**. While its primary goal is to enforce best practices and maintain code consistency, some rules—particularly stylistic ones—are rather opinionated. <br /> If the available customization and override options still don't meet your requirements, feel free to fork the project and tailor it to your needs.
|
|
5
|
+
- **Flexible**: [Highly-customizable options](#customization) and configurations with sensible defaults.
|
|
6
|
+
- **Smart**: Context-aware linting with [automatic dependency detection](#automatic-dependency-detection) and _.gitignore_ recognition.
|
|
7
|
+
- **Comprehensive**: [Supports popular plugins](#plugin-support) for TypeScript, Astro, Vue & Nuxt, Tailwind, Zod, Vitest, Markdown, and more.
|
|
8
|
+
- **Type-safe**: [Fully-typed and well-documented API](#api-reference) with `overrides` support for every built-in configuration object.
|
|
9
|
+
- **Modern**: Requires ESLint ^10.4.0 and Node.js ^20.19.0 (ESM-only)
|
|
15
10
|
|
|
16
11
|
## Table of Contents
|
|
12
|
+
- [Plugin Support](#plugin-support)
|
|
17
13
|
- [Installation and Configuration](#installation-and-configuration)
|
|
14
|
+
- [Customization](#customization)
|
|
18
15
|
- [Automatic Dependency Detection](#automatic-dependency-detection)
|
|
16
|
+
- [Framework and Tool Integrations](#framework-and-tool-integrations)
|
|
17
|
+
- [IDE Support](#ide-support)
|
|
19
18
|
- [Formatting](#formatting)
|
|
20
|
-
- [VS Code Integration](#vs-code-integration)
|
|
21
|
-
- [Customization](#customization)
|
|
22
|
-
- [OXLint](#oxlint)
|
|
23
|
-
- [ESLint](#eslint)
|
|
24
19
|
- [API Reference](#api-reference)
|
|
25
20
|
- [Versioning Policy](#versioning-policy)
|
|
26
21
|
- [Roadmap to v1.0.0](#roadmap-to-v100)
|
|
@@ -28,170 +23,216 @@ A modern, flexible ESLint configuration for enforcing best practices and maintai
|
|
|
28
23
|
- [Credits](#credits)
|
|
29
24
|
- [License](#license)
|
|
30
25
|
|
|
31
|
-
##
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
|
|
39
|
-
|
|
26
|
+
## Plugin Support
|
|
27
|
+
Legend:
|
|
28
|
+
- ✅ Supported
|
|
29
|
+
- ⌛️ In progress
|
|
30
|
+
- ◻️ Enabled by default
|
|
31
|
+
- ⬛ Disabled by default
|
|
32
|
+
- 🔎 [Automatically detected](#automatic-dependency-detection) (`autoDetectDeps: true`)
|
|
33
|
+
|
|
34
|
+
| Category | Support | Activation |
|
|
35
|
+
| :----------------------------------------------------------- | :-----: | :----: |
|
|
36
|
+
| **Languages** | | |
|
|
37
|
+
| [JavaScript][eslint] | ✅ | ◻️ |
|
|
38
|
+
| [TypeScript][plugin-ts] | ✅ | 🔎 |
|
|
39
|
+
| [Markdown][plugin-md] | ✅ | ◻️ |
|
|
40
|
+
| [HTML][plugin-html] | ✅ | ⬛ |
|
|
41
|
+
| [CSS][plugin-css] | ✅ | ⬛ |
|
|
42
|
+
| **Formatting** | | |
|
|
43
|
+
| [Stylistic][plugin-stylistic] | ✅ | ◻️ |
|
|
44
|
+
| [Perfectionist][plugin-perfectionist] | ✅ | ◻️ |
|
|
45
|
+
| **Frameworks** | | |
|
|
46
|
+
| [Astro][plugin-astro] ([JSX accessibility][plugin-jsx-a11y]) | ✅ | 🔎 |
|
|
47
|
+
| [React][plugin-react] ([hooks][plugin-react-hooks]) | ⌛️ | N/A |
|
|
48
|
+
| [Next][plugin-next] | ⌛️ | N/A |
|
|
49
|
+
| [Vue & Nuxt][plugin-vue] ([accessibility][plugin-vue-a11y]) | ✅ | 🔎 |
|
|
50
|
+
| [Tailwind][plugin-tailwind] | ✅ | ⬛ |
|
|
51
|
+
| **Testing Tools** | | |
|
|
52
|
+
| [Storybook][plugin-storybook] | ✅ | 🔎 |
|
|
53
|
+
| [Vitest][plugin-vitest] | ✅ | 🔎 |
|
|
54
|
+
| [Cypress][plugin-cypress] | ✅ | 🔎 |
|
|
55
|
+
| [Playwright][plugin-playwright] | ✅ | 🔎 |
|
|
56
|
+
| **Miscellaneous** | | |
|
|
57
|
+
| [_package.json_][plugin-package-json] | ✅ | ◻️ |
|
|
58
|
+
| [promises][plugin-promise] | ✅ | ◻️ |
|
|
59
|
+
| [Imports][plugin-import-x] | ✅ | ◻️ |
|
|
60
|
+
| [Zod][plugin-zod] | ✅ | 🔎 |
|
|
61
|
+
| [Node][plugin-node] | ⌛️ | N/A |
|
|
62
|
+
| [Unicorn][plugin-unicorn] | ⌛️ | N/A |
|
|
40
63
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
64
|
+
## Installation and Configuration
|
|
65
|
+
1. Install the package and ESLint as dev dependencies:
|
|
66
|
+
```shell
|
|
67
|
+
npm i -D @shayanthenerd/eslint-config eslint
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
2. Create an ESLint configuration file (_eslint.config.js_) at the root of your project:
|
|
71
|
+
```js title="eslint.config.js"
|
|
72
|
+
import { defineConfig } from '@shayanthenerd/eslint-config';
|
|
73
|
+
|
|
74
|
+
export default defineConfig();
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Note: TypeScript configuration files (_eslint.config.ts_) are also supported. Node.js versions below v22.18.0 may require [additional setup][eslint-config-ts-setup].
|
|
78
|
+
|
|
79
|
+
3. Add the following scripts to your _package.json_:
|
|
80
|
+
```json title="package.json"
|
|
81
|
+
{
|
|
82
|
+
"scripts": {
|
|
83
|
+
"lint:inspect": "npx @eslint/config-inspector",
|
|
84
|
+
"lint": "eslint --fix --cache --cache-location='node_modules/.cache/.eslintcache'"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
46
88
|
|
|
47
|
-
|
|
48
|
-
```
|
|
89
|
+
---
|
|
49
90
|
|
|
50
|
-
|
|
91
|
+
After installation:
|
|
92
|
+
- Use `npm run lint` to lint and fix files.
|
|
93
|
+
- Use `npm run lint:inspect` to see a visual breakdown of your configuration.
|
|
94
|
+
- See [IDE Support](#ide-support) for editor integration.
|
|
95
|
+
- See [Customization](#customization) for advanced configuration.
|
|
96
|
+
- See [Formatting](#formatting) for formatting options and Prettier integration.
|
|
51
97
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
98
|
+
## Customization
|
|
99
|
+
`defineConfig()` supports both simple and advanced use cases:
|
|
100
|
+
```js title="eslint.config.js"
|
|
101
|
+
import eslintPluginYaml from 'eslint-plugin-yaml';
|
|
102
|
+
import * as eslintPluginRegexp from 'eslint-plugin-regexp';
|
|
56
103
|
|
|
57
|
-
Then, update your ESLint config file:
|
|
58
|
-
```js
|
|
59
104
|
import { defineConfig } from '@shayanthenerd/eslint-config';
|
|
60
105
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const eslintConfig = defineConfig();
|
|
64
|
-
|
|
65
|
-
export default eslintConfigNuxt(eslintConfig);
|
|
66
|
-
```
|
|
106
|
+
// Use the default configuration:
|
|
107
|
+
export default defineConfig();
|
|
67
108
|
|
|
68
|
-
|
|
69
|
-
|
|
109
|
+
// Customize the built-in configurations:
|
|
110
|
+
export default defineConfig({
|
|
111
|
+
autoDetectDeps: false,
|
|
112
|
+
configs: {
|
|
113
|
+
stylistic: false,
|
|
114
|
+
markdown: {
|
|
115
|
+
language: 'commonmark',
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
});
|
|
70
119
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
{
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
/* Customize based on your development environment. */
|
|
79
|
-
"env": {
|
|
80
|
-
"worker": false,
|
|
81
|
-
"commonjs": false,
|
|
82
|
-
"bun": false,
|
|
83
|
-
"deno": false,
|
|
84
|
-
"node": true,
|
|
85
|
-
"nodeBuiltin": true,
|
|
86
|
-
"browser": true,
|
|
87
|
-
"serviceworker": false,
|
|
88
|
-
"sharedWorker": false,
|
|
89
|
-
"webextension": false,
|
|
90
|
-
"audioWorklet": false,
|
|
91
|
-
"vitest": true,
|
|
92
|
-
"vue": true,
|
|
93
|
-
"astro": true
|
|
120
|
+
// Use custom configuration objects:
|
|
121
|
+
export default defineConfig([
|
|
122
|
+
{
|
|
123
|
+
files: ['**/*.yaml', '**/*.yml'],
|
|
124
|
+
ignores: ['**/*.schema.yaml', '**/*.schema.yml'],
|
|
125
|
+
extends: [eslintPluginYaml.configs.recommended],
|
|
94
126
|
},
|
|
127
|
+
eslintPluginRegexp.configs['flat/recommended'],
|
|
128
|
+
]);
|
|
95
129
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
130
|
+
// Customize the built-in configurations and use custom configuration objects:
|
|
131
|
+
export default defineConfig(
|
|
132
|
+
{
|
|
133
|
+
autoDetectDeps: 'verbose',
|
|
134
|
+
configs: {
|
|
135
|
+
typescript: {
|
|
136
|
+
typeDefinitionStyle: 'type',
|
|
137
|
+
overrides: {
|
|
138
|
+
rules: {
|
|
139
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
[
|
|
146
|
+
{
|
|
147
|
+
files: ['**/*.yaml', '**/*.yml'],
|
|
148
|
+
ignores: ['**/*.schema.yaml', '**/*.schema.yml'],
|
|
149
|
+
extends: [eslintPluginYaml.configs.recommended],
|
|
150
|
+
},
|
|
151
|
+
eslintPluginRegexp.configs['flat/recommended'],
|
|
152
|
+
],
|
|
153
|
+
);
|
|
106
154
|
```
|
|
107
155
|
|
|
108
|
-
|
|
156
|
+
Every built-in configuration accepts an `overrides` option. These values are merged into the generated configuration and take precedence over the defaults.
|
|
157
|
+
```ts
|
|
158
|
+
import type { ESLint, Linter } from 'eslint';
|
|
109
159
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
160
|
+
interface Overrides {
|
|
161
|
+
name?: string,
|
|
162
|
+
files?: (string | string[])[],
|
|
163
|
+
ignores?: string[],
|
|
164
|
+
plugins?: Record<string, ESLint.Plugin>,
|
|
165
|
+
languageOptions?: Linter.Config['languageOptions'],
|
|
166
|
+
settings?: Record<string, unknown>,
|
|
167
|
+
rules?: ConfigRules, // The available rules in the current configuration object
|
|
119
168
|
}
|
|
120
169
|
```
|
|
121
170
|
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
That's it! You can now run OXLint and ESLint in your project:
|
|
125
|
-
```shell
|
|
126
|
-
npm run lint
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
To get a visual breakdown of your configuration, run:
|
|
130
|
-
```shell
|
|
131
|
-
npm run lint:inspect
|
|
132
|
-
```
|
|
133
|
-
|
|
134
171
|
## Automatic Dependency Detection
|
|
135
|
-
|
|
136
|
-
> [!IMPORTANT]
|
|
137
|
-
> This behavior is particularly noticeable with package managers that use a flat _node_modules_ structure, such as **NPM** or **Bun**. <br />
|
|
138
|
-
A concrete example is `eslint-plugin-storybook`, which is a dependency of this package. Since the plugin transitively depends on `storybook`, NPM and Bun hoist `storybook` to the root of your _node_modules_. As a result, the ESLint configuration for `storybook` will be automatically enabled, even if you haven't explicitly installed it. <br />
|
|
139
|
-
Using a package manager with strict dependency resolution, such as **PNPM**, prevents this issue by hiding transitive dependencies from the root of your _node_modules_.
|
|
172
|
+
[local-pkg][local-pkg] is used to detect installed dependencies and automatically enable the relevant integrations. Package managers that hoist transitive dependencies (such as NPM and Bun) may sometimes cause an integration to get enabled unexpectedly. This is because **_local-pkg_ scans _node_modules_ instead of _package.json_.**
|
|
140
173
|
|
|
141
|
-
|
|
174
|
+
PNPM's strict dependency resolution avoids this issue.
|
|
142
175
|
|
|
143
|
-
|
|
176
|
+
> [!NOTE]
|
|
177
|
+
> For example, `eslint-plugin-storybook` depends on `storybook`, which is hoisted by NPM and Bun. As a result, the integration for `storybook` will be enabled automatically, even if you haven't explicitly installed it.
|
|
144
178
|
|
|
145
|
-
|
|
179
|
+
To opt out of this behavior, either [globally disable automatic dependency detection](#customization) or manually disable the unwanted integrations that were enabled automatically.
|
|
146
180
|
|
|
147
|
-
##
|
|
148
|
-
|
|
181
|
+
## Framework and Tool Integrations
|
|
182
|
+
### Tailwind
|
|
183
|
+
The Tailwind integration isn't automatically enabled because ESLint needs to know where to locate your Tailwind configuration.
|
|
184
|
+
```js title="eslint.config.js"
|
|
185
|
+
import { defineConfig } from '@shayanthenerd/eslint-config';
|
|
149
186
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
187
|
+
export default defineConfig({
|
|
188
|
+
configs: {
|
|
189
|
+
tailwind: {
|
|
190
|
+
/* Either option is sufficient, but both can be provided. */
|
|
191
|
+
config: './tailwind.config.js',
|
|
192
|
+
entryPoint: './app/assets/styles/app.css',
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
});
|
|
153
196
|
```
|
|
154
197
|
|
|
155
|
-
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
198
|
+
For editor integration, to avoid inconsistent diagnostics and auto-fixes from the [Tailwind CSS IntelliSense VS Code extension][extension-tailwind], add the following settings to _.vscode/settings.json_:
|
|
199
|
+
```json title=".vscode/settings.json"
|
|
200
|
+
{
|
|
201
|
+
"tailwindCSS.lint.cssConflict": "ignore",
|
|
202
|
+
"tailwindCSS.lint.recommendedVariantOrder": "ignore",
|
|
203
|
+
"tailwindCSS.lint.suggestCanonicalClasses": "ignore",
|
|
204
|
+
|
|
205
|
+
"eslint.rules.customizations": [
|
|
206
|
+
{ "rule": "better-tailwindcss/*", "severity": "off", "fixable": true },
|
|
207
|
+
{ "rule": "better-tailwindcss/no-restricted-classes", "severity": "warn", "fixable": true },
|
|
208
|
+
{ "rule": "better-tailwindcss/no-conflicting-classes", "severity": "error", "fixable": false },
|
|
209
|
+
{ "rule": "better-tailwindcss/no-unknown-classes", "severity": "warn", "fixable": false }
|
|
210
|
+
]
|
|
211
|
+
}
|
|
164
212
|
```
|
|
165
213
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
import type { Config } from 'prettier';
|
|
214
|
+
### Nuxt
|
|
215
|
+
Nuxt support is already included through the Vue integration, so you don’t need to install or configure [@nuxt/eslint][eslint-nuxt] manually. If you need additional rules tailored to Nuxt, refer to the plugin’s documentation for setup instructions.
|
|
169
216
|
|
|
170
|
-
|
|
217
|
+
> [!TIP]
|
|
218
|
+
> `configs.nuxt` only includes options for Nuxt Image, Nuxt UI, and the `<Icon>` component. Vue's rules and `overrides` can be configured via `configs.vue`.
|
|
171
219
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
semi: true, // Override `semi` from the shared config
|
|
175
|
-
} satisfies Config;
|
|
176
|
-
```
|
|
220
|
+
### Markdown
|
|
221
|
+
Markdown linting is powered by [@eslint/markdown][plugin-md].
|
|
177
222
|
|
|
178
|
-
|
|
179
|
-
```json
|
|
180
|
-
{
|
|
181
|
-
"scripts": {
|
|
182
|
-
"format": "prettier --write . '!**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,html,vue,astro}' --cache"
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
```
|
|
223
|
+
By default, the plugin uses GitHub Flavored Markdown (GFM). You can [switch to CommonMark](#customization) if you prefer, but rules related to tables, label references, and other GFM syntax will be disabled because CommonMark doesn't support them.
|
|
186
224
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
225
|
+
> [!NOTE]
|
|
226
|
+
> Fenced code blocks inside Markdown files are not linted by @eslint/markdown.
|
|
227
|
+
|
|
228
|
+
## IDE Support
|
|
229
|
+
Install the VS Code extensions for [ESLint][extension-eslint] and [Prettier][extension-prettier]. Then add the following in _.vscode/settings.json_:
|
|
230
|
+
```jsonc title=".vscode/settings.json"
|
|
190
231
|
{
|
|
191
232
|
/* Enforce Unix-like line endings (LF). */
|
|
192
233
|
"files.eol": "\n",
|
|
193
234
|
|
|
194
|
-
/* Enforce
|
|
235
|
+
/* Enforce 2 spaces for indentation. */
|
|
195
236
|
"editor.tabSize": 2,
|
|
196
237
|
"editor.insertSpaces": true,
|
|
197
238
|
"editor.detectIndentation": false,
|
|
@@ -202,35 +243,27 @@ Install VS Code extensions for [ESLint](https://marketplace.visualstudio.com/ite
|
|
|
202
243
|
"source.organizeImports": "never",
|
|
203
244
|
"source.removeUnusedImports": "never",
|
|
204
245
|
|
|
205
|
-
/* Apply
|
|
206
|
-
"source.fixAll.oxc": "explicit",
|
|
246
|
+
/* Apply ESLint fixes when saving files. */
|
|
207
247
|
"source.fixAll.eslint": "explicit"
|
|
208
248
|
},
|
|
209
|
-
"oxc.lint.run": "onSave",
|
|
210
|
-
"eslint.run": "onSave",
|
|
211
|
-
"editor.formatOnSave": true,
|
|
212
|
-
"eslint.format.enable": true,
|
|
213
249
|
|
|
214
|
-
|
|
215
|
-
"
|
|
216
|
-
"[javascript][typescript][javascriptreact][typescriptreact][html][vue][astro]": {
|
|
217
|
-
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
|
218
|
-
},
|
|
250
|
+
"eslint.run": "onSave",
|
|
251
|
+
"eslint.format.enable": true,
|
|
219
252
|
"eslint.validate": [
|
|
220
253
|
"javascript",
|
|
221
254
|
"typescript",
|
|
222
255
|
"javascriptreact",
|
|
223
256
|
"typescriptreact",
|
|
257
|
+
"json",
|
|
258
|
+
"markdown",
|
|
224
259
|
"html",
|
|
225
260
|
"css",
|
|
226
261
|
"tailwindcss",
|
|
227
|
-
"
|
|
228
|
-
"
|
|
262
|
+
"astro",
|
|
263
|
+
"vue"
|
|
229
264
|
],
|
|
230
265
|
|
|
231
|
-
/* Adjust these based on the features you're using to silently auto-fix the stylistic rules
|
|
232
|
-
"tailwindCSS.lint.cssConflict": "ignore", // Only if you're using the Tailwind config
|
|
233
|
-
"tailwindCSS.lint.recommendedVariantOrder": "ignore", // Only if you're using the Tailwind config
|
|
266
|
+
/* Adjust these based on the features you're using to silently auto-fix the stylistic rules. */
|
|
234
267
|
"eslint.rules.customizations": [
|
|
235
268
|
{ "rule": "*styl*", "severity": "off", "fixable": true },
|
|
236
269
|
{ "rule": "*sort*", "severity": "off", "fixable": true },
|
|
@@ -241,214 +274,313 @@ Install VS Code extensions for [ESLint](https://marketplace.visualstudio.com/ite
|
|
|
241
274
|
{ "rule": "*order-*", "severity": "off", "fixable": true },
|
|
242
275
|
{ "rule": "*newline*", "severity": "off", "fixable": true },
|
|
243
276
|
{ "rule": "*attribute*", "severity": "off", "fixable": true },
|
|
277
|
+
{ "rule": "package-json/order-properties", "severity": "off", "fixable": true },
|
|
244
278
|
{ "rule": "vue/max-len", "severity": "off", "fixable": true },
|
|
245
279
|
{ "rule": "vue/comma-dangle", "severity": "off", "fixable": true },
|
|
246
|
-
{ "rule": "vue/space-in-parens", "severity": "off", "fixable": true }
|
|
247
|
-
{ "rule": "better-tailwindcss/*", "severity": "off", "fixable": true },
|
|
248
|
-
{ "rule": "better-tailwindcss/no-restricted-classes", "severity": "error", "fixable": true },
|
|
249
|
-
{ "rule": "better-tailwindcss/no-conflicting-classes", "severity": "error", "fixable": false },
|
|
250
|
-
{ "rule": "better-tailwindcss/no-unregistered-classes", "severity": "error", "fixable": false }
|
|
280
|
+
{ "rule": "vue/space-in-parens", "severity": "off", "fixable": true }
|
|
251
281
|
]
|
|
252
282
|
}
|
|
253
283
|
```
|
|
254
284
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
Since OXLint and ESLint use separate config files, customizations made in your ESLint config will not apply to OXLint. However, you can still customize OXLint rules in your _.oxlintrc.json_ file. Here's an example:
|
|
258
|
-
```jsonc
|
|
259
|
-
{
|
|
260
|
-
/* Base configuration */
|
|
285
|
+
> [!TIP]
|
|
286
|
+
> These settings match the default behavior of this configuration. If you've customized any formatting or stylistic rules, update the corresponding editor settings to keep them consistent.
|
|
261
287
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
288
|
+
## Formatting
|
|
289
|
+
This configuration uses [ESLint Stylistic][plugin-stylistic] to format:
|
|
290
|
+
- JavaScript and TypeScript (_js_, _cjs_, _mjs_, _jsx_, _ts_, _cts_, _mts_, _tsx_),
|
|
291
|
+
- Astro (similar to _jsx_/_tsx_), and
|
|
292
|
+
- Vue's `<script>` blocks.
|
|
266
293
|
|
|
267
|
-
|
|
268
|
-
/* Override rules for specific files. */
|
|
269
|
-
{
|
|
270
|
-
"files": ["app/**/*.tsx"],
|
|
271
|
-
"ignores": ["app/app.tsx"],
|
|
272
|
-
"rules": {
|
|
273
|
-
"oxlint/max-depth": ["error", { "max": 5 }],
|
|
274
|
-
"oxlint/explicit-function-return-type": "off"
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
],
|
|
294
|
+
HTML and Vue's `<template>` blocks are formatted with [@html-eslint/eslint-plugin][plugin-html] and [eslint-plugin-vue][plugin-vue], respectively.
|
|
278
295
|
|
|
279
|
-
|
|
280
|
-
|
|
296
|
+
For file types not handled by ESLint Stylistic—such as CSS, JSON, Yaml, and Markdown—you can use Prettier. To simplify the setup, this package also provides a customizable [shared Prettier configuration][prettier-shared-config].
|
|
297
|
+
|
|
298
|
+
1. Install Prettier as a dev dependency:
|
|
299
|
+
```shell
|
|
300
|
+
npm i -D prettier
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
2. Create a Prettier config file in the root of your project (_prettier.config.js_):
|
|
304
|
+
```js title="prettier.config.js"
|
|
305
|
+
import prettierConfig from '@shayanthenerd/eslint-config/prettier';
|
|
306
|
+
|
|
307
|
+
/** @type {import('prettier').Config} */
|
|
308
|
+
export default {
|
|
309
|
+
...prettierConfig,
|
|
310
|
+
semi: false, // Override `semi` from the shared config
|
|
311
|
+
};
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Or if you prefer using TypeScript (_prettier.config.ts_):
|
|
315
|
+
```ts title="prettier.config.ts"
|
|
316
|
+
import type { Config } from 'prettier';
|
|
317
|
+
|
|
318
|
+
import prettierConfig from '@shayanthenerd/eslint-config/prettier';
|
|
319
|
+
|
|
320
|
+
export default {
|
|
321
|
+
...prettierConfig,
|
|
322
|
+
semi: true, // Override `semi` from the shared config
|
|
323
|
+
} satisfies Config;
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Using ESLint Stylistic with Prettier
|
|
327
|
+
In this setup, Prettier formats everything that ESLint Stylistic doesn't. To prevent overlaps and potential race conditions, Prettier should only target files that ESLint Stylistic doesn't format.
|
|
328
|
+
|
|
329
|
+
_package.json_:
|
|
330
|
+
```json title="package.json"
|
|
331
|
+
{
|
|
332
|
+
"scripts": {
|
|
333
|
+
"format": "prettier --write . '!**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,html,vue,astro}' --cache"
|
|
334
|
+
}
|
|
281
335
|
}
|
|
282
336
|
```
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
ignores: [],
|
|
291
|
-
plugins: {},
|
|
292
|
-
settings: {},
|
|
293
|
-
languageOptions: {
|
|
294
|
-
parser: {},
|
|
295
|
-
globals: {},
|
|
337
|
+
_.vscode/settings.json_:
|
|
338
|
+
```json title=".vscode/settings.json"
|
|
339
|
+
{
|
|
340
|
+
"editor.formatOnSave": true,
|
|
341
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
342
|
+
"[javascript][typescript][javascriptreact][typescriptreact][html][vue][astro][{**/package.json}]": {
|
|
343
|
+
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
|
296
344
|
},
|
|
297
|
-
rules: {},
|
|
298
345
|
}
|
|
299
346
|
```
|
|
300
347
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
`defineConfig` also accepts any number of custom ESLint Flat Configs (_eslint.config.js_):
|
|
304
|
-
```js
|
|
305
|
-
import eslintPluginYaml from 'eslint-plugin-yaml';
|
|
306
|
-
import * as eslintPluginRegexp from 'eslint-plugin-regexp';
|
|
307
|
-
import { defineConfig } from '@shayanthenerd/eslint-config';
|
|
308
|
-
|
|
309
|
-
export default defineConfig(
|
|
310
|
-
/* The options object: */
|
|
311
|
-
{
|
|
312
|
-
env: 'bun',
|
|
313
|
-
configs: {
|
|
314
|
-
typescript: {
|
|
315
|
-
typeDefinitionStyle: 'type',
|
|
316
|
-
overrides: {
|
|
317
|
-
rules: {
|
|
318
|
-
'@typescript-eslint/no-unsafe-type-assertion': 'off',
|
|
319
|
-
},
|
|
320
|
-
},
|
|
321
|
-
},
|
|
322
|
-
},
|
|
323
|
-
},
|
|
348
|
+
### Using Prettier Alone
|
|
349
|
+
If you prefer to use Prettier as the only formatter, [disable the stylistic configuration](#customization) and let Prettier handle all formatting. Note that **this approach provides less granular control over the formatting options**.
|
|
324
350
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
);
|
|
351
|
+
_package.json_:
|
|
352
|
+
```json title="package.json"
|
|
353
|
+
{
|
|
354
|
+
"scripts": {
|
|
355
|
+
"format": "prettier --write . --cache"
|
|
356
|
+
}
|
|
357
|
+
}
|
|
333
358
|
```
|
|
359
|
+
_.vscode/settings.json_:
|
|
360
|
+
```json title=".vscode/settings.json"
|
|
361
|
+
{
|
|
362
|
+
"eslint.format.enable": false,
|
|
363
|
+
"editor.formatOnSave": true,
|
|
364
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
365
|
+
"editor.codeActionsOnSave": {
|
|
366
|
+
"source.fixAll.eslint": "never"
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
When using this approach:
|
|
372
|
+
- Avoid running `lint` and `format` scripts on the same files simultaneously.
|
|
373
|
+
- Use either ESLint fixes or Prettier formatting when saving files, but not both.
|
|
334
374
|
|
|
335
375
|
## API Reference
|
|
336
376
|
<details>
|
|
337
|
-
<summary>
|
|
338
|
-
|
|
377
|
+
<summary>
|
|
378
|
+
<!-- eslint-disable-next-line markdown/no-html -->
|
|
379
|
+
The API reference of the <code>options</code> object passed to <code>defineConfig</code>
|
|
380
|
+
</summary><br />
|
|
339
381
|
|
|
382
|
+
<small>Some types are omitted or aliased for brevity.</small>
|
|
383
|
+
|
|
384
|
+
<!-- START_AUTO-GENERATED_API_REFERENCE -->
|
|
340
385
|
```ts
|
|
386
|
+
import type { ESLint, Linter } from 'eslint';
|
|
387
|
+
|
|
388
|
+
type VueAttributeCategory =
|
|
389
|
+
| 'SLOT'
|
|
390
|
+
| 'EVENTS'
|
|
391
|
+
| 'GLOBAL'
|
|
392
|
+
| 'UNIQUE'
|
|
393
|
+
| 'CONTENT'
|
|
394
|
+
| 'DEFINITION'
|
|
395
|
+
| 'OTHER_ATTR'
|
|
396
|
+
| 'ATTR_STATIC'
|
|
397
|
+
| 'ATTR_DYNAMIC'
|
|
398
|
+
| 'CONDITIONALS'
|
|
399
|
+
| 'LIST_RENDERING'
|
|
400
|
+
| 'TWO_WAY_BINDING'
|
|
401
|
+
| 'OTHER_DIRECTIVES'
|
|
402
|
+
| 'RENDER_MODIFIERS'
|
|
403
|
+
| 'ATTR_SHORTHAND_BOOL';
|
|
404
|
+
|
|
405
|
+
interface Overrides {
|
|
406
|
+
name?: string,
|
|
407
|
+
files?: (string | string[])[],
|
|
408
|
+
ignores?: string[],
|
|
409
|
+
plugins?: Record<string, ESLint.Plugin>,
|
|
410
|
+
languageOptions?: Linter.Config['languageOptions'],
|
|
411
|
+
settings?: Record<string, unknown>,
|
|
412
|
+
rules?: ConfigRules, // The available rules in the current configuration object
|
|
413
|
+
}
|
|
414
|
+
|
|
341
415
|
interface Options {
|
|
342
416
|
autoDetectDeps?: boolean | 'verbose',
|
|
417
|
+
env?: 'browser' | 'bun' | 'deno' | 'node',
|
|
343
418
|
gitignore?: false | string,
|
|
344
419
|
packageDir?: string,
|
|
345
|
-
|
|
346
|
-
tsConfig?: {
|
|
347
|
-
rootDir: string,
|
|
420
|
+
tsConfig?: false | {
|
|
348
421
|
filename?: string,
|
|
422
|
+
rootDir: string,
|
|
349
423
|
},
|
|
350
424
|
|
|
351
|
-
|
|
352
|
-
name?: string,
|
|
425
|
+
project?: {
|
|
353
426
|
basePath?: string,
|
|
354
|
-
ignores?: string[],
|
|
355
427
|
globals?: {
|
|
356
|
-
|
|
357
|
-
|
|
428
|
+
astro?: boolean,
|
|
429
|
+
audioWorklet?: boolean,
|
|
430
|
+
browser?: boolean,
|
|
358
431
|
bun?: boolean,
|
|
432
|
+
commonjs?: boolean,
|
|
359
433
|
deno?: boolean,
|
|
360
434
|
node?: boolean,
|
|
361
435
|
nodeBuiltin?: boolean,
|
|
362
|
-
browser?: boolean,
|
|
363
436
|
serviceworker?: boolean,
|
|
364
437
|
sharedWorker?: boolean,
|
|
365
|
-
webextension?: boolean,
|
|
366
|
-
audioWorklet?: boolean,
|
|
367
438
|
vitest?: boolean,
|
|
368
439
|
vue?: boolean,
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
440
|
+
webextension?: boolean,
|
|
441
|
+
worker?: boolean,
|
|
442
|
+
custom?: Record<string, 'off' | boolean | 'readable' | 'readonly' | 'writable' | 'writeable'>,
|
|
443
|
+
},
|
|
444
|
+
ignores?: string[],
|
|
374
445
|
linterOptions?: {
|
|
375
446
|
noInlineConfig?: boolean,
|
|
376
|
-
|
|
377
|
-
|
|
447
|
+
reportUnusedDisableDirectives?: 'off' | 'warn' | 'error',
|
|
448
|
+
reportUnusedInlineConfigs?: 'off' | 'warn' | 'error',
|
|
378
449
|
},
|
|
379
|
-
|
|
380
|
-
[name: string]: unknown,
|
|
381
|
-
}
|
|
450
|
+
name?: string,
|
|
382
451
|
rules?: Linter.RulesRecord,
|
|
452
|
+
settings?: Record<string, unknown>,
|
|
383
453
|
},
|
|
384
454
|
|
|
385
455
|
configs?: {
|
|
386
|
-
|
|
456
|
+
astro?: boolean | {
|
|
457
|
+
overrides?: Overrides,
|
|
458
|
+
},
|
|
387
459
|
base?: {
|
|
460
|
+
functionStyle?: 'expression' | 'declaration',
|
|
388
461
|
maxDepth?: number,
|
|
389
462
|
maxNestedCallbacks?: number,
|
|
390
463
|
preferNamedExports?: boolean,
|
|
391
|
-
|
|
392
|
-
|
|
464
|
+
overrides?: Overrides,
|
|
465
|
+
},
|
|
466
|
+
css?: boolean | {
|
|
467
|
+
allowedRelativeFontUnits?: (
|
|
468
|
+
| '%'
|
|
469
|
+
| 'ch'
|
|
470
|
+
| 'em'
|
|
471
|
+
| 'ex'
|
|
472
|
+
| 'ic'
|
|
473
|
+
| 'lh'
|
|
474
|
+
| 'cap'
|
|
475
|
+
| 'rch'
|
|
476
|
+
| 'rem'
|
|
477
|
+
| 'rex'
|
|
478
|
+
| 'ric'
|
|
479
|
+
| 'rlh'
|
|
480
|
+
| 'rcap'
|
|
481
|
+
)[],
|
|
482
|
+
useBaseline?: false | number | 'newly' | 'widely',
|
|
483
|
+
overrides?: Overrides,
|
|
484
|
+
},
|
|
485
|
+
html?: boolean | {
|
|
486
|
+
idNamingConvention?: 'camelCase' | 'kebab-case' | 'PascalCase' | 'snake_case',
|
|
487
|
+
useBaseline?: false | number | 'newly' | 'widely',
|
|
488
|
+
overrides?: Overrides,
|
|
489
|
+
},
|
|
490
|
+
importX?: boolean | {
|
|
491
|
+
overrides?: Overrides,
|
|
492
|
+
},
|
|
493
|
+
markdown?: boolean | {
|
|
494
|
+
allowedHtmlTags?: string[],
|
|
495
|
+
frontmatter?: false | 'json' | 'toml' | 'yaml',
|
|
496
|
+
language?: 'gfm' | 'commonmark',
|
|
497
|
+
overrides?: Overrides,
|
|
498
|
+
},
|
|
499
|
+
nuxt?: boolean | {
|
|
500
|
+
icon?: boolean | {
|
|
501
|
+
component?: string,
|
|
502
|
+
},
|
|
503
|
+
image?: boolean,
|
|
504
|
+
ui?: boolean | {
|
|
505
|
+
prefix?: string,
|
|
506
|
+
},
|
|
507
|
+
},
|
|
508
|
+
packageJson?: boolean | {
|
|
509
|
+
overrides?: Overrides,
|
|
510
|
+
},
|
|
511
|
+
perfectionist?: boolean | {
|
|
512
|
+
sortType?: 'custom' | 'natural' | 'unsorted' | 'line-length' | 'alphabetical' | 'subgroup-order',
|
|
513
|
+
overrides?: Overrides,
|
|
514
|
+
},
|
|
515
|
+
promise?: boolean | {
|
|
516
|
+
overrides?: Overrides,
|
|
393
517
|
},
|
|
394
518
|
stylistic?: boolean | {
|
|
395
|
-
semi?: 'always' | 'never',
|
|
396
|
-
trailingComma?: 'always' | 'never' | 'always-multiline' | 'only-multiline',
|
|
397
|
-
memberDelimiterStyle?: 'semi' | 'comma',
|
|
398
|
-
quotes?: 'single' | 'double' | 'backtick',
|
|
399
|
-
jsxQuotes?: 'prefer-single' | 'prefer-double',
|
|
400
519
|
arrowParens?: 'always' | 'as-needed',
|
|
401
520
|
indent?: number,
|
|
521
|
+
jsxQuotes?: 'prefer-double' | 'prefer-single',
|
|
522
|
+
maxAttributesPerLine?: number,
|
|
402
523
|
maxConsecutiveEmptyLines?: number,
|
|
403
524
|
maxLineLength?: number,
|
|
404
|
-
|
|
525
|
+
memberDelimiterStyle?: 'semi' | 'comma',
|
|
526
|
+
quotes?: 'double' | 'single' | 'backtick',
|
|
405
527
|
selfCloseVoidHTMLElements?: 'never' | 'always',
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
useBaseline?: number | false | 'widely' | 'newly',
|
|
410
|
-
idNamingConvention?: 'camelCase' | 'snake_case' | 'PascalCase' | 'kebab-case',
|
|
411
|
-
overrides?: {},
|
|
412
|
-
},
|
|
413
|
-
css?: boolean | {
|
|
414
|
-
useBaseline?: number | false | 'widely' | 'newly',
|
|
415
|
-
allowedRelativeFontUnits?: ('%' | 'cap' | 'ch' | 'em' | 'ex' | 'ic' | 'lh' | 'rcap' | 'rch' | 'rem' | 'rex' | 'ric' | 'rlh')[],
|
|
416
|
-
overrides?: {},
|
|
528
|
+
semi?: 'never' | 'always',
|
|
529
|
+
trailingComma?: 'never' | 'always' | 'only-multiline' | 'always-multiline',
|
|
530
|
+
overrides?: Overrides,
|
|
417
531
|
},
|
|
418
532
|
tailwind?: false | {
|
|
419
533
|
config: string,
|
|
534
|
+
cwd?: string,
|
|
420
535
|
entryPoint?: string,
|
|
536
|
+
ignoredUnknownClasses?: string[],
|
|
421
537
|
multilineSort?: boolean,
|
|
422
|
-
|
|
423
|
-
overrides?: {},
|
|
538
|
+
overrides?: Overrides,
|
|
424
539
|
} | {
|
|
425
540
|
config?: string,
|
|
541
|
+
cwd?: string,
|
|
426
542
|
entryPoint: string,
|
|
543
|
+
ignoredUnknownClasses?: string[],
|
|
427
544
|
multilineSort?: boolean,
|
|
428
|
-
|
|
429
|
-
|
|
545
|
+
overrides?: Overrides,
|
|
546
|
+
},
|
|
547
|
+
test?: {
|
|
548
|
+
maxNestedDescribe?: number,
|
|
549
|
+
testFunction?: 'it' | 'test',
|
|
550
|
+
cypress?: boolean | {
|
|
551
|
+
overrides?: Overrides,
|
|
552
|
+
},
|
|
553
|
+
playwright?: boolean | {
|
|
554
|
+
overrides?: Overrides,
|
|
555
|
+
},
|
|
556
|
+
storybook?: boolean | {
|
|
557
|
+
overrides?: Overrides,
|
|
558
|
+
},
|
|
559
|
+
vitest?: boolean | {
|
|
560
|
+
overrides?: Overrides,
|
|
561
|
+
},
|
|
430
562
|
},
|
|
431
563
|
typescript?: boolean | {
|
|
432
564
|
allowedDefaultProjects?: string[],
|
|
433
|
-
methodSignatureStyle?: '
|
|
434
|
-
typeDefinitionStyle?: 'interface' | 'type',
|
|
435
|
-
overrides?: {},
|
|
436
|
-
},
|
|
437
|
-
importX?: boolean | {
|
|
565
|
+
methodSignatureStyle?: 'method' | 'property',
|
|
438
566
|
removeUnusedImports?: boolean,
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
perfectionist?: boolean | {
|
|
442
|
-
sortType?: 'custom' | 'natural' | 'alphabetical' | 'line-length' | 'unsorted',
|
|
443
|
-
overrides?: {},
|
|
567
|
+
typeDefinitionStyle?: 'type' | 'interface',
|
|
568
|
+
overrides?: Overrides,
|
|
444
569
|
},
|
|
445
570
|
vue?: boolean | {
|
|
446
571
|
accessibility?: boolean | {
|
|
572
|
+
accessibleChildComponents?: string[],
|
|
447
573
|
anchorComponents?: string[],
|
|
448
574
|
imageComponents?: string[],
|
|
449
|
-
accessibleChildComponents?: string[],
|
|
450
575
|
},
|
|
451
|
-
|
|
576
|
+
allowedStyleAttributes?: ['plain' | 'module' | 'scoped', 'plain' | 'module' | 'scoped'],
|
|
577
|
+
attributeHyphenation?: 'never' | 'always',
|
|
578
|
+
attributesOrder?: (VueAttributeCategory | VueAttributeCategory[])[],
|
|
579
|
+
blockLang?: {
|
|
580
|
+
script?: 'js' | 'ts' | 'jsx' | 'tsx' | 'implicit',
|
|
581
|
+
style?: 'css' | 'scss' | 'postcss' | 'implicit',
|
|
582
|
+
},
|
|
583
|
+
blocksOrder?: (
|
|
452
584
|
| 'docs'
|
|
453
585
|
| 'template'
|
|
454
586
|
| 'script[setup]'
|
|
@@ -458,92 +590,116 @@ export default defineConfig(
|
|
|
458
590
|
| 'style:not([scoped])'
|
|
459
591
|
| 'i18n:not([locale=en])'
|
|
460
592
|
)[],
|
|
593
|
+
componentNameCaseInTemplate?: 'kebab-case' | 'PascalCase',
|
|
594
|
+
destructureProps?: 'never' | 'always' | 'only-when-assigned',
|
|
595
|
+
ignoredUndefinedComponents?: string[],
|
|
461
596
|
macrosOrder?: (
|
|
462
597
|
| 'definePage'
|
|
598
|
+
| 'defineEmits'
|
|
463
599
|
| 'defineModel'
|
|
464
600
|
| 'defineProps'
|
|
465
|
-
| 'defineEmits'
|
|
466
601
|
| 'defineSlots'
|
|
467
602
|
| 'defineCustom'
|
|
468
603
|
| 'defineExpose'
|
|
469
604
|
| 'defineOptions'
|
|
470
605
|
)[],
|
|
471
|
-
attributesOrder?: RuleOptions<'vue/attributes-order'>['order'],
|
|
472
|
-
attributeHyphenation?: 'never' | 'always',
|
|
473
606
|
preferVBindSameNameShorthand?: 'never' | 'always',
|
|
474
607
|
preferVBindTrueShorthand?: 'never' | 'always',
|
|
475
|
-
allowedStyleAttributes?: ['module' | 'plain' | 'scoped', 'module' | 'plain' | 'scoped'],
|
|
476
|
-
blockLang?: {
|
|
477
|
-
style?: 'css' | 'implicit' | 'scss' | 'postcss',
|
|
478
|
-
script?: 'js' | 'ts' | 'jsx' | 'tsx' | 'implicit',
|
|
479
|
-
},
|
|
480
|
-
destructureProps?: 'never' | 'always',
|
|
481
|
-
componentNameCaseInTemplate?: 'PascalCase' | 'kebab-case',
|
|
482
|
-
vForDelimiterStyle?: 'in' | 'of',
|
|
483
|
-
vOnHandlerStyle?: 'inline' | 'inline-function' | ['method', 'inline' | 'inline-function'],
|
|
484
608
|
restrictedElements?: (string | {
|
|
485
609
|
element: string | string[],
|
|
486
610
|
message: string,
|
|
487
611
|
})[],
|
|
488
612
|
restrictedStaticAttributes?: (string | {
|
|
489
|
-
key: string,
|
|
490
|
-
value?: string | true,
|
|
491
613
|
element: string,
|
|
614
|
+
key: string,
|
|
492
615
|
message: string,
|
|
616
|
+
value: true | string,
|
|
493
617
|
})[],
|
|
494
|
-
|
|
495
|
-
overrides?:
|
|
496
|
-
},
|
|
497
|
-
nuxt?: boolean | {
|
|
498
|
-
image?: boolean,
|
|
499
|
-
icon?: boolean | {
|
|
500
|
-
component?: string,
|
|
501
|
-
}
|
|
502
|
-
ui?: boolean | {
|
|
503
|
-
prefix?: string,
|
|
504
|
-
}
|
|
618
|
+
vForDelimiterStyle?: 'in' | 'of',
|
|
619
|
+
overrides?: Overrides,
|
|
505
620
|
},
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
},
|
|
510
|
-
vitest?: boolean | {
|
|
511
|
-
overrides?: {},
|
|
512
|
-
},
|
|
513
|
-
playwright?: boolean | {
|
|
514
|
-
overrides?: {},
|
|
515
|
-
},
|
|
516
|
-
cypress?: boolean | {
|
|
517
|
-
overrides?: {},
|
|
518
|
-
},
|
|
519
|
-
testFunction?: 'test' | 'it',
|
|
520
|
-
maxNestedDescribe?: number,
|
|
621
|
+
zod?: boolean | {
|
|
622
|
+
mini?: boolean,
|
|
623
|
+
overrides?: Overrides,
|
|
521
624
|
},
|
|
522
625
|
},
|
|
523
626
|
}
|
|
524
627
|
```
|
|
628
|
+
<!-- END_AUTO-GENERATED_API_REFERENCE -->
|
|
525
629
|
</details>
|
|
526
630
|
|
|
527
631
|
## Versioning Policy
|
|
528
|
-
This project adheres to [The Semantic Versioning Standard]
|
|
529
|
-
-
|
|
632
|
+
This project adheres to [The Semantic Versioning Standard][semver]. However, to facilitate rapid development and fast iteration, **the following changes are considered non-breaking**:
|
|
633
|
+
- Updates to dependency versions
|
|
530
634
|
- Modifications to rule options
|
|
531
635
|
- Enabling or disabling rules and plugins
|
|
532
636
|
|
|
533
637
|
Under this policy, minor updates may introduce new linting errors, which could break your project's build pipeline. To prevent this, it's recommended to use an exact version. Alternatively, you can use a tilde (`~`) version range in your _package.json_ file (e.g., `"@shayanthenerd/eslint-config": "~1.2.3"`), which will restrict updates to patches only, ensuring your project's build pipeline remains stable.
|
|
534
638
|
|
|
535
|
-
You can find a list of all available versions and their changelogs on the [releases page]
|
|
639
|
+
You can find a list of all available versions and their changelogs on the [releases page][releases].
|
|
536
640
|
|
|
537
641
|
## Roadmap to v1.0.0
|
|
538
|
-
- [ ]
|
|
539
|
-
- [ ] Add support for other
|
|
540
|
-
- [ ] Develop
|
|
642
|
+
- [ ] Add integration for ESLint plugins such as [eslint-plugin-n][plugin-node], [eslint-plugin-unicorn][plugin-unicorn], and more.
|
|
643
|
+
- [ ] Add support for other React, Next, Astro, and Markdown.
|
|
644
|
+
- [ ] Develop an interactive starter wizard to quickly scaffold the configurations for ESLint, Prettier, etc.
|
|
541
645
|
|
|
542
646
|
## Contribution Guide
|
|
543
|
-
|
|
647
|
+
Contributions of all kinds are welcome. Please check out the [CONTRIBUTING.md][contributing] file.
|
|
544
648
|
|
|
545
649
|
## Credits
|
|
546
|
-
This project was inspired by the work of [Anthony Fu]
|
|
650
|
+
This project was inspired by the work of [Anthony Fu][antfu], whose generous contributions to the JavaScript and the ESLint ecosystem were instrumental in making it possible.
|
|
547
651
|
|
|
548
652
|
## License
|
|
549
|
-
[MIT]
|
|
653
|
+
[MIT][license] License © 2025-PRESENT — [Shayan Zamani][ShayanTheNerd]
|
|
654
|
+
|
|
655
|
+
<!-- Badges -->
|
|
656
|
+
[jsr]: https://jsr.io/badges/@shayanthenerd/eslint-config
|
|
657
|
+
[jsr-version-badge]: https://jsr.io/badges/@shayanthenerd/eslint-config?logoColor=FEFEFE&labelColor=3B82F6&color=3B82F6
|
|
658
|
+
[license]: ./LICENSE
|
|
659
|
+
[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg?logoColor=FEFEFE&labelColor=3B82F6&color=3B82F6
|
|
660
|
+
[npm-version-badge]: https://img.shields.io/npm/v/@shayanthenerd/eslint-config?label=&logo=npm&logoColor=FEFEFE&labelColor=3B82F6&color=3B82F6
|
|
661
|
+
[npmx]: https://www.npmjs.com/package/@shayanthenerd/eslint-config
|
|
662
|
+
|
|
663
|
+
<!-- Editor Extensions -->
|
|
664
|
+
[extension-eslint]: https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
|
|
665
|
+
[extension-prettier]: https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
|
|
666
|
+
[extension-tailwind]: https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss
|
|
667
|
+
|
|
668
|
+
<!-- ESLint Plugins -->
|
|
669
|
+
[plugin-astro]: https://ota-meshi.github.io/eslint-plugin-astro
|
|
670
|
+
[plugin-css]: https://github.com/eslint/css
|
|
671
|
+
[plugin-cypress]: https://github.com/cypress-io/eslint-plugin-cypress
|
|
672
|
+
[plugin-html]: https://html-eslint.org
|
|
673
|
+
[plugin-import-x]: https://github.com/un-ts/eslint-plugin-import-x
|
|
674
|
+
[plugin-jsx-a11y]: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
|
|
675
|
+
[plugin-md]: https://github.com/eslint/markdown
|
|
676
|
+
[plugin-next]: https://nextjs.org/docs/app/api-reference/config/eslint#eslint-plugin
|
|
677
|
+
[plugin-node]: https://github.com/eslint-community/eslint-plugin-n
|
|
678
|
+
[plugin-package-json]: https://github.com/JoshuaKGoldberg/eslint-plugin-package-json
|
|
679
|
+
[plugin-perfectionist]: https://perfectionist.dev
|
|
680
|
+
[plugin-playwright]: https://github.com/mskelton/eslint-plugin-playwright
|
|
681
|
+
[plugin-promise]: https://github.com/eslint-community/eslint-plugin-promise
|
|
682
|
+
[plugin-react]: https://eslint-react.xyz
|
|
683
|
+
[plugin-react-hooks]: https://react.dev/reference/eslint-plugin-react-hooks
|
|
684
|
+
[plugin-storybook]: https://storybook.js.org/docs/configure/integration/eslint-plugin
|
|
685
|
+
[plugin-stylistic]: https://eslint.style
|
|
686
|
+
[plugin-tailwind]: https://github.com/schoero/eslint-plugin-better-tailwindcss
|
|
687
|
+
[plugin-ts]: https://typescript-eslint.io
|
|
688
|
+
[plugin-unicorn]: https://github.com/sindresorhus/eslint-plugin-unicorn
|
|
689
|
+
[plugin-vitest]: https://github.com/vitest-dev/eslint-plugin-vitest
|
|
690
|
+
[plugin-vue]: https://eslint.vuejs.org
|
|
691
|
+
[plugin-vue-a11y]: https://vue-a11y.github.io/eslint-plugin-vuejs-accessibility
|
|
692
|
+
[plugin-zod]: https://github.com/marcalexiei/eslint-zod
|
|
693
|
+
|
|
694
|
+
<!-- References -->
|
|
695
|
+
[antfu]: https://github.com/antfu
|
|
696
|
+
[contributing]: ./.github/CONTRIBUTING.md
|
|
697
|
+
[eslint]: https://eslint.org
|
|
698
|
+
[online-preview]: https://eslintconfig.netlify.app
|
|
699
|
+
[eslint-config-ts-setup]: https://eslint.org/docs/latest/use/configure/configuration-files#typescript-configuration-files
|
|
700
|
+
[eslint-nuxt]: https://eslint.nuxt.com
|
|
701
|
+
[local-pkg]: https://github.com/antfu-collective/local-pkg
|
|
702
|
+
[prettier-shared-config]: https://prettier.io/docs/sharing-configurations
|
|
703
|
+
[releases]: https://github.com/ShayanTheNerd/eslint-config/releases
|
|
704
|
+
[semver]: https://semver.org
|
|
705
|
+
[ShayanTheNerd]: https://github.com/ShayanTheNerd
|