-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New rule: jsx-one-expression-per-line #1497
New rule: jsx-one-expression-per-line #1497
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this seems pretty solid.
I gather that you're choosing an indent of zero, so that the indent rule can correct it properly?
There are only tests for components. Should it also warn on |
That's right.
Not sure why that would make a difference, but I added a case for ya. |
].join('\n'), | ||
output: [ | ||
'<div>', | ||
' <span />foo', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the lack of whitespace before "foo" is important, then it's just as important after "foo" - meaning, this example can't be autofixed.
However,
<div>
<span /> foo <input />
</div>
definitely should become:
<div>
<span />
foo
<input />
</div>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ljharb I believe white space in jsx is differnt from HTML and in your example the two jsx snippets are actually rendered differently. foo
in the first snippet will be rendered to the DOM with a whitespace on either side, while foo
in the second snippet will have no whitespace.
However, even if I'm correct the rule still does need to be patched. Currently, the autofix does change the rendered whitespace under certain conditions, which is obviously unacceptable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using curlies and transforming into a string literal with spacing on either side seems the most accurate. Is this acceptible?
<div>
<span />
{' foo '}
<input />
</div>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, that'd be great!
As long as the autofix is not changing the resulting whitespace that's rendered, we're good.
@TSMMark i think we'd need to either add an option, or have this be the default, so that the things that aren't autofixable aren't warned. |
For the record, I am attempting to handle all autofix cases and it is proving rather difficult. Edit: Just discovered |
@ljharb Well, I had to throw everything out and start over, but now we can handle all cases! 😌 How's it look? |
Now that we handle all nodes instead of only React elements, this name seems more fitting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking much better :-)
].join('\n'), | ||
output: [ | ||
'<div>', | ||
' foo ', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can cause issues due to rules that strip trailing spaces; i think this needs to remain as foo {"bar"}
, untouched.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
foo
and {"bar"}
are 2 different expressions and I don't want them on the same line. JSX parser ignores trailing spaces such as these, however, I'll see if I can kill them, as per #1497 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right - but the jsx parser doesn't ignore the space in between foo {"bar" }
- so to make it the same, with an autofix, you'd need:
foo
{' '}
{'bar'}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if you look on the next line 117 you will see {\' \'}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It results in the same output after JSX parsing. I am following the guidelines:
Since all rules are run again after the initial round of fixes is applied, it’s not necessary for a rule to check whether the code style of a fix will cause errors to be reported by another rule.
https://eslint.org/docs/developer-guide/working-with-rules#applying-fixes
The trailing space in the output foo
is inconsequential. Its only impact is offending no-trailing-spaces
, which, as stated in the guide, is not our concern here.
].join('\n'), | ||
output: [ | ||
'<div>', | ||
' {"foo"} ', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this trailing space should be removed, if the space on the next line is being explicitly preserved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSX parser already ignores trailing spaces, and no-trailing-spaces
will chop them off anyway... but let me see if I can get rid of them. My thought process was the JSX output is identical so I would not need to handle them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i agree that no-trailing-spaces could do the cleanup, but it seems easy enough to .trim()
any newly autofixed lines :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See latest commit, best I can do right now. As you said, this does trim the newly autofixed nodes; however, it does not handle cases where the 'Literal' node is the first node on the line because it does not need to be placed on a new line, requiring no report/fix for that node.
Example:
].join('\n'), | ||
output: [ | ||
'<Text style={styles.foo}>', | ||
'{ bar } ', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also here?
From issue #1491.
Tested against a small react-native app with 50-100 components and it works great.