microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
162.27k stars 28.57k forks source link

HTML formatting gone wrong. #204793

Closed rhmnmbr closed 6 months ago

rhmnmbr commented 7 months ago

Type: Bug

Angular HTML formatting breaks when too many nested tag.

VS Code version: Code 1.86.1 (31c37ee8f63491495ac49e43b8544550fbae4533, 2024-02-07T09:08:20.941Z) OS version: Windows_NT x64 10.0.22631 Modes:

System Info |Item|Value| |---|---| |CPUs|11th Gen Intel(R) Core(TM) i5-11400H @ 2.70GHz (12 x 2688)| |GPU Status|2d_canvas: enabled
canvas_oop_rasterization: enabled_on
direct_rendering_display_compositor: disabled_off_ok
gpu_compositing: enabled
multiple_raster_threads: enabled_on
opengl: enabled_on
rasterization: enabled
raw_draw: disabled_off_ok
skia_graphite: disabled_off
video_decode: enabled
video_encode: enabled
vulkan: disabled_off
webgl: enabled
webgl2: enabled
webgpu: enabled| |Load (avg)|undefined| |Memory (System)|15.71GB (0.89GB free)| |Process Argv|D:\\EDMI\\config\\sw0087-eziconfig main --crash-reporter-id d49a9d61-6bc6-44d2-a08c-b999ada21421| |Screen Reader|no| |VM|0%|
Extensions (73) Extension|Author (truncated)|Version ---|---|--- ng-template|Ang|17.1.1 astro-vscode|ast|2.7.1 vscode-log-viewer|ber|0.14.1 vscode-tailwindcss|bra|0.10.5 npm-intellisense|chr|1.4.5 doxdocgen|csc|1.4.0 dbclient-jdbc|cwe|1.3.4 angular-schematics|cyr|6.9.0 dart-code|Dar|3.82.0 flutter|Dar|3.82.0 vscode-eslint|dba|2.4.4 FreeMarker|dco|0.0.9 xml|Dot|2.5.1 apc-extension|drc|0.3.6 gitlens|eam|14.8.0 EditorConfig|Edi|0.16.4 LogFileHighlighter|emi|2.17.0 prettier-vscode|esb|10.1.0 thefoldingstuff|geo|0.2.1 vscode-pull-request-github|Git|0.80.0 go|gol|0.40.3 rest-client|hum|0.25.1 pubspec-assist|jer|2.3.2 angular-essentials|joh|16.0.4 Angular2|joh|16.0.1 vscode-peacock|joh|4.2.2 roslynator|jos|4.10.0 csharpextensions|kre|1.7.3 vscode-dbml|mat|0.3.5 rainbow-csv|mec|3.11.0 fluent-icons|mig|0.0.18 dotenv|mik|1.0.1 theme-monokai-pro-vscode|mon|1.2.2 vscode-docker|ms-|1.28.0 csdevkit|ms-|1.3.10 csharp|ms-|2.15.30 dotnet-interactive-vscode|ms-|1.0.5101020 vscode-dotnet-pack|ms-|1.0.13 vscode-dotnet-runtime|ms-|2.0.1 vscode-dotnet-sdk|ms-|0.8.0 vscodeintellicode-csharp|ms-|0.1.26 debugpy|ms-|2024.0.0 isort|ms-|2023.10.1 python|ms-|2024.0.1 vscode-pylance|ms-|2023.12.1 jupyter|ms-|2024.1.1 jupyter-keymap|ms-|1.1.2 jupyter-renderers|ms-|1.0.17 vscode-jupyter-cell-tags|ms-|0.1.8 vscode-jupyter-slideshow|ms-|0.1.5 remote-containers|ms-|0.338.1 remote-ssh|ms-|0.108.0 remote-ssh-edit|ms-|0.86.0 remote-wsl|ms-|0.86.0 vscode-remote-extensionpack|ms-|0.25.0 cmake-tools|ms-|1.16.32 cpptools|ms-|1.18.5 cpptools-extension-pack|ms-|1.3.0 makefile-tools|ms-|0.8.22 remote-explorer|ms-|0.4.1 remote-server|ms-|1.5.0 vscode-selfhost-test-provider|ms-|0.3.25 vscode-typescript-next|ms-|5.4.20240208 material-icon-theme|PKi|4.33.0 quicktype|qui|12.0.46 synthwave-vscode|Rob|0.1.15 rust-analyzer|rus|0.3.1831 markdown-preview-enhanced|shd|0.8.11 svg-preview|Sim|2.8.3 ayu|tea|1.0.5 cmake|twx|0.0.17 markdown-all-in-one|yzh|3.6.2 material-theme|zhu|3.16.2 (11 theme extensions excluded)
A/B Experiments ``` vsliv368:30146709 vspor879:30202332 vspor708:30202333 vspor363:30204092 vswsl492:30256859 vscoreces:30445986 vscod805cf:30301675 binariesv615:30325510 vsaa593cf:30376535 py29gd2263:30899288 c4g48928:30535728 azure-dev_surveyone:30548225 962ge761:30959799 pythongtdpath:30769146 welcomedialogc:30910334 pythonidxpt:30866567 pythonnoceb:30805159 asynctok:30898717 pythontestfixt:30902429 pythonregdiag2:30936856 pyreplss1:30897532 pythonmypyd1:30879173 pythoncet0:30885854 pythontbext0:30879054 dsvsc016:30899300 dsvsc017:30899301 dsvsc018:30899302 pydisww1:30959800 dsvsc019b:30953937 3ef8e399:30949928 bg6jg535:30958357 ccp1r3:30958155 ```
aeschli commented 7 months ago

Please paste a small code sample..

rhmnmbr commented 7 months ago
<div class="grid grid-nogutter">
  <div class="card p-fluid w-full">

    <p-table #dt [value]="data" dataKey="id" [lazy]="true" (onLazyLoad)="loadData($event)" [paginator]="true"
      [paginatorPosition]="'top'" [rows]="10" [totalRecords]="count" [showCurrentPageReport]="true"
      [currentPageReportTemplate]="data.length > 0 ? 'Menampilkan {first} - {last} dari {totalRecords} data' : ''"
      [expandedRowKeys]="expandedRows">
      <ng-template pTemplate="caption">
        <div class="flex align-items-center justify-content-between">
          <h5>Daftar Pesanan</h5>
          <span class="p-input-icon-left w-auto">
            <i class="pi pi-search"></i>
            <input #fi pInputText type="text" (input)="dt.filterGlobal(fi.value, 'contains')" placeholder="Pencarian"
              size="35" class="w-auto" />
          </span>
        </div>
      </ng-template>
      <ng-template pTemplate="header">
        <tr>
          <th style="width: 0%"></th>
          <th pSortableColumn="code">
            Kode
            <p-sortIcon field="code"></p-sortIcon>
          </th>
          <th class="white-space-nowrap" pSortableColumn="orderDate">
            Tanggal Pesan
            <p-sortIcon field="orderDate"></p-sortIcon>
          </th>
          <th class="white-space-nowrap" pSortableColumn="method">
            Pembayaran
            <p-sortIcon field="method"></p-sortIcon>
          </th>
          <th class="white-space-nowrap" pSortableColumn="totalPrice">
            Total
            <p-sortIcon field="totalPrice"></p-sortIcon>
          </th>
          <th class="white-space-nowrap" pSortableColumn="totalDiscount">
            Diskon
            <p-sortIcon field="totalDiscount"></p-sortIcon>
          </th>
          <th pSortableColumn="statusId">
            Status
            <p-sortIcon field="statusId"></p-sortIcon>
          </th>

          <th alignFrozen="right" pFrozenColumn>
          </th>
        </tr>
      </ng-template>
      <ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex" let-expanded="expanded">
        <tr>
          <td>
            <button type="button" pButton pRipple [pRowToggler]="rowData"
              class="p-button-text p-button-rounded p-button-plain"
              [icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"
              style="width: 1.5rem;height: 1.5rem;"></button>
          </td>
          <td class="white-space-nowrap">{{ rowData.code }}</td>
          <td class="white-space-nowrap">{{ rowData.orderDate }}</td>
          <td class="white-space-nowrap">
            @switch (rowData.method) {
            @case ('transfer') {
            <p-tag icon="pi pi-credit-card" [value]="rowData.methodName" severity="success"></p-tag>
            }
            @case ('cod') {
            <p-tag icon="pi pi-wallet" [value]="rowData.methodName"></p-tag>
            }
            }
          </td>
          <td class="white-space-nowrap">{{ rowData.totalPrice | number }}</td>
          <td class="white-space-nowrap">{{ rowData.totalDiscount | number }}</td>
          <td class="white-space-nowrap">
            @switch (rowData.statusId) {
            @case ('1.placed') {
            <p-tag icon="pi pi-shopping-cart" [value]="rowData.statusName" severity="warning"></p-tag>
            }
            @case ('2.confirmed') {
            <p-tag icon="pi pi-box" [value]="rowData.statusName" severity="primary"></p-tag>
            }
            @case ('3.shipped') {
            <p-tag icon="pi pi-truck" [value]="rowData.statusName" severity="info"></p-tag>
            }
            @case ('4.finished') {
            <p-tag icon="pi pi-verified" [value]="rowData.statusName" severity="success"></p-tag>
            }
            @case ('5.canceled') {
            <p-tag icon="pi pi-ban" [value]="rowData.statusName" severity="danger"></p-tag>
            }
            @case ('6.expired') {
            <p-tag icon="pi pi-ban" [value]="rowData.statusName" severity="danger"></p-tag>
            }
            }
          </td>

          <td class="white-space-nowrap text-center" style="width: 0%;" alignFrozen="right" pFrozenColumn>
            <div class="flex justify-content-evenly">
              <button pButton pRipple type="button" icon="pi pi-box" pTooltip="Proses" tooltipPosition="left"
                class="p-button-rounded p-button-primary p-button-text pt-0 pb-0"
                style="width: 1.5rem;height: 1.5rem;"></button>
              <button pButton pRipple type="button" icon="pi pi-truck" pTooltip="Kirim" tooltipPosition="left"
                class="p-button-rounded p-button-info p-button-text pt-0 pb-0"
                style="width: 1.5rem;height: 1.5rem;"></button>
              <button pButton pRipple type="button" icon="pi pi-verified" pTooltip="Selesai" tooltipPosition="left"
                class="p-button-rounded p-button-success p-button-text pt-0 pb-0"
                style="width: 1.5rem;height: 1.5rem;"></button>
              <button pButton pRipple type="button" icon="pi pi-ban" pTooltip="Batal" tooltipPosition="left"
                class="p-button-rounded p-button-danger p-button-text pt-0 pb-0"
                style="width: 1.5rem;height: 1.5rem;"></button>
            </div>
          </td>
        </tr>
      </ng-template>
      <ng-template pTemplate="rowexpansion" let-rowData>
        <tr>
          <td colspan="8">
            <p-table [value]="rowData.products">
              <ng-template pTemplate="header">
        <tr>
          <th>Code</th>
          <th>Name</th>
          <th>Category</th>
          <th>Quantity</th>
        </tr>
      </ng-template>
      <ng-template pTemplate="body" let-product>
        <tr>
          <td>{{ product.code }}</td>
          <td>{{ product.name }}</td>
          <td>{{ product.category }}</td>
          <td>{{ product.quantity }}</td>
        </tr>
      </ng-template>
    </p-table>
    </td>
    </tr>
    </ng-template>
    <ng-template pTemplate="emptymessage">
      <tr>
        <td [attr.colspan]="8">
          Data tidak ditemukan
        </td>
      </tr>
    </ng-template>
    </p-table>

  </div>
</div>
aeschli commented 7 months ago

This is what I get when formatting with the built-in HTML formatter:

<div class="grid grid-nogutter">
    <div class="card p-fluid w-full">

        <p-table #dt [value]="data" dataKey="id" [lazy]="true" (onLazyLoad)="loadData($event)" [paginator]="true"
            [paginatorPosition]="'top'" [rows]="10" [totalRecords]="count" [showCurrentPageReport]="true"
            [currentPageReportTemplate]="data.length > 0 ? 'Menampilkan {first} - {last} dari {totalRecords} data' : ''"
            [expandedRowKeys]="expandedRows">
            <ng-template pTemplate="caption">
                <div class="flex align-items-center justify-content-between">
                    <h5>Daftar Pesanan</h5>
                    <span class="p-input-icon-left w-auto">
                        <i class="pi pi-search"></i>
                        <input #fi pInputText type="text" (input)="dt.filterGlobal(fi.value, 'contains')"
                            placeholder="Pencarian" size="35" class="w-auto" />
                    </span>
                </div>
            </ng-template>
            <ng-template pTemplate="header">
                <tr>
                    <th style="width: 0%"></th>
                    <th pSortableColumn="code">
                        Kode
                        <p-sortIcon field="code"></p-sortIcon>
                    </th>
                    <th class="white-space-nowrap" pSortableColumn="orderDate">
                        Tanggal Pesan
                        <p-sortIcon field="orderDate"></p-sortIcon>
                    </th>
                    <th class="white-space-nowrap" pSortableColumn="method">
                        Pembayaran
                        <p-sortIcon field="method"></p-sortIcon>
                    </th>
                    <th class="white-space-nowrap" pSortableColumn="totalPrice">
                        Total
                        <p-sortIcon field="totalPrice"></p-sortIcon>
                    </th>
                    <th class="white-space-nowrap" pSortableColumn="totalDiscount">
                        Diskon
                        <p-sortIcon field="totalDiscount"></p-sortIcon>
                    </th>
                    <th pSortableColumn="statusId">
                        Status
                        <p-sortIcon field="statusId"></p-sortIcon>
                    </th>

                    <th alignFrozen="right" pFrozenColumn>
                    </th>
                </tr>
            </ng-template>
            <ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex" let-expanded="expanded">
                <tr>
                    <td>
                        <button type="button" pButton pRipple [pRowToggler]="rowData"
                            class="p-button-text p-button-rounded p-button-plain"
                            [icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"
                            style="width: 1.5rem;height: 1.5rem;"></button>
                    </td>
                    <td class="white-space-nowrap">{{ rowData.code }}</td>
                    <td class="white-space-nowrap">{{ rowData.orderDate }}</td>
                    <td class="white-space-nowrap">
                        @switch (rowData.method) {
                        @case ('transfer') {
                        <p-tag icon="pi pi-credit-card" [value]="rowData.methodName" severity="success"></p-tag>
                        }
                        @case ('cod') {
                        <p-tag icon="pi pi-wallet" [value]="rowData.methodName"></p-tag>
                        }
                        }
                    </td>
                    <td class="white-space-nowrap">{{ rowData.totalPrice | number }}</td>
                    <td class="white-space-nowrap">{{ rowData.totalDiscount | number }}</td>
                    <td class="white-space-nowrap">
                        @switch (rowData.statusId) {
                        @case ('1.placed') {
                        <p-tag icon="pi pi-shopping-cart" [value]="rowData.statusName" severity="warning"></p-tag>
                        }
                        @case ('2.confirmed') {
                        <p-tag icon="pi pi-box" [value]="rowData.statusName" severity="primary"></p-tag>
                        }
                        @case ('3.shipped') {
                        <p-tag icon="pi pi-truck" [value]="rowData.statusName" severity="info"></p-tag>
                        }
                        @case ('4.finished') {
                        <p-tag icon="pi pi-verified" [value]="rowData.statusName" severity="success"></p-tag>
                        }
                        @case ('5.canceled') {
                        <p-tag icon="pi pi-ban" [value]="rowData.statusName" severity="danger"></p-tag>
                        }
                        @case ('6.expired') {
                        <p-tag icon="pi pi-ban" [value]="rowData.statusName" severity="danger"></p-tag>
                        }
                        }
                    </td>

                    <td class="white-space-nowrap text-center" style="width: 0%;" alignFrozen="right" pFrozenColumn>
                        <div class="flex justify-content-evenly">
                            <button pButton pRipple type="button" icon="pi pi-box" pTooltip="Proses"
                                tooltipPosition="left" class="p-button-rounded p-button-primary p-button-text pt-0 pb-0"
                                style="width: 1.5rem;height: 1.5rem;"></button>
                            <button pButton pRipple type="button" icon="pi pi-truck" pTooltip="Kirim"
                                tooltipPosition="left" class="p-button-rounded p-button-info p-button-text pt-0 pb-0"
                                style="width: 1.5rem;height: 1.5rem;"></button>
                            <button pButton pRipple type="button" icon="pi pi-verified" pTooltip="Selesai"
                                tooltipPosition="left" class="p-button-rounded p-button-success p-button-text pt-0 pb-0"
                                style="width: 1.5rem;height: 1.5rem;"></button>
                            <button pButton pRipple type="button" icon="pi pi-ban" pTooltip="Batal"
                                tooltipPosition="left" class="p-button-rounded p-button-danger p-button-text pt-0 pb-0"
                                style="width: 1.5rem;height: 1.5rem;"></button>
                        </div>
                    </td>
                </tr>
            </ng-template>
            <ng-template pTemplate="rowexpansion" let-rowData>
                <tr>
                    <td colspan="8">
                        <p-table [value]="rowData.products">
                            <ng-template pTemplate="header">
                <tr>
                    <th>Code</th>
                    <th>Name</th>
                    <th>Category</th>
                    <th>Quantity</th>
                </tr>
            </ng-template>
            <ng-template pTemplate="body" let-product>
                <tr>
                    <td>{{ product.code }}</td>
                    <td>{{ product.name }}</td>
                    <td>{{ product.category }}</td>
                    <td>{{ product.quantity }}</td>
                </tr>
            </ng-template>
        </p-table>
        </td>
        </tr>
        </ng-template>
        <ng-template pTemplate="emptymessage">
            <tr>
                <td [attr.colspan]="8">
                    Data tidak ditemukan
                </td>
            </tr>
        </ng-template>
        </p-table>

    </div>
</div>

What is the bug?

rhmnmbr commented 7 months ago

image

rhmnmbr commented 6 months ago

image

@aeschli Hello, I think the indentation from the image above is not just right.

aeschli commented 6 months ago

We use beautifyjs as the underlying HTML formatter. Would you mind filing this request directly against https://github.com/beautify-web/js-beautify ?