@dartess/eslint-plugin 0.4.0 → 0.6.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/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  [//]: # (https://keepachangelog.com/en/1.1.0/)
4
4
 
5
+ ## [0.6.0] - 2026-01-17
6
+ - replace legacy `eslint-plugin-react` with modern `@eslint-react/eslint-plugin`
7
+
8
+ If you're using React: uninstall `eslint-plugin-react`, then install `@eslint-react/eslint-plugin` and `@stylistic/eslint-plugin`.
9
+
10
+ ## [0.5.0] - 2026-01-16
11
+ - add rule `@dartess/mobx-sync-action`
12
+ - add `@dartess/mobx-sync-action` to `mobx` config
13
+
5
14
  ## [0.4.0] - 2026-01-15
6
15
  - add rule `@dartess/mobx-sync-autorun`
7
16
  - add `@dartess/mobx-sync-autorun` to `mobx` config
package/README.md CHANGED
@@ -10,7 +10,7 @@ Also extends
10
10
  * `eslint-plugin-de-morgan` — `recommended`
11
11
 
12
12
  Also can extends (if it is applicable)
13
- * `eslint-plugin-react` — `recommended` & `jsx-runtime`
13
+ * `@eslint-react/eslint-plugin` — `strict-type-checked`
14
14
  * `eslint-plugin-react-hooks` — `recommended`
15
15
  * `@next/eslint-plugin-next` — `recommended` & `core-web-vitals`
16
16
  * `eslint-config-next`
@@ -25,7 +25,7 @@ All of it pinched with extra configs, setups and extra rules. Just take it and u
25
25
 
26
26
  2. The package is intended for use only with the `flat` eslint config.
27
27
 
28
- 3. _(for React users)_ The package is intended for use with [React New JSX Transform](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html).
28
+ 3. _(for React users)_ The package is intended for use with [React New JSX Transform](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) and React 19+.
29
29
 
30
30
  ## Installation
31
31
 
@@ -46,7 +46,10 @@ npm i -D eslint \
46
46
  Next, also install the packages that suit your needs.
47
47
 
48
48
  ```sh
49
- npm i -D eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y
49
+ npm i -D eslint-plugin-react-hooks \
50
+ eslint-plugin-jsx-a11y \
51
+ @eslint-react/eslint-plugin \
52
+ @stylistic/eslint-plugin
50
53
  ```
51
54
  ```sh
52
55
  npm i -D @next/eslint-plugin-next
@@ -60,8 +63,6 @@ npm i -D eslint-plugin-storybook
60
63
 
61
64
  ## Usage configs
62
65
 
63
- Shared config based on `eslint-config-airbnb`, `eslint-config-airbnb-typescript`, `eslint-plugin-react/recommended`, `eslint-plugin-react/jsx-runtime`.
64
-
65
66
  Edit or create `eslint.config.ts` (or `eslint.config.mts`). You probably have to install `jiti` for it.
66
67
 
67
68
  ```ts
@@ -159,15 +160,21 @@ Each rule has emojis denoting:
159
160
 
160
161
  | Name | Description | ✅ | 🔧 | 💡 |
161
162
  |:-----------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------|:--|:---|:---|
162
- | [strict-observable-components-declaration](docs/rules/strict-observable-components-declaration.md) | Wrapping components in `observer` must comply with the regulations. || | |
163
- | [require-observer](docs/rules/require-observer.md) | Components using the stores must be wrapped in an `observer` | ✅ | 🔧 | |
164
- | [prevent-mixing-external-and-internal-classes](docs/rules/prevent-mixing-external-and-internal-classes.md) | Prevent mixing of outer and inner classes to avoid dependency on style order. | | | |
163
+ | **imports** | _config: recommended_ | | | |
164
+ | [max-parent-import-depth](docs/rules/max-parent-import-depth.md) | Limit relative imports to a maximum parent depth. | ✅ | | |
165
+ | **TypeScript** | _config: recommended_ | | | |
166
+ | [ts-named-tuple-elements](docs/rules/ts-named-tuple-elements.md) | Enforce (or forbid) named tuple elements | ✅ | | |
167
+ | **React** | _config: react_ | | | |
165
168
  | [jsx-no-text-as-child](docs/rules/jsx-text-as-child.md) | JSX elements should not have text without translation | | | |
169
+ | [prevent-mixing-external-and-internal-classes](docs/rules/prevent-mixing-external-and-internal-classes.md) | Prevent mixing of outer and inner classes to avoid dependency on style order. | | | |
170
+ | **Storybook** | _config: storybook_ | | | |
166
171
  | [stories-export-meta](docs/rules/stories-export-meta.md) | Storybook's Meta should be typed | ✅ | | |
167
172
  | [stories-export-typed](docs/rules/stories-export-typed.md) | Storybook's Stories should be typed | ✅ | | |
168
- | [max-parent-import-depth](docs/rules/max-parent-import-depth.md) | Limit relative imports to a maximum parent depth. || | |
169
- | [ts-named-tuple-elements](docs/rules/ts-named-tuple-elements.md) | Enforce (or forbid) named tuple elements | ✅ | | |
170
- | [mobx-sync-autorun](docs/rules/mobx-sync-autorun.md) | Enforce synchronous autorun callback | ✅ | | |
173
+ | **MobX** | _config: mobx_ | | | |
174
+ | [strict-observable-components-declaration](docs/rules/strict-observable-components-declaration.md) | Wrapping components in `observer` must comply with the regulations. | ✅ | | |
175
+ | [require-observer](docs/rules/require-observer.md) | Components using the stores must be wrapped in an `observer` | ✅ | 🔧 | |
176
+ | [mobx-sync-autorun](docs/rules/mobx-sync-autorun.md) | Enforce synchronous autorun callback | ✅ | | |
177
+ | [mobx-sync-action](docs/rules/mobx-sync-action.md) | Enforce synchronous actions | ✅ | | |
171
178
 
172
179
  ## Code Reuse Policy
173
180
 
@@ -5,10 +5,11 @@ const config = [
5
5
  name: '@dartess/mobx',
6
6
  rules: {
7
7
  'mobx/missing-observer': 'off', // replaced by the neater "@dartess/require-observer"
8
- 'mobx/missing-make-observable': 'off', // useless with modern decorators syntax
8
+ 'mobx/missing-make-observable': 'off', // useless with modern decorators syntax. TODO check original plugin?
9
9
  '@dartess/strict-observable-components-declaration': 'error',
10
10
  '@dartess/require-observer': 'error',
11
- '@dartess/mobx-sync-autorun': 'error',
11
+ '@dartess/mobx-sync-autorun': 'error', // TODO implement it by types?
12
+ '@dartess/mobx-sync-action': 'error', // TODO implement it by types?
12
13
  },
13
14
  },
14
15
  ];
@@ -1,33 +1,23 @@
1
- // This file contains code from the `eslint-config-airbnb` project
2
- // Original author: Jake Teton-Landis (https://twitter.com/@jitl)
3
- // License: MIT (see LICENSE-eslint-config-airbnb.md file)
4
- import reactPlugin from 'eslint-plugin-react';
1
+ import eslintReact from '@eslint-react/eslint-plugin';
2
+ import stylisticPlugin from '@stylistic/eslint-plugin';
5
3
  import reactHooksPlugin from 'eslint-plugin-react-hooks';
6
4
  import jsxA11yPlugin from 'eslint-plugin-jsx-a11y';
7
- import vendorRulesReact from "./vendor-rules/react.js";
8
5
  const config = [
9
6
  {
10
7
  name: '@dartess/react-setup',
11
8
  plugins: {
12
9
  'react-hooks': reactHooksPlugin,
13
10
  'jsx-a11y': jsxA11yPlugin,
11
+ '@stylistic': stylisticPlugin,
14
12
  },
15
13
  settings: {
16
- react: {
14
+ 'react-x': {
17
15
  version: 'detect',
18
16
  },
19
17
  },
20
18
  },
19
+ eslintReact.configs['strict-type-checked'],
21
20
  reactHooksPlugin.configs.flat.recommended,
22
- {
23
- name: 'react/recommended', // missed name, @see e.g. https://github.com/jsx-eslint/eslint-plugin-react/pull/3882
24
- ...reactPlugin.configs.flat.recommended,
25
- },
26
- {
27
- name: '@dartess/eslint-plugin-react/jsx-runtime',
28
- files: ['**/*.{jsx,tsx}'],
29
- ...reactPlugin.configs.flat['jsx-runtime'],
30
- },
31
21
  {
32
22
  name: '@dartess/react',
33
23
  files: ['**/*.{jsx,tsx}'],
@@ -49,12 +39,7 @@ const config = [
49
39
  },
50
40
  },
51
41
  rules: {
52
- ...vendorRulesReact,
53
- // too hard for fixing, TODO maybe try later?
54
- 'react/jsx-props-no-spreading': 'off',
55
42
  // TODO: try to enable this rules later (if needed)
56
- 'react/require-default-props': 'off',
57
- 'react/no-unstable-nested-components': 'off',
58
43
  'jsx-a11y/click-events-have-key-events': 'off',
59
44
  'jsx-a11y/anchor-is-valid': 'off',
60
45
  'jsx-a11y/interactive-supports-focus': 'off',
@@ -63,12 +48,29 @@ const config = [
63
48
  'jsx-a11y/no-noninteractive-tabindex': 'off', // TODO enable later
64
49
  'jsx-a11y/no-noninteractive-element-interactions': 'off', // TODO enable later
65
50
  'jsx-a11y/label-has-associated-control': 'off', // TODO enable later but with `assert`=`either`
66
- // Append 'tsx' to Airbnb 'react/jsx-filename-extension' rule
67
- // Original: ['.jsx']
68
- 'react/jsx-filename-extension': ['error', { extensions: ['.jsx', '.tsx'] }],
69
- // overrides
70
- 'react/jsx-no-duplicate-props': 'off', // checked by typescript
71
- 'react/jsx-no-undef': 'off', // checked by typescript
51
+ '@eslint-react/naming-convention/filename': 'error', // enforce corrent filename
52
+ // disable some recommended rules
53
+ '@eslint-react/prefer-destructuring-assignment': 'off', // can break discriminated union types
54
+ // mark some recommended warns as errors
55
+ '@eslint-react/dom/no-missing-button-type': 'error',
56
+ '@eslint-react/naming-convention/use-state': 'error',
57
+ '@eslint-react/naming-convention/ref-name': 'error',
58
+ '@eslint-react/naming-convention/context-name': 'error',
59
+ '@eslint-react/dom/no-missing-iframe-sandbox': 'error',
60
+ '@eslint-react/dom/no-unsafe-iframe-sandbox': 'error',
61
+ '@eslint-react/jsx-no-comment-textnodes': 'error',
62
+ '@eslint-react/no-unstable-context-value': 'error',
63
+ '@eslint-react/dom/no-script-url': 'error',
64
+ '@eslint-react/dom/no-unsafe-target-blank': 'error',
65
+ '@eslint-react/no-useless-fragment': 'error',
66
+ '@eslint-react/dom/no-dangerously-set-innerhtml': 'error',
67
+ '@eslint-react/no-forward-ref': 'error',
68
+ // enable airbnb-style rules
69
+ '@eslint-react/jsx-shorthand-boolean': 'error',
70
+ '@eslint-react/jsx-shorthand-fragment': 'error',
71
+ '@eslint-react/naming-convention/component-name': 'error',
72
+ '@stylistic/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }],
73
+ '@stylistic/jsx-self-closing-comp': 'error',
72
74
  },
73
75
  },
74
76
  ];
@@ -7,7 +7,7 @@ declare const rules: {
7
7
  name: string;
8
8
  message: string;
9
9
  }, ...{
10
- name: "name" | "length" | "find" | "parent" | "menubar" | "self" | "addEventListener" | "blur" | "close" | "closed" | "confirm" | "defaultStatus" | "defaultstatus" | "event" | "external" | "focus" | "frameElement" | "frames" | "history" | "innerHeight" | "innerWidth" | "location" | "locationbar" | "moveBy" | "moveTo" | "onblur" | "onerror" | "onfocus" | "onload" | "onresize" | "onunload" | "open" | "opener" | "opera" | "outerHeight" | "outerWidth" | "pageXOffset" | "pageYOffset" | "print" | "removeEventListener" | "resizeBy" | "resizeTo" | "screen" | "screenLeft" | "screenTop" | "screenX" | "screenY" | "scroll" | "scrollbars" | "scrollBy" | "scrollTo" | "scrollX" | "scrollY" | "status" | "statusbar" | "stop" | "toolbar" | "top";
10
+ name: "name" | "length" | "find" | "parent" | "self" | "addEventListener" | "blur" | "close" | "closed" | "confirm" | "defaultStatus" | "defaultstatus" | "event" | "external" | "focus" | "frameElement" | "frames" | "history" | "innerHeight" | "innerWidth" | "location" | "locationbar" | "menubar" | "moveBy" | "moveTo" | "onblur" | "onerror" | "onfocus" | "onload" | "onresize" | "onunload" | "open" | "opener" | "opera" | "outerHeight" | "outerWidth" | "pageXOffset" | "pageYOffset" | "print" | "removeEventListener" | "resizeBy" | "resizeTo" | "screen" | "screenLeft" | "screenTop" | "screenX" | "screenY" | "scroll" | "scrollbars" | "scrollBy" | "scrollTo" | "scrollX" | "scrollY" | "status" | "statusbar" | "stop" | "toolbar" | "top";
11
11
  message: string;
12
12
  }[]];
13
13
  'no-shadow': "error";
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import ruleRequireObserver from "./rules/require-observer.js";
8
8
  import ruleMaxParentImportDepth from "./rules/max-parent-import-depth.js";
9
9
  import ruleTsNamedTupleElements from "./rules/ts-named-tuple-elements.js";
10
10
  import ruleMobxSyncAutorun from "./rules/mobx-sync-autorun.js";
11
+ import ruleMobxSyncAction from "./rules/mobx-sync-action.js";
11
12
  const plugin = {
12
13
  meta: {
13
14
  name: packageJson.name,
@@ -24,6 +25,7 @@ const plugin = {
24
25
  'max-parent-import-depth': ruleMaxParentImportDepth,
25
26
  'ts-named-tuple-elements': ruleTsNamedTupleElements,
26
27
  'mobx-sync-autorun': ruleMobxSyncAutorun,
28
+ 'mobx-sync-action': ruleMobxSyncAction,
27
29
  },
28
30
  };
29
31
  export default plugin;
@@ -0,0 +1,3 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"requireSyncAction", [], unknown, ESLintUtils.RuleListener>;
3
+ export default _default;
@@ -0,0 +1,28 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ export default ESLintUtils.RuleCreator(() => '')({
3
+ name: 'mobx-sync-action',
4
+ defaultOptions: [],
5
+ meta: {
6
+ type: 'problem',
7
+ docs: {
8
+ description: 'Mobx methods marked as `@action` must must be synchronous.',
9
+ },
10
+ messages: {
11
+ requireSyncAction: '`action` must be synchronous function',
12
+ },
13
+ schema: [],
14
+ },
15
+ create(context) {
16
+ const selector = [
17
+ 'MethodDefinition[value.async="true"] Decorator[expression.object.name="action"]',
18
+ 'MethodDefinition[value.async="true"] Decorator[expression.name="action"]',
19
+ 'PropertyDefinition[value.type="ArrowFunctionExpression"][value.async="true"] Decorator[expression.object.name="action"]',
20
+ 'PropertyDefinition[value.type="ArrowFunctionExpression"][value.async="true"] Decorator[expression.name="action"]',
21
+ ].join(', ');
22
+ return {
23
+ [selector]: node => {
24
+ context.report({ node, messageId: 'requireSyncAction' });
25
+ },
26
+ };
27
+ },
28
+ });
@@ -0,0 +1,27 @@
1
+ # Enforce synchronous actions
2
+
3
+ Mobx methods marked as `@action` must be synchronous: https://mobx.js.org/actions.html#asynchronous-actions
4
+
5
+ ## Rule Details
6
+
7
+ Examples of **incorrect** code for this rule:
8
+
9
+ ```ts
10
+ class Store {
11
+ @action async method1() {};
12
+ @action.bound async method2() {};
13
+ @action method3 = async () => {};
14
+ @action.bound method4 = async () => {};
15
+ }
16
+ ```
17
+
18
+ Examples of **correct** code for this rule:
19
+
20
+ ```ts
21
+ class Store {
22
+ @action method1() {};
23
+ @action.bound method2() {};
24
+ @action method3 = () => {};
25
+ @action.bound method4 = () => {};
26
+ }
27
+ ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dartess/eslint-plugin",
3
3
  "type": "module",
4
- "version": "0.4.0",
4
+ "version": "0.6.0",
5
5
  "description": "A set of rules and configs for various TypeScript projects",
6
6
  "keywords": [
7
7
  "eslint",
@@ -47,8 +47,10 @@
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@eslint-community/eslint-plugin-eslint-comments": "^4.0.0",
50
+ "@eslint-react/eslint-plugin": "^2.7.0",
50
51
  "@eslint/js": "^9.0.0",
51
52
  "@next/eslint-plugin-next": "^16.0.0",
53
+ "@stylistic/eslint-plugin": "^5.7.0",
52
54
  "eslint": "^9.0.0",
53
55
  "eslint-import-resolver-typescript": "^4.0.0",
54
56
  "eslint-plugin-de-morgan": "^2.0.0",
@@ -56,23 +58,25 @@
56
58
  "eslint-plugin-import-x": "^4.1.0",
57
59
  "eslint-plugin-jsx-a11y": "^6.10.0",
58
60
  "eslint-plugin-mobx": "~0.0.13",
59
- "eslint-plugin-react": "^7.37.0",
60
61
  "eslint-plugin-react-hooks": "^7.0.0",
61
62
  "eslint-plugin-storybook": "^10.0.0",
62
63
  "eslint-plugin-unicorn": ">=58.0.0",
63
64
  "typescript-eslint": "^8.15.0"
64
65
  },
65
66
  "peerDependenciesMeta": {
67
+ "@eslint-react/eslint-plugin": {
68
+ "optional": true
69
+ },
66
70
  "@next/eslint-plugin-next": {
67
71
  "optional": true
68
72
  },
69
- "eslint-plugin-jsx-a11y": {
73
+ "@stylistic/eslint-plugin": {
70
74
  "optional": true
71
75
  },
72
- "eslint-plugin-mobx": {
76
+ "eslint-plugin-jsx-a11y": {
73
77
  "optional": true
74
78
  },
75
- "eslint-plugin-react": {
79
+ "eslint-plugin-mobx": {
76
80
  "optional": true
77
81
  },
78
82
  "eslint-plugin-react-hooks": {
@@ -1,213 +0,0 @@
1
- declare const rules: {
2
- /**
3
- * react
4
- * copied from
5
- * https://github.com/airbnb/javascript/blob/c25bce83be4db06e6a221d79686c485cd2ed5d5d/packages/eslint-config-airbnb/rules/react-a11y.js
6
- * */
7
- 'no-underscore-dangle': ["error", {
8
- allowAfterThis: boolean;
9
- allowAfterSuper: boolean;
10
- enforceInMethodNames: boolean;
11
- allow: string[];
12
- }];
13
- 'react/display-name': ["off", {
14
- ignoreTranspilerName: boolean;
15
- }];
16
- 'react/jsx-boolean-value': ["error", string, {
17
- always: never[];
18
- }];
19
- 'react/jsx-closing-bracket-location': ["error", string];
20
- 'react/jsx-closing-tag-location': "error";
21
- 'react/jsx-curly-spacing': ["error", string, {
22
- allowMultiline: boolean;
23
- }];
24
- 'react/jsx-indent-props': ["error", number];
25
- 'react/jsx-max-props-per-line': ["error", {
26
- maximum: number;
27
- when: string;
28
- }];
29
- 'react/jsx-no-bind': ["error", {
30
- ignoreRefs: boolean;
31
- allowArrowFunctions: boolean;
32
- allowFunctions: boolean;
33
- allowBind: boolean;
34
- ignoreDOMComponents: boolean;
35
- }];
36
- 'react/jsx-pascal-case': ["error", {
37
- allowAllCaps: boolean;
38
- ignore: never[];
39
- }];
40
- 'react/no-danger': "error";
41
- 'react/no-did-update-set-state': "error";
42
- 'react/no-will-update-set-state': "error";
43
- 'react/no-direct-mutation-state': "off";
44
- 'react/prefer-es6-class': ["error", string];
45
- 'react/prefer-stateless-function': ["error", {
46
- ignorePureComponents: boolean;
47
- }];
48
- 'react/self-closing-comp': "error";
49
- 'react/sort-comp': ["error", {
50
- order: string[];
51
- groups: {
52
- lifecycle: string[];
53
- rendering: string[];
54
- };
55
- }];
56
- 'react/jsx-wrap-multilines': ["error", {
57
- declaration: string;
58
- assignment: string;
59
- return: string;
60
- arrow: string;
61
- condition: string;
62
- logical: string;
63
- prop: string;
64
- }];
65
- 'react/jsx-first-prop-new-line': ["error", string];
66
- 'react/jsx-equals-spacing': ["error", string];
67
- 'react/jsx-indent': ["error", number];
68
- 'react/jsx-no-target-blank': ["error", {
69
- enforceDynamicLinks: string;
70
- }];
71
- 'react/jsx-filename-extension': ["error", {
72
- extensions: string[];
73
- }];
74
- 'react/style-prop-object': "error";
75
- 'react/jsx-tag-spacing': ["error", {
76
- closingSlash: string;
77
- beforeSelfClosing: string;
78
- afterOpening: string;
79
- beforeClosing: string;
80
- }];
81
- 'react/require-default-props': ["error", {
82
- forbidDefaultForRequired: boolean;
83
- }];
84
- 'react/void-dom-elements-no-children': "error";
85
- 'react/no-redundant-should-component-update': "error";
86
- 'react/no-unused-state': "error";
87
- 'react/no-typos': "error";
88
- 'react/jsx-curly-brace-presence': ["error", {
89
- props: string;
90
- children: string;
91
- }];
92
- 'react/jsx-one-expression-per-line': ["error", {
93
- allow: string;
94
- }];
95
- 'react/no-access-state-in-setstate': "error";
96
- 'react/button-has-type': ["error", {
97
- button: boolean;
98
- submit: boolean;
99
- reset: boolean;
100
- }];
101
- 'react/no-this-in-sfc': "error";
102
- 'react/jsx-props-no-multi-spaces': "error";
103
- 'react/jsx-fragments': ["error", string];
104
- 'react/jsx-curly-newline': ["error", {
105
- multiline: string;
106
- singleline: string;
107
- }];
108
- 'react/jsx-props-no-spreading': ["error", {
109
- html: string;
110
- custom: string;
111
- explicitSpread: string;
112
- exceptions: never[];
113
- }];
114
- 'react/jsx-no-script-url': ["error", {
115
- name: string;
116
- props: string[];
117
- }[]];
118
- 'react/jsx-no-useless-fragment': "error";
119
- 'react/jsx-no-constructed-context-values': "error";
120
- 'react/no-unstable-nested-components': "error";
121
- 'react/no-namespace': "error";
122
- 'react/prefer-exact-props': "error";
123
- 'react/no-arrow-function-lifecycle': "error";
124
- 'react/no-invalid-html-attribute': "error";
125
- 'react/no-unused-class-component-methods': "error";
126
- 'react/hook-use-state': "error";
127
- 'react/iframe-missing-sandbox': "error";
128
- /**
129
- * react-a11y
130
- * copied from
131
- * https://github.com/airbnb/javascript/blob/c25bce83be4db06e6a221d79686c485cd2ed5d5d/packages/eslint-config-airbnb/rules/react-a11y.js
132
- * */
133
- 'jsx-a11y/alt-text': ["error", {
134
- elements: string[];
135
- img: never[];
136
- object: never[];
137
- area: never[];
138
- 'input[type="image"]': never[];
139
- }];
140
- 'jsx-a11y/anchor-has-content': ["error", {
141
- components: never[];
142
- }];
143
- 'jsx-a11y/anchor-is-valid': ["error", {
144
- components: string[];
145
- specialLink: string[];
146
- aspects: string[];
147
- }];
148
- 'jsx-a11y/aria-activedescendant-has-tabindex': "error";
149
- 'jsx-a11y/aria-props': "error";
150
- 'jsx-a11y/aria-proptypes': "error";
151
- 'jsx-a11y/aria-role': ["error", {
152
- ignoreNonDOM: boolean;
153
- }];
154
- 'jsx-a11y/aria-unsupported-elements': "error";
155
- 'jsx-a11y/click-events-have-key-events': "error";
156
- 'jsx-a11y/heading-has-content': ["error", {
157
- components: string[];
158
- }];
159
- 'jsx-a11y/html-has-lang': "error";
160
- 'jsx-a11y/iframe-has-title': "error";
161
- 'jsx-a11y/img-redundant-alt': "error";
162
- 'jsx-a11y/interactive-supports-focus': "error";
163
- 'jsx-a11y/label-has-associated-control': ["error", {
164
- labelComponents: never[];
165
- labelAttributes: never[];
166
- controlComponents: never[];
167
- assert: string;
168
- depth: number;
169
- }];
170
- 'jsx-a11y/lang': "error";
171
- 'jsx-a11y/media-has-caption': ["error", {
172
- audio: never[];
173
- video: never[];
174
- track: never[];
175
- }];
176
- 'jsx-a11y/mouse-events-have-key-events': "error";
177
- 'jsx-a11y/no-access-key': "error";
178
- 'jsx-a11y/no-distracting-elements': ["error", {
179
- elements: string[];
180
- }];
181
- 'jsx-a11y/no-interactive-element-to-noninteractive-role': ["error", {
182
- tr: string[];
183
- }];
184
- 'jsx-a11y/no-noninteractive-element-interactions': ["error", {
185
- handlers: string[];
186
- }];
187
- 'jsx-a11y/no-noninteractive-element-to-interactive-role': ["error", {
188
- ul: string[];
189
- ol: string[];
190
- li: string[];
191
- table: string[];
192
- td: string[];
193
- }];
194
- 'jsx-a11y/no-noninteractive-tabindex': ["error", {
195
- tags: never[];
196
- roles: string[];
197
- allowExpressionValues: boolean;
198
- }];
199
- 'jsx-a11y/no-redundant-roles': ["error", {
200
- nav: string[];
201
- }];
202
- 'jsx-a11y/no-static-element-interactions': ["error", {
203
- handlers: string[];
204
- }];
205
- 'jsx-a11y/role-has-required-aria-props': "error";
206
- 'jsx-a11y/role-supports-aria-props': "error";
207
- 'jsx-a11y/scope': "error";
208
- 'jsx-a11y/tabindex-no-positive': "error";
209
- 'jsx-a11y/anchor-ambiguous-text': "error";
210
- 'jsx-a11y/no-aria-hidden-on-focusable': "error";
211
- 'jsx-a11y/prefer-tag-over-role': "error";
212
- };
213
- export default rules;
@@ -1,470 +0,0 @@
1
- // This file contains code from the `eslint-config-airbnb` project
2
- // Original author: Jake Teton-Landis (https://twitter.com/@jitl)
3
- // License: MIT (see LICENSE-eslint-config-airbnb.md file)
4
- const rules = {
5
- /**
6
- * react
7
- * copied from
8
- * https://github.com/airbnb/javascript/blob/c25bce83be4db06e6a221d79686c485cd2ed5d5d/packages/eslint-config-airbnb/rules/react-a11y.js
9
- * */
10
- 'no-underscore-dangle': [
11
- 'error',
12
- {
13
- allowAfterThis: false,
14
- allowAfterSuper: false,
15
- enforceInMethodNames: true,
16
- allow: ['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__'],
17
- },
18
- ],
19
- // TODO check it later
20
- // Prevent missing displayName in a React component definition
21
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/display-name.md
22
- 'react/display-name': ['off', { ignoreTranspilerName: false }],
23
- // Enforce boolean attributes notation in JSX
24
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md
25
- 'react/jsx-boolean-value': ['error', 'never', { always: [] }],
26
- // Validate closing bracket location in JSX
27
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md
28
- 'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
29
- // Validate closing tag location in JSX
30
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md
31
- 'react/jsx-closing-tag-location': 'error',
32
- // Enforce or disallow spaces inside of curly braces in JSX attributes
33
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md
34
- 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
35
- // Validate props indentation in JSX
36
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md
37
- 'react/jsx-indent-props': ['error', 2],
38
- // Limit maximum of props on a single line in JSX
39
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md
40
- 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }],
41
- // Prevent usage of .bind() in JSX props
42
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
43
- 'react/jsx-no-bind': [
44
- 'error',
45
- {
46
- ignoreRefs: true,
47
- allowArrowFunctions: true,
48
- allowFunctions: false,
49
- allowBind: false,
50
- ignoreDOMComponents: true,
51
- },
52
- ],
53
- // Enforce PascalCase for user-defined JSX components
54
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md
55
- 'react/jsx-pascal-case': [
56
- 'error',
57
- {
58
- allowAllCaps: true,
59
- ignore: [],
60
- },
61
- ],
62
- // Prevent usage of dangerous JSX properties
63
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-danger.md
64
- 'react/no-danger': 'error',
65
- // Prevent usage of setState in componentDidUpdate
66
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md
67
- 'react/no-did-update-set-state': 'error',
68
- // Prevent usage of setState in componentWillUpdate
69
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-will-update-set-state.md
70
- 'react/no-will-update-set-state': 'error',
71
- // Prevent direct mutation of this.state
72
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md
73
- 'react/no-direct-mutation-state': 'off',
74
- // Require ES6 class declarations over React.createClass
75
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md
76
- 'react/prefer-es6-class': ['error', 'always'],
77
- // Require stateless functions when not using lifecycle methods, setState or ref
78
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md
79
- 'react/prefer-stateless-function': ['error', { ignorePureComponents: true }],
80
- // Prevent extra closing tags for components without children
81
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md
82
- 'react/self-closing-comp': 'error',
83
- // Enforce component methods order
84
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/sort-comp.md
85
- 'react/sort-comp': [
86
- 'error',
87
- {
88
- order: [
89
- 'static-variables',
90
- 'static-methods',
91
- 'instance-variables',
92
- 'lifecycle',
93
- '/^handle.+$/',
94
- '/^on.+$/',
95
- 'getters',
96
- 'setters',
97
- '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/',
98
- 'instance-methods',
99
- 'everything-else',
100
- 'rendering',
101
- ],
102
- groups: {
103
- lifecycle: [
104
- 'displayName',
105
- 'propTypes',
106
- 'contextTypes',
107
- 'childContextTypes',
108
- 'mixins',
109
- 'statics',
110
- 'defaultProps',
111
- 'constructor',
112
- 'getDefaultProps',
113
- 'getInitialState',
114
- 'state',
115
- 'getChildContext',
116
- 'getDerivedStateFromProps',
117
- 'componentWillMount',
118
- 'UNSAFE_componentWillMount',
119
- 'componentDidMount',
120
- 'componentWillReceiveProps',
121
- 'UNSAFE_componentWillReceiveProps',
122
- 'shouldComponentUpdate',
123
- 'componentWillUpdate',
124
- 'UNSAFE_componentWillUpdate',
125
- 'getSnapshotBeforeUpdate',
126
- 'componentDidUpdate',
127
- 'componentDidCatch',
128
- 'componentWillUnmount',
129
- ],
130
- rendering: ['/^render.+$/', 'render'],
131
- },
132
- },
133
- ],
134
- // Prevent missing parentheses around multilines JSX
135
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-wrap-multilines.md
136
- 'react/jsx-wrap-multilines': [
137
- 'error',
138
- {
139
- declaration: 'parens-new-line',
140
- assignment: 'parens-new-line',
141
- return: 'parens-new-line',
142
- arrow: 'parens-new-line',
143
- condition: 'parens-new-line',
144
- logical: 'parens-new-line',
145
- prop: 'parens-new-line',
146
- },
147
- ],
148
- // Require that the first prop in a JSX element be on a new line when the element is multiline
149
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md
150
- 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
151
- // Enforce spacing around jsx equals signs
152
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-equals-spacing.md
153
- 'react/jsx-equals-spacing': ['error', 'never'],
154
- // Enforce JSX indentation
155
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md
156
- 'react/jsx-indent': ['error', 2],
157
- // Disallow target="_blank" on links
158
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/ac102885765be5ff37847a871f239c6703e1c7cc/docs/rules/jsx-no-target-blank.md
159
- 'react/jsx-no-target-blank': ['error', { enforceDynamicLinks: 'always' }],
160
- // only .jsx files may have JSX
161
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md
162
- 'react/jsx-filename-extension': ['error', { extensions: ['.jsx'] }],
163
- // Require style prop value be an object or var
164
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/style-prop-object.md
165
- 'react/style-prop-object': 'error',
166
- // Validate whitespace in and around the JSX opening and closing brackets
167
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-tag-spacing.md
168
- 'react/jsx-tag-spacing': [
169
- 'error',
170
- {
171
- closingSlash: 'never',
172
- beforeSelfClosing: 'always',
173
- afterOpening: 'never',
174
- beforeClosing: 'never',
175
- },
176
- ],
177
- // Enforce a defaultProps definition for every prop that is not a required prop
178
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/require-default-props.md
179
- 'react/require-default-props': [
180
- 'error',
181
- {
182
- forbidDefaultForRequired: true,
183
- },
184
- ],
185
- // Prevent void DOM elements from receiving children
186
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/void-dom-elements-no-children.md
187
- 'react/void-dom-elements-no-children': 'error',
188
- // Prevent usage of shouldComponentUpdate when extending React.PureComponent
189
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/9e13ae2c51e44872b45cc15bf1ac3a72105bdd0e/docs/rules/no-redundant-should-component-update.md
190
- 'react/no-redundant-should-component-update': 'error',
191
- // Prevent unused state values
192
- // https://github.com/jsx-eslint/eslint-plugin-react/pull/1103/
193
- 'react/no-unused-state': 'error',
194
- // Prevents common casing typos
195
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/73abadb697034b5ccb514d79fb4689836fe61f91/docs/rules/no-typos.md
196
- 'react/no-typos': 'error',
197
- // Enforce curly braces or disallow unnecessary curly braces in JSX props and/or children
198
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-curly-brace-presence.md
199
- 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }],
200
- // One JSX Element Per Line
201
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-one-expression-per-line.md
202
- 'react/jsx-one-expression-per-line': ['error', { allow: 'single-child' }],
203
- // Prevent using this.state within a this.setState
204
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-access-state-in-setstate.md
205
- 'react/no-access-state-in-setstate': 'error',
206
- // Prevent usage of button elements without an explicit type attribute
207
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/button-has-type.md
208
- 'react/button-has-type': [
209
- 'error',
210
- {
211
- button: true,
212
- submit: true,
213
- reset: false,
214
- },
215
- ],
216
- // Prevent this from being used in stateless functional components
217
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-this-in-sfc.md
218
- 'react/no-this-in-sfc': 'error',
219
- // Disallow multiple spaces between inline JSX props
220
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/ac102885765be5ff37847a871f239c6703e1c7cc/docs/rules/jsx-props-no-multi-spaces.md
221
- 'react/jsx-props-no-multi-spaces': 'error',
222
- // Enforce shorthand or standard form for React fragments
223
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/bc976b837abeab1dffd90ac6168b746a83fc83cc/docs/rules/jsx-fragments.md
224
- 'react/jsx-fragments': ['error', 'syntax'],
225
- // Enforce linebreaks in curly braces in JSX attributes and expressions.
226
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-curly-newline.md
227
- 'react/jsx-curly-newline': [
228
- 'error',
229
- {
230
- multiline: 'consistent',
231
- singleline: 'consistent',
232
- },
233
- ],
234
- // Disallow JSX props spreading
235
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md
236
- 'react/jsx-props-no-spreading': [
237
- 'error',
238
- {
239
- html: 'enforce',
240
- custom: 'enforce',
241
- explicitSpread: 'ignore',
242
- exceptions: [],
243
- },
244
- ],
245
- // Prevent usage of `javascript:` URLs
246
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-script-url.md
247
- 'react/jsx-no-script-url': [
248
- 'error',
249
- [
250
- {
251
- name: 'Link',
252
- props: ['to'],
253
- },
254
- ],
255
- ],
256
- // Disallow unnecessary fragments
257
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-useless-fragment.md
258
- 'react/jsx-no-useless-fragment': 'error',
259
- // Prevent react contexts from taking non-stable values
260
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/e2eaadae316f9506d163812a09424eb42698470a/docs/rules/jsx-no-constructed-context-values.md
261
- 'react/jsx-no-constructed-context-values': 'error',
262
- // Prevent creating unstable components inside components
263
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/c2a790a3472eea0f6de984bdc3ee2a62197417fb/docs/rules/no-unstable-nested-components.md
264
- 'react/no-unstable-nested-components': 'error',
265
- // Enforce that namespaces are not used in React elements
266
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/8785c169c25b09b33c95655bf508cf46263bc53f/docs/rules/no-namespace.md
267
- 'react/no-namespace': 'error',
268
- // Prefer exact proptype definitions
269
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/8785c169c25b09b33c95655bf508cf46263bc53f/docs/rules/prefer-exact-props.md
270
- 'react/prefer-exact-props': 'error',
271
- // Lifecycle methods should be methods on the prototype, not class fields
272
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/21e01b61af7a38fc86d94f27eb66cda8054582ed/docs/rules/no-arrow-function-lifecycle.md
273
- 'react/no-arrow-function-lifecycle': 'error',
274
- // Prevent usage of invalid attributes
275
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/21e01b61af7a38fc86d94f27eb66cda8054582ed/docs/rules/no-invalid-html-attribute.md
276
- 'react/no-invalid-html-attribute': 'error',
277
- // Prevent declaring unused methods of component class
278
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/21e01b61af7a38fc86d94f27eb66cda8054582ed/docs/rules/no-unused-class-component-methods.md
279
- 'react/no-unused-class-component-methods': 'error',
280
- // Ensure destructuring and symmetric naming of useState hook value and setter variables
281
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/c8833f301314dab3e79ef7ac4cf863e4d5fa0019/docs/rules/hook-use-state.md
282
- 'react/hook-use-state': 'error',
283
- // Enforce sandbox attribute on iframe elements
284
- // https://github.com/jsx-eslint/eslint-plugin-react/blob/c8833f301314dab3e79ef7ac4cf863e4d5fa0019/docs/rules/iframe-missing-sandbox.md
285
- 'react/iframe-missing-sandbox': 'error',
286
- /**
287
- * react-a11y
288
- * copied from
289
- * https://github.com/airbnb/javascript/blob/c25bce83be4db06e6a221d79686c485cd2ed5d5d/packages/eslint-config-airbnb/rules/react-a11y.js
290
- * */
291
- // Enforce that all elements that require alternative text have meaningful information
292
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md
293
- 'jsx-a11y/alt-text': [
294
- 'error',
295
- {
296
- elements: ['img', 'object', 'area', 'input[type="image"]'],
297
- img: [],
298
- object: [],
299
- area: [],
300
- 'input[type="image"]': [],
301
- },
302
- ],
303
- // Enforce that anchors have content
304
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md
305
- 'jsx-a11y/anchor-has-content': ['error', { components: [] }],
306
- // ensure <a> tags are valid
307
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/0745af376cdc8686d85a361ce36952b1fb1ccf6e/docs/rules/anchor-is-valid.md
308
- 'jsx-a11y/anchor-is-valid': [
309
- 'error',
310
- {
311
- components: ['Link'],
312
- specialLink: ['to'],
313
- aspects: ['noHref', 'invalidHref', 'preferButton'],
314
- },
315
- ],
316
- // elements with aria-activedescendant must be tabbable
317
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md
318
- 'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
319
- // Enforce all aria-* props are valid.
320
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md
321
- 'jsx-a11y/aria-props': 'error',
322
- // Enforce ARIA state and property values are valid.
323
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md
324
- 'jsx-a11y/aria-proptypes': 'error',
325
- // Require ARIA roles to be valid and non-abstract
326
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md
327
- 'jsx-a11y/aria-role': ['error', { ignoreNonDOM: false }],
328
- // Enforce that elements that do not support ARIA roles, states, and
329
- // properties do not have those attributes.
330
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md
331
- 'jsx-a11y/aria-unsupported-elements': 'error',
332
- // require onClick be accompanied by onKeyUp/onKeyDown/onKeyPress
333
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md
334
- 'jsx-a11y/click-events-have-key-events': 'error',
335
- // ensure <hX> tags have content and are not aria-hidden
336
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md
337
- 'jsx-a11y/heading-has-content': ['error', { components: [''] }],
338
- // require HTML elements to have a "lang" prop
339
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md
340
- 'jsx-a11y/html-has-lang': 'error',
341
- // ensure iframe elements have a unique title
342
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md
343
- 'jsx-a11y/iframe-has-title': 'error',
344
- // Prevent img alt text from containing redundant words like "image", "picture", or "photo"
345
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md
346
- 'jsx-a11y/img-redundant-alt': 'error',
347
- // Elements with an interactive role and interaction handlers must be focusable
348
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md
349
- 'jsx-a11y/interactive-supports-focus': 'error',
350
- // Enforce that a label tag has a text label and an associated control.
351
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/b800f40a2a69ad48015ae9226fbe879f946757ed/docs/rules/label-has-associated-control.md
352
- 'jsx-a11y/label-has-associated-control': [
353
- 'error',
354
- {
355
- labelComponents: [],
356
- labelAttributes: [],
357
- controlComponents: [],
358
- assert: 'both',
359
- depth: 25,
360
- },
361
- ],
362
- // require HTML element's lang prop to be valid
363
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/lang.md
364
- 'jsx-a11y/lang': 'error',
365
- // media elements must have captions
366
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md
367
- 'jsx-a11y/media-has-caption': [
368
- 'error',
369
- {
370
- audio: [],
371
- video: [],
372
- track: [],
373
- },
374
- ],
375
- // require that mouseover/out come with focus/blur, for keyboard-only users
376
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md
377
- 'jsx-a11y/mouse-events-have-key-events': 'error',
378
- // Prevent use of `accessKey`
379
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md
380
- 'jsx-a11y/no-access-key': 'error',
381
- // prevent distracting elements, like <marquee> and <blink>
382
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-distracting-elements.md
383
- 'jsx-a11y/no-distracting-elements': [
384
- 'error',
385
- {
386
- elements: ['marquee', 'blink'],
387
- },
388
- ],
389
- // WAI-ARIA roles should not be used to convert an interactive element to non-interactive
390
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-interactive-element-to-noninteractive-role.md
391
- 'jsx-a11y/no-interactive-element-to-noninteractive-role': [
392
- 'error',
393
- {
394
- tr: ['none', 'presentation'],
395
- },
396
- ],
397
- // A non-interactive element does not support event handlers (mouse and key handlers)
398
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-interactions.md
399
- 'jsx-a11y/no-noninteractive-element-interactions': [
400
- 'error',
401
- {
402
- handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'],
403
- },
404
- ],
405
- // WAI-ARIA roles should not be used to convert a non-interactive element to interactive
406
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-to-interactive-role.md
407
- 'jsx-a11y/no-noninteractive-element-to-interactive-role': [
408
- 'error',
409
- {
410
- ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
411
- ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
412
- li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
413
- table: ['grid'],
414
- td: ['gridcell'],
415
- },
416
- ],
417
- // Tab key navigation should be limited to elements on the page that can be interacted with.
418
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md
419
- 'jsx-a11y/no-noninteractive-tabindex': [
420
- 'error',
421
- {
422
- tags: [],
423
- roles: ['tabpanel'],
424
- allowExpressionValues: true,
425
- },
426
- ],
427
- // ensure HTML elements do not specify redundant ARIA roles
428
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-redundant-roles.md
429
- 'jsx-a11y/no-redundant-roles': [
430
- 'error',
431
- {
432
- nav: ['navigation'],
433
- },
434
- ],
435
- // Enforce that DOM elements without semantic behavior not have interaction handlers
436
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md
437
- 'jsx-a11y/no-static-element-interactions': [
438
- 'error',
439
- {
440
- handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'],
441
- },
442
- ],
443
- // Enforce that elements with ARIA roles must have all required attributes
444
- // for that role.
445
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md
446
- 'jsx-a11y/role-has-required-aria-props': 'error',
447
- // Enforce that elements with explicit or implicit roles defined contain
448
- // only aria-* properties supported by that role.
449
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md
450
- 'jsx-a11y/role-supports-aria-props': 'error',
451
- // only allow <th> to have the "scope" attr
452
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/scope.md
453
- 'jsx-a11y/scope': 'error',
454
- // Enforce tabIndex value is not greater than zero.
455
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md
456
- 'jsx-a11y/tabindex-no-positive': 'error',
457
- // ----------------------------------------------------
458
- // Rules that no longer exist in eslint-plugin-jsx-a11y
459
- // ----------------------------------------------------
460
- // Ensures anchor text is not ambiguous
461
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/93f78856655696a55309440593e0948c6fb96134/docs/rules/anchor-ambiguous-text.md
462
- 'jsx-a11y/anchor-ambiguous-text': 'error',
463
- // Enforce that aria-hidden="true" is not set on focusable elements.
464
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/93f78856655696a55309440593e0948c6fb96134/docs/rules/no-aria-hidden-on-focusable.md
465
- 'jsx-a11y/no-aria-hidden-on-focusable': 'error',
466
- // Enforces using semantic DOM elements over the ARIA role property.
467
- // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/93f78856655696a55309440593e0948c6fb96134/docs/rules/prefer-tag-over-role.md
468
- 'jsx-a11y/prefer-tag-over-role': 'error',
469
- };
470
- export default rules;