Skip to content

Commit

Permalink
[New] jsx-wrap-multilines: add never option to prohibit wrapping …
Browse files Browse the repository at this point in the history
…parens on multiline JSX
  • Loading branch information
reedws authored and ljharb committed Dec 15, 2023
1 parent 37d8bbe commit b4b7497
Show file tree
Hide file tree
Showing 4 changed files with 469 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [`no-unknown-property`]: add `displaystyle` on `<math>` ([#3652][] @lounsbrough)
* [`prefer-read-only-props`], [`prop-types`], component detection: allow components to be async functions ([#3654][] @pnodet)
* [`no-unknown-property`]: support `onResize` on audio/video tags ([#3662][] @caesar1030)
* [`jsx-wrap-multilines`]: add `never` option to prohibit wrapping parens on multiline JSX ([#3668][] @reedws)

### Fixed
* [`jsx-no-leaked-render`]: preserve RHS parens for multiline jsx elements while fixing ([#3623][] @akulsr0)
Expand All @@ -26,6 +27,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [Refactor] [`jsx-props-no-multi-spaces`]: extract type parameters to var ([#3634][] @HenryBrown0)
* [Docs] [`jsx-key`]: fix correct example ([#3656][] @developer-bandi)

[#3668]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3668
[#3666]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3666
[#3662]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3662
[#3656]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3656
Expand Down
231 changes: 230 additions & 1 deletion docs/rules/jsx-wrap-multilines.md
Expand Up @@ -50,7 +50,7 @@ var Hello = createReactClass({
});
```

Examples of **correct** code for this rule:
Examples of **correct** code for this rule, when configured with either `parens` or `parens-new-line`:

```jsx
var singleLineJSX = <p>Hello</p>
Expand All @@ -66,6 +66,36 @@ var Hello = createReactClass({
});
```

Examples of **incorrect** code for this rule, when configured with `never`:

```jsx
var singleLineJSX = <p>Hello</p>

var Hello = createReactClass({
render: function() {
return (
<div>
<p>Hello {this.props.name}</p>
</div>
);
}
});
```

Examples of **correct** code for this rule, when configured with `never`:

```jsx
var singleLineJSX = <p>Hello</p>

var Hello = createReactClass({
render: function() {
return <div>
<p>Hello {this.props.name}</p>
</div>;
}
});
```

### `declaration`

Examples of **incorrect** code for this rule, when configured with `{ declaration: "parens" }`:
Expand Down Expand Up @@ -116,6 +146,30 @@ var hello = (
);
```

Examples of **incorrect** code for this rule, when configured with `{ declaration: "never" }`:

```jsx
var hello = (<div>
<p>Hello</p>
</div>);
```

```jsx
var hello = (
<div>
<p>Hello</p>
</div>
);
```

Examples of **correct** code for this rule, when configured with `{ declaration: "never" }`.

```jsx
var hello = <div>
<p>Hello</p>
</div>;
```

### `assignment`

Examples of **incorrect** code for this rule, when configured with `{ assignment: "parens" }`.
Expand Down Expand Up @@ -172,6 +226,33 @@ hello = (
);
```

Examples of **incorrect** code for this rule, when configured with `{ assignment: "never" }`.

```jsx
var hello;
hello = (<div>
<p>Hello</p>
</div>);
```

```jsx
var hello;
hello = (
<div>
<p>Hello</p>
</div>
);
```

Examples of **correct** code for this rule, when configured with `{ assignment: "never" }`.

```jsx
var hello;
hello = <div>
<p>Hello</p>
</div>;
```

### `return`

Examples of **incorrect** code for this rule, when configured with `{ return: "parens" }`.
Expand Down Expand Up @@ -234,6 +315,36 @@ function hello() {
}
```

Examples of **incorrect** code for this rule, when configured with `{ return: "never" }`.

```jsx
function hello() {
return (<div>
<p>Hello</p>
</div>);
}
```

```jsx
function hello() {
return (
<div>
<p>Hello</p>
</div>
);
}
```

Examples of **correct** code for this rule, when configured with `{ return: "never" }`.

```jsx
function hello() {
return <div>
<p>Hello</p>
</div>;
}
```

### `arrow`

Examples of **incorrect** code for this rule, when configured with `{ arrow: "parens" }`.
Expand Down Expand Up @@ -284,6 +395,30 @@ var hello = () => (
);
```

Examples of **incorrect** code for this rule, when configured with `{ arrow: "never" }`.

```jsx
var hello = () => (<div>
<p>World</p>
</div>);
```

```jsx
var hello = () => (
<div>
<p>World</p>
</div>
);
```

Examples of **correct** code for this rule, when configured with `{ arrow: "never" }`.

```jsx
var hello = () => <div>
<p>World</p>
</div>;
```

### `condition`

Examples of **incorrect** code for this rule, when configured with `{ condition: "parens" }`.
Expand Down Expand Up @@ -346,6 +481,36 @@ Examples of **correct** code for this rule, when configured with `{ condition: "
</div>
```

Examples of **incorrect** code for this rule, when configured with `{ condition: "never" }`.

```jsx
<div>
{foo ? (<div>
<p>Hello</p>
</div>) : null}
</div>
```

```jsx
<div>
{foo ? (
<div>
<p>Hello</p>
</div>
): null}
</div>
```

Examples of **correct** code for this rule, when configured with `{ condition: "never" }`.

```jsx
<div>
{foo ? <div>
<p>Hello</p>
</div> : null}
</div>
```

### `logical`

Examples of **incorrect** code for this rule, when configured with `{ logical: "parens" }`.
Expand Down Expand Up @@ -416,6 +581,40 @@ Examples of **correct** code for this rule, when configured with `{ logical: "pa
</div>
```

Examples of **incorrect** code for this rule, when configured with `{ logical: "never" }`.

```jsx
<div>
{foo &&
(<div>
<p>Hello World</p>
</div>)
}
</div>
```

```jsx
<div>
{foo && (
<div>
<p>Hello World</p>
</div>
)}
</div>
```

Examples of **correct** code for this rule, when configured with `{ logical: "never" }`.

```jsx
<div>
{foo &&
<div>
<p>Hello World</p>
</div>
}
</div>
```

### `prop`

Examples of **incorrect** code for this rule, when configured with `{ prop: "parens" }`.
Expand Down Expand Up @@ -477,3 +676,33 @@ Examples of **correct** code for this rule, when configured with `{ prop: "paren
<p>Hello</p>
</div>;
```

Examples of **incorrect** code for this rule, when configured with `{ prop: "never" }`.

```jsx
<div foo={(<div>
<p>Hello</p>
</div>)}>
<p>Hello</p>
</div>;
```

```jsx
<div foo={(
<div>
<p>Hello</p>
</div>
)}>
<p>Hello</p>
</div>;
```

Examples of **correct** code for this rule, when configured with `{ prop: "never" }`.

```jsx
<div foo={<div>
<p>Hello</p>
</div>}>
<p>Hello</p>
</div>;
```
24 changes: 17 additions & 7 deletions lib/rules/jsx-wrap-multilines.js
Expand Up @@ -31,6 +31,7 @@ const DEFAULTS = {

const messages = {
missingParens: 'Missing parentheses around multilines JSX',
extraParens: 'Expected no parentheses around multilines JSX',
parensOnNewLines: 'Parentheses around JSX should be on separate lines',
};

Expand All @@ -51,25 +52,25 @@ module.exports = {
// true/false are for backwards compatibility
properties: {
declaration: {
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
},
assignment: {
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
},
return: {
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
},
arrow: {
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
},
condition: {
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
},
logical: {
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
},
prop: {
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
},
},
additionalProperties: false,
Expand Down Expand Up @@ -184,6 +185,15 @@ module.exports = {
}
}
}

if (option === 'never' && isParenthesized(context, node)) {
const tokenBefore = sourceCode.getTokenBefore(node);
const tokenAfter = sourceCode.getTokenAfter(node);
report(node, 'extraParens', (fixer) => fixer.replaceTextRange(
[tokenBefore.range[0], tokenAfter.range[1]],
sourceCode.getText(node)
));
}
}

// --------------------------------------------------------------------------
Expand Down

0 comments on commit b4b7497

Please sign in to comment.