@jsenv/humanize 1.5.2 → 1.7.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 +539 -482
- package/dist/browser/jsenv_humanize_browser.js.map +76 -0
- package/dist/node/jsenv_humanize_node.js +58 -7
- package/dist/node/jsenv_humanize_node.js.map +97 -0
- package/dist/node/jsenv_humanize_node_modules.js +23 -15
- package/dist/node/jsenv_humanize_node_modules.js.map +21 -0
- package/package.json +20 -17
- package/src/_tests/byte/file_size.test.js +0 -18
- package/src/_tests/byte/memory.test.js +0 -11
- package/src/_tests/content_frame/content_frame.test.js +0 -156
- package/src/_tests/content_frame/snapshots/10_line_and_column_are_zero.txt +0 -2
- package/src/_tests/content_frame/snapshots/11_line_is_last.txt +0 -3
- package/src/_tests/content_frame/snapshots/1_basic.txt +0 -4
- package/src/_tests/content_frame/snapshots/2_basic_2.txt +0 -6
- package/src/_tests/content_frame/snapshots/3_empty_last_line.txt +0 -7
- package/src/_tests/content_frame/snapshots/4_no_column.txt +0 -3
- package/src/_tests/content_frame/snapshots/5_line_1_and_2_digits.txt +0 -3
- package/src/_tests/content_frame/snapshots/6_line_too_long_column_undefined.txt +0 -3
- package/src/_tests/content_frame/snapshots/7_line_too_long_column_near_start.txt +0 -4
- package/src/_tests/content_frame/snapshots/8_line_too_long_column_near_middle.txt +0 -4
- package/src/_tests/content_frame/snapshots/9_line_too_long_column_near_end.txt +0 -4
- package/src/_tests/js_value/_inspect.test.html +0 -22
- package/src/_tests/js_value/array.test.js +0 -72
- package/src/_tests/js_value/biginit.test.js +0 -35
- package/src/_tests/js_value/boolean.test.js +0 -45
- package/src/_tests/js_value/date.test.js +0 -15
- package/src/_tests/js_value/error.test.js +0 -33
- package/src/_tests/js_value/function.test.js +0 -51
- package/src/_tests/js_value/instance.test.js +0 -12
- package/src/_tests/js_value/null.test.js +0 -6
- package/src/_tests/js_value/number.test.js +0 -182
- package/src/_tests/js_value/object.test.js +0 -173
- package/src/_tests/js_value/regexp.test.js +0 -15
- package/src/_tests/js_value/string.test.js +0 -106
- package/src/_tests/js_value/symbol.test.js +0 -20
- package/src/_tests/js_value/undefined.test.js +0 -6
- package/src/_tests/log/log_long.test_manual.mjs +0 -39
- package/src/_tests/log/log_modified.test_manual.mjs +0 -7
- package/src/_tests/log/logger.test.mjs +0 -90
- package/src/_tests/log/spinner.duration.test_manual.mjs +0 -25
- package/src/_tests/log/spinner.test.mjs +0 -33
- package/src/_tests/log/spinner.test_manual.mjs +0 -15
- package/src/_tests/percentage/percentage_distribution.test.mjs +0 -89
- package/src/_tests/time/decimals.test.js +0 -119
- package/src/_tests/time/duration.test.js +0 -20
- package/src/_tests/time/ellapsed.test.js +0 -10
- package/src/ansi/ansi_browser.js +0 -3
- package/src/ansi/ansi_node.js +0 -13
- package/src/ansi/ansi_runtime_agnostic.js +0 -107
- package/src/byte/byte.js +0 -44
- package/src/content_frame/content_frame.js +0 -157
- package/src/error/error_to_html.js +0 -22
- package/src/error/error_to_markdown.js +0 -14
- package/src/js_value/array.js +0 -58
- package/src/js_value/bigint.js +0 -3
- package/src/js_value/bigint_object.js +0 -5
- package/src/js_value/boolean.js +0 -1
- package/src/js_value/boolean_object.js +0 -12
- package/src/js_value/constructor.js +0 -10
- package/src/js_value/date.js +0 -8
- package/src/js_value/error.js +0 -34
- package/src/js_value/function.js +0 -20
- package/src/js_value/humanize.js +0 -142
- package/src/js_value/null.js +0 -1
- package/src/js_value/number.js +0 -101
- package/src/js_value/number_object.js +0 -9
- package/src/js_value/object.js +0 -78
- package/src/js_value/regexp.js +0 -1
- package/src/js_value/string.js +0 -141
- package/src/js_value/string_object.js +0 -10
- package/src/js_value/symbol.js +0 -24
- package/src/js_value/undefined.js +0 -1
- package/src/log/LOG_LEVELS.js +0 -9
- package/src/log/call_orderer.js +0 -39
- package/src/log/detailed_message.js +0 -29
- package/src/log/details.js +0 -26
- package/src/log/dynamic_log.js +0 -186
- package/src/log/logger.js +0 -85
- package/src/log/section.js +0 -50
- package/src/log/spinner.js +0 -72
- package/src/log/task_log.js +0 -49
- package/src/main_browser.js +0 -13
- package/src/main_node.js +0 -24
- package/src/percentage/distribute_percentages.js +0 -53
- package/src/time/time.js +0 -151
- package/src/unicode/unicode_browser.js +0 -7
- package/src/unicode/unicode_node.js +0 -8
- package/src/unicode/unicode_runtime_agnostic.js +0 -56
- package/src/utils/decimals.js +0 -95
- package/src/utils/indentation.js +0 -38
package/src/log/logger.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LOG_LEVEL_DEBUG,
|
|
3
|
-
LOG_LEVEL_ERROR,
|
|
4
|
-
LOG_LEVEL_INFO,
|
|
5
|
-
LOG_LEVEL_OFF,
|
|
6
|
-
LOG_LEVEL_WARN,
|
|
7
|
-
} from "./LOG_LEVELS.js";
|
|
8
|
-
|
|
9
|
-
export const createLogger = ({ logLevel = LOG_LEVEL_INFO } = {}) => {
|
|
10
|
-
if (logLevel === LOG_LEVEL_DEBUG) {
|
|
11
|
-
return {
|
|
12
|
-
level: "debug",
|
|
13
|
-
levels: { debug: true, info: true, warn: true, error: true },
|
|
14
|
-
debug,
|
|
15
|
-
info,
|
|
16
|
-
warn,
|
|
17
|
-
error,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
if (logLevel === LOG_LEVEL_INFO) {
|
|
21
|
-
return {
|
|
22
|
-
level: "info",
|
|
23
|
-
levels: { debug: false, info: true, warn: true, error: true },
|
|
24
|
-
debug: debugDisabled,
|
|
25
|
-
info,
|
|
26
|
-
warn,
|
|
27
|
-
error,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
if (logLevel === LOG_LEVEL_WARN) {
|
|
31
|
-
return {
|
|
32
|
-
level: "warn",
|
|
33
|
-
levels: { debug: false, info: false, warn: true, error: true },
|
|
34
|
-
debug: debugDisabled,
|
|
35
|
-
info: infoDisabled,
|
|
36
|
-
warn,
|
|
37
|
-
error,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
if (logLevel === LOG_LEVEL_ERROR) {
|
|
41
|
-
return {
|
|
42
|
-
level: "error",
|
|
43
|
-
levels: { debug: false, info: false, warn: false, error: true },
|
|
44
|
-
debug: debugDisabled,
|
|
45
|
-
info: infoDisabled,
|
|
46
|
-
warn: warnDisabled,
|
|
47
|
-
error,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
if (logLevel === LOG_LEVEL_OFF) {
|
|
51
|
-
return {
|
|
52
|
-
level: "off",
|
|
53
|
-
levels: { debug: false, info: false, warn: false, error: false },
|
|
54
|
-
debug: debugDisabled,
|
|
55
|
-
info: infoDisabled,
|
|
56
|
-
warn: warnDisabled,
|
|
57
|
-
error: errorDisabled,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
throw new Error(`unexpected logLevel.
|
|
61
|
-
--- logLevel ---
|
|
62
|
-
${logLevel}
|
|
63
|
-
--- allowed log levels ---
|
|
64
|
-
${LOG_LEVEL_OFF}
|
|
65
|
-
${LOG_LEVEL_ERROR}
|
|
66
|
-
${LOG_LEVEL_WARN}
|
|
67
|
-
${LOG_LEVEL_INFO}
|
|
68
|
-
${LOG_LEVEL_DEBUG}`);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const debug = (...args) => console.debug(...args);
|
|
72
|
-
|
|
73
|
-
const debugDisabled = () => {};
|
|
74
|
-
|
|
75
|
-
const info = (...args) => console.info(...args);
|
|
76
|
-
|
|
77
|
-
const infoDisabled = () => {};
|
|
78
|
-
|
|
79
|
-
const warn = (...args) => console.warn(...args);
|
|
80
|
-
|
|
81
|
-
const warnDisabled = () => {};
|
|
82
|
-
|
|
83
|
-
const error = (...args) => console.error(...args);
|
|
84
|
-
|
|
85
|
-
const errorDisabled = () => {};
|
package/src/log/section.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import stripAnsi from "strip-ansi";
|
|
2
|
-
import { ANSI } from "../ansi/ansi_node.js";
|
|
3
|
-
|
|
4
|
-
export const renderBigSection = (params) => {
|
|
5
|
-
return renderSection({
|
|
6
|
-
width: 45,
|
|
7
|
-
...params,
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const renderSection = ({
|
|
12
|
-
title,
|
|
13
|
-
content,
|
|
14
|
-
dashColor = ANSI.GREY,
|
|
15
|
-
width = 38,
|
|
16
|
-
bottomSeparator = true,
|
|
17
|
-
}) => {
|
|
18
|
-
let section = "";
|
|
19
|
-
|
|
20
|
-
if (title) {
|
|
21
|
-
const titleWidth = stripAnsi(title).length;
|
|
22
|
-
const minWidthRequired = `--- … ---`.length;
|
|
23
|
-
const needsTruncate = titleWidth + minWidthRequired >= width;
|
|
24
|
-
if (needsTruncate) {
|
|
25
|
-
const titleTruncated = title.slice(0, width - minWidthRequired);
|
|
26
|
-
const leftDashes = ANSI.color("---", dashColor);
|
|
27
|
-
const rightDashes = ANSI.color("---", dashColor);
|
|
28
|
-
section += `${leftDashes} ${titleTruncated}… ${rightDashes}`;
|
|
29
|
-
} else {
|
|
30
|
-
const remainingWidth = width - titleWidth - 2; // 2 for spaces around the title
|
|
31
|
-
const dashLeftCount = Math.floor(remainingWidth / 2);
|
|
32
|
-
const dashRightCount = remainingWidth - dashLeftCount;
|
|
33
|
-
const leftDashes = ANSI.color("-".repeat(dashLeftCount), dashColor);
|
|
34
|
-
const rightDashes = ANSI.color("-".repeat(dashRightCount), dashColor);
|
|
35
|
-
section += `${leftDashes} ${title} ${rightDashes}`;
|
|
36
|
-
}
|
|
37
|
-
section += "\n";
|
|
38
|
-
} else {
|
|
39
|
-
const topDashes = ANSI.color(`-`.repeat(width), dashColor);
|
|
40
|
-
section += topDashes;
|
|
41
|
-
section += "\n";
|
|
42
|
-
}
|
|
43
|
-
section += `${content}`;
|
|
44
|
-
if (bottomSeparator) {
|
|
45
|
-
section += "\n";
|
|
46
|
-
const bottomDashes = ANSI.color(`-`.repeat(width), dashColor);
|
|
47
|
-
section += bottomDashes;
|
|
48
|
-
}
|
|
49
|
-
return section;
|
|
50
|
-
};
|
package/src/log/spinner.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { ANSI } from "../ansi/ansi_node.js";
|
|
2
|
-
|
|
3
|
-
export const startSpinner = ({
|
|
4
|
-
dynamicLog,
|
|
5
|
-
frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
|
|
6
|
-
fps = 20,
|
|
7
|
-
keepProcessAlive = false,
|
|
8
|
-
stopOnWriteFromOutside = true,
|
|
9
|
-
stopOnVerticalOverflow = true,
|
|
10
|
-
render = () => "",
|
|
11
|
-
effect = () => {},
|
|
12
|
-
animated = dynamicLog.stream.isTTY,
|
|
13
|
-
}) => {
|
|
14
|
-
let frameIndex = 0;
|
|
15
|
-
let interval;
|
|
16
|
-
let running = true;
|
|
17
|
-
|
|
18
|
-
const spinner = {
|
|
19
|
-
message: undefined,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const update = (message) => {
|
|
23
|
-
spinner.message = running
|
|
24
|
-
? `${frames[frameIndex]} ${message}\n`
|
|
25
|
-
: `${message}\n`;
|
|
26
|
-
return spinner.message;
|
|
27
|
-
};
|
|
28
|
-
spinner.update = update;
|
|
29
|
-
|
|
30
|
-
let cleanup;
|
|
31
|
-
if (animated && ANSI.supported) {
|
|
32
|
-
running = true;
|
|
33
|
-
cleanup = effect();
|
|
34
|
-
dynamicLog.update(update(render()));
|
|
35
|
-
|
|
36
|
-
interval = setInterval(() => {
|
|
37
|
-
frameIndex = frameIndex === frames.length - 1 ? 0 : frameIndex + 1;
|
|
38
|
-
dynamicLog.update(update(render()));
|
|
39
|
-
}, 1000 / fps);
|
|
40
|
-
if (!keepProcessAlive) {
|
|
41
|
-
interval.unref();
|
|
42
|
-
}
|
|
43
|
-
} else {
|
|
44
|
-
dynamicLog.update(update(render()));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const stop = (message) => {
|
|
48
|
-
running = false;
|
|
49
|
-
if (interval) {
|
|
50
|
-
clearInterval(interval);
|
|
51
|
-
interval = null;
|
|
52
|
-
}
|
|
53
|
-
if (cleanup) {
|
|
54
|
-
cleanup();
|
|
55
|
-
cleanup = null;
|
|
56
|
-
}
|
|
57
|
-
if (dynamicLog && message) {
|
|
58
|
-
dynamicLog.update(update(message));
|
|
59
|
-
dynamicLog = null;
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
spinner.stop = stop;
|
|
63
|
-
|
|
64
|
-
if (stopOnVerticalOverflow) {
|
|
65
|
-
dynamicLog.onVerticalOverflow = stop;
|
|
66
|
-
}
|
|
67
|
-
if (stopOnWriteFromOutside) {
|
|
68
|
-
dynamicLog.onWriteFromOutside = stop;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return spinner;
|
|
72
|
-
};
|
package/src/log/task_log.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { humanizeDuration } from "../time/time.js";
|
|
2
|
-
import { UNICODE } from "../unicode/unicode_node.js";
|
|
3
|
-
import { createDynamicLog } from "./dynamic_log.js";
|
|
4
|
-
import { startSpinner } from "./spinner.js";
|
|
5
|
-
|
|
6
|
-
export const createTaskLog = (
|
|
7
|
-
label,
|
|
8
|
-
{ disabled = false, animated = true, stopOnWriteFromOutside } = {},
|
|
9
|
-
) => {
|
|
10
|
-
if (disabled) {
|
|
11
|
-
return {
|
|
12
|
-
setRightText: () => {},
|
|
13
|
-
done: () => {},
|
|
14
|
-
happen: () => {},
|
|
15
|
-
fail: () => {},
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
if (animated && process.env.CAPTURING_SIDE_EFFECTS) {
|
|
19
|
-
animated = false;
|
|
20
|
-
}
|
|
21
|
-
const startMs = Date.now();
|
|
22
|
-
const dynamicLog = createDynamicLog();
|
|
23
|
-
let message = label;
|
|
24
|
-
const taskSpinner = startSpinner({
|
|
25
|
-
dynamicLog,
|
|
26
|
-
render: () => message,
|
|
27
|
-
stopOnWriteFromOutside,
|
|
28
|
-
animated,
|
|
29
|
-
});
|
|
30
|
-
return {
|
|
31
|
-
setRightText: (value) => {
|
|
32
|
-
message = `${label} ${value}`;
|
|
33
|
-
},
|
|
34
|
-
done: () => {
|
|
35
|
-
const msEllapsed = Date.now() - startMs;
|
|
36
|
-
taskSpinner.stop(
|
|
37
|
-
`${UNICODE.OK} ${label} (done in ${humanizeDuration(msEllapsed)})`,
|
|
38
|
-
);
|
|
39
|
-
},
|
|
40
|
-
happen: (message) => {
|
|
41
|
-
taskSpinner.stop(
|
|
42
|
-
`${UNICODE.INFO} ${message} (at ${new Date().toLocaleTimeString()})`,
|
|
43
|
-
);
|
|
44
|
-
},
|
|
45
|
-
fail: (message = `failed to ${label}`) => {
|
|
46
|
-
taskSpinner.stop(`${UNICODE.FAILURE} ${message}`);
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
};
|
package/src/main_browser.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// tslint:disable:ordered-imports
|
|
2
|
-
|
|
3
|
-
export { createDetailedMessage } from "./log/detailed_message.js";
|
|
4
|
-
export { ANSI } from "./ansi/ansi_browser.js";
|
|
5
|
-
export { UNICODE } from "./unicode/unicode_browser.js";
|
|
6
|
-
export { humanize, humanizeMethodSymbol } from "./js_value/humanize.js";
|
|
7
|
-
export { humanizeDuration, humanizeEllapsedTime } from "./time/time.js";
|
|
8
|
-
export { humanizeFileSize, humanizeMemory } from "./byte/byte.js";
|
|
9
|
-
export { distributePercentages } from "./percentage/distribute_percentages.js";
|
|
10
|
-
export { generateContentFrame } from "./content_frame/content_frame.js";
|
|
11
|
-
export { createCallOrderer } from "./log/call_orderer.js";
|
|
12
|
-
export { errorToMarkdown } from "./error/error_to_markdown.js";
|
|
13
|
-
export { errorToHTML } from "./error/error_to_html.js";
|
package/src/main_node.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// tslint:disable:ordered-imports
|
|
2
|
-
|
|
3
|
-
export {
|
|
4
|
-
createDetailedMessage,
|
|
5
|
-
renderNamedSections,
|
|
6
|
-
} from "./log/detailed_message.js";
|
|
7
|
-
export { ANSI } from "./ansi/ansi_node.js";
|
|
8
|
-
export { UNICODE } from "./unicode/unicode_node.js";
|
|
9
|
-
export { humanize, humanizeMethodSymbol } from "./js_value/humanize.js";
|
|
10
|
-
export { humanizeDuration, humanizeEllapsedTime } from "./time/time.js";
|
|
11
|
-
export { humanizeFileSize, humanizeMemory } from "./byte/byte.js";
|
|
12
|
-
export { distributePercentages } from "./percentage/distribute_percentages.js";
|
|
13
|
-
export { generateContentFrame } from "./content_frame/content_frame.js";
|
|
14
|
-
export { createCallOrderer } from "./log/call_orderer.js";
|
|
15
|
-
export { errorToMarkdown } from "./error/error_to_markdown.js";
|
|
16
|
-
export { errorToHTML } from "./error/error_to_html.js";
|
|
17
|
-
|
|
18
|
-
// node only
|
|
19
|
-
export { renderSection, renderBigSection } from "./log/section.js";
|
|
20
|
-
export { renderDetails } from "./log/details.js";
|
|
21
|
-
export { createLogger } from "./log/logger.js";
|
|
22
|
-
export { createDynamicLog } from "./log/dynamic_log.js";
|
|
23
|
-
export { startSpinner } from "./log/spinner.js";
|
|
24
|
-
export { createTaskLog } from "./log/task_log.js";
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { getPrecision, setRoundedPrecision } from "../utils/decimals.js";
|
|
2
|
-
|
|
3
|
-
export const distributePercentages = (
|
|
4
|
-
namedNumbers,
|
|
5
|
-
{ maxPrecisionHint = 2 } = {},
|
|
6
|
-
) => {
|
|
7
|
-
const numberNames = Object.keys(namedNumbers);
|
|
8
|
-
if (numberNames.length === 0) {
|
|
9
|
-
return {};
|
|
10
|
-
}
|
|
11
|
-
if (numberNames.length === 1) {
|
|
12
|
-
const firstNumberName = numberNames[0];
|
|
13
|
-
return { [firstNumberName]: "100 %" };
|
|
14
|
-
}
|
|
15
|
-
const numbers = numberNames.map((name) => namedNumbers[name]);
|
|
16
|
-
const total = numbers.reduce((sum, value) => sum + value, 0);
|
|
17
|
-
const ratios = numbers.map((number) => number / total);
|
|
18
|
-
const percentages = {};
|
|
19
|
-
ratios.pop();
|
|
20
|
-
ratios.forEach((ratio, index) => {
|
|
21
|
-
const percentage = ratio * 100;
|
|
22
|
-
percentages[numberNames[index]] = percentage;
|
|
23
|
-
});
|
|
24
|
-
const lowestPercentage = (1 / Math.pow(10, maxPrecisionHint)) * 100;
|
|
25
|
-
let precision = 0;
|
|
26
|
-
Object.keys(percentages).forEach((name) => {
|
|
27
|
-
const percentage = percentages[name];
|
|
28
|
-
if (percentage < lowestPercentage) {
|
|
29
|
-
// check the amout of meaningful decimals
|
|
30
|
-
// and that what we will use
|
|
31
|
-
const percentageRounded = setRoundedPrecision(percentage);
|
|
32
|
-
const percentagePrecision = getPrecision(percentageRounded);
|
|
33
|
-
if (percentagePrecision > precision) {
|
|
34
|
-
precision = percentagePrecision;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
let remainingPercentage = 100;
|
|
39
|
-
|
|
40
|
-
Object.keys(percentages).forEach((name) => {
|
|
41
|
-
const percentage = percentages[name];
|
|
42
|
-
const percentageAllocated = setRoundedPrecision(percentage, {
|
|
43
|
-
decimals: precision,
|
|
44
|
-
});
|
|
45
|
-
remainingPercentage -= percentageAllocated;
|
|
46
|
-
percentages[name] = percentageAllocated;
|
|
47
|
-
});
|
|
48
|
-
const lastName = numberNames[numberNames.length - 1];
|
|
49
|
-
percentages[lastName] = setRoundedPrecision(remainingPercentage, {
|
|
50
|
-
decimals: precision,
|
|
51
|
-
});
|
|
52
|
-
return percentages;
|
|
53
|
-
};
|
package/src/time/time.js
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import { setPrecision, setRoundedPrecision } from "../utils/decimals.js";
|
|
2
|
-
|
|
3
|
-
export const humanizeEllapsedTime = (ms, { short } = {}) => {
|
|
4
|
-
if (ms < 1000) {
|
|
5
|
-
return short ? "0s" : "0 second";
|
|
6
|
-
}
|
|
7
|
-
const { primary, remaining } = parseMs(ms);
|
|
8
|
-
if (!remaining) {
|
|
9
|
-
return inspectEllapsedUnit(primary, short);
|
|
10
|
-
}
|
|
11
|
-
return `${inspectEllapsedUnit(primary, short)} and ${inspectEllapsedUnit(
|
|
12
|
-
remaining,
|
|
13
|
-
short,
|
|
14
|
-
)}`;
|
|
15
|
-
};
|
|
16
|
-
const inspectEllapsedUnit = (unit, short) => {
|
|
17
|
-
const count =
|
|
18
|
-
unit.name === "second" ? Math.floor(unit.count) : Math.round(unit.count);
|
|
19
|
-
let name = unit.name;
|
|
20
|
-
if (short) {
|
|
21
|
-
name = unitShort[name];
|
|
22
|
-
if (count <= 1) {
|
|
23
|
-
return `${count}${name}`;
|
|
24
|
-
}
|
|
25
|
-
return `${count}${name}s`;
|
|
26
|
-
}
|
|
27
|
-
if (count <= 1) {
|
|
28
|
-
return `${count} ${name}`;
|
|
29
|
-
}
|
|
30
|
-
return `${count} ${name}s`;
|
|
31
|
-
};
|
|
32
|
-
const unitShort = {
|
|
33
|
-
year: "y",
|
|
34
|
-
month: "m",
|
|
35
|
-
week: "w",
|
|
36
|
-
day: "d",
|
|
37
|
-
hour: "h",
|
|
38
|
-
minute: "m",
|
|
39
|
-
second: "s",
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const humanizeDuration = (
|
|
43
|
-
ms,
|
|
44
|
-
{ short, rounded = true, decimals } = {},
|
|
45
|
-
) => {
|
|
46
|
-
// ignore ms below meaningfulMs so that:
|
|
47
|
-
// humanizeDuration(0.5) -> "0 second"
|
|
48
|
-
// humanizeDuration(1.1) -> "0.001 second" (and not "0.0011 second")
|
|
49
|
-
// This tool is meant to be read by humans and it would be barely readable to see
|
|
50
|
-
// "0.0001 second" (stands for 0.1 millisecond)
|
|
51
|
-
// yes we could return "0.1 millisecond" but we choosed consistency over precision
|
|
52
|
-
// so that the prefered unit is "second" (and does not become millisecond when ms is super small)
|
|
53
|
-
if (ms < 1) {
|
|
54
|
-
return short ? "0s" : "0 second";
|
|
55
|
-
}
|
|
56
|
-
const { primary, remaining } = parseMs(ms);
|
|
57
|
-
if (!remaining) {
|
|
58
|
-
return humanizeDurationUnit(primary, {
|
|
59
|
-
decimals:
|
|
60
|
-
decimals === undefined ? (primary.name === "second" ? 1 : 0) : decimals,
|
|
61
|
-
short,
|
|
62
|
-
rounded,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
return `${humanizeDurationUnit(primary, {
|
|
66
|
-
decimals: decimals === undefined ? 0 : decimals,
|
|
67
|
-
short,
|
|
68
|
-
rounded,
|
|
69
|
-
})} and ${humanizeDurationUnit(remaining, {
|
|
70
|
-
decimals: decimals === undefined ? 0 : decimals,
|
|
71
|
-
short,
|
|
72
|
-
rounded,
|
|
73
|
-
})}`;
|
|
74
|
-
};
|
|
75
|
-
const humanizeDurationUnit = (unit, { decimals, short, rounded }) => {
|
|
76
|
-
const count = rounded
|
|
77
|
-
? setRoundedPrecision(unit.count, { decimals })
|
|
78
|
-
: setPrecision(unit.count, { decimals });
|
|
79
|
-
let name = unit.name;
|
|
80
|
-
if (short) {
|
|
81
|
-
name = unitShort[name];
|
|
82
|
-
return `${count}${name}`;
|
|
83
|
-
}
|
|
84
|
-
if (count <= 1) {
|
|
85
|
-
return `${count} ${name}`;
|
|
86
|
-
}
|
|
87
|
-
return `${count} ${name}s`;
|
|
88
|
-
};
|
|
89
|
-
const MS_PER_UNITS = {
|
|
90
|
-
year: 31_557_600_000,
|
|
91
|
-
month: 2_629_000_000,
|
|
92
|
-
week: 604_800_000,
|
|
93
|
-
day: 86_400_000,
|
|
94
|
-
hour: 3_600_000,
|
|
95
|
-
minute: 60_000,
|
|
96
|
-
second: 1000,
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const parseMs = (ms) => {
|
|
100
|
-
const unitNames = Object.keys(MS_PER_UNITS);
|
|
101
|
-
const smallestUnitName = unitNames[unitNames.length - 1];
|
|
102
|
-
let firstUnitName = smallestUnitName;
|
|
103
|
-
let firstUnitCount = ms / MS_PER_UNITS[smallestUnitName];
|
|
104
|
-
const firstUnitIndex = unitNames.findIndex((unitName) => {
|
|
105
|
-
if (unitName === smallestUnitName) {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
const msPerUnit = MS_PER_UNITS[unitName];
|
|
109
|
-
const unitCount = Math.floor(ms / msPerUnit);
|
|
110
|
-
if (unitCount) {
|
|
111
|
-
firstUnitName = unitName;
|
|
112
|
-
firstUnitCount = unitCount;
|
|
113
|
-
return true;
|
|
114
|
-
}
|
|
115
|
-
return false;
|
|
116
|
-
});
|
|
117
|
-
if (firstUnitName === smallestUnitName) {
|
|
118
|
-
return {
|
|
119
|
-
primary: {
|
|
120
|
-
name: firstUnitName,
|
|
121
|
-
count: firstUnitCount,
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
const remainingMs = ms - firstUnitCount * MS_PER_UNITS[firstUnitName];
|
|
126
|
-
const remainingUnitName = unitNames[firstUnitIndex + 1];
|
|
127
|
-
const remainingUnitCount = remainingMs / MS_PER_UNITS[remainingUnitName];
|
|
128
|
-
// - 1 year and 1 second is too much information
|
|
129
|
-
// so we don't check the remaining units
|
|
130
|
-
// - 1 year and 0.0001 week is awful
|
|
131
|
-
// hence the if below
|
|
132
|
-
if (Math.round(remainingUnitCount) < 1) {
|
|
133
|
-
return {
|
|
134
|
-
primary: {
|
|
135
|
-
name: firstUnitName,
|
|
136
|
-
count: firstUnitCount,
|
|
137
|
-
},
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
// - 1 year and 1 month is great
|
|
141
|
-
return {
|
|
142
|
-
primary: {
|
|
143
|
-
name: firstUnitName,
|
|
144
|
-
count: firstUnitCount,
|
|
145
|
-
},
|
|
146
|
-
remaining: {
|
|
147
|
-
name: remainingUnitName,
|
|
148
|
-
count: remainingUnitCount,
|
|
149
|
-
},
|
|
150
|
-
};
|
|
151
|
-
};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import isUnicodeSupported from "is-unicode-supported";
|
|
2
|
-
import { ANSI } from "../ansi/ansi_node.js";
|
|
3
|
-
import { createUnicode } from "./unicode_runtime_agnostic.js";
|
|
4
|
-
|
|
5
|
-
export const UNICODE = createUnicode({
|
|
6
|
-
supported: process.env.FORCE_UNICODE === "1" || isUnicodeSupported(),
|
|
7
|
-
ANSI,
|
|
8
|
-
});
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// see also https://github.com/sindresorhus/figures
|
|
2
|
-
|
|
3
|
-
export const createUnicode = ({ supported, ANSI }) => {
|
|
4
|
-
const UNICODE = {
|
|
5
|
-
supported,
|
|
6
|
-
get COMMAND_RAW() {
|
|
7
|
-
return UNICODE.supported ? `❯` : `>`;
|
|
8
|
-
},
|
|
9
|
-
get OK_RAW() {
|
|
10
|
-
return UNICODE.supported ? `✔` : `√`;
|
|
11
|
-
},
|
|
12
|
-
get FAILURE_RAW() {
|
|
13
|
-
return UNICODE.supported ? `✖` : `×`;
|
|
14
|
-
},
|
|
15
|
-
get DEBUG_RAW() {
|
|
16
|
-
return UNICODE.supported ? `◆` : `♦`;
|
|
17
|
-
},
|
|
18
|
-
get INFO_RAW() {
|
|
19
|
-
return UNICODE.supported ? `ℹ` : `i`;
|
|
20
|
-
},
|
|
21
|
-
get WARNING_RAW() {
|
|
22
|
-
return UNICODE.supported ? `⚠` : `‼`;
|
|
23
|
-
},
|
|
24
|
-
get CIRCLE_CROSS_RAW() {
|
|
25
|
-
return UNICODE.supported ? `ⓧ` : `(×)`;
|
|
26
|
-
},
|
|
27
|
-
get CIRCLE_DOTTED_RAW() {
|
|
28
|
-
return UNICODE.supported ? `◌` : `*`;
|
|
29
|
-
},
|
|
30
|
-
get COMMAND() {
|
|
31
|
-
return ANSI.color(UNICODE.COMMAND_RAW, ANSI.GREY); // ANSI_MAGENTA)
|
|
32
|
-
},
|
|
33
|
-
get OK() {
|
|
34
|
-
return ANSI.color(UNICODE.OK_RAW, ANSI.GREEN);
|
|
35
|
-
},
|
|
36
|
-
get FAILURE() {
|
|
37
|
-
return ANSI.color(UNICODE.FAILURE_RAW, ANSI.RED);
|
|
38
|
-
},
|
|
39
|
-
get DEBUG() {
|
|
40
|
-
return ANSI.color(UNICODE.DEBUG_RAW, ANSI.GREY);
|
|
41
|
-
},
|
|
42
|
-
get INFO() {
|
|
43
|
-
return ANSI.color(UNICODE.INFO_RAW, ANSI.BLUE);
|
|
44
|
-
},
|
|
45
|
-
get WARNING() {
|
|
46
|
-
return ANSI.color(UNICODE.WARNING_RAW, ANSI.YELLOW);
|
|
47
|
-
},
|
|
48
|
-
get CIRCLE_CROSS() {
|
|
49
|
-
return ANSI.color(UNICODE.CIRCLE_CROSS_RAW, ANSI.RED);
|
|
50
|
-
},
|
|
51
|
-
get ELLIPSIS() {
|
|
52
|
-
return UNICODE.supported ? `…` : `...`;
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
return UNICODE;
|
|
56
|
-
};
|
package/src/utils/decimals.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
export const getPrecision = (number) => {
|
|
2
|
-
if (Math.floor(number) === number) return 0;
|
|
3
|
-
const [, decimals] = number.toString().split(".");
|
|
4
|
-
return decimals.length || 0;
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export const setRoundedPrecision = (
|
|
8
|
-
number,
|
|
9
|
-
{ decimals = 1, decimalsWhenSmall = decimals } = {},
|
|
10
|
-
) => {
|
|
11
|
-
return setDecimalsPrecision(number, {
|
|
12
|
-
decimals,
|
|
13
|
-
decimalsWhenSmall,
|
|
14
|
-
transform: Math.round,
|
|
15
|
-
});
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const setFlooredPrecision = (
|
|
19
|
-
number,
|
|
20
|
-
{ decimals = 1, decimalsWhenSmall = decimals } = {},
|
|
21
|
-
) => {
|
|
22
|
-
return setDecimalsPrecision(number, {
|
|
23
|
-
decimals,
|
|
24
|
-
decimalsWhenSmall,
|
|
25
|
-
transform: Math.floor,
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export const setCeiledPrecision = (
|
|
30
|
-
number,
|
|
31
|
-
{ decimals = 1, decimalsWhenSmall = decimals } = {},
|
|
32
|
-
) => {
|
|
33
|
-
return setDecimalsPrecision(number, {
|
|
34
|
-
decimals,
|
|
35
|
-
decimalsWhenSmall,
|
|
36
|
-
transform: Math.ceil,
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export const setPrecision = (
|
|
41
|
-
number,
|
|
42
|
-
{ decimals = 1, decimalsWhenSmall = decimals } = {},
|
|
43
|
-
) => {
|
|
44
|
-
return setDecimalsPrecision(number, {
|
|
45
|
-
decimals,
|
|
46
|
-
decimalsWhenSmall,
|
|
47
|
-
transform: parseInt,
|
|
48
|
-
});
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const setDecimalsPrecision = (
|
|
52
|
-
number,
|
|
53
|
-
{
|
|
54
|
-
transform,
|
|
55
|
-
decimals, // max decimals for number in [-Infinity, -1[]1, Infinity]
|
|
56
|
-
decimalsWhenSmall, // max decimals for number in [-1,1]
|
|
57
|
-
} = {},
|
|
58
|
-
) => {
|
|
59
|
-
if (number === 0) {
|
|
60
|
-
return 0;
|
|
61
|
-
}
|
|
62
|
-
let numberCandidate = Math.abs(number);
|
|
63
|
-
if (numberCandidate < 1) {
|
|
64
|
-
const integerGoal = Math.pow(10, decimalsWhenSmall - 1);
|
|
65
|
-
let i = 1;
|
|
66
|
-
while (numberCandidate < integerGoal) {
|
|
67
|
-
numberCandidate *= 10;
|
|
68
|
-
i *= 10;
|
|
69
|
-
}
|
|
70
|
-
const asInteger = transform(numberCandidate);
|
|
71
|
-
const asFloat = asInteger / i;
|
|
72
|
-
return number < 0 ? -asFloat : asFloat;
|
|
73
|
-
}
|
|
74
|
-
const coef = Math.pow(10, decimals);
|
|
75
|
-
const numberMultiplied = (number + Number.EPSILON) * coef;
|
|
76
|
-
const asInteger = transform(numberMultiplied);
|
|
77
|
-
const asFloat = asInteger / coef;
|
|
78
|
-
return number < 0 ? -asFloat : asFloat;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// https://www.codingem.com/javascript-how-to-limit-decimal-places/
|
|
82
|
-
// export const roundNumber = (number, maxDecimals) => {
|
|
83
|
-
// const decimalsExp = Math.pow(10, maxDecimals)
|
|
84
|
-
// const numberRoundInt = Math.round(decimalsExp * (number + Number.EPSILON))
|
|
85
|
-
// const numberRoundFloat = numberRoundInt / decimalsExp
|
|
86
|
-
// return numberRoundFloat
|
|
87
|
-
// }
|
|
88
|
-
|
|
89
|
-
// export const setPrecision = (number, precision) => {
|
|
90
|
-
// if (Math.floor(number) === number) return number
|
|
91
|
-
// const [int, decimals] = number.toString().split(".")
|
|
92
|
-
// if (precision <= 0) return int
|
|
93
|
-
// const numberTruncated = `${int}.${decimals.slice(0, precision)}`
|
|
94
|
-
// return numberTruncated
|
|
95
|
-
// }
|