@vernikr/size-report 2.6.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/page/panel.js CHANGED
@@ -66,27 +66,41 @@ function appDirHead(name, here, sub) {
66
66
  return head;
67
67
  }
68
68
 
69
+ /* The order inside one level, and the two rules of it: a hidden name (a leading dot) stands after every visible one —
70
+ * a project's service files are not what a reader looks for first — and otherwise the alphabet decides. "Other things
71
+ * being equal" is the whole of it: what the report holds stands before what it does not, and that partition is made
72
+ * before the names are compared. The rule is a function of two strings, which is what lets it be checked on its own
73
+ * rather than through a tree of a fixture that has no hidden files in it. */
74
+ export function appName(a, b) {
75
+ const hidden = (name) => (name.charAt(0) === '.' ? 1 : 0);
76
+ if (hidden(a) !== hidden(b)) return hidden(a) - hidden(b);
77
+ return a < b ? -1 : (a > b ? 1 : 0);
78
+ }
79
+
69
80
  /* The folder's sign is a click target of its own, separate from the checkbox: the checkbox answers for the numbers (it
70
81
  * switches the subtree's files on), while the sign answers for how much of the tree is visible. One target for two
71
82
  * different decisions would mean a folder can be folded only together with switching its files on. The sign is drawn
72
83
  * as a span rather than a button and stands beside the label rather than inside it: a label is one click target, and a
73
84
  * control nested in it would be reached as that same target.
74
85
  *
86
+ * The tree opens folded — the sign of an untouched folder says so — and the reader's unfolding is what the memory
87
+ * keeps (`appFoldSet`).
88
+ *
75
89
  * A click on the sign rebuilds nothing: the subtree lies in the markup and a class on the row hides it. A rebuild here
76
90
  * would be honest work for nothing — it counts the whole table (every row by every column) and so pays for numbers
77
91
  * folding does not change. That is why only the three things the reader sees change: the class, the sign and the note
78
92
  * in the memory. */
79
93
  function appFoldBox(name, path) {
80
- const folded = appView.folded[path] === true;
81
- const box = appEl('span', 'fold', folded ? '' : '');
82
- box.title = (folded ? appUi.foldOpen : appUi.foldClose).replace('{name}', name);
94
+ const open = appView.open[path] === true;
95
+ const box = appEl('span', 'fold', open ? '' : '');
96
+ box.title = (open ? appUi.foldClose : appUi.foldOpen).replace('{name}', name);
83
97
  box.addEventListener('click', () => {
84
- const now = !(appView.folded[path] === true);
98
+ const now = !(appView.open[path] === true);
85
99
  appFoldSet(path, now);
86
100
  const li = box.closest('li');
87
- if (li !== null) li.classList.toggle('folded', now);
88
- box.textContent = now ? '' : '';
89
- box.title = (now ? appUi.foldOpen : appUi.foldClose).replace('{name}', name);
101
+ if (li !== null) li.classList.toggle('folded', !now);
102
+ box.textContent = now ? '' : '';
103
+ box.title = (now ? appUi.foldClose : appUi.foldOpen).replace('{name}', name);
90
104
  });
91
105
  return box;
92
106
  }
@@ -98,14 +112,14 @@ function appLeaves(node) {
98
112
  node.others.forEach((entry) => {
99
113
  items.push({ name: entry.path.split('/').pop(), i: null, entry: entry });
100
114
  });
101
- return items.sort((a, b) => (a.name < b.name ? -1 : (a.name > b.name ? 1 : 0)));
115
+ return items.sort((a, b) => appName(a.name, b.name));
102
116
  }
103
117
 
104
118
  /* A folder row: the folding sign, the checkbox with the number of files and the subtree. A folded folder differs by
105
119
  * its class alone — the markup stays the same. */
106
120
  function appDir(name, sub, prefix) {
107
121
  const here = prefix === '' ? name : prefix + '/' + name;
108
- const folded = appView.folded[here] === true;
122
+ const folded = appView.open[here] !== true;
109
123
  const li = appEl('li', folded ? 'folded' : null);
110
124
  li.appendChild(appFoldBox(name, here));
111
125
  li.appendChild(appDirHead(name, here, sub));
@@ -126,7 +140,7 @@ function appLeaf(leaf) {
126
140
  * it does not distract from what is in the table, while it can still be found — in the same place where it was. */
127
141
  function appTreeList(node, prefix) {
128
142
  const list = appEl('ul', 'tree');
129
- const dirs = [...node.dirs.keys()].sort()
143
+ const dirs = [...node.dirs.keys()].sort(appName)
130
144
  .map((name) => ({ name: name, sub: node.dirs.get(name), inReport: appIndexes(node.dirs.get(name)).length > 0 }));
131
145
  const leaves = appLeaves(node);
132
146
  const inside = leaves.filter((leaf) => leaf.entry === null);
package/src/page/state.js CHANGED
@@ -11,10 +11,10 @@ import { appDecode } from './payload.js';
11
11
  * network: the styling arrives in the same file, and the cell markup follows the rules of the shared part of the styling
12
12
  * (`clip`, a commit's caption).
13
13
  *
14
- * The panel remembers the reader's choice between visits and can hand it over as a link ("the choice's memory" below):
15
- * the record is tied to the report's passport and keeps only what is switched off, by name, so someone else's record is
16
- * not applied while a vanished name simply means nothing. The same record goes into the address which is what one
17
- * sends to a colleague.
14
+ * The panel remembers the reader's choice between visits ("the choice's memory" below): the record is tied to the
15
+ * report's passport and keeps only what is switched off, by name, so someone else's record is not applied while a
16
+ * vanished name simply means nothing. The record stays in the browser's memory and nowhere else: a report opened from
17
+ * disk keeps a clean address, and a link made in an earlier release is still read (`appLinkUse`).
18
18
  *
19
19
  * The page draws no conclusion about how a number was obtained: the method of each metric arrives in the data, and the
20
20
  * page prints it. There is no second rule of counting here, and no vocabulary of precision either. */
@@ -47,7 +47,10 @@ let appFoldKey = null;
47
47
  * on the data, and until the block is unpacked there is nothing to count it from. */
48
48
  export function appBoot(text) {
49
49
  appData = appDecode(JSON.parse(text));
50
- appView = { metrics: {}, files: [], folded: {} };
50
+ /* The tree is folded as it opens: a project's tree is longer than the window, and the reader's first look is at a
51
+ * short list rather than at everything. What is remembered is the opposite — the folders the reader unfolded
52
+ * (`appFoldRead`). */
53
+ appView = { metrics: {}, files: [], open: {} };
51
54
  appMetric = {};
52
55
  appMeasured = {};
53
56
  appData.metrics.forEach((m) => { appView.metrics[m.key] = true; appMetric[m.key] = m; });
@@ -57,14 +60,12 @@ export function appBoot(text) {
57
60
  }
58
61
 
59
62
  /* A link is that same choice in the address, under a name of its own: someone else's anchor on the page does not count
60
- * as a link, and there is nothing to argue with it about. */
63
+ * as a link, and there is nothing to argue with it about. The page does not write it any more — it only reads what came
64
+ * with the address — and this paragraph is what such a link is read by. */
61
65
  const APP_LINK = '#size-report=';
62
66
 
63
- /* Three circumstances of the first drawing, which act on it alone: the address is not rewritten during it (it was sent to
64
- * the reader rather than the other way), the memory is not touched (a link that came in is not the reader's choice), and
65
- * the message about the link has not faded yet. */
66
- let appStartup = true;
67
- let appForeign = false;
67
+ /* One circumstance of the first drawing, and it acts on it alone: the memory is not written while somebody else's link
68
+ * is open what came in is not the reader's choice, and only his own action makes it his. */
68
69
  let appTransient = false;
69
70
 
70
71
  /* -------- the reader's memory of his choice -------- */
@@ -121,59 +122,27 @@ function appRecordOk(rec) {
121
122
  return rec !== null && typeof rec === 'object' && rec.v === 1 && rec.passport === appPassport();
122
123
  }
123
124
 
124
- /* The address is the link for a colleague, while the memory is the reader's own: the memory is written on the click
125
- * itself that is what survives a closingand the address 200 ms after the last of a burst of switches, because a
126
- * burst is one link rather than five history entries and five URL parses. The delay is short enough for a person and
127
- * long enough to swallow a run of clicks; a timer that fires after the page is gone writes nothing useful, which is the
128
- * price of not writing the address five times. */
129
- const APP_ADDRESS_DELAY = 200;
130
- let appAddressTimer = null;
131
-
132
- /* An address that came in from outside wins over a write this page has not made yet: a click arms a write, a link
133
- * arrives within the delay, and the choice left behind must not land on the address the reader was sent — a refused link
134
- * arms nothing to replace it, so without this the page would rewrite someone else's address a fifth of a second later. */
135
- export function appAddressDrop() {
136
- if (appAddressTimer === null) return;
137
- clearTimeout(appAddressTimer);
138
- appAddressTimer = null;
139
- }
140
-
141
- function appAddressLater(text) {
142
- appAddressDrop();
143
- appAddressTimer = setTimeout(() => {
144
- appAddressTimer = null;
145
- try {
146
- window.history.replaceState(null, '', APP_LINK + encodeURIComponent(text));
147
- } catch (_e) {
148
- /* The browser grants no change of the address: the link is then taken from the browser's memory. */
149
- }
150
- }, APP_ADDRESS_DELAY);
151
- }
152
-
153
- /* One record for a click and two destinations: the same text goes into the memory and — a moment later — into the
154
- * address, so the two cannot describe different choices. */
125
+ /* The record goes into the browser's memory and nowhere else: it is written on the click itself, which is what survives
126
+ * a closing, and the page's address keeps a clean tail — the report is a local page whose address is copied as it is,
127
+ * and a reader's choice belongs in the browser that made it rather than in the tab's title bar. What a link sent from an
128
+ * earlier release holds is still read (`appLinkUse`), and it is not written into the reader's memory: what came in is
129
+ * not his choice until he changes something. */
155
130
  export function appWrite() {
131
+ if (appTransient) return;
156
132
  const rec = appRecord();
157
- const text = JSON.stringify(rec);
158
133
  const empty = Object.keys(rec.metrics).length === 0 && Object.keys(rec.files).length === 0;
159
- if (!appTransient) {
160
- try {
161
- if (empty) window.localStorage.removeItem(appKey);
162
- else window.localStorage.setItem(appKey, text);
163
- } catch (_e) {
164
- /* There is no memory (the browser grants this page none): the choice will not survive a closing, while the numbers
165
- * and the markup do not depend on it. */
166
- }
134
+ try {
135
+ if (empty) window.localStorage.removeItem(appKey);
136
+ else window.localStorage.setItem(appKey, JSON.stringify(rec));
137
+ } catch (_e) {
138
+ /* There is no memory (the browser grants this page none): the choice will not survive a closing, while the numbers
139
+ * and the markup do not depend on it. */
167
140
  }
168
- /* But not during the first drawing and not when the link turned out to be someone else's: an address that came in is
169
- * not ours, and the reader has yet to read it. */
170
- if (appStartup || appForeign) return;
171
- appAddressLater(text);
172
141
  }
173
142
 
174
143
  /* A reset to "everything on": the border between "this is no longer in the report" and "switched off" is the record
175
- * rather than a missing value. A link carries the sender's whole choice, which is why it is applied to a clean view rather
176
- * than on top of someone else's. */
144
+ * rather than a missing value. A link carries the sender's whole choice, which is why it is applied to a clean view
145
+ * rather than on top of someone else's. */
177
146
  function appAll() {
178
147
  appData.metrics.forEach((m) => { appView.metrics[m.key] = true; });
179
148
  appData.files.forEach((_f, i) => { appView.files[i] = true; });
@@ -273,14 +242,15 @@ export function appApply(rec) {
273
242
  appData.files.forEach((_f, i) => { if (files[appFileAt(i)] === false) appView.files[i] = false; });
274
243
  }
275
244
 
276
- /* -------- the folded tree -------- */
277
-
245
+ /* -------- the unfolded tree -------- */
278
246
 
279
- /* Folded folders are a memory of the same kind as the choice, but of a record of their own: it is about how much of the
280
- * tree is visible rather than about which numbers are read. Hence it does not go into the address: a link is sent for the
281
- * sake of the numbers, while an unfolded tree is the onlooker's business. As with the choice, only what is folded is kept
282
- * (`true`), and a folder's name is its path ("src/page"), so a vanished name simply means nothing. `appFoldKey` is
283
- * set with the rest of the model (`appBoot`), for the reason the key itself is. */
247
+ /* How much of the tree is visible is a memory of the same kind as the choice, but of a record of its own: it is about
248
+ * what the onlooker looks at rather than about which numbers are read, which is why it never goes into a link and never
249
+ * leaves the browser. The tree opens folded, so **the unfolded folders are what is kept** (`true`) the default is the
250
+ * absence of the name, the same way "switched on" is the absence of a choice. A folder's name is its path ("src/page"),
251
+ * so a vanished name simply means nothing, and unfolding nothing is the state the page opens in: then the record is not
252
+ * kept at all rather than being kept empty. `appFoldKey` is set with the model (`appBoot`), for the reason the key
253
+ * itself is. */
284
254
  export function appFoldRead() {
285
255
  let text = null;
286
256
  try {
@@ -296,19 +266,19 @@ export function appFoldRead() {
296
266
  return;
297
267
  }
298
268
  if (!appRecordOk(rec)) return;
299
- const folded = rec.folded || {};
300
- Object.keys(folded).forEach((p) => { if (folded[p] === true) appView.folded[p] = true; });
269
+ const open = rec.open || {};
270
+ Object.keys(open).forEach((p) => { if (open[p] === true) appView.open[p] = true; });
301
271
  }
302
272
 
303
- export function appFoldSet(path, folded) {
304
- if (folded) appView.folded[path] = true;
305
- else delete appView.folded[path];
306
- const rec = { v: 1, passport: appPassport(), folded: Object.assign({}, appView.folded) };
273
+ export function appFoldSet(path, open) {
274
+ if (open) appView.open[path] = true;
275
+ else delete appView.open[path];
276
+ const rec = { v: 1, passport: appPassport(), open: Object.assign({}, appView.open) };
307
277
  try {
308
- if (Object.keys(rec.folded).length === 0) window.localStorage.removeItem(appFoldKey);
278
+ if (Object.keys(rec.open).length === 0) window.localStorage.removeItem(appFoldKey);
309
279
  else window.localStorage.setItem(appFoldKey, JSON.stringify(rec));
310
280
  } catch (_e) {
311
- /* There is no memory: what is folded will not survive a closing, while the view does not depend on it — the tree is
312
- * folded exactly the way the reader folded it just now. */
281
+ /* There is no memory: what is unfolded will not survive a closing, while the view does not depend on it — the tree
282
+ * is unfolded exactly the way the reader unfolded it just now. */
313
283
  }
314
284
  }