@perfective/eslint-config-react 0.16.0 → 0.17.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.
Files changed (44) hide show
  1. package/LICENSE +1 -1
  2. package/README.adoc +66 -42
  3. package/README.md +60 -48
  4. package/config/jsx-a11y/jsx-a11y-config.d.ts +2 -0
  5. package/config/jsx-a11y/jsx-a11y-config.js +81 -0
  6. package/config/perfective-eslint-react-config.d.ts +7 -0
  7. package/config/perfective-eslint-react-config.js +24 -0
  8. package/config/react/jsx.d.ts +1 -0
  9. package/config/react/jsx.js +88 -0
  10. package/config/react/react-config.d.ts +2 -0
  11. package/config/react/react-config.js +139 -0
  12. package/config/react-hooks/react-hooks-config.d.ts +2 -0
  13. package/config/react-hooks/react-hooks-config.js +14 -0
  14. package/config/react-perf/react-perf-config.d.ts +2 -0
  15. package/config/react-perf/react-perf-config.js +14 -0
  16. package/config/testing-library/index.d.ts +1 -0
  17. package/config/testing-library/index.js +1 -0
  18. package/config/testing-library/testing-library-config.d.ts +8 -0
  19. package/config/testing-library/testing-library-config.js +14 -0
  20. package/config/typescript-eslint/index.d.ts +1 -0
  21. package/config/typescript-eslint/index.js +1 -0
  22. package/{rules/eslint-config → config/typescript-eslint}/rules/typescript-eslint.d.ts +5 -1
  23. package/config/typescript-eslint/rules/typescript-eslint.js +11 -0
  24. package/config/unicorn/index.d.ts +1 -0
  25. package/config/unicorn/index.js +1 -0
  26. package/{rules/eslint-config → config/unicorn}/rules/unicorn.d.ts +4 -1
  27. package/config/unicorn/rules/unicorn.js +9 -0
  28. package/index.d.ts +1 -0
  29. package/index.js +1 -58
  30. package/package.json +29 -8
  31. package/testing-library/package.json +13 -0
  32. package/typescript-eslint/package.json +13 -0
  33. package/unicorn/package.json +13 -0
  34. package/rules/eslint-config/index.js +0 -15
  35. package/rules/eslint-config/rules/typescript-eslint.js +0 -17
  36. package/rules/eslint-config/rules/unicorn.js +0 -7
  37. package/rules/jsx-a11y/index.js +0 -79
  38. package/rules/react/index.js +0 -159
  39. package/rules/react/jsx.js +0 -91
  40. package/rules/react-hooks/index.js +0 -10
  41. package/rules/react-hooks-ssr/index.js +0 -9
  42. package/rules/react-perf/index.js +0 -12
  43. package/rules.d.ts +0 -3
  44. package/rules.js +0 -13
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2020-2024 Andrey Mikheychik (https://github.com/amikheychik)
3
+ Copyright (c) 2020-2026 Andrey Mikheychik (https://github.com/amikheychik)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.adoc CHANGED
@@ -2,75 +2,99 @@
2
2
 
3
3
  `@perfective/eslint-config-react` provides
4
4
  a https://eslint.org/docs/latest/developer-guide/shareable-configs[shareable ESLint configuration]
5
- for developing the `@perfective` https://reactjs.org[React] packages.
6
- This package extends the
7
- `link:https://www.npmjs.com/package/@perfective/eslint-config[@perfective/eslint-config]` package.
5
+ for https://reactjs.org[React] development.
8
6
 
9
- `@perfective/eslint-config-react` uses the following ESLint plugins:
7
+ `@perfective/eslint-config-react` adds the following ESLint plugins to the
8
+ `link:https://www.npmjs.com/package/@perfective/eslint-config[@perfective/eslint-config]` configuration:
10
9
 
11
10
  * `link:https://github.com/jsx-eslint/eslint-plugin-react[eslint-plugin-react]`;
12
11
  * `link:https://www.npmjs.com/package/eslint-plugin-react-hooks[eslint-plugin-react-hooks]`;
13
- * `link:https://github.com/correttojs/eslint-plugin-react-hooks-ssr[eslint-plugin-react-hooks-ssr]`;
14
12
  * `link:https://github.com/cvazac/eslint-plugin-react-perf[eslint-plugin-react-perf]`;
15
13
  * `link:https://github.com/jsx-eslint/eslint-plugin-jsx-a11y[eslint-plugin-jsx-a11y]`.
16
14
 
17
15
 
18
16
  == Setup
19
17
 
20
- . Require `@perfective/eslint-config-react` and its peer dependencies as dev dependencies:
18
+ . Require `@perfective/eslint-config-react`:
19
+ +
20
+ [source,bash]
21
+ ----
22
+ npm install --save-dev @perfective/eslint-config-react
23
+ ----
24
+ +
25
+ Required peer dependencies are installed automatically.
26
+ +
27
+ . Import `perfectiveEslintReactConfig` to `eslint.config.js`:
28
+ +
29
+ [source,javascript]
30
+ ----
31
+ import { perfectiveEslintReactConfig } from '@perfective/eslint-config-react';
32
+
33
+ export default perfectiveEslintReactConfig();
34
+ ----
35
+ +
36
+ . _Optional_ Install optional peer dependencies to add tool-specific linting rules.
21
37
  +
22
38
  [source,bash]
23
39
  ----
24
40
  npm install --save-dev \
25
- @perfective/eslint-config-react \
26
- @babel/eslint-parser \
27
- @typescript-eslint/eslint-plugin \
28
- @typescript-eslint/parser \
29
- eslint \
30
- eslint-import-resolver-typescript \
31
- eslint-plugin-array-func \
32
41
  eslint-plugin-cypress \
33
- eslint-plugin-eslint-comments \
34
- eslint-plugin-import \
35
42
  eslint-plugin-jest \
36
43
  eslint-plugin-jest-dom \
37
- eslint-plugin-jsdoc \
38
- eslint-plugin-jsx-a11y \
39
- eslint-plugin-n \
40
- eslint-plugin-prefer-arrow \
41
- eslint-plugin-promise \
42
- eslint-plugin-react \
43
- eslint-plugin-react-hooks \
44
- eslint-plugin-react-hooks-ssr \
45
- eslint-plugin-react-perf \
46
- eslint-plugin-rxjs \
47
- eslint-plugin-security \
48
- eslint-plugin-simple-import-sort \
49
- eslint-plugin-sonarjs \
50
- eslint-plugin-testing-library \
51
- eslint-plugin-unicorn
44
+ eslint-plugin-rxjs-x \
45
+ eslint-plugin-testing-library
52
46
  ----
53
47
  +
54
- . Require the configuration in your root `.eslintrc.js`.
48
+ Import configurations to `eslint.config.js`.
55
49
  +
56
50
  [source,javascript]
57
51
  ----
58
- module.exports = {
59
- extends: ['@perfective/eslint-config-react'],
60
- }
52
+ import { perfectiveEslintReactConfig } from '@perfective/eslint-config-react';
53
+
54
+ // Optional dependencies.
55
+ import { cypressConfig } from '@perfective/eslint-config/cypress';
56
+ import { jestConfig, jestTypescriptConfig } from '@perfective/eslint-config/jest';
57
+ import { jestDomConfig } from '@perfective/eslint-config/jest-dom';
58
+ import { rxjsConfig } from '@perfective/eslint-config/rxjs';
59
+ import { testingLibraryConfig } from '@perfective/eslint-config-react/testing-library';
60
+
61
+ export default perfectiveEslintReactConfig([
62
+ cypressConfig,
63
+ jestConfig,
64
+ jestTypescriptConfig,
65
+ jestDomConfig,
66
+ rxjsConfig,
67
+ testingLibraryConfig,
68
+ ]);
61
69
  ----
70
+ +
71
+ NOTE: `*.d.ts` files and `dist` directories are ignored by the configuration.
72
+ `node_modules` and dot-files are ignored by the `eslint`.
73
+ If more directories or file types need to be ignored, see the
74
+ `link:https://eslint.org/docs/latest/use/configure/ignore#the-eslintignore-file[.eslintignore]` file docs.
75
+
76
+
77
+ == Packages
78
+
79
+ The following is the list of available packages and their exports.
80
+
81
+ === `@perfective/eslint-config-react`
62
82
 
83
+ * `perfectiveEslintReactConfig(configs: Linter.Config[] = []): Linter.Config[]`
84
+ — creates a list of flat configs.
63
85
 
64
- == Rules Configuration Extension Functions
86
+ === `@perfective/eslint-config-react/typescript-eslint`
65
87
 
66
- This package re-exports
67
- https://github.com/perfective/eslint-config#rules-configuration-extension-functions[rules configuration functions],
68
- including overrides with additional React customizations:
88
+ * `typescriptEslintNamingConvention(extensions: TypescriptEslintNamingConvention[] = []): TypescriptEslintNamingConvention[]`
89
+ — creates a React-compatible configuration with the given extensions
90
+ for the `@typescript-eslint/naming-convention` rule.
69
91
 
70
- * `typescriptEslintNamingConvention(extensions)`;
71
- * `unicornPreventAbbreviations(replacements, options)`.
92
+ === `@perfective/eslint-config-react/testing-library`
72
93
 
94
+ * `testingLibraryConfig(files: Glob[] = jestFiles): Linter.Config`
95
+ — creates a flat config for `eslint-plugin-testing-library` for a given list of files globs.
73
96
 
74
- == Roadmap
97
+ === `@perfective/eslint-config-react/unicorn`
75
98
 
76
- * Research more ESLint React plugins.
99
+ * `unicornPreventAbbreviations(replacements: UnicornPreventAbbreviationReplacements = {}, options: Partial<Pick<UnicornPreventAbbreviations, 'checkProperties'>> = {}): UnicornPreventAbbreviations`
100
+ — adds React-specific abbreviations for the `unicorn/prevent-abbreviations` rule.
package/README.md CHANGED
@@ -2,59 +2,71 @@
2
2
 
3
3
  `@perfective/eslint-config-react` provides
4
4
  a [shareable ESLint configuration](https://eslint.org/docs/latest/developer-guide/shareable-configs)
5
- for developing the `@perfective` [React](https://reactjs.org) packages.
6
- This package extends the
7
- [`@perfective/eslint-config`](https://www.npmjs.com/package/@perfective/eslint-config) package.
5
+ for [React](https://reactjs.org) development.
8
6
 
9
- `@perfective/eslint-config-react` uses the following ESLint plugins:
7
+ `@perfective/eslint-config-react` adds the following ESLint plugins to the
8
+ [`@perfective/eslint-config`](https://www.npmjs.com/package/@perfective/eslint-config) configuration:
10
9
 
11
- - [`eslint-plugin-react`](https://github.com/jsx-eslint/eslint-plugin-react);
12
- - [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks);
13
- - [`eslint-plugin-react-hooks-ssr`](https://github.com/correttojs/eslint-plugin-react-hooks-ssr);
14
- - [`eslint-plugin-react-perf`](https://github.com/cvazac/eslint-plugin-react-perf);
15
- - [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y).
10
+ - [`eslint-plugin-react`](https://github.com/jsx-eslint/eslint-plugin-react);
11
+ - [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks);
12
+ - [`eslint-plugin-react-perf`](https://github.com/cvazac/eslint-plugin-react-perf);
13
+ - [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y).
16
14
 
17
15
  ## Setup
18
16
 
19
- 1. Require `@perfective/eslint-config-react` and its peer dependencies as dev dependencies:
20
-
21
- ```bash
22
- npm install --save-dev \
23
- @perfective/eslint-config-react \
24
- @babel/eslint-parser \
25
- @typescript-eslint/eslint-plugin \
26
- @typescript-eslint/parser \
27
- eslint \
28
- eslint-import-resolver-typescript \
29
- eslint-plugin-array-func \
17
+ 1. Require `@perfective/eslint-config-react`:
18
+
19
+ ```bash
20
+ npm install --save-dev @perfective/eslint-config-react
21
+ ```
22
+
23
+ Required peer dependencies are installed automatically.
24
+
25
+ 2. Import `perfectiveEslintReactConfig` to `eslint.config.js`:
26
+
27
+ ```javascript
28
+ import { perfectiveEslintReactConfig } from '@perfective/eslint-config-react';
29
+
30
+ export default perfectiveEslintReactConfig();
31
+ ```
32
+
33
+ 3. _Optional_ Install optional peer dependencies to add tool-specific linting rules.
34
+
35
+ ```bash
36
+ npm install --save-dev \
30
37
  eslint-plugin-cypress \
31
- eslint-plugin-eslint-comments \
32
- eslint-plugin-import \
33
38
  eslint-plugin-jest \
34
39
  eslint-plugin-jest-dom \
35
- eslint-plugin-jsdoc \
36
- eslint-plugin-jsx-a11y \
37
- eslint-plugin-n \
38
- eslint-plugin-node \
39
- eslint-plugin-prefer-arrow \
40
- eslint-plugin-promise \
41
- eslint-plugin-react \
42
- eslint-plugin-react-hooks \
43
- eslint-plugin-react-hooks-ssr \
44
- eslint-plugin-react-perf \
45
- eslint-plugin-rxjs \
46
- eslint-plugin-simple-import-sort \
47
- eslint-plugin-sonarjs \
48
- eslint-plugin-testing-library \
49
- eslint-plugin-unicorn
50
- ```
51
-
52
- 2. Require the configuration in your root `.eslintrc.js`.
53
-
54
- ```javascript
55
- module.exports = {
56
- extends: ['@perfective/eslint-config-react'],
57
- };
58
- ```
59
-
60
- 3. Configure your `.eslintignore` file.
40
+ eslint-plugin-rxjs-x \
41
+ eslint-plugin-testing-library
42
+ ```
43
+
44
+ Import configurations to `eslint.config.js`.
45
+
46
+ ```javascript
47
+ import { perfectiveEslintReactConfig } from '@perfective/eslint-config-react';
48
+
49
+ // Optional dependencies.
50
+ import { cypressConfig } from '@perfective/eslint-config/cypress';
51
+ import { jestConfig, jestTypescriptConfig } from '@perfective/eslint-config/jest';
52
+ import { jestDomConfig } from '@perfective/eslint-config/jest-dom';
53
+ import { rxjsConfig } from '@perfective/eslint-config/rxjs';
54
+ import { testingLibraryConfig } from '@perfective/eslint-config-react/testing-library';
55
+
56
+ export default perfectiveEslintReactConfig([
57
+ cypressConfig,
58
+ jestConfig,
59
+ jestTypescriptConfig,
60
+ jestDomConfig,
61
+ rxjsConfig,
62
+ testingLibraryConfig,
63
+ ]);
64
+ ```
65
+
66
+ > **Note:** `*.d.ts` files and `dist` directories are ignored by the configuration.
67
+ > `node_modules` and dot-files are ignored by the `eslint`.
68
+ > If more directories or file types need to be ignored, see the
69
+ > [`.eslintignore` file](https://eslint.org/docs/latest/use/configure/ignore#the-eslintignore-file) docs.
70
+
71
+ Read the [full documentation](https://github.com/perfective/estlint-config-react/blob/main/README.adoc)
72
+ in the repository.
@@ -0,0 +1,2 @@
1
+ import { Linter } from 'eslint';
2
+ export declare function jsxA11yConfig(): Linter.Config;
@@ -0,0 +1,81 @@
1
+ import jsxA11yPlugin from 'eslint-plugin-jsx-a11y';
2
+ export function jsxA11yConfig() {
3
+ return {
4
+ plugins: {
5
+ 'jsx-a11y': jsxA11yPlugin
6
+ },
7
+ rules: {
8
+ 'jsx-a11y/accessible-emoji': 'error',
9
+ 'jsx-a11y/alt-text': 'error',
10
+ 'jsx-a11y/anchor-has-content': ['error', {
11
+ components: []
12
+ }],
13
+ 'jsx-a11y/anchor-is-valid': ['error', {
14
+ components: [],
15
+ specialLink: [],
16
+ aspects: ['noHref', 'invalidHref', 'preferButton']
17
+ }],
18
+ 'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
19
+ 'jsx-a11y/aria-props': 'error',
20
+ 'jsx-a11y/aria-proptypes': 'error',
21
+ 'jsx-a11y/aria-role': ['error', {
22
+ allowedInvalidRoles: [],
23
+ ignoreNonDOM: false
24
+ }],
25
+ 'jsx-a11y/aria-unsupported-elements': 'error',
26
+ 'jsx-a11y/autocomplete-valid': ['error', {
27
+ inputComponents: []
28
+ }],
29
+ 'jsx-a11y/click-events-have-key-events': 'error',
30
+ 'jsx-a11y/heading-has-content': ['error', {
31
+ components: []
32
+ }],
33
+ 'jsx-a11y/html-has-lang': 'error',
34
+ 'jsx-a11y/iframe-has-title': 'error',
35
+ 'jsx-a11y/img-redundant-alt': ['error', {
36
+ components: [],
37
+ words: []
38
+ }],
39
+ 'jsx-a11y/interactive-supports-focus': ['error', {
40
+ tabbable: []
41
+ }],
42
+ 'jsx-a11y/label-has-associated-control': ['error', {
43
+ labelComponents: [],
44
+ labelAttributes: [],
45
+ controlComponents: [],
46
+ assert: 'either',
47
+ depth: 2
48
+ }],
49
+ 'jsx-a11y/lang': 'error',
50
+ 'jsx-a11y/media-has-caption': ['error', {
51
+ audio: [],
52
+ video: [],
53
+ track: []
54
+ }],
55
+ 'jsx-a11y/mouse-events-have-key-events': ['error', {
56
+ hoverInHandlers: ['onMouseOver'],
57
+ hoverOutHandlers: ['onMouseOut']
58
+ }],
59
+ 'jsx-a11y/no-access-key': 'error',
60
+ 'jsx-a11y/no-aria-hidden-on-focusable': 'error',
61
+ 'jsx-a11y/no-autofocus': ['error', {
62
+ ignoreNonDOM: false
63
+ }],
64
+ 'jsx-a11y/no-distracting-elements': 'error',
65
+ 'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error',
66
+ 'jsx-a11y/no-noninteractive-element-interactions': 'error',
67
+ 'jsx-a11y/no-noninteractive-element-to-interactive-role': 'error',
68
+ 'jsx-a11y/no-noninteractive-tabindex': 'error',
69
+ 'jsx-a11y/no-onchange': 'error',
70
+ 'jsx-a11y/no-redundant-roles': ['error', {
71
+ nav: ['navigation']
72
+ }],
73
+ 'jsx-a11y/no-static-element-interactions': 'error',
74
+ 'jsx-a11y/prefer-tag-over-role': 'error',
75
+ 'jsx-a11y/role-has-required-aria-props': 'error',
76
+ 'jsx-a11y/role-supports-aria-props': 'error',
77
+ 'jsx-a11y/scope': 'error',
78
+ 'jsx-a11y/tabindex-no-positive': 'error'
79
+ }
80
+ };
81
+ }
@@ -0,0 +1,7 @@
1
+ import { Linter } from 'eslint';
2
+ /**
3
+ * Creates a list of flat configs.
4
+ *
5
+ * @since v0.17.0
6
+ */
7
+ export declare function perfectiveEslintReactConfig(configs?: Linter.Config[]): Linter.Config[];
@@ -0,0 +1,24 @@
1
+ import { perfectiveEslintConfig, typescriptFiles } from '@perfective/eslint-config';
2
+ import { jsxA11yConfig } from "./jsx-a11y/jsx-a11y-config.js";
3
+ import { reactConfig } from "./react/react-config.js";
4
+ import { reactHooksConfig } from "./react-hooks/react-hooks-config.js";
5
+ import { reactPerfConfig } from "./react-perf/react-perf-config.js";
6
+ import { typescriptEslintNamingConvention } from "./typescript-eslint/rules/typescript-eslint.js";
7
+ import { unicornPreventAbbreviations } from "./unicorn/rules/unicorn.js";
8
+ export function perfectiveEslintReactConfig(configs = []) {
9
+ return perfectiveEslintConfig([jsxA11yConfig, reactConfig, reactHooksConfig, reactPerfConfig, {
10
+ rules: {
11
+ '@stylistic/indent': ['warn', 4, {
12
+ SwitchCase: 1,
13
+ ignoredNodes: ['TSTypeParameterInstantiation']
14
+ }],
15
+ 'unicorn/prevent-abbreviations': ['warn', unicornPreventAbbreviations()]
16
+ }
17
+ }, {
18
+ files: typescriptFiles,
19
+ rules: {
20
+ '@typescript-eslint/naming-convention': ['error', ...typescriptEslintNamingConvention()],
21
+ 'prefer-arrow/prefer-arrow-functions': 'off'
22
+ }
23
+ }, ...configs]);
24
+ }
@@ -0,0 +1 @@
1
+ export declare const reactJsxRules: Record<string, unknown>;
@@ -0,0 +1,88 @@
1
+ export const reactJsxRules = {
2
+ 'react/jsx-boolean-value': ['warn', 'always'],
3
+ 'react/jsx-child-element-spacing': 'off',
4
+ 'react/jsx-closing-bracket-location': 'off',
5
+ 'react/jsx-closing-tag-location': 'off',
6
+ 'react/jsx-curly-brace-presence': 'off',
7
+ 'react/jsx-curly-newline': 'off',
8
+ 'react/jsx-curly-spacing': 'off',
9
+ 'react/jsx-equals-spacing': 'off',
10
+ 'react/jsx-filename-extension': ['error', {
11
+ allow: 'always',
12
+ extensions: ['.jsx', '.tsx'],
13
+ ignoreFilesWithoutCode: false
14
+ }],
15
+ 'react/jsx-first-prop-new-line': 'off',
16
+ 'react/jsx-fragments': ['warn', 'element'],
17
+ 'react/jsx-handler-names': ['error', {
18
+ eventHandlerPrefix: 'handle',
19
+ eventHandlerPropPrefix: 'on',
20
+ checkLocalVariables: true,
21
+ checkInlineFunction: true
22
+ }],
23
+ 'react/jsx-indent': 'off',
24
+ 'react/jsx-indent-props': 'off',
25
+ 'react/jsx-key': ['error', {
26
+ checkFragmentShorthand: true,
27
+ checkKeyMustBeforeSpread: true,
28
+ warnOnDuplicates: true
29
+ }],
30
+ 'react/jsx-max-depth': ['error', {
31
+ max: 4
32
+ }],
33
+ 'react/jsx-max-props-per-line': 'off',
34
+ 'react/jsx-newline': 'off',
35
+ 'react/jsx-no-bind': ['error', {
36
+ ignoreDOMComponents: false,
37
+ ignoreRefs: false,
38
+ allowArrowFunctions: false,
39
+ allowFunctions: false
40
+ }],
41
+ 'react/jsx-no-comment-textnodes': 'error',
42
+ 'react/jsx-no-constructed-context-values': 'error',
43
+ 'react/jsx-no-duplicate-props': ['error', {
44
+ ignoreCase: true
45
+ }],
46
+ 'react/jsx-no-leaked-render': ['warn', {
47
+ validStrategies: ['ternary']
48
+ }],
49
+ 'react/jsx-no-literals': ['error', {
50
+ noStrings: false,
51
+ allowedStrings: [],
52
+ ignoreProps: true,
53
+ noAttributeStrings: false
54
+ }],
55
+ 'react/jsx-props-no-spread-multi': 'error',
56
+ 'react/jsx-no-script-url': ['error', {
57
+ includeFromSettings: false
58
+ }],
59
+ 'react/jsx-no-target-blank': ['warn', {
60
+ allowReferrer: false,
61
+ enforceDynamicLinks: 'always',
62
+ forms: true,
63
+ links: true,
64
+ warnOnSpreadAttributes: true
65
+ }],
66
+ 'react/jsx-no-undef': ['error', {
67
+ allowGlobals: false
68
+ }],
69
+ 'react/jsx-no-useless-fragment': ['warn', {
70
+ allowExpressions: true
71
+ }],
72
+ 'react/jsx-one-expression-per-line': 'off',
73
+ 'react/jsx-pascal-case': 'off',
74
+ 'react/jsx-props-no-multi-spaces': 'off',
75
+ 'react/jsx-props-no-spreading': ['error', {
76
+ html: 'enforce',
77
+ custom: 'enforce',
78
+ explicitSpread: 'enforce',
79
+ exceptions: []
80
+ }],
81
+ 'react/jsx-sort-default-props': 'off',
82
+ 'react/jsx-sort-props': 'off',
83
+ 'react/jsx-space-before-closing': 'off',
84
+ 'react/jsx-tag-spacing': 'off',
85
+ 'react/jsx-uses-react': 'error',
86
+ 'react/jsx-uses-vars': 'error',
87
+ 'react/jsx-wrap-multilines': 'off'
88
+ };
@@ -0,0 +1,2 @@
1
+ import { Linter } from 'eslint';
2
+ export declare function reactConfig(): Linter.Config;
@@ -0,0 +1,139 @@
1
+ import react from 'eslint-plugin-react';
2
+ import globals from 'globals';
3
+ import { javascriptFiles, typescriptFiles } from '@perfective/eslint-config';
4
+ import { reactJsxRules } from "./jsx.js";
5
+ export function reactConfig() {
6
+ return {
7
+ files: [...javascriptFiles, ...typescriptFiles],
8
+ plugins: {
9
+ react: react
10
+ },
11
+ languageOptions: {
12
+ parserOptions: {
13
+ ecmaFeatures: {
14
+ jsx: true
15
+ }
16
+ },
17
+ globals: Object.assign({}, globals.browser)
18
+ },
19
+ rules: Object.assign(Object.assign({}, reactJsxRules), {
20
+ 'react/boolean-prop-naming': ['error', {
21
+ propTypeNames: ['bool'],
22
+ rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+',
23
+ validateNested: true
24
+ }],
25
+ 'react/button-has-type': ['error', {
26
+ button: true,
27
+ submit: true,
28
+ reset: true
29
+ }],
30
+ 'react/checked-requires-onchange-or-readonly': 'error',
31
+ 'react/default-props-match-prop-types': 'error',
32
+ 'react/destructuring-assignment': ['error', 'never'],
33
+ 'react/display-name': ['error', {
34
+ checkContextObjects: true,
35
+ ignoreTranspilerName: false
36
+ }],
37
+ 'react/forbid-component-props': 'error',
38
+ 'react/forbid-dom-props': ['error', {
39
+ forbid: []
40
+ }],
41
+ 'react/forbid-elements': ['error', {
42
+ forbid: []
43
+ }],
44
+ 'react/forbid-foreign-prop-types': 'error',
45
+ 'react/forbid-prop-types': ['error', {
46
+ forbid: ['any', 'array', 'object'],
47
+ checkContextTypes: true,
48
+ checkChildContextTypes: true
49
+ }],
50
+ 'react/forward-ref-uses-ref': 'error',
51
+ 'react/function-component-definition': ['warn', {
52
+ namedComponents: 'function-declaration',
53
+ unnamedComponents: 'function-expression'
54
+ }],
55
+ 'react/hook-use-state': ['error', {
56
+ allowDestructuredState: false
57
+ }],
58
+ 'react/iframe-missing-sandbox': 'error',
59
+ 'react/no-access-state-in-setstate': 'error',
60
+ 'react/no-adjacent-inline-elements': 'error',
61
+ 'react/no-array-index-key': 'error',
62
+ 'react/no-arrow-function-lifecycle': 'warn',
63
+ 'react/no-children-prop': ['error', {
64
+ allowFunctions: false
65
+ }],
66
+ 'react/no-danger': 'error',
67
+ 'react/no-danger-with-children': 'error',
68
+ 'react/no-deprecated': 'error',
69
+ 'react/no-did-mount-set-state': ['error', 'disallow-in-func'],
70
+ 'react/no-did-update-set-state': ['error', 'disallow-in-func'],
71
+ 'react/no-direct-mutation-state': 'error',
72
+ 'react/no-find-dom-node': 'error',
73
+ 'react/no-invalid-html-attribute': 'warn',
74
+ 'react/no-is-mounted': 'error',
75
+ 'react/no-multi-comp': ['error', {
76
+ ignoreStateless: false
77
+ }],
78
+ 'react/no-namespace': 'error',
79
+ 'react/no-object-type-as-default-prop': 'error',
80
+ 'react/no-redundant-should-component-update': 'error',
81
+ 'react/no-render-return-value': 'error',
82
+ 'react/no-set-state': 'off',
83
+ 'react/no-string-refs': ['error', {
84
+ noTemplateLiterals: true
85
+ }],
86
+ 'react/no-this-in-sfc': 'error',
87
+ 'react/no-typos': 'error',
88
+ 'react/no-unescaped-entities': ['error', {
89
+ forbid: ['>', '}']
90
+ }],
91
+ 'react/no-unknown-property': ['warn', {
92
+ ignore: [],
93
+ requireDataLowercase: true
94
+ }],
95
+ 'react/no-unsafe': 'error',
96
+ 'react/no-unstable-nested-components': ['error', {
97
+ allowAsProps: false
98
+ }],
99
+ 'react/no-unused-prop-types': 'error',
100
+ 'react/no-unused-state': 'error',
101
+ 'react/no-will-update-set-state': ['error', 'disallow-in-func'],
102
+ 'react/prefer-es6-class': ['error', 'always'],
103
+ 'react/prefer-exact-props': 'off',
104
+ 'react/prefer-read-only-props': 'warn',
105
+ 'react/prefer-stateless-function': 'off',
106
+ 'react/prop-types': 'error',
107
+ 'react/react-in-jsx-scope': 'error',
108
+ 'react/require-default-props': 'error',
109
+ 'react/require-optimization': ['error', {
110
+ allowDecorators: []
111
+ }],
112
+ 'react/require-render-return': 'error',
113
+ 'react/self-closing-comp': ['warn', {
114
+ component: true,
115
+ html: true
116
+ }],
117
+ 'react/sort-comp': ['error', {
118
+ order: ['static-methods', 'lifecycle', 'everything-else', 'render'],
119
+ groups: {
120
+ lifecycle: ['displayName', 'propTypes', 'contextTypes', 'childContextTypes', 'mixins', 'statics', 'defaultProps', 'constructor', 'getDefaultProps', 'state', 'getInitialState', 'getChildContext', 'getDerivedStateFromProps', 'componentWillMount', 'UNSAFE_componentWillMount', 'componentDidMount', 'componentWillReceiveProps', 'UNSAFE_componentWillReceiveProps', 'shouldComponentUpdate', 'componentWillUpdate', 'UNSAFE_componentWillUpdate', 'getSnapshotBeforeUpdate', 'componentDidUpdate', 'componentDidCatch', 'componentWillUnmount']
121
+ }
122
+ }],
123
+ 'react/sort-default-props': ['error', {
124
+ ignoreCase: false
125
+ }],
126
+ 'react/sort-prop-types': ['error', {
127
+ ignoreCase: false,
128
+ callbacksLast: true,
129
+ requiredFirst: true,
130
+ sortShapeProp: true,
131
+ noSortAlphabetically: false
132
+ }],
133
+ 'react/state-in-constructor': ['error', 'always'],
134
+ 'react/static-property-placement': ['error', 'static public field'],
135
+ 'react/style-prop-object': 'error',
136
+ 'react/void-dom-elements-no-children': 'error'
137
+ })
138
+ };
139
+ }
@@ -0,0 +1,2 @@
1
+ import { Linter } from 'eslint';
2
+ export declare function reactHooksConfig(): Linter.Config;
@@ -0,0 +1,14 @@
1
+ import { configs } from 'eslint-plugin-react-hooks';
2
+ import { javascriptFiles, typescriptFiles } from '@perfective/eslint-config';
3
+ export function reactHooksConfig() {
4
+ return {
5
+ files: [...javascriptFiles, ...typescriptFiles],
6
+ plugins: {
7
+ 'react-hooks': configs['recommended-latest'].plugins['react-hooks']
8
+ },
9
+ rules: {
10
+ 'react-hooks/rules-of-hooks': 'error',
11
+ 'react-hooks/exhaustive-deps': 'warn'
12
+ }
13
+ };
14
+ }
@@ -0,0 +1,2 @@
1
+ import { Linter } from 'eslint';
2
+ export declare function reactPerfConfig(): Linter.Config;
@@ -0,0 +1,14 @@
1
+ import reactPerfPlugin from 'eslint-plugin-react-perf';
2
+ export function reactPerfConfig() {
3
+ return {
4
+ plugins: {
5
+ 'react-perf': reactPerfPlugin
6
+ },
7
+ rules: {
8
+ 'react-perf/jsx-no-jsx-as-prop': 'error',
9
+ 'react-perf/jsx-no-new-array-as-prop': 'error',
10
+ 'react-perf/jsx-no-new-function-as-prop': 'error',
11
+ 'react-perf/jsx-no-new-object-as-prop': 'error'
12
+ }
13
+ };
14
+ }