@dartess/eslint-plugin 0.5.0 → 0.7.1

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +23 -20
  3. package/dist/configs/mobx.js +3 -3
  4. package/dist/configs/react.js +28 -26
  5. package/dist/configs/recommended.js +1 -1
  6. package/dist/configs/storybook.js +1 -1
  7. package/dist/configs/vendor-rules/variables.d.ts +1 -1
  8. package/dist/index.js +13 -13
  9. package/dist/rules/{max-parent-import-depth.js → imports-max-parent-depth.js} +1 -1
  10. package/dist/rules/{prevent-mixing-external-and-internal-classes.js → jsx-no-cross-context-classes.js} +1 -1
  11. package/dist/rules/{jsx-text-as-child.js → jsx-no-text-as-child.js} +1 -1
  12. package/dist/rules/{require-observer.js → mobx-require-observer.js} +1 -1
  13. package/dist/rules/{strict-observable-components-declaration.js → mobx-strict-observable-components-declaration.js} +1 -1
  14. package/docs/rules/{max-parent-import-depth.md → imports-max-parent-depth.md} +1 -1
  15. package/docs/rules/{prevent-mixing-external-and-internal-classes.md → jsx-no-cross-context-classes.md} +1 -1
  16. package/docs/rules/{require-observer.md → mobx-require-observer.md} +1 -1
  17. package/docs/rules/{strict-observable-components-declaration.md → mobx-strict-observable-components-declaration.md} +3 -3
  18. package/docs/rules/mobx-sync-action.md +1 -1
  19. package/docs/rules/mobx-sync-autorun.md +1 -1
  20. package/docs/rules/stories-export-meta.md +1 -1
  21. package/docs/rules/stories-export-typed.md +1 -1
  22. package/package.json +9 -5
  23. package/dist/configs/vendor-rules/react.d.ts +0 -213
  24. package/dist/configs/vendor-rules/react.js +0 -470
  25. /package/dist/rules/{max-parent-import-depth.d.ts → imports-max-parent-depth.d.ts} +0 -0
  26. /package/dist/rules/{prevent-mixing-external-and-internal-classes.d.ts → jsx-no-cross-context-classes.d.ts} +0 -0
  27. /package/dist/rules/{jsx-text-as-child.d.ts → jsx-no-text-as-child.d.ts} +0 -0
  28. /package/dist/rules/{require-observer.d.ts → mobx-require-observer.d.ts} +0 -0
  29. /package/dist/rules/{strict-observable-components-declaration.d.ts → mobx-strict-observable-components-declaration.d.ts} +0 -0
  30. /package/docs/rules/{jsx-text-as-child.md → jsx-no-text-as-child.md} +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  [//]: # (https://keepachangelog.com/en/1.1.0/)
4
4
 
5
+ ## [0.7.1] - 2026-01-18
6
+ - rename some rules for more clear naming and consistency:
7
+
8
+ * `jsx-text-as-child` -> `jsx-no-text-as-child`
9
+ * `prevent-mixing-external-and-internal-classes` -> `jsx-no-cross-context-classes`
10
+ * `max-parent-import-depth` -> `imports-max-parent-depth`
11
+ * `strict-observable-components-declaration` -> `mobx-strict-observable-components-declaration`
12
+ * `require-observer` -> `mobx-require-observer`
13
+
14
+ Please, rename rules in your config, if you're using them directly
15
+
16
+ ## [0.6.0] - 2026-01-17
17
+ - replace legacy `eslint-plugin-react` with modern `@eslint-react/eslint-plugin`
18
+
19
+ If you're using React: uninstall `eslint-plugin-react`, then install `@eslint-react/eslint-plugin` and `@stylistic/eslint-plugin`.
20
+
5
21
  ## [0.5.0] - 2026-01-16
6
22
  - add rule `@dartess/mobx-sync-action`
7
23
  - add `@dartess/mobx-sync-action` 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
@@ -155,23 +158,23 @@ Each rule has emojis denoting:
155
158
  - 🔧 if some problems reported by the rule are automatically fixable by the `--fix` [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) option
156
159
  - 💡 if some problems reported by the rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions)
157
160
 
158
- | Name | Description | ✅ | 🔧 | 💡 |
159
- |:-----------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------|:--|:---|:---|
160
- | **imports** | _config: recommended_ | | | |
161
- | [max-parent-import-depth](docs/rules/max-parent-import-depth.md) | Limit relative imports to a maximum parent depth. | ✅ | | |
162
- | **TypeScript** | _config: recommended_ | | | |
163
- | [ts-named-tuple-elements](docs/rules/ts-named-tuple-elements.md) | Enforce (or forbid) named tuple elements | ✅ | | |
164
- | **React** | _config: react_ | | | |
165
- | [jsx-no-text-as-child](docs/rules/jsx-text-as-child.md) | JSX elements should not have text without translation | | | |
166
- | [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. | | | |
167
- | **Storybook** | _config: storybook_ | | | |
168
- | [stories-export-meta](docs/rules/stories-export-meta.md) | Storybook's Meta should be typed | ✅ | | |
169
- | [stories-export-typed](docs/rules/stories-export-typed.md) | Storybook's Stories should be typed | ✅ | | |
170
- | **MobX** | _config: mobx_ | | | |
171
- | [strict-observable-components-declaration](docs/rules/strict-observable-components-declaration.md) | Wrapping components in `observer` must comply with the regulations. | ✅ | | |
172
- | [require-observer](docs/rules/require-observer.md) | Components using the stores must be wrapped in an `observer` | ✅ | 🔧 | |
173
- | [mobx-sync-autorun](docs/rules/mobx-sync-autorun.md) | Enforce synchronous autorun callback | ✅ | | |
174
- | [mobx-sync-action](docs/rules/mobx-sync-action.md) | Enforce synchronous actions | | | |
161
+ | Name | Description | ✅ | 🔧 | 💡 |
162
+ |:-------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------|:--|:---|:---|
163
+ | **imports** | _config: recommended_ | | | |
164
+ | [imports-max-parent-depth](docs/rules/imports-max-parent-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_ | | | |
168
+ | [jsx-no-text-as-child](docs/rules/jsx-no-text-as-child.md) | JSX elements should not have text without translation | | | |
169
+ | [jsx-no-cross-context-classes](docs/rules/jsx-no-cross-context-classes.md) | Prevent mixing of outer and inner classes to avoid dependency on style order. | | | |
170
+ | **Storybook** | _config: storybook_ | | | |
171
+ | [stories-export-meta](docs/rules/stories-export-meta.md) | Storybook's Meta should be typed | ✅ | | |
172
+ | [stories-export-typed](docs/rules/stories-export-typed.md) | Storybook's Stories should be typed | ✅ | | |
173
+ | **MobX** | _config: mobx_ | | | |
174
+ | [mobx-strict-observable-components-declaration](docs/rules/mobx-strict-observable-components-declaration.md) | Wrapping components in `observer` must comply with the regulations. | ✅ | | |
175
+ | [mobx-require-observer](docs/rules/mobx-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 || | |
175
178
 
176
179
  ## Code Reuse Policy
177
180
 
@@ -4,10 +4,10 @@ const config = [
4
4
  {
5
5
  name: '@dartess/mobx',
6
6
  rules: {
7
- 'mobx/missing-observer': 'off', // replaced by the neater "@dartess/require-observer"
7
+ 'mobx/missing-observer': 'off', // replaced by the neater "@dartess/mobx-require-observer"
8
8
  'mobx/missing-make-observable': 'off', // useless with modern decorators syntax. TODO check original plugin?
9
- '@dartess/strict-observable-components-declaration': 'error',
10
- '@dartess/require-observer': 'error',
9
+ '@dartess/mobx-strict-observable-components-declaration': 'error',
10
+ '@dartess/mobx-require-observer': 'error',
11
11
  '@dartess/mobx-sync-autorun': 'error', // TODO implement it by types?
12
12
  '@dartess/mobx-sync-action': 'error', // TODO implement it by types?
13
13
  },
@@ -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
  ];
@@ -84,7 +84,7 @@ const config = [
84
84
  ],
85
85
  'unicorn/no-useless-undefined': 'error',
86
86
  'unicorn/prefer-node-protocol': 'error',
87
- '@dartess/max-parent-import-depth': 'error',
87
+ '@dartess/imports-max-parent-depth': 'error',
88
88
  'import-x/order': [
89
89
  'error',
90
90
  {
@@ -13,7 +13,7 @@ const config = [
13
13
  '@dartess/stories-export-meta': 'error', // TODO can be replaced with native storybook/meta-satisfies-type ?
14
14
  '@dartess/stories-export-typed': 'error',
15
15
  '@typescript-eslint/no-explicit-any': 'off', // can be hard for typing in stories
16
- '@dartess/jsx-text-as-child': 'off', // not necessary in stories
16
+ '@dartess/jsx-no-text-as-child': 'off', // not necessary in stories
17
17
  },
18
18
  },
19
19
  ];
@@ -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
@@ -1,11 +1,11 @@
1
1
  import packageJson from '../package.json' with { type: 'json' };
2
- import ruleJsxTextAsChildFrom from "./rules/jsx-text-as-child.js";
3
- import rulePreventMixingExternalAndInternalClasses from "./rules/prevent-mixing-external-and-internal-classes.js";
2
+ import ruleJsxNoTextAsChild from "./rules/jsx-no-text-as-child.js";
3
+ import ruleJsxNoCrossContextClasses from "./rules/jsx-no-cross-context-classes.js";
4
4
  import ruleStoriesExportMeta from "./rules/stories-export-meta.js";
5
5
  import ruleStoriesExportTyped from "./rules/stories-export-typed.js";
6
- import ruleStrictObservableComponentsDeclaration from "./rules/strict-observable-components-declaration.js";
7
- import ruleRequireObserver from "./rules/require-observer.js";
8
- import ruleMaxParentImportDepth from "./rules/max-parent-import-depth.js";
6
+ import ruleMobxStrictObservableComponentsDeclaration from "./rules/mobx-strict-observable-components-declaration.js";
7
+ import ruleMobxRequireObserver from "./rules/mobx-require-observer.js";
8
+ import ruleImportsMaxParentDepth from "./rules/imports-max-parent-depth.js";
9
9
  import ruleTsNamedTupleElements from "./rules/ts-named-tuple-elements.js";
10
10
  import ruleMobxSyncAutorun from "./rules/mobx-sync-autorun.js";
11
11
  import ruleMobxSyncAction from "./rules/mobx-sync-action.js";
@@ -16,16 +16,16 @@ const plugin = {
16
16
  },
17
17
  processors: {},
18
18
  rules: {
19
- 'jsx-text-as-child': ruleJsxTextAsChildFrom,
20
- 'prevent-mixing-external-and-internal-classes': rulePreventMixingExternalAndInternalClasses,
21
- 'stories-export-meta': ruleStoriesExportMeta,
19
+ 'imports-max-parent-depth': ruleImportsMaxParentDepth,
20
+ 'jsx-no-cross-context-classes': ruleJsxNoCrossContextClasses,
21
+ 'jsx-no-text-as-child': ruleJsxNoTextAsChild,
22
+ 'mobx-strict-observable-components-declaration': ruleMobxStrictObservableComponentsDeclaration,
23
+ 'mobx-sync-action': ruleMobxSyncAction,
24
+ 'mobx-sync-autorun': ruleMobxSyncAutorun,
25
+ 'mobx-require-observer': ruleMobxRequireObserver,
22
26
  'stories-export-typed': ruleStoriesExportTyped,
23
- 'strict-observable-components-declaration': ruleStrictObservableComponentsDeclaration,
24
- 'require-observer': ruleRequireObserver,
25
- 'max-parent-import-depth': ruleMaxParentImportDepth,
27
+ 'stories-export-meta': ruleStoriesExportMeta,
26
28
  'ts-named-tuple-elements': ruleTsNamedTupleElements,
27
- 'mobx-sync-autorun': ruleMobxSyncAutorun,
28
- 'mobx-sync-action': ruleMobxSyncAction,
29
29
  },
30
30
  };
31
31
  export default plugin;
@@ -1,6 +1,6 @@
1
1
  import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
2
2
  export default ESLintUtils.RuleCreator(() => '')({
3
- name: 'max-parent-import-depth',
3
+ name: 'imports-max-parent-depth',
4
4
  defaultOptions: [],
5
5
  meta: {
6
6
  type: 'problem',
@@ -1,6 +1,6 @@
1
1
  import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
2
2
  export default ESLintUtils.RuleCreator(() => '')({
3
- name: 'prevent-mixing-external-and-internal-classes',
3
+ name: 'jsx-no-cross-context-classes',
4
4
  defaultOptions: [{}],
5
5
  meta: {
6
6
  type: 'suggestion',
@@ -5,7 +5,7 @@ import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
5
5
  */
6
6
  import emojiRegex from 'emoji-regex';
7
7
  export default ESLintUtils.RuleCreator(() => '')({
8
- name: 'jsx-text-as-child',
8
+ name: 'jsx-no-text-as-child',
9
9
  defaultOptions: [{}],
10
10
  meta: {
11
11
  type: 'problem',
@@ -14,7 +14,7 @@ function isCustomHook(fn) {
14
14
  return false;
15
15
  }
16
16
  export default ESLintUtils.RuleCreator(() => '')({
17
- name: 'require-observer',
17
+ name: 'mobx-require-observer',
18
18
  meta: {
19
19
  type: 'problem',
20
20
  docs: {
@@ -1,6 +1,6 @@
1
1
  import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
2
2
  export default ESLintUtils.RuleCreator(() => '')({
3
- name: 'strict-observable-components-declaration',
3
+ name: 'mobx-strict-observable-components-declaration',
4
4
  defaultOptions: [{}],
5
5
  meta: {
6
6
  type: 'suggestion',
@@ -1,4 +1,4 @@
1
- # Disallow relative imports going up more than a specified number of parent directories (max-parent-import-depth)
1
+ # Disallow relative imports going up more than a specified number of parent directories (imports-max-parent-depth)
2
2
 
3
3
  This rule limits the number of parent directory (../) levels allowed in import and export statements to enforce a flatter and more maintainable project structure.
4
4
 
@@ -1,4 +1,4 @@
1
- # Prevent mixing of outer and inner classes to avoid dependency on style order (prevent-mixing-external-and-internal-classes)
1
+ # Prevent mixing of outer and inner classes to avoid dependency on style order (jsx-no-cross-context-classes)
2
2
 
3
3
  Avoid mixing outer and inner classes on the same element. The import order of the style is not guaranteed,
4
4
  so the order in which the style is applied is also not guaranteed.
@@ -1,4 +1,4 @@
1
- # Require wrap components in observer if needed (require-observer)
1
+ # Require wrap components in observer if needed (mobx-require-observer)
2
2
 
3
3
  This rule requires that React components using specified store hooks are wrapped in `observer()` from `mobx-react-lite`.
4
4
 
@@ -1,4 +1,4 @@
1
- # Wrapping components in `observer` must comply with the regulations (strict-observable-components-declaration)
1
+ # Wrapping components in `observer` must comply with the regulations (mobx-strict-observable-components-declaration)
2
2
 
3
3
  For more convenient work and debugging, several factors must be agreed upon:
4
4
  the component that is passed to the observer must have the same name as
@@ -44,7 +44,7 @@ const Component = observer(function Component() {})
44
44
 
45
45
  ```json
46
46
  {
47
- "@dartess/strict-observable-components-declaration": ["error", {"ignoreObserverArg": ["forwardRef"]}]
47
+ "@dartess/mobx-strict-observable-components-declaration": ["error", {"ignoreObserverArg": ["forwardRef"]}]
48
48
  }
49
49
  ```
50
50
 
@@ -52,6 +52,6 @@ const Component = observer(function Component() {})
52
52
 
53
53
  ```json
54
54
  {
55
- "@dartess/strict-observable-components-declaration": ["error", {"allowedHocs": ["someHocName"]}]
55
+ "@dartess/mobx-strict-observable-components-declaration": ["error", {"allowedHocs": ["someHocName"]}]
56
56
  }
57
57
  ```
@@ -1,4 +1,4 @@
1
- # Enforce synchronous actions
1
+ # Enforce synchronous actions (mobx-sync-action)
2
2
 
3
3
  Mobx methods marked as `@action` must be synchronous: https://mobx.js.org/actions.html#asynchronous-actions
4
4
 
@@ -1,4 +1,4 @@
1
- # Enforce synchronous autorun callback
1
+ # Enforce synchronous autorun callback (mobx-sync-autorun)
2
2
 
3
3
  Mobx `autorun` function must accept only synchronous `effect` callback.
4
4
  This follows from the rules from official documentation, https://mobx.js.org/reactions.html#rules #2:
@@ -1,4 +1,4 @@
1
- # Makes meta-information typing mandatory
1
+ # Makes meta-information typing mandatory (stories-export-meta)
2
2
 
3
3
  Storybook stories should contain meta information. Thanks to this rule, meta-information will always be typed.
4
4
 
@@ -1,4 +1,4 @@
1
- # Makes stories typing mandatory
1
+ # Makes stories typing mandatory (stories-export-typed)
2
2
 
3
3
  Forces typing of exported stories.
4
4
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dartess/eslint-plugin",
3
3
  "type": "module",
4
- "version": "0.5.0",
4
+ "version": "0.7.1",
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;