-
Notifications
You must be signed in to change notification settings - Fork 47.3k
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
JSX whitespace coalescing rules #480
Conversation
@jeffmo Sanity check |
|
||
var lastNonEmptyLine = -1; | ||
trimmedLines.forEach(function (line, ii) { | ||
if (line) lastNonEmptyLine = ii; |
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'm finding it a little difficult to follow what's going on in here, but I think this is the source of failure when transforming something like:
/**
* @jsx React.DOM
*/
<img alt="" src="" />
which, after these changes, now transforms to
/**
* @jsx React.DOM
*/
React.DOM.img( {alt:"" src:""} )
In that scenario, line
here is ""
-- and thus falsey.
On a side note (for future ref): I believe our style guide asks that you always use curly braces and to put conditional bodies on a new line
on |
@jeffmo More thoroughly documented the refactoring tool, but I'm not sure how useful/understandable it really is. I doubt anyone would be able to make an informed decision on which transformations to disable (I would keep all of them enabled). In my opinion the annotated space It's also worth pointing out that running From my perspective I feel good about the current code and as far as I can tell, it follows your code style. Obviously, feel free to object :) and like I said on IRC, I'll be available until friday, but after that I won't be back until next sunday. Although it is not required I do recommend considering #489 as well, without it the explicit whitespace injected by the refactoring tool will cause quite a lot of additional DOM spans to be rendered, as well as when explicitly inserting whitespace as you're aware can be quite common. |
It looks like
transforms to
Note the spaces around "stuff". Don't the rules that we've settled on suggest that there shouldn't be spaces here? (At least thats what the conversion tool's output suggests...) |
@jeffmo Correct, and it produces the correct output (without spaces) for me.
Is it perhaps a repeat of yesterday?
Hehe (Just to be on the safe-side, note that JSXTranformer in my refactoring tool branch does NOT have the whitespace patch applied, they are separate branches) |
What's the status here? |
I think we need a solution to span-wrapping of Adding spans can break styling and externally-expected DOM structures -- so we need some kind of workaround for the transition (or maybe we bite the bullet). @syranide: Were you planning to talk to @petehunt and @sebmarkbage about fixing the spans issue at a deeper level? |
(other than that, I think this is good to go) |
@jeffmo #489 solves that specific case, that PR previously made sense by itself as However, it seems to me like React generating spans is simply the way it is currently. In my opinion, in this context, using spans without a That being said, I did look into it. There are basically two possible solutions that I considered:
So, given the current state of React of So #489 should suffice for any "issues" introduced by JSX and the "codemod", and should bring parity and possibly even improvements to any projects as compared to before this PR is introduced. That is, nothing can get worse, it may only change for the better in certain cases (and if you rely on such specific behavior, you're going to be in trouble anyway sooner or later). |
@jeffmo Not saying we should do it, but one idea is to keep a legacy version of JSX(Transform) in the repository for the time being. So that anyone who feel they can't switch to the newer right away can stay behind a short while. Also, what is your thoughts for the "codemod" tool? Bundle it with React for now? Point people towards my repository? (Just checking, I honestly have no preference) |
The simplified (technical) explanation for the current whitespace rules would be:
|
This is a great summary, thanks.
That's not a bad idea -- but I'd be a little worried about maintenance and having to support the old + the new transform. I say we just bite the bullet and move forward
I have a little CLI npm module I've packaged up (not published or checked in anywhere yet) that I've been using to codemod whole directories. We can probably just publish that and reference it in the CHANGELOG (as well as in the announcements for the next major rev cut) Anyway, you've convinced me it's worth moving forward despite the spans problem, so let's land this damn thing already! |
@jeffmo Sounds great! |
@jeffmo PS. I have not yet thoroughly vetted my |
Should make facebook#480 a little less painless. This brings us a lot closer to pretending we're in a world where text components don't exist at all; I think this is a lot nicer overall. With this, `<div>{['A', ' ', 'B']}</div>` turns into `<div>A B</div>` instead of `<div><span>A</span><span> </span><span>B</span></div>`. The only "weird" thing that I can see here is that `<div>x{flag && <a />}</div>` will toggle between rendering to `<div>x</div>` and `<div><span>x</span><a /></div>`.
@jeffmo Rebased (only a test had a non-conflict conflict). |
JSX whitespace coalescing rules
This was fixed by facebook#480.
What's the current status of how React transforms JSX whitespace? I'm trying to figure it out for vanillajsx. |
Current rules
While they seem reasonable to some extent, they are quite nonsensical from a theoretical perspective.
{expr}
is treated identically to<tag>
and</tag>
· space
¬ newline
Whitespace rules
1. Remove whitespace, makes no sense whatsoever.
2. Replace whitespace with a space, consistent output
Minimal whitespace is always produced and it is consistent with normal browser rendering, any and all special whitespace requirements are explicit and easy to spot in the code.
3. Replace whitespace with spaces, faithful to source code
Unintended double-spaces are possible but unlikely and normally renders identically to 2. Interesting in that it might encourage less hacky
and morewhite-space: pre
, all things considered it seems like a feature.4. Keep whitespace as is, identical to source
Normally renders identically to 3 but relying on non-escaped non-space whitespace seems really finicky and hardly something that should be encouraged, non-space whitespace should be explicitly injected.
Newline rules
A. Remove newlines, consistent and uncomplicated
Text requires explicit whitespace injection, slightly cumbersome and ugly in "worst case".
B. Remove newlines but insert a space between text
Most likely what the user wants without having to be overly explicit, implicit space can be overridden with braces.
C. Remove newlines, but insert a space before/after text
This may seem kind of interesting at first, even though it's a bit weird. However this is, in its basic form, the root cause of all the excess whitespace that is creeping in at the start and end of every text with the current rules. In my opinion, the only way this rule makes sense (without being a burden) is if it does not match after an opening tag or before a closing tag... simply put, it would only add a space when text is sibling to a node (or a brace). Which would make it quite magic, which isn't necessarily bad, but my gut feeling says it is. Being explicit in ambiguous cases is preferable to it sometimes making the wrong decision (especially when it comes to tests), and the rules would be very complex to explain.
D. Remove newlines but insert a newline between text
Likely unintended and very unlikely to be useful, easy to break if relying on identical text output, implicit newline can be overriden with braces.
E. Remove newlines before and after tags, faithful to source code
Although there are vaguely potential uses for this, that much text should never be inlined, be explicit if you absolutely must, implicit newlines can be overriden with braces.
F. Keep newlines as is, identical to source but whitespace is trimmed
This is a horrible feature in HTML, let's not go there.
All lines are trimmed from leading and trailing whitespace, indenting code must never interfere with output in my opinion.
Contenders
2A/2B. Minimal whitespace, consistent output, encourage explicit whitespace
The user is encouraged to be explicit in special-cases. With 2A we assume nothing, slightly cumbersome/ugly when dealing with moderate amounts of text, but very straight-forward. With 2B we reasonably assume that multi line texts should be separated by a space, the user can override if necessary.
3A/B. Additional whitespace is most likely intentional, but very rarely useful
Although in my opinion this is largely because of the largely unknown
white-space: pre
, although still limited in usefulness. Otherwise same as 2A/B, except that 3B has a bit weird mix of keeping and generating whitespace, but results are intuitive and straight-forward still.My personal vote goes to 3B at this time.
It's also worth mentioning that ALL whitespace rules can be overriden with braces, so none of these rules are able to exclude any useful behavior, it can only make the resulting code more or less ugly.
I would also strongly recommend #489 to cut down on braces exploding into spans (especially when transforming existing code as it would add braces in a lot of places, generating lots and lots of unnecessary spans).
Legacy JSX
Seeing as there's probably already a bit of code out there using JSX, I've written a first implementation of a tool that converts existing JSX files so that they continue to produce identical output even after switching to these new whitespace rules (final implementation is awaiting final verdict on which whitespace rules we want). This obviously potentially uglifies the code a bit with
{' '}
, but they are easy to spot, and each transformation in the tool is optional, including even using{(' ')}
as space to make it more obvious what's auto-generated.https://github.com/syranide/react/compare/jsx-legacy-whitespace-tool