Skip to content

Commit

Permalink
Merge branch 'master' into issue-3686
Browse files Browse the repository at this point in the history
  • Loading branch information
Efimenko authored Sep 19, 2024
2 parents 40beeb5 + 9668ee0 commit 01ac0a2
Show file tree
Hide file tree
Showing 63 changed files with 1,946 additions and 282 deletions.
62 changes: 60 additions & 2 deletions .github/workflows/node-18+.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,64 @@ jobs:
- 10
- 9
- 8
typescript-eslint:
- 5
- 6
- 7
- 8
exclude:
- eslint: 3
babel-eslint: 10
- eslint: 3
typescript-eslint: 5
- eslint: 4
typescript-eslint: 5
- eslint: 4.14
typescript-eslint: 5
- eslint: 5
typescript-eslint: 5
- eslint: 3
typescript-eslint: 6
- eslint: 4
typescript-eslint: 6
- eslint: 4.14
typescript-eslint: 6
- eslint: 5
typescript-eslint: 6
- eslint: 6
typescript-eslint: 6
- eslint: 9
typescript-eslint: 6
- eslint: 3
typescript-eslint: 7
- eslint: 4
typescript-eslint: 7
- eslint: 4.14
typescript-eslint: 7
- eslint: 5
typescript-eslint: 7
- eslint: 6
typescript-eslint: 7
- eslint: 7
typescript-eslint: 7
- eslint: 9
typescript-eslint: 7
- eslint: 3
typescript-eslint: 8
- eslint: 4
typescript-eslint: 8
- eslint: 4.14
typescript-eslint: 8
- eslint: 5
typescript-eslint: 8
- eslint: 6
typescript-eslint: 8
- eslint: 7
typescript-eslint: 8
- eslint: 9
typescript-eslint: 5
- node-version: 19
typescript-eslint: 7

steps:
- uses: actions/checkout@v4
Expand All @@ -46,9 +104,9 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
after_install: |
npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@5" "babel-eslint@${{ matrix.babel-eslint }}"
npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.typescript-eslint }}" "babel-eslint@${{ matrix.babel-eslint }}"
env:
NPM_CONFIG_LEGACY_PEER_DEPS: true
NPM_CONFIG_LEGACY_PEER_DEPS: "${{ matrix.typescript-eslint >= 6 && 'false' || 'true' }}"
- run: npx ls-engines
- run: npm run unit-test
- uses: codecov/[email protected]
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/node-minors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
after_install: |
npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.node-version >= 14 && '5' || (matrix.node-version >= 12 && '4' || (matrix.node-version >= 10 && '4.0' || (matrix.node-version >= 8 && '3' || '2'))) }}" "babel-eslint@${{ matrix.babel-eslint }}"
npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.node-version >= 18 && matrix.eslint >= 8 && '8' || (matrix.node-version >= 16 && matrix.eslint >= 7 && '6' || (matrix.node-version >= 14 && '5' || (matrix.node-version >= 12 && '4' || (matrix.node-version >= 10 && '4.0' || (matrix.node-version >= 8 && '3' || '2'))))) }}" "babel-eslint@${{ matrix.babel-eslint }}"
skip-ls-check: ${{ matrix.node-version < 10 && true || false }}
env:
NPM_CONFIG_LEGACY_PEER_DEPS: true
NPM_CONFIG_LEGACY_PEER_DEPS: "${{ matrix.node-version >= 16 && matrix.eslint >= 7 && 'false' || 'true' }}"
- run: npx ls-engines
if: ${{ matrix.node-version >= 12 }}
- run: npm run unit-test
Expand Down
21 changes: 16 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,29 @@ jobs:
id: changelog
run: |
# Parse the changelog for common links
_links="$(grep -P '^\[.*]:.+' ${GITHUB_WORKSPACE}/CHANGELOG.md | sort -u)"
_links="$(egrep '^\[.*]:.+' ${GITHUB_WORKSPACE:-.}/CHANGELOG.md | sort -u)"
_links="${_links//'%'/'%25'}"
_links="${_links//$'\n'/'%0A'}"
# _links="${_links//$'\n'/'%0A'}"
_links="${_links//$'\r'/'%0D'}"
# Set output 'links' to $_links
DELIMITER=$(uuidgen)
echo "links<<${DELIMITER}" >> "${GITHUB_OUTPUT}"
echo "$_links" >> "${GITHUB_OUTPUT}"
echo "${DELIMITER}" >> "${GITHUB_OUTPUT}"
- uses: softprops/action-gh-release@v1
- id: prune-footnotes
run: |
cat << 'EOF' > tmp.md
${{ steps.changelog_reader.outputs.changes }}
${{ steps.changelog.outputs.links }}
EOF
DELIMITER=$(uuidgen)
echo "body<<${DELIMITER}" >> "${GITHUB_OUTPUT}"
npx gfm-footnotes -i tmp.md > "${GITHUB_OUTPUT}"
echo "${DELIMITER}" >> "${GITHUB_OUTPUT}"
- uses: softprops/action-gh-release@v2
with:
body: |
${{ steps.changelog_reader.outputs.changes }}
${{ steps.changelog.outputs.links }}
${{ steps.prune-footnotes.outputs.body }}
52 changes: 52 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,64 @@
# Change Log

All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).
This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com).

## Unreleased

## [7.36.1] - 2024.09.12

### Fixed
* [`no-is-mounted`]: fix logic in method name check ([#3821][] @Mathias-S)
* [`jsx-no-literals`]: Avoid crashing on valueless boolean props ([#3823][] @reosarevok)

[7.36.1]: https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.36.0...v7.36.1
[#3823]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3823
[#3821]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3821

## [7.36.0] - 2024.09.12

### Added
* [`no-string-refs`]: allow this.refs in > 18.3.0 ([#3807][] @henryqdineen)
* [`jsx-no-literals`] Add `elementOverrides` option and the ability to ignore this rule on specific elements ([#3812][] @Pearce-Ropion)
* [`forward-ref-uses-ref`]: add rule for checking ref parameter is added ([#3667][] @NotWoods)

### Fixed
* [`function-component-definition`], [`boolean-prop-naming`], [`jsx-first-prop-new-line`], [`jsx-props-no-multi-spaces`], `propTypes`: use type args ([#3629][] @HenryBrown0)
* JSX pragma: fail gracefully ([#3632][] @ljharb)
* [`jsx-props-no-spreading`]: add `explicitSpread` option to schema ([#3799][] @ljharb)

### Changed
* [Tests] add @typescript-eslint/parser v6 ([#3629][] @HenryBrown0)
* [Tests] add @typescript-eslint/parser v7 and v8 ([#3629][] @hampustagerud)
* [Docs] [`no-danger`]: update broken link ([#3817][] @lucasrmendonca)
* [types] add jsdoc type annotations ([#3731][] @y-hsgw)
* [Tests] `button-has-type`: add test case with spread ([#3731][] @y-hsgw)

[7.36.0]: https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.35.2...v7.36.0
[#3799]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3799
[#3632]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3632
[#3812]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3812
[#3731]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3731
[#3694]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3667
[#3629]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3629
[#3817]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3817
[#3807]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3807

## [7.35.2] - 2024.09.03

### Fixed
* [`jsx-curly-brace-presence`]: avoid autofixing attributes with double quotes to a double quoted attribute ([#3814][] @ljharb)

[7.35.2]: https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.35.1...v7.35.2
[#3814]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3814

## [7.35.1] - 2024.09.02

### Fixed
* [`jsx-curly-brace-presence`]: do not trigger on strings containing a quote character ([#3798][] @akulsr0)

[7.35.1]: https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.35.0...v7.35.1
[#3798]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3798

## [7.35.0] - 2024.07.19
Expand Down Expand Up @@ -4266,6 +4317,7 @@ If you're still not using React 15 you can keep the old behavior by setting the
[`forbid-elements`]: docs/rules/forbid-elements.md
[`forbid-foreign-prop-types`]: docs/rules/forbid-foreign-prop-types.md
[`forbid-prop-types`]: docs/rules/forbid-prop-types.md
[`forward-ref-uses-ref`]: docs/rules/forward-ref-uses-ref.md
[`function-component-definition`]: docs/rules/function-component-definition.md
[`hook-use-state`]: docs/rules/hook-use-state.md
[`iframe-missing-sandbox`]: docs/rules/iframe-missing-sandbox.md
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ module.exports = [
| [forbid-elements](docs/rules/forbid-elements.md) | Disallow certain elements | | | | | |
| [forbid-foreign-prop-types](docs/rules/forbid-foreign-prop-types.md) | Disallow using another component's propTypes | | | | | |
| [forbid-prop-types](docs/rules/forbid-prop-types.md) | Disallow certain propTypes | | | | | |
| [forward-ref-uses-ref](docs/rules/forward-ref-uses-ref.md) | Require all forwardRef components include a ref parameter | | | | 💡 | |
| [function-component-definition](docs/rules/function-component-definition.md) | Enforce a specific function type for function components | | | 🔧 | | |
| [hook-use-state](docs/rules/hook-use-state.md) | Ensure destructuring and symmetric naming of useState hook value and setter variables | | | | 💡 | |
| [iframe-missing-sandbox](docs/rules/iframe-missing-sandbox.md) | Enforce sandbox attribute on iframe elements | | | | | |
Expand Down
45 changes: 45 additions & 0 deletions docs/rules/forward-ref-uses-ref.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Require all forwardRef components include a ref parameter (`react/forward-ref-uses-ref`)

💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).

<!-- end auto-generated rule header -->

Requires that components wrapped with `forwardRef` must have a `ref` parameter. Omitting the `ref` argument is usually a bug, and components not using `ref` don't need to be wrapped by `forwardRef`.

See <https://react.dev/reference/react/forwardRef>

## Rule Details

This rule checks all React components using `forwardRef` and verifies that there is a second parameter.

The following patterns are considered warnings:

```jsx
var React = require('react');

var Component = React.forwardRef((props) => (
<div />
));
```

The following patterns are **not** considered warnings:

```jsx
var React = require('react');

var Component = React.forwardRef((props, ref) => (
<div ref={ref} />
));

var Component = React.forwardRef((props, ref) => (
<div />
));

function Component(props) {
return <div />;
};
```

## When not to use

If you don't want to enforce that components using `forwardRef` utilize the forwarded ref.
55 changes: 55 additions & 0 deletions docs/rules/jsx-no-literals.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,61 @@ The supported options are:
- `allowedStrings` - An array of unique string values that would otherwise warn, but will be ignored.
- `ignoreProps` (default: `false`) - When `true` the rule ignores literals used in props, wrapped or unwrapped.
- `noAttributeStrings` (default: `false`) - Enforces no string literals used in attributes when set to `true`.
- `elementOverrides` - An object where the keys are the element names and the values are objects with the same options as above. This allows you to specify different options for different elements.

### `elementOverrides`

The `elementOverrides` option allows you to specify different options for different elements. This is useful when you want to enforce different rules for different elements. For example, you may want to allow string literals in `Button` elements, but not in the rest of your application.

The element name only accepts component names.
HTML element tag names are not supported. Component names are case-sensitive and should exactly match the name of the component as it is used in the JSX.
It can also be the name of a compound component (ie. `Modal.Button`).

Specifying options creates a new context for the rule, so the rule will only apply the new options to the specified element and its children (if `applyToNestedElements` is `true` - see below).
This means that the root rule options will not apply to the specified element.

In addition to the options above (`noStrings`, `allowedStrings`, `noAttributeStrings` and `ignoreProps`), you can also specify the the following options that are specific to `elementOverrides`:

- `allowElement` (default: `false`) - When `true` the rule will allow the specified element to have string literals as children, wrapped or unwrapped without warning.
- `applyToNestedElements` (default: `true`) - When `false` the rule will not apply the current options set to nested elements. This is useful when you want to apply the rule to a specific element, but not to its children.

**Note**: As this rule has no way of differentiating between different componets with the same name, it is recommended to use this option with specific components that are unique to your application.

#### `elementOverrides` Examples

The following are **correct** examples that demonstrate how to use the `elementOverrides` option:

```js
// "react/jsx-no-literals": [<enabled>, {"elementOverrides": { "Button": {"allowElement": true} }}]

var Hello = <div>{'test'}</div>;
var World = <Button>test</Button>;
```

```js
// "react/jsx-no-literals": [<enabled>, {"elementOverrides": { "Text": {"allowElement": true} }}]

var World = <Text>Hello <a href="a">world</a></Text>;
```

```js
// "react/jsx-no-literals": [<enabled>, {"elementOverrides": { "Text": {"allowElement": true, "applyToNestedElements": false} }}]

var linkText = 'world';
var World = <Text>Hello <a href="a">{linkText}</a></Text>;
```

```js
// "react/jsx-no-literals": [<enabled>, {"noStrings": true, "elementOverrides": { "Button": {"noStrings": false} }}]
// OR
// "react/jsx-no-literals": [<enabled>, {"noStrings": true, "elementOverrides": { "Button": {} }}]

var test = 'test'
var Hello = <div>{test}</div>;
var World = <Button>{'test'}</Button>;
```

## Examples

To use, you can specify as follows:

Expand Down
4 changes: 2 additions & 2 deletions docs/rules/no-danger.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

<!-- end auto-generated rule header -->

Dangerous properties in React are those whose behavior is known to be a common source of application vulnerabilities. The properties names clearly indicate they are dangerous and should be avoided unless great care is taken.
Dangerous properties in React are those whose behavior is known to be a common source of application vulnerabilities. The properties' names clearly indicate they are dangerous and should be avoided unless great care is taken.

See <https://facebook.github.io/react/tips/dangerously-set-inner-html.html>
See <https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html>

## Rule Details

Expand Down
12 changes: 7 additions & 5 deletions lib/rules/boolean-prop-naming.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,16 @@ module.exports = {
return;
}

const annotationTypeParams = component.node.parent.id.typeAnnotation.typeAnnotation.typeParameters;
const annotationTypeArguments = propsUtil.getTypeArguments(
component.node.parent.id.typeAnnotation.typeAnnotation
);
if (
annotationTypeParams && (
annotationTypeParams.type === 'TSTypeParameterInstantiation'
|| annotationTypeParams.type === 'TypeParameterInstantiation'
annotationTypeArguments && (
annotationTypeArguments.type === 'TSTypeParameterInstantiation'
|| annotationTypeArguments.type === 'TypeParameterInstantiation'
)
) {
return annotationTypeParams.params.find(
return annotationTypeArguments.params.find(
(param) => param.type === 'TSTypeReference' || param.type === 'GenericTypeAnnotation'
);
}
Expand Down
10 changes: 8 additions & 2 deletions lib/rules/button-has-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const messages = {
forbiddenValue: '"{{value}}" is an invalid value for button type attribute',
};

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
docs: {
Expand Down Expand Up @@ -149,14 +150,19 @@ module.exports = {
}

const props = node.arguments[1].properties;
const typeProp = props.find((prop) => prop.key && prop.key.name === 'type');
const typeProp = props.find((prop) => (
'key' in prop
&& prop.key
&& 'name' in prop.key
&& prop.key.name === 'type'
));

if (!typeProp) {
reportMissing(node);
return;
}

checkExpression(node, typeProp.value);
checkExpression(node, 'value' in typeProp ? typeProp.value : undefined);
},
};
},
Expand Down
3 changes: 2 additions & 1 deletion lib/rules/checked-requires-onchange-or-readonly.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const defaultOptions = {
};

/**
* @param {string[]} properties
* @param {object[]} properties
* @param {string} keyName
* @returns {Set<string>}
*/
Expand All @@ -41,6 +41,7 @@ function extractTargetProps(properties, keyName) {
);
}

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
docs: {
Expand Down
Loading

0 comments on commit 01ac0a2

Please sign in to comment.