Avoid introducing linebreaks in template interpolations#15209
Avoid introducing linebreaks in template interpolations#15209fisker merged 5 commits intoprettier:mainfrom
Conversation
f611481 to
2a60012
Compare
|
I haven't fully reviewed the code yet, so I can't approve it on GitHub. However, I'd like to express my personal opinion on this approach. I am in favor of this approach. From my experience, template literals often contain sentences in natural language. Therefore, I believe it's hard to determine the format of expressions within template literals solely from AST. Ideally, we wouldn't want to introduce a format that depends on user-input line breaks. However, I think this is acceptable. If we decide to accept this PR, we'll need to update https://prettier.io/docs/en/rationale.html. |
|
I've gone ahead and updated the rationale (and the changelog). Does anyone have opinions on whether we should still keep the old "sufficiently simple" heuristic, or just rely on the "is there a linebreak" thing? |
| export @decorator class Foo {} | ||
| ``` | ||
|
|
||
| ### Template literals |
There was a problem hiding this comment.
Can you add code example to here same as changelog?
|
Is the current heuristic really hopeless? Or can it probably just be updated to cover cases like |
|
I don't think the current heuristic is salvageable. As @sosukesuzuki points out, the fundamental problem is that the appropriate formatting depends on the content of the template string, which is just not something it's practical for Prettier to reason about. It's not just stuff like |
4861776 to
bf9845a
Compare
|
Rebased. Friendly ping for maintainers - can we get this merged? |
|
I hate that prettier mangles template literals, but I have a question about your implementation. You state that you won't add linebreaks in this example: But that expression would already not be split or kept as one line because prettier only splits up a line when the line break occur within a sub expression |
Suppose let items = `
${someComplicatedExpression(
asdf,
)}
${someComplicatedExpression(
asdf,
)}
`;With this PR, it won't anymore; it just leaves the input alone, like this: let items = `
${someComplicatedExpression(asdf)}
${someComplicatedExpression(asdf)}
`;Does that answer your question? If not I don't understand your question. |
|
@bakkot It perfectly answers my question. That makes total sense, if the user has a line break within the sub expression within a template string, it will format it nicely... if no line breaks, it doesn't touch it. I played around with it and it behaves like I would expect, which is leaving my template strings alone. |
|
@sosukesuzuki Any chance we could look at this PR again? It's a blocker in our teams adopting prettier and from the checks above it seems to be mergeable pending review. |
|
@fisker Can you review this? |
|
@sosukesuzuki Is it possible to land this without @fisker's review? This has been ready for four months. |
|
@sosukesuzuki @fisker ping? |
|
I'm deeply sorry for the long delay. Sometimes respects the original line break is annoying, when I delete props from object literal, I don't know if it can fit one line, I often have to delete new line after Anyway, I agree curenttly we format the template literals really bad in some cases, I'll just remain neutral on this one. @thorn0 also seems not happy with this solution, #15209 (comment) |
|
What about template literals like Prettier pr-15209 Input: let items = `${someComplicatedExpression(asdf) + cantileveredRhinocerosFactory / someComplicatedExpression(asdf) - transdecimalThingamabobProvider}px`;Output: let items = `${someComplicatedExpression(asdf) + cantileveredRhinocerosFactory / someComplicatedExpression(asdf) - transdecimalThingamabobProvider}px`; |
That's a convincing example. But what about longer expressions, those that are longer than |
|
In my experience it people overwhelmingly prefer not to have linebreaks within an interpolation, even if the interpolation is long. So I think the right default is to not introduce any linebreaks and allow users to opt in where it makes sense to do so by adding one, instead of trying to have a more complicated rule. I'm open to more complicated rules if you want to suggest them, but I think there's a lot of value in simplicity. |
Description
In a template string like
avoid adding a linebreak when formatting the expression unless one is already present or it's unavoidable due to e.g. a nested function. Previously a linebreak could be introduced whenever some interpolation in the template was sufficiently "not simple":
Now it will instead be left alone.
If a linebreak is already present within the
${...}, format as normal.Fixes (?) #3368. It doesn't introduce a new option; instead, if you actively want a linebreak, you can add one yourself (just like for object literals). At the moment it still keeps the old "sufficiently simple" heuristic, but I'm happy to rip that out and just rely on the "is a newline already present" heuristic instead.
A possible refinement is to only apply avoid linebreaks when either the line before or after the interpolation has some non-whitespace text. That would allow introducing linebreaks in cases like this:
I'm happy to push a commit with that change if you'd like.
Checklist
I haven't done these yet because I'm waiting for approval for this approach. I'll update this PR if and when it's decided this is a good idea.
docs/directory).changelog_unreleased/*/XXXX.mdfile followingchangelog_unreleased/TEMPLATE.md.✨Try the playground for this PR✨