Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…into feature/add-jsdoc-annotations
  • Loading branch information
y-hsgw committed Jul 30, 2024
2 parents 4d4cd3c + 983b88d commit fe9ced2
Show file tree
Hide file tree
Showing 169 changed files with 1,901 additions and 725 deletions.
2 changes: 1 addition & 1 deletion .eslint-doc-generatorrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const config = {
['jsx-runtime', '🏃'],
['recommended', '☑️'],
],
ignoreConfig: ['all'],
ignoreConfig: ['all', 'flat'],
urlConfigs: 'https://github.com/jsx-eslint/eslint-plugin-react/#shareable-configs',
};

Expand Down
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"ignorePatterns": [
"coverage/",
".nyc_output/",
"tests/fixtures/flat-config/"
],
"rules": {
"comma-dangle": [2, "always-multiline"],
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/node-18+.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
matrix:
node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
eslint:
- 9
- 8
- 7
- 6
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/node-pretest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ jobs:
name: 'nvm install lts/* && npm install'
with:
node-version: 'lts/*'
env:
NPM_CONFIG_LEGACY_PEER_DEPS: true
- run: npm run pretest

posttest:
Expand Down
43 changes: 41 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,48 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange

## Unreleased

## [7.35.0] - 2024.07.19

### Added
* support eslint v9 ([#3759][] @mdjermanovic)
* export flat configs from plugin root and fix flat config crash ([#3694][] @bradzacher @mdjermanovic)
* add [`jsx-props-no-spread-multi`] ([#3724][] @SimonSchick)
* [`forbid-component-props`]: add `propNamePattern` to allow / disallow prop name patterns ([#3774][] @akulsr0)
* [`jsx-handler-names`]: support ignoring component names ([#3772][] @akulsr0)
* version settings: Allow react defaultVersion to be configurable ([#3771][] @onlywei)
* [`jsx-closing-tag-location`]: add `line-aligned` option ([#3777] @kimtaejin3)
* [`no-danger`]: add `customComponentNames` option ([#3748][] @akulsr0)

### Fixed
* [`no-invalid-html-attribute`]: substitute placeholders in suggestion messages ([#3759][] @mdjermanovic)
* [`sort-prop-types`]: single line type ending without semicolon ([#3784][] @akulsr0)
* [`require-default-props`]: report when required props have default value ([#3785][] @akulsr0)

### Changed
* [Refactor] `variableUtil`: Avoid creating a single flat variable scope for each lookup ([#3782][] @DanielRosenwasser)

[7.35.0]: https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.34.4...v7.35.0
[#3785]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3785
[#3784]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3784
[#3782]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3782
[#3777]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3777
[#3774]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3774
[#3772]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3772
[#3771]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3771
[#3759]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3759
[#3748]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3748
[#3724]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3724
[#3694]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3694

## [7.34.4] - 2024.07.13

### Fixed

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

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

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

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

Expand Down Expand Up @@ -4257,6 +4295,7 @@ If you're still not using React 15 you can keep the old behavior by setting the
[`jsx-one-expression-per-line`]: docs/rules/jsx-one-expression-per-line.md
[`jsx-pascal-case`]: docs/rules/jsx-pascal-case.md
[`jsx-props-no-multi-spaces`]: docs/rules/jsx-props-no-multi-spaces.md
[`jsx-props-no-spread-multi`]: docs/rules/jsx-props-no-spread-multi.md
[`jsx-props-no-spreading`]: docs/rules/jsx-props-no-spreading.md
[`jsx-props-no-spreading`]: docs/rules/jsx-props-no-spreading.md
[`jsx-sort-default-props`]: docs/rules/jsx-sort-default-props.md
Expand Down
36 changes: 17 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ You should also specify settings that will be shared across all the plugin rules
"fragment": "Fragment", // Fragment to use (may be a property of <pragma>), default to "Fragment"
"version": "detect", // React version. "detect" automatically picks the version you have installed.
// You can also use `16.0`, `16.3`, etc, if you want to override the detected value.
// It will default to "latest" and warn if missing, and to "detect" in the future
// Defaults to the "defaultVersion" setting and warns if missing, and to "detect" in the future
"defaultVersion": "", // Default React version to use when the version you have installed cannot be detected.
// If not provided, defaults to the latest React version.
"flowVersion": "0.53" // Flow version
},
"propWrapperFunctions": [
Expand Down Expand Up @@ -203,27 +205,22 @@ Refer to the [official docs](https://eslint.org/docs/latest/user-guide/configuri
The schema of the `settings.react` object would be identical to that of what's already described above in the legacy config section.

<!-- markdownlint-disable-next-line no-duplicate-heading -->
### Shareable configs

There're also 3 shareable configs.

- `eslint-plugin-react/configs/all`
- `eslint-plugin-react/configs/recommended`
- `eslint-plugin-react/configs/jsx-runtime`
### Flat Configs

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.
This plugin exports 3 flat configs:

**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).
- `flat.all`
- `flat.recommended`
- `flat['jsx-runtime']`

In the new config system, `plugin:` protocol(e.g. `plugin:react/recommended`) is no longer valid.
As eslint does not automatically import the preset config (shareable config), you explicitly do it by yourself.
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).

```js
const reactRecommended = require('eslint-plugin-react/configs/recommended');
const reactPlugin = require('eslint-plugin-react');

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

```js
const reactRecommended = require('eslint-plugin-react/configs/recommended');
const reactPlugin = require('eslint-plugin-react');
const globals = require('globals');

module.exports = [
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
...reactRecommended,
...reactPlugin.configs.flat.recommended,
languageOptions: {
...reactRecommended.languageOptions,
...reactPlugin.configs.flat.recommended.languageOptions,
globals: {
...globals.serviceworker,
...globals.browser,
Expand All @@ -257,14 +254,14 @@ module.exports = [
The above example is same as the example below, as the new config system is based on chaining.

```js
const reactRecommended = require('eslint-plugin-react/configs/recommended');
const reactPlugin = require('eslint-plugin-react');
const globals = require('globals');

module.exports = [
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
...reactRecommended,
...reactPlugin.configs.flat.recommended,
},
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
Expand Down Expand Up @@ -338,6 +335,7 @@ module.exports = [
| [jsx-one-expression-per-line](docs/rules/jsx-one-expression-per-line.md) | Require one JSX element per line | | | 🔧 | | |
| [jsx-pascal-case](docs/rules/jsx-pascal-case.md) | Enforce PascalCase for user-defined JSX components | | | | | |
| [jsx-props-no-multi-spaces](docs/rules/jsx-props-no-multi-spaces.md) | Disallow multiple spaces between inline JSX props | | | 🔧 | | |
| [jsx-props-no-spread-multi](docs/rules/jsx-props-no-spread-multi.md) | Disallow JSX prop spreading the same identifier multiple times | | | | | |
| [jsx-props-no-spreading](docs/rules/jsx-props-no-spreading.md) | Disallow JSX prop spreading | | | | | |
| [jsx-sort-default-props](docs/rules/jsx-sort-default-props.md) | Enforce defaultProps declarations alphabetical sorting | | | | ||
| [jsx-sort-props](docs/rules/jsx-sort-props.md) | Enforce props alphabetical sorting | | | 🔧 | | |
Expand Down
46 changes: 5 additions & 41 deletions configs/all.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,13 @@
'use strict';

const fromEntries = require('object.fromentries');
const entries = require('object.entries');
const plugin = require('..');

const allRules = require('../lib/rules');

function filterRules(rules, predicate) {
return fromEntries(entries(rules).filter((entry) => predicate(entry[1])));
}

/**
* @param {object} rules - rules object mapping rule name to rule module
* @returns {Record<string, 2>}
*/
function configureAsError(rules) {
return fromEntries(Object.keys(rules).map((key) => [`react/${key}`, 2]));
}

const activeRules = filterRules(allRules, (rule) => !rule.meta.deprecated);
const activeRulesConfig = configureAsError(activeRules);

const deprecatedRules = filterRules(allRules, (rule) => rule.meta.deprecated);
const legacyConfig = plugin.configs.all;

module.exports = {
plugins: {
/**
* @type {{
* deprecatedRules: Record<string, import('eslint').Rule.RuleModule>,
* rules: Record<string, import('eslint').Rule.RuleModule>,
* }}
*/
react: {
deprecatedRules,
rules: allRules,
},
},
rules: activeRulesConfig,
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
plugins: { react: plugin },
rules: legacyConfig.rules,
languageOptions: { parserOptions: legacyConfig.parserOptions },
};

// this is so the `languageOptions` property won't be warned in the new config system
Object.defineProperty(module.exports, 'languageOptions', { enumerable: false });
21 changes: 8 additions & 13 deletions configs/jsx-runtime.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
'use strict';

const all = require('./all');
const plugin = require('..');

module.exports = Object.assign({}, all, {
languageOptions: Object.assign({}, all.languageOptions, {
parserOptions: Object.assign({}, all.languageOptions.parserOptions, {
jsxPragma: null, // for @typescript/eslint-parser
}),
}),
rules: {
'react/react-in-jsx-scope': 0,
'react/jsx-uses-react': 0,
},
});
const legacyConfig = plugin.configs['jsx-runtime'];

module.exports = {
plugins: { react: plugin },
rules: legacyConfig.rules,
languageOptions: { parserOptions: legacyConfig.parserOptions },
};

// this is so the `languageOptions` property won't be warned in the new config system
Object.defineProperty(module.exports, 'languageOptions', { enumerable: false });
37 changes: 8 additions & 29 deletions configs/recommended.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,13 @@
'use strict';

const all = require('./all');
const plugin = require('..');

module.exports = Object.assign({}, all, {
languageOptions: all.languageOptions,
rules: {
'react/display-name': 2,
'react/jsx-key': 2,
'react/jsx-no-comment-textnodes': 2,
'react/jsx-no-duplicate-props': 2,
'react/jsx-no-target-blank': 2,
'react/jsx-no-undef': 2,
'react/jsx-uses-react': 2,
'react/jsx-uses-vars': 2,
'react/no-children-prop': 2,
'react/no-danger-with-children': 2,
'react/no-deprecated': 2,
'react/no-direct-mutation-state': 2,
'react/no-find-dom-node': 2,
'react/no-is-mounted': 2,
'react/no-render-return-value': 2,
'react/no-string-refs': 2,
'react/no-unescaped-entities': 2,
'react/no-unknown-property': 2,
'react/no-unsafe': 0,
'react/prop-types': 2,
'react/react-in-jsx-scope': 2,
'react/require-render-return': 2,
},
});
const legacyConfig = plugin.configs.recommended;

module.exports = {
plugins: { react: plugin },
rules: legacyConfig.rules,
languageOptions: { parserOptions: legacyConfig.parserOptions },
};

// this is so the `languageOptions` property won't be warned in the new config system
Object.defineProperty(module.exports, 'languageOptions', { enumerable: false });
22 changes: 21 additions & 1 deletion docs/rules/forbid-component-props.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Examples of **correct** code for this rule:
### `forbid`

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

```js
Expand All @@ -55,6 +55,16 @@ custom message, and a component allowlist:
}
```

For glob string patterns:

```js
{
"propNamePattern": '**-**',
"allowedFor": ['div'],
"message": "Avoid using kebab-case except div"
}
```

Use `disallowedFor` as an exclusion list to warn on props for specific components. `disallowedFor` must have at least one item.

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

For glob string patterns:

```js
{
"propNamePattern": "**-**",
"disallowedFor": ["MyComponent"],
"message": "Avoid using kebab-case for MyComponent"
}
```

### Related rules

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

0 comments on commit fe9ced2

Please sign in to comment.