@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 +9 -0
- package/README.md +18 -11
- package/dist/configs/mobx.js +3 -2
- package/dist/configs/react.js +28 -26
- package/dist/configs/vendor-rules/variables.d.ts +1 -1
- package/dist/index.js +2 -0
- package/dist/rules/mobx-sync-action.d.ts +3 -0
- package/dist/rules/mobx-sync-action.js +28 -0
- package/docs/rules/mobx-sync-action.md +27 -0
- package/package.json +9 -5
- package/dist/configs/vendor-rules/react.d.ts +0 -213
- package/dist/configs/vendor-rules/react.js +0 -470
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
|
-
*
|
|
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
|
|
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
|
-
|
|
|
163
|
-
| [
|
|
164
|
-
|
|
|
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
|
-
|
|
|
169
|
-
| [
|
|
170
|
-
| [
|
|
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
|
|
package/dist/configs/mobx.js
CHANGED
|
@@ -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
|
];
|
package/dist/configs/react.js
CHANGED
|
@@ -1,33 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
-
|
|
67
|
-
//
|
|
68
|
-
'react/
|
|
69
|
-
//
|
|
70
|
-
'react/
|
|
71
|
-
'react/
|
|
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" | "
|
|
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,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
|
+
"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
|
|
73
|
+
"@stylistic/eslint-plugin": {
|
|
70
74
|
"optional": true
|
|
71
75
|
},
|
|
72
|
-
"eslint-plugin-
|
|
76
|
+
"eslint-plugin-jsx-a11y": {
|
|
73
77
|
"optional": true
|
|
74
78
|
},
|
|
75
|
-
"eslint-plugin-
|
|
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;
|