| /** |
| * @license |
| * Copyright 2021 The Chromium Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| import {css, html, LitElement} from 'lit'; |
| import {customElement, property} from 'lit/decorators.js'; |
| import {BinarySizeInfo} from './binary-size'; |
| |
| const MINUS_SIGN = '\u2212'; |
| const EM_DASH = '\u2014'; |
| const LEFT_PARENTHESIS = '\u0028'; |
| const RIGHT_PARENTHESIS = '\u0029'; |
| |
| @customElement('binary-size-table') |
| export class BinarySizeTable extends LitElement { |
| @property() |
| binarySizeInfo: BinarySizeInfo; |
| |
| @property() |
| showAllRows: boolean; |
| |
| static override styles = css` |
| table { |
| border-collapse: collapse; |
| } |
| th { |
| padding: 0.2em 0.4em; |
| text-align: center; |
| } |
| td { |
| white-space: normal; |
| word-break: break-word; |
| padding: 0.2em 0.4em; |
| border-top: 1px solid var(--border-color); |
| } |
| td.size { |
| text-align: right; |
| } |
| td.surplus { |
| color: var(--positive-green-text-color); |
| } |
| td.deficit { |
| color: var(--negative-red-text-color); |
| } |
| a { |
| color: var(--link-color); |
| text-decoration: none; |
| } |
| a:hover { |
| text-decoration: underline; |
| } |
| gr-button { |
| padding: 0.6em 0.4em; |
| } |
| `; |
| |
| override render() { |
| const rows = this.binarySizeInfo?.rows |
| ?.filter( |
| row => |
| row.trySize !== row.ciSize || row.budgetExceeded || this.showAllRows |
| ) |
| .map( |
| row => html` <tr> |
| <td class="size" title="${row.ciSize} B"> |
| <a href="${row.ciUrl}" target="blank" |
| >${humanByteSize(row.ciSize)}</a |
| > |
| </td> |
| <td class="size" title="${row.trySize} B"> |
| <a href="${row.tryUrl}" target="blank" |
| >${humanByteSize(row.trySize)}</a |
| > |
| </td> |
| <td |
| class="${row.creepExceeded ? 'size, deficit' : 'size'}" |
| title="${row.trySize - row.ciSize} B" |
| > |
| ${humanByteSizeDelta(row.ciSize, row.trySize)} |
| </td> |
| <td class="size">${percentSizeDelta(row.ciSize, row.trySize)}</td> |
| ${this.binarySizeInfo?.showCreepBudgets |
| ? html` <td class="size" title="${row.tryCreepBudget} B"> |
| ${humanByteSize(row.tryCreepBudget!)} |
| </td>` |
| : ''} |
| ${this.binarySizeInfo?.showBudgets |
| ? html` <td class="size" title="${row.tryBudget} B"> |
| <a href="${row.ownerUrl}" target="blank" |
| >${humanByteSize(row.tryBudget!)}</a |
| > |
| </td> |
| <td class="size, ${row.budgetExceeded ? 'deficit' : 'surplus'}"> |
| ${humanByteSizeRemainingBudget(row.tryBudget!, row.trySize)} |
| </td>` |
| : ''} |
| <td>${row.binary}</td> |
| <td>${row.builder}</td> |
| </tr>` |
| ); |
| |
| return html` |
| <gr-button @tap=${() => (this.showAllRows = !this.showAllRows)}> |
| Show ${this.showAllRows ? 'Less' : 'All'} |
| </gr-button> |
| <table> |
| <tr> |
| <th>Size before</th> |
| <th>Size after</th> |
| <th colspan="2">Size delta</th> |
| ${ |
| this.binarySizeInfo?.showCreepBudgets |
| ? html`<th>Creep budget</th>` |
| : '' |
| } |
| ${ |
| this.binarySizeInfo?.showBudgets |
| ? html`<th colspan="2">Budget info</th>` |
| : '' |
| } |
| <th>File</th> |
| <th>Builder</td> |
| </tr> |
| ${rows} |
| </table> |
| `; |
| } |
| |
| constructor(binarySizeInfo: BinarySizeInfo) { |
| super(); |
| this.binarySizeInfo = binarySizeInfo; |
| this.showAllRows = false; |
| } |
| } |
| |
| /** |
| * Convert a positive number of bytes to a human-readable string. |
| */ |
| export function humanByteSize(bytes: number): string { |
| const units = ['B', 'KiB', 'MiB', 'GiB']; |
| const decPoints = [0, 2, 3, 4]; |
| let unitIndex = 0; |
| while (Math.abs(bytes) >= 2048 && unitIndex < units.length - 1) { |
| bytes /= 1024; |
| unitIndex += 1; |
| } |
| return `${bytes.toFixed(decPoints[unitIndex])} ${units[unitIndex]}`; |
| } |
| |
| /** |
| * Return a plus for positive numbers, a minus for negative numbers. |
| */ |
| export function signFor(number: number): string { |
| if (number > 0) { |
| return '+'; |
| } else if (number < 0) { |
| return MINUS_SIGN; |
| } else { |
| return ''; |
| } |
| } |
| |
| /** |
| * Convert a difference between two numbers of bytes to a human-readable |
| * string, with plus or minus in front. |
| */ |
| export function humanByteSizeDelta(before: number, after: number): string { |
| const delta = after - before; |
| if (delta === 0) { |
| return EM_DASH; |
| } |
| return signFor(delta) + humanByteSize(Math.abs(delta)); |
| } |
| |
| /** |
| * Convert a difference between two numbers to a percentage with 4 decimal |
| * places, with plus or minus in front. |
| */ |
| export function percentSizeDelta(before: number, after: number): string { |
| const delta = ((after - before) / before) * 100; |
| if (delta === 0) { |
| return EM_DASH; |
| } |
| return signFor(delta) + Math.abs(delta).toFixed(4) + '%'; |
| } |
| |
| /** |
| * Convert a difference between a size and it's corresponding budget (in |
| * bytes) to a human readable string showing the space remaining or the |
| * deficit (in parenthesis). |
| */ |
| export function humanByteSizeRemainingBudget( |
| budget: number, |
| size: number |
| ): string { |
| const delta = budget - size; |
| if (delta === 0) { |
| return EM_DASH; |
| } |
| if (delta > 0) { |
| return humanByteSize(Math.abs(delta)); |
| } else { |
| // deficit denoted by parenthesis - e.g.: (VALUE) |
| return ( |
| LEFT_PARENTHESIS + humanByteSize(Math.abs(delta)) + RIGHT_PARENTHESIS |
| ); |
| } |
| } |