prettier/prettier

Angular control flow should respect `--html-whitespace-sensitivity strict`

开放

#16,577 创建于 2024年8月15日

 (4 条评论) (14 个反应) (0 位负责人)JavaScript (4,987 个派生)batch import
help wantedlang:angular

仓库指标

星标
 (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.

  1. The spacing around @if () {} is significant to rendered content.
  2. 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
>

贡献者指南