@vernikr/size-report 2.7.0 → 2.8.1

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,70 +1,116 @@
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
+ * Everything here hangs off `#grid`, and that is not a habit: this sheet is the package's **shared** part (`src/css.js`)
5
+ * while the page brings a `.panel .row` of its own, and an unscoped rule for the table's rows took that row out of the
6
+ * flow with it (the panel's switches stood on top of one another until the rules were scoped).
7
7
  *
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; }
29
- .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; }
51
- .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. */
56
- .clip { display: flex; align-items: baseline; gap: 6px; width: 100%; }
57
- .when { flex: none; opacity: .7; }
58
- .subj { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; display: block; }
59
- .subj.plain { opacity: .7; }
60
- .sect { flex: none; opacity: .7; font-size: 11px; text-decoration: none; border-bottom: 1px dotted currentColor; }
8
+ * Four figures are the whole geometry a metric column, a row, the header and the commit column and they are written
9
+ * twice, here and in the script that counts the window's ordinals in them. Two copies of a number are two answers waiting
10
+ * to happen, hence `test/page-grid.test.js` reads these four declarations and holds the script to them.
11
+ *
12
+ * One border: 1px of one colour — a row's bottom edge, a group's left edge, the lines of the header. A heavier line or a
13
+ * second colour would promise a hierarchy to be worked out rather than read.
14
+ *
15
+ * One type face for the whole table; numbers line up by their digits thanks to tabular-nums rather than through a
16
+ * monospaced font. Every column is the same width and fixed: the numbers are short and of one kind, and a width that came
17
+ * out of the text would have to be measured over every cell of the column — the very cost this step removed. The header is
18
+ * two lines of one row each — `--head` is exactly two `--row` — and a name too long for its group is cut with an ellipsis
19
+ * rather than wrapped (`appCaption`) or run over its neighbour.
20
+ */
21
+ #grid {
22
+ --col: 70px;
23
+ --row: 25px;
24
+ --head: 50px;
25
+ --commit: 220px;
26
+ --grid-line: rgba(127, 127, 127, .25);
27
+ position: relative;
28
+ font-variant-numeric: tabular-nums;
29
+ }
30
+
31
+ /* The window: the rows stand at their own `top` inside the scrolled content, so scrolling costs the browser nothing but
32
+ * painting no layout and no script while the width of the content gives the scrollbar its length and the script its
33
+ * ordinals. The cells of a row are one grid of fixed tracks (`grid-auto-columns`): a cell cannot change the width of a
34
+ * column, and it cannot push its neighbour. */
35
+ #grid .row { position: absolute; left: 0; width: 100%; height: var(--row); }
36
+ #grid .cells {
37
+ position: absolute;
38
+ top: 0;
39
+ display: grid;
40
+ grid-auto-flow: column;
41
+ grid-auto-columns: var(--col);
42
+ height: var(--row);
43
+ }
44
+ #grid .cells > span, #grid .hgroups > span, #grid .hmetrics > span { box-sizing: border-box; white-space: nowrap; }
45
+ /* Two pixels of padding and a line of twenty: with the border, a cell is one `--row` high — the same for the header's
46
+ * cells as for the numbers, or the header would be a band of another rhythm. */
47
+ #grid .cells > span {
48
+ padding: 2px 4px;
49
+ line-height: 20px;
50
+ border-bottom: 1px solid var(--grid-line);
51
+ }
52
+ #grid .num { text-align: right; }
53
+ /* The left edge of a group — the total, and every file — is carried by the group's first metric. One class instead of
54
+ * the four rules of "which metric is switched on": the window is built out of the files that are on, so which column
55
+ * stands first in a group is the page's own answer rather than something the styling has to work out. */
56
+ #grid .cells > .g, #grid .hmetrics > .g, #grid .hgroups > .gh { border-left: 1px solid var(--grid-line); }
57
+
58
+ /* The header: one row of groups (the total and the files) over one row of metrics, stuck to the top edge of the shell,
59
+ * and the commit column stuck to its left edge. Both carry an opaque background (Canvas), or the numbers would show
60
+ * through them while the reader scrolls. The two lines are placed by `top` and are one row high each, so the header
61
+ * aligns with the table below it rather than standing a size of its own. */
62
+ #grid .head { position: sticky; top: 0; left: 0; z-index: 3; height: var(--head); background: Canvas; }
63
+ #grid .hgroups, #grid .hmetrics { position: absolute; display: grid; grid-auto-flow: column; grid-auto-columns: var(--col); }
64
+ #grid .hgroups { top: 0; height: var(--row); }
65
+ #grid .hmetrics { top: var(--row); height: var(--row); }
66
+ #grid .hgroups > span, #grid .hmetrics > span {
67
+ padding: 2px 4px;
68
+ line-height: 20px;
69
+ border-bottom: 1px solid var(--grid-line);
70
+ }
71
+ /* A file's name stands over its group of metrics and is centred on it: the group is a column of numbers, and a caption
72
+ * that began at its left edge would carry the eye to the wrong place. */
73
+ #grid .hgroups > span { text-align: center; overflow: hidden; text-overflow: ellipsis; }
74
+ #grid .hmetrics > span { text-align: center; color: CanvasText; }
75
+
76
+ /* The commit column: a sticky cell of every row, so the commit a number belongs to is in sight while the reader scrolls
77
+ * sideways. Its width is fixed and is the script's `APP_COMMIT` as well — the numbers are placed from the left edge of
78
+ * the grid *beside* the column, and a caption longer than it is clipped (the whole subject stands in the tooltip). */
79
+ #grid .c-commit {
80
+ position: sticky;
81
+ left: 0;
82
+ z-index: 2;
83
+ box-sizing: border-box;
84
+ width: var(--commit);
85
+ height: var(--row);
86
+ line-height: var(--row);
87
+ padding: 0 4px;
88
+ background: Canvas;
89
+ text-align: left;
90
+ font-weight: 400;
91
+ overflow: hidden;
92
+ text-overflow: ellipsis;
93
+ white-space: nowrap;
94
+ border-bottom: 1px solid var(--grid-line);
95
+ }
96
+ #grid .c-commit a { color: inherit; }
97
+ #grid .head .c-commit { z-index: 6; height: var(--head); line-height: var(--head); }
98
+ /* This block fills the commit column: the cell clips what does not fit, and the subject is what gives way (the flex
99
+ * item of `flex: 1 1 auto`), while the date and the journal mark keep their own width. */
100
+ #grid .clip { display: flex; align-items: baseline; gap: 6px; width: 100%; }
101
+ #grid .when { flex: none; opacity: .7; }
102
+ #grid .subj { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; display: block; }
103
+ #grid .subj.plain { opacity: .7; }
104
+ #grid .sect { flex: none; opacity: .7; font-size: 11px; text-decoration: none; border-bottom: 1px dotted currentColor; }
61
105
  /* Growth green, fall red — by agreement with whoever asked for the report (growth is "more logic" rather than alarm). */
62
- .up { color: #1e8449; }
63
- .down { color: #c0392b; }
64
- .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)); }
106
+ #grid .up { color: #1e8449; }
107
+ #grid .down { color: #c0392b; }
108
+ #grid .miss { opacity: .5; }
109
+ /* The top row holds the current sizes: it is also what explains what the deltas below refer to — by its weight rather
110
+ * than by a heavier line, which would be a second border among the rows. */
111
+ #grid .row.now > .c-commit { font-weight: 600; }
112
+ /* A row's highlight is laid over rather than swapped in: the sticky column has to stay opaque, or numbers show through
113
+ * it while the reader scrolls sideways. */
114
+ #grid .row:hover > .c-commit, #grid .row:hover > .cells > span {
115
+ background-image: linear-gradient(rgba(127, 127, 127, .08), rgba(127, 127, 127, .08));
116
+ }
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
- }