Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
* [`jsx-newline`]: add new rule ([#2693][] @jzabala)
* [`jsx-no-constructed-context-values`]: add new rule which checks when the value passed to a Context Provider will cause needless rerenders ([#2763][] @dylanOshima)
* [`jsx-wrap-multilines`]: fix crash with `declaration`s that are on a new line after `=` ([#2875][] @ljharb)
* [`jsx-indent-props`]: add `ignoreTernaryOperator` option ([#2846][] @SebastianZimmer)

### Fixed
* [`display-name`]/component detection: avoid a crash on anonymous components ([#2840][] @ljharb)
Expand All @@ -36,6 +37,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
[#2869]: https://github.com/yannickcr/eslint-plugin-react/issues/2869
[#2852]: https://github.com/yannickcr/eslint-plugin-react/pull/2852
[#2851]: https://github.com/yannickcr/eslint-plugin-react/issues/2851
[#2846]: https://github.com/yannickcr/eslint-plugin-react/pull/2846
[#2843]: https://github.com/yannickcr/eslint-plugin-react/pull/2843
[#2840]: https://github.com/yannickcr/eslint-plugin-react/issues/2840
[#2835]: https://github.com/yannickcr/eslint-plugin-react/pull/2835
Expand Down
21 changes: 19 additions & 2 deletions docs/rules/jsx-indent-props.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ firstName="John"

## Rule Options

It takes an option as the second parameter which can be `"tab"` for tab-based indentation, a positive number for space indentations or `"first"` for aligning the first prop for each line with the tag's first prop.
It takes an option as the second parameter which can either be the indent mode or an object to define further settings.
The indent mode can be `"tab"` for tab-based indentation, a positive number for space indentations or `"first"` for aligning the first prop for each line with the tag's first prop.
Note that using the `"first"` option allows very inconsistent indentation unless you also enable a rule that enforces the position of the first prop.
If the second parameter is an object, it can be used to specify the indent mode as well as the option `ignoreTernaryOperator`, which causes the indent level not to be increased by a `?` or `:` operator (default is `false`).


```js
...
"react/jsx-indent-props": [<enabled>, 'tab'|<number>|'first']
"react/jsx-indent-props": [<enabled>, 'tab'|<number>|'first'|<object>]
...
```

Expand Down Expand Up @@ -100,6 +103,20 @@ firstName="John"

<Hello firstName="Jane"
lastName="Doe" />

// indent level increase on ternary operator (default setting)
// [2, 2]
? <Hello
firstName="John"
lastName="Doe"
/>

// no indent level increase on ternary operator
// [2, { indentMode: 2, ignoreTernaryOperator: true} ]
? <Hello
firstName="John"
lastName="Doe"
/>
```

## When not to use
Expand Down
34 changes: 29 additions & 5 deletions lib/rules/jsx-indent-props.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ module.exports = {
enum: ['tab', 'first']
}, {
type: 'integer'
}, {
type: 'object',
properties: {
indentMode: {
oneOf: [{
enum: ['tab', 'first']
}, {
type: 'integer'
}]
},
ignoreTernaryOperator: {
type: 'boolean'
}
}
}]
}]
},
Expand All @@ -66,18 +80,28 @@ module.exports = {
isUsingOperator: false,
currentOperator: false
};
let ignoreTernaryOperator = false;

if (context.options.length) {
if (context.options[0] === 'first') {
const isConfigObject = typeof context.options[0] === 'object';
const indentMode = isConfigObject
? context.options[0].indentMode
: context.options[0];

if (indentMode === 'first') {
indentSize = 'first';
indentType = 'space';
} else if (context.options[0] === 'tab') {
} else if (indentMode === 'tab') {
indentSize = 1;
indentType = 'tab';
} else if (typeof context.options[0] === 'number') {
indentSize = context.options[0];
} else if (typeof indentMode === 'number') {
indentSize = indentMode;
indentType = 'space';
}

if (isConfigObject && context.options[0].ignoreTernaryOperator) {
ignoreTernaryOperator = true;
}
}

/**
Expand Down Expand Up @@ -145,7 +169,7 @@ module.exports = {
function checkNodesIndent(nodes, indent) {
nodes.forEach((node) => {
const nodeIndent = getNodeIndent(node);
if (line.isUsingOperator && !line.currentOperator && indentSize !== 'first') {
if (line.isUsingOperator && !line.currentOperator && indentSize !== 'first' && !ignoreTernaryOperator) {
indent += indentSize;
line.isUsingOperator = false;
}
Expand Down
42 changes: 42 additions & 0 deletions tests/lib/rules/jsx-indent-props.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,48 @@ ruleTester.run('jsx-indent-props', rule, {
'/>'
].join('\n'),
options: ['first']
}, {
code: [
'{this.props.ignoreTernaryOperatorFalse',
' ? <span',
' className="value"',
' some={{aaa}}',
' />',
' : null}'
].join('\n'),
output: [
'{this.props.ignoreTernaryOperatorFalse',
' ? <span',
' className="value"',
' some={{aaa}}',
' />',
' : null}'
].join('\n'),
options: [{
indentMode: 2,
ignoreTernaryOperator: false
}]
}, {
code: [
'{this.props.ignoreTernaryOperatorTrue',
' ? <span',
' className="value"',
' some={{aaa}}',
' />',
' : null}'
].join('\n'),
output: [
'{this.props.ignoreTernaryOperatorTrue',
' ? <span',
' className="value"',
' some={{aaa}}',
' />',
' : null}'
].join('\n'),
options: [{
indentMode: 2,
ignoreTernaryOperator: true
}]
}],

invalid: [{
Expand Down