Angular control flow should respect `--html-whitespace-sensitivity strict`
#16,577 创建于 2024年8月15日
仓库指标
- 星标
- (52,204 个星标)
- PR 合并指标
- (平均合并 6天) (30 天内合并 186 个 PR)
描述
Prettier 3.2.5 Playground link
--parser angular
--html-whitespace-sensitivity strict
Input:
<span>Foo@if(true) {bar}</span>baz
Importantly, at runtime this renders as "Foobarbaz".
Output:
<span
>Foo
@if (true) {
bar
}</span
>baz
Importantly, at runtime this renders as "Foo bar baz".
This is bad because it changes the rendered output during formatting. Normally I think that is allowed in Prettier given how HTML/Angular whitespace works, however the --html-whitespace-sensitivity strict option is specifically intended to avoid changing runtime rendering behavior. So while this output is probably reasonable for --html-whitespace-sensitivity ignore, I think it is a bug for strict.
Why?
There's two related bugs here.
- The spacing around
@if () {}is significant to rendered content. - The spacing within the
{}is significant to rendered content.
If any of those spaces are present, then the rendered output will display a space. As a result, the presence of any spaces before/after a control flow statement need to be consistent. Since there's two ways to introduce such spacing before a block's content and two ways to introduce a space after, Prettier could choose to move or duplicate a space between 1. and 2. as long as at least one space already existed in the input.
I put together a Stackblitz to visualize how Angular actually renders these cases in practice.
This problem likely also applies for @else, @switch, and @for. I didn't exhaustively check them though.
Expected output:
I think the ideal output is likely to just retain the @if on a single line (keep it identical to the input) if that fits in the line length. If not, we can put newlines around the condition expression and indent that.
<!-- Probably best if it fits in the line length. -->
<div
>Foo@if (true) {bar}</div
>
<!-- Otherwise this might be the best we can do. -->
<div
>Foo@if (
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongCondition
) {bar}</div
>