@vernikr/size-report 2.3.0 → 2.5.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 +929 -1051
- package/bin/postinstall.js +17 -18
- package/bin/size.js +2 -2
- package/package.json +3 -4
- package/src/args.js +72 -72
- package/src/artifact.js +14 -14
- package/src/check.js +41 -42
- package/src/cli.js +26 -29
- package/src/config.js +87 -91
- package/src/css.js +14 -14
- package/src/data.js +33 -35
- package/src/derived.js +31 -35
- package/src/doctor.js +95 -99
- package/src/explain.js +46 -47
- package/src/git.js +66 -71
- package/src/history.js +81 -69
- package/src/hook.js +130 -149
- package/src/init.js +36 -37
- package/src/journal.js +17 -15
- package/src/locales.js +25 -16
- package/src/metrics.js +56 -55
- package/src/minify.js +28 -27
- package/src/modes.js +57 -60
- package/src/optional.js +13 -11
- package/src/page/app.css +78 -87
- package/src/page/app.js +31 -30
- package/src/page/build.js +40 -39
- package/src/page/dom.js +16 -3
- package/src/page/panel.js +85 -64
- package/src/page/state.js +72 -87
- package/src/page/table.js +21 -24
- package/src/parse-worker.js +10 -10
- package/src/parse.js +43 -45
- package/src/project.js +100 -104
- package/src/refusal.js +75 -76
- package/src/size-table.js +41 -76
- package/src/strip/forms.js +5 -5
- package/src/strip/guard.js +27 -28
- package/src/strip/js.js +27 -27
- package/src/strip.js +18 -21
- package/src/table.css +13 -14
- package/src/tokens.js +28 -27
- package/src/tool.js +10 -11
- package/templates/README.md +71 -77
- package/templates/ci.yml +33 -33
- package/templates/size-report.config.json +3 -3
- package/CHANGELOG.md +0 -639
package/src/page/state.js
CHANGED
|
@@ -1,27 +1,22 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/* The page's choice state: what is switched on, how it survives a closing and how it travels as a link.
|
|
2
2
|
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* же расчёт, что считает статическую таблицу, и не может дать других чисел.
|
|
3
|
+
* An ordinary source file rather than a string inside the engine: a linter sees it, and it is pasted into the assembled
|
|
4
|
+
* page (`pageScript` strips module syntax — the `import` lines and the `export` keywords of the chapters). The numbers
|
|
5
|
+
* come from the derived quantities, so switching a metric, a category or a file calls the same calculation the report's
|
|
6
|
+
* numbers come from and cannot yield different ones.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* правила общей части оформления).
|
|
8
|
+
* The page is one file without external references, so there is no dynamic import here and nothing is loaded over the
|
|
9
|
+
* network: the styling arrives in the same file, and the cell markup follows the rules of the shared part of the styling
|
|
10
|
+
* (`clip`, a commit's caption).
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
12
|
+
* The panel remembers the reader's choice between visits and can hand it over as a link ("the choice's memory" below):
|
|
13
|
+
* the record is tied to the report's passport and keeps only what is switched off, by name, so someone else's record is
|
|
14
|
+
* not applied while a vanished name simply means nothing. The same record goes into the address — which is what one
|
|
15
|
+
* sends to a colleague.
|
|
18
16
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
|
|
23
|
-
/* Импорт — одной строкой: модульный синтаксис снимается при вклейке построчно,
|
|
24
|
-
* и оставшаяся строка `import` попала бы в страницу (её ловит проверка). */
|
|
17
|
+
* The page does not derive a number's accuracy itself: the marks of approximate cells arrive in the data, from the same
|
|
18
|
+
* rule that names a metric's accuracy. The page draws no such conclusion from paths and formats — there will be no
|
|
19
|
+
* second rule of accuracy. */
|
|
25
20
|
|
|
26
21
|
export const appData = JSON.parse(document.getElementById('data').textContent);
|
|
27
22
|
export const appUi = JSON.parse(document.getElementById('ui').textContent);
|
|
@@ -29,42 +24,39 @@ export const appView = { metrics: {}, files: [], folded: {} };
|
|
|
29
24
|
appData.metrics.forEach((m) => { appView.metrics[m.key] = true; });
|
|
30
25
|
appData.files.forEach(() => { appView.files.push(true); });
|
|
31
26
|
|
|
32
|
-
/*
|
|
33
|
-
*
|
|
34
|
-
* посчитано» у страницы нет. */
|
|
27
|
+
/* A metric's description by key: the tooltip of an approximate cell names the way its number was obtained — the same one
|
|
28
|
+
* that stands in the metric's caption, so the page holds no two answers about "counted with what". */
|
|
35
29
|
export const appMetric = {};
|
|
36
30
|
appData.metrics.forEach((m) => { appMetric[m.key] = m; });
|
|
37
31
|
|
|
38
|
-
/*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* (`appFileAt`), — дерево и память читателя разойтись не могут. */
|
|
32
|
+
/* A column by a file's path: the page's tree is the project's tree (every path of the catalogue) while the numbers
|
|
33
|
+
* belong to columns only, so this pointer is what decides whether a leaf is a checkbox or a caption. The name follows the
|
|
34
|
+
* same rule as the choice's record (`appFileAt`), so the tree and the reader's memory cannot drift apart. */
|
|
42
35
|
export const appMeasured = {};
|
|
43
36
|
appData.files.forEach((_f, i) => { appMeasured[appFileAt(i)] = i; });
|
|
44
37
|
|
|
45
|
-
/*
|
|
46
|
-
*
|
|
38
|
+
/* 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
|
|
39
|
+
* as a link, and there is nothing to argue with it about. */
|
|
47
40
|
const APP_LINK = '#size-report=';
|
|
48
41
|
|
|
49
|
-
/*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* ещё не гаснет. */
|
|
42
|
+
/* Three circumstances of the first drawing, which act on it alone: the address is not rewritten during it (it was sent to
|
|
43
|
+
* the reader rather than the other way), the memory is not touched (a link that came in is not the reader's choice), and
|
|
44
|
+
* the message about the link has not faded yet. */
|
|
53
45
|
let appStartup = true;
|
|
54
46
|
let appForeign = false;
|
|
55
47
|
let appTransient = false;
|
|
56
48
|
|
|
57
|
-
/* --------
|
|
49
|
+
/* -------- the reader's memory of his choice -------- */
|
|
58
50
|
|
|
59
|
-
/*
|
|
60
|
-
*
|
|
51
|
+
/* The name of a file for the record is its path at HEAD, or the last of the settings when the file is already gone from
|
|
52
|
+
* there: that is the name it is recognised by in the report. */
|
|
61
53
|
export function appFileAt(i) {
|
|
62
54
|
const f = appData.files[i];
|
|
63
55
|
return f.path === null ? f.paths[0] : f.path;
|
|
64
56
|
}
|
|
65
57
|
|
|
66
|
-
/*
|
|
67
|
-
*
|
|
58
|
+
/* The passport's fingerprint: an identifying mark of a record rather than protection against forgery, so 32 bits are
|
|
59
|
+
* enough (FNV-1a). */
|
|
68
60
|
function appHash(text) {
|
|
69
61
|
let h = 2166136261;
|
|
70
62
|
for (let i = 0; i < text.length; i++) {
|
|
@@ -74,22 +66,20 @@ function appHash(text) {
|
|
|
74
66
|
return (h >>> 0).toString(16);
|
|
75
67
|
}
|
|
76
68
|
|
|
77
|
-
/*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* история, к которой читатель и возвращается. */
|
|
69
|
+
/* The report's passport: the tool's name, the data schema, the artifact's path, the title and the column labels in the
|
|
70
|
+
* report's order. It is what tells one report from another — the record's key is chosen by it, so a choice made in
|
|
71
|
+
* someone else's report is not picked up. The package version and the top of the history are absent on purpose: this is
|
|
72
|
+
* the same report — updating the tool does not change what a column means, while a grown history is the very history the
|
|
73
|
+
* reader comes back to. */
|
|
83
74
|
function appPassport() {
|
|
84
75
|
return appHash([appData.tool.name, appData.schema, appData.report.artifact,
|
|
85
76
|
appData.report.title, appData.files.map((f) => f.label).join('|')].join('\n'));
|
|
86
77
|
}
|
|
87
78
|
const appKey = 'size-report:' + appPassport();
|
|
88
79
|
|
|
89
|
-
/*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* убирает запись, а не оставляет след, неотличимый от выбора. */
|
|
80
|
+
/* One record of the choice for everything: it goes both into the memory and into the address, so there are no two formats
|
|
81
|
+
* of one state. Only what is switched off is kept, by name: "switched on" and "no record" are the same state, which is
|
|
82
|
+
* why turning every checkbox back on removes the record instead of leaving a trace indistinguishable from a choice. */
|
|
93
83
|
function appRecord() {
|
|
94
84
|
const metrics = {};
|
|
95
85
|
const files = {};
|
|
@@ -98,7 +88,7 @@ function appRecord() {
|
|
|
98
88
|
return { v: 1, passport: appPassport(), metrics: metrics, files: files };
|
|
99
89
|
}
|
|
100
90
|
|
|
101
|
-
//
|
|
91
|
+
// Whether a record is ours and of the right format — one rule for the memory and the address alike.
|
|
102
92
|
function appRecordOk(rec) {
|
|
103
93
|
return rec !== null && typeof rec === 'object' && rec.v === 1 && rec.passport === appPassport();
|
|
104
94
|
}
|
|
@@ -111,34 +101,33 @@ export function appWrite() {
|
|
|
111
101
|
if (empty) window.localStorage.removeItem(appKey);
|
|
112
102
|
else window.localStorage.setItem(appKey, JSON.stringify(rec));
|
|
113
103
|
} catch (_e) {
|
|
114
|
-
/*
|
|
115
|
-
*
|
|
104
|
+
/* There is no memory (the browser grants this page none): the choice will not survive a closing, while the numbers
|
|
105
|
+
* and the markup do not depend on it. */
|
|
116
106
|
}
|
|
117
107
|
}
|
|
118
|
-
/*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
108
|
+
/* The address is the link for a colleague, which is why it repeats the choice. But not during the first drawing and not
|
|
109
|
+
* when the link turned out to be someone else's: an address that came in is not ours, and the reader has yet to read
|
|
110
|
+
* it. */
|
|
121
111
|
if (appStartup || appForeign) return;
|
|
122
112
|
try {
|
|
123
113
|
window.history.replaceState(null, '', APP_LINK + encodeURIComponent(JSON.stringify(rec)));
|
|
124
114
|
} catch (_e) {
|
|
125
|
-
/*
|
|
115
|
+
/* The browser grants no change of the address: the link is then taken from the browser's memory. */
|
|
126
116
|
}
|
|
127
117
|
}
|
|
128
118
|
|
|
129
|
-
/*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
119
|
+
/* A reset to "everything on": the border between "this is no longer in the report" and "switched off" is the record
|
|
120
|
+
* rather than a missing value. A link carries the sender's whole choice, which is why it is applied to a clean view rather
|
|
121
|
+
* than on top of someone else's. */
|
|
132
122
|
function appAll() {
|
|
133
123
|
appData.metrics.forEach((m) => { appView.metrics[m.key] = true; });
|
|
134
124
|
appData.files.forEach((_f, i) => { appView.files[i] = true; });
|
|
135
125
|
}
|
|
136
126
|
|
|
137
|
-
/*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
* не спорить с обычными якорями страницы. */
|
|
127
|
+
/* What the address says. It answers either with a record of ours or with a refusal (`linkForeign` — a link of another
|
|
128
|
+
* report, `linkBroken` — nothing to read): someone else's or a broken choice is not applied, but it does not stay silent
|
|
129
|
+
* either — otherwise the reader would not understand why he sees something other than what was sent to him. An address
|
|
130
|
+
* without the link's name is no link at all: silence, so as not to argue with the page's ordinary anchors. */
|
|
142
131
|
function appLinkRead() {
|
|
143
132
|
const hash = window.location.hash || '';
|
|
144
133
|
if (hash.indexOf(APP_LINK) !== 0) return { rec: null, refused: null };
|
|
@@ -160,8 +149,8 @@ function appLinkRead() {
|
|
|
160
149
|
return { rec: rec, refused: null, extra: appUnknown(rec) };
|
|
161
150
|
}
|
|
162
151
|
|
|
163
|
-
/*
|
|
164
|
-
*
|
|
152
|
+
/* How many names in the link are unknown to this report: the reader has to be told about them — otherwise he would look
|
|
153
|
+
* in the table for something that was never there. */
|
|
165
154
|
function appUnknown(rec) {
|
|
166
155
|
const known = {};
|
|
167
156
|
const metricKeys = {};
|
|
@@ -173,19 +162,18 @@ function appUnknown(rec) {
|
|
|
173
162
|
return n;
|
|
174
163
|
}
|
|
175
164
|
|
|
176
|
-
/*
|
|
177
|
-
*
|
|
165
|
+
/* The message about the link fades after the reader's very first action: he has read it, and a permanent warning is noise
|
|
166
|
+
* on top of the numbers. */
|
|
178
167
|
export function appNotice(text) {
|
|
179
168
|
const el = document.getElementById('notice');
|
|
180
169
|
el.textContent = text;
|
|
181
170
|
el.hidden = text === '';
|
|
182
171
|
}
|
|
183
172
|
|
|
184
|
-
/*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* чужим. Отказ объясняется словами — и не трогает ни вид, ни адрес. */
|
|
173
|
+
/* What its event does with the address — opening the page and an anchor change on an already open one (the browser does
|
|
174
|
+
* not reload the document then, it only moves the anchor, so without this reading a link would work in a new tab alone).
|
|
175
|
+
* A link of ours replaces the view whole: it holds the sender's entire choice rather than a difference from someone
|
|
176
|
+
* else's. A refusal is explained in words — and touches neither the view nor the address. */
|
|
189
177
|
export function appLinkUse() {
|
|
190
178
|
const link = appLinkRead();
|
|
191
179
|
if (link.rec !== null) {
|
|
@@ -201,9 +189,8 @@ export function appLinkUse() {
|
|
|
201
189
|
return 'none';
|
|
202
190
|
}
|
|
203
191
|
|
|
204
|
-
/*
|
|
205
|
-
*
|
|
206
|
-
* равносильна её отсутствию. */
|
|
192
|
+
/* Reading: only a record of ours — of our format version and our passport. Another report's record lies under another key,
|
|
193
|
+
* while a foreign, outdated or broken one amounts to its absence. */
|
|
207
194
|
export function appRead() {
|
|
208
195
|
let text = null;
|
|
209
196
|
try {
|
|
@@ -221,10 +208,9 @@ export function appRead() {
|
|
|
221
208
|
return appRecordOk(rec) ? rec : null;
|
|
222
209
|
}
|
|
223
210
|
|
|
224
|
-
/*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* как их видит тот, кто открыл страницу впервые. */
|
|
211
|
+
/* Applying goes by name: a file is recognised by its path, a metric by its key. A name the report does not hold matches
|
|
212
|
+
* nothing (a column was pointed at another path, a metric was dropped from the settings), while files and metrics that
|
|
213
|
+
* appeared stay switched on — the way someone opening the page for the first time sees them. */
|
|
228
214
|
export function appApply(rec) {
|
|
229
215
|
const metrics = rec.metrics || {};
|
|
230
216
|
const files = rec.files || {};
|
|
@@ -232,13 +218,12 @@ export function appApply(rec) {
|
|
|
232
218
|
appData.files.forEach((_f, i) => { if (files[appFileAt(i)] === false) appView.files[i] = false; });
|
|
233
219
|
}
|
|
234
220
|
|
|
235
|
-
/* --------
|
|
221
|
+
/* -------- the folded tree -------- */
|
|
236
222
|
|
|
237
|
-
/*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
* («src/page»), поэтому исчезнувшее имя просто ничего не значит. */
|
|
223
|
+
/* 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
|
|
224
|
+
* tree is visible rather than about which numbers are read. Hence it does not go into the address: a link is sent for the
|
|
225
|
+
* sake of the numbers, while an unfolded tree is the onlooker's business. As with the choice, only what is folded is kept
|
|
226
|
+
* (`true`), and a folder's name is its path ("src/page"), so a vanished name simply means nothing. */
|
|
242
227
|
const appFoldKey = appKey + ':tree';
|
|
243
228
|
|
|
244
229
|
export function appFoldRead() {
|
|
@@ -268,7 +253,7 @@ export function appFoldSet(path, folded) {
|
|
|
268
253
|
if (Object.keys(rec.folded).length === 0) window.localStorage.removeItem(appFoldKey);
|
|
269
254
|
else window.localStorage.setItem(appFoldKey, JSON.stringify(rec));
|
|
270
255
|
} catch (_e) {
|
|
271
|
-
/*
|
|
272
|
-
*
|
|
256
|
+
/* There is no memory: what is folded will not survive a closing, while the view does not depend on it — the tree is
|
|
257
|
+
* folded exactly the way the reader folded it just now. */
|
|
273
258
|
}
|
|
274
259
|
}
|
package/src/page/table.js
CHANGED
|
@@ -2,11 +2,10 @@ import { cellParts, commitParts, nowModel, rowModel, valueParts } from '../deriv
|
|
|
2
2
|
import { appEl } from './dom.js';
|
|
3
3
|
import { appData, appUi, appView, appMetric } from './state.js';
|
|
4
4
|
|
|
5
|
-
/*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* метрики (её способ и идёт в подсказку клетки) либо ничего. */
|
|
5
|
+
/* An approximate cell: the mark comes from the engine's data rather than being derived here from a file's path — the rule
|
|
6
|
+
* of accuracy lives where the numbers are counted. For a file's cell it is that number itself, for a total the worst of
|
|
7
|
+
* what went into it, or the sum would promise an accuracy its terms do not have. Returns the metric's description (its way
|
|
8
|
+
* of counting is what goes into the cell's tooltip) or nothing. */
|
|
10
9
|
export function appApprox(where, files, key) {
|
|
11
10
|
const marks = appData.approx[key];
|
|
12
11
|
if (marks === undefined) return null;
|
|
@@ -18,13 +17,13 @@ export function appApprox(where, files, key) {
|
|
|
18
17
|
return null;
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
/*
|
|
22
|
-
*
|
|
20
|
+
/* The cell's class is assembled in one place: both the mark of approximation and the gap ("no such file") are properties
|
|
21
|
+
* of the cell itself rather than of its content. */
|
|
23
22
|
function appCellClass(first, miss, approx) {
|
|
24
23
|
return 'num' + (first ? ' g' : '') + (miss ? ' miss' : '') + (approx === null ? '' : ' approx');
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
//
|
|
26
|
+
// The markup of a commit row's cell: the rules live in cellParts, only the node is here.
|
|
28
27
|
export function appCell(cell, first, approx) {
|
|
29
28
|
const parts = cellParts(cell.value, cell.delta, '−');
|
|
30
29
|
const td = appEl('td', appCellClass(first, parts.miss, approx));
|
|
@@ -34,7 +33,7 @@ export function appCell(cell, first, approx) {
|
|
|
34
33
|
return td;
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
//
|
|
36
|
+
// The markup of the top row's cell: the rules live in valueParts.
|
|
38
37
|
export function appValueCell(value, first, approx) {
|
|
39
38
|
const parts = valueParts(value);
|
|
40
39
|
const td = appEl('td', appCellClass(first, parts.miss, approx));
|
|
@@ -43,9 +42,8 @@ export function appValueCell(value, first, approx) {
|
|
|
43
42
|
return td;
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
/*
|
|
47
|
-
*
|
|
48
|
-
* оформления, поэтому колонка не прыгает при переключении файлов. */
|
|
45
|
+
/* A commit's caption: the date, the subject, the journal section's mark. The column's width and the clipping of a long
|
|
46
|
+
* subject come from the shared part of the styling, which is why the column does not jump when files are switched. */
|
|
49
47
|
export function appCommit(row) {
|
|
50
48
|
const parts = commitParts(row, appData.report.showSha, row.href);
|
|
51
49
|
const name = parts.href ? appEl('a', 'subj', parts.subject) : appEl('span', 'subj', parts.subject);
|
|
@@ -69,9 +67,9 @@ export function appSubHead(metrics) {
|
|
|
69
67
|
return tr;
|
|
70
68
|
}
|
|
71
69
|
|
|
72
|
-
/*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
70
|
+
/* The empty states: when there will be no numbers at all, the page says so in words rather than showing a grid without
|
|
71
|
+
* columns. Every file can be switched off — then the total volume remains, and the note explains why there are no
|
|
72
|
+
* columns. */
|
|
75
73
|
export function appState(metricsCount, filesCount) {
|
|
76
74
|
const state = document.getElementById('state');
|
|
77
75
|
const text = metricsCount === 0 ? appUi.empty : (filesCount === 0 ? appUi.noFiles : '');
|
|
@@ -80,9 +78,9 @@ export function appState(metricsCount, filesCount) {
|
|
|
80
78
|
document.getElementById('shell').hidden = metricsCount === 0;
|
|
81
79
|
}
|
|
82
80
|
|
|
83
|
-
/*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
81
|
+
/* The header: a row of groups (the total and the files) and a row of metrics under it. The metrics repeat for every file,
|
|
82
|
+
* so the sub-header is assembled once and its nodes then move on into the following ones — no copies of the markup are
|
|
83
|
+
* made. */
|
|
86
84
|
export function appHead(shown, files, metrics) {
|
|
87
85
|
const head = appEl('tr');
|
|
88
86
|
const commit = appEl('th', 'c-commit', appUi.commit);
|
|
@@ -107,9 +105,9 @@ export function appHead(shown, files, metrics) {
|
|
|
107
105
|
return thead;
|
|
108
106
|
}
|
|
109
107
|
|
|
110
|
-
/*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
108
|
+
/* A commit row: the caption and the numbers. The deltas come from the shared calculation (`rowModel`) rather than from
|
|
109
|
+
* here — two ways to count one row would be two answers. The mark of approximation is each cell's own: for a total it
|
|
110
|
+
* covers every file that went into it, for a file that file alone. */
|
|
113
111
|
export function appRow(r, metrics, files) {
|
|
114
112
|
const row = appData.rows[r];
|
|
115
113
|
const prev = r === 0 ? null : appData.rows[r - 1];
|
|
@@ -125,9 +123,8 @@ export function appRow(r, metrics, files) {
|
|
|
125
123
|
return tr;
|
|
126
124
|
}
|
|
127
125
|
|
|
128
|
-
/*
|
|
129
|
-
*
|
|
130
|
-
* стоит первой. */
|
|
126
|
+
/* The body: the commit rows built from the newest down, plus the "now" row with the absolute sizes at HEAD. The deltas
|
|
127
|
+
* under it add up to it, which is why it stands first. */
|
|
131
128
|
export function appBody(metrics, files) {
|
|
132
129
|
const body = appEl('tbody');
|
|
133
130
|
for (let r = appData.rows.length - 1; r >= 0; r--) body.appendChild(appRow(r, metrics, files));
|
package/src/parse-worker.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import vm from 'vm';
|
|
2
2
|
import { workerData } from 'worker_threads';
|
|
3
3
|
|
|
4
|
-
/*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
/* The parsing worker: it compiles the text and answers with a reason (or with the absence of
|
|
5
|
+
* one). Nothing is executed — `SourceTextModule` only parses the text, so neither `import`
|
|
6
|
+
* nor the code of the module runs: the file of the project stays foreign code that nobody
|
|
7
|
+
* launches.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
* `vm.SourceTextModule`
|
|
11
|
-
*
|
|
12
|
-
* `available: false`,
|
|
9
|
+
* The flags arrive from the main thread (`--experimental-vm-modules`, without which
|
|
10
|
+
* `vm.SourceTextModule` does not exist, and `--no-warnings` lest the experimental warning end
|
|
11
|
+
* up in the command's output). The module may be absent: then the answer carries
|
|
12
|
+
* `available: false`, and the main thread falls back to launching `node --check`.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
* (`Atomics.wait`),
|
|
14
|
+
* Readiness is marked in shared memory: the main thread waits for it synchronously
|
|
15
|
+
* (`Atomics.wait`), because measuring the history is synchronous.
|
|
16
16
|
*/
|
|
17
17
|
const { port, sig } = workerData;
|
|
18
18
|
const available = typeof vm.SourceTextModule === 'function';
|