Skip to content

Commit fe9ced2

Browse files
committed
Merge branch 'master' of https://github.com/y-hsgw/eslint-plugin-react into feature/add-jsdoc-annotations
2 parents 4d4cd3c + 983b88d commit fe9ced2

File tree

169 files changed

+1901
-725
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

169 files changed

+1901
-725
lines changed

.eslint-doc-generatorrc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const config = {
44
['jsx-runtime', '🏃'],
55
['recommended', '☑️'],
66
],
7-
ignoreConfig: ['all'],
7+
ignoreConfig: ['all', 'flat'],
88
urlConfigs: 'https://github.com/jsx-eslint/eslint-plugin-react/#shareable-configs',
99
};
1010

.eslintrc

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"ignorePatterns": [
1717
"coverage/",
1818
".nyc_output/",
19+
"tests/fixtures/flat-config/"
1920
],
2021
"rules": {
2122
"comma-dangle": [2, "always-multiline"],

.github/workflows/node-18+.yml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ jobs:
2626
matrix:
2727
node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
2828
eslint:
29+
- 9
2930
- 8
3031
- 7
3132
- 6

.github/workflows/node-pretest.yml

-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ jobs:
1212
name: 'nvm install lts/* && npm install'
1313
with:
1414
node-version: 'lts/*'
15-
env:
16-
NPM_CONFIG_LEGACY_PEER_DEPS: true
1715
- run: npm run pretest
1816

1917
posttest:

CHANGELOG.md

+41-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,48 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
55

66
## Unreleased
77

8+
## [7.35.0] - 2024.07.19
9+
10+
### Added
11+
* support eslint v9 ([#3759][] @mdjermanovic)
12+
* export flat configs from plugin root and fix flat config crash ([#3694][] @bradzacher @mdjermanovic)
13+
* add [`jsx-props-no-spread-multi`] ([#3724][] @SimonSchick)
14+
* [`forbid-component-props`]: add `propNamePattern` to allow / disallow prop name patterns ([#3774][] @akulsr0)
15+
* [`jsx-handler-names`]: support ignoring component names ([#3772][] @akulsr0)
16+
* version settings: Allow react defaultVersion to be configurable ([#3771][] @onlywei)
17+
* [`jsx-closing-tag-location`]: add `line-aligned` option ([#3777] @kimtaejin3)
18+
* [`no-danger`]: add `customComponentNames` option ([#3748][] @akulsr0)
19+
20+
### Fixed
21+
* [`no-invalid-html-attribute`]: substitute placeholders in suggestion messages ([#3759][] @mdjermanovic)
22+
* [`sort-prop-types`]: single line type ending without semicolon ([#3784][] @akulsr0)
23+
* [`require-default-props`]: report when required props have default value ([#3785][] @akulsr0)
24+
25+
### Changed
26+
* [Refactor] `variableUtil`: Avoid creating a single flat variable scope for each lookup ([#3782][] @DanielRosenwasser)
27+
28+
[7.35.0]: https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.34.4...v7.35.0
29+
[#3785]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3785
30+
[#3784]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3784
31+
[#3782]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3782
32+
[#3777]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3777
33+
[#3774]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3774
34+
[#3772]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3772
35+
[#3771]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3771
36+
[#3759]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3759
37+
[#3748]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3748
38+
[#3724]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3724
39+
[#3694]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3694
40+
41+
## [7.34.4] - 2024.07.13
42+
843
### Fixed
944

10-
* [`prop-types`]: fix `className` missing in prop validation false negative ([#3749] @akulsr0)
45+
* [`prop-types`]: fix `className` missing in prop validation false negative ([#3749][] @akulsr0)
46+
* [`sort-prop-types`]: Check for undefined before accessing `node.typeAnnotation.typeAnnotation` ([#3779][] @tylerlaprade)
1147

48+
[7.34.4]: https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.34.3...v7.34.4
49+
[#3779]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3779
1250
[#3749]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3749
1351

1452
## [7.34.3] - 2024.06.18
@@ -31,7 +69,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
3169

3270
### Fixed
3371
* [`boolean-prop-naming`]: avoid a crash with a non-TSTypeReference type ([#3718][] @developer-bandi)
34-
* [`jsx-no-leaked-render`]: invalid report if left side is boolean ([#3746][] @akulsr0)
72+
* [`jsx-no-leaked-render`]: invalid report if left eside is boolean ([#3746][] @akulsr0)
3573
* [`jsx-closing-bracket-location`]: message shows `{{details}}` when there are no details ([#3759][] @mdjermanovic)
3674
* [`no-invalid-html-attribute`]: ensure error messages are correct ([#3759][] @mdjermanovic, @ljharb)
3775

@@ -4257,6 +4295,7 @@ If you're still not using React 15 you can keep the old behavior by setting the
42574295
[`jsx-one-expression-per-line`]: docs/rules/jsx-one-expression-per-line.md
42584296
[`jsx-pascal-case`]: docs/rules/jsx-pascal-case.md
42594297
[`jsx-props-no-multi-spaces`]: docs/rules/jsx-props-no-multi-spaces.md
4298+
[`jsx-props-no-spread-multi`]: docs/rules/jsx-props-no-spread-multi.md
42604299
[`jsx-props-no-spreading`]: docs/rules/jsx-props-no-spreading.md
42614300
[`jsx-props-no-spreading`]: docs/rules/jsx-props-no-spreading.md
42624301
[`jsx-sort-default-props`]: docs/rules/jsx-sort-default-props.md

README.md

+17-19
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ You should also specify settings that will be shared across all the plugin rules
4242
"fragment": "Fragment", // Fragment to use (may be a property of <pragma>), default to "Fragment"
4343
"version": "detect", // React version. "detect" automatically picks the version you have installed.
4444
// You can also use `16.0`, `16.3`, etc, if you want to override the detected value.
45-
// It will default to "latest" and warn if missing, and to "detect" in the future
45+
// Defaults to the "defaultVersion" setting and warns if missing, and to "detect" in the future
46+
"defaultVersion": "", // Default React version to use when the version you have installed cannot be detected.
47+
// If not provided, defaults to the latest React version.
4648
"flowVersion": "0.53" // Flow version
4749
},
4850
"propWrapperFunctions": [
@@ -203,27 +205,22 @@ Refer to the [official docs](https://eslint.org/docs/latest/user-guide/configuri
203205
The schema of the `settings.react` object would be identical to that of what's already described above in the legacy config section.
204206

205207
<!-- markdownlint-disable-next-line no-duplicate-heading -->
206-
### Shareable configs
207-
208-
There're also 3 shareable configs.
209-
210-
- `eslint-plugin-react/configs/all`
211-
- `eslint-plugin-react/configs/recommended`
212-
- `eslint-plugin-react/configs/jsx-runtime`
208+
### Flat Configs
213209

214-
If your eslint.config.js is ESM, include the `.js` extension (e.g. `eslint-plugin-react/recommended.js`). Note that the next semver-major will require omitting the extension for these imports.
210+
This plugin exports 3 flat configs:
215211

216-
**Note**: These configurations will import `eslint-plugin-react` and enable JSX in [`languageOptions.parserOptions`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuration-objects).
212+
- `flat.all`
213+
- `flat.recommended`
214+
- `flat['jsx-runtime']`
217215

218-
In the new config system, `plugin:` protocol(e.g. `plugin:react/recommended`) is no longer valid.
219-
As eslint does not automatically import the preset config (shareable config), you explicitly do it by yourself.
216+
The flat configs are available via the root plugin import. They will configure the plugin under the `react/` namespace and enable JSX in [`languageOptions.parserOptions`](https://eslint.org/docs/latest/use/configure/language-options#specifying-parser-options).
220217

221218
```js
222-
const reactRecommended = require('eslint-plugin-react/configs/recommended');
219+
const reactPlugin = require('eslint-plugin-react');
223220

224221
module.exports = [
225222
226-
reactRecommended, // This is not a plugin object, but a shareable config object
223+
reactPlugin.configs.flat.recommended, // This is not a plugin object, but a shareable config object
227224
228225
];
229226
```
@@ -234,16 +231,16 @@ You can of course add/override some properties.
234231
For most of the cases, you probably want to configure some properties by yourself.
235232

236233
```js
237-
const reactRecommended = require('eslint-plugin-react/configs/recommended');
234+
const reactPlugin = require('eslint-plugin-react');
238235
const globals = require('globals');
239236

240237
module.exports = [
241238
242239
{
243240
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
244-
...reactRecommended,
241+
...reactPlugin.configs.flat.recommended,
245242
languageOptions: {
246-
...reactRecommended.languageOptions,
243+
...reactPlugin.configs.flat.recommended.languageOptions,
247244
globals: {
248245
...globals.serviceworker,
249246
...globals.browser,
@@ -257,14 +254,14 @@ module.exports = [
257254
The above example is same as the example below, as the new config system is based on chaining.
258255

259256
```js
260-
const reactRecommended = require('eslint-plugin-react/configs/recommended');
257+
const reactPlugin = require('eslint-plugin-react');
261258
const globals = require('globals');
262259

263260
module.exports = [
264261
265262
{
266263
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
267-
...reactRecommended,
264+
...reactPlugin.configs.flat.recommended,
268265
},
269266
{
270267
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
@@ -338,6 +335,7 @@ module.exports = [
338335
| [jsx-one-expression-per-line](docs/rules/jsx-one-expression-per-line.md) | Require one JSX element per line | | | 🔧 | | |
339336
| [jsx-pascal-case](docs/rules/jsx-pascal-case.md) | Enforce PascalCase for user-defined JSX components | | | | | |
340337
| [jsx-props-no-multi-spaces](docs/rules/jsx-props-no-multi-spaces.md) | Disallow multiple spaces between inline JSX props | | | 🔧 | | |
338+
| [jsx-props-no-spread-multi](docs/rules/jsx-props-no-spread-multi.md) | Disallow JSX prop spreading the same identifier multiple times | | | | | |
341339
| [jsx-props-no-spreading](docs/rules/jsx-props-no-spreading.md) | Disallow JSX prop spreading | | | | | |
342340
| [jsx-sort-default-props](docs/rules/jsx-sort-default-props.md) | Enforce defaultProps declarations alphabetical sorting | | | | ||
343341
| [jsx-sort-props](docs/rules/jsx-sort-props.md) | Enforce props alphabetical sorting | | | 🔧 | | |

configs/all.js

+5-41
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,13 @@
11
'use strict';
22

3-
const fromEntries = require('object.fromentries');
4-
const entries = require('object.entries');
3+
const plugin = require('..');
54

6-
const allRules = require('../lib/rules');
7-
8-
function filterRules(rules, predicate) {
9-
return fromEntries(entries(rules).filter((entry) => predicate(entry[1])));
10-
}
11-
12-
/**
13-
* @param {object} rules - rules object mapping rule name to rule module
14-
* @returns {Record<string, 2>}
15-
*/
16-
function configureAsError(rules) {
17-
return fromEntries(Object.keys(rules).map((key) => [`react/${key}`, 2]));
18-
}
19-
20-
const activeRules = filterRules(allRules, (rule) => !rule.meta.deprecated);
21-
const activeRulesConfig = configureAsError(activeRules);
22-
23-
const deprecatedRules = filterRules(allRules, (rule) => rule.meta.deprecated);
5+
const legacyConfig = plugin.configs.all;
246

257
module.exports = {
26-
plugins: {
27-
/**
28-
* @type {{
29-
* deprecatedRules: Record<string, import('eslint').Rule.RuleModule>,
30-
* rules: Record<string, import('eslint').Rule.RuleModule>,
31-
* }}
32-
*/
33-
react: {
34-
deprecatedRules,
35-
rules: allRules,
36-
},
37-
},
38-
rules: activeRulesConfig,
39-
languageOptions: {
40-
parserOptions: {
41-
ecmaFeatures: {
42-
jsx: true,
43-
},
44-
},
45-
},
8+
plugins: { react: plugin },
9+
rules: legacyConfig.rules,
10+
languageOptions: { parserOptions: legacyConfig.parserOptions },
4611
};
4712

48-
// this is so the `languageOptions` property won't be warned in the new config system
4913
Object.defineProperty(module.exports, 'languageOptions', { enumerable: false });

configs/jsx-runtime.js

+8-13
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
'use strict';
22

3-
const all = require('./all');
3+
const plugin = require('..');
44

5-
module.exports = Object.assign({}, all, {
6-
languageOptions: Object.assign({}, all.languageOptions, {
7-
parserOptions: Object.assign({}, all.languageOptions.parserOptions, {
8-
jsxPragma: null, // for @typescript/eslint-parser
9-
}),
10-
}),
11-
rules: {
12-
'react/react-in-jsx-scope': 0,
13-
'react/jsx-uses-react': 0,
14-
},
15-
});
5+
const legacyConfig = plugin.configs['jsx-runtime'];
6+
7+
module.exports = {
8+
plugins: { react: plugin },
9+
rules: legacyConfig.rules,
10+
languageOptions: { parserOptions: legacyConfig.parserOptions },
11+
};
1612

17-
// this is so the `languageOptions` property won't be warned in the new config system
1813
Object.defineProperty(module.exports, 'languageOptions', { enumerable: false });

configs/recommended.js

+8-29
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,13 @@
11
'use strict';
22

3-
const all = require('./all');
3+
const plugin = require('..');
44

5-
module.exports = Object.assign({}, all, {
6-
languageOptions: all.languageOptions,
7-
rules: {
8-
'react/display-name': 2,
9-
'react/jsx-key': 2,
10-
'react/jsx-no-comment-textnodes': 2,
11-
'react/jsx-no-duplicate-props': 2,
12-
'react/jsx-no-target-blank': 2,
13-
'react/jsx-no-undef': 2,
14-
'react/jsx-uses-react': 2,
15-
'react/jsx-uses-vars': 2,
16-
'react/no-children-prop': 2,
17-
'react/no-danger-with-children': 2,
18-
'react/no-deprecated': 2,
19-
'react/no-direct-mutation-state': 2,
20-
'react/no-find-dom-node': 2,
21-
'react/no-is-mounted': 2,
22-
'react/no-render-return-value': 2,
23-
'react/no-string-refs': 2,
24-
'react/no-unescaped-entities': 2,
25-
'react/no-unknown-property': 2,
26-
'react/no-unsafe': 0,
27-
'react/prop-types': 2,
28-
'react/react-in-jsx-scope': 2,
29-
'react/require-render-return': 2,
30-
},
31-
});
5+
const legacyConfig = plugin.configs.recommended;
6+
7+
module.exports = {
8+
plugins: { react: plugin },
9+
rules: legacyConfig.rules,
10+
languageOptions: { parserOptions: legacyConfig.parserOptions },
11+
};
3212

33-
// this is so the `languageOptions` property won't be warned in the new config system
3413
Object.defineProperty(module.exports, 'languageOptions', { enumerable: false });

docs/rules/forbid-component-props.md

+21-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Examples of **correct** code for this rule:
4444
### `forbid`
4545

4646
An array specifying the names of props that are forbidden. The default value of this option is `['className', 'style']`.
47-
Each array element can either be a string with the property name or object specifying the property name, an optional
47+
Each array element can either be a string with the property name or object specifying the property name or glob string, an optional
4848
custom message, and a component allowlist:
4949

5050
```js
@@ -55,6 +55,16 @@ custom message, and a component allowlist:
5555
}
5656
```
5757

58+
For glob string patterns:
59+
60+
```js
61+
{
62+
"propNamePattern": '**-**',
63+
"allowedFor": ['div'],
64+
"message": "Avoid using kebab-case except div"
65+
}
66+
```
67+
5868
Use `disallowedFor` as an exclusion list to warn on props for specific components. `disallowedFor` must have at least one item.
5969

6070
```js
@@ -65,6 +75,16 @@ Use `disallowedFor` as an exclusion list to warn on props for specific component
6575
}
6676
```
6777

78+
For glob string patterns:
79+
80+
```js
81+
{
82+
"propNamePattern": "**-**",
83+
"disallowedFor": ["MyComponent"],
84+
"message": "Avoid using kebab-case for MyComponent"
85+
}
86+
```
87+
6888
### Related rules
6989

7090
- [forbid-dom-props](./forbid-dom-props.md)

0 commit comments

Comments
 (0)