diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0aa9588e97..0b95e4560f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [`jsx-boolean-value`]: add `assumeUndefinedIsFalse` option ([#3675][] @developer-bandi)
* `linkAttribute` setting, [`jsx-no-target-blank`]: support multiple properties ([#3673][] @burtek)
* [`jsx-no-script-url`]: add `includeFromSettings` option to support `linkAttributes` setting ([#3673][] @burtek)
+* [`jsx-one-expression-per-line`]: add `non-jsx` option to allow non-JSX children in one line ([#3677][] @burtek)
### Fixed
* [`jsx-no-leaked-render`]: preserve RHS parens for multiline jsx elements while fixing ([#3623][] @akulsr0)
@@ -32,6 +33,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [Docs] [`jsx-key`]: fix correct example ([#3656][] @developer-bandi)
* [Tests] `jsx-wrap-multilines`: passing tests ([#3545][] @burtek)
+[#3677]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3677
[#3675]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3675
[#3674]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3674
[#3673]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3673
diff --git a/docs/rules/jsx-one-expression-per-line.md b/docs/rules/jsx-one-expression-per-line.md
index 9c5fe0eac6..d2f170278b 100644
--- a/docs/rules/jsx-one-expression-per-line.md
+++ b/docs/rules/jsx-one-expression-per-line.md
@@ -133,3 +133,11 @@ Examples of **correct** code for this rule, when configured as `"single-child"`:
```
+
+Examples of **correct** code for this rule, when configured as `"non-jsx"`:
+
+```jsx
+Hello {someVariable}
+
+Hello {} there!
+```
diff --git a/lib/rules/jsx-one-expression-per-line.js b/lib/rules/jsx-one-expression-per-line.js
index 6d0d1575d9..4c5a9c970f 100644
--- a/lib/rules/jsx-one-expression-per-line.js
+++ b/lib/rules/jsx-one-expression-per-line.js
@@ -38,7 +38,7 @@ module.exports = {
type: 'object',
properties: {
allow: {
- enum: ['none', 'literal', 'single-child'],
+ enum: ['none', 'literal', 'single-child', 'non-jsx'],
},
},
default: optionDefaults,
@@ -65,6 +65,13 @@ module.exports = {
return;
}
+ if (
+ options.allow === 'non-jsx'
+ && !children.find((child) => (child.type === 'JSXFragment' || child.type === 'JSXElement'))
+ ) {
+ return;
+ }
+
const openingElement = node.openingElement || node.openingFragment;
const closingElement = node.closingElement || node.closingFragment;
const openingElementStartLine = openingElement.loc.start.line;
diff --git a/tests/lib/rules/jsx-one-expression-per-line.js b/tests/lib/rules/jsx-one-expression-per-line.js
index 0c684c7da5..62afc430d4 100644
--- a/tests/lib/rules/jsx-one-expression-per-line.js
+++ b/tests/lib/rules/jsx-one-expression-per-line.js
@@ -155,6 +155,22 @@ ruleTester.run('jsx-one-expression-per-line', rule, {
code: '{"foo"}',
options: [{ allow: 'single-child' }],
},
+ {
+ code: '123',
+ options: [{ allow: 'non-jsx' }],
+ },
+ {
+ code: 'foo',
+ options: [{ allow: 'non-jsx' }],
+ },
+ {
+ code: '{"foo"}',
+ options: [{ allow: 'non-jsx' }],
+ },
+ {
+ code: '{}',
+ options: [{ allow: 'non-jsx' }],
+ },
{
code: '{foo && }',
options: [{ allow: 'single-child' }],
@@ -184,6 +200,38 @@ ruleTester.run('jsx-one-expression-per-line', rule, {
`,
features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix
},
+ {
+ code: 'Hello {name}',
+ options: [{ allow: 'non-jsx' }],
+ },
+ {
+ code: `
+
+ Hello {name} there!
+ `,
+ options: [{ allow: 'non-jsx' }],
+ },
+ {
+ code: `
+
+ Hello {} there!
+ `,
+ options: [{ allow: 'non-jsx' }],
+ },
+ {
+ code: `
+
+ Hello {()} there!
+ `,
+ options: [{ allow: 'non-jsx' }],
+ },
+ {
+ code: `
+
+ Hello {(() => )()} there!
+ `,
+ options: [{ allow: 'non-jsx' }],
+ },
]),
invalid: parsers.all([
@@ -493,6 +541,28 @@ foo
],
parserOptions,
},
+ {
+ code: `
+
+
+
+ `,
+ output: `
+
+ ${' '/* intentional trailing space */}
+{' '}
+
+
+ `,
+ errors: [
+ {
+ messageId: 'moveToNewLine',
+ data: { descriptor: 'Baz' },
+ },
+ ],
+ options: [{ allow: 'non-jsx' }],
+ parserOptions,
+ },
{
code: `
@@ -1257,6 +1327,23 @@ foo
},
],
},
+ {
+ code: `
+
+ `,
+ output: `
+
+
+
+ `,
+ options: [{ allow: 'non-jsx' }],
+ errors: [
+ {
+ messageId: 'moveToNewLine',
+ data: { descriptor: 'Foo' },
+ },
+ ],
+ },
{
code: `