@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/README.md +65 -44
- package/package.json +2 -2
- package/src/css.js +2 -2
- package/src/locales.js +0 -6
- package/src/page/app.css +7 -29
- package/src/page/app.js +29 -57
- package/src/page/build.js +6 -9
- package/src/page/table.js +221 -294
- package/src/table.css +89 -57
- package/src/page/work.js +0 -55
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ shows.
|
|
|
10
10
|
|
|
11
11
|
## Status
|
|
12
12
|
|
|
13
|
-
**Release 2.
|
|
13
|
+
**Release 2.8.0 (2026-09-18).** The tool lives as a package of its own: the registry name is
|
|
14
14
|
`@vernikr/size-report` (published by tag from CI, with no secret). A project may keep no settings at
|
|
15
15
|
all: without a config file the tool derives them from the project itself and says so in one line,
|
|
16
16
|
and `--init` pins what was derived into a file. The report is **one file**, the self-contained page
|
|
@@ -19,6 +19,26 @@ is installed and on the first run. The version is in the manifest, and every rel
|
|
|
19
19
|
the journal — `worklog/` for today's entries, `worklog/archive/WORKLOG.md` for the earlier ones:
|
|
20
20
|
what changes in the numbers is measured rather than retold.
|
|
21
21
|
|
|
22
|
+
2.8.0 is about what the report costs whoever opens it, and its figures are measured rather than retold.
|
|
23
|
+
**The table is a window of itself:** every row and every column in sight is built, plus four beyond each edge so that
|
|
24
|
+
the edge of the window is never seen empty, while the rest of the table exists as the extent of the scrolled box and
|
|
25
|
+
nothing else. This repository's own report was a `<table>` of 238 500 cells — 253 770 nodes in the document, 377 396 in
|
|
26
|
+
the browser, 1.46 GB of a fresh Chrome's memory with the page open and nothing else — and the window of it is
|
|
27
|
+
**2 460 nodes, 7 320 and 0.15 GB**: a hundredth of the nodes and a tenth of the memory. Scrolling the whole table cost
|
|
28
|
+
**1.1 s of task time over 251 steps**, against **36 s over 60 steps** for the same page as a full table (a median of
|
|
29
|
+
571 ms a frame, which is the freeze a reader felt). **Every column is 70px wide and fixed** — the numbers are short and
|
|
30
|
+
of one kind, and a width that came out of the text is a measurement of every cell of the column — while a file's name
|
|
31
|
+
that does not fit its group is cut with an ellipsis rather than wrapped (the whole name stands in the tooltip). **The
|
|
32
|
+
stripe over a drawing is gone with the freeze it was drawn for**: a switch costs a few milliseconds, so there is nothing
|
|
33
|
+
for an indicator to indicate, and `src/page/work.js` left the tree with it. A virtualizer library was measured and not
|
|
34
|
+
taken — `@tanstack/virtual-core` is ~6.7 kB gzip and headless, `virtua`'s grid is experimental and `Clusterize.js`
|
|
35
|
+
knows rows and not columns — because each would be vendored into the artifact, which the report then measures as its own
|
|
36
|
+
bytes. **The checks of the old table are deactivated while it is rebuilt:** `test/page-view.test.js`, `page-cols`,
|
|
37
|
+
`page-tree` and `page-choice` skip every check with its reason at the top of the file, and this document names them
|
|
38
|
+
where they are the promise-holders of what they described; `test/page-grid.test.js` is what guards the window meanwhile.
|
|
39
|
+
The figures and the reasoning stand in `worklog/0208-table-window.md`. The checks grow with the work: 81 → **88** in the
|
|
40
|
+
fast profile and 186 → **193** in the full one.
|
|
41
|
+
|
|
22
42
|
2.7.0 is about the page and what a reader does with it, and its figures are measured rather than retold.
|
|
23
43
|
**The report's address stays clean:** a switch writes the record into the browser's memory and nothing into the
|
|
24
44
|
address bar — the page no longer puts a `#size-report=…` tail on the report it was opened with — while a link
|
|
@@ -217,8 +237,8 @@ commits and installs hooks; the reason for each expensive file is named line by
|
|
|
217
237
|
|
|
218
238
|
| Run | Command | Checks |
|
|
219
239
|
|---|---|---|
|
|
220
|
-
| Fast — every edit | `pnpm test` | **
|
|
221
|
-
| Full — release and CI | `pnpm test:all` | **
|
|
240
|
+
| Fast — every edit | `pnpm test` | **88 of 193** |
|
|
241
|
+
| Full — release and CI | `pnpm test:all` | **193** |
|
|
222
242
|
|
|
223
243
|
No check is lost or weakened: the full run starts all 186 with the same files, the fast one takes part
|
|
224
244
|
of them. The default is the full run — a file becomes fast only explicitly and with a reason — so new
|
|
@@ -336,35 +356,36 @@ row hides it, so a click on the sign changes exactly the three things the reader
|
|
|
336
356
|
sign and the note in the memory. What guards this is that after folding the table is the same markup
|
|
337
357
|
rather than a rebuilt one (`test/page-tree.test.js`).
|
|
338
358
|
|
|
339
|
-
**
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
**A click
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
`
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
359
|
+
**The table is a window of itself, and the window is what a scroll moves.** A row stands at its own `top` inside the
|
|
360
|
+
scrolled content and a column at its own `left`, so scrolling costs the browser nothing but painting — no layout of the
|
|
361
|
+
table to redo and no script to run — while the page works only when the window has really moved, and then only on what
|
|
362
|
+
left it and what entered it. The header sticks to the top of the shell and the commit column to its left, so the commit a
|
|
363
|
+
number belongs to and the file it stands under are always in sight. The price of a table is what this step removed:
|
|
364
|
+
238 500 cells were 253 770 nodes in the document and 377 396 in the browser, **1.46 GB** of a fresh Chrome's memory at
|
|
365
|
+
rest, and any change of a column's visibility meant the browser laying the whole of it out again — 234.5 ms of layout for
|
|
366
|
+
a *single* cell of this repository's report, 539 ms for 6 000 (`probes/step-12-columns.mjs`). A window of the same
|
|
367
|
+
table is **2 460 nodes and 0.15 GB**, a hundredth of the nodes and a tenth of the memory, and the whole-table scroll
|
|
368
|
+
pass that took 36 s of task time over 60 steps takes **1.1 s over 251** (`worklog/0208-table-window.md`). **The columns
|
|
369
|
+
are one width and fixed, 70px each**: the numbers are short and of one kind, and a width that came out of the text is a
|
|
370
|
+
measurement of every cell of the column — the very cost this step removed. A file's name over its group is cut with an
|
|
371
|
+
ellipsis rather than wrapped (the header is one line high and the whole name stands in the tooltip). The geometry is
|
|
372
|
+
three figures — a column, a row, the header — written in the styling and in the script that counts the window's ordinals
|
|
373
|
+
in them, and `test/page-grid.test.js` reads both and holds them together.
|
|
374
|
+
|
|
375
|
+
**A click builds the window again, and that is cheap now.** A file switched off is simply not among the columns that
|
|
376
|
+
are built, and a metric switched off not among the metrics: there is nothing to hide and nothing to carry, and the
|
|
377
|
+
window is built from the choice as it is — a few hundred cells, 1–5 ms on this repository's report against the ~1 s the
|
|
378
|
+
same click cost as a table. The totals are the sum over the files that are on, counted by the shared `rowModel` for the
|
|
379
|
+
rows the window holds (`src/derived.js`), rather than kept in a running cache that a second road would have to agree
|
|
380
|
+
with. **There is no stripe over the page any longer, and that is a measurement rather than an omission:** it stood over
|
|
381
|
+
the browser's relayout of the whole table, and work that is over before a frame could paint it has no moment to be
|
|
382
|
+
shown in (`src/page/work.js` left the tree with the freeze it was drawn for). **Nothing of it is a library**, and that
|
|
383
|
+
was measured too: a virtualizer of both axes is not a solved problem for a page like this one —
|
|
384
|
+
`@tanstack/virtual-core` is ~6.7 kB gzip and headless (the rows and the columns are two virtualizers, and every node
|
|
385
|
+
is still yours to write), `virtua` calls its grid `experimental_VGrid` and has no sticky pieces, `Clusterize.js`
|
|
386
|
+
virtualizes rows out of a string of all of them and knows nothing of columns — and each would have to be vendored into
|
|
387
|
+
the artifact, whose bytes this very tool measures. What is left to write after any of them is what the chapter is: the
|
|
388
|
+
window, the cells, the header and the pinned column.
|
|
368
389
|
|
|
369
390
|
**The columns the last commit touched come first.** The report is rebuilt after every commit, and a
|
|
370
391
|
reader's first question is what that edit brought. The mark comes from the history rather than from the
|
|
@@ -374,7 +395,7 @@ the report itself, which the hook commits, is skipped, or the mark would depend
|
|
|
374
395
|
commit, the same run would give different bytes and the hook would commit the report a second time.
|
|
375
396
|
Inside each part the order stays as it comes from the settings (the sort is stable): the order of the
|
|
376
397
|
columns is what the reader is used to, and his choice of files does not rearrange it
|
|
377
|
-
(`test/page-
|
|
398
|
+
(`test/page-grid.test.js`, the contract's `last` field).
|
|
378
399
|
|
|
379
400
|
**On a wide window the panel stands to the left of the table and takes no room from the numbers** (from
|
|
380
401
|
900px, `src/page/app.css`). That is not decoration: a desktop has much side room and little vertical
|
|
@@ -557,15 +578,14 @@ acceptance for each.
|
|
|
557
578
|
| `src/size-table.js` | The package's entry point: a re-export of the public API (55 names) and no calculation of its own |
|
|
558
579
|
| `src/derived.js` | The report's shared calculation: totals, deltas, a cell, a commit's caption — one for the engine and the page's program |
|
|
559
580
|
| `src/css.js` | Reading the styling from disk: which sets of styles exist and what role each has |
|
|
560
|
-
| `src/table.css` | The report's table: the geometry of
|
|
581
|
+
| `src/table.css` | The report's table: the geometry of the window — one width per column, one height per row, the header — the sticky header and commit column, a file's caption cut with an ellipsis, the colour of deltas |
|
|
561
582
|
| `src/page/app.css` | The page's styling on top of the shared part: the panel with the file tree and its sticky row of categories (a column on the left on a wide screen, the page fitting the window), the empty states, a narrow window |
|
|
562
583
|
| `src/page/payload.js` | The page's block in sparse form, and the one place that unrolls it back: the history as changes (a file's appearance, its moves, its disappearance) turned into the snapshots the calculation and the table already speak — a value that did not move is one object shared by the rows that hold it |
|
|
563
584
|
| `src/page/state.js` | The page's state: the report's data (the block unrolled by the payload chapter), the view of the checkboxes, the pointer "which path is which column", the unfolded folders, the record's passport, the browser's memory and the link that is read out of the address — a chapter of the page's program |
|
|
564
585
|
| `src/page/dom.js` | The page's nodes: the small helpers of markup (`appEl`, `appBox`) — one set for the panel and the table alike |
|
|
565
586
|
| `src/page/panel.js` | The panel of choices: the switches of metrics and files, the categories, the tree of the project's paths (files outside the report keep a checkbox off with a reason and stand after the rest, and a hidden name after every visible one; the tree opens folded and folders carry a sign that hides the subtree by a class rather than by a rebuild); built once, with the fields of the switches and of the folders and categories written where they stand |
|
|
566
|
-
| `src/page/table.js` | The page's table
|
|
567
|
-
| `src/page/
|
|
568
|
-
| `src/page/app.js` | Assembling and starting the page: the first drawing, then a switch that counts the numbers on the click, hands the columns to the queue and writes the fields it reached without making a node; an anchor change; pasted into the assembled page |
|
|
587
|
+
| `src/page/table.js` | The page's table as a window: the rows and the columns the reader can see (plus four beyond each edge), a cell, a commit's caption, the header, the empty states and the two figures of the window — markup over the shared calculation, with the totals counted per row from the choice, the geometry in pixels that the styling mirrors, and the reason a library was not taken |
|
|
588
|
+
| `src/page/app.js` | Assembling and starting the page: the first drawing, then a switch that builds the window again and writes the fields it reached without making a node of the panel; an anchor change; pasted into the assembled page |
|
|
569
589
|
| `src/page/build.js` | Assembling the page: data, styling and program in one file with no external references — the pasted text is **squeezed** on the way in (comments and indentation out, the same stripping the `min` metric counts) while the sources keep them, and the result is guarded by the stripper's own `assertCompilable` |
|
|
570
590
|
| `src/git.js` | The only border where git is called: the pinned settings, blobs by the batch, the history, the comparison with the working tree |
|
|
571
591
|
| `src/strip.js` | Removing ballast: which form goes to which file (extension, strategy) and which strategies are minification itself — the entry to the parsing of forms |
|
|
@@ -597,7 +617,7 @@ acceptance for each.
|
|
|
597
617
|
| `test/api.test.js` | The package's public API: the list of names is frozen, and splitting the engine may not change it |
|
|
598
618
|
| `eslint.config.js` | The rules of formatting: the same as the consumer project's, plus a ban on gluing operators into one line (`pnpm run lint`, `pnpm run lint:strict`) |
|
|
599
619
|
| `tools/harness.js` | The harness of the checks: paths, clones of the fixture (including one shared per suite and one with CRLF), running the tool, reading refusals, hashes |
|
|
600
|
-
| `tools/page-harness.js` | The harness of the contract and page checks: the contract data, the assembled page, reading it in a real DOM, the panel's switches, the page's calculation and its decoder evaluated from their sources, the block unpacked, and the platform's unpacker put into jsdom (which has none) — one for
|
|
620
|
+
| `tools/page-harness.js` | The harness of the contract and page checks: the contract data, the assembled page, reading it in a real DOM, the panel's switches, the page's calculation and its decoder evaluated from their sources, the block unpacked, and the platform's unpacker put into jsdom (which has none) — one for seven suites |
|
|
601
621
|
| `tools/suites.js` | The split of the suite: which files go into the fast run (with a reason for each) and why every dear one is in the full run |
|
|
602
622
|
| `tools/run-tests.js` | Running the suite (`pnpm test`, `pnpm test:all`, `pnpm run suites:measure`): each file's duration measured on its own, and the counts of checks adding up |
|
|
603
623
|
| `tools/docs-facts.js` | Reading facts out of the documentation — one layer for the four checks of the documentation guard: what a document names (paths, calls, section addresses) against what the repository holds |
|
|
@@ -613,10 +633,11 @@ acceptance for each.
|
|
|
613
633
|
| `test/refusals-catalog.test.js` | The guard of the refusal catalogue: every refusal site in the sources has an entry, every entry declares its advice, and refusals handed to another check are really accepted by it (the named file and line are checked) |
|
|
614
634
|
| `test/contract-data.test.js` | The data contract: the numbers against the reference, the set of fields against the derived quantities, the metric's method against the way the numbers were counted — and the round trip through the page's sparse block, which restores the contract whole and twice over the same bytes |
|
|
615
635
|
| `test/contract-derived.test.js` | The derived quantities against the artifact's numbers: a row's totals, a cell's delta and the delta of a total — on the code that lies in the tree |
|
|
616
|
-
| `test/page-
|
|
617
|
-
| `test/page-
|
|
618
|
-
| `test/page-
|
|
619
|
-
| `test/page-
|
|
636
|
+
| `test/page-grid.test.js` | The grid of the page as a window: what the reader sees is built and no more, the geometry of the styling against the script's, the rows and the columns that a scroll builds and drops, a number under its own caption, a file and a metric switched off, and every row of the window against the engine's own calculation |
|
|
637
|
+
| `test/page-view.test.js` | The assembled page: pasted with no copy of the calculation, self-contained, the empty states, the styling, the switches, a click that makes no table and the carried totals against the engine's own sums — **deactivated** while the table is rebuilt, every check skipped with its reason in the file |
|
|
638
|
+
| `test/page-tree.test.js` | The panel's file tree: folders by the project's paths, three states, the subtree, files and folders outside the report (a checkbox off, a place after the rest), the hidden names at the end of a level, the tree that opens folded and the unfolding the memory keeps, folding without a rebuild and a scroll a click does not touch — **deactivated** with the table, the checks skipped with their reason |
|
|
639
|
+
| `test/page-choice.test.js` | The reader's choice and the work a click starts: the memory and a revisit, someone else's report, a foreign and a broken record, an address that stays clean, a link read at opening and on an open page, and the drawing of a long switch in a task of its own behind the stripe — **deactivated**: the choice and the link are the same, while the counts and the stripe are not |
|
|
640
|
+
| `test/page-cols.test.js` | The fixed layout the page carries: a column's width is counted from the model rather than measured in a laid-out cell, the clip keeps a caption inside its column, the sticky header and commit column keep their edges, and the table names its own width — **deactivated** with the table: the columns are one fixed width now |
|
|
620
641
|
| `test/module.test.js` | A module under a `.js` extension: measured without touching the settings; the stripper's guard is alive (proved by mutation) and does not accuse the innocent |
|
|
621
642
|
| `test/guard.test.js` | Parsing a module: it goes through a thread, both paths give one verdict, the fallback works with the thread's file away, and hundreds of parses are cheaper than a launch |
|
|
622
643
|
| `test/runner.test.js` | Reading a process's output: chunks are glued as buffers rather than appended to a string — a multi-byte character at a chunk border does not turn into two replacement characters |
|
|
@@ -696,7 +717,7 @@ The same release can be taken by a reference to the repository — installation
|
|
|
696
717
|
registry, but stays tied to a revision:
|
|
697
718
|
|
|
698
719
|
```bash
|
|
699
|
-
pnpm add -D github:vernikr/size-report#v2.
|
|
720
|
+
pnpm add -D github:vernikr/size-report#v2.8.0
|
|
700
721
|
```
|
|
701
722
|
|
|
702
723
|
With no network (or nothing to fetch from codeload) — the tarball: `pnpm pack` in the package clone, then
|
|
@@ -708,7 +729,7 @@ the branch moves on the installation fails with `Could not resolve <sha> to a co
|
|
|
708
729
|
observation rather than reasoning: the short pin `6530237` installed while `main` stood on it and stopped
|
|
709
730
|
working at the very next commit, while the same sha in full installed. A branch name (`#main`) and a tag
|
|
710
731
|
are both accepted, but a branch is a moving target and a tag is constant: this release stands on the tag
|
|
711
|
-
`v2.
|
|
732
|
+
`v2.8.0`, which is also the one in the example (forty characters work as well, but they have to be copied
|
|
712
733
|
out of the history by eye).
|
|
713
734
|
|
|
714
735
|
The revision in the example is a part of the claim rather than decoration: what is described below is
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vernikr/size-report",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"author": "vernikr",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"report"
|
|
66
66
|
],
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@vernikr/size-report": "2.
|
|
68
|
+
"@vernikr/size-report": "2.7.0",
|
|
69
69
|
"c8": "10",
|
|
70
70
|
"dependency-cruiser": "17",
|
|
71
71
|
"eslint": "^9.18.0",
|
package/src/css.js
CHANGED
|
@@ -7,8 +7,8 @@ import fs from 'node:fs';
|
|
|
7
7
|
*
|
|
8
8
|
* There are two sets, each with a role of its own:
|
|
9
9
|
*
|
|
10
|
-
* 1. `table.css` — the **table**:
|
|
11
|
-
* the colours of the deltas.
|
|
10
|
+
* 1. `table.css` — the **table**: the geometry of the window (a column, a row, the header), the sticky header
|
|
11
|
+
* and commit column, a commit's caption, the colours of the deltas.
|
|
12
12
|
* 2. `page/app.css` — the page's look **on top of the table**: the canvas, the panel of choices, the empty
|
|
13
13
|
* states and the adaptation to a narrow window.
|
|
14
14
|
*
|
package/src/locales.js
CHANGED
|
@@ -53,9 +53,6 @@ export const LOCALES = {
|
|
|
53
53
|
* таблица не сказала бы читателю ничего. */
|
|
54
54
|
unpack: 'Данные отчёта сжаты, а браузер не умеет их распаковать: в нём нет DecompressionStream. '
|
|
55
55
|
+ 'Обновите браузер — таблицу показывать не из чего.',
|
|
56
|
-
/* Полоска вверху страницы: имя для тех, кто читает страницу не глазами, — она показывает,
|
|
57
|
-
* что идёт отрисовка колонок, а не что отчёт завис. */
|
|
58
|
-
working: 'отрисовка колонок',
|
|
59
56
|
note: 'Абсолютные размеры стоят один раз — в строке «{now}». Строк: {rows}: коммиты без '
|
|
60
57
|
+ 'изменения объёма и коммиты, тронувшие только выключенные файлы, строк не получают. '
|
|
61
58
|
+ 'Собрано из истории git: {command}.'
|
|
@@ -116,9 +113,6 @@ export const LOCALES = {
|
|
|
116
113
|
* browser without `DecompressionStream` gets instead of an empty table. */
|
|
117
114
|
unpack: 'The report\u2019s data is compressed and this browser cannot unpack it: there is no '
|
|
118
115
|
+ 'DecompressionStream. Update the browser — there is nothing to build the table from.',
|
|
119
|
-
/* The bar at the top of the page: a name for whoever reads the page without eyes — it shows
|
|
120
|
-
* that the columns are being drawn rather than that the report has hung. */
|
|
121
|
-
working: 'drawing the columns',
|
|
122
116
|
note: 'Absolute sizes appear once — in the “{now}” row. Rows: {rows}: commits that change '
|
|
123
117
|
+ 'no number, and commits touching only the disabled files, get no row. '
|
|
124
118
|
+ 'Collected from git history: {command}.'
|
package/src/page/app.css
CHANGED
|
@@ -116,7 +116,8 @@ h1 { margin: 0 0 3px; font-size: 21px; font-weight: 650; letter-spacing: -.012em
|
|
|
116
116
|
|
|
117
117
|
/* The table has a frame and a scroll of its own: the header and the commit column stick to it (the rules of stickiness
|
|
118
118
|
* live in the shared part) rather than to the page, so scrolling sideways shows whose row it is while scrolling down shows
|
|
119
|
-
* which column it is.
|
|
119
|
+
* which column it is. What stands inside that frame is a window of the grid rather than the whole of it
|
|
120
|
+
* (`src/page/table.js`). */
|
|
120
121
|
.shell {
|
|
121
122
|
overflow: auto;
|
|
122
123
|
max-height: calc(100vh - 300px);
|
|
@@ -127,34 +128,11 @@ h1 { margin: 0 0 3px; font-size: 21px; font-weight: 650; letter-spacing: -.012em
|
|
|
127
128
|
/* Numbers are denser than the page's text: there are more of them, they are shorter, and they are read by their digits. */
|
|
128
129
|
#grid { font-size: 12.5px; }
|
|
129
130
|
|
|
130
|
-
/*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* stripe — a travelling highlight, which is what this state is in the language of progress — and it moves by a transform,
|
|
136
|
-
* so the stripe itself costs the compositor rather than the page. Its colour is the system accent, the one colour the page
|
|
137
|
-
* uses for anything but the numbers, and it carries a role and a name, because a reader without eyes has to be told that
|
|
138
|
-
* work is going on rather than that the report is broken. */
|
|
139
|
-
.bar { position: fixed; top: 0; left: 0; right: 0; z-index: 5; height: 3px; overflow: hidden; }
|
|
140
|
-
.bar[hidden] { display: none; }
|
|
141
|
-
.bar > i {
|
|
142
|
-
display: block;
|
|
143
|
-
width: 30%;
|
|
144
|
-
height: 100%;
|
|
145
|
-
background: AccentColor;
|
|
146
|
-
animation: bar-run 1.1s linear infinite;
|
|
147
|
-
}
|
|
148
|
-
@keyframes bar-run {
|
|
149
|
-
from { transform: translateX(-100%); }
|
|
150
|
-
to { transform: translateX(333%); }
|
|
151
|
-
}
|
|
152
|
-
/* Whoever asked the system for less motion gets a still stripe: the state is what matters, not its travelling. */
|
|
153
|
-
@media (prefers-reduced-motion: reduce) {
|
|
154
|
-
.bar > i { animation: none; width: 100%; }
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/* The message about a link that came in stands above the table, so that it cannot be missed, while it does not push the
|
|
131
|
+
/* There is no stripe of progress over the page any longer, and that is a measurement rather than an omission: it stood
|
|
132
|
+
* over the browser's relayout of the whole table, and the table is built as a window now — a switch costs a few
|
|
133
|
+
* milliseconds (`src/page/table.js`), so an indicator would be a promise the page does not keep.
|
|
134
|
+
*
|
|
135
|
+
* The message about a link that came in stands above the table, so that it cannot be missed, while it does not push the
|
|
158
136
|
* table away: one line in the place of the page. Its colour is the system one (the accent), for the page keeps no colours
|
|
159
137
|
* of its own. */
|
|
160
138
|
.notice {
|
package/src/page/app.js
CHANGED
|
@@ -1,42 +1,23 @@
|
|
|
1
1
|
import { appUnpack } from './payload.js';
|
|
2
2
|
import { appApply, appBoot, appData, appFoldRead, appLinkUse, appNotice, appRead, appUi, appView, appWrite } from './state.js';
|
|
3
|
-
import {
|
|
4
|
-
import { appDraw } from './work.js';
|
|
3
|
+
import { appState, appTable, appWindow } from './table.js';
|
|
5
4
|
import { appPanel, appPanelAll, appPanelState } from './panel.js';
|
|
6
5
|
|
|
7
|
-
/* Assembling the report: the table is
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
/* Assembling the report: the table is a window of the grid (`appWindow` of the table chapter) and nothing is built
|
|
7
|
+
* that the reader cannot see. Two paths and no third, as before: `appPaint` draws the whole view (the first drawing, a
|
|
8
|
+
* record from the browser's memory, a link in the address), while a click on a box does the same work for the choice
|
|
9
|
+
* it made — and the difference between them is only how much of the view moved.
|
|
11
10
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* browser's own relayout of the table, and it is paid once here rather than once per slice). Neither path makes a
|
|
18
|
-
* node.
|
|
11
|
+
* What a click costs now: the window of rows and columns is built again — a few hundred cells, measured at 1–5 ms on
|
|
12
|
+
* this repository's report — instead of a class on every node of a column of a table the browser lays out whole. The
|
|
13
|
+
* stripe that used to stand over a long drawing (`src/page/work.js`) is gone with the reason for it: a switch no
|
|
14
|
+
* longer has anything to wait for, and an indicator over work that is over before it could be painted would be a
|
|
15
|
+
* promise the page does not keep.
|
|
19
16
|
*/
|
|
20
17
|
|
|
21
|
-
// The table's
|
|
18
|
+
// The table's window: made once, at the first drawing.
|
|
22
19
|
let appCache = null;
|
|
23
20
|
|
|
24
|
-
/* One file's column drawn from the view — the state is read when the slice runs rather than kept from the click that
|
|
25
|
-
* queued it, so a click that arrives while the queue is running is drawn by the next slice rather than after it. */
|
|
26
|
-
function appDrawColumn(i) {
|
|
27
|
-
appColumn(appCache, i, appView.files[i] === true);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/* The columns of a switch that have to be drawn, as the units the work chapter weighs (`{i, units}` — the file and the
|
|
31
|
-
* nodes of its column). Only the columns whose nodes are out of step with the view are asked for (`appColumnStale`): a
|
|
32
|
-
* report opened with everything switched on has nothing to draw, and a column that is already right would cost its
|
|
33
|
-
* nodes again. The count is the table's (`appColumnSize`), because the table is the only place that knows how many
|
|
34
|
-
* nodes a column has. */
|
|
35
|
-
function appColumns(indexes) {
|
|
36
|
-
const todo = indexes.filter((i) => appColumnStale(appCache, i));
|
|
37
|
-
appDraw(appDrawColumn, todo.map((i) => ({ i: i, units: appColumnSize(appCache, i) })));
|
|
38
|
-
}
|
|
39
|
-
|
|
40
21
|
/* The note under the table: what a row is and how the report was made. It does not depend on the choice, so it is
|
|
41
22
|
* written once — with the table rather than with every drawing of it. */
|
|
42
23
|
function appNote() {
|
|
@@ -45,68 +26,59 @@ function appNote() {
|
|
|
45
26
|
.replace('{command}', appData.report.fixCommand);
|
|
46
27
|
}
|
|
47
28
|
|
|
48
|
-
/* What the empty states are told: how many metrics and how many files are left. The
|
|
49
|
-
* case
|
|
29
|
+
/* What the empty states are told: how many metrics and how many files are left. The window stands there in either
|
|
30
|
+
* case — the words are about what is shown. */
|
|
50
31
|
export function appCounts() {
|
|
51
32
|
appState(appData.metrics.filter((m) => appView.metrics[m.key] === true).length,
|
|
52
33
|
appView.files.filter((on) => on === true).length);
|
|
53
34
|
}
|
|
54
35
|
|
|
55
|
-
/* The whole view drawn:
|
|
56
|
-
*
|
|
36
|
+
/* The whole view drawn: the window of the grid, the metrics, the empty states and the panel's fields. This is what a
|
|
37
|
+
* link, a record from the memory and the first drawing need. */
|
|
57
38
|
export function appPaint() {
|
|
58
|
-
|
|
59
|
-
appTotalsReset(appCache);
|
|
60
|
-
appMetrics(appCache);
|
|
39
|
+
appWindow(appCache, true);
|
|
61
40
|
appCounts();
|
|
62
41
|
appPanelAll();
|
|
63
42
|
appWrite();
|
|
64
43
|
}
|
|
65
44
|
|
|
66
|
-
/* One file switched by the reader: the view,
|
|
67
|
-
*
|
|
68
|
-
* reader has read it. */
|
|
45
|
+
/* One file switched by the reader: the view, the window (its column is simply not among the columns that are built),
|
|
46
|
+
* the fields it shows in. The message about a link fades here: by this action the reader has read it. */
|
|
69
47
|
export function appSwitch(i, on) {
|
|
70
48
|
if (appView.files[i] === on) return;
|
|
71
49
|
appView.files[i] = on;
|
|
72
|
-
|
|
73
|
-
appTotals(appCache);
|
|
50
|
+
appWindow(appCache, true);
|
|
74
51
|
appCounts();
|
|
75
52
|
appPanelState([i]);
|
|
76
53
|
appWrite();
|
|
77
54
|
appNotice('');
|
|
78
|
-
appColumns([i]);
|
|
79
55
|
}
|
|
80
56
|
|
|
81
|
-
/* A group switched at once — a folder or a category: the same work per file, then the
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* counts them as one piece of work. */
|
|
57
|
+
/* A group switched at once — a folder or a category: the same work per file, then the fields of the files the choice
|
|
58
|
+
* really reached (switching a folder on when a part of it was already on touches only the rest, and a field that did
|
|
59
|
+
* not move is not written). The columns of the whole group leave or enter the window together. */
|
|
85
60
|
export function appSwitchGroup(indexes, on) {
|
|
86
61
|
const touched = indexes.filter((i) => appView.files[i] !== on);
|
|
87
|
-
touched.forEach((i) => {
|
|
88
|
-
|
|
89
|
-
appContribute(appCache, i, on);
|
|
90
|
-
});
|
|
91
|
-
appTotals(appCache);
|
|
62
|
+
touched.forEach((i) => { appView.files[i] = on; });
|
|
63
|
+
appWindow(appCache, true);
|
|
92
64
|
appCounts();
|
|
93
65
|
appPanelState(touched);
|
|
94
66
|
appWrite();
|
|
95
67
|
appNotice('');
|
|
96
|
-
appColumns(touched);
|
|
97
68
|
}
|
|
98
69
|
|
|
99
|
-
/* One metric switched:
|
|
100
|
-
*
|
|
70
|
+
/* One metric switched: the columns of that metric are not among the columns that are built any longer, so this is the
|
|
71
|
+
* same drawing as a file's switch. The metric's own field is the box the reader just clicked. */
|
|
101
72
|
export function appSwitchMetric() {
|
|
102
|
-
|
|
73
|
+
appWindow(appCache, true);
|
|
103
74
|
appCounts();
|
|
104
75
|
appWrite();
|
|
105
76
|
appNotice('');
|
|
106
77
|
}
|
|
107
78
|
|
|
108
79
|
/* The first drawing: the choice is already in the view (the link and the memory are applied above), the panel is
|
|
109
|
-
* built to match it, the
|
|
80
|
+
* built to match it, the window of the grid is built — the columns the choice leaves and the rows the shell shows —
|
|
81
|
+
* and the panel's fields are written from the view. */
|
|
110
82
|
function appFirst() {
|
|
111
83
|
appPanel();
|
|
112
84
|
appCache = appTable(document.getElementById('grid'));
|
package/src/page/build.js
CHANGED
|
@@ -24,8 +24,10 @@ export function esc(s) {
|
|
|
24
24
|
*
|
|
25
25
|
* The chapters follow the page's subjects, and the order of pasting (the list below) is the order of declarations in
|
|
26
26
|
* the assembled program: the calculation first, then the choice's state, the nodes, the panel, the table and the
|
|
27
|
-
* assembling.
|
|
28
|
-
*
|
|
27
|
+
* assembling. A chapter that is gone leaves the page with one subject fewer rather than with a hole: the stripe over
|
|
28
|
+
* a long drawing left with the freeze it was drawn for (`src/page/app.js` says what a switch costs now). The
|
|
29
|
+
* chapters are **slices of one text**: pasting glues them in a row, so the assembled page would stay the same if
|
|
30
|
+
* the chapters became one file again. */
|
|
29
31
|
export function stripModules(src) {
|
|
30
32
|
return src.split('\n')
|
|
31
33
|
.filter((line) => !/^import\s.*;\s*$/.test(line))
|
|
@@ -43,7 +45,7 @@ export function pageSource(file) {
|
|
|
43
45
|
/* The list of chapters lives here rather than in the tests: one copy for the builder and for the guard
|
|
44
46
|
* (`test/page-view.test.js` reads the same program and compares it with the sources). The payload chapter comes
|
|
45
47
|
* first of the page's own: it is what turns the block into the data everything else reads. */
|
|
46
|
-
export const PAGE_PARTS = ['./payload.js', './state.js', './dom.js', './
|
|
48
|
+
export const PAGE_PARTS = ['./payload.js', './state.js', './dom.js', './panel.js', './table.js', './app.js'];
|
|
47
49
|
|
|
48
50
|
/* The form the artifact carries: the same stripping the `min` metric counts (`src/strip.js`) — comments out,
|
|
49
51
|
* indentation and blank lines out — applied to what is pasted, while the sources on disk keep everything: they are
|
|
@@ -255,14 +257,9 @@ export function pageHtml(data, cfg) {
|
|
|
255
257
|
+ squeezedCss(TABLE_CSS) + '\n' + squeezedCss(PAGE_CSS) + '\n</style>\n</head>\n<body>\n'
|
|
256
258
|
+ '<header>\n<h1>' + esc(data.report.heading) + '</h1>\n'
|
|
257
259
|
+ '<p class="sub">' + esc(subText(data, loc.page)) + '</p>\n</header>\n'
|
|
258
|
-
/* The stripe of the drawing stands first in the page and is fixed to the window's top edge rather than laid out
|
|
259
|
-
* with the rest: the page's shape is a grid of five rows (`src/page/app.css`), and a stripe that appeared and
|
|
260
|
-
* disappeared inside it would move the numbers under the reader's eyes every time a switch is drawn. It holds an
|
|
261
|
-
* empty child rather than a share: the length of an indeterminate stripe is the styling's business. */
|
|
262
|
-
+ '<div id="bar" class="bar" role="progressbar" aria-label="' + esc(loc.page.working) + '" hidden><i></i></div>\n'
|
|
263
260
|
+ '<div id="panel" class="panel"></div>\n'
|
|
264
261
|
+ '<p id="notice" class="notice" hidden></p>\n'
|
|
265
|
-
+ '<div id="shell" class="shell"><
|
|
262
|
+
+ '<div id="shell" class="shell"><div id="grid" class="grid"></div></div>\n'
|
|
266
263
|
+ '<p id="state" class="state" hidden></p>\n'
|
|
267
264
|
+ '<p id="note" class="note"></p>\n'
|
|
268
265
|
+ '<script type="application/octet-stream" id="data" data-pack="base64+gzip">'
|