@jsenv/humanize 1.3.0 → 1.4.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/dist/browser/jsenv_humanize_browser.js +127 -20
- package/dist/node/jsenv_humanize_node.js +305 -26
- package/dist/node/jsenv_humanize_node_modules.js +709 -0
- package/package.json +4 -3
- package/src/ansi/ansi_runtime_agnostic.js +67 -9
- package/src/log/call_orderer.js +39 -0
- package/src/log/detailed_message.js +20 -8
- package/src/log/details.js +26 -0
- package/src/log/dynamic_log.js +4 -3
- package/src/log/section.js +50 -0
- package/src/main_browser.js +1 -0
- package/src/main_node.js +7 -1
- package/dist/node/js/vendors.js +0 -295
|
@@ -1,27 +1,73 @@
|
|
|
1
1
|
const createDetailedMessage = (message, details = {}) => {
|
|
2
|
-
let
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
return
|
|
2
|
+
let text = "".concat(message);
|
|
3
|
+
const namedSectionsText = renderNamedSections(details);
|
|
4
|
+
if (namedSectionsText) {
|
|
5
|
+
text += "\n".concat(namedSectionsText);
|
|
6
|
+
}
|
|
7
|
+
return text;
|
|
8
|
+
};
|
|
9
|
+
const renderNamedSections = namedSections => {
|
|
10
|
+
let text = "";
|
|
11
|
+
let keys = Object.keys(namedSections);
|
|
12
|
+
for (const key of keys) {
|
|
13
|
+
const isLastKey = key === keys[keys.length - 1];
|
|
14
|
+
const value = namedSections[key];
|
|
15
|
+
text += "--- ".concat(key, " ---\n").concat(Array.isArray(value) ? value.join("\n") : value);
|
|
16
|
+
if (!isLastKey) {
|
|
17
|
+
text += "\n";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return text;
|
|
8
21
|
};
|
|
9
22
|
|
|
10
23
|
// https://github.com/Marak/colors.js/blob/master/lib/styles.js
|
|
11
24
|
// https://stackoverflow.com/a/75985833/2634179
|
|
12
25
|
const RESET = "\x1b[0m";
|
|
26
|
+
const RED = "red";
|
|
27
|
+
const GREEN = "green";
|
|
28
|
+
const YELLOW = "yellow";
|
|
29
|
+
const BLUE = "blue";
|
|
30
|
+
const MAGENTA = "magenta";
|
|
31
|
+
const CYAN = "cyan";
|
|
32
|
+
const GREY = "grey";
|
|
33
|
+
const WHITE = "white";
|
|
34
|
+
const BLACK = "black";
|
|
35
|
+
const TEXT_COLOR_ANSI_CODES = {
|
|
36
|
+
[RED]: "\x1b[31m",
|
|
37
|
+
[GREEN]: "\x1b[32m",
|
|
38
|
+
[YELLOW]: "\x1b[33m",
|
|
39
|
+
[BLUE]: "\x1b[34m",
|
|
40
|
+
[MAGENTA]: "\x1b[35m",
|
|
41
|
+
[CYAN]: "\x1b[36m",
|
|
42
|
+
[GREY]: "\x1b[90m",
|
|
43
|
+
[WHITE]: "\x1b[37m",
|
|
44
|
+
[BLACK]: "\x1b[30m"
|
|
45
|
+
};
|
|
46
|
+
const BACKGROUND_COLOR_ANSI_CODES = {
|
|
47
|
+
[RED]: "\x1b[41m",
|
|
48
|
+
[GREEN]: "\x1b[42m",
|
|
49
|
+
[YELLOW]: "\x1b[43m",
|
|
50
|
+
[BLUE]: "\x1b[44m",
|
|
51
|
+
[MAGENTA]: "\x1b[45m",
|
|
52
|
+
[CYAN]: "\x1b[46m",
|
|
53
|
+
[GREY]: "\x1b[100m",
|
|
54
|
+
[WHITE]: "\x1b[47m",
|
|
55
|
+
[BLACK]: "\x1b[40m"
|
|
56
|
+
};
|
|
13
57
|
const createAnsi = ({
|
|
14
58
|
supported
|
|
15
59
|
}) => {
|
|
16
60
|
const ANSI = {
|
|
17
61
|
supported,
|
|
18
|
-
RED
|
|
19
|
-
GREEN
|
|
20
|
-
YELLOW
|
|
21
|
-
BLUE
|
|
22
|
-
MAGENTA
|
|
23
|
-
CYAN
|
|
24
|
-
GREY
|
|
62
|
+
RED,
|
|
63
|
+
GREEN,
|
|
64
|
+
YELLOW,
|
|
65
|
+
BLUE,
|
|
66
|
+
MAGENTA,
|
|
67
|
+
CYAN,
|
|
68
|
+
GREY,
|
|
69
|
+
WHITE,
|
|
70
|
+
BLACK,
|
|
25
71
|
color: (text, color) => {
|
|
26
72
|
if (!ANSI.supported) {
|
|
27
73
|
return text;
|
|
@@ -33,7 +79,28 @@ const createAnsi = ({
|
|
|
33
79
|
// cannot set color of blank chars
|
|
34
80
|
return text;
|
|
35
81
|
}
|
|
36
|
-
|
|
82
|
+
const ansiEscapeCodeForTextColor = TEXT_COLOR_ANSI_CODES[color];
|
|
83
|
+
if (!ansiEscapeCodeForTextColor) {
|
|
84
|
+
return text;
|
|
85
|
+
}
|
|
86
|
+
return "".concat(ansiEscapeCodeForTextColor).concat(text).concat(RESET);
|
|
87
|
+
},
|
|
88
|
+
backgroundColor: (text, color) => {
|
|
89
|
+
if (!ANSI.supported) {
|
|
90
|
+
return text;
|
|
91
|
+
}
|
|
92
|
+
if (!color) {
|
|
93
|
+
return text;
|
|
94
|
+
}
|
|
95
|
+
if (typeof text === "string" && text.trim() === "") {
|
|
96
|
+
// cannot set background color of blank chars
|
|
97
|
+
return text;
|
|
98
|
+
}
|
|
99
|
+
const ansiEscapeCodeForBackgroundColor = BACKGROUND_COLOR_ANSI_CODES[color];
|
|
100
|
+
if (!ansiEscapeCodeForBackgroundColor) {
|
|
101
|
+
return text;
|
|
102
|
+
}
|
|
103
|
+
return "".concat(ansiEscapeCodeForBackgroundColor).concat(text).concat(RESET);
|
|
37
104
|
},
|
|
38
105
|
BOLD: "\x1b[1m",
|
|
39
106
|
UNDERLINE: "\x1b[4m",
|
|
@@ -49,7 +116,8 @@ const createAnsi = ({
|
|
|
49
116
|
if (text === "") {
|
|
50
117
|
return text;
|
|
51
118
|
}
|
|
52
|
-
|
|
119
|
+
const ansiEscapeCodeForEffect = effect;
|
|
120
|
+
return "".concat(ansiEscapeCodeForEffect).concat(text).concat(RESET);
|
|
53
121
|
}
|
|
54
122
|
};
|
|
55
123
|
return ANSI;
|
|
@@ -209,11 +277,11 @@ const groupDigits = (digits, {
|
|
|
209
277
|
if (digitCount < minimumDigits) {
|
|
210
278
|
return digits;
|
|
211
279
|
}
|
|
212
|
-
let digitsWithSeparator = digits.slice(-
|
|
213
|
-
let remainingDigits = digits.slice(0, -
|
|
280
|
+
let digitsWithSeparator = digits.slice(-3);
|
|
281
|
+
let remainingDigits = digits.slice(0, -3);
|
|
214
282
|
while (remainingDigits.length) {
|
|
215
|
-
const group = remainingDigits.slice(-
|
|
216
|
-
remainingDigits = remainingDigits.slice(0, -
|
|
283
|
+
const group = remainingDigits.slice(-3);
|
|
284
|
+
remainingDigits = remainingDigits.slice(0, -3);
|
|
217
285
|
digitsWithSeparator = "".concat(group, "_").concat(digitsWithSeparator);
|
|
218
286
|
}
|
|
219
287
|
return digitsWithSeparator;
|
|
@@ -1272,4 +1340,43 @@ const fillLeft = (value, biggestValue, char = " ") => {
|
|
|
1272
1340
|
return padded;
|
|
1273
1341
|
};
|
|
1274
1342
|
|
|
1275
|
-
|
|
1343
|
+
const createCallOrderer = () => {
|
|
1344
|
+
const queue = [];
|
|
1345
|
+
const callWhenPreviousExecutionAreDone = (executionIndex, callback) => {
|
|
1346
|
+
if (queue[executionIndex]) {
|
|
1347
|
+
throw new Error("".concat(executionIndex, " already used"));
|
|
1348
|
+
}
|
|
1349
|
+
let allBeforeAreDone = true;
|
|
1350
|
+
if (executionIndex > 0) {
|
|
1351
|
+
let beforeIndex = executionIndex - 1;
|
|
1352
|
+
do {
|
|
1353
|
+
const value = queue[beforeIndex];
|
|
1354
|
+
if (!value) {
|
|
1355
|
+
allBeforeAreDone = false;
|
|
1356
|
+
break;
|
|
1357
|
+
}
|
|
1358
|
+
} while (beforeIndex--);
|
|
1359
|
+
}
|
|
1360
|
+
if (!allBeforeAreDone) {
|
|
1361
|
+
queue[executionIndex] = callback;
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
queue[executionIndex] = true;
|
|
1365
|
+
callback();
|
|
1366
|
+
let afterIndex = executionIndex + 1;
|
|
1367
|
+
while (afterIndex < queue.length) {
|
|
1368
|
+
const value = queue[afterIndex];
|
|
1369
|
+
if (value === undefined) {
|
|
1370
|
+
break;
|
|
1371
|
+
}
|
|
1372
|
+
if (typeof value === "function") {
|
|
1373
|
+
queue[afterIndex] = true;
|
|
1374
|
+
value();
|
|
1375
|
+
}
|
|
1376
|
+
afterIndex++;
|
|
1377
|
+
}
|
|
1378
|
+
};
|
|
1379
|
+
return callWhenPreviousExecutionAreDone;
|
|
1380
|
+
};
|
|
1381
|
+
|
|
1382
|
+
export { ANSI, UNICODE, createCallOrderer, createDetailedMessage, distributePercentages, generateContentFrame, humanize, humanizeDuration, humanizeEllapsedTime, humanizeFileSize, humanizeMemory, humanizeMethodSymbol };
|
|
@@ -1,42 +1,89 @@
|
|
|
1
|
-
import { createSupportsColor, isUnicodeSupported, clearTerminal, eraseLines } from "./
|
|
2
|
-
import
|
|
1
|
+
import { createSupportsColor, isUnicodeSupported, stripAnsi, emojiRegex, eastAsianWidth, clearTerminal, eraseLines } from "./jsenv_humanize_node_modules.js";
|
|
2
|
+
import { stripVTControlCharacters } from "node:util";
|
|
3
3
|
import "node:process";
|
|
4
4
|
import "node:os";
|
|
5
5
|
import "node:tty";
|
|
6
6
|
|
|
7
7
|
const createDetailedMessage = (message, details = {}) => {
|
|
8
|
-
let
|
|
8
|
+
let text = `${message}`;
|
|
9
|
+
const namedSectionsText = renderNamedSections(details);
|
|
10
|
+
if (namedSectionsText) {
|
|
11
|
+
text += `
|
|
12
|
+
${namedSectionsText}`;
|
|
13
|
+
}
|
|
14
|
+
return text;
|
|
15
|
+
};
|
|
9
16
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
const renderNamedSections = (namedSections) => {
|
|
18
|
+
let text = "";
|
|
19
|
+
let keys = Object.keys(namedSections);
|
|
20
|
+
for (const key of keys) {
|
|
21
|
+
const isLastKey = key === keys[keys.length - 1];
|
|
22
|
+
const value = namedSections[key];
|
|
23
|
+
text += `--- ${key} ---
|
|
14
24
|
${
|
|
15
25
|
Array.isArray(value)
|
|
16
26
|
? value.join(`
|
|
17
27
|
`)
|
|
18
28
|
: value
|
|
19
29
|
}`;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
30
|
+
if (!isLastKey) {
|
|
31
|
+
text += "\n";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return text;
|
|
23
35
|
};
|
|
24
36
|
|
|
25
37
|
// https://github.com/Marak/colors.js/blob/master/lib/styles.js
|
|
26
38
|
// https://stackoverflow.com/a/75985833/2634179
|
|
27
39
|
const RESET = "\x1b[0m";
|
|
28
40
|
|
|
41
|
+
const RED = "red";
|
|
42
|
+
const GREEN = "green";
|
|
43
|
+
const YELLOW = "yellow";
|
|
44
|
+
const BLUE = "blue";
|
|
45
|
+
const MAGENTA = "magenta";
|
|
46
|
+
const CYAN = "cyan";
|
|
47
|
+
const GREY = "grey";
|
|
48
|
+
const WHITE = "white";
|
|
49
|
+
const BLACK = "black";
|
|
50
|
+
|
|
51
|
+
const TEXT_COLOR_ANSI_CODES = {
|
|
52
|
+
[RED]: "\x1b[31m",
|
|
53
|
+
[GREEN]: "\x1b[32m",
|
|
54
|
+
[YELLOW]: "\x1b[33m",
|
|
55
|
+
[BLUE]: "\x1b[34m",
|
|
56
|
+
[MAGENTA]: "\x1b[35m",
|
|
57
|
+
[CYAN]: "\x1b[36m",
|
|
58
|
+
[GREY]: "\x1b[90m",
|
|
59
|
+
[WHITE]: "\x1b[37m",
|
|
60
|
+
[BLACK]: "\x1b[30m",
|
|
61
|
+
};
|
|
62
|
+
const BACKGROUND_COLOR_ANSI_CODES = {
|
|
63
|
+
[RED]: "\x1b[41m",
|
|
64
|
+
[GREEN]: "\x1b[42m",
|
|
65
|
+
[YELLOW]: "\x1b[43m",
|
|
66
|
+
[BLUE]: "\x1b[44m",
|
|
67
|
+
[MAGENTA]: "\x1b[45m",
|
|
68
|
+
[CYAN]: "\x1b[46m",
|
|
69
|
+
[GREY]: "\x1b[100m",
|
|
70
|
+
[WHITE]: "\x1b[47m",
|
|
71
|
+
[BLACK]: "\x1b[40m",
|
|
72
|
+
};
|
|
73
|
+
|
|
29
74
|
const createAnsi = ({ supported }) => {
|
|
30
75
|
const ANSI = {
|
|
31
76
|
supported,
|
|
32
77
|
|
|
33
|
-
RED
|
|
34
|
-
GREEN
|
|
35
|
-
YELLOW
|
|
36
|
-
BLUE
|
|
37
|
-
MAGENTA
|
|
38
|
-
CYAN
|
|
39
|
-
GREY
|
|
78
|
+
RED,
|
|
79
|
+
GREEN,
|
|
80
|
+
YELLOW,
|
|
81
|
+
BLUE,
|
|
82
|
+
MAGENTA,
|
|
83
|
+
CYAN,
|
|
84
|
+
GREY,
|
|
85
|
+
WHITE,
|
|
86
|
+
BLACK,
|
|
40
87
|
color: (text, color) => {
|
|
41
88
|
if (!ANSI.supported) {
|
|
42
89
|
return text;
|
|
@@ -48,7 +95,29 @@ const createAnsi = ({ supported }) => {
|
|
|
48
95
|
// cannot set color of blank chars
|
|
49
96
|
return text;
|
|
50
97
|
}
|
|
51
|
-
|
|
98
|
+
const ansiEscapeCodeForTextColor = TEXT_COLOR_ANSI_CODES[color];
|
|
99
|
+
if (!ansiEscapeCodeForTextColor) {
|
|
100
|
+
return text;
|
|
101
|
+
}
|
|
102
|
+
return `${ansiEscapeCodeForTextColor}${text}${RESET}`;
|
|
103
|
+
},
|
|
104
|
+
backgroundColor: (text, color) => {
|
|
105
|
+
if (!ANSI.supported) {
|
|
106
|
+
return text;
|
|
107
|
+
}
|
|
108
|
+
if (!color) {
|
|
109
|
+
return text;
|
|
110
|
+
}
|
|
111
|
+
if (typeof text === "string" && text.trim() === "") {
|
|
112
|
+
// cannot set background color of blank chars
|
|
113
|
+
return text;
|
|
114
|
+
}
|
|
115
|
+
const ansiEscapeCodeForBackgroundColor =
|
|
116
|
+
BACKGROUND_COLOR_ANSI_CODES[color];
|
|
117
|
+
if (!ansiEscapeCodeForBackgroundColor) {
|
|
118
|
+
return text;
|
|
119
|
+
}
|
|
120
|
+
return `${ansiEscapeCodeForBackgroundColor}${text}${RESET}`;
|
|
52
121
|
},
|
|
53
122
|
|
|
54
123
|
BOLD: "\x1b[1m",
|
|
@@ -65,7 +134,8 @@ const createAnsi = ({ supported }) => {
|
|
|
65
134
|
if (text === "") {
|
|
66
135
|
return text;
|
|
67
136
|
}
|
|
68
|
-
|
|
137
|
+
const ansiEscapeCodeForEffect = effect;
|
|
138
|
+
return `${ansiEscapeCodeForEffect}${text}${RESET}`;
|
|
69
139
|
},
|
|
70
140
|
};
|
|
71
141
|
|
|
@@ -227,11 +297,11 @@ const groupDigits = (digits, { minimumDigits, groupLength }) => {
|
|
|
227
297
|
return digits;
|
|
228
298
|
}
|
|
229
299
|
|
|
230
|
-
let digitsWithSeparator = digits.slice(-
|
|
231
|
-
let remainingDigits = digits.slice(0, -
|
|
300
|
+
let digitsWithSeparator = digits.slice(-3);
|
|
301
|
+
let remainingDigits = digits.slice(0, -3);
|
|
232
302
|
while (remainingDigits.length) {
|
|
233
|
-
const group = remainingDigits.slice(-
|
|
234
|
-
remainingDigits = remainingDigits.slice(0, -
|
|
303
|
+
const group = remainingDigits.slice(-3);
|
|
304
|
+
remainingDigits = remainingDigits.slice(0, -3);
|
|
235
305
|
digitsWithSeparator = `${group}_${digitsWithSeparator}`;
|
|
236
306
|
}
|
|
237
307
|
return digitsWithSeparator;
|
|
@@ -1297,6 +1367,119 @@ const fillLeft = (value, biggestValue, char = " ") => {
|
|
|
1297
1367
|
return padded;
|
|
1298
1368
|
};
|
|
1299
1369
|
|
|
1370
|
+
const createCallOrderer = () => {
|
|
1371
|
+
const queue = [];
|
|
1372
|
+
const callWhenPreviousExecutionAreDone = (executionIndex, callback) => {
|
|
1373
|
+
if (queue[executionIndex]) {
|
|
1374
|
+
throw new Error(`${executionIndex} already used`);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
let allBeforeAreDone = true;
|
|
1378
|
+
if (executionIndex > 0) {
|
|
1379
|
+
let beforeIndex = executionIndex - 1;
|
|
1380
|
+
do {
|
|
1381
|
+
const value = queue[beforeIndex];
|
|
1382
|
+
if (!value) {
|
|
1383
|
+
allBeforeAreDone = false;
|
|
1384
|
+
break;
|
|
1385
|
+
}
|
|
1386
|
+
} while (beforeIndex--);
|
|
1387
|
+
}
|
|
1388
|
+
if (!allBeforeAreDone) {
|
|
1389
|
+
queue[executionIndex] = callback;
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
queue[executionIndex] = true;
|
|
1393
|
+
callback();
|
|
1394
|
+
let afterIndex = executionIndex + 1;
|
|
1395
|
+
while (afterIndex < queue.length) {
|
|
1396
|
+
const value = queue[afterIndex];
|
|
1397
|
+
if (value === undefined) {
|
|
1398
|
+
break;
|
|
1399
|
+
}
|
|
1400
|
+
if (typeof value === "function") {
|
|
1401
|
+
queue[afterIndex] = true;
|
|
1402
|
+
value();
|
|
1403
|
+
}
|
|
1404
|
+
afterIndex++;
|
|
1405
|
+
}
|
|
1406
|
+
};
|
|
1407
|
+
return callWhenPreviousExecutionAreDone;
|
|
1408
|
+
};
|
|
1409
|
+
|
|
1410
|
+
const renderBigSection = (params) => {
|
|
1411
|
+
return renderSection({
|
|
1412
|
+
width: 45,
|
|
1413
|
+
...params,
|
|
1414
|
+
});
|
|
1415
|
+
};
|
|
1416
|
+
|
|
1417
|
+
const renderSection = ({
|
|
1418
|
+
title,
|
|
1419
|
+
content,
|
|
1420
|
+
dashColor = ANSI.GREY,
|
|
1421
|
+
width = 38,
|
|
1422
|
+
bottomSeparator = true,
|
|
1423
|
+
}) => {
|
|
1424
|
+
let section = "";
|
|
1425
|
+
|
|
1426
|
+
if (title) {
|
|
1427
|
+
const titleWidth = stripAnsi(title).length;
|
|
1428
|
+
const minWidthRequired = `--- … ---`.length;
|
|
1429
|
+
const needsTruncate = titleWidth + minWidthRequired >= width;
|
|
1430
|
+
if (needsTruncate) {
|
|
1431
|
+
const titleTruncated = title.slice(0, width - minWidthRequired);
|
|
1432
|
+
const leftDashes = ANSI.color("---", dashColor);
|
|
1433
|
+
const rightDashes = ANSI.color("---", dashColor);
|
|
1434
|
+
section += `${leftDashes} ${titleTruncated}… ${rightDashes}`;
|
|
1435
|
+
} else {
|
|
1436
|
+
const remainingWidth = width - titleWidth - 2; // 2 for spaces around the title
|
|
1437
|
+
const dashLeftCount = Math.floor(remainingWidth / 2);
|
|
1438
|
+
const dashRightCount = remainingWidth - dashLeftCount;
|
|
1439
|
+
const leftDashes = ANSI.color("-".repeat(dashLeftCount), dashColor);
|
|
1440
|
+
const rightDashes = ANSI.color("-".repeat(dashRightCount), dashColor);
|
|
1441
|
+
section += `${leftDashes} ${title} ${rightDashes}`;
|
|
1442
|
+
}
|
|
1443
|
+
section += "\n";
|
|
1444
|
+
} else {
|
|
1445
|
+
const topDashes = ANSI.color(`-`.repeat(width), dashColor);
|
|
1446
|
+
section += topDashes;
|
|
1447
|
+
section += "\n";
|
|
1448
|
+
}
|
|
1449
|
+
section += `${content}`;
|
|
1450
|
+
if (bottomSeparator) {
|
|
1451
|
+
section += "\n";
|
|
1452
|
+
const bottomDashes = ANSI.color(`-`.repeat(width), dashColor);
|
|
1453
|
+
section += bottomDashes;
|
|
1454
|
+
}
|
|
1455
|
+
return section;
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
const renderDetails = (data) => {
|
|
1459
|
+
const details = [];
|
|
1460
|
+
for (const key of Object.keys(data)) {
|
|
1461
|
+
const value = data[key];
|
|
1462
|
+
let valueString = "";
|
|
1463
|
+
valueString += ANSI.color(`${key}:`, ANSI.GREY);
|
|
1464
|
+
const useNonGreyAnsiColor =
|
|
1465
|
+
typeof value === "string" && value.includes("\x1b");
|
|
1466
|
+
valueString += " ";
|
|
1467
|
+
valueString += useNonGreyAnsiColor
|
|
1468
|
+
? value
|
|
1469
|
+
: ANSI.color(String(value), ANSI.GREY);
|
|
1470
|
+
details.push(valueString);
|
|
1471
|
+
}
|
|
1472
|
+
if (details.length === 0) {
|
|
1473
|
+
return "";
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
let string = "";
|
|
1477
|
+
string += ` ${ANSI.color("(", ANSI.GREY)}`;
|
|
1478
|
+
string += details.join(ANSI.color(", ", ANSI.GREY));
|
|
1479
|
+
string += ANSI.color(")", ANSI.GREY);
|
|
1480
|
+
return string;
|
|
1481
|
+
};
|
|
1482
|
+
|
|
1300
1483
|
const LOG_LEVEL_OFF = "off";
|
|
1301
1484
|
|
|
1302
1485
|
const LOG_LEVEL_DEBUG = "debug";
|
|
@@ -1385,6 +1568,101 @@ const error = (...args) => console.error(...args);
|
|
|
1385
1568
|
|
|
1386
1569
|
const errorDisabled = () => {};
|
|
1387
1570
|
|
|
1571
|
+
const createMeasureTextWidth = ({ stripAnsi }) => {
|
|
1572
|
+
const segmenter = new Intl.Segmenter();
|
|
1573
|
+
const defaultIgnorableCodePointRegex = /^\p{Default_Ignorable_Code_Point}$/u;
|
|
1574
|
+
|
|
1575
|
+
const measureTextWidth = (
|
|
1576
|
+
string,
|
|
1577
|
+
{
|
|
1578
|
+
ambiguousIsNarrow = true,
|
|
1579
|
+
countAnsiEscapeCodes = false,
|
|
1580
|
+
skipEmojis = false,
|
|
1581
|
+
} = {},
|
|
1582
|
+
) => {
|
|
1583
|
+
if (typeof string !== "string" || string.length === 0) {
|
|
1584
|
+
return 0;
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
if (!countAnsiEscapeCodes) {
|
|
1588
|
+
string = stripAnsi(string);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
if (string.length === 0) {
|
|
1592
|
+
return 0;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
let width = 0;
|
|
1596
|
+
const eastAsianWidthOptions = { ambiguousAsWide: !ambiguousIsNarrow };
|
|
1597
|
+
|
|
1598
|
+
for (const { segment: character } of segmenter.segment(string)) {
|
|
1599
|
+
const codePoint = character.codePointAt(0);
|
|
1600
|
+
|
|
1601
|
+
// Ignore control characters
|
|
1602
|
+
if (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f)) {
|
|
1603
|
+
continue;
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
// Ignore zero-width characters
|
|
1607
|
+
if (
|
|
1608
|
+
(codePoint >= 0x20_0b && codePoint <= 0x20_0f) || // Zero-width space, non-joiner, joiner, left-to-right mark, right-to-left mark
|
|
1609
|
+
codePoint === 0xfe_ff // Zero-width no-break space
|
|
1610
|
+
) {
|
|
1611
|
+
continue;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
// Ignore combining characters
|
|
1615
|
+
if (
|
|
1616
|
+
(codePoint >= 0x3_00 && codePoint <= 0x3_6f) || // Combining diacritical marks
|
|
1617
|
+
(codePoint >= 0x1a_b0 && codePoint <= 0x1a_ff) || // Combining diacritical marks extended
|
|
1618
|
+
(codePoint >= 0x1d_c0 && codePoint <= 0x1d_ff) || // Combining diacritical marks supplement
|
|
1619
|
+
(codePoint >= 0x20_d0 && codePoint <= 0x20_ff) || // Combining diacritical marks for symbols
|
|
1620
|
+
(codePoint >= 0xfe_20 && codePoint <= 0xfe_2f) // Combining half marks
|
|
1621
|
+
) {
|
|
1622
|
+
continue;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
// Ignore surrogate pairs
|
|
1626
|
+
if (codePoint >= 0xd8_00 && codePoint <= 0xdf_ff) {
|
|
1627
|
+
continue;
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
// Ignore variation selectors
|
|
1631
|
+
if (codePoint >= 0xfe_00 && codePoint <= 0xfe_0f) {
|
|
1632
|
+
continue;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
// This covers some of the above cases, but we still keep them for performance reasons.
|
|
1636
|
+
if (defaultIgnorableCodePointRegex.test(character)) {
|
|
1637
|
+
continue;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
if (!skipEmojis && emojiRegex().test(character)) {
|
|
1641
|
+
if (process.env.CAPTURING_SIDE_EFFECTS) {
|
|
1642
|
+
if (character === "✔️") {
|
|
1643
|
+
width += 2;
|
|
1644
|
+
continue;
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
width += measureTextWidth(character, {
|
|
1648
|
+
skipEmojis: true,
|
|
1649
|
+
countAnsiEscapeCodes: true, // to skip call to stripAnsi
|
|
1650
|
+
});
|
|
1651
|
+
continue;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
width += eastAsianWidth(codePoint, eastAsianWidthOptions);
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
return width;
|
|
1658
|
+
};
|
|
1659
|
+
return measureTextWidth;
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1662
|
+
const measureTextWidth = createMeasureTextWidth({
|
|
1663
|
+
stripAnsi: stripVTControlCharacters,
|
|
1664
|
+
});
|
|
1665
|
+
|
|
1388
1666
|
/*
|
|
1389
1667
|
* see also https://github.com/vadimdemedes/ink
|
|
1390
1668
|
*/
|
|
@@ -1420,7 +1698,7 @@ const createDynamicLog = ({
|
|
|
1420
1698
|
const logLines = lastOutput.split(/\r\n|\r|\n/);
|
|
1421
1699
|
let visualLineCount = 0;
|
|
1422
1700
|
for (const logLine of logLines) {
|
|
1423
|
-
const width =
|
|
1701
|
+
const width = measureTextWidth(logLine);
|
|
1424
1702
|
if (width === 0) {
|
|
1425
1703
|
visualLineCount++;
|
|
1426
1704
|
} else {
|
|
@@ -1485,7 +1763,8 @@ const createDynamicLog = ({
|
|
|
1485
1763
|
update("");
|
|
1486
1764
|
|
|
1487
1765
|
writing = true;
|
|
1488
|
-
callback();
|
|
1766
|
+
callback(update);
|
|
1767
|
+
lastOutput = "";
|
|
1489
1768
|
writing = false;
|
|
1490
1769
|
|
|
1491
1770
|
update(ouputAfterCallback);
|
|
@@ -1685,4 +1964,4 @@ const createTaskLog = (
|
|
|
1685
1964
|
};
|
|
1686
1965
|
};
|
|
1687
1966
|
|
|
1688
|
-
export { ANSI, UNICODE, createDetailedMessage, createDynamicLog, createLogger, createTaskLog, distributePercentages, generateContentFrame, humanize, humanizeDuration, humanizeEllapsedTime, humanizeFileSize, humanizeMemory, humanizeMethodSymbol, startSpinner };
|
|
1967
|
+
export { ANSI, UNICODE, createCallOrderer, createDetailedMessage, createDynamicLog, createLogger, createTaskLog, distributePercentages, generateContentFrame, humanize, humanizeDuration, humanizeEllapsedTime, humanizeFileSize, humanizeMemory, humanizeMethodSymbol, renderBigSection, renderDetails, renderNamedSections, renderSection, startSpinner };
|