Skip to content

Commit 93b535f

Browse files
authored
Merge branch 'master' into akul/issue-3783
2 parents fec5d6a + 4b3209b commit 93b535f

File tree

171 files changed

+1818
-724
lines changed

Some content is hidden

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

171 files changed

+1818
-724
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

+57-56
Original file line numberDiff line numberDiff line change
@@ -16,67 +16,68 @@
1616
"ignorePatterns": [
1717
"coverage/",
1818
".nyc_output/",
19+
"tests/fixtures/flat-config/"
1920
],
2021
"rules": {
2122
"comma-dangle": [2, "always-multiline"],
2223
"object-shorthand": [2, "always", {
2324
"ignoreConstructors": false,
2425
"avoidQuotes": false, // this is the override vs airbnb
25-
}],
26-
"max-len": [2, 120, {
27-
"ignoreStrings": true,
28-
"ignoreTemplateLiterals": true,
29-
"ignoreComments": true,
30-
}],
31-
"consistent-return": 0,
26+
}],
27+
"max-len": [2, 140, {
28+
"ignoreStrings": true,
29+
"ignoreTemplateLiterals": true,
30+
"ignoreComments": true,
31+
}],
32+
"consistent-return": 0,
3233

33-
"prefer-destructuring": [2, { "array": false, "object": false }, { "enforceForRenamedProperties": false }],
34-
"prefer-object-spread": 0, // until node 8 is required
35-
"prefer-rest-params": 0, // until node 6 is required
36-
"prefer-spread": 0, // until node 6 is required
37-
"function-call-argument-newline": 1, // TODO: enable
38-
"function-paren-newline": 0,
39-
"no-plusplus": [2, {"allowForLoopAfterthoughts": true}],
40-
"no-param-reassign": 1,
41-
"no-restricted-syntax": [2, {
42-
"selector": "ObjectPattern",
43-
"message": "Object destructuring is not compatible with Node v4"
44-
}],
45-
"strict": [2, "safe"],
46-
"valid-jsdoc": [2, {
47-
"requireReturn": false,
48-
"requireParamDescription": false,
49-
"requireReturnDescription": false,
50-
}],
34+
"prefer-destructuring": [2, { "array": false, "object": false }, { "enforceForRenamedProperties": false }],
35+
"prefer-object-spread": 0, // until node 8 is required
36+
"prefer-rest-params": 0, // until node 6 is required
37+
"prefer-spread": 0, // until node 6 is required
38+
"function-call-argument-newline": 1, // TODO: enable
39+
"function-paren-newline": 0,
40+
"no-plusplus": [2, {"allowForLoopAfterthoughts": true}],
41+
"no-param-reassign": 1,
42+
"no-restricted-syntax": [2, {
43+
"selector": "ObjectPattern",
44+
"message": "Object destructuring is not compatible with Node v4"
45+
}],
46+
"strict": [2, "safe"],
47+
"valid-jsdoc": [2, {
48+
"requireReturn": false,
49+
"requireParamDescription": false,
50+
"requireReturnDescription": false,
51+
}],
5152

52-
"eslint-plugin/consistent-output": 0,
53-
"eslint-plugin/require-meta-docs-description": [2, { "pattern": "^(Enforce|Require|Disallow)" }],
54-
"eslint-plugin/require-meta-schema": 0,
55-
"eslint-plugin/require-meta-type": 0
56-
},
57-
"overrides": [
58-
{
59-
"files": "tests/**",
60-
"rules": {
61-
"no-template-curly-in-string": 1,
62-
},
63-
},
64-
{
65-
"files": "markdown.config.js",
66-
"rules": {
67-
"no-console": 0,
68-
},
69-
},
70-
{
71-
"files": ".github/workflows/*.js",
72-
"parserOptions": {
73-
"ecmaVersion": 2019,
74-
},
75-
"rules": {
76-
"camelcase": 0,
77-
"no-console": 0,
78-
"no-restricted-syntax": 0,
79-
},
80-
},
81-
],
82-
}
53+
"eslint-plugin/consistent-output": 0,
54+
"eslint-plugin/require-meta-docs-description": [2, { "pattern": "^(Enforce|Require|Disallow)" }],
55+
"eslint-plugin/require-meta-schema": 0,
56+
"eslint-plugin/require-meta-type": 0
57+
},
58+
"overrides": [
59+
{
60+
"files": "tests/**",
61+
"rules": {
62+
"no-template-curly-in-string": 1,
63+
},
64+
},
65+
{
66+
"files": "markdown.config.js",
67+
"rules": {
68+
"no-console": 0,
69+
},
70+
},
71+
{
72+
"files": ".github/workflows/*.js",
73+
"parserOptions": {
74+
"ecmaVersion": 2019,
75+
},
76+
"rules": {
77+
"camelcase": 0,
78+
"no-console": 0,
79+
"no-restricted-syntax": 0,
80+
},
81+
},
82+
],
83+
}

.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

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

66
## Unreleased
77

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

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

41+
[7.34.4]: https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.34.3...v7.34.4
42+
[#3779]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3779
1243
[#3749]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3749
1344

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

3263
### Fixed
3364
* [`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)
65+
* [`jsx-no-leaked-render`]: invalid report if left eside is boolean ([#3746][] @akulsr0)
3566
* [`jsx-closing-bracket-location`]: message shows `{{details}}` when there are no details ([#3759][] @mdjermanovic)
3667
* [`no-invalid-html-attribute`]: ensure error messages are correct ([#3759][] @mdjermanovic, @ljharb)
3768

@@ -4257,6 +4288,7 @@ If you're still not using React 15 you can keep the old behavior by setting the
42574288
[`jsx-one-expression-per-line`]: docs/rules/jsx-one-expression-per-line.md
42584289
[`jsx-pascal-case`]: docs/rules/jsx-pascal-case.md
42594290
[`jsx-props-no-multi-spaces`]: docs/rules/jsx-props-no-multi-spaces.md
4291+
[`jsx-props-no-spread-multi`]: docs/rules/jsx-props-no-spread-multi.md
42604292
[`jsx-props-no-spreading`]: docs/rules/jsx-props-no-spreading.md
42614293
[`jsx-props-no-spreading`]: docs/rules/jsx-props-no-spreading.md
42624294
[`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 });

0 commit comments

Comments
 (0)