Skip to content

Commit f2869fd

Browse files
justisbljharb
authored andcommitted
[New] jsx-props-no-multi-spaces: improve autofix for multi-line
1 parent dd2e968 commit f2869fd

File tree

3 files changed

+79
-10
lines changed

3 files changed

+79
-10
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
66

77
## Unreleased
88

9+
### Added
10+
* [`jsx-props-no-multi-spaces`]: improve autofix for multi-line ([#3930][] @justisb)
11+
912
### Fixed
1013
* [`no-unknown-property`]: allow `onLoad` on `body` ([#3923][] @DerekStapleton)
1114

15+
[#3930]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3930
1216
[#3923]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3923
1317

1418
## [7.37.5] - 2025.04.03

lib/rules/jsx-props-no-multi-spaces.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,22 @@ module.exports = {
8080
prop1: getPropName(prev),
8181
prop2: getPropName(node),
8282
},
83+
fix(fixer) {
84+
const comments = sourceCode.getCommentsBefore ? sourceCode.getCommentsBefore(node) : [];
85+
const nodes = [].concat(prev, comments, node);
86+
const fixes = [];
87+
88+
for (let i = 1; i < nodes.length; i += 1) {
89+
const prevNode = nodes[i - 1];
90+
const currNode = nodes[i];
91+
if (currNode.loc.start.line - prevNode.loc.end.line >= 2) {
92+
const indent = ' '.repeat(currNode.loc.start.column);
93+
fixes.push(fixer.replaceTextRange([prevNode.range[1], currNode.range[0]], `\n${indent}`));
94+
}
95+
}
96+
97+
return fixes;
98+
},
8399
});
84100
}
85101

tests/lib/rules/jsx-props-no-multi-spaces.js

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
8484
{
8585
code: `
8686
<button
87-
title="Some button"
87+
title="Some button 8"
8888
type="button"
8989
/>
9090
`,
9191
},
9292
{
9393
code: `
9494
<button
95-
title="Some button"
95+
title="Some button 8"
9696
onClick={(value) => {
9797
console.log(value);
9898
}}
@@ -104,7 +104,7 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
104104
{
105105
code: `
106106
<button
107-
title="Some button"
107+
title="Some button 2"
108108
// this is a comment
109109
onClick={(value) => {
110110
console.log(value);
@@ -116,7 +116,7 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
116116
{
117117
code: `
118118
<button
119-
title="Some button"
119+
title="Some button 2"
120120
// this is a comment
121121
// this is a second comment
122122
onClick={(value) => {
@@ -129,7 +129,7 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
129129
{
130130
code: `
131131
<App
132-
foo="Some button" // comment
132+
foo="Some button 3" // comment
133133
// comment
134134
bar=""
135135
/>
@@ -138,7 +138,7 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
138138
{
139139
code: `
140140
<button
141-
title="Some button"
141+
title="Some button 3"
142142
/* this is a multiline comment
143143
...
144144
... */
@@ -263,6 +263,12 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
263263
type="button"
264264
/>
265265
`,
266+
output: `
267+
<button
268+
title='Some button'${semver.satisfies(eslintPkg.version, '> 3') ? '' : '\n'}
269+
type="button"
270+
/>
271+
`,
266272
errors: [
267273
{
268274
messageId: 'noLineGap',
@@ -273,7 +279,7 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
273279
{
274280
code: `
275281
<button
276-
title="Some button"
282+
title="Some button 4"
277283
278284
onClick={(value) => {
279285
console.log(value);
@@ -282,6 +288,15 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
282288
type="button"
283289
/>
284290
`,
291+
output: `
292+
<button
293+
title="Some button 4"${semver.satisfies(eslintPkg.version, '> 3') ? '' : '\n'}
294+
onClick={(value) => {
295+
console.log(value);
296+
}}${semver.satisfies(eslintPkg.version, '> 3') ? '' : '\n'}
297+
type="button"
298+
/>
299+
`,
285300
errors: [
286301
{
287302
messageId: 'noLineGap',
@@ -297,7 +312,7 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
297312
{
298313
code: `
299314
<button
300-
title="Some button"
315+
title="Some button 5"
301316
// this is a comment
302317
onClick={(value) => {
303318
console.log(value);
@@ -306,6 +321,16 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
306321
type="button"
307322
/>
308323
`,
324+
output: `
325+
<button
326+
title="Some button 5"
327+
// this is a comment
328+
onClick={(value) => {
329+
console.log(value);
330+
}}
331+
type="button"
332+
/>
333+
`,
309334
errors: [
310335
{
311336
messageId: 'noLineGap',
@@ -316,7 +341,7 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
316341
{
317342
code: `
318343
<button
319-
title="Some button"
344+
title="Some button 6"
320345
// this is a comment
321346
// second comment
322347
@@ -327,6 +352,17 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
327352
type="button"
328353
/>
329354
`,
355+
output: `
356+
<button
357+
title="Some button 6"
358+
// this is a comment
359+
// second comment
360+
onClick={(value) => {
361+
console.log(value);
362+
}}
363+
type="button"
364+
/>
365+
`,
330366
errors: [
331367
{
332368
messageId: 'noLineGap',
@@ -341,7 +377,7 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
341377
{
342378
code: `
343379
<button
344-
title="Some button"
380+
title="Some button 7"
345381
/*this is a
346382
multiline
347383
comment
@@ -354,6 +390,19 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
354390
type="button"
355391
/>
356392
`,
393+
output: `
394+
<button
395+
title="Some button 7"
396+
/*this is a
397+
multiline
398+
comment
399+
*/
400+
onClick={(value) => {
401+
console.log(value);
402+
}}
403+
type="button"
404+
/>
405+
`,
357406
errors: [
358407
{
359408
messageId: 'noLineGap',

0 commit comments

Comments
 (0)