@vernikr/size-report 2.7.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/table.css CHANGED
@@ -1,58 +1,88 @@
1
- /* One type face for the whole table; numbers line up by their digits thanks to tabular-nums rather than through a
2
- * monospaced font.
1
+ /* The report's table: a grid of plain elements rather than a `<table>`, and only the part of it the reader looks at is
2
+ * built (`src/page/table.js` says why, and what was measured).
3
3
  *
4
- * The layout is **fixed**, and the widths come from the `<colgroup>` the page builds along with the table (`appCols`):
5
- * laying this table out as `auto` means measuring every cell of it 174 468 of them here to assign the widths of
6
- * 265 columns.
4
+ * Three figures are the whole geometry a metric column, a row and the header and they are written twice, here and
5
+ * in the script that counts the window's ordinals in them. Two copies of a number are two answers waiting to happen,
6
+ * hence `test/page-grid.test.js` reads these three declarations and holds the script to them. The fourth, the commit
7
+ * column's width, is the styling's alone: the script places the numbers from the left edge of the grid, and the caption
8
+ * is pinned over them.
7
9
  *
8
- * **Both declarations are needed, and the width is the one that is easy to lose.** A fixed layout with `width: auto`
9
- * falls back to the automatic algorithm the specification says so, and Chrome does it: the columns' widths are then
10
- * ignored, the cells are measured all the same, and nothing looks wrong except that nothing is won. `100%` is what
11
- * gives the table a definite width: it is the window, and the columns are wider than it, so the table keeps the widths
12
- * it was given (`check` and the browser probe both watch this). */
13
- table { border-collapse: collapse; font-variant-numeric: tabular-nums; table-layout: fixed; width: 100%; }
14
- /* A counted width is the **border box** of a column — the padding of its cells and the group's border are inside it
15
- * (measured in Chrome: `7ch` gave a 47px content box with 4px of padding each side). `--ch` is that count in
16
- * characters, written by the page per column; `--clip` is the fixed measure a commit's caption is clipped to, and the
17
- * one a narrow window may shorten (app.css). */
18
- #grid { --cell-pad: 4px; --col-line: 1px; --clip: 190px; }
19
- th, td { padding: 2px var(--cell-pad); border-bottom: 1px solid rgba(127, 127, 127, .25); white-space: nowrap; }
20
- /* The count over-measures a sign and a thin space, which is the safe side: a cell clips nothing, so a column a
21
- * character short would show a number running over its neighbour. */
22
- #grid col { width: calc(var(--ch, 0px) + var(--cell-pad) * 2 + var(--col-line)); }
23
- #grid col.c-commit { width: calc(var(--clip) + var(--cell-pad) * 2 + var(--col-line)); }
24
- /* A two-row header: both rows stick, so the second is offset by exactly the first one's height (line-height 20 plus the
25
- * 2px bottom border), or the rows would overlap. */
26
- thead th { position: sticky; top: 0; z-index: 3; background: Canvas; text-align: center; line-height: 20px; padding: 0 var(--cell-pad); }
27
- thead tr:first-child th { border-bottom-width: 2px; }
28
- thead tr:last-child th { top: 22px; }
10
+ * One type face for the whole table; numbers line up by their digits thanks to tabular-nums rather than through a
11
+ * monospaced font. Every column is the same width and fixed: the numbers are short and of one kind, and a width that
12
+ * came out of the text would have to be measured over every cell of the column the very cost this step removed.
13
+ * A file's caption over its group is cut with an ellipsis rather than wrapped (`appCaption`), because the header is one
14
+ * line high and the grid is built of rows of one height.
15
+ */
16
+ #grid {
17
+ --col: 70px;
18
+ --row: 25px;
19
+ --head: 44px;
20
+ --commit: 220px;
21
+ --grid-line: rgba(127, 127, 127, .25);
22
+ --grid-edge: rgba(127, 127, 127, .35);
23
+ position: relative;
24
+ font-variant-numeric: tabular-nums;
25
+ }
26
+
27
+ /* The window: the rows stand at their own `top` inside the scrolled content, so scrolling costs the browser nothing but
28
+ * painting no layout and no script while the width of the content gives the scrollbar its length and the script its
29
+ * ordinals. The cells of a row are one grid of fixed tracks (`grid-auto-columns`): a cell cannot change the width of a
30
+ * column, and it cannot push its neighbour. */
31
+ .row { position: absolute; left: 0; width: 100%; height: var(--row); }
32
+ .cells {
33
+ position: absolute;
34
+ top: 0;
35
+ display: grid;
36
+ grid-auto-flow: column;
37
+ grid-auto-columns: var(--col);
38
+ height: var(--row);
39
+ }
40
+ .cells > span, .hgroups > span, .hmetrics > span { box-sizing: border-box; white-space: nowrap; }
41
+ .cells > span { padding: 2px 4px; line-height: 20px; border-bottom: 1px solid var(--grid-line); }
29
42
  .num { text-align: right; }
30
- /* The group's left border is carried by the first *enabled* metric: four rules instead of the eight combinations of
31
- * "which of them is first", so switching a metric off moves the border by itself and no line of JS knows about it.
32
- * The registry holds four metrics (`raw`, `min`, `tok`, `gzip`) that is the count below, and `test/page-view.test.js`
33
- * reddens if a fifth name appears. A group's heading (`.gh`) spans its metrics rather than belonging to one, so its
34
- * own left edge is there while any metric is on (`.m-none` is set when the reader switched them all off). */
35
- #grid .g { border-left: 0; }
36
- #grid:not(.m-off-0) .g.m0,
37
- #grid.m-off-0:not(.m-off-1) .g.m1,
38
- #grid.m-off-0.m-off-1:not(.m-off-2) .g.m2,
39
- #grid.m-off-0.m-off-1.m-off-2:not(.m-off-3) .g.m3 { border-left: 1px solid rgba(127, 127, 127, .35); }
40
- #grid:not(.m-none) .gh { border-left: 1px solid rgba(127, 127, 127, .35); }
41
- /* A metric switched off hides all of its cells and both of its headings at once — one class on the table instead of a
42
- * pass over the metric's cells (measured: 265 operations against 56 496). */
43
- #grid.m-off-0 .m0, #grid.m-off-1 .m1, #grid.m-off-2 .m2, #grid.m-off-3 .m3 { display: none; }
44
- /* A file's column switched off: its cells and its headings together. The hidden column keeps its place in the markup,
45
- * so the columns that stay do not move. */
46
- #grid .off { display: none; }
47
- /* The sticky left column: an opaque background (Canvas), or numbers would show through the cell when scrolling sideways. A
48
- * tier above the neighbouring cells (2) and below the header (3); the header's corner is above them all, or the column groups
49
- * would crawl over the commit column. */
50
- .c-commit { position: sticky; left: 0; z-index: 2; background: Canvas; text-align: left; font-weight: 400; }
43
+ /* The left edge of a group the total, and every file — is carried by the group's first metric. One class instead of
44
+ * the four rules of "which metric is switched on": the window is built out of the files that are on, so which column
45
+ * stands first in a group is the page's own answer rather than something the styling has to work out. */
46
+ .cells > .g, .hmetrics > .g, .hgroups > .gh { border-left: 1px solid var(--grid-edge); }
47
+
48
+ /* The header: one row of groups (the total and the files) over one row of metrics, stuck to the top edge of the shell,
49
+ * and the commit column stuck to its left edge. Both carry an opaque background (Canvas), or the numbers would show
50
+ * through them while the reader scrolls. */
51
+ .head { position: sticky; top: 0; left: 0; z-index: 3; height: var(--head); background: Canvas; }
52
+ .hgroups, .hmetrics { position: absolute; display: grid; grid-auto-flow: column; grid-auto-columns: var(--col); }
53
+ .hgroups { top: 0; height: 22px; }
54
+ .hmetrics { top: 22px; height: 22px; }
55
+ .hgroups > span, .hmetrics > span { padding: 0 4px; line-height: 20px; border-bottom: 2px solid var(--grid-edge); }
56
+ .hgroups > span { text-align: left; }
57
+ /* A file's name is one line of a fixed room: a name that does not fit is cut with an ellipsis (`appCaption` puts the
58
+ * whole of it into the tooltip) rather than wrapped the grid is rows of one height — or run over its neighbour. */
59
+ .hgroups > span { overflow: hidden; text-overflow: ellipsis; }
60
+ .hmetrics > span { text-align: center; color: CanvasText; }
61
+
62
+ /* The commit column: a sticky cell of every row, so the commit a number belongs to is in sight while the reader
63
+ * scrolls sideways. Its width is fixed, and a caption longer than it is clipped the whole subject stands in the
64
+ * tooltip. */
65
+ .c-commit {
66
+ position: sticky;
67
+ left: 0;
68
+ z-index: 2;
69
+ box-sizing: border-box;
70
+ width: var(--commit);
71
+ height: var(--row);
72
+ line-height: var(--row);
73
+ padding: 0 4px;
74
+ background: Canvas;
75
+ text-align: left;
76
+ font-weight: 400;
77
+ overflow: hidden;
78
+ text-overflow: ellipsis;
79
+ white-space: nowrap;
80
+ border-bottom: 1px solid var(--grid-line);
81
+ }
51
82
  .c-commit a { color: inherit; }
52
- thead .c-commit { z-index: 6; }
53
- /* This block fills the commit column, whose width is set by the column itself (`#grid col.c-commit`). It took the
54
- * column's measure with it: the cell's content would otherwise go past its borders and be drawn over the neighbouring
55
- * numbers, because a table cell clips nothing. */
83
+ .head .c-commit { z-index: 6; height: var(--head); line-height: var(--head); border-bottom-width: 2px; }
84
+ /* This block fills the commit column: the cell clips what does not fit, and the subject is what gives way (the flex
85
+ * item of `flex: 1 1 auto`), while the date and the journal mark keep their own width. */
56
86
  .clip { display: flex; align-items: baseline; gap: 6px; width: 100%; }
57
87
  .when { flex: none; opacity: .7; }
58
88
  .subj { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; display: block; }
@@ -62,9 +92,11 @@ thead .c-commit { z-index: 6; }
62
92
  .up { color: #1e8449; }
63
93
  .down { color: #c0392b; }
64
94
  .miss { opacity: .5; }
65
- /* The top row holds the current sizes: it is also what explains what the deltas refer to. */
66
- tr.now th, tr.now td { border-bottom: 2px solid rgba(127, 127, 127, .35); }
67
- tr.now .c-commit { font-weight: 600; }
68
- /* A row's highlight is laid over rather than swapped in: the sticky column has to stay opaque, or numbers show through it
69
- * when scrolling. */
70
- tbody tr:hover th, tbody tr:hover td { background-image: linear-gradient(rgba(127, 127, 127, .08), rgba(127, 127, 127, .08)); }
95
+ /* The top row holds the current sizes: it is also what explains what the deltas below refer to. */
96
+ .row.now > .c-commit { font-weight: 600; }
97
+ .row.now > .c-commit, .row.now > .cells > span { border-bottom-width: 2px; }
98
+ /* A row's highlight is laid over rather than swapped in: the sticky column has to stay opaque, or numbers show through
99
+ * it while the reader scrolls sideways. */
100
+ .row:hover > .c-commit, .row:hover > .cells > span {
101
+ background-image: linear-gradient(rgba(127, 127, 127, .08), rgba(127, 127, 127, .08));
102
+ }
package/src/page/work.js DELETED
@@ -1,55 +0,0 @@
1
- /* The page's long work, and the stripe that says it is going on.
2
- *
3
- * A switch on a file's box changes a class on every node of that file's column, and a folder or a category is that same
4
- * work over every file below it. That alone is cheap — measured at about 2 µs a node, so a whole category of this
5
- * repository's report (73 columns, 55 042 nodes) is 120 ms of it — but it is not the price. **The browser lays this
6
- * table out again for any change of a column's visibility, and that is close to a second on a table of a few hundred
7
- * thousand cells** (`probes/step-12-columns.mjs`: 1 cell toggled 234 ms of layout, 750 cells 287 ms, 6 000 cells
8
- * 539 ms, and the whole click on the shipped page 867 ms blocked with a 742 ms task).
9
- *
10
- * Hence the shape of this chapter, and it is a decision rather than a default. The drawing of a switch is **one task**:
11
- * what is queued is drawn in a single go, one layout, one repaint. Slicing it — a queue worked off between timeouts —
12
- * was written first and measured (Chrome 153, this repository's report): 37 slices of two columns each paid the table's
13
- * relayout 37 times, 2.5–4 s a slice, 95 frames and 169 layouts of 151.9 s of pure layout time against 1.04 s for the
14
- * same click when it is not sliced, with the tab growing to several gigabytes of repaint. The slice is the thing that
15
- * freezes the page, only more often, so there is none.
16
- *
17
- * What is left is honesty about it: work short enough to be over before the browser could paint a stripe is done on the
18
- * click itself, and above that the stripe appears, the drawing happens in the next task, and the stripe goes away —
19
- * so a reader sees that the page is working rather than wondering whether it hung. The stripe carries no share: within
20
- * one task the browser cannot repaint, so a bar that filled would be a bar that lies, and the page already knows the
21
- * one thing that is true about it (the work is going on).
22
- */
23
-
24
- /* Above this much node work the drawing is one task with a stripe rather than a task on the click: a stripe that
25
- * appears and disappears within the same frame is worse than none, and the figure is one file's column of a report of
26
- * this repository's size (754 nodes). */
27
- export const APP_LONG = 2000;
28
-
29
- /* The stripe: on while a switch is being drawn, off when it is done. There is nothing to count here, and the length is
30
- * carried by the styling (an indeterminate stripe), which is why this function takes a switch rather than a share. */
31
- export function appBar(shown) {
32
- const bar = document.getElementById('bar');
33
- if (bar !== null) bar.hidden = !shown;
34
- }
35
-
36
- /* What a switch asks for: `items` are the columns that have to be drawn (`{i, units}` — the file's index and the nodes
37
- * of its column), `step` draws one of them from the view, and the total decides whether the drawing is the reader's own
38
- * click or the next task with the stripe over it. Only the columns out of step with the view are asked for at all
39
- * (`appColumnStale`), so a report opened with everything switched on has nothing to draw here. */
40
- export function appDraw(step, items) {
41
- /* Counted by a plain walk rather than by `reduce`: the page's shell is held to a rule that it counts no totals of the
42
- * table itself, and a guard that has to tell a sum of nodes from a sum of numbers is a guard that will be argued with
43
- * one day. The count of nodes is not one of the report's numbers. */
44
- let units = 0;
45
- items.forEach((item) => { units += item.units; });
46
- if (units <= APP_LONG) {
47
- items.forEach((item) => step(item.i));
48
- return;
49
- }
50
- appBar(true);
51
- setTimeout(() => {
52
- items.forEach((item) => step(item.i));
53
- appBar(false);
54
- }, 0);
55
- }