-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Glimmer: fix newlines rendering in non-mustache attributes #8667
Conversation
@dcyriller I saw you were an author of this part of code. Let me know what you think! My first PR to prettier so might be rough around the edges :) |
We don't trim attribute in html Prettier pr-8667 --parser html Input: <a title="
attr
"></a> Output: <a
title="
attr
"
></a> |
// they're a ConcatStatement rather than a single TextNode | ||
// if the attribute value is a plain string, we only trim it and avoid inserting hardlines | ||
// since they're not rendered correctly within attributes | ||
if (isParentOfSomeType(path, ["AttrNode"])) { |
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 conditionnal will match <htmlElement attribute="textNode">
's TextNode but not <htmlElement attribute="textNodeInConcatStatement {{mustache}}">
's.
I would suggest to use instead:
if (isParentOfSomeType(path, ["AttrNode"])) { | |
if (path.stack.includes("attributes")) { |
to match both.
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 you apply this suggestion, you'll notice that you can return return concat([trimmedValue]);
from line 234 and get rid of the big else
statement.
Doing that, we'd split the TextNode printer in two: one for TextNode
s nested in attributes, one for other TextNode
s. We'd be able later to print differently attributes whether they be class
/ style
/ srcset
/ other.
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 conditionnal will match <htmlElement attribute="textNode">'s TextNode but not <htmlElement attribute="textNodeInConcatStatement {{mustache}}">'s.
Correct and that's the whole point — presence of MustacheStatement
makes it ConcatStatement
which is handled properly.
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 is handled correctly in the sense it doesn’t have the bug. But a TextNode in a ConcatStatement should probably be formatted no differently than a simple TextNode (ie. trimmed / not trimmed)?
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.
@dcyriller just tried your suggestion and remembered why I didn't do that. It breaks mustache handling in attributes:
<div
- class='a-first-class
- {{if this.optionOne 'optionOne'}}
-
- {{if this.optionTwo 'optionTwo'}}
-
- {{if this.optionThree 'optionThree'}}
-
- {{if this.optionFour 'optionFour'}}
-
- {{if this.optionFive 'optionFive'}}
-
- {{this.class}}'
+ class='a-first-class {{if this.optionOne 'optionOne'}} {{
+ if this.optionTwo 'optionTwo'
+ }} {{if this.optionThree 'optionThree'}} {{
+ if this.optionFour 'optionFour'
+ }} {{if this.optionFive 'optionFive'}} {{this.class}}'
...attributes
>
</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.
This ☝️ would actually be an improvement - if applied to only class names.
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.
Yeah, this is something I wanted to discuss with you too. In #6207 they ask to format classes with newlines (but not extra newlines) whereas I feel like ☝️ option is not bad. We could consider that ticket an improvement or bring it up for more discussion.
@fisker handlebars printer for attributes is not yet splitted: we could rewrite whitespaces in |
@dcyriller I'm not familiar with handlebars, html didn't trim attribute, I think we should not do trim in handlebars either? And yes, html format |
@fisker @dcyriller Ah, I missed the fact that Prettier treats attribute values differently depending on an attribute. I initially skipped trimming entirely but then noticed a failing glimmer test that checked for Looking at something like this: <input
class="
class"
style="
foo:bar"
srcset="
srcset"
title="
title"
alt="
alt"
unspecified="
unspecified"
/> I see that "html" printer only trims <input
class="class"
style="foo: bar;"
srcset="
srcset"
title="
title"
alt="
alt"
unspecified="
unspecified"
/>
<input
class="
class"
style="
foo:bar"
srcset="
srcset"
title="
title"
alt="
alt"
unspecified="
unspecified"
/>; I can skip trimming for now entirely, so that we get consistent behavior and fix this bug, then work on splitting printer behavior depending on an attribute? |
srcset has own parser Prettier 2.0.5 --parser html Input: <img
class="
class"
style="
foo:bar"
srcset="
srcset------------------------------------------------------------ 1x,
srcset_2 2x"
title="
title"
alt="
alt"
unspecified="
unspecified"
/> Output: <img
class="class"
style="foo: bar;"
srcset="
srcset------------------------------------------------------------ 1x,
srcset_2 2x
"
title="
title"
alt="
alt"
unspecified="
unspecified"
/> |
We can look at |
@dcyriller would you like me to wait until you merge your PR and then we rebase this one on top? or should we merge this as is and then follow up with yours? |
.replace(/^\s+/g, leadingSpace) | ||
.replace(/\s+$/, trailingSpace); | ||
|
||
// Glimmer parser treats attribute values with mustaches differently |
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 comment might removed - it doesn't explain how prettier printer works (but the undelying ast).
@@ -406,7 +406,6 @@ sometimes{{nogaps}}areimportant<Hello></Hello> | |||
<div class="a list of classes"> | |||
|
|||
</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.
This change might be reverted
@fisker what do you think? IMHO if this is merged, I can rebase and add more tests on #8677 (as the bug would be fixed) |
@dcyriller This PR prints trimmed attribute values, it's not okay right? So we can't merge this one. |
The other one - to format only class names - is ready 👍. |
@dcyriller ok, waiting for yours to merge before we go ahead with this one |
@Alonski @dcyriller any idea why the tests are failing on CI? everything passes locally, ran |
@@ -6,7 +6,7 @@ module.exports = function (ast, newNode) { | |||
|
|||
// (Glimmer/HTML) ignore TextNode whitespace | |||
if (ast.type === "TextNode") { | |||
const trimmed = ast.chars.trim(); | |||
const trimmed = ast.chars.trim().replace(/\s+/g, " "); |
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.
Please, only do nessary change, should check attribute name.
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.
@fisker actually I don't quite understand why we need to do this. Could you explain? Why are we "cleaning" AST and when does this happen? Also, why does the test fail now if we only changed Prettier output and not the underlying AST? Checking for attribute==class will involve some duplication from Glimmer's printer which I'd rather avoid. I'm also not sure if this place is performance critical?
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 only runs when comparing the AST during test, so performance is not very important, but make sure the formated / original code have the same AST is very important.
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, why does the test fail now if we only changed Prettier output and not the underlying AST?
You changed the output, it parse to different ASTs.
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 not familiar with glimmer AST , but I checked failed tests on CI , the attribute with TextNode
have "name": "class"
, can we use it ?.
…ettier into glimmer_newlines_in_attributes
Fixes #8648
It appears that
hardline
"primitive" can't be rendered within an attribute in Prettier and results in\n
output as[object Object]
.When working on a fix for this, I found out that Glimmer parser treats attribute values with mustaches differently: they're a
ConcatStatement
rather than a singleTextNode
if the attribute value is a plain string.This PR changes
TextNode
output behavior to only trim it if it's the only node within an attribute (as opposed toConcatStatement
).changelog_unreleased/*/pr-XXXX.md
file followingchangelog_unreleased/TEMPLATE.md
.✨Try the playground for this PR✨