@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.
Files changed (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +496 -0
  3. package/dist/_virtual/rolldown_runtime.cjs +30 -0
  4. package/dist/configs/base.cjs +44 -0
  5. package/dist/configs/base.js +43 -0
  6. package/dist/configs/commons.cjs +26 -0
  7. package/dist/configs/commons.js +25 -0
  8. package/dist/configs/css.cjs +29 -0
  9. package/dist/configs/css.js +28 -0
  10. package/dist/configs/cypress.cjs +23 -0
  11. package/dist/configs/cypress.js +22 -0
  12. package/dist/configs/html.cjs +23 -0
  13. package/dist/configs/html.js +22 -0
  14. package/dist/configs/importX.cjs +26 -0
  15. package/dist/configs/importX.js +25 -0
  16. package/dist/configs/nuxtMultiRootTemplate.cjs +14 -0
  17. package/dist/configs/nuxtMultiRootTemplate.js +14 -0
  18. package/dist/configs/oxlintOverrides.cjs +49 -0
  19. package/dist/configs/oxlintOverrides.js +48 -0
  20. package/dist/configs/perfectionist.cjs +24 -0
  21. package/dist/configs/perfectionist.js +23 -0
  22. package/dist/configs/playwright.cjs +23 -0
  23. package/dist/configs/playwright.js +22 -0
  24. package/dist/configs/storybook.cjs +24 -0
  25. package/dist/configs/storybook.js +23 -0
  26. package/dist/configs/stylistic.cjs +23 -0
  27. package/dist/configs/stylistic.js +22 -0
  28. package/dist/configs/tailwind.cjs +43 -0
  29. package/dist/configs/tailwind.js +42 -0
  30. package/dist/configs/typescript.cjs +31 -0
  31. package/dist/configs/typescript.js +30 -0
  32. package/dist/configs/vitest.cjs +23 -0
  33. package/dist/configs/vitest.js +22 -0
  34. package/dist/configs/vue.cjs +35 -0
  35. package/dist/configs/vue.js +34 -0
  36. package/dist/configs/vueComponentNames.cjs +19 -0
  37. package/dist/configs/vueComponentNames.js +19 -0
  38. package/dist/index.cjs +55 -0
  39. package/dist/index.d.cts +16 -0
  40. package/dist/index.d.ts +16 -0
  41. package/dist/index.js +54 -0
  42. package/dist/oxlint.config.jsonc +192 -0
  43. package/dist/prettier.config.js +42 -0
  44. package/dist/rules/css.cjs +65 -0
  45. package/dist/rules/css.js +65 -0
  46. package/dist/rules/cypress.cjs +16 -0
  47. package/dist/rules/cypress.js +15 -0
  48. package/dist/rules/html.cjs +53 -0
  49. package/dist/rules/html.js +53 -0
  50. package/dist/rules/importX.cjs +51 -0
  51. package/dist/rules/importX.js +50 -0
  52. package/dist/rules/javascript.cjs +164 -0
  53. package/dist/rules/javascript.js +163 -0
  54. package/dist/rules/perfectionist.cjs +73 -0
  55. package/dist/rules/perfectionist.js +73 -0
  56. package/dist/rules/playwright.cjs +28 -0
  57. package/dist/rules/playwright.js +27 -0
  58. package/dist/rules/storybook.cjs +16 -0
  59. package/dist/rules/storybook.js +15 -0
  60. package/dist/rules/stylistic.cjs +160 -0
  61. package/dist/rules/stylistic.js +160 -0
  62. package/dist/rules/tailwind.cjs +36 -0
  63. package/dist/rules/tailwind.js +36 -0
  64. package/dist/rules/typescript.cjs +62 -0
  65. package/dist/rules/typescript.js +62 -0
  66. package/dist/rules/vitest.cjs +47 -0
  67. package/dist/rules/vitest.js +46 -0
  68. package/dist/rules/vue.cjs +169 -0
  69. package/dist/rules/vue.js +169 -0
  70. package/dist/rules/vueAccessibility.cjs +23 -0
  71. package/dist/rules/vueAccessibility.js +23 -0
  72. package/dist/types/configOptions/base.d.cts +47 -0
  73. package/dist/types/configOptions/base.d.ts +47 -0
  74. package/dist/types/configOptions/css.d.cts +27 -0
  75. package/dist/types/configOptions/css.d.ts +27 -0
  76. package/dist/types/configOptions/html.d.cts +27 -0
  77. package/dist/types/configOptions/html.d.ts +27 -0
  78. package/dist/types/configOptions/importX.d.cts +20 -0
  79. package/dist/types/configOptions/importX.d.ts +20 -0
  80. package/dist/types/configOptions/nuxt.d.cts +42 -0
  81. package/dist/types/configOptions/nuxt.d.ts +42 -0
  82. package/dist/types/configOptions/perfectionist.d.cts +16 -0
  83. package/dist/types/configOptions/perfectionist.d.ts +16 -0
  84. package/dist/types/configOptions/stylistic.d.cts +145 -0
  85. package/dist/types/configOptions/stylistic.d.ts +145 -0
  86. package/dist/types/configOptions/tailwind.d.cts +46 -0
  87. package/dist/types/configOptions/tailwind.d.ts +46 -0
  88. package/dist/types/configOptions/test.d.cts +55 -0
  89. package/dist/types/configOptions/test.d.ts +55 -0
  90. package/dist/types/configOptions/typescript.d.cts +36 -0
  91. package/dist/types/configOptions/typescript.d.ts +36 -0
  92. package/dist/types/configOptions/vue.d.cts +211 -0
  93. package/dist/types/configOptions/vue.d.ts +211 -0
  94. package/dist/types/configOptions/vueAccessibility.d.cts +34 -0
  95. package/dist/types/configOptions/vueAccessibility.d.ts +34 -0
  96. package/dist/types/eslint-schema.d.cts +13258 -0
  97. package/dist/types/eslint-schema.d.ts +13258 -0
  98. package/dist/types/eslintRules.d.cts +12 -0
  99. package/dist/types/eslintRules.d.ts +12 -0
  100. package/dist/types/helpers.d.cts +5 -0
  101. package/dist/types/helpers.d.ts +5 -0
  102. package/dist/types/index.d.cts +360 -0
  103. package/dist/types/index.d.ts +360 -0
  104. package/dist/utils/globs.cjs +31 -0
  105. package/dist/utils/globs.js +30 -0
  106. package/dist/utils/ignores/defaultIgnorePatterns.cjs +58 -0
  107. package/dist/utils/ignores/defaultIgnorePatterns.js +57 -0
  108. package/dist/utils/ignores/getIgnorePatterns.cjs +16 -0
  109. package/dist/utils/ignores/getIgnorePatterns.js +16 -0
  110. package/dist/utils/ignores/resolveGitignorePatterns.cjs +27 -0
  111. package/dist/utils/ignores/resolveGitignorePatterns.js +26 -0
  112. package/dist/utils/isEmptyString.cjs +8 -0
  113. package/dist/utils/isEmptyString.js +7 -0
  114. package/dist/utils/isEnabled.cjs +8 -0
  115. package/dist/utils/isEnabled.js +7 -0
  116. package/dist/utils/isPackageDetected.cjs +22 -0
  117. package/dist/utils/isPackageDetected.js +20 -0
  118. package/dist/utils/options/defaultOptions.cjs +168 -0
  119. package/dist/utils/options/defaultOptions.js +167 -0
  120. package/dist/utils/options/enableDetectedConfigs.cjs +36 -0
  121. package/dist/utils/options/enableDetectedConfigs.js +36 -0
  122. package/dist/utils/options/mergeWithDefaults.cjs +22 -0
  123. package/dist/utils/options/mergeWithDefaults.js +21 -0
  124. package/dist/utils/vue/getRestrictedVueElements.cjs +28 -0
  125. package/dist/utils/vue/getRestrictedVueElements.js +27 -0
  126. package/dist/utils/vue/getRestrictedVueInputs.cjs +24 -0
  127. package/dist/utils/vue/getRestrictedVueInputs.js +23 -0
  128. 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    [![NPM Version](https://img.shields.io/npm/v/@shayanthenerd/eslint-config?label=&logo=npm&logoColor=DDDDDD&labelColor=212121&color=212121&registry_uri=https://registry.npmjs.com/@shayanthenerd/eslint-config&link=https://github.com/ShayanTheNerd/eslint-config)](https://www.npmjs.com/package/@shayanthenerd/eslint-config) [![JSR Registry](https://jsr.io/badges/@shayanthenerd?logoColor=DDDDDD&labelColor=212121&color=212121)](https://jsr.io/@shayanthenerd/eslint-config) [![License MIT](https://img.shields.io/badge/License-MIT-blue.svg?labelColor=212121&color=212121)](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;