Skip to content

Commit d6cdc8a

Browse files
jjangga0214ljharb
authored andcommitted
[New] support new config system
- add configs/ entry points for recommended configs - add documentation to readme
1 parent 8c9ec8a commit d6cdc8a

File tree

6 files changed

+362
-196
lines changed

6 files changed

+362
-196
lines changed

CHANGELOG.md

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

66
## Unreleased
77

8+
### Added
9+
* [New] support new config system ([#3429][] @jjangga0214)
10+
11+
[#3424]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3429
12+
813
## [7.31.8] - 2022.09.08
914

1015
### Fixed

README.md

+171-35
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ React specific linting rules for `eslint`
1515
npm install eslint eslint-plugin-react --save-dev
1616
```
1717

18-
It is also possible to install ESLint globally rather than locally (using npm install eslint --global). However, this is not recommended, and any plugins or shareable configs that you use must be installed locally in either case.
18+
It is also possible to install ESLint globally rather than locally (using `npm install -g eslint`). However, this is not recommended, and any plugins or shareable configs that you use must be installed locally in either case.
1919

20-
## Configuration
20+
## Configuration (legacy: `.eslintrc*`)
2121

2222
Use [our preset](#recommended) to get reasonable defaults:
2323

@@ -109,6 +109,174 @@ Enable the rules that you would like to use.
109109
}
110110
```
111111

112+
### Shareable configs
113+
114+
#### Recommended
115+
116+
This plugin exports a `recommended` configuration that enforces React good practices.
117+
118+
To enable this configuration use the `extends` property in your `.eslintrc` config file:
119+
120+
```json
121+
{
122+
"extends": ["eslint:recommended", "plugin:react/recommended"]
123+
}
124+
```
125+
126+
See [`eslint` documentation](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending configuration files.
127+
128+
#### All
129+
130+
This plugin also exports an `all` configuration that includes every available rule.
131+
This pairs well with the `eslint:all` rule.
132+
133+
```json
134+
{
135+
"plugins": [
136+
"react"
137+
],
138+
"extends": ["eslint:all", "plugin:react/all"]
139+
}
140+
```
141+
142+
**Note**: These configurations will import `eslint-plugin-react` and enable JSX in [parser options](https://eslint.org/docs/user-guide/configuring/language-options#specifying-parser-options).
143+
144+
## Configuration (new: `eslint.config.js`)
145+
146+
From [`v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), eslint announced a new config system.
147+
In the new system, `.eslintrc*` is no longer used. `eslint.config.js` would be the default config file name.
148+
In eslint `v8`, the legacy system (`.eslintrc*`) would still be supported, while in eslint `v9`, only the new system would be supported.
149+
150+
And from [`v8.23.0`](https://github.com/eslint/eslint/releases/tag/v8.23.0), eslint CLI starts to look up `eslint.config.js`.
151+
**So, if your eslint is `>=8.23.0`, you're 100% ready to use the new config system.**
152+
153+
You might want to check out the official blog posts,
154+
155+
- <https://eslint.org/blog/2022/08/new-config-system-part-1/>
156+
- <https://eslint.org/blog/2022/08/new-config-system-part-2/>
157+
- <https://eslint.org/blog/2022/08/new-config-system-part-3/>
158+
159+
and the [official docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new).
160+
161+
### Plugin
162+
163+
The default export of `eslint-plugin-react` is a plugin object.
164+
165+
```js
166+
const react = require('eslint-plugin-react');
167+
const globals = require('globals');
168+
169+
module.exports = [
170+
171+
{
172+
files: ['**/*.{js,jsx,mjs,cjs,ts,tsx}'],
173+
plugins: {
174+
react,
175+
},
176+
languageOptions: {
177+
parserOptions: {
178+
ecmaFeatures: {
179+
jsx: true,
180+
},
181+
},
182+
globals: {
183+
...globals.browser,
184+
},
185+
},
186+
rules: {
187+
// ... any rules you want
188+
'react/jsx-uses-react': 'error',
189+
'react/jsx-uses-vars': 'error',
190+
},
191+
// ... others are omitted for brevity
192+
},
193+
194+
];
195+
```
196+
197+
### Configuring shared settings
198+
199+
Refer to the [official docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuring-shared-settings).
200+
201+
The schema of the `settings.react` object would be identical to that of what's already described above in the legacy config section.
202+
203+
<!-- markdownlint-disable-next-line no-duplicate-heading -->
204+
### Shareable configs
205+
206+
There're also 3 shareable configs.
207+
208+
- `eslint-plugin-react/configs/all`
209+
- `eslint-plugin-react/configs/recommended`
210+
- `eslint-plugin-react/configs/jsx-runtime`
211+
212+
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.
213+
214+
**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).
215+
216+
In the new config system, `plugin:` protocol(e.g. `plugin:react/recommended`) is no longer valid.
217+
As eslint does not automatically import the preset config (shareable config), you explicitly do it by yourself.
218+
219+
```js
220+
const reactRecommended = require('eslint-plugin-react/configs/recommended');
221+
222+
module.exports = [
223+
224+
reactRecommended, // This is not a plugin object, but a shareable config object
225+
226+
];
227+
```
228+
229+
You can of course add/override some properties.
230+
231+
**Note**: Our shareable configs does not preconfigure `files` or [`languageOptions.globals`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuration-objects).
232+
For most of the cases, you probably want to configure some properties by yourself.
233+
234+
```js
235+
const reactRecommended = require('eslint-plugin-react/configs/recommended');
236+
const globals = require('globals');
237+
238+
module.exports = [
239+
240+
{
241+
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
242+
...reactRecommended,
243+
languageOptions: {
244+
...reactRecommended.languageOptions,
245+
globals: {
246+
...globals.serviceworker,
247+
...globals.browser;
248+
},
249+
},
250+
},
251+
252+
];
253+
```
254+
255+
The above example is same as the example below, as the new config system is based on chaining.
256+
257+
```js
258+
const reactRecommended = require('eslint-plugin-react/configs/recommended');
259+
const globals = require('globals');
260+
261+
module.exports = [
262+
263+
{
264+
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
265+
...reactRecommended,
266+
},
267+
{
268+
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
269+
languageOptions: {
270+
globals: {
271+
...globals.serviceworker,
272+
...globals.browser,
273+
},
274+
},
275+
},
276+
277+
];
278+
```
279+
112280
## List of supported rules
113281

114282
✔: Enabled in the [`recommended`](#recommended) configuration.\
@@ -225,44 +393,12 @@ Enable the rules that you would like to use.
225393
| | 🔧 | | [react/jsx-wrap-multilines](docs/rules/jsx-wrap-multilines.md) | Disallow missing parentheses around multiline JSX |
226394
<!-- AUTO-GENERATED-CONTENT:END -->
227395

228-
### Other useful plugins
396+
## Other useful plugins
229397

230398
- Rules of Hooks: [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/master/packages/eslint-plugin-react-hooks)
231399
- JSX accessibility: [eslint-plugin-jsx-a11y](https://github.com/evcohen/eslint-plugin-jsx-a11y)
232400
- React Native: [eslint-plugin-react-native](https://github.com/Intellicode/eslint-plugin-react-native)
233401

234-
## Shareable configurations
235-
236-
### Recommended
237-
238-
This plugin exports a `recommended` configuration that enforces React good practices.
239-
240-
To enable this configuration use the `extends` property in your `.eslintrc` config file:
241-
242-
```json
243-
{
244-
"extends": ["eslint:recommended", "plugin:react/recommended"]
245-
}
246-
```
247-
248-
See [`eslint` documentation](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending configuration files.
249-
250-
### All
251-
252-
This plugin also exports an `all` configuration that includes every available rule.
253-
This pairs well with the `eslint:all` rule.
254-
255-
```json
256-
{
257-
"plugins": [
258-
"react"
259-
],
260-
"extends": ["eslint:all", "plugin:react/all"]
261-
}
262-
```
263-
264-
**Note**: These configurations will import `eslint-plugin-react` and enable JSX in [parser options](https://eslint.org/docs/user-guide/configuring/language-options#specifying-parser-options).
265-
266402
## License
267403

268404
`eslint-plugin-react` is licensed under the [MIT License](https://opensource.org/licenses/mit-license.php).

configs/all.js

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
'use strict';
2+
3+
const react = require('../index');
4+
5+
const plugin = Object.assign({}, react);
6+
delete plugin.configs;
7+
8+
/* eslint-disable global-require */
9+
const allRules = {
10+
'boolean-prop-naming': require('../lib/rules/boolean-prop-naming'),
11+
'button-has-type': require('../lib/rules/button-has-type'),
12+
'default-props-match-prop-types': require('../lib/rules/default-props-match-prop-types'),
13+
'destructuring-assignment': require('../lib/rules/destructuring-assignment'),
14+
'display-name': require('../lib/rules/display-name'),
15+
'forbid-component-props': require('../lib/rules/forbid-component-props'),
16+
'forbid-dom-props': require('../lib/rules/forbid-dom-props'),
17+
'forbid-elements': require('../lib/rules/forbid-elements'),
18+
'forbid-foreign-prop-types': require('../lib/rules/forbid-foreign-prop-types'),
19+
'forbid-prop-types': require('../lib/rules/forbid-prop-types'),
20+
'function-component-definition': require('../lib/rules/function-component-definition'),
21+
'hook-use-state': require('../lib/rules/hook-use-state'),
22+
'iframe-missing-sandbox': require('../lib/rules/iframe-missing-sandbox'),
23+
'jsx-boolean-value': require('../lib/rules/jsx-boolean-value'),
24+
'jsx-child-element-spacing': require('../lib/rules/jsx-child-element-spacing'),
25+
'jsx-closing-bracket-location': require('../lib/rules/jsx-closing-bracket-location'),
26+
'jsx-closing-tag-location': require('../lib/rules/jsx-closing-tag-location'),
27+
'jsx-curly-spacing': require('../lib/rules/jsx-curly-spacing'),
28+
'jsx-curly-newline': require('../lib/rules/jsx-curly-newline'),
29+
'jsx-equals-spacing': require('../lib/rules/jsx-equals-spacing'),
30+
'jsx-filename-extension': require('../lib/rules/jsx-filename-extension'),
31+
'jsx-first-prop-new-line': require('../lib/rules/jsx-first-prop-new-line'),
32+
'jsx-handler-names': require('../lib/rules/jsx-handler-names'),
33+
'jsx-indent': require('../lib/rules/jsx-indent'),
34+
'jsx-indent-props': require('../lib/rules/jsx-indent-props'),
35+
'jsx-key': require('../lib/rules/jsx-key'),
36+
'jsx-max-depth': require('../lib/rules/jsx-max-depth'),
37+
'jsx-max-props-per-line': require('../lib/rules/jsx-max-props-per-line'),
38+
'jsx-newline': require('../lib/rules/jsx-newline'),
39+
'jsx-no-bind': require('../lib/rules/jsx-no-bind'),
40+
'jsx-no-comment-textnodes': require('../lib/rules/jsx-no-comment-textnodes'),
41+
'jsx-no-constructed-context-values': require('../lib/rules/jsx-no-constructed-context-values'),
42+
'jsx-no-duplicate-props': require('../lib/rules/jsx-no-duplicate-props'),
43+
'jsx-no-leaked-render': require('../lib/rules/jsx-no-leaked-render'),
44+
'jsx-no-literals': require('../lib/rules/jsx-no-literals'),
45+
'jsx-no-script-url': require('../lib/rules/jsx-no-script-url'),
46+
'jsx-no-target-blank': require('../lib/rules/jsx-no-target-blank'),
47+
'jsx-no-useless-fragment': require('../lib/rules/jsx-no-useless-fragment'),
48+
'jsx-one-expression-per-line': require('../lib/rules/jsx-one-expression-per-line'),
49+
'jsx-no-undef': require('../lib/rules/jsx-no-undef'),
50+
'jsx-curly-brace-presence': require('../lib/rules/jsx-curly-brace-presence'),
51+
'jsx-pascal-case': require('../lib/rules/jsx-pascal-case'),
52+
'jsx-fragments': require('../lib/rules/jsx-fragments'),
53+
'jsx-props-no-multi-spaces': require('../lib/rules/jsx-props-no-multi-spaces'),
54+
'jsx-props-no-spreading': require('../lib/rules/jsx-props-no-spreading'),
55+
'jsx-sort-default-props': require('../lib/rules/jsx-sort-default-props'),
56+
'jsx-sort-props': require('../lib/rules/jsx-sort-props'),
57+
'jsx-space-before-closing': require('../lib/rules/jsx-space-before-closing'),
58+
'jsx-tag-spacing': require('../lib/rules/jsx-tag-spacing'),
59+
'jsx-uses-react': require('../lib/rules/jsx-uses-react'),
60+
'jsx-uses-vars': require('../lib/rules/jsx-uses-vars'),
61+
'jsx-wrap-multilines': require('../lib/rules/jsx-wrap-multilines'),
62+
'no-invalid-html-attribute': require('../lib/rules/no-invalid-html-attribute'),
63+
'no-access-state-in-setstate': require('../lib/rules/no-access-state-in-setstate'),
64+
'no-adjacent-inline-elements': require('../lib/rules/no-adjacent-inline-elements'),
65+
'no-array-index-key': require('../lib/rules/no-array-index-key'),
66+
'no-arrow-function-lifecycle': require('../lib/rules/no-arrow-function-lifecycle'),
67+
'no-children-prop': require('../lib/rules/no-children-prop'),
68+
'no-danger': require('../lib/rules/no-danger'),
69+
'no-danger-with-children': require('../lib/rules/no-danger-with-children'),
70+
'no-deprecated': require('../lib/rules/no-deprecated'),
71+
'no-did-mount-set-state': require('../lib/rules/no-did-mount-set-state'),
72+
'no-did-update-set-state': require('../lib/rules/no-did-update-set-state'),
73+
'no-direct-mutation-state': require('../lib/rules/no-direct-mutation-state'),
74+
'no-find-dom-node': require('../lib/rules/no-find-dom-node'),
75+
'no-is-mounted': require('../lib/rules/no-is-mounted'),
76+
'no-multi-comp': require('../lib/rules/no-multi-comp'),
77+
'no-namespace': require('../lib/rules/no-namespace'),
78+
'no-set-state': require('../lib/rules/no-set-state'),
79+
'no-string-refs': require('../lib/rules/no-string-refs'),
80+
'no-redundant-should-component-update': require('../lib/rules/no-redundant-should-component-update'),
81+
'no-render-return-value': require('../lib/rules/no-render-return-value'),
82+
'no-this-in-sfc': require('../lib/rules/no-this-in-sfc'),
83+
'no-typos': require('../lib/rules/no-typos'),
84+
'no-unescaped-entities': require('../lib/rules/no-unescaped-entities'),
85+
'no-unknown-property': require('../lib/rules/no-unknown-property'),
86+
'no-unsafe': require('../lib/rules/no-unsafe'),
87+
'no-unstable-nested-components': require('../lib/rules/no-unstable-nested-components'),
88+
'no-unused-class-component-methods': require('../lib/rules/no-unused-class-component-methods'),
89+
'no-unused-prop-types': require('../lib/rules/no-unused-prop-types'),
90+
'no-unused-state': require('../lib/rules/no-unused-state'),
91+
'no-will-update-set-state': require('../lib/rules/no-will-update-set-state'),
92+
'prefer-es6-class': require('../lib/rules/prefer-es6-class'),
93+
'prefer-exact-props': require('../lib/rules/prefer-exact-props'),
94+
'prefer-read-only-props': require('../lib/rules/prefer-read-only-props'),
95+
'prefer-stateless-function': require('../lib/rules/prefer-stateless-function'),
96+
'prop-types': require('../lib/rules/prop-types'),
97+
'react-in-jsx-scope': require('../lib/rules/react-in-jsx-scope'),
98+
'require-default-props': require('../lib/rules/require-default-props'),
99+
'require-optimization': require('../lib/rules/require-optimization'),
100+
'require-render-return': require('../lib/rules/require-render-return'),
101+
'self-closing-comp': require('../lib/rules/self-closing-comp'),
102+
'sort-comp': require('../lib/rules/sort-comp'),
103+
'sort-prop-types': require('../lib/rules/sort-prop-types'),
104+
'state-in-constructor': require('../lib/rules/state-in-constructor'),
105+
'static-property-placement': require('../lib/rules/static-property-placement'),
106+
'style-prop-object': require('../lib/rules/style-prop-object'),
107+
'void-dom-elements-no-children': require('../lib/rules/void-dom-elements-no-children'),
108+
};
109+
/* eslint-enable global-require */
110+
111+
module.exports = {
112+
plugins: {
113+
react: plugin,
114+
},
115+
languageOptions: {
116+
parserOptions: {
117+
ecmaFeatures: {
118+
jsx: true,
119+
},
120+
},
121+
},
122+
rules: allRules,
123+
};

configs/jsx-runtime.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
3+
const all = require('./all');
4+
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+
});

0 commit comments

Comments
 (0)