@shayanthenerd/eslint-config 0.26.1 → 0.26.3
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 +27 -22
- package/dist/configs/react.mjs +2 -4
- package/dist/configs/vue.mjs +1 -5
- package/dist/helpers/isPackageDetected.mjs +5 -4
- package/dist/helpers/options/enableDetectedConfigs.mjs +33 -16
- package/dist/rules/html.mjs +1 -0
- package/dist/rules/javascript.mjs +1 -1
- package/dist/rules/node.mjs +1 -1
- package/dist/rules/packageJson.mjs +28 -0
- package/dist/rules/react.mjs +49 -44
- package/dist/rules/unicorn.mjs +21 -0
- package/dist/rules/vue.mjs +45 -3
- package/dist/types/eslint-schema.d.mts +524 -362
- package/dist/types/options/vue.d.mts +33 -2
- package/package.json +27 -27
- package/dist/rules/vueAccessibility.mjs +0 -47
- package/dist/types/options/vueAccessibility.d.mts +0 -38
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ ESLint configuration for enforcing best practices and maintaining a consistent c
|
|
|
6
6
|
- **Smart**: Context-aware linting with [automatic dependency detection](#automatic-dependency-detection) and _.gitignore_ recognition.
|
|
7
7
|
- **Comprehensive**: [Supports useful plugins](#plugin-support) for TypeScript, React & Next, Vue & Nuxt, Astro, Tailwind, and more.
|
|
8
8
|
- **Type-safe**: [Fully-typed and well-documented API](#api-reference) with `overrides` support for built-in configuration objects.
|
|
9
|
-
- **Modern**: Requires ESLint ^10.
|
|
9
|
+
- **Modern**: Requires ESLint ^10.6.0 and Node.js ^20.19.0 (ESM-only)
|
|
10
10
|
|
|
11
11
|
## Table of Contents
|
|
12
12
|
- [Plugin Support](#plugin-support)
|
|
@@ -25,40 +25,40 @@ ESLint configuration for enforcing best practices and maintaining a consistent c
|
|
|
25
25
|
|
|
26
26
|
## Plugin Support
|
|
27
27
|
Legend:
|
|
28
|
-
- ✅ Enabled by default
|
|
29
|
-
-
|
|
30
|
-
-
|
|
28
|
+
- ✅ — **Enabled** by default
|
|
29
|
+
- ⚙️ — **Opt-in** (requires manual configuration)
|
|
30
|
+
- 🔍 — [**Automatically detected**](#automatic-dependency-detection) (based on project dependencies)
|
|
31
31
|
|
|
32
32
|
| Category | Activation |
|
|
33
33
|
| :---------------------------------------------------------------------------------------------------- | :--------: |
|
|
34
34
|
| **Languages** | |
|
|
35
35
|
| [JavaScript][eslint] | ✅ |
|
|
36
|
-
| [TypeScript][plugin-ts] |
|
|
36
|
+
| [TypeScript][plugin-ts] | 🔍 |
|
|
37
37
|
| [Markdown][plugin-md] | ✅ |
|
|
38
|
-
| [HTML][plugin-html] |
|
|
39
|
-
| [CSS][plugin-css] |
|
|
38
|
+
| [HTML][plugin-html] | ⚙️ |
|
|
39
|
+
| [CSS][plugin-css] | ⚙️ |
|
|
40
40
|
| **Formatting** | |
|
|
41
41
|
| [Stylistic][plugin-stylistic] | ✅ |
|
|
42
42
|
| [Perfectionist][plugin-perfectionist] | ✅ |
|
|
43
43
|
| **Frameworks & Libraries** | |
|
|
44
|
-
| [Astro][plugin-astro] ([jsx-accessibility][plugin-jsx-a11y]) |
|
|
45
|
-
| [React][plugin-react] ([jsx-accessibility][plugin-jsx-a11y], [@html-eslint/react][plugin-html-react]) |
|
|
46
|
-
| [Next][plugin-next] |
|
|
47
|
-
| [Vue & Nuxt][plugin-vue] ([vue-accessibility][plugin-vue-a11y]) |
|
|
48
|
-
| [Tailwind][plugin-tailwind] |
|
|
49
|
-
| [Zod & Zod Mini][plugin-zod] |
|
|
44
|
+
| [Astro][plugin-astro] ([jsx-accessibility][plugin-jsx-a11y]) | 🔍 |
|
|
45
|
+
| [React][plugin-react] ([jsx-accessibility][plugin-jsx-a11y], [@html-eslint/react][plugin-html-react]) | 🔍 |
|
|
46
|
+
| [Next][plugin-next] | 🔍 |
|
|
47
|
+
| [Vue & Nuxt][plugin-vue] ([vue-accessibility][plugin-vue-a11y]) | 🔍 |
|
|
48
|
+
| [Tailwind][plugin-tailwind] | ⚙️ |
|
|
49
|
+
| [Zod & Zod Mini][plugin-zod] | 🔍 |
|
|
50
50
|
| **Testing Tools** | |
|
|
51
|
-
| [Storybook][plugin-storybook] |
|
|
52
|
-
| [Vitest][plugin-vitest] |
|
|
53
|
-
| [Cypress][plugin-cypress] |
|
|
54
|
-
| [Playwright][plugin-playwright] |
|
|
51
|
+
| [Storybook][plugin-storybook] | 🔍 |
|
|
52
|
+
| [Vitest][plugin-vitest] | 🔍 |
|
|
53
|
+
| [Cypress][plugin-cypress] | 🔍 |
|
|
54
|
+
| [Playwright][plugin-playwright] | 🔍 |
|
|
55
55
|
| **Miscellaneous** | |
|
|
56
56
|
| [_package.json_][plugin-package-json] | ✅ |
|
|
57
57
|
| [Node][plugin-n] | ✅ |
|
|
58
58
|
| [Promises][plugin-promise] | ✅ |
|
|
59
59
|
| [Imports][plugin-import-x] | ✅ |
|
|
60
60
|
| [Unicorn][plugin-unicorn] | ✅ |
|
|
61
|
-
| [Baseline][plugin-baseline] |
|
|
61
|
+
| [Baseline][plugin-baseline] | 🔍 |
|
|
62
62
|
|
|
63
63
|
## Installation and Configuration
|
|
64
64
|
1. Install the package and ESLint as dev dependencies:
|
|
@@ -230,7 +230,15 @@ By default, the plugin uses GitHub Flavored Markdown (GFM). You can [switch to C
|
|
|
230
230
|
Some rules depend on the specified Node.js version. Visit the documentation for [version-resolution options and project-specific configurations](https://github.com/eslint-community/eslint-plugin-n#configured-nodejs-version-range).
|
|
231
231
|
|
|
232
232
|
## IDE Support
|
|
233
|
-
Install the VS Code extensions for [ESLint][extension-eslint] and [Prettier][extension-prettier].
|
|
233
|
+
Install the VS Code extensions for [ESLint][extension-eslint] and [Prettier][extension-prettier].
|
|
234
|
+
> [!TIP]
|
|
235
|
+
> In case you're using PNPM without `shamefullyHoist: true`, add the following to your _pnpm-workspace.yaml_ and run `pnpm install --yes` so ESLint's VS Code extension works as expected:
|
|
236
|
+
> ```yaml title="pnpm-workspace.yaml"
|
|
237
|
+
> publicHoistPattern:
|
|
238
|
+
> - '*eslint*'
|
|
239
|
+
> ```
|
|
240
|
+
|
|
241
|
+
You can also add the following to your _.vscode/settings.json_:
|
|
234
242
|
```jsonc title=".vscode/settings.json"
|
|
235
243
|
{
|
|
236
244
|
/* Enforce Unix-like line endings (LF). */
|
|
@@ -286,9 +294,6 @@ Install the VS Code extensions for [ESLint][extension-eslint] and [Prettier][ext
|
|
|
286
294
|
}
|
|
287
295
|
```
|
|
288
296
|
|
|
289
|
-
> [!TIP]
|
|
290
|
-
> These settings match the default behavior of this configuration. If you've customized any formatting or stylistic rules, update the corresponding editor settings to keep them consistent.
|
|
291
|
-
|
|
292
297
|
## Formatting
|
|
293
298
|
This configuration uses [ESLint Stylistic][plugin-stylistic] to format:
|
|
294
299
|
- JavaScript and TypeScript (_js_, _cjs_, _mjs_, _jsx_, _ts_, _cts_, _mts_, _tsx_),
|
package/dist/configs/react.mjs
CHANGED
|
@@ -16,11 +16,9 @@ function getReactConfig(options) {
|
|
|
16
16
|
files: [globs.src],
|
|
17
17
|
plugins: {
|
|
18
18
|
"@eslint-react": eslintPluginReact,
|
|
19
|
+
"@html-eslint/react": eslintPluginHtmlReact,
|
|
19
20
|
...isEnabled(unicorn) && { unicorn: eslintPluginUnicorn },
|
|
20
|
-
...isEnabled(accessibility) && {
|
|
21
|
-
"jsx-a11y": eslintPluginJsxA11y,
|
|
22
|
-
"@html-eslint/react": eslintPluginHtmlReact
|
|
23
|
-
}
|
|
21
|
+
...isEnabled(accessibility) && { "jsx-a11y": eslintPluginJsxA11y }
|
|
24
22
|
},
|
|
25
23
|
rules: getReactRules(options)
|
|
26
24
|
}, overrides);
|
package/dist/configs/vue.mjs
CHANGED
|
@@ -2,7 +2,6 @@ import { globs } from "../helpers/globs.mjs";
|
|
|
2
2
|
import { isEnabled } from "../utils/isEnabled.mjs";
|
|
3
3
|
import { defaultOptions } from "../helpers/options/defaultOptions.mjs";
|
|
4
4
|
import { getVueRules } from "../rules/vue.mjs";
|
|
5
|
-
import { getVueAccessibilityRules } from "../rules/vueAccessibility.mjs";
|
|
6
5
|
import { mergeConfigs } from "eslint-flat-config-utils";
|
|
7
6
|
import eslintPluginVue from "eslint-plugin-vue";
|
|
8
7
|
import { parser } from "typescript-eslint";
|
|
@@ -30,10 +29,7 @@ function getVueConfig(options) {
|
|
|
30
29
|
vueFeatures: { filter: false }
|
|
31
30
|
}
|
|
32
31
|
},
|
|
33
|
-
rules:
|
|
34
|
-
...getVueRules(options),
|
|
35
|
-
...isVueAccessibilityEnabled && getVueAccessibilityRules(options)
|
|
36
|
-
}
|
|
32
|
+
rules: getVueRules(options)
|
|
37
33
|
}, overrides);
|
|
38
34
|
}
|
|
39
35
|
//#endregion
|
|
@@ -4,10 +4,11 @@ import { styleText } from "node:util";
|
|
|
4
4
|
import { isPackageExists } from "local-pkg";
|
|
5
5
|
//#region src/helpers/isPackageDetected.ts
|
|
6
6
|
const detectedPackages = [];
|
|
7
|
-
function logDetectedPackages() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
function logDetectedPackages(disabledConfigs) {
|
|
8
|
+
const nonDisabledDetectedPackages = detectedPackages.filter((packageName) => !disabledConfigs[packageName]);
|
|
9
|
+
if (nonDisabledDetectedPackages.length > 0) {
|
|
10
|
+
nonDisabledDetectedPackages.sort();
|
|
11
|
+
console.info(`${styleText("green", "✔")} ESLint integrations enabled via dependency detection:`, nonDisabledDetectedPackages.map((packageName) => styleText("blue", packageName)).join(", "));
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
function isPackageDetected(packageName, options) {
|
|
@@ -1,7 +1,24 @@
|
|
|
1
|
+
import { isEnabled } from "../../utils/isEnabled.mjs";
|
|
1
2
|
import { isPackageDetected, logDetectedPackages } from "../isPackageDetected.mjs";
|
|
2
3
|
//#region src/helpers/options/enableDetectedConfigs.ts
|
|
3
4
|
function enableDetectedConfigs(options) {
|
|
4
|
-
const
|
|
5
|
+
const explicitlyDisabledConfigs = {
|
|
6
|
+
"typescript": options.configs?.typescript === false,
|
|
7
|
+
"zod": options.configs?.zod === false,
|
|
8
|
+
"astro": options.configs?.astro === false,
|
|
9
|
+
"react": options.configs?.react === false,
|
|
10
|
+
"next": options.configs?.next === false,
|
|
11
|
+
"vue": options.configs?.vue === false,
|
|
12
|
+
"nuxt": options.configs?.nuxt === false,
|
|
13
|
+
"@nuxt/ui": isEnabled(options.configs?.nuxt) && options.configs?.nuxt?.ui === false,
|
|
14
|
+
"@nuxt/icon": isEnabled(options.configs?.nuxt) && options.configs?.nuxt?.icon === false,
|
|
15
|
+
"@nuxt/image": isEnabled(options.configs?.nuxt) && options.configs?.nuxt?.image === false,
|
|
16
|
+
"vitest": options.configs?.test?.vitest === false,
|
|
17
|
+
"cypress": options.configs?.test?.cypress === false,
|
|
18
|
+
"storybook": options.configs?.test?.storybook === false,
|
|
19
|
+
"@playwright/test": options.configs?.test?.playwright === false
|
|
20
|
+
};
|
|
21
|
+
const autoDetectedPackages = {
|
|
5
22
|
typescript: isPackageDetected("typescript", options),
|
|
6
23
|
zod: isPackageDetected("zod", options),
|
|
7
24
|
astro: isPackageDetected("astro", options),
|
|
@@ -30,17 +47,17 @@ function enableDetectedConfigs(options) {
|
|
|
30
47
|
options.configs.stylistic ??= true;
|
|
31
48
|
options.configs.perfectionist ??= true;
|
|
32
49
|
options.configs.useBaseline ??= options.env === "browser";
|
|
33
|
-
options.configs.typescript ??=
|
|
34
|
-
options.configs.zod ??=
|
|
35
|
-
options.configs.astro ??=
|
|
36
|
-
options.configs.vue ??=
|
|
37
|
-
options.configs.nuxt ??=
|
|
38
|
-
options.configs.react ??=
|
|
39
|
-
options.configs.next ??=
|
|
40
|
-
options.configs.test.vitest ??=
|
|
41
|
-
options.configs.test.cypress ??=
|
|
42
|
-
options.configs.test.storybook ??=
|
|
43
|
-
options.configs.test.playwright ??=
|
|
50
|
+
options.configs.typescript ??= autoDetectedPackages.typescript;
|
|
51
|
+
options.configs.zod ??= autoDetectedPackages.zod;
|
|
52
|
+
options.configs.astro ??= autoDetectedPackages.astro;
|
|
53
|
+
options.configs.vue ??= autoDetectedPackages.vue;
|
|
54
|
+
options.configs.nuxt ??= autoDetectedPackages.nuxt;
|
|
55
|
+
options.configs.react ??= autoDetectedPackages.react;
|
|
56
|
+
options.configs.next ??= autoDetectedPackages.next;
|
|
57
|
+
options.configs.test.vitest ??= autoDetectedPackages.vitest;
|
|
58
|
+
options.configs.test.cypress ??= autoDetectedPackages.cypress;
|
|
59
|
+
options.configs.test.storybook ??= autoDetectedPackages.storybook;
|
|
60
|
+
options.configs.test.playwright ??= autoDetectedPackages.playwright;
|
|
44
61
|
options.tsConfig ??= options.configs.typescript ? {
|
|
45
62
|
rootDir: ".",
|
|
46
63
|
filename: "tsconfig.json"
|
|
@@ -51,11 +68,11 @@ function enableDetectedConfigs(options) {
|
|
|
51
68
|
}
|
|
52
69
|
if (options.configs.nuxt) {
|
|
53
70
|
if (options.configs.nuxt === true) options.configs.nuxt = {};
|
|
54
|
-
options.configs.nuxt.ui ??=
|
|
55
|
-
options.configs.nuxt.icon ??=
|
|
56
|
-
options.configs.nuxt.image ??=
|
|
71
|
+
options.configs.nuxt.ui ??= autoDetectedPackages.nuxtUI;
|
|
72
|
+
options.configs.nuxt.icon ??= autoDetectedPackages.nuxtIcon;
|
|
73
|
+
options.configs.nuxt.image ??= autoDetectedPackages.nuxtImage;
|
|
57
74
|
}
|
|
58
|
-
if (options.autoDetectDeps === "verbose") logDetectedPackages();
|
|
75
|
+
if (options.autoDetectDeps === "verbose") logDetectedPackages(explicitlyDisabledConfigs);
|
|
59
76
|
return options;
|
|
60
77
|
}
|
|
61
78
|
//#endregion
|
package/dist/rules/html.mjs
CHANGED
|
@@ -12,6 +12,7 @@ function getHtmlRules(options) {
|
|
|
12
12
|
"@html-eslint/no-duplicate-id": "error",
|
|
13
13
|
"@html-eslint/no-duplicate-in-head": "error",
|
|
14
14
|
"@html-eslint/no-ineffective-attrs": "warn",
|
|
15
|
+
"@html-eslint/no-inline-styles": ["warn", { allowExpressions: true }],
|
|
15
16
|
"@html-eslint/no-invalid-attr-value": "error",
|
|
16
17
|
"@html-eslint/no-invalid-entity": "error",
|
|
17
18
|
"@html-eslint/no-nested-interactive": "error",
|
|
@@ -16,7 +16,7 @@ function getJavaScriptRules(options) {
|
|
|
16
16
|
"no-compare-neg-zero": "error",
|
|
17
17
|
"no-cond-assign": "error",
|
|
18
18
|
"no-const-assign": isTypeScriptEnabled ? "off" : "error",
|
|
19
|
-
"no-constant-binary-expression": "error",
|
|
19
|
+
"no-constant-binary-expression": ["error", { checkRelationalComparisons: true }],
|
|
20
20
|
"no-constant-condition": "error",
|
|
21
21
|
"no-constructor-return": "error",
|
|
22
22
|
"no-control-regex": "error",
|
package/dist/rules/node.mjs
CHANGED
|
@@ -15,7 +15,7 @@ function getNodeRules(options) {
|
|
|
15
15
|
"n/no-unpublished-import": "error",
|
|
16
16
|
"n/no-unsupported-features/es-builtins": "error",
|
|
17
17
|
"n/no-unsupported-features/es-syntax": "error",
|
|
18
|
-
"n/no-unsupported-features/node-builtins": "error",
|
|
18
|
+
"n/no-unsupported-features/node-builtins": ["error", { allowExperimental: true }],
|
|
19
19
|
"n/prefer-global/buffer": "warn",
|
|
20
20
|
"n/prefer-global/console": "warn",
|
|
21
21
|
"n/prefer-global/crypto": "warn",
|
|
@@ -64,9 +64,28 @@ const packageJsonRules = {
|
|
|
64
64
|
] }],
|
|
65
65
|
"package-json/scripts-name-casing": "warn",
|
|
66
66
|
"package-json/sort-collections": ["warn", [
|
|
67
|
+
{
|
|
68
|
+
key: "author",
|
|
69
|
+
order: [
|
|
70
|
+
"name",
|
|
71
|
+
"email",
|
|
72
|
+
"url"
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
key: "bugs",
|
|
77
|
+
order: ["email", "url"]
|
|
78
|
+
},
|
|
67
79
|
"config",
|
|
68
80
|
"dependencies",
|
|
81
|
+
"devEngines",
|
|
69
82
|
"devDependencies",
|
|
83
|
+
"directories",
|
|
84
|
+
{
|
|
85
|
+
key: "dist",
|
|
86
|
+
order: ["shasum", "tarball"]
|
|
87
|
+
},
|
|
88
|
+
"engines",
|
|
70
89
|
"exports",
|
|
71
90
|
"husky",
|
|
72
91
|
"husky.hooks",
|
|
@@ -76,6 +95,15 @@ const packageJsonRules = {
|
|
|
76
95
|
"overrides",
|
|
77
96
|
"peerDependencies",
|
|
78
97
|
"peerDependenciesMeta",
|
|
98
|
+
{
|
|
99
|
+
key: "repository",
|
|
100
|
+
order: [
|
|
101
|
+
"type",
|
|
102
|
+
"url",
|
|
103
|
+
"directory"
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
"release",
|
|
79
107
|
"simple-git-hooks"
|
|
80
108
|
]],
|
|
81
109
|
"package-json/specify-peers-locally": "warn",
|
package/dist/rules/react.mjs
CHANGED
|
@@ -16,7 +16,48 @@ const commonCallees = [
|
|
|
16
16
|
function getReactRules(options) {
|
|
17
17
|
const { react, unicorn, tailwind, useBaseline } = options.configs;
|
|
18
18
|
const { imageComponents: userImageComponents, anchorComponents: userAnchorComponents, headingComponents: userHeadingComponents } = isEnabled(react) && isEnabled(react.accessibility) ? react.accessibility : defaultOptions.configs.react.accessibility;
|
|
19
|
-
const
|
|
19
|
+
const jsxA11yRules = {
|
|
20
|
+
"jsx-a11y/alt-text": ["error", { img: userImageComponents }],
|
|
21
|
+
"jsx-a11y/anchor-ambiguous-text": "warn",
|
|
22
|
+
"jsx-a11y/anchor-has-content": ["error", { components: userAnchorComponents }],
|
|
23
|
+
"jsx-a11y/anchor-is-valid": ["error", {
|
|
24
|
+
specialLink: ["to"],
|
|
25
|
+
components: userAnchorComponents
|
|
26
|
+
}],
|
|
27
|
+
"jsx-a11y/aria-activedescendant-has-tabindex": "error",
|
|
28
|
+
"jsx-a11y/aria-props": "error",
|
|
29
|
+
"jsx-a11y/aria-proptypes": "error",
|
|
30
|
+
"jsx-a11y/aria-role": "error",
|
|
31
|
+
"jsx-a11y/aria-unsupported-elements": "error",
|
|
32
|
+
"jsx-a11y/autocomplete-valid": "error",
|
|
33
|
+
"jsx-a11y/click-events-have-key-events": "error",
|
|
34
|
+
"jsx-a11y/control-has-associated-label": "error",
|
|
35
|
+
"jsx-a11y/heading-has-content": ["error", { components: userHeadingComponents }],
|
|
36
|
+
"jsx-a11y/html-has-lang": "error",
|
|
37
|
+
"jsx-a11y/iframe-has-title": "error",
|
|
38
|
+
"jsx-a11y/img-redundant-alt": ["error", { components: userImageComponents }],
|
|
39
|
+
"jsx-a11y/interactive-supports-focus": "error",
|
|
40
|
+
"jsx-a11y/label-has-associated-control": "error",
|
|
41
|
+
"jsx-a11y/lang": "error",
|
|
42
|
+
"jsx-a11y/media-has-caption": "error",
|
|
43
|
+
"jsx-a11y/mouse-events-have-key-events": "error",
|
|
44
|
+
"jsx-a11y/no-access-key": "warn",
|
|
45
|
+
"jsx-a11y/no-aria-hidden-on-focusable": "error",
|
|
46
|
+
"jsx-a11y/no-autofocus": "warn",
|
|
47
|
+
"jsx-a11y/no-distracting-elements": "warn",
|
|
48
|
+
"jsx-a11y/no-interactive-element-to-noninteractive-role": "error",
|
|
49
|
+
"jsx-a11y/no-noninteractive-element-interactions": "error",
|
|
50
|
+
"jsx-a11y/no-noninteractive-element-to-interactive-role": "error",
|
|
51
|
+
"jsx-a11y/no-noninteractive-tabindex": "error",
|
|
52
|
+
"jsx-a11y/no-redundant-roles": "warn",
|
|
53
|
+
"jsx-a11y/no-static-element-interactions": "warn",
|
|
54
|
+
"jsx-a11y/prefer-tag-over-role": "warn",
|
|
55
|
+
"jsx-a11y/role-has-required-aria-props": "warn",
|
|
56
|
+
"jsx-a11y/role-supports-aria-props": "warn",
|
|
57
|
+
"jsx-a11y/scope": "error",
|
|
58
|
+
"jsx-a11y/tabindex-no-positive": "error"
|
|
59
|
+
};
|
|
60
|
+
const reactAndHtmlReactRules = {
|
|
20
61
|
/*** @eslint/react ***/
|
|
21
62
|
"@eslint-react/error-boundaries": "error",
|
|
22
63
|
"@eslint-react/exhaustive-deps": "error",
|
|
@@ -103,46 +144,6 @@ function getReactRules(options) {
|
|
|
103
144
|
"@eslint-react/naming-convention-context-name": "warn",
|
|
104
145
|
"@eslint-react/naming-convention-id-name": "warn",
|
|
105
146
|
"@eslint-react/naming-convention-ref-name": "warn",
|
|
106
|
-
/*** jsx-a11y ***/
|
|
107
|
-
"jsx-a11y/alt-text": ["error", { img: userImageComponents }],
|
|
108
|
-
"jsx-a11y/anchor-ambiguous-text": "warn",
|
|
109
|
-
"jsx-a11y/anchor-has-content": ["error", { components: userAnchorComponents }],
|
|
110
|
-
"jsx-a11y/anchor-is-valid": ["error", {
|
|
111
|
-
specialLink: ["to"],
|
|
112
|
-
components: userAnchorComponents
|
|
113
|
-
}],
|
|
114
|
-
"jsx-a11y/aria-activedescendant-has-tabindex": "error",
|
|
115
|
-
"jsx-a11y/aria-props": "error",
|
|
116
|
-
"jsx-a11y/aria-proptypes": "error",
|
|
117
|
-
"jsx-a11y/aria-role": "error",
|
|
118
|
-
"jsx-a11y/aria-unsupported-elements": "error",
|
|
119
|
-
"jsx-a11y/autocomplete-valid": "error",
|
|
120
|
-
"jsx-a11y/click-events-have-key-events": "error",
|
|
121
|
-
"jsx-a11y/control-has-associated-label": "error",
|
|
122
|
-
"jsx-a11y/heading-has-content": ["error", { components: userHeadingComponents }],
|
|
123
|
-
"jsx-a11y/html-has-lang": "error",
|
|
124
|
-
"jsx-a11y/iframe-has-title": "error",
|
|
125
|
-
"jsx-a11y/img-redundant-alt": ["error", { components: userImageComponents }],
|
|
126
|
-
"jsx-a11y/interactive-supports-focus": "error",
|
|
127
|
-
"jsx-a11y/label-has-associated-control": "error",
|
|
128
|
-
"jsx-a11y/lang": "error",
|
|
129
|
-
"jsx-a11y/media-has-caption": "error",
|
|
130
|
-
"jsx-a11y/mouse-events-have-key-events": "error",
|
|
131
|
-
"jsx-a11y/no-access-key": "warn",
|
|
132
|
-
"jsx-a11y/no-aria-hidden-on-focusable": "error",
|
|
133
|
-
"jsx-a11y/no-autofocus": "warn",
|
|
134
|
-
"jsx-a11y/no-distracting-elements": "warn",
|
|
135
|
-
"jsx-a11y/no-interactive-element-to-noninteractive-role": "error",
|
|
136
|
-
"jsx-a11y/no-noninteractive-element-interactions": "error",
|
|
137
|
-
"jsx-a11y/no-noninteractive-element-to-interactive-role": "error",
|
|
138
|
-
"jsx-a11y/no-noninteractive-tabindex": "error",
|
|
139
|
-
"jsx-a11y/no-redundant-roles": "warn",
|
|
140
|
-
"jsx-a11y/no-static-element-interactions": "warn",
|
|
141
|
-
"jsx-a11y/prefer-tag-over-role": "warn",
|
|
142
|
-
"jsx-a11y/role-has-required-aria-props": "warn",
|
|
143
|
-
"jsx-a11y/role-supports-aria-props": "warn",
|
|
144
|
-
"jsx-a11y/scope": "error",
|
|
145
|
-
"jsx-a11y/tabindex-no-positive": "error",
|
|
146
147
|
/*** @html-eslint/react ***/
|
|
147
148
|
"@html-eslint/react/no-invalid-attr-value": "error",
|
|
148
149
|
"@html-eslint/react/use-baseline": isEnabled(useBaseline) ? ["warn", { available: useBaseline.baseline }] : "off",
|
|
@@ -152,9 +153,13 @@ function getReactRules(options) {
|
|
|
152
153
|
"@html-eslint/react/classname-spacing": ["warn", { callees: commonCallees }],
|
|
153
154
|
"@html-eslint/react/no-duplicate-classname": ["warn", { callees: commonCallees }]
|
|
154
155
|
};
|
|
155
|
-
if (isEnabled(tailwind))
|
|
156
|
-
if (isEnabled(unicorn))
|
|
157
|
-
|
|
156
|
+
if (isEnabled(tailwind)) reactAndHtmlReactRules["better-tailwindcss/no-duplicate-classes"] = "off";
|
|
157
|
+
if (isEnabled(unicorn)) reactAndHtmlReactRules["unicorn/no-invalid-file-input-accept"] = "error";
|
|
158
|
+
const isReactAccessibilityEnabled = isEnabled(react) && isEnabled(react.accessibility);
|
|
159
|
+
return {
|
|
160
|
+
...reactAndHtmlReactRules,
|
|
161
|
+
...isReactAccessibilityEnabled && jsxA11yRules
|
|
162
|
+
};
|
|
158
163
|
}
|
|
159
164
|
//#endregion
|
|
160
165
|
export { getReactRules };
|
package/dist/rules/unicorn.mjs
CHANGED
|
@@ -14,6 +14,7 @@ const unicornRules = {
|
|
|
14
14
|
"unicorn/consistent-json-file-read": "error",
|
|
15
15
|
"unicorn/consistent-optional-chaining": "warn",
|
|
16
16
|
"unicorn/consistent-template-literal-escape": "warn",
|
|
17
|
+
"unicorn/consistent-tuple-labels": "warn",
|
|
17
18
|
"unicorn/custom-error-definition": "error",
|
|
18
19
|
"unicorn/dom-node-dataset": "warn",
|
|
19
20
|
"unicorn/empty-brace-spaces": "warn",
|
|
@@ -32,6 +33,7 @@ const unicornRules = {
|
|
|
32
33
|
"unicorn/no-array-from-fill": "warn",
|
|
33
34
|
"unicorn/no-array-method-this-argument": "warn",
|
|
34
35
|
"unicorn/no-array-sort-for-min-max": "warn",
|
|
36
|
+
"unicorn/no-async-promise-finally": "warn",
|
|
35
37
|
"unicorn/no-await-expression-member": "warn",
|
|
36
38
|
"unicorn/no-await-in-promise-methods": "error",
|
|
37
39
|
"unicorn/no-blob-to-file": "warn",
|
|
@@ -59,7 +61,9 @@ const unicornRules = {
|
|
|
59
61
|
"unicorn/no-invalid-character-comparison": "error",
|
|
60
62
|
"unicorn/no-invalid-fetch-options": "error",
|
|
61
63
|
"unicorn/no-invalid-remove-event-listener": "error",
|
|
64
|
+
"unicorn/no-invalid-well-known-symbol-methods": "error",
|
|
62
65
|
"unicorn/no-late-current-target-access": "warn",
|
|
66
|
+
"unicorn/no-late-event-control": "error",
|
|
63
67
|
"unicorn/no-lonely-if": "warn",
|
|
64
68
|
"unicorn/no-loop-iterable-mutation": "warn",
|
|
65
69
|
"unicorn/no-magic-array-flat-depth": "warn",
|
|
@@ -75,6 +79,7 @@ const unicornRules = {
|
|
|
75
79
|
"unicorn/no-object-methods-with-collections": "warn",
|
|
76
80
|
"unicorn/no-optional-chaining-on-undeclared-variable": "error",
|
|
77
81
|
"unicorn/no-redundant-comparison": "warn",
|
|
82
|
+
"unicorn/no-return-array-push": "warn",
|
|
78
83
|
"unicorn/no-selector-as-dom-name": "error",
|
|
79
84
|
"unicorn/no-single-promise-in-promise-methods": "warn",
|
|
80
85
|
"unicorn/no-static-only-class": "warn",
|
|
@@ -87,6 +92,7 @@ const unicornRules = {
|
|
|
87
92
|
"unicorn/no-unnecessary-array-flat-depth": "warn",
|
|
88
93
|
"unicorn/no-unnecessary-array-splice-count": "warn",
|
|
89
94
|
"unicorn/no-unnecessary-boolean-comparison": "warn",
|
|
95
|
+
"unicorn/no-unnecessary-fetch-options": "warn",
|
|
90
96
|
"unicorn/no-unnecessary-global-this": "warn",
|
|
91
97
|
"unicorn/no-unnecessary-nested-ternary": "warn",
|
|
92
98
|
"unicorn/no-unnecessary-polyfills": "warn",
|
|
@@ -97,6 +103,7 @@ const unicornRules = {
|
|
|
97
103
|
"unicorn/no-unreadable-iife": "warn",
|
|
98
104
|
"unicorn/no-unreadable-new-expression": "warn",
|
|
99
105
|
"unicorn/no-unsafe-buffer-conversion": "warn",
|
|
106
|
+
"unicorn/no-unsafe-promise-all-settled-values": "error",
|
|
100
107
|
"unicorn/no-unsafe-property-key": "error",
|
|
101
108
|
"unicorn/no-unused-array-method-return": "warn",
|
|
102
109
|
"unicorn/no-unused-properties": "warn",
|
|
@@ -122,8 +129,11 @@ const unicornRules = {
|
|
|
122
129
|
"unicorn/no-zero-fractions": "warn",
|
|
123
130
|
"unicorn/number-literal-case": "warn",
|
|
124
131
|
"unicorn/numeric-separators-style": "warn",
|
|
132
|
+
"unicorn/prefer-abort-signal-any": "warn",
|
|
133
|
+
"unicorn/prefer-abort-signal-timeout": "warn",
|
|
125
134
|
"unicorn/prefer-add-event-listener": "warn",
|
|
126
135
|
"unicorn/prefer-add-event-listener-options": "warn",
|
|
136
|
+
"unicorn/prefer-aggregate-error": "warn",
|
|
127
137
|
"unicorn/prefer-array-flat": "warn",
|
|
128
138
|
"unicorn/prefer-array-flat-map": "warn",
|
|
129
139
|
"unicorn/prefer-array-from-async": "warn",
|
|
@@ -136,6 +146,7 @@ const unicornRules = {
|
|
|
136
146
|
"unicorn/prefer-at": "warn",
|
|
137
147
|
"unicorn/prefer-bigint-literals": "warn",
|
|
138
148
|
"unicorn/prefer-blob-reading-methods": "warn",
|
|
149
|
+
"unicorn/prefer-block-statement-over-iife": "warn",
|
|
139
150
|
"unicorn/prefer-boolean-return": "warn",
|
|
140
151
|
"unicorn/prefer-class-fields": "warn",
|
|
141
152
|
"unicorn/prefer-classlist-toggle": "warn",
|
|
@@ -147,12 +158,15 @@ const unicornRules = {
|
|
|
147
158
|
"unicorn/prefer-dom-node-append": "warn",
|
|
148
159
|
"unicorn/prefer-dom-node-html-methods": "warn",
|
|
149
160
|
"unicorn/prefer-dom-node-remove": "warn",
|
|
161
|
+
"unicorn/prefer-dom-node-replace-children": "warn",
|
|
150
162
|
"unicorn/prefer-dom-node-text-content": "warn",
|
|
163
|
+
"unicorn/prefer-error-is-error": "error",
|
|
151
164
|
"unicorn/prefer-event-target": "warn",
|
|
152
165
|
"unicorn/prefer-export-from": ["warn", { checkUsedVariables: false }],
|
|
153
166
|
"unicorn/prefer-flat-math-min-max": "warn",
|
|
154
167
|
"unicorn/prefer-get-or-insert-computed": "warn",
|
|
155
168
|
"unicorn/prefer-global-number-constants": "warn",
|
|
169
|
+
"unicorn/prefer-group-by": "warn",
|
|
156
170
|
"unicorn/prefer-has-check": "warn",
|
|
157
171
|
"unicorn/prefer-hoisting-branch-code": "warn",
|
|
158
172
|
"unicorn/prefer-https": "warn",
|
|
@@ -161,6 +175,7 @@ const unicornRules = {
|
|
|
161
175
|
"unicorn/prefer-includes": "warn",
|
|
162
176
|
"unicorn/prefer-iterable-in-constructor": "warn",
|
|
163
177
|
"unicorn/prefer-iterator-concat": "warn",
|
|
178
|
+
"unicorn/prefer-iterator-helpers": "warn",
|
|
164
179
|
"unicorn/prefer-iterator-to-array": "warn",
|
|
165
180
|
"unicorn/prefer-iterator-to-array-at-end": "warn",
|
|
166
181
|
"unicorn/prefer-keyboard-event-key": "error",
|
|
@@ -184,9 +199,11 @@ const unicornRules = {
|
|
|
184
199
|
"unicorn/prefer-object-destructuring-defaults": "warn",
|
|
185
200
|
"unicorn/prefer-object-from-entries": "warn",
|
|
186
201
|
"unicorn/prefer-object-iterable-methods": "warn",
|
|
202
|
+
"unicorn/prefer-observer-apis": "warn",
|
|
187
203
|
"unicorn/prefer-optional-catch-binding": "warn",
|
|
188
204
|
"unicorn/prefer-path2d": "warn",
|
|
189
205
|
"unicorn/prefer-private-class-fields": "warn",
|
|
206
|
+
"unicorn/prefer-promise-try": "warn",
|
|
190
207
|
"unicorn/prefer-promise-with-resolvers": "warn",
|
|
191
208
|
"unicorn/prefer-queue-microtask": "warn",
|
|
192
209
|
"unicorn/prefer-reflect-apply": "warn",
|
|
@@ -194,9 +211,11 @@ const unicornRules = {
|
|
|
194
211
|
"unicorn/prefer-regexp-test": "warn",
|
|
195
212
|
"unicorn/prefer-response-static-json": "warn",
|
|
196
213
|
"unicorn/prefer-scoped-selector": "warn",
|
|
214
|
+
"unicorn/prefer-set-methods": "warn",
|
|
197
215
|
"unicorn/prefer-set-size": "warn",
|
|
198
216
|
"unicorn/prefer-simple-condition-first": "warn",
|
|
199
217
|
"unicorn/prefer-simple-sort-comparator": "warn",
|
|
218
|
+
"unicorn/prefer-simplified-conditions": "warn",
|
|
200
219
|
"unicorn/prefer-single-array-predicate": "warn",
|
|
201
220
|
"unicorn/prefer-single-call": "warn",
|
|
202
221
|
"unicorn/prefer-single-object-destructuring": "warn",
|
|
@@ -212,12 +231,14 @@ const unicornRules = {
|
|
|
212
231
|
"unicorn/prefer-string-trim-start-end": "warn",
|
|
213
232
|
"unicorn/prefer-structured-clone": "warn",
|
|
214
233
|
"unicorn/prefer-temporal": "warn",
|
|
234
|
+
"unicorn/prefer-toggle-attribute": "warn",
|
|
215
235
|
"unicorn/prefer-top-level-await": "warn",
|
|
216
236
|
"unicorn/prefer-type-error": "warn",
|
|
217
237
|
"unicorn/prefer-uint8array-base64": "warn",
|
|
218
238
|
"unicorn/prefer-unary-minus": "warn",
|
|
219
239
|
"unicorn/prefer-url-can-parse": "warn",
|
|
220
240
|
"unicorn/prefer-url-href": "warn",
|
|
241
|
+
"unicorn/prefer-url-search-parameters": "warn",
|
|
221
242
|
"unicorn/prefer-while-loop-condition": "warn",
|
|
222
243
|
"unicorn/relative-url-style": "warn",
|
|
223
244
|
"unicorn/require-array-join-separator": "warn",
|
package/dist/rules/vue.mjs
CHANGED
|
@@ -8,6 +8,7 @@ function getVueRules(options) {
|
|
|
8
8
|
const { typescript, stylistic, vue, nuxt } = options.configs;
|
|
9
9
|
const { indent, trailingComma, maxLineLength, maxAttributesPerLine, maxConsecutiveEmptyLines, selfCloseVoidHtmlElements } = isEnabled(stylistic) ? stylistic : defaultOptions.configs.stylistic;
|
|
10
10
|
const { blockLang, blocksOrder, macrosOrder, attributesOrder, destructureProps, vForDelimiterStyle, attributeHyphenation, allowedStyleAttributes, preferVBindTrueShorthand, componentNameCaseInTemplate, preferVBindSameNameShorthand, restrictedElements: userRestrictedElements, ignoredUndefinedComponents: userIgnoredUndefinedComponents, restrictedStaticAttributes: userRestrictedStaticAttributes } = isEnabled(vue) ? vue : defaultOptions.configs.vue;
|
|
11
|
+
const { imageComponents: userImageComponents, anchorComponents: userAnchorComponents, accessibleChildComponents: userAccessibleChildComponents } = isEnabled(vue) && isEnabled(vue.accessibility) ? vue.accessibility : defaultOptions.configs.vue.accessibility;
|
|
11
12
|
const isNuxtEnabled = isEnabled(nuxt);
|
|
12
13
|
const isNuxtImageEnabled = isNuxtEnabled ? nuxt.image : void 0;
|
|
13
14
|
const isNuxtUIEnabled = isNuxtEnabled ? nuxt.ui : void 0;
|
|
@@ -18,8 +19,43 @@ function getVueRules(options) {
|
|
|
18
19
|
const restrictedVueInputs = isNuxtUIEnabled ? getRestrictedVueInputs(nuxtUIPrefix) : [];
|
|
19
20
|
const isScriptLangTS = blockLang.script === "ts";
|
|
20
21
|
const isStyleLangImplicit = blockLang.style === "implicit";
|
|
21
|
-
|
|
22
|
-
"
|
|
22
|
+
const vueAccessibilityRules = {
|
|
23
|
+
"vuejs-accessibility/alt-text": ["error", { img: userImageComponents }],
|
|
24
|
+
"vuejs-accessibility/anchor-has-content": ["error", {
|
|
25
|
+
components: userAnchorComponents,
|
|
26
|
+
accessibleChildren: userAccessibleChildComponents
|
|
27
|
+
}],
|
|
28
|
+
"vuejs-accessibility/aria-props": "error",
|
|
29
|
+
"vuejs-accessibility/aria-role": "error",
|
|
30
|
+
"vuejs-accessibility/aria-unsupported-elements": "error",
|
|
31
|
+
"vuejs-accessibility/form-control-has-label": ["error", { labelComponents: isNuxtUIEnabled ? [`${nuxtUIPrefix}FormField`] : void 0 }],
|
|
32
|
+
"vuejs-accessibility/heading-has-content": "error",
|
|
33
|
+
"vuejs-accessibility/iframe-has-title": "error",
|
|
34
|
+
"vuejs-accessibility/interactive-supports-focus": "error",
|
|
35
|
+
"vuejs-accessibility/label-has-for": ["error", {
|
|
36
|
+
allowChildren: true,
|
|
37
|
+
required: { some: ["nesting", "id"] },
|
|
38
|
+
controlComponents: [
|
|
39
|
+
"input",
|
|
40
|
+
"output",
|
|
41
|
+
"meter",
|
|
42
|
+
"select",
|
|
43
|
+
"textarea",
|
|
44
|
+
"progress"
|
|
45
|
+
]
|
|
46
|
+
}],
|
|
47
|
+
"vuejs-accessibility/media-has-caption": "error",
|
|
48
|
+
"vuejs-accessibility/no-access-key": "warn",
|
|
49
|
+
"vuejs-accessibility/no-aria-hidden-on-focusable": "error",
|
|
50
|
+
"vuejs-accessibility/no-autofocus": "warn",
|
|
51
|
+
"vuejs-accessibility/no-distracting-elements": "warn",
|
|
52
|
+
"vuejs-accessibility/no-redundant-roles": "warn",
|
|
53
|
+
"vuejs-accessibility/no-role-presentation-on-focusable": "error",
|
|
54
|
+
"vuejs-accessibility/no-static-element-interactions": "error",
|
|
55
|
+
"vuejs-accessibility/role-has-required-aria-props": "error",
|
|
56
|
+
"vuejs-accessibility/tabindex-no-positive": "error"
|
|
57
|
+
};
|
|
58
|
+
const vueAndNuxtRules = {
|
|
23
59
|
"vue/jsx-uses-vars": "error",
|
|
24
60
|
"vue/comment-directive": ["error", { reportUnusedDisableDirectives: true }],
|
|
25
61
|
"vue/multi-word-component-names": "error",
|
|
@@ -330,7 +366,7 @@ function getVueRules(options) {
|
|
|
330
366
|
isNuxtUIEnabled && `^${nuxtUIPrefix}`,
|
|
331
367
|
...userIgnoredUndefinedComponents
|
|
332
368
|
].filter(isTruthy) }],
|
|
333
|
-
"vue/no-undef-directives":
|
|
369
|
+
"vue/no-undef-directives": isNuxtEnabled ? "off" : "error",
|
|
334
370
|
"vue/no-unused-emit-declarations": "error",
|
|
335
371
|
"vue/no-unused-properties": ["error", {
|
|
336
372
|
groups: [
|
|
@@ -367,6 +403,12 @@ function getVueRules(options) {
|
|
|
367
403
|
"vue/slot-name-casing": "warn",
|
|
368
404
|
"vue/v-for-delimiter-style": ["warn", vForDelimiterStyle]
|
|
369
405
|
};
|
|
406
|
+
if (isEnabled(stylistic)) vueAndNuxtRules["@stylistic/max-len"] = "off";
|
|
407
|
+
const isVueAccessibilityEnabled = isEnabled(vue) && isEnabled(vue.accessibility);
|
|
408
|
+
return {
|
|
409
|
+
...vueAndNuxtRules,
|
|
410
|
+
...isVueAccessibilityEnabled && vueAccessibilityRules
|
|
411
|
+
};
|
|
370
412
|
}
|
|
371
413
|
//#endregion
|
|
372
414
|
export { getVueRules };
|