@vernikr/size-report 2.8.2 → 2.8.3
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 +24 -8
- package/package.json +2 -2
- package/src/page/table.js +102 -45
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ shows.
|
|
|
10
10
|
|
|
11
11
|
## Status
|
|
12
12
|
|
|
13
|
-
**Release 2.8.
|
|
13
|
+
**Release 2.8.3 (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,19 @@ 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.3 is about what a sideways scroll of the report costs, and its figures are measured rather than retold. **A step
|
|
23
|
+
sideways moves the window instead of building it:** a row is made once and lives through the move, keeping its node and
|
|
24
|
+
its numbers — the window's columns are the range of that row's numbers, so the columns that entered it are made and the
|
|
25
|
+
ones that left are dropped, the header's line of names and its line of metrics by the same rule. A switch of the
|
|
26
|
+
reader's own and the shell's resize are the one thing that cannot be a move — a column that is not built cannot be
|
|
27
|
+
shown — and they build the window from nothing as they did. **Measured on this repository's own report in live Chrome**
|
|
28
|
+
(`probes/step-12-window.mjs`, two rounds, 1440 × 900): the page's own handling of one step **10.4 → 0.6 ms** (worst
|
|
29
|
+
19.2 → 3.6) and the layout the step forces **14.4 → 5.9 ms**; over a sweep of forty steps the browser's own accounting
|
|
30
|
+
gives layout **0.605 → 0.246 s**, style recalculation 0.169 → 0.056 s and task time **1.281 → 0.350 s**. The checks go
|
|
31
|
+
86 → **87** in the fast profile and 191 → **192** in the full one: `test/page-grid.test.js` holds the rule by node
|
|
32
|
+
identity — a page that built the same numbers again would read the same — and by the numbers of the window built at
|
|
33
|
+
that place in one leap. The figures and the reasoning stand in `worklog/0211-sideways-step.md`.
|
|
34
|
+
|
|
22
35
|
2.8.2 is about the page's own sources and the checks that guard them, and its figures are measured rather than retold.
|
|
23
36
|
**The four page suites that went quiet with the `<table>` are alive again against the window:** `test/page-view.test.js`,
|
|
24
37
|
`page-cols`, `page-tree` and `page-choice` read the grid and the panel they guard rather than markup that no longer
|
|
@@ -271,8 +284,8 @@ commits and installs hooks; the reason for each expensive file is named line by
|
|
|
271
284
|
|
|
272
285
|
| Run | Command | Checks |
|
|
273
286
|
|---|---|---|
|
|
274
|
-
| Fast — every edit | `pnpm test` | **
|
|
275
|
-
| Full — release and CI | `pnpm test:all` | **
|
|
287
|
+
| Fast — every edit | `pnpm test` | **87 of 192** |
|
|
288
|
+
| Full — release and CI | `pnpm test:all` | **192** |
|
|
276
289
|
|
|
277
290
|
No check is lost or weakened: the full run starts every file, the fast one takes part of them. The default is the full run — a file becomes fast only explicitly and with a reason — so new
|
|
278
291
|
expensive work cannot quietly move into the fast one. Two declarations guard that:
|
|
@@ -407,7 +420,10 @@ right edge of the pinned commit column rather than under it, and every line of t
|
|
|
407
420
|
cell, along a group's left edge — is one pixel of one colour: a heavier line would promise a hierarchy to work out
|
|
408
421
|
rather than read. The geometry is four figures — a column, a row, the header, the pinned column — written in the styling
|
|
409
422
|
and in the script that counts the window's ordinals in them, and `test/page-grid.test.js` reads both and holds them
|
|
410
|
-
together.
|
|
423
|
+
together. **A step sideways moves that window rather than building it:** the rows live through the move and only the
|
|
424
|
+
columns that entered are made, at 10.4 → **0.6 ms** for the page's own handling of the step, 14.4 → **5.9 ms** for the
|
|
425
|
+
layout it forces and 1.281 → **0.350 s** of task time over a sweep of forty steps
|
|
426
|
+
(`probes/step-12-window.mjs`).
|
|
411
427
|
|
|
412
428
|
**A click builds the window again, and that is cheap now.** A file switched off is simply not among the columns that
|
|
413
429
|
are built, and a metric switched off not among the metrics: there is nothing to hide and nothing to carry, and the
|
|
@@ -586,7 +602,7 @@ acceptance for each.
|
|
|
586
602
|
| `tools/parity-freeze.js` | Takes the parity reference (`pnpm run parity`): with the frozen copy, at the project revision from the manifest — `--json`, the config, the artifact's hash, the tool's hash |
|
|
587
603
|
| `tools/make-fixture.js` | Assembles the synthetic fixture (`pnpm run fixture`): a deterministic history with traps plus the reference numbers |
|
|
588
604
|
| `tools/synthetic/` | The subjects of that assembly, one per matter: `repo.js` — how git is spoken to (pinned time, author, settings), `content.js` — what the files hold, `history.js` — which commits come of it, `note.js` — the fixture's note with the list of traps |
|
|
589
|
-
| `probes/` | The scripted measurements behind `plans/2026-09-17-page-perf/`: one file per step, run by hand against live Chrome at the debug port — the fixed layout, where `content-visibility` acts at all,
|
|
605
|
+
| `probes/` | The scripted measurements behind `plans/2026-09-17-page-perf/`: one file per step, run by hand against live Chrome at the debug port — the fixed layout, where `content-visibility` acts at all, the price of a switch and of a step sideways — (`probes/README.md`). Outside the sensors' paths on purpose: they measure the product rather than being part of it, and a suite cannot see layout, paint or a browser's own skipping |
|
|
590
606
|
| `tools/parity-live.js` | Compares the engine with the live project on a clone: the numbers and the self-contained report at the path the consumer's settings give (`pnpm run parity:live`) |
|
|
591
607
|
| `tools/pack-check.js` | Assembles the tarball and checks that everything works from it: all sources arrived, the numbers and the report as from the repository (`pnpm run pack:check`) |
|
|
592
608
|
| `tools/check-standards.js` | Checks that both references reproduce: a re-take goes nowhere and is compared with what is committed (our files byte for byte, the bundle by content), and that the live-history bundle carries `HEAD` (`pnpm run check:standards`) |
|
|
@@ -622,7 +638,7 @@ acceptance for each.
|
|
|
622
638
|
| `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 |
|
|
623
639
|
| `src/page/dom.js` | The page's nodes: the small helpers of markup (`appEl`, `appBox`) — one set for the panel and the table alike |
|
|
624
640
|
| `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 |
|
|
625
|
-
| `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 order of the columns — 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 |
|
|
641
|
+
| `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), moved by a scroll rather than built again (a row lives through a step sideways and only the columns that entered it are made), a cell, a commit's caption, the header, the empty states and the order of the columns — 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 |
|
|
626
642
|
| `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 |
|
|
627
643
|
| `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` |
|
|
628
644
|
| `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 |
|
|
@@ -755,7 +771,7 @@ The same release can be taken by a reference to the repository — installation
|
|
|
755
771
|
registry, but stays tied to a revision:
|
|
756
772
|
|
|
757
773
|
```bash
|
|
758
|
-
pnpm add -D github:vernikr/size-report#v2.8.
|
|
774
|
+
pnpm add -D github:vernikr/size-report#v2.8.3
|
|
759
775
|
```
|
|
760
776
|
|
|
761
777
|
With no network (or nothing to fetch from codeload) — the tarball: `pnpm pack` in the package clone, then
|
|
@@ -767,7 +783,7 @@ the branch moves on the installation fails with `Could not resolve <sha> to a co
|
|
|
767
783
|
observation rather than reasoning: the short pin `6530237` installed while `main` stood on it and stopped
|
|
768
784
|
working at the very next commit, while the same sha in full installed. A branch name (`#main`) and a tag
|
|
769
785
|
are both accepted, but a branch is a moving target and a tag is constant: this release stands on the tag
|
|
770
|
-
`v2.8.
|
|
786
|
+
`v2.8.3`, which is also the one in the example (forty characters work as well, but they have to be copied
|
|
771
787
|
out of the history by eye).
|
|
772
788
|
|
|
773
789
|
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.8.
|
|
3
|
+
"version": "2.8.3",
|
|
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.8.
|
|
68
|
+
"@vernikr/size-report": "2.8.2",
|
|
69
69
|
"c8": "10",
|
|
70
70
|
"dependency-cruiser": "17",
|
|
71
71
|
"eslint": "^9.18.0",
|
package/src/page/table.js
CHANGED
|
@@ -31,6 +31,14 @@ import { appData, appUi, appView } from './state.js';
|
|
|
31
31
|
* table, against 6.5 ms for building the whole window again). The header sticks to the shell's top and the commit
|
|
32
32
|
* column to its left (both `position: sticky`), so the row and the column a number belongs to are always in sight.
|
|
33
33
|
*
|
|
34
|
+
* **A step down the table and a step sideways cost the same kind of work.** A row is made once and then stands at its
|
|
35
|
+
* own place in the scrolled content while the window moves over it: the window's columns are the range of that row's
|
|
36
|
+
* numbers, so a step sideways makes the columns that entered and drops the ones that left (`appStrip`) — a cell per
|
|
37
|
+
* row, the header's two lines included. A row that left the window vertically is dropped and made again when the
|
|
38
|
+
* reader comes back to it, which is what makes a jump down the table cost the same as a step. Building the rows again
|
|
39
|
+
* on every sideways scroll — the first version of this step — is what `probes/step-12-window.mjs` measures against the
|
|
40
|
+
* splice (`worklog/0211-sideways-step.md`).
|
|
41
|
+
*
|
|
34
42
|
* The choice is applied by building the window again: the columns of a switched-off file are simply not among the
|
|
35
43
|
* columns that are built, so there is nothing to hide and nothing to recount — the totals are the sum over the files
|
|
36
44
|
* that are on, counted by `rowModel` for the rows the window holds (`src/derived.js`, one place for that
|
|
@@ -138,6 +146,27 @@ export function appState(metricsCount, filesCount) {
|
|
|
138
146
|
document.getElementById('shell').hidden = metricsCount === 0;
|
|
139
147
|
}
|
|
140
148
|
|
|
149
|
+
/* A strip of pieces of one range, moved to another: the pieces the two ranges share are kept, and only the ends are
|
|
150
|
+
* made and dropped. The unit of a strip is its child — a row's numbers are one column to a child, the header's line of
|
|
151
|
+
* names one group, its line of metrics one column — so the same movement serves all three, and a group of metrics
|
|
152
|
+
* cannot be split by the window (a column of numbers would lose its caption). A window that jumped clear of the old
|
|
153
|
+
* range — the reader dragged the scrollbar — has nothing to keep and the strip is made again; the empty range
|
|
154
|
+
* `[c, c - 1]` is how a strip that holds nothing yet says so. */
|
|
155
|
+
function appStrip(strip, was, now, make) {
|
|
156
|
+
const a = Math.max(was[0], now[0]);
|
|
157
|
+
const b = Math.min(was[1], now[1]);
|
|
158
|
+
if (a > b) {
|
|
159
|
+
strip.textContent = '';
|
|
160
|
+
for (let c = now[0]; c <= now[1]; c++) strip.appendChild(make(c));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
for (let n = a - was[0]; n > 0; n--) strip.firstChild.remove();
|
|
164
|
+
for (let n = was[1] - b; n > 0; n--) strip.lastChild.remove();
|
|
165
|
+
const edge = strip.firstChild;
|
|
166
|
+
for (let c = a - 1; c >= now[0]; c--) strip.insertBefore(make(c), edge);
|
|
167
|
+
for (let c = b + 1; c <= now[1]; c++) strip.appendChild(make(c));
|
|
168
|
+
}
|
|
169
|
+
|
|
141
170
|
/* One cell of the window: the column decides what it holds. The group is the column's ordinal divided by the number of
|
|
142
171
|
* metrics — `0` is the total over the files, `g ≥ 1` is the g-th column of the order — and it is the same arithmetic
|
|
143
172
|
* the header is placed by, so a column and its caption cannot drift apart. The model lists the *enabled* files in the
|
|
@@ -153,9 +182,13 @@ function appCell(model, c, now, cache) {
|
|
|
153
182
|
return appNum(now ? valueParts(cell) : cellParts(cell.value, cell.delta, '−'), cls);
|
|
154
183
|
}
|
|
155
184
|
|
|
156
|
-
/* A row of the window: the caption of the commit and
|
|
157
|
-
* state at HEAD (`nowModel`) rather than the last commit's cells: an absolute number stands in the
|
|
158
|
-
* the deltas below it add up to it.
|
|
185
|
+
/* A row of the window: the caption of the commit and an empty strip of numbers for the window to fill (`appCells`).
|
|
186
|
+
* The top row is the state at HEAD (`nowModel`) rather than the last commit's cells: an absolute number stands in the
|
|
187
|
+
* table once, and the deltas below it add up to it.
|
|
188
|
+
*
|
|
189
|
+
* The model is kept in the entry beside the node because the numbers of a row depend on the commit and the choice
|
|
190
|
+
* rather than on the place the window stands at: a step sideways asks for a cell's arithmetic, never for `rowModel`
|
|
191
|
+
* again. The strip is born empty — the range `[c0, c0 - 1]` — and is filled by the first `appCells`. */
|
|
159
192
|
function appRow(cache, r, span) {
|
|
160
193
|
const last = appData.rows.length;
|
|
161
194
|
const now = r === 0;
|
|
@@ -163,28 +196,36 @@ function appRow(cache, r, span) {
|
|
|
163
196
|
const model = now
|
|
164
197
|
? nowModel(appData.now, cache.keys, appView.files)
|
|
165
198
|
: rowModel(appData.rows[i].values, i === 0 ? null : appData.rows[i - 1].values, cache.keys, appView.files);
|
|
166
|
-
const
|
|
167
|
-
|
|
199
|
+
const el = appEl('div', 'row' + (now ? ' now' : ''));
|
|
200
|
+
el.style.top = (APP_HEAD + r * APP_ROW) + 'px';
|
|
168
201
|
const commit = appEl('div', 'c-commit');
|
|
169
202
|
if (now) commit.textContent = appUi.now;
|
|
170
203
|
else commit.appendChild(appCommit(appData.rows[i]));
|
|
171
|
-
|
|
204
|
+
el.appendChild(commit);
|
|
172
205
|
const cells = appEl('div', 'cells');
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
206
|
+
el.appendChild(cells);
|
|
207
|
+
return { el: el, cells: cells, model: model, now: now, cols: [span.c0, span.c0 - 1] };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* A row's numbers at the window's columns: the columns the two windows share keep their cells, and a column that
|
|
211
|
+
* entered is made. The numbers stand beside the pinned commit column rather than under it — the column lies over the
|
|
212
|
+
* content — so the strip is placed by the window's first column, and the cells of it follow their strip. A step down
|
|
213
|
+
* the table asks for the columns it already holds, and the row is not touched at all. */
|
|
214
|
+
function appCells(entry, cache, span) {
|
|
215
|
+
const cols = [span.c0, span.c1];
|
|
216
|
+
if (entry.cols[0] === cols[0] && entry.cols[1] === cols[1]) return;
|
|
217
|
+
entry.cells.style.left = (APP_COMMIT + cols[0] * APP_COL) + 'px';
|
|
218
|
+
appStrip(entry.cells, entry.cols, cols, (c) => appCell(entry.model, c, entry.now, cache));
|
|
219
|
+
entry.cols = cols;
|
|
179
220
|
}
|
|
180
221
|
|
|
181
222
|
/* A built row into the window: the map is what says which rows are in the markup, so a row goes into it where it is
|
|
182
223
|
* made — otherwise a window that moved would build its rows beside the ones that are still there. */
|
|
183
224
|
function appPlace(cache, r, span) {
|
|
184
|
-
const
|
|
185
|
-
cache.rows.set(r,
|
|
186
|
-
cache
|
|
187
|
-
|
|
225
|
+
const entry = appRow(cache, r, span);
|
|
226
|
+
cache.rows.set(r, entry);
|
|
227
|
+
appCells(entry, cache, span);
|
|
228
|
+
cache.grid.appendChild(entry.el);
|
|
188
229
|
}
|
|
189
230
|
|
|
190
231
|
/* A caption of the header: a file's name or a metric's. The room is a fixed number of columns, so a name that does
|
|
@@ -197,30 +238,39 @@ function appCaption(text, cls, span) {
|
|
|
197
238
|
return el;
|
|
198
239
|
}
|
|
199
240
|
|
|
200
|
-
/* The header: the
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
function
|
|
204
|
-
const
|
|
205
|
-
const g0 = Math.floor(span.c0 / count);
|
|
206
|
-
const g1 = Math.floor(span.c1 / count);
|
|
207
|
-
const left = (APP_COMMIT + g0 * count * APP_COL) + 'px';
|
|
208
|
-
const head = appEl('div', 'head');
|
|
209
|
-
head.appendChild(appEl('div', 'c-commit', appUi.commit));
|
|
241
|
+
/* The header's frame: the commit column and the two empty strips that `appStrip` fills — the names of the groups over
|
|
242
|
+
* the columns, their metrics under them. An empty strip says `[0, -1]`, which is what makes the first `appHead` fill
|
|
243
|
+
* it rather than move it. */
|
|
244
|
+
function appHeadNew() {
|
|
245
|
+
const el = appEl('div', 'head');
|
|
210
246
|
const groups = appEl('div', 'hgroups');
|
|
211
|
-
groups.style.left = left;
|
|
212
247
|
const metrics = appEl('div', 'hmetrics');
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
248
|
+
el.appendChild(appEl('div', 'c-commit', appUi.commit));
|
|
249
|
+
el.appendChild(groups);
|
|
250
|
+
el.appendChild(metrics);
|
|
251
|
+
return { el: el, groups: groups, metrics: metrics, g: [0, -1] };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* The header: the total and the enabled files over their columns, and one caption per metric column under them. The two
|
|
255
|
+
* strips move by the same `appStrip` as a row's numbers, and the unit of the metrics line is a column, so its strip is
|
|
256
|
+
* asked for whole groups — the metrics of a column stand under their file even when the window cuts the last group.
|
|
257
|
+
* A window that did not leave a group (a step down the table) leaves the header alone. */
|
|
258
|
+
function appHead(cache, span) {
|
|
259
|
+
const count = cache.keys.length;
|
|
260
|
+
const g0 = count === 0 ? 0 : Math.floor(span.c0 / count);
|
|
261
|
+
const g1 = count === 0 ? -1 : Math.floor(span.c1 / count);
|
|
262
|
+
if (cache.head === null) cache.head = appHeadNew();
|
|
263
|
+
const h = cache.head;
|
|
264
|
+
if (h.g[0] === g0 && h.g[1] === g1) return h.el;
|
|
265
|
+
const was = h.g;
|
|
266
|
+
h.g = [g0, g1];
|
|
267
|
+
h.groups.style.left = (APP_COMMIT + g0 * count * APP_COL) + 'px';
|
|
268
|
+
h.metrics.style.left = h.groups.style.left;
|
|
269
|
+
appStrip(h.groups, was, h.g, (g) => appCaption(
|
|
270
|
+
g === 0 ? appUi.total : appData.files[cache.list[g - 1]].label, 'gh', count));
|
|
271
|
+
appStrip(h.metrics, [was[0] * count, was[1] * count + count - 1], [g0 * count, g1 * count + count - 1],
|
|
272
|
+
(c) => appCaption(cache.labels[c % count], c % count === 0 ? 'g' : '', 1));
|
|
273
|
+
return h.el;
|
|
224
274
|
}
|
|
225
275
|
|
|
226
276
|
/* The window the shell shows: the rows and the columns, in the ordinals of the whole grid, and the size of that
|
|
@@ -259,26 +309,32 @@ export function appSpan(cache) {
|
|
|
259
309
|
};
|
|
260
310
|
}
|
|
261
311
|
|
|
262
|
-
/* The window drawn.
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
312
|
+
/* The window drawn. Moving over the grid costs what left it and what entered it, and nothing else: the rows in the
|
|
313
|
+
* markup are the window's rows (what left it is dropped, what entered it is made) and each of them holds the columns
|
|
314
|
+
* of the window (`appCells`), so a step in either direction is paid by the rows that moved rather than by the table.
|
|
315
|
+
*
|
|
316
|
+
* The reader's own choice (`redraw`) is the one thing that cannot be a move: the columns of a switched-off file are
|
|
317
|
+
* simply not among the columns that are built, so there is nothing to hide and nothing to recount — the totals are the
|
|
318
|
+
* sum over the files that are on (`rowModel`), and the window is built from nothing. The shell's own size is the same
|
|
319
|
+
* kind of change: it decides how much of the grid is in sight, which is not a place to move to. */
|
|
266
320
|
export function appWindow(cache, redraw) {
|
|
267
321
|
const span = appSpan(cache);
|
|
268
322
|
const was = cache.win;
|
|
269
323
|
cache.win = span;
|
|
270
|
-
if (redraw === true || was === null
|
|
324
|
+
if (redraw === true || was === null) {
|
|
271
325
|
/* The grid holds the header and the rows of the window and nothing else, so the whole of it is thrown away rather
|
|
272
326
|
* than tracked piece by piece — and the rows that are made below say in the map that they are there. */
|
|
273
327
|
cache.grid.textContent = '';
|
|
274
328
|
cache.rows.clear();
|
|
329
|
+
cache.head = null;
|
|
275
330
|
cache.grid.appendChild(appHead(cache, span));
|
|
276
331
|
for (let r = span.r0; r <= span.r1; r++) appPlace(cache, r, span);
|
|
277
332
|
return;
|
|
278
333
|
}
|
|
334
|
+
appHead(cache, span);
|
|
279
335
|
[...cache.rows.keys()].forEach((r) => {
|
|
280
|
-
if (r >= span.r0 && r <= span.r1) return;
|
|
281
|
-
cache.rows.get(r).remove();
|
|
336
|
+
if (r >= span.r0 && r <= span.r1) { appCells(cache.rows.get(r), cache, span); return; }
|
|
337
|
+
cache.rows.get(r).el.remove();
|
|
282
338
|
cache.rows.delete(r);
|
|
283
339
|
});
|
|
284
340
|
for (let r = span.r0; r <= span.r1; r++) {
|
|
@@ -299,6 +355,7 @@ export function appTable(grid) {
|
|
|
299
355
|
rank: [],
|
|
300
356
|
slot: [],
|
|
301
357
|
rows: new Map(),
|
|
358
|
+
head: null,
|
|
302
359
|
win: null
|
|
303
360
|
};
|
|
304
361
|
cache.shell.addEventListener('scroll', () => appWindow(cache));
|