@shayanthenerd/eslint-config 0.26.0 → 0.26.2
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 +13 -6
- package/dist/configs/html.mjs +1 -1
- package/dist/configs/react.mjs +2 -4
- package/dist/configs/vue.mjs +1 -5
- package/dist/helpers/ignores/defaultIgnorePatterns.mjs +1 -0
- 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 +13 -0
- package/dist/rules/vue.mjs +45 -3
- package/dist/types/eslint-schema.d.mts +385 -312
- package/dist/types/options/vue.d.mts +33 -2
- package/package.json +21 -21
- 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)
|
|
@@ -27,7 +27,7 @@ ESLint configuration for enforcing best practices and maintaining a consistent c
|
|
|
27
27
|
Legend:
|
|
28
28
|
- ✅ Enabled by default
|
|
29
29
|
- ❌ Disabled by default
|
|
30
|
-
- 🔎 [Automatically detected](#automatic-dependency-detection)
|
|
30
|
+
- 🔎 [Automatically detected](#automatic-dependency-detection)
|
|
31
31
|
|
|
32
32
|
| Category | Activation |
|
|
33
33
|
| :---------------------------------------------------------------------------------------------------- | :--------: |
|
|
@@ -175,6 +175,8 @@ PNPM's strict dependency resolution avoids this issue.
|
|
|
175
175
|
> [!NOTE]
|
|
176
176
|
> For example, `eslint-plugin-storybook` depends on `storybook`, which is hoisted by NPM and Bun. As a result, the integration for `storybook` will be enabled automatically, even if you haven't explicitly installed it.
|
|
177
177
|
|
|
178
|
+
`configs.useBaseline` is automatically enabled when `autoDetectDeps: true` and `env: 'browser'` (both are the defaults).
|
|
179
|
+
|
|
178
180
|
To opt out of this behavior, either [globally disable automatic dependency detection](#customization) or manually disable the unwanted integrations that were enabled automatically.
|
|
179
181
|
|
|
180
182
|
## Framework and Tool Integrations
|
|
@@ -228,7 +230,15 @@ By default, the plugin uses GitHub Flavored Markdown (GFM). You can [switch to C
|
|
|
228
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).
|
|
229
231
|
|
|
230
232
|
## IDE Support
|
|
231
|
-
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_:
|
|
232
242
|
```jsonc title=".vscode/settings.json"
|
|
233
243
|
{
|
|
234
244
|
/* Enforce Unix-like line endings (LF). */
|
|
@@ -284,9 +294,6 @@ Install the VS Code extensions for [ESLint][extension-eslint] and [Prettier][ext
|
|
|
284
294
|
}
|
|
285
295
|
```
|
|
286
296
|
|
|
287
|
-
> [!TIP]
|
|
288
|
-
> 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.
|
|
289
|
-
|
|
290
297
|
## Formatting
|
|
291
298
|
This configuration uses [ESLint Stylistic][plugin-stylistic] to format:
|
|
292
299
|
- JavaScript and TypeScript (_js_, _cjs_, _mjs_, _jsx_, _ts_, _cts_, _mts_, _tsx_),
|
package/dist/configs/html.mjs
CHANGED
|
@@ -11,7 +11,7 @@ function getHtmlConfig(options) {
|
|
|
11
11
|
const { overrides } = isEnabled(html) ? html : defaultOptions.configs.html;
|
|
12
12
|
return mergeConfigs({
|
|
13
13
|
name: "shayanthenerd/html",
|
|
14
|
-
files: [globs.
|
|
14
|
+
files: [globs.html],
|
|
15
15
|
plugins: {
|
|
16
16
|
"@html-eslint": eslintPluginHtml,
|
|
17
17
|
...isEnabled(unicorn) && { unicorn: eslintPluginUnicorn }
|
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",
|
|
@@ -59,7 +60,9 @@ const unicornRules = {
|
|
|
59
60
|
"unicorn/no-invalid-character-comparison": "error",
|
|
60
61
|
"unicorn/no-invalid-fetch-options": "error",
|
|
61
62
|
"unicorn/no-invalid-remove-event-listener": "error",
|
|
63
|
+
"unicorn/no-invalid-well-known-symbol-methods": "error",
|
|
62
64
|
"unicorn/no-late-current-target-access": "warn",
|
|
65
|
+
"unicorn/no-late-event-control": "error",
|
|
63
66
|
"unicorn/no-lonely-if": "warn",
|
|
64
67
|
"unicorn/no-loop-iterable-mutation": "warn",
|
|
65
68
|
"unicorn/no-magic-array-flat-depth": "warn",
|
|
@@ -75,6 +78,7 @@ const unicornRules = {
|
|
|
75
78
|
"unicorn/no-object-methods-with-collections": "warn",
|
|
76
79
|
"unicorn/no-optional-chaining-on-undeclared-variable": "error",
|
|
77
80
|
"unicorn/no-redundant-comparison": "warn",
|
|
81
|
+
"unicorn/no-return-array-push": "warn",
|
|
78
82
|
"unicorn/no-selector-as-dom-name": "error",
|
|
79
83
|
"unicorn/no-single-promise-in-promise-methods": "warn",
|
|
80
84
|
"unicorn/no-static-only-class": "warn",
|
|
@@ -122,8 +126,10 @@ const unicornRules = {
|
|
|
122
126
|
"unicorn/no-zero-fractions": "warn",
|
|
123
127
|
"unicorn/number-literal-case": "warn",
|
|
124
128
|
"unicorn/numeric-separators-style": "warn",
|
|
129
|
+
"unicorn/prefer-abort-signal-timeout": "warn",
|
|
125
130
|
"unicorn/prefer-add-event-listener": "warn",
|
|
126
131
|
"unicorn/prefer-add-event-listener-options": "warn",
|
|
132
|
+
"unicorn/prefer-aggregate-error": "warn",
|
|
127
133
|
"unicorn/prefer-array-flat": "warn",
|
|
128
134
|
"unicorn/prefer-array-flat-map": "warn",
|
|
129
135
|
"unicorn/prefer-array-from-async": "warn",
|
|
@@ -147,7 +153,9 @@ const unicornRules = {
|
|
|
147
153
|
"unicorn/prefer-dom-node-append": "warn",
|
|
148
154
|
"unicorn/prefer-dom-node-html-methods": "warn",
|
|
149
155
|
"unicorn/prefer-dom-node-remove": "warn",
|
|
156
|
+
"unicorn/prefer-dom-node-replace-children": "warn",
|
|
150
157
|
"unicorn/prefer-dom-node-text-content": "warn",
|
|
158
|
+
"unicorn/prefer-error-is-error": "error",
|
|
151
159
|
"unicorn/prefer-event-target": "warn",
|
|
152
160
|
"unicorn/prefer-export-from": ["warn", { checkUsedVariables: false }],
|
|
153
161
|
"unicorn/prefer-flat-math-min-max": "warn",
|
|
@@ -184,9 +192,11 @@ const unicornRules = {
|
|
|
184
192
|
"unicorn/prefer-object-destructuring-defaults": "warn",
|
|
185
193
|
"unicorn/prefer-object-from-entries": "warn",
|
|
186
194
|
"unicorn/prefer-object-iterable-methods": "warn",
|
|
195
|
+
"unicorn/prefer-observer-apis": "warn",
|
|
187
196
|
"unicorn/prefer-optional-catch-binding": "warn",
|
|
188
197
|
"unicorn/prefer-path2d": "warn",
|
|
189
198
|
"unicorn/prefer-private-class-fields": "warn",
|
|
199
|
+
"unicorn/prefer-promise-try": "warn",
|
|
190
200
|
"unicorn/prefer-promise-with-resolvers": "warn",
|
|
191
201
|
"unicorn/prefer-queue-microtask": "warn",
|
|
192
202
|
"unicorn/prefer-reflect-apply": "warn",
|
|
@@ -194,6 +204,7 @@ const unicornRules = {
|
|
|
194
204
|
"unicorn/prefer-regexp-test": "warn",
|
|
195
205
|
"unicorn/prefer-response-static-json": "warn",
|
|
196
206
|
"unicorn/prefer-scoped-selector": "warn",
|
|
207
|
+
"unicorn/prefer-set-methods": "warn",
|
|
197
208
|
"unicorn/prefer-set-size": "warn",
|
|
198
209
|
"unicorn/prefer-simple-condition-first": "warn",
|
|
199
210
|
"unicorn/prefer-simple-sort-comparator": "warn",
|
|
@@ -212,12 +223,14 @@ const unicornRules = {
|
|
|
212
223
|
"unicorn/prefer-string-trim-start-end": "warn",
|
|
213
224
|
"unicorn/prefer-structured-clone": "warn",
|
|
214
225
|
"unicorn/prefer-temporal": "warn",
|
|
226
|
+
"unicorn/prefer-toggle-attribute": "warn",
|
|
215
227
|
"unicorn/prefer-top-level-await": "warn",
|
|
216
228
|
"unicorn/prefer-type-error": "warn",
|
|
217
229
|
"unicorn/prefer-uint8array-base64": "warn",
|
|
218
230
|
"unicorn/prefer-unary-minus": "warn",
|
|
219
231
|
"unicorn/prefer-url-can-parse": "warn",
|
|
220
232
|
"unicorn/prefer-url-href": "warn",
|
|
233
|
+
"unicorn/prefer-url-search-parameters": "warn",
|
|
221
234
|
"unicorn/prefer-while-loop-condition": "warn",
|
|
222
235
|
"unicorn/relative-url-style": "warn",
|
|
223
236
|
"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 };
|