@shayanthenerd/eslint-config 0.1.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/LICENSE +21 -0
- package/README.md +496 -0
- package/dist/_virtual/rolldown_runtime.cjs +30 -0
- package/dist/configs/base.cjs +44 -0
- package/dist/configs/base.js +43 -0
- package/dist/configs/commons.cjs +26 -0
- package/dist/configs/commons.js +25 -0
- package/dist/configs/css.cjs +29 -0
- package/dist/configs/css.js +28 -0
- package/dist/configs/cypress.cjs +23 -0
- package/dist/configs/cypress.js +22 -0
- package/dist/configs/html.cjs +23 -0
- package/dist/configs/html.js +22 -0
- package/dist/configs/importX.cjs +26 -0
- package/dist/configs/importX.js +25 -0
- package/dist/configs/nuxtMultiRootTemplate.cjs +14 -0
- package/dist/configs/nuxtMultiRootTemplate.js +14 -0
- package/dist/configs/oxlintOverrides.cjs +49 -0
- package/dist/configs/oxlintOverrides.js +48 -0
- package/dist/configs/perfectionist.cjs +24 -0
- package/dist/configs/perfectionist.js +23 -0
- package/dist/configs/playwright.cjs +23 -0
- package/dist/configs/playwright.js +22 -0
- package/dist/configs/storybook.cjs +24 -0
- package/dist/configs/storybook.js +23 -0
- package/dist/configs/stylistic.cjs +23 -0
- package/dist/configs/stylistic.js +22 -0
- package/dist/configs/tailwind.cjs +43 -0
- package/dist/configs/tailwind.js +42 -0
- package/dist/configs/typescript.cjs +31 -0
- package/dist/configs/typescript.js +30 -0
- package/dist/configs/vitest.cjs +23 -0
- package/dist/configs/vitest.js +22 -0
- package/dist/configs/vue.cjs +35 -0
- package/dist/configs/vue.js +34 -0
- package/dist/configs/vueComponentNames.cjs +19 -0
- package/dist/configs/vueComponentNames.js +19 -0
- package/dist/index.cjs +55 -0
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +54 -0
- package/dist/oxlint.config.jsonc +192 -0
- package/dist/prettier.config.js +42 -0
- package/dist/rules/css.cjs +65 -0
- package/dist/rules/css.js +65 -0
- package/dist/rules/cypress.cjs +16 -0
- package/dist/rules/cypress.js +15 -0
- package/dist/rules/html.cjs +53 -0
- package/dist/rules/html.js +53 -0
- package/dist/rules/importX.cjs +51 -0
- package/dist/rules/importX.js +50 -0
- package/dist/rules/javascript.cjs +164 -0
- package/dist/rules/javascript.js +163 -0
- package/dist/rules/perfectionist.cjs +73 -0
- package/dist/rules/perfectionist.js +73 -0
- package/dist/rules/playwright.cjs +28 -0
- package/dist/rules/playwright.js +27 -0
- package/dist/rules/storybook.cjs +16 -0
- package/dist/rules/storybook.js +15 -0
- package/dist/rules/stylistic.cjs +160 -0
- package/dist/rules/stylistic.js +160 -0
- package/dist/rules/tailwind.cjs +36 -0
- package/dist/rules/tailwind.js +36 -0
- package/dist/rules/typescript.cjs +62 -0
- package/dist/rules/typescript.js +62 -0
- package/dist/rules/vitest.cjs +47 -0
- package/dist/rules/vitest.js +46 -0
- package/dist/rules/vue.cjs +169 -0
- package/dist/rules/vue.js +169 -0
- package/dist/rules/vueAccessibility.cjs +23 -0
- package/dist/rules/vueAccessibility.js +23 -0
- package/dist/types/configOptions/base.d.cts +47 -0
- package/dist/types/configOptions/base.d.ts +47 -0
- package/dist/types/configOptions/css.d.cts +27 -0
- package/dist/types/configOptions/css.d.ts +27 -0
- package/dist/types/configOptions/html.d.cts +27 -0
- package/dist/types/configOptions/html.d.ts +27 -0
- package/dist/types/configOptions/importX.d.cts +20 -0
- package/dist/types/configOptions/importX.d.ts +20 -0
- package/dist/types/configOptions/nuxt.d.cts +42 -0
- package/dist/types/configOptions/nuxt.d.ts +42 -0
- package/dist/types/configOptions/perfectionist.d.cts +16 -0
- package/dist/types/configOptions/perfectionist.d.ts +16 -0
- package/dist/types/configOptions/stylistic.d.cts +145 -0
- package/dist/types/configOptions/stylistic.d.ts +145 -0
- package/dist/types/configOptions/tailwind.d.cts +46 -0
- package/dist/types/configOptions/tailwind.d.ts +46 -0
- package/dist/types/configOptions/test.d.cts +55 -0
- package/dist/types/configOptions/test.d.ts +55 -0
- package/dist/types/configOptions/typescript.d.cts +36 -0
- package/dist/types/configOptions/typescript.d.ts +36 -0
- package/dist/types/configOptions/vue.d.cts +211 -0
- package/dist/types/configOptions/vue.d.ts +211 -0
- package/dist/types/configOptions/vueAccessibility.d.cts +34 -0
- package/dist/types/configOptions/vueAccessibility.d.ts +34 -0
- package/dist/types/eslint-schema.d.cts +13258 -0
- package/dist/types/eslint-schema.d.ts +13258 -0
- package/dist/types/eslintRules.d.cts +12 -0
- package/dist/types/eslintRules.d.ts +12 -0
- package/dist/types/helpers.d.cts +5 -0
- package/dist/types/helpers.d.ts +5 -0
- package/dist/types/index.d.cts +360 -0
- package/dist/types/index.d.ts +360 -0
- package/dist/utils/globs.cjs +31 -0
- package/dist/utils/globs.js +30 -0
- package/dist/utils/ignores/defaultIgnorePatterns.cjs +58 -0
- package/dist/utils/ignores/defaultIgnorePatterns.js +57 -0
- package/dist/utils/ignores/getIgnorePatterns.cjs +16 -0
- package/dist/utils/ignores/getIgnorePatterns.js +16 -0
- package/dist/utils/ignores/resolveGitignorePatterns.cjs +27 -0
- package/dist/utils/ignores/resolveGitignorePatterns.js +26 -0
- package/dist/utils/isEmptyString.cjs +8 -0
- package/dist/utils/isEmptyString.js +7 -0
- package/dist/utils/isEnabled.cjs +8 -0
- package/dist/utils/isEnabled.js +7 -0
- package/dist/utils/isPackageDetected.cjs +22 -0
- package/dist/utils/isPackageDetected.js +20 -0
- package/dist/utils/options/defaultOptions.cjs +168 -0
- package/dist/utils/options/defaultOptions.js +167 -0
- package/dist/utils/options/enableDetectedConfigs.cjs +36 -0
- package/dist/utils/options/enableDetectedConfigs.js +36 -0
- package/dist/utils/options/mergeWithDefaults.cjs +22 -0
- package/dist/utils/options/mergeWithDefaults.js +21 -0
- package/dist/utils/vue/getRestrictedVueElements.cjs +28 -0
- package/dist/utils/vue/getRestrictedVueElements.js +27 -0
- package/dist/utils/vue/getRestrictedVueInputs.cjs +24 -0
- package/dist/utils/vue/getRestrictedVueInputs.js +23 -0
- package/package.json +130 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Shayan Zamani
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
# @shayanthenerd/eslint-config [](https://www.npmjs.com/package/@shayanthenerd/eslint-config) [](https://jsr.io/@shayanthenerd/eslint-config) [](https://github.com/ShayanTheNerd/eslint-config/blob/main/LICENSE)
|
|
2
|
+
|
|
3
|
+
A modern, flexible ESLint configuration for enforcing best practices and maintaining a consistent coding style.
|
|
4
|
+
|
|
5
|
+
- **Performant**: Powered by [OXLint](https://oxc.rs/docs/guide/usage/linter) for rapid linting
|
|
6
|
+
- **Flat Config**: Type-safe [ESLint Flat Config](https://eslint.org/docs/latest/use/configure/configuration-files) with `extends` and `overrides` support
|
|
7
|
+
- **Comprehensive**: Dependency detection with support for TypeScript, Vue & Nuxt, Tailwind, Storybook, Vitest & Playwright, and more
|
|
8
|
+
- **Automatic Formatting**: Fine-grained control over formatting with [ESLint Stylistic](https://eslint.style), eliminating the need for Prettier
|
|
9
|
+
- **Smart Defaults**: Respects your _.gitignore_ file and provides reasonable, opinionated, yet [highly customizable](#customization) defaults
|
|
10
|
+
- **Developer-friendly**: Easy to use and well-documented with JSDoc
|
|
11
|
+
- **Modern**: Requires Node.js v20.12.0+ and ESLint v9.28.0+
|
|
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.
|
|
15
|
+
|
|
16
|
+
## Table of Contents
|
|
17
|
+
- [Installation and Configuration](#installation-and-configuration)
|
|
18
|
+
- [Automatic Dependency Detection](#automatic-dependency-detection)
|
|
19
|
+
- [Formatting](#formatting)
|
|
20
|
+
- [VS Code Integration](#vs-code-integration)
|
|
21
|
+
- [Customization](#customization)
|
|
22
|
+
- [OXLint](#oxlint)
|
|
23
|
+
- [ESLint](#eslint)
|
|
24
|
+
- [API Reference](#api-reference)
|
|
25
|
+
- [Versioning Policy](#versioning-policy)
|
|
26
|
+
- [Roadmap to v1.0.0](#roadmap-to-v100)
|
|
27
|
+
- [Contribution Guide](#contribution-guide)
|
|
28
|
+
- [Credits](#credits)
|
|
29
|
+
- [License](#license)
|
|
30
|
+
|
|
31
|
+
## Installation and Configuration
|
|
32
|
+
1. Install the package:
|
|
33
|
+
```shell
|
|
34
|
+
npm i -D @shayanthenerd/eslint-config
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
OXLint and all necessary ESLint plugins and parsers will be installed automatically, so you don't need to install them separately.
|
|
38
|
+
|
|
39
|
+
If you're using TypeScript and see [eslint-plugin-import-x](https://github.com/un-ts/eslint-plugin-import-x) fail to resolve imports, you should also install [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) as a dev dependency.
|
|
40
|
+
|
|
41
|
+
2. Create an ESLint config file (_eslint.config.js_) at the root of your project:
|
|
42
|
+
```js
|
|
43
|
+
import { defineConfig } from '@shayanthenerd/eslint-config';
|
|
44
|
+
|
|
45
|
+
export default defineConfig();
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
You can also use a TypeScript file (_eslint.config.ts_) for your ESLint configuration. Depending on your Node.js version, [additional setup](https://eslint.org/docs/latest/use/configure/configuration-files#typescript-configuration-files) may be required.
|
|
49
|
+
|
|
50
|
+
3. Create an OXLint config file (_.oxlintrc.json_) in the root of your project:
|
|
51
|
+
```jsonc
|
|
52
|
+
{
|
|
53
|
+
"$schema": "./node_modules/oxlint/configuration_schema.json", // Optional
|
|
54
|
+
|
|
55
|
+
"extends": ["./node_modules/@shayanthenerd/eslint-config/dist/oxlint.config.jsonc"],
|
|
56
|
+
|
|
57
|
+
/* Customize based on your development environment. */
|
|
58
|
+
"env": {
|
|
59
|
+
"builtin": true,
|
|
60
|
+
"es2026": true,
|
|
61
|
+
"commonjs": false,
|
|
62
|
+
"node": true,
|
|
63
|
+
"browser": true,
|
|
64
|
+
"worker": true,
|
|
65
|
+
"serviceworker": false,
|
|
66
|
+
"webextensions": false
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
"categories": {
|
|
70
|
+
"correctness": "error",
|
|
71
|
+
"suspicious": "error",
|
|
72
|
+
"restriction": "error",
|
|
73
|
+
"pedantic": "error",
|
|
74
|
+
"perf": "warn",
|
|
75
|
+
"style": "warn",
|
|
76
|
+
"nursery": "error"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Due to [the limitation of OXLint](https://oxc.rs/docs/guide/usage/linter/nested-config#extending-configuration-files), only `rules`, `plugins`, and `overrides` can be extended. Check out [OXLint config reference](https://oxc.rs/docs/guide/usage/linter/config-file-reference) for more details.
|
|
82
|
+
|
|
83
|
+
4. Add the following scripts to your _package.json_ file:
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"scripts": {
|
|
87
|
+
"lint:inspect": "npx @eslint/config-inspector",
|
|
88
|
+
"lint:oxlint": "oxlint --fix",
|
|
89
|
+
"lint:eslint": "eslint --fix --cache --cache-location='node_modules/.cache/.eslintcache'",
|
|
90
|
+
"lint": "npm run lint:oxlint && npm run lint:eslint"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
That's it! You can now run OXLint and ESLint in your project:
|
|
98
|
+
```shell
|
|
99
|
+
npm run lint
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
To get a visual breakdown of your configuration, run:
|
|
103
|
+
```shell
|
|
104
|
+
npm run lint:inspect
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Automatic Dependency Detection
|
|
108
|
+
By default, this config automatically detects dependencies in your project, and enables the appropriate ESLint configurations. This is powered by [local-pkg](https://github.com/antfu-collective/local-pkg), which scans your _node_modules_ directory instead of _package.json_. <br />
|
|
109
|
+
For instance, if you install a package "A" that depends on another package "B", your package manager will install both. Even if "B" isn't listed in your _package.json_ file, it will be present in _node_modules_. Consequently, this config will detect both "A" and "B" and enable the appropriate ESLint configurations for them. <br />
|
|
110
|
+
To opt out of this behavior, you can either set `autoDetectDeps: false` in the options object or explicitly disable any unwanted configurations that were automatically enabled.
|
|
111
|
+
|
|
112
|
+
Unlike other plugins, the configurations for Tailwind aren't automatically enabled upon dependency detection. This is because you must explicitly provide the path to your Tailwind config file or entry point.
|
|
113
|
+
|
|
114
|
+
Stylistic, Perfectionist, ImportX, and core (JavaScript) rules are enabled by default.
|
|
115
|
+
|
|
116
|
+
## Formatting
|
|
117
|
+
This config uses [ESLint Stylistic](https://eslint.style) to format JavaScript and TypeScript files (`?([mc])[jt]s?(x)`) as well as the `<script>` blocks in Vue components. HTML and the `<template>` blocks in Vue components are formatted with [html-eslint](https://html-eslint.org) and [eslint-plugin-vue](https://eslint.vuejs.org), respectively. For other files such as CSS, JSON, and Markdown, you'll need Prettier. To make this easier, a customizable [shared Prettier configuration](https://prettier.io/docs/sharing-configurations) is provided. Here's how to set it up:
|
|
118
|
+
|
|
119
|
+
1. Install Prettier:
|
|
120
|
+
```shell
|
|
121
|
+
npm i -D prettier
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
2. Create a Prettier config file (_prettier.config.js_) in the root of your project:
|
|
125
|
+
```js
|
|
126
|
+
import prettierConfig from '@shayanthenerd/eslint-config/prettier.config.js';
|
|
127
|
+
|
|
128
|
+
/** @type {import('prettier').Config} */
|
|
129
|
+
export default {
|
|
130
|
+
...prettierConfig,
|
|
131
|
+
semi: false, // Override the `semi` option from the shared config
|
|
132
|
+
};
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
3. To prevent conflicts with ESLint, Prettier should be configured to only format files other than JavaScript, TypeScript, HTML, and Vue. Hence, add the following script to your _package.json_ file:
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"scripts": {
|
|
139
|
+
"format": "prettier --write . '!**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,html,vue}' --cache"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
For IDE setup guidance, refer to [VS Code Integration](#vs-code-integration).
|
|
145
|
+
|
|
146
|
+
## VS Code Integration
|
|
147
|
+
Install VS Code extensions for [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint), [OXLint](https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode), and [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode). Then, add the following in the _.vscode/settings.json_ file of your project:
|
|
148
|
+
```jsonc
|
|
149
|
+
{
|
|
150
|
+
/* Enforce Unix-like line endings (LF). */
|
|
151
|
+
"files.eol": "\n",
|
|
152
|
+
|
|
153
|
+
/* Enforce either tabs or spaces for indentation. */
|
|
154
|
+
"editor.tabSize": 2,
|
|
155
|
+
"editor.insertSpaces": false,
|
|
156
|
+
"editor.detectIndentation": false,
|
|
157
|
+
|
|
158
|
+
"editor.codeActionsOnSave": {
|
|
159
|
+
/* Imports are sorted and organized with eslint-plugin-perfectionist. */
|
|
160
|
+
"source.sortImports": "never",
|
|
161
|
+
"source.organizeImports": "never",
|
|
162
|
+
|
|
163
|
+
/* Apply OXLint and ESLint automatic fixes on file save. */
|
|
164
|
+
"source.fixAll.oxc": "explicit",
|
|
165
|
+
"source.fixAll.eslint": "explicit"
|
|
166
|
+
},
|
|
167
|
+
"eslint.run": "onSave",
|
|
168
|
+
"oxc.lint.run": "onSave",
|
|
169
|
+
"editor.formatOnSave": true,
|
|
170
|
+
|
|
171
|
+
/* Format and lint JavaScript, TypeScript, HTML, and Vue files with ESLint, while everything else is formatted with Prettier. */
|
|
172
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
173
|
+
"[javascript][typescript][javascriptreact][typescriptreact][html][vue]": {
|
|
174
|
+
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
|
175
|
+
},
|
|
176
|
+
"eslint.validate": [
|
|
177
|
+
"javascript",
|
|
178
|
+
"typescript",
|
|
179
|
+
"javascriptreact",
|
|
180
|
+
"typescriptreact",
|
|
181
|
+
"html",
|
|
182
|
+
"css",
|
|
183
|
+
"tailwindcss",
|
|
184
|
+
"vue"
|
|
185
|
+
],
|
|
186
|
+
|
|
187
|
+
/* Adjust these based on the features you're using to silently auto-fix the stylistic rules in your IDE. */
|
|
188
|
+
"tailwindCSS.lint.cssConflict": "ignore", // Only if you're using the Tailwind config
|
|
189
|
+
"eslint.rules.customizations": [
|
|
190
|
+
{ "rule": "*styl*", "severity": "off", "fixable": true },
|
|
191
|
+
{ "rule": "*sort*", "severity": "off", "fixable": true },
|
|
192
|
+
{ "rule": "*indent", "severity": "off", "fixable": true },
|
|
193
|
+
{ "rule": "*quotes", "severity": "off", "fixable": true },
|
|
194
|
+
{ "rule": "import*", "severity": "off", "fixable": true },
|
|
195
|
+
{ "rule": "*-spac*", "severity": "off", "fixable": true },
|
|
196
|
+
{ "rule": "*order-*", "severity": "off", "fixable": true },
|
|
197
|
+
{ "rule": "*newline*", "severity": "off", "fixable": true },
|
|
198
|
+
{ "rule": "*attribute*", "severity": "off", "fixable": true },
|
|
199
|
+
{ "rule": "vue/max-len", "severity": "off", "fixable": true },
|
|
200
|
+
{ "rule": "vue/comma-dangle", "severity": "off", "fixable": true },
|
|
201
|
+
{ "rule": "vue/space-in-parens", "severity": "off", "fixable": true },
|
|
202
|
+
{ "rule": "better-tailwindcss/*", "severity": "off", "fixable": true },
|
|
203
|
+
{ "rule": "better-tailwindcss/no-restricted-classes", "severity": "error", "fixable": true },
|
|
204
|
+
{ "rule": "better-tailwindcss/no-conflicting-classes", "severity": "error", "fixable": false },
|
|
205
|
+
{ "rule": "better-tailwindcss/no-unregistered-classes", "severity": "error", "fixable": false }
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Customization
|
|
211
|
+
### OXLint
|
|
212
|
+
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:
|
|
213
|
+
```jsonc
|
|
214
|
+
{
|
|
215
|
+
/* Base configuration */
|
|
216
|
+
|
|
217
|
+
"rules": {
|
|
218
|
+
/* Globally override rules. */
|
|
219
|
+
"oxlint/no-named-as-default-member": "warn"
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
"overrides": [
|
|
223
|
+
/* Override rules for specific files. */
|
|
224
|
+
{
|
|
225
|
+
"files": ["app/**/*.tsx"],
|
|
226
|
+
"ignores": ["app/app.tsx"],
|
|
227
|
+
"rules": {
|
|
228
|
+
"oxlint/max-depth": ["error", { "max": 5 }],
|
|
229
|
+
"oxlint/explicit-function-return-type": "off"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
],
|
|
233
|
+
|
|
234
|
+
/* OXLint respects the ignore patterns defined in `.gitignore` and `.eslintignore` files by default. */
|
|
235
|
+
"ignorePatterns": ["**/*.min.*", "**/oxlint-schema.d.ts"]
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### ESLint
|
|
240
|
+
|
|
241
|
+
`defineConfig` takes the `options` object as the first argument. `options` is thoroughly documented with JSDoc, and provides many options for rule customizations. In addition, each config object in `options.configs` accepts an `overrides` option:
|
|
242
|
+
```ts
|
|
243
|
+
interface overrides {
|
|
244
|
+
name: '',
|
|
245
|
+
files: [],
|
|
246
|
+
ignores: [],
|
|
247
|
+
plugins: {},
|
|
248
|
+
settings: {},
|
|
249
|
+
languageOptions: {
|
|
250
|
+
parser: {},
|
|
251
|
+
globals: {},
|
|
252
|
+
},
|
|
253
|
+
rules: {},
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
`overrides` is merged with the default config, taking precedence over its properties. However, there is no guarantee that the resulting configuration works correctly — it depends on the options you provide.
|
|
258
|
+
|
|
259
|
+
`defineConfig` also accepts any number of custom ESLint Flat Configs (_eslint.config.js_):
|
|
260
|
+
```js
|
|
261
|
+
import eslintPluginYaml from 'eslint-plugin-yaml';
|
|
262
|
+
import * as eslintPluginRegexp from 'eslint-plugin-regexp';
|
|
263
|
+
import { defineConfig } from '@shayanthenerd/eslint-config';
|
|
264
|
+
|
|
265
|
+
export default defineConfig(
|
|
266
|
+
/* The options object: */
|
|
267
|
+
{
|
|
268
|
+
env: 'bun',
|
|
269
|
+
configs: {
|
|
270
|
+
typescript: {
|
|
271
|
+
typeDefinitionStyle: 'type',
|
|
272
|
+
overrides: {
|
|
273
|
+
rules: {
|
|
274
|
+
'@typescript-eslint/no-unsafe-type-assertion': 'off',
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
|
|
281
|
+
/* ESLint Flat Configs: */
|
|
282
|
+
{
|
|
283
|
+
files: ['**/*.yaml', '**/*.yml'],
|
|
284
|
+
ignores: ['**/*.schema.yaml', '**/*.schema.yml'],
|
|
285
|
+
extends: [pluginYaml.configs.recommended],
|
|
286
|
+
},
|
|
287
|
+
regexpPlugin.configs['flat/recommended'],
|
|
288
|
+
);
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## API Reference
|
|
292
|
+
<details>
|
|
293
|
+
<summary>The API reference</summary>
|
|
294
|
+
Some types are omitted or aliased for brevity.
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
interface options {
|
|
298
|
+
autoDetectDeps?: boolean | 'verbose',
|
|
299
|
+
gitignore?: false | string,
|
|
300
|
+
packageDir?: string,
|
|
301
|
+
env?: 'bun' | 'node',
|
|
302
|
+
tsConfig?: {
|
|
303
|
+
rootDir: string,
|
|
304
|
+
filename?: string,
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
global?: {
|
|
308
|
+
name?: string,
|
|
309
|
+
basePath?: string,
|
|
310
|
+
ignores?: string[],
|
|
311
|
+
globals?: {
|
|
312
|
+
node?: boolean,
|
|
313
|
+
commonjs?: boolean,
|
|
314
|
+
browser?: boolean,
|
|
315
|
+
worker?: boolean,
|
|
316
|
+
serviceworker?: boolean,
|
|
317
|
+
webextension?: boolean,
|
|
318
|
+
custom?: {
|
|
319
|
+
[key: string]: boolean | 'off' | 'readonly' | 'readable' | 'writable' | 'writeable',
|
|
320
|
+
},
|
|
321
|
+
}
|
|
322
|
+
linterOptions?: {
|
|
323
|
+
noInlineConfig?: boolean,
|
|
324
|
+
reportUnusedInlineConfigs?: 'error' | 'off' | 'warn',
|
|
325
|
+
reportUnusedDisableDirectives?: 'error' | 'off' | 'warn',
|
|
326
|
+
},
|
|
327
|
+
settings?: {
|
|
328
|
+
[name: string]: unknown,
|
|
329
|
+
}
|
|
330
|
+
rules?: Linter.RulesRecord,
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
configs?: {
|
|
334
|
+
oxlint?: false | string,
|
|
335
|
+
base?: {
|
|
336
|
+
maxDepth?: number,
|
|
337
|
+
maxNestedCallbacks?: number,
|
|
338
|
+
preferNamedExports?: boolean,
|
|
339
|
+
functionStyle?: 'declaration' | 'expression',
|
|
340
|
+
overrides?: {},
|
|
341
|
+
},
|
|
342
|
+
stylistic?: boolean | {
|
|
343
|
+
semi?: 'always' | 'never',
|
|
344
|
+
trailingComma?: 'always' | 'never' | 'always-multiline' | 'only-multiline',
|
|
345
|
+
memberDelimiterStyle?: 'semi' | 'comma',
|
|
346
|
+
quotes?: 'single' | 'double' | 'backtick',
|
|
347
|
+
jsxQuotes?: 'prefer-single' | 'prefer-double',
|
|
348
|
+
arrowParens?: 'always' | 'as-needed',
|
|
349
|
+
useTabs?: boolean,
|
|
350
|
+
indent?: number,
|
|
351
|
+
maxConsecutiveEmptyLines?: number,
|
|
352
|
+
maxLineLength?: number,
|
|
353
|
+
maxAttributesPerLine?: number,
|
|
354
|
+
selfCloseVoidHTMLElements?: 'never' | 'always',
|
|
355
|
+
overrides?: {},
|
|
356
|
+
},
|
|
357
|
+
html?: boolean | {
|
|
358
|
+
useBaseline?: number | false | 'widely' | 'newly',
|
|
359
|
+
idNamingConvention?: 'camelCase' | 'snake_case' | 'PascalCase' | 'kebab-case',
|
|
360
|
+
overrides?: {},
|
|
361
|
+
},
|
|
362
|
+
css?: boolean | {
|
|
363
|
+
useBaseline?: number | false | 'widely' | 'newly',
|
|
364
|
+
allowedRelativeFontUnits?: ('%' | 'cap' | 'ch' | 'em' | 'ex' | 'ic' | 'lh' | 'rcap' | 'rch' | 'rem' | 'rex' | 'ric' | 'rlh')[],
|
|
365
|
+
overrides?: {},
|
|
366
|
+
},
|
|
367
|
+
tailwind?: false | {
|
|
368
|
+
config: string,
|
|
369
|
+
entryPoint?: string,
|
|
370
|
+
multilineSort?: boolean,
|
|
371
|
+
ignoredUnregisteredClasses?: string[],
|
|
372
|
+
overrides?: {},
|
|
373
|
+
} | {
|
|
374
|
+
config?: string,
|
|
375
|
+
entryPoint: string,
|
|
376
|
+
multilineSort?: boolean,
|
|
377
|
+
ignoredUnregisteredClasses?: string[],
|
|
378
|
+
overrides?: {},
|
|
379
|
+
},
|
|
380
|
+
typescript?: boolean | {
|
|
381
|
+
allowedDefaultProjects?: string[],
|
|
382
|
+
methodSignatureStyle?: 'property' | 'method',
|
|
383
|
+
typeDefinitionStyle?: 'interface' | 'type',
|
|
384
|
+
overrides?: {},
|
|
385
|
+
},
|
|
386
|
+
importX?: boolean | {
|
|
387
|
+
requireFileExtension?: 'always' | 'never',
|
|
388
|
+
overrides?: {},
|
|
389
|
+
},
|
|
390
|
+
perfectionist?: boolean | {
|
|
391
|
+
sortType?: 'custom' | 'natural' | 'alphabetical' | 'line-length' | 'unsorted',
|
|
392
|
+
overrides?: {},
|
|
393
|
+
},
|
|
394
|
+
vue?: boolean | {
|
|
395
|
+
accessibility?: boolean | {
|
|
396
|
+
anchorComponents?: string[],
|
|
397
|
+
imageComponents?: string[],
|
|
398
|
+
accessibleChildComponents?: string[],
|
|
399
|
+
},
|
|
400
|
+
blockOrder?: (
|
|
401
|
+
| 'docs'
|
|
402
|
+
| 'template'
|
|
403
|
+
| 'script[setup]'
|
|
404
|
+
| 'style[scoped]'
|
|
405
|
+
| 'i18n[locale=en]'
|
|
406
|
+
| 'script:not([setup])'
|
|
407
|
+
| 'style:not([scoped])'
|
|
408
|
+
| 'i18n:not([locale=en])'
|
|
409
|
+
)[],
|
|
410
|
+
macrosOrder?: (
|
|
411
|
+
| 'definePage'
|
|
412
|
+
| 'defineModel'
|
|
413
|
+
| 'defineProps'
|
|
414
|
+
| 'defineEmits'
|
|
415
|
+
| 'defineSlots'
|
|
416
|
+
| 'defineCustom'
|
|
417
|
+
| 'defineExpose'
|
|
418
|
+
| 'defineOptions'
|
|
419
|
+
)[],
|
|
420
|
+
attributesOrder?: RuleOptions<'vue/attributes-order'>['order'],
|
|
421
|
+
attributeHyphenation?: 'never' | 'always',
|
|
422
|
+
preferVBindSameNameShorthand?: 'never' | 'always',
|
|
423
|
+
preferVBindTrueShorthand?: 'never' | 'always',
|
|
424
|
+
allowedStyleAttributes?: ['module' | 'plain' | 'scoped', 'module' | 'plain' | 'scoped'],
|
|
425
|
+
blockLang?: {
|
|
426
|
+
style?: 'css' | 'implicit' | 'scss' | 'postcss',
|
|
427
|
+
script?: 'js' | 'ts' | 'jsx' | 'tsx' | 'implicit',
|
|
428
|
+
},
|
|
429
|
+
destructureProps?: 'never' | 'always',
|
|
430
|
+
componentNameCaseInTemplate?: 'PascalCase' | 'kebab-case',
|
|
431
|
+
vForDelimiterStyle?: 'in' | 'of',
|
|
432
|
+
vOnHandlerStyle?: 'inline' | 'inline-function' | ['method', 'inline' | 'inline-function'],
|
|
433
|
+
restrictedElements?: (string | {
|
|
434
|
+
element: string | string[],
|
|
435
|
+
message: string,
|
|
436
|
+
})[],
|
|
437
|
+
restrictedStaticAttributes?: (string | {
|
|
438
|
+
key: string,
|
|
439
|
+
value?: string | true,
|
|
440
|
+
element: string,
|
|
441
|
+
message: string,
|
|
442
|
+
})[],
|
|
443
|
+
ignoredUndefinedComponents?: string[],
|
|
444
|
+
overrides?: {},
|
|
445
|
+
},
|
|
446
|
+
nuxt?: boolean | {
|
|
447
|
+
image?: boolean,
|
|
448
|
+
ui?: boolean | {
|
|
449
|
+
prefix?: string,
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
test?: {
|
|
453
|
+
storybook?: boolean | {
|
|
454
|
+
overrides?: {},
|
|
455
|
+
},
|
|
456
|
+
vitest?: boolean | {
|
|
457
|
+
overrides?: {},
|
|
458
|
+
},
|
|
459
|
+
playwright?: boolean | {
|
|
460
|
+
overrides?: {},
|
|
461
|
+
},
|
|
462
|
+
cypress?: boolean | {
|
|
463
|
+
overrides?: {},
|
|
464
|
+
},
|
|
465
|
+
testFunction?: 'test' | 'it',
|
|
466
|
+
maxNestedDescribe?: number,
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
</details>
|
|
472
|
+
|
|
473
|
+
## Versioning Policy
|
|
474
|
+
This project adheres to [The Semantic Versioning Standard](https://semver.org). However, to facilitate rapid development and fast iteration, the following changes are considered non-breaking:
|
|
475
|
+
- Upgrades to dependency versions
|
|
476
|
+
- Modifications to rule options
|
|
477
|
+
- Enabling or disabling rules and plugins
|
|
478
|
+
|
|
479
|
+
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.
|
|
480
|
+
|
|
481
|
+
You can find a list of all available versions and their changelogs on the [releases page](https://github.com/ShayanTheNerd/eslint-config/releases).
|
|
482
|
+
|
|
483
|
+
## Roadmap to v1.0.0
|
|
484
|
+
- [ ] Integrate additional ESLint plugins, such as [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn), [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n), and [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc).
|
|
485
|
+
- [ ] Add support for other frameworks and file types, including Astro, React, Next.js, MDX, Markdown, and JSON.
|
|
486
|
+
- [ ] Reduce bundle size by dynamically (programmatically) installing dependencies as needed.
|
|
487
|
+
- [ ] Develop a starter wizard to automate the setup of OXLint, ESLint, Prettier, and other configurations.
|
|
488
|
+
|
|
489
|
+
## Contribution Guide
|
|
490
|
+
Any form of contribution is always appreciated! Please refer to the [CONTRIBUTING.md](CONTRIBUTING.md) file.
|
|
491
|
+
|
|
492
|
+
## Credits
|
|
493
|
+
This project was inspired by the work of [Anthony Fu](https://github.com/antfu), whose generous contributions to the JavaScript and ESLint ecosystem were instrumental in making it possible.
|
|
494
|
+
|
|
495
|
+
## License
|
|
496
|
+
[MIT](LICENSE) License © 2025-PRESENT — [Shayan Zamani](https://github.com/ShayanTheNerd)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
|
|
25
|
+
Object.defineProperty(exports, '__toESM', {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
get: function () {
|
|
28
|
+
return __toESM;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require__Users_shayan_Desktop_Dev_GitHub_eslint_config_src_utils_globs = require('../utils/globs.cjs');
|
|
3
|
+
const require__Users_shayan_Desktop_Dev_GitHub_eslint_config_src_rules_javascript = require('../rules/javascript.cjs');
|
|
4
|
+
const typescript_eslint = require_rolldown_runtime.__toESM(require("typescript-eslint"));
|
|
5
|
+
const eslint_flat_config_utils = require_rolldown_runtime.__toESM(require("eslint-flat-config-utils"));
|
|
6
|
+
const globals = require_rolldown_runtime.__toESM(require("globals"));
|
|
7
|
+
const __eslint_js = require_rolldown_runtime.__toESM(require("@eslint/js"));
|
|
8
|
+
|
|
9
|
+
//#region src/configs/base.ts
|
|
10
|
+
function getBaseConfig(options) {
|
|
11
|
+
const { configs: { vue, base: { overrides } }, global: { globals: { node, worker, browser, commonjs, webextension, serviceworker, custom: userGlobals } } } = options;
|
|
12
|
+
const baseConfig = {
|
|
13
|
+
name: "shayanthenerd/base",
|
|
14
|
+
files: [require__Users_shayan_Desktop_Dev_GitHub_eslint_config_src_utils_globs.globs.src, vue ? require__Users_shayan_Desktop_Dev_GitHub_eslint_config_src_utils_globs.globs.vue : ""],
|
|
15
|
+
extends: [__eslint_js.default.configs.recommended],
|
|
16
|
+
languageOptions: {
|
|
17
|
+
parserOptions: {
|
|
18
|
+
parser: typescript_eslint.default.parser,
|
|
19
|
+
ecmaVersion: "latest",
|
|
20
|
+
ecmaFeatures: {
|
|
21
|
+
jsx: true,
|
|
22
|
+
impliedStrict: true
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
globals: {
|
|
26
|
+
...globals.default.builtin,
|
|
27
|
+
...globals.default.es2026,
|
|
28
|
+
...commonjs ? globals.default.commonjs : {},
|
|
29
|
+
...node ? globals.default.node : {},
|
|
30
|
+
...node ? globals.default.nodeBuiltin : {},
|
|
31
|
+
...browser ? globals.default.browser : {},
|
|
32
|
+
...worker ? globals.default.worker : {},
|
|
33
|
+
...serviceworker ? globals.default.serviceworker : {},
|
|
34
|
+
...webextension ? globals.default.webextensions : {},
|
|
35
|
+
...userGlobals
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
rules: require__Users_shayan_Desktop_Dev_GitHub_eslint_config_src_rules_javascript.getJavaScriptRules(options)
|
|
39
|
+
};
|
|
40
|
+
return (0, eslint_flat_config_utils.mergeConfigs)(baseConfig, overrides);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
exports.getBaseConfig = getBaseConfig;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { globs } from "../utils/globs.js";
|
|
2
|
+
import { getJavaScriptRules } from "../rules/javascript.js";
|
|
3
|
+
import typescriptESLint from "typescript-eslint";
|
|
4
|
+
import { mergeConfigs } from "eslint-flat-config-utils";
|
|
5
|
+
import globals from "globals";
|
|
6
|
+
import javascriptESLint from "@eslint/js";
|
|
7
|
+
|
|
8
|
+
//#region src/configs/base.ts
|
|
9
|
+
function getBaseConfig(options) {
|
|
10
|
+
const { configs: { vue, base: { overrides } }, global: { globals: { node, worker, browser, commonjs, webextension, serviceworker, custom: userGlobals } } } = options;
|
|
11
|
+
const baseConfig = {
|
|
12
|
+
name: "shayanthenerd/base",
|
|
13
|
+
files: [globs.src, vue ? globs.vue : ""],
|
|
14
|
+
extends: [javascriptESLint.configs.recommended],
|
|
15
|
+
languageOptions: {
|
|
16
|
+
parserOptions: {
|
|
17
|
+
parser: typescriptESLint.parser,
|
|
18
|
+
ecmaVersion: "latest",
|
|
19
|
+
ecmaFeatures: {
|
|
20
|
+
jsx: true,
|
|
21
|
+
impliedStrict: true
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
globals: {
|
|
25
|
+
...globals.builtin,
|
|
26
|
+
...globals.es2026,
|
|
27
|
+
...commonjs ? globals.commonjs : {},
|
|
28
|
+
...node ? globals.node : {},
|
|
29
|
+
...node ? globals.nodeBuiltin : {},
|
|
30
|
+
...browser ? globals.browser : {},
|
|
31
|
+
...worker ? globals.worker : {},
|
|
32
|
+
...serviceworker ? globals.serviceworker : {},
|
|
33
|
+
...webextension ? globals.webextensions : {},
|
|
34
|
+
...userGlobals
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
rules: getJavaScriptRules(options)
|
|
38
|
+
};
|
|
39
|
+
return mergeConfigs(baseConfig, overrides);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { getBaseConfig };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require__Users_shayan_Desktop_Dev_GitHub_eslint_config_src_utils_globs = require('../utils/globs.cjs');
|
|
3
|
+
const typescript_eslint = require_rolldown_runtime.__toESM(require("typescript-eslint"));
|
|
4
|
+
|
|
5
|
+
//#region src/configs/commons.ts
|
|
6
|
+
function getCommonsConfig(options) {
|
|
7
|
+
const commonsConfig = {
|
|
8
|
+
name: "shayanthenerd/commons",
|
|
9
|
+
files: [require__Users_shayan_Desktop_Dev_GitHub_eslint_config_src_utils_globs.globs.commons],
|
|
10
|
+
ignores: [require__Users_shayan_Desktop_Dev_GitHub_eslint_config_src_utils_globs.globs.commonsIgnore],
|
|
11
|
+
plugins: { "@typescript-eslint": typescript_eslint.default.plugin },
|
|
12
|
+
rules: {
|
|
13
|
+
"@typescript-eslint/explicit-function-return-type": "error",
|
|
14
|
+
"no-restricted-exports": [options.configs.base.preferNamedExports ? "error" : "off", { restrictDefaultExports: {
|
|
15
|
+
named: true,
|
|
16
|
+
direct: true,
|
|
17
|
+
namedFrom: true,
|
|
18
|
+
namespaceFrom: true
|
|
19
|
+
} }]
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
return commonsConfig;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
exports.getCommonsConfig = getCommonsConfig;
|