@shayanthenerd/eslint-config 0.32.0 → 0.33.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 +62 -38
- package/dist/configs/astro.mjs +5 -1
- package/dist/configs/packageJson.mjs +1 -1
- package/dist/configs/react.mjs +2 -2
- package/dist/configs/tailwind.mjs +7 -1
- package/dist/configs/typescript.mjs +4 -6
- package/dist/helpers/ignores/defaultIgnorePatterns.mjs +1 -6
- package/dist/helpers/options/defaultOptions.mjs +13 -3
- package/dist/helpers/options/enableDetectedConfigs.mjs +18 -7
- package/dist/index.d.mts +1 -0
- package/dist/rules/astro.mjs +61 -54
- package/dist/rules/baseline.mjs +1 -1
- package/dist/rules/css.mjs +35 -7
- package/dist/rules/html.mjs +3 -2
- package/dist/rules/importX.mjs +2 -2
- package/dist/rules/javascript.mjs +6 -5
- package/dist/rules/next.mjs +2 -0
- package/dist/rules/node.mjs +1 -1
- package/dist/rules/packageJson.mjs +166 -153
- package/dist/rules/perfectionist.mjs +41 -11
- package/dist/rules/playwright.mjs +10 -0
- package/dist/rules/react.mjs +57 -54
- package/dist/rules/stylistic.mjs +1 -1
- package/dist/rules/tanstack.mjs +1 -1
- package/dist/rules/typescript.mjs +2 -2
- package/dist/rules/unicorn.mjs +15 -6
- package/dist/rules/vue.mjs +38 -41
- package/dist/rules/zod.mjs +2 -0
- package/dist/types/eslint-schema.d.mts +776 -651
- package/dist/types/index.d.mts +50 -7
- package/dist/types/options/baseline.d.mts +24 -3
- package/dist/types/options/react.d.mts +9 -9
- package/dist/types/options/typescript.d.mts +3 -3
- package/dist/types/options/vue.d.mts +1 -1
- package/package.json +34 -33
package/README.md
CHANGED
|
@@ -25,40 +25,40 @@ ESLint configuration for enforcing best practices and maintaining a consistent c
|
|
|
25
25
|
## Plugin Support
|
|
26
26
|
Legend:
|
|
27
27
|
- ✅ — **Enabled** by default
|
|
28
|
+
- 🔍 — [**Automatically detected**](#automatic-dependency-detection)
|
|
28
29
|
- ⚙️ — **Opt-in** (requires manual configuration)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
| [
|
|
35
|
-
| [
|
|
36
|
-
| [
|
|
37
|
-
| [
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
| [
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
| [
|
|
44
|
-
| [
|
|
45
|
-
| [
|
|
46
|
-
| [
|
|
47
|
-
| [
|
|
48
|
-
| [
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
| [
|
|
52
|
-
| [
|
|
53
|
-
| [
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
| [
|
|
57
|
-
| [
|
|
58
|
-
| [
|
|
59
|
-
| [
|
|
60
|
-
| [
|
|
61
|
-
| [Baseline][plugin-baseline] ([css/use-baseline], [@html-eslint/use-baseline], [@html-eslint/react/use-baseline]) | 🔍 |
|
|
30
|
+
|
|
31
|
+
| Category | Activation |
|
|
32
|
+
| :------------------------------------------------------------------------------------------------------ | :--------: |
|
|
33
|
+
| **Languages** | |
|
|
34
|
+
| [JavaScript][eslint] | ✅ |
|
|
35
|
+
| [TypeScript][plugin-ts] | 🔍 |
|
|
36
|
+
| [Markdown][plugin-md] | ✅ |
|
|
37
|
+
| [HTML][plugin-html] | ⚙️ |
|
|
38
|
+
| [CSS][plugin-css] | ⚙️ |
|
|
39
|
+
| **Formatting** | |
|
|
40
|
+
| [Stylistic][plugin-stylistic] | ✅ |
|
|
41
|
+
| [Perfectionist][plugin-perfectionist] | ✅ |
|
|
42
|
+
| **Frameworks & Libraries** | |
|
|
43
|
+
| [Astro][plugin-astro] ([jsx-accessibility][plugin-jsx-a11y-x]) | 🔍 |
|
|
44
|
+
| [React][plugin-react] ([jsx-accessibility][plugin-jsx-a11y-x], [@html-eslint/react][plugin-html-react]) | 🔍 |
|
|
45
|
+
| [Next][plugin-next] | 🔍 |
|
|
46
|
+
| [TanStack Start][plugin-tanstack-start], [TanStack Query][plugin-tanstack-query], [TanStack Router][plugin-tanstack-router] | 🔍 |
|
|
47
|
+
| [Vue & Nuxt][plugin-vue] ([vue-accessibility][plugin-vue-a11y]) | 🔍 |
|
|
48
|
+
| [Tailwind][plugin-tailwind] | ⚙️ |
|
|
49
|
+
| [Zod & Zod Mini][plugin-zod] | 🔍 |
|
|
50
|
+
| **Testing Tools** | |
|
|
51
|
+
| [Storybook][plugin-storybook] | 🔍 |
|
|
52
|
+
| [Vitest][plugin-vitest] | 🔍 |
|
|
53
|
+
| [Cypress][plugin-cypress] | 🔍 |
|
|
54
|
+
| [Playwright][plugin-playwright] | 🔍 |
|
|
55
|
+
| **Miscellaneous** | |
|
|
56
|
+
| [_package.json_][plugin-package-json] | ✅ |
|
|
57
|
+
| [Node][plugin-n] | ✅ |
|
|
58
|
+
| [Promises][plugin-promise] | ✅ |
|
|
59
|
+
| [Imports][plugin-import-x] | ✅ |
|
|
60
|
+
| [Unicorn][plugin-unicorn] | ✅ |
|
|
61
|
+
| [Baseline][plugin-baseline] ([css/use-baseline], [@html-eslint/use-baseline], [@html-eslint/react/use-baseline]) | 🔍 |
|
|
62
62
|
|
|
63
63
|
## Installation and Configuration
|
|
64
64
|
1. Install the package and ESLint as dev dependencies:
|
|
@@ -81,7 +81,7 @@ Legend:
|
|
|
81
81
|
"scripts": {
|
|
82
82
|
"lint": "eslint --max-warnings=0 --cache --cache-location='node_modules/.cache/.eslintcache'",
|
|
83
83
|
"lint:fix": "eslint --fix --max-warnings=0 --cache --cache-location='node_modules/.cache/.eslintcache'",
|
|
84
|
-
"lint:inspect": "
|
|
84
|
+
"lint:inspect": "pnpx @eslint/config-inspector"
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
```
|
|
@@ -214,8 +214,27 @@ For editor integration, to reduce noise and avoid inconsistent diagnostics from
|
|
|
214
214
|
}
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
+
### Astro
|
|
218
|
+
The accessibility rules in [eslint-plugin-astro][plugin-astro] require [eslint-plugin-jsx-a11y-x][plugin-jsx-a11y-x] as a peer dependency. Install it with:
|
|
219
|
+
```shell
|
|
220
|
+
pnpm add -D eslint-plugin-jsx-a11y-x
|
|
221
|
+
```
|
|
222
|
+
When both `astro` and `eslint-plugin-jsx-a11y-x` are detected as dependencies, `configs.astro.accessibility` is set to `true` automatically. To disable the accessibility rules, set `configs.astro.accessibility` to `false`.
|
|
223
|
+
|
|
224
|
+
### Vue
|
|
225
|
+
[ESLint Stylistic][plugin-stylistic] and [eslint-plugin-vue][plugin-vue] don't format `<style>` blocks inside Vue SFCs. On the other hand, [Prettier][prettier] cannot be limited to just `<style>` blocks, and formats the whole file, including `<script>` and `<template>` blocks, which could conflict with ESLint. To work around this, you may use Tailwind, format styles manually, keep styles in separate `.css` files, or use Prettier and resolve any resulting conflicts.
|
|
226
|
+
|
|
227
|
+
Read more about the formatting options and Prettier integration in the [Formatting](#formatting) section.
|
|
228
|
+
|
|
217
229
|
### Nuxt
|
|
218
|
-
The required Nuxt configurations and rules are already included, so there's no need to
|
|
230
|
+
The required Nuxt configurations and rules are already included, so there's no need to use the [@nuxt/eslint][eslint-nuxt] module.
|
|
231
|
+
|
|
232
|
+
### React/Next
|
|
233
|
+
The required Next configurations and rules, including for core web vitals, are already provided, so there's no need to use [eslint-config-next][eslint-next]. Similarly, the React integration also provides React-specific configurations and rules for accessibility and React Hooks.
|
|
234
|
+
|
|
235
|
+
### TanStack Start
|
|
236
|
+
> [!NOTE]
|
|
237
|
+
> The rules in [@tanstack/eslint-plugin-start][plugin-tanstack-start] require type information, and will be disabled automatically if the TypeScript integration is not enabled.
|
|
219
238
|
|
|
220
239
|
### Markdown
|
|
221
240
|
Markdown linting is powered by [@eslint/markdown][plugin-md].
|
|
@@ -344,7 +363,7 @@ For file types that ESLint Stylistic does not handle—such as CSS, JSON, YAML,
|
|
|
344
363
|
```json title="package.json"
|
|
345
364
|
{
|
|
346
365
|
"scripts": {
|
|
347
|
-
"format": "prettier --write . '!**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,html,vue,astro}' --cache"
|
|
366
|
+
"format": "prettier --write . '!pnpm-lock.yaml' '!**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,html,vue,astro}' --cache"
|
|
348
367
|
}
|
|
349
368
|
}
|
|
350
369
|
```
|
|
@@ -427,7 +446,7 @@ For file types that ESLint Stylistic does not handle—such as CSS, JSON, YAML,
|
|
|
427
446
|
```json title="package.json"
|
|
428
447
|
{
|
|
429
448
|
"scripts": {
|
|
430
|
-
"format": "prettier --write . --cache",
|
|
449
|
+
"format": "prettier --write . '!pnpm-lock.yaml' --cache",
|
|
431
450
|
}
|
|
432
451
|
}
|
|
433
452
|
```
|
|
@@ -517,6 +536,7 @@ For file types that ESLint Stylistic does not handle—such as CSS, JSON, YAML,
|
|
|
517
536
|
|
|
518
537
|
configs?: {
|
|
519
538
|
astro?: boolean | {
|
|
539
|
+
accessibility?: boolean,
|
|
520
540
|
overrides?: Overrides,
|
|
521
541
|
},
|
|
522
542
|
baseline?: boolean | {
|
|
@@ -537,6 +557,7 @@ For file types that ESLint Stylistic does not handle—such as CSS, JSON, YAML,
|
|
|
537
557
|
overrides?: Overrides,
|
|
538
558
|
},
|
|
539
559
|
css?: boolean | {
|
|
560
|
+
allowedUnknownPseudoSelectors?: string[],
|
|
540
561
|
overrides?: Overrides,
|
|
541
562
|
},
|
|
542
563
|
html?: boolean | {
|
|
@@ -574,6 +595,8 @@ For file types that ESLint Stylistic does not handle—such as CSS, JSON, YAML,
|
|
|
574
595
|
overrides?: Overrides,
|
|
575
596
|
},
|
|
576
597
|
packageJson?: boolean | {
|
|
598
|
+
allowedDistTags?: string[],
|
|
599
|
+
allowedDistTagsFor?: ('dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies')[],
|
|
577
600
|
overrides?: Overrides,
|
|
578
601
|
},
|
|
579
602
|
perfectionist?: boolean | {
|
|
@@ -763,7 +786,7 @@ This project was inspired by the work of [Anthony Fu][antfu], whose generous con
|
|
|
763
786
|
[plugin-html]: https://html-eslint.org
|
|
764
787
|
[plugin-html-react]: https://html-eslint.org/docs/react/getting-started
|
|
765
788
|
[plugin-import-x]: https://github.com/un-ts/eslint-plugin-import-x
|
|
766
|
-
[plugin-jsx-a11y]: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
|
|
789
|
+
[plugin-jsx-a11y-x]: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y-x
|
|
767
790
|
[plugin-md]: https://github.com/eslint/markdown
|
|
768
791
|
[plugin-n]: https://github.com/eslint-community/eslint-plugin-n
|
|
769
792
|
[plugin-next]: https://github.com/vercel/next.js/tree/HEAD/packages/eslint-plugin-next
|
|
@@ -796,6 +819,7 @@ This project was inspired by the work of [Anthony Fu][antfu], whose generous con
|
|
|
796
819
|
[eslint]: https://eslint.org
|
|
797
820
|
[online-preview]: https://eslintconfig.netlify.app
|
|
798
821
|
[eslint-config-ts-setup]: https://eslint.org/docs/latest/use/configure/configuration-files#typescript-configuration-files
|
|
822
|
+
[eslint-next]: https://nextjs.org/docs/app/api-reference/config/eslint
|
|
799
823
|
[eslint-nuxt]: https://eslint.nuxt.com
|
|
800
824
|
[local-pkg]: https://github.com/antfu-collective/local-pkg
|
|
801
825
|
[prettier]: https://prettier.io
|
package/dist/configs/astro.mjs
CHANGED
|
@@ -6,9 +6,10 @@ import * as eslintParserAstro from "astro-eslint-parser";
|
|
|
6
6
|
import { mergeConfigs } from "eslint-flat-config-utils";
|
|
7
7
|
import eslintPluginAstro from "eslint-plugin-astro";
|
|
8
8
|
import { parser } from "typescript-eslint";
|
|
9
|
+
import path from "node:path";
|
|
9
10
|
//#region src/configs/astro.ts
|
|
10
11
|
function getAstroConfig(options) {
|
|
11
|
-
const { astro } = options
|
|
12
|
+
const { tsConfig, configs: { astro } } = options;
|
|
12
13
|
const { overrides } = isEnabled(astro) ? astro : defaultOptions.configs.astro;
|
|
13
14
|
const astroConfig = {
|
|
14
15
|
name: "shayanthenerd/astro",
|
|
@@ -22,6 +23,9 @@ function getAstroConfig(options) {
|
|
|
22
23
|
parser: eslintParserAstro,
|
|
23
24
|
parserOptions: {
|
|
24
25
|
parser,
|
|
26
|
+
projectService: false,
|
|
27
|
+
project: tsConfig ? path.resolve(tsConfig.rootDir, tsConfig.filename) : void 0,
|
|
28
|
+
tsconfigRootDir: tsConfig ? path.resolve(tsConfig.rootDir) : void 0,
|
|
25
29
|
extraFileExtensions: [".astro"]
|
|
26
30
|
}
|
|
27
31
|
},
|
|
@@ -13,7 +13,7 @@ function getPackageJsonConfig(options) {
|
|
|
13
13
|
files: [globs.packageJson],
|
|
14
14
|
plugins: { "package-json": eslintPluginPackageJson },
|
|
15
15
|
languageOptions: { parser: eslintPluginPackageJson.configs.recommended.languageOptions.parser },
|
|
16
|
-
rules: getPackageJsonRules()
|
|
16
|
+
rules: getPackageJsonRules(options)
|
|
17
17
|
};
|
|
18
18
|
return mergeConfigs(packageJsonConfig, overrides);
|
|
19
19
|
}
|
package/dist/configs/react.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { isEnabled } from "../utils/isEnabled.mjs";
|
|
|
4
4
|
import { getReactRules } from "../rules/react.mjs";
|
|
5
5
|
import { mergeConfigs } from "eslint-flat-config-utils";
|
|
6
6
|
import eslintPluginUnicorn from "eslint-plugin-unicorn";
|
|
7
|
-
import
|
|
7
|
+
import eslintPluginJsxA11yX from "eslint-plugin-jsx-a11y-x";
|
|
8
8
|
import eslintPluginReact from "@eslint-react/eslint-plugin";
|
|
9
9
|
import eslintPluginHtmlReact from "@html-eslint/eslint-plugin-react";
|
|
10
10
|
//#region src/configs/react.ts
|
|
@@ -18,7 +18,7 @@ function getReactConfig(options) {
|
|
|
18
18
|
"@eslint-react": eslintPluginReact,
|
|
19
19
|
"@html-eslint/react": eslintPluginHtmlReact,
|
|
20
20
|
...isEnabled(unicorn) && { unicorn: eslintPluginUnicorn },
|
|
21
|
-
...isEnabled(accessibility) && { "jsx-a11y":
|
|
21
|
+
...isEnabled(accessibility) && { "jsx-a11y-x": eslintPluginJsxA11yX }
|
|
22
22
|
},
|
|
23
23
|
rules: getReactRules(options)
|
|
24
24
|
};
|
|
@@ -14,6 +14,11 @@ const astroAttributes = {
|
|
|
14
14
|
name: "^class:list$",
|
|
15
15
|
match: [{ type: MatcherType.String }, { type: MatcherType.ObjectKey }]
|
|
16
16
|
};
|
|
17
|
+
const reactAttributes = {
|
|
18
|
+
kind: SelectorKind.Attribute,
|
|
19
|
+
name: "^(?:className|.*Class)$",
|
|
20
|
+
match: [{ type: MatcherType.String }, { type: MatcherType.ObjectKey }]
|
|
21
|
+
};
|
|
17
22
|
const vueAttributes = {
|
|
18
23
|
kind: SelectorKind.Attribute,
|
|
19
24
|
name: "^(?:v-bind:)?(exactActiveClass|activeClass|inactiveClass|active-class|inactive-class)$",
|
|
@@ -43,13 +48,14 @@ const nuxtUiAppConfigUiFields = {
|
|
|
43
48
|
}]
|
|
44
49
|
};
|
|
45
50
|
function getTailwindConfig(options) {
|
|
46
|
-
const { tsConfig, configs: { vue, nuxt, html, astro, tailwind } } = options;
|
|
51
|
+
const { tsConfig, configs: { vue, nuxt, html, astro, react, tailwind } } = options;
|
|
47
52
|
const { cwd, config, overrides, entryPoint } = isEnabled(tailwind) ? tailwind : defaultOptions.configs.tailwind;
|
|
48
53
|
const tsconfigPath = tsConfig ? path.resolve(tsConfig.rootDir, tsConfig.filename) : void 0;
|
|
49
54
|
const isNuxtUiEnabled = isEnabled(nuxt) && isEnabled(nuxt.ui);
|
|
50
55
|
const selectors = [
|
|
51
56
|
...getDefaultSelectors(),
|
|
52
57
|
isEnabled(astro) ? astroAttributes : void 0,
|
|
58
|
+
isEnabled(react) ? reactAttributes : void 0,
|
|
53
59
|
isEnabled(vue) ? vueAttributes : void 0,
|
|
54
60
|
isNuxtUiEnabled ? nuxtUiAttributes : void 0,
|
|
55
61
|
isNuxtUiEnabled ? nuxtUiAppConfigUiFields : void 0
|
|
@@ -8,26 +8,24 @@ import { parser, plugin } from "typescript-eslint";
|
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
//#region src/configs/typescript.ts
|
|
10
10
|
function getTypescriptConfig(options) {
|
|
11
|
-
const { tsConfig, configs: { vue,
|
|
12
|
-
const { allowedDefaultProjects } = isEnabled(typescript) ? typescript : defaultOptions.configs.typescript;
|
|
11
|
+
const { tsConfig, configs: { vue, typescript } } = options;
|
|
12
|
+
const { allowedDefaultProjects: userAllowedDefaultProjects } = isEnabled(typescript) ? typescript : defaultOptions.configs.typescript;
|
|
13
13
|
const { overrides } = isEnabled(typescript) ? typescript : defaultOptions.configs.typescript;
|
|
14
14
|
const typescriptConfig = {
|
|
15
15
|
name: "shayanthenerd/typescript",
|
|
16
16
|
files: [
|
|
17
17
|
globs.src,
|
|
18
18
|
globs.jsxTsx,
|
|
19
|
-
isEnabled(vue) ? globs.vue : ""
|
|
20
|
-
isEnabled(astro) ? globs.astro : ""
|
|
19
|
+
isEnabled(vue) ? globs.vue : ""
|
|
21
20
|
].filter(isTruthy),
|
|
22
21
|
plugins: { "@typescript-eslint": plugin },
|
|
23
22
|
languageOptions: {
|
|
24
23
|
parser,
|
|
25
24
|
parserOptions: {
|
|
26
|
-
warnOnUnsupportedTypeScriptVersion: false,
|
|
27
25
|
tsconfigRootDir: tsConfig ? path.resolve(tsConfig.rootDir) : void 0,
|
|
28
26
|
projectService: {
|
|
29
27
|
defaultProject: tsConfig ? tsConfig.filename : void 0,
|
|
30
|
-
allowDefaultProject:
|
|
28
|
+
allowDefaultProject: userAllowedDefaultProjects
|
|
31
29
|
}
|
|
32
30
|
}
|
|
33
31
|
},
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
//#region src/helpers/ignores/defaultIgnorePatterns.ts
|
|
2
2
|
const defaultIgnorePatterns = [
|
|
3
|
-
"**/*.min.*",
|
|
4
3
|
"**/jspm_packages",
|
|
5
4
|
"**/pnpm-lock.yaml",
|
|
6
|
-
"**/bower_components",
|
|
7
5
|
"**/package-lock.json",
|
|
8
6
|
"**/typegen.d.ts",
|
|
9
7
|
"**/next-env.d.ts",
|
|
@@ -18,6 +16,7 @@ const defaultIgnorePatterns = [
|
|
|
18
16
|
"**/public",
|
|
19
17
|
"**/output",
|
|
20
18
|
"**/.output",
|
|
19
|
+
"**/*.min.*",
|
|
21
20
|
"**/.serverless",
|
|
22
21
|
"**/.eslint-config-inspector",
|
|
23
22
|
"**/tmp",
|
|
@@ -29,22 +28,18 @@ const defaultIgnorePatterns = [
|
|
|
29
28
|
"**/.cache",
|
|
30
29
|
"**/deno_dir",
|
|
31
30
|
"**/.parcel-cache",
|
|
32
|
-
"**/*.lerna_backup",
|
|
33
31
|
"**/.postcss-cache",
|
|
34
32
|
"**/.vitepress/cache",
|
|
35
33
|
"**/vite.config.*.timestamp-*",
|
|
36
34
|
"**/.nx",
|
|
37
35
|
"**/.vite",
|
|
38
|
-
"**/.yarn",
|
|
39
36
|
"**/.nuxt",
|
|
40
37
|
"**/.next",
|
|
41
38
|
"**/.astro",
|
|
42
39
|
"**/.vitest",
|
|
43
40
|
"**/.vercel",
|
|
44
|
-
"**/.svelte-kit",
|
|
45
41
|
"**/.vite-inspect",
|
|
46
42
|
"**/coverage",
|
|
47
|
-
"**/_fixtures",
|
|
48
43
|
"**/.nyc_output",
|
|
49
44
|
"**/__snapshots__",
|
|
50
45
|
"**/.idea",
|
|
@@ -34,7 +34,10 @@ const defaultOptions = {
|
|
|
34
34
|
settings: {}
|
|
35
35
|
},
|
|
36
36
|
configs: {
|
|
37
|
-
astro: {
|
|
37
|
+
astro: {
|
|
38
|
+
accessibility: false,
|
|
39
|
+
overrides: {}
|
|
40
|
+
},
|
|
38
41
|
baseline: {
|
|
39
42
|
baseline: "widely",
|
|
40
43
|
css: {
|
|
@@ -52,7 +55,10 @@ const defaultOptions = {
|
|
|
52
55
|
},
|
|
53
56
|
overrides: {}
|
|
54
57
|
},
|
|
55
|
-
css: {
|
|
58
|
+
css: {
|
|
59
|
+
allowedUnknownPseudoSelectors: [],
|
|
60
|
+
overrides: {}
|
|
61
|
+
},
|
|
56
62
|
html: {
|
|
57
63
|
idNamingConvention: "snake_case",
|
|
58
64
|
overrides: {}
|
|
@@ -77,7 +83,11 @@ const defaultOptions = {
|
|
|
77
83
|
ui: { prefix: "U" },
|
|
78
84
|
overrides: {}
|
|
79
85
|
},
|
|
80
|
-
packageJson: {
|
|
86
|
+
packageJson: {
|
|
87
|
+
allowedDistTags: [],
|
|
88
|
+
allowedDistTagsFor: [],
|
|
89
|
+
overrides: {}
|
|
90
|
+
},
|
|
81
91
|
perfectionist: {
|
|
82
92
|
sortType: "line-length",
|
|
83
93
|
overrides: {}
|
|
@@ -7,8 +7,12 @@ function enableDetectedConfigs(options) {
|
|
|
7
7
|
"typescript": options.configs?.typescript === false,
|
|
8
8
|
"zod": options.configs?.zod === false,
|
|
9
9
|
"astro": options.configs?.astro === false,
|
|
10
|
+
"eslint-plugin-jsx-a11y-x": isEnabled(options.configs?.astro) && options.configs?.astro?.accessibility === false,
|
|
10
11
|
"react": options.configs?.react === false,
|
|
11
12
|
"next": options.configs?.next === false,
|
|
13
|
+
"@tanstack/react-router": isEnabled(options.configs?.tanstack) && options.configs?.tanstack?.router === false,
|
|
14
|
+
"@tanstack/react-start": isEnabled(options.configs?.tanstack) && options.configs?.tanstack?.start === false,
|
|
15
|
+
"@tanstack/react-query": isEnabled(options.configs?.tanstack) && options.configs?.tanstack?.query === false,
|
|
12
16
|
"vue": options.configs?.vue === false,
|
|
13
17
|
"nuxt": options.configs?.nuxt === false,
|
|
14
18
|
"@nuxt/ui": isEnabled(options.configs?.nuxt) && options.configs?.nuxt?.ui === false,
|
|
@@ -23,6 +27,7 @@ function enableDetectedConfigs(options) {
|
|
|
23
27
|
typescript: isPackageDetected("typescript", options),
|
|
24
28
|
zod: isPackageDetected("zod", options),
|
|
25
29
|
astro: isPackageDetected("astro", options),
|
|
30
|
+
eslintPluginJsxA11yX: isPackageDetected("eslint-plugin-jsx-a11y-x", options),
|
|
26
31
|
react: isPackageDetected("react", options),
|
|
27
32
|
next: isPackageDetected("next", options),
|
|
28
33
|
tanstackStart: isPackageDetected("@tanstack/react-start", options),
|
|
@@ -38,6 +43,8 @@ function enableDetectedConfigs(options) {
|
|
|
38
43
|
storybook: isPackageDetected("storybook", options),
|
|
39
44
|
playwright: isPackageDetected("@playwright/test", options)
|
|
40
45
|
};
|
|
46
|
+
options.autoDetectDeps ??= defaultOptions.autoDetectDeps;
|
|
47
|
+
options.env ??= defaultOptions.env;
|
|
41
48
|
options.configs ??= {};
|
|
42
49
|
options.configs.test ??= {};
|
|
43
50
|
options.configs.node ??= true;
|
|
@@ -50,7 +57,7 @@ function enableDetectedConfigs(options) {
|
|
|
50
57
|
options.configs.importX ??= true;
|
|
51
58
|
options.configs.stylistic ??= true;
|
|
52
59
|
options.configs.perfectionist ??= true;
|
|
53
|
-
options.configs.baseline ??= options.env === "browser";
|
|
60
|
+
options.configs.baseline ??= options.autoDetectDeps && options.env === "browser";
|
|
54
61
|
options.configs.typescript ??= autoDetectedPackages.typescript;
|
|
55
62
|
options.configs.zod ??= autoDetectedPackages.zod;
|
|
56
63
|
options.configs.astro ??= autoDetectedPackages.astro;
|
|
@@ -80,18 +87,22 @@ function enableDetectedConfigs(options) {
|
|
|
80
87
|
options.configs.vue = options.configs.vue === true ? {} : options.configs.vue;
|
|
81
88
|
options.configs.vue.blockLang = { script: "ts" };
|
|
82
89
|
}
|
|
83
|
-
if (options.configs.tanstack) {
|
|
84
|
-
if (options.configs.tanstack === true) options.configs.tanstack = {};
|
|
85
|
-
options.configs.tanstack.start ??= autoDetectedPackages.tanstackStart;
|
|
86
|
-
options.configs.tanstack.query ??= autoDetectedPackages.tanstackQuery;
|
|
87
|
-
options.configs.tanstack.router ??= autoDetectedPackages.tanstackRouter;
|
|
88
|
-
}
|
|
89
90
|
if (options.configs.nuxt) {
|
|
90
91
|
if (options.configs.nuxt === true) options.configs.nuxt = {};
|
|
91
92
|
options.configs.nuxt.ui ??= autoDetectedPackages.nuxtUI;
|
|
92
93
|
options.configs.nuxt.icon ??= autoDetectedPackages.nuxtIcon;
|
|
93
94
|
options.configs.nuxt.image ??= autoDetectedPackages.nuxtImage;
|
|
94
95
|
}
|
|
96
|
+
if (options.configs.astro) {
|
|
97
|
+
options.configs.astro = options.configs.astro === true ? {} : options.configs.astro;
|
|
98
|
+
options.configs.astro.accessibility ??= autoDetectedPackages.eslintPluginJsxA11yX;
|
|
99
|
+
}
|
|
100
|
+
if (options.configs.tanstack) {
|
|
101
|
+
if (options.configs.tanstack === true) options.configs.tanstack = {};
|
|
102
|
+
options.configs.tanstack.start ??= autoDetectedPackages.tanstackStart;
|
|
103
|
+
options.configs.tanstack.query ??= autoDetectedPackages.tanstackQuery;
|
|
104
|
+
options.configs.tanstack.router ??= autoDetectedPackages.tanstackRouter;
|
|
105
|
+
}
|
|
95
106
|
if (options.autoDetectDeps === "verbose") logDetectedPackages(explicitlyDisabledConfigs);
|
|
96
107
|
return options;
|
|
97
108
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -35,6 +35,7 @@ import { Linter } from "eslint";
|
|
|
35
35
|
* ],
|
|
36
36
|
* );
|
|
37
37
|
*/
|
|
38
|
+
declare function defineConfig(): Linter.Config[];
|
|
38
39
|
declare function defineConfig(options: Options): Linter.Config[];
|
|
39
40
|
declare function defineConfig(configs: Linter.Config[]): Linter.Config[];
|
|
40
41
|
declare function defineConfig(options: Options, configs: Linter.Config[]): Linter.Config[];
|
package/dist/rules/astro.mjs
CHANGED
|
@@ -1,60 +1,67 @@
|
|
|
1
|
+
import { defaultOptions } from "../helpers/options/defaultOptions.mjs";
|
|
1
2
|
import { isEnabled } from "../utils/isEnabled.mjs";
|
|
2
3
|
//#region src/rules/astro.ts
|
|
3
|
-
const astroRules = {
|
|
4
|
-
"astro/missing-client-only-directive-value": "error",
|
|
5
|
-
"astro/no-conflict-set-directives": "error",
|
|
6
|
-
"astro/no-deprecated-astro-canonicalurl": "error",
|
|
7
|
-
"astro/no-deprecated-astro-fetchcontent": "error",
|
|
8
|
-
"astro/no-deprecated-astro-resolve": "error",
|
|
9
|
-
"astro/no-deprecated-getentrybyslug": "error",
|
|
10
|
-
"astro/no-exports-from-components": "error",
|
|
11
|
-
"astro/no-prerender-export-outside-pages": "error",
|
|
12
|
-
"astro/no-unused-define-vars-in-style": "warn",
|
|
13
|
-
"astro/no-set-html-directive": "warn",
|
|
14
|
-
"astro/no-unsafe-inline-scripts": "warn",
|
|
15
|
-
"astro/no-set-text-directive": "warn",
|
|
16
|
-
"astro/no-unused-css-selector": "warn",
|
|
17
|
-
"astro/prefer-class-list-directive": "warn",
|
|
18
|
-
"astro/prefer-split-class-list": "warn",
|
|
19
|
-
"astro/jsx-a11y/alt-text": "error",
|
|
20
|
-
"astro/jsx-a11y/anchor-ambiguous-text": "warn",
|
|
21
|
-
"astro/jsx-a11y/anchor-has-content": "warn",
|
|
22
|
-
"astro/jsx-a11y/anchor-is-valid": "error",
|
|
23
|
-
"astro/jsx-a11y/aria-activedescendant-has-tabindex": "warn",
|
|
24
|
-
"astro/jsx-a11y/aria-props": "error",
|
|
25
|
-
"astro/jsx-a11y/aria-proptypes": "error",
|
|
26
|
-
"astro/jsx-a11y/aria-role": "warn",
|
|
27
|
-
"astro/jsx-a11y/aria-unsupported-elements": "error",
|
|
28
|
-
"astro/jsx-a11y/autocomplete-valid": "error",
|
|
29
|
-
"astro/jsx-a11y/click-events-have-key-events": "warn",
|
|
30
|
-
"astro/jsx-a11y/control-has-associated-label": "warn",
|
|
31
|
-
"astro/jsx-a11y/heading-has-content": "warn",
|
|
32
|
-
"astro/jsx-a11y/html-has-lang": "error",
|
|
33
|
-
"astro/jsx-a11y/iframe-has-title": "warn",
|
|
34
|
-
"astro/jsx-a11y/img-redundant-alt": "warn",
|
|
35
|
-
"astro/jsx-a11y/interactive-supports-focus": "warn",
|
|
36
|
-
"astro/jsx-a11y/label-has-associated-control": "warn",
|
|
37
|
-
"astro/jsx-a11y/lang": "error",
|
|
38
|
-
"astro/jsx-a11y/media-has-caption": "warn",
|
|
39
|
-
"astro/jsx-a11y/mouse-events-have-key-events": "warn",
|
|
40
|
-
"astro/jsx-a11y/no-access-key": "warn",
|
|
41
|
-
"astro/jsx-a11y/no-aria-hidden-on-focusable": "error",
|
|
42
|
-
"astro/jsx-a11y/no-autofocus": "warn",
|
|
43
|
-
"astro/jsx-a11y/no-distracting-elements": "warn",
|
|
44
|
-
"astro/jsx-a11y/no-interactive-element-to-noninteractive-role": "warn",
|
|
45
|
-
"astro/jsx-a11y/no-noninteractive-element-interactions": "warn",
|
|
46
|
-
"astro/jsx-a11y/no-noninteractive-element-to-interactive-role": "warn",
|
|
47
|
-
"astro/jsx-a11y/no-noninteractive-tabindex": "warn",
|
|
48
|
-
"astro/jsx-a11y/no-redundant-roles": "warn",
|
|
49
|
-
"astro/jsx-a11y/no-static-element-interactions": "warn",
|
|
50
|
-
"astro/jsx-a11y/prefer-tag-over-role": "warn",
|
|
51
|
-
"astro/jsx-a11y/role-has-required-aria-props": "warn",
|
|
52
|
-
"astro/jsx-a11y/role-supports-aria-props": "warn",
|
|
53
|
-
"astro/jsx-a11y/scope": "error",
|
|
54
|
-
"astro/jsx-a11y/tabindex-no-positive": "warn"
|
|
55
|
-
};
|
|
56
4
|
function getAstroRules(options) {
|
|
57
|
-
const { importX, stylistic } = options.configs;
|
|
5
|
+
const { astro, importX, stylistic } = options.configs;
|
|
6
|
+
const { semi } = isEnabled(stylistic) ? stylistic : defaultOptions.configs.stylistic;
|
|
7
|
+
const { accessibility } = isEnabled(astro) ? astro : defaultOptions.configs.astro;
|
|
8
|
+
const astroRules = {
|
|
9
|
+
"astro/missing-client-only-directive-value": "error",
|
|
10
|
+
"astro/no-conflict-set-directives": "error",
|
|
11
|
+
"astro/no-deprecated-astro-canonicalurl": "error",
|
|
12
|
+
"astro/no-deprecated-astro-fetchcontent": "error",
|
|
13
|
+
"astro/no-deprecated-astro-resolve": "error",
|
|
14
|
+
"astro/no-deprecated-getentrybyslug": "error",
|
|
15
|
+
"astro/no-exports-from-components": "error",
|
|
16
|
+
"astro/no-prerender-export-outside-pages": "error",
|
|
17
|
+
"astro/no-unused-define-vars-in-style": "warn",
|
|
18
|
+
"astro/no-set-html-directive": "warn",
|
|
19
|
+
"astro/no-unsafe-inline-scripts": "warn",
|
|
20
|
+
"astro/no-set-text-directive": "warn",
|
|
21
|
+
"astro/no-unused-css-selector": "warn",
|
|
22
|
+
"astro/prefer-class-list-directive": "warn",
|
|
23
|
+
"astro/prefer-split-class-list": "warn",
|
|
24
|
+
"astro/semi": ["warn", semi]
|
|
25
|
+
};
|
|
26
|
+
const astroJsxA11yRules = {
|
|
27
|
+
"astro/jsx-a11y/alt-text": "error",
|
|
28
|
+
"astro/jsx-a11y/anchor-ambiguous-text": "warn",
|
|
29
|
+
"astro/jsx-a11y/anchor-has-content": "warn",
|
|
30
|
+
"astro/jsx-a11y/anchor-is-valid": "error",
|
|
31
|
+
"astro/jsx-a11y/aria-activedescendant-has-tabindex": "warn",
|
|
32
|
+
"astro/jsx-a11y/aria-props": "error",
|
|
33
|
+
"astro/jsx-a11y/aria-proptypes": "error",
|
|
34
|
+
"astro/jsx-a11y/aria-role": "warn",
|
|
35
|
+
"astro/jsx-a11y/aria-unsupported-elements": "error",
|
|
36
|
+
"astro/jsx-a11y/autocomplete-valid": "error",
|
|
37
|
+
"astro/jsx-a11y/click-events-have-key-events": "warn",
|
|
38
|
+
"astro/jsx-a11y/control-has-associated-label": "warn",
|
|
39
|
+
"astro/jsx-a11y/heading-has-content": "warn",
|
|
40
|
+
"astro/jsx-a11y/html-has-lang": "error",
|
|
41
|
+
"astro/jsx-a11y/iframe-has-title": "warn",
|
|
42
|
+
"astro/jsx-a11y/img-redundant-alt": "warn",
|
|
43
|
+
"astro/jsx-a11y/interactive-supports-focus": "warn",
|
|
44
|
+
"astro/jsx-a11y/label-has-associated-control": "warn",
|
|
45
|
+
"astro/jsx-a11y/lang": "error",
|
|
46
|
+
"astro/jsx-a11y/media-has-caption": "warn",
|
|
47
|
+
"astro/jsx-a11y/mouse-events-have-key-events": "warn",
|
|
48
|
+
"astro/jsx-a11y/no-access-key": "warn",
|
|
49
|
+
"astro/jsx-a11y/no-aria-hidden-on-focusable": "error",
|
|
50
|
+
"astro/jsx-a11y/no-autofocus": "warn",
|
|
51
|
+
"astro/jsx-a11y/no-distracting-elements": "warn",
|
|
52
|
+
"astro/jsx-a11y/no-interactive-element-to-noninteractive-role": "warn",
|
|
53
|
+
"astro/jsx-a11y/no-noninteractive-element-interactions": "warn",
|
|
54
|
+
"astro/jsx-a11y/no-noninteractive-element-to-interactive-role": "warn",
|
|
55
|
+
"astro/jsx-a11y/no-noninteractive-tabindex": "warn",
|
|
56
|
+
"astro/jsx-a11y/no-redundant-roles": "warn",
|
|
57
|
+
"astro/jsx-a11y/no-static-element-interactions": "warn",
|
|
58
|
+
"astro/jsx-a11y/prefer-tag-over-role": "warn",
|
|
59
|
+
"astro/jsx-a11y/role-has-required-aria-props": "warn",
|
|
60
|
+
"astro/jsx-a11y/role-supports-aria-props": "warn",
|
|
61
|
+
"astro/jsx-a11y/scope": "error",
|
|
62
|
+
"astro/jsx-a11y/tabindex-no-positive": "warn"
|
|
63
|
+
};
|
|
64
|
+
if (isEnabled(accessibility)) Object.assign(astroRules, astroJsxA11yRules);
|
|
58
65
|
if (isEnabled(importX)) astroRules["import-x/exports-last"] = "off";
|
|
59
66
|
if (isEnabled(stylistic)) astroRules["@stylistic/jsx-one-expression-per-line"] = "off";
|
|
60
67
|
return astroRules;
|
package/dist/rules/baseline.mjs
CHANGED
|
@@ -14,7 +14,7 @@ function getBaselineRules(options) {
|
|
|
14
14
|
baseline,
|
|
15
15
|
includeWebApis: { preset: "auto" },
|
|
16
16
|
includeJsBuiltins: { preset: "auto" },
|
|
17
|
-
ignoreFeatures: userIgnoredFeatures,
|
|
17
|
+
ignoreFeatures: ["async-clipboard", ...userIgnoredFeatures],
|
|
18
18
|
ignoreNodeTypes: userIgnoredNodeTypes
|
|
19
19
|
}]
|
|
20
20
|
};
|
package/dist/rules/css.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defaultOptions } from "../helpers/options/defaultOptions.mjs";
|
|
2
2
|
import { isEnabled } from "../utils/isEnabled.mjs";
|
|
3
|
+
import { isTruthy } from "../utils/isTruthy.mjs";
|
|
3
4
|
//#region src/rules/css.ts
|
|
4
5
|
const allowedPhysicalUnits = [
|
|
5
6
|
"cqh",
|
|
@@ -46,7 +47,8 @@ const allowedPhysicalProperties = [
|
|
|
46
47
|
"contain-intrinsic-height"
|
|
47
48
|
];
|
|
48
49
|
function getCssRules(options) {
|
|
49
|
-
const { unicorn, tailwind, baseline } = options.configs;
|
|
50
|
+
const { css, vue, unicorn, tailwind, baseline } = options.configs;
|
|
51
|
+
const { allowedUnknownPseudoSelectors: userAllowedUnknownPseudoSelectors } = isEnabled(css) ? css : defaultOptions.configs.css;
|
|
50
52
|
const { allowedAtRules: userAllowedAtRules, allowedFunctions: userAllowedFunctions, allowedMediaConditions: userAllowedMediaConditions, allowedProperties: userAllowedProperties, allowedPropertyValues: userAllowedPropertyValues, allowedSelectors: userAllowedSelectors, allowedUnits: userAllowedUnits } = isEnabled(baseline) ? baseline.css : defaultOptions.configs.baseline.css;
|
|
51
53
|
const cssRules = {
|
|
52
54
|
"css/font-family-fallbacks": "warn",
|
|
@@ -82,15 +84,41 @@ function getCssRules(options) {
|
|
|
82
84
|
allowFunctions: userAllowedFunctions,
|
|
83
85
|
allowMediaConditions: userAllowedMediaConditions,
|
|
84
86
|
allowProperties: userAllowedProperties,
|
|
85
|
-
allowPropertyValues:
|
|
86
|
-
|
|
87
|
+
allowPropertyValues: {
|
|
88
|
+
"background-clip": ["text"],
|
|
89
|
+
...userAllowedPropertyValues
|
|
90
|
+
},
|
|
91
|
+
allowSelectors: ["selection", ...userAllowedSelectors],
|
|
87
92
|
allowUnits: userAllowedUnits
|
|
88
93
|
}] : "off"
|
|
89
94
|
};
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
const unicornRules = {
|
|
96
|
+
"unicorn/no-deprecated-css-features": "error",
|
|
97
|
+
"unicorn/no-duplicate-css-selectors": "warn",
|
|
98
|
+
"unicorn/no-duplicate-font-family-names": "error",
|
|
99
|
+
"unicorn/no-invalid-media-features": "error",
|
|
100
|
+
"unicorn/no-nesting-with-mixed-specificity": "warn",
|
|
101
|
+
"unicorn/no-redundant-nested-style-rules": "warn",
|
|
102
|
+
"unicorn/no-shorthand-property-overrides": "warn",
|
|
103
|
+
"unicorn/no-unknown-css-annotations": "error",
|
|
104
|
+
"unicorn/no-unknown-pseudo-selectors": ["error", { allow: [
|
|
105
|
+
"::-ms-reveal",
|
|
106
|
+
":-webkit-autofill",
|
|
107
|
+
"::-webkit-inner-spin-button",
|
|
108
|
+
"::-webkit-search-cancel-button",
|
|
109
|
+
"::-webkit-search-results-button",
|
|
110
|
+
...isEnabled(vue) ? [
|
|
111
|
+
":deep",
|
|
112
|
+
":global",
|
|
113
|
+
":slotted"
|
|
114
|
+
] : [],
|
|
115
|
+
...userAllowedUnknownPseudoSelectors
|
|
116
|
+
].filter(isTruthy) }],
|
|
117
|
+
"unicorn/no-unscoped-css-nesting-selector": isEnabled(tailwind) ? ["error", { scopingRootAtRules: ["utility", "custom-variant"] }] : "error",
|
|
118
|
+
"unicorn/prefer-explicit-viewport-units": "warn",
|
|
119
|
+
"unicorn/prefer-media-feature-range-syntax": "warn"
|
|
120
|
+
};
|
|
121
|
+
if (isEnabled(unicorn)) Object.assign(cssRules, unicornRules);
|
|
94
122
|
return cssRules;
|
|
95
123
|
}
|
|
96
124
|
//#endregion
|