@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/humanize",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Generate messages meant to read by humans",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -32,13 +32,14 @@
|
|
|
32
32
|
"/dist/",
|
|
33
33
|
"/src/"
|
|
34
34
|
],
|
|
35
|
+
"sideEffects": false,
|
|
35
36
|
"scripts": {
|
|
36
37
|
"build": "node ./scripts/build.mjs",
|
|
37
38
|
"prepublishOnly": "npm run build"
|
|
38
39
|
},
|
|
39
40
|
"dependencies": {
|
|
40
|
-
"
|
|
41
|
-
"ansi
|
|
41
|
+
"ansi-escapes": "7.0.0",
|
|
42
|
+
"strip-ansi": "7.1.0"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
45
|
"is-unicode-supported": "2.1.0",
|
|
@@ -2,17 +2,52 @@
|
|
|
2
2
|
// https://stackoverflow.com/a/75985833/2634179
|
|
3
3
|
const RESET = "\x1b[0m";
|
|
4
4
|
|
|
5
|
+
const RED = "red";
|
|
6
|
+
const GREEN = "green";
|
|
7
|
+
const YELLOW = "yellow";
|
|
8
|
+
const BLUE = "blue";
|
|
9
|
+
const MAGENTA = "magenta";
|
|
10
|
+
const CYAN = "cyan";
|
|
11
|
+
const GREY = "grey";
|
|
12
|
+
const WHITE = "white";
|
|
13
|
+
const BLACK = "black";
|
|
14
|
+
|
|
15
|
+
const TEXT_COLOR_ANSI_CODES = {
|
|
16
|
+
[RED]: "\x1b[31m",
|
|
17
|
+
[GREEN]: "\x1b[32m",
|
|
18
|
+
[YELLOW]: "\x1b[33m",
|
|
19
|
+
[BLUE]: "\x1b[34m",
|
|
20
|
+
[MAGENTA]: "\x1b[35m",
|
|
21
|
+
[CYAN]: "\x1b[36m",
|
|
22
|
+
[GREY]: "\x1b[90m",
|
|
23
|
+
[WHITE]: "\x1b[37m",
|
|
24
|
+
[BLACK]: "\x1b[30m",
|
|
25
|
+
};
|
|
26
|
+
const BACKGROUND_COLOR_ANSI_CODES = {
|
|
27
|
+
[RED]: "\x1b[41m",
|
|
28
|
+
[GREEN]: "\x1b[42m",
|
|
29
|
+
[YELLOW]: "\x1b[43m",
|
|
30
|
+
[BLUE]: "\x1b[44m",
|
|
31
|
+
[MAGENTA]: "\x1b[45m",
|
|
32
|
+
[CYAN]: "\x1b[46m",
|
|
33
|
+
[GREY]: "\x1b[100m",
|
|
34
|
+
[WHITE]: "\x1b[47m",
|
|
35
|
+
[BLACK]: "\x1b[40m",
|
|
36
|
+
};
|
|
37
|
+
|
|
5
38
|
export const createAnsi = ({ supported }) => {
|
|
6
39
|
const ANSI = {
|
|
7
40
|
supported,
|
|
8
41
|
|
|
9
|
-
RED
|
|
10
|
-
GREEN
|
|
11
|
-
YELLOW
|
|
12
|
-
BLUE
|
|
13
|
-
MAGENTA
|
|
14
|
-
CYAN
|
|
15
|
-
GREY
|
|
42
|
+
RED,
|
|
43
|
+
GREEN,
|
|
44
|
+
YELLOW,
|
|
45
|
+
BLUE,
|
|
46
|
+
MAGENTA,
|
|
47
|
+
CYAN,
|
|
48
|
+
GREY,
|
|
49
|
+
WHITE,
|
|
50
|
+
BLACK,
|
|
16
51
|
color: (text, color) => {
|
|
17
52
|
if (!ANSI.supported) {
|
|
18
53
|
return text;
|
|
@@ -24,7 +59,29 @@ export const createAnsi = ({ supported }) => {
|
|
|
24
59
|
// cannot set color of blank chars
|
|
25
60
|
return text;
|
|
26
61
|
}
|
|
27
|
-
|
|
62
|
+
const ansiEscapeCodeForTextColor = TEXT_COLOR_ANSI_CODES[color];
|
|
63
|
+
if (!ansiEscapeCodeForTextColor) {
|
|
64
|
+
return text;
|
|
65
|
+
}
|
|
66
|
+
return `${ansiEscapeCodeForTextColor}${text}${RESET}`;
|
|
67
|
+
},
|
|
68
|
+
backgroundColor: (text, color) => {
|
|
69
|
+
if (!ANSI.supported) {
|
|
70
|
+
return text;
|
|
71
|
+
}
|
|
72
|
+
if (!color) {
|
|
73
|
+
return text;
|
|
74
|
+
}
|
|
75
|
+
if (typeof text === "string" && text.trim() === "") {
|
|
76
|
+
// cannot set background color of blank chars
|
|
77
|
+
return text;
|
|
78
|
+
}
|
|
79
|
+
const ansiEscapeCodeForBackgroundColor =
|
|
80
|
+
BACKGROUND_COLOR_ANSI_CODES[color];
|
|
81
|
+
if (!ansiEscapeCodeForBackgroundColor) {
|
|
82
|
+
return text;
|
|
83
|
+
}
|
|
84
|
+
return `${ansiEscapeCodeForBackgroundColor}${text}${RESET}`;
|
|
28
85
|
},
|
|
29
86
|
|
|
30
87
|
BOLD: "\x1b[1m",
|
|
@@ -41,7 +98,8 @@ export const createAnsi = ({ supported }) => {
|
|
|
41
98
|
if (text === "") {
|
|
42
99
|
return text;
|
|
43
100
|
}
|
|
44
|
-
|
|
101
|
+
const ansiEscapeCodeForEffect = effect;
|
|
102
|
+
return `${ansiEscapeCodeForEffect}${text}${RESET}`;
|
|
45
103
|
},
|
|
46
104
|
};
|
|
47
105
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const createCallOrderer = () => {
|
|
2
|
+
const queue = [];
|
|
3
|
+
const callWhenPreviousExecutionAreDone = (executionIndex, callback) => {
|
|
4
|
+
if (queue[executionIndex]) {
|
|
5
|
+
throw new Error(`${executionIndex} already used`);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let allBeforeAreDone = true;
|
|
9
|
+
if (executionIndex > 0) {
|
|
10
|
+
let beforeIndex = executionIndex - 1;
|
|
11
|
+
do {
|
|
12
|
+
const value = queue[beforeIndex];
|
|
13
|
+
if (!value) {
|
|
14
|
+
allBeforeAreDone = false;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
} while (beforeIndex--);
|
|
18
|
+
}
|
|
19
|
+
if (!allBeforeAreDone) {
|
|
20
|
+
queue[executionIndex] = callback;
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
queue[executionIndex] = true;
|
|
24
|
+
callback();
|
|
25
|
+
let afterIndex = executionIndex + 1;
|
|
26
|
+
while (afterIndex < queue.length) {
|
|
27
|
+
const value = queue[afterIndex];
|
|
28
|
+
if (value === undefined) {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === "function") {
|
|
32
|
+
queue[afterIndex] = true;
|
|
33
|
+
value();
|
|
34
|
+
}
|
|
35
|
+
afterIndex++;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
return callWhenPreviousExecutionAreDone;
|
|
39
|
+
};
|
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
export const createDetailedMessage = (message, details = {}) => {
|
|
2
|
-
let
|
|
2
|
+
let text = `${message}`;
|
|
3
|
+
const namedSectionsText = renderNamedSections(details);
|
|
4
|
+
if (namedSectionsText) {
|
|
5
|
+
text += `
|
|
6
|
+
${namedSectionsText}`;
|
|
7
|
+
}
|
|
8
|
+
return text;
|
|
9
|
+
};
|
|
3
10
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
11
|
+
export const renderNamedSections = (namedSections) => {
|
|
12
|
+
let text = "";
|
|
13
|
+
let keys = Object.keys(namedSections);
|
|
14
|
+
for (const key of keys) {
|
|
15
|
+
const isLastKey = key === keys[keys.length - 1];
|
|
16
|
+
const value = namedSections[key];
|
|
17
|
+
text += `--- ${key} ---
|
|
8
18
|
${
|
|
9
19
|
Array.isArray(value)
|
|
10
20
|
? value.join(`
|
|
11
21
|
`)
|
|
12
22
|
: value
|
|
13
23
|
}`;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
if (!isLastKey) {
|
|
25
|
+
text += "\n";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return text;
|
|
17
29
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ANSI } from "../ansi/ansi_node.js";
|
|
2
|
+
|
|
3
|
+
export const renderDetails = (data) => {
|
|
4
|
+
const details = [];
|
|
5
|
+
for (const key of Object.keys(data)) {
|
|
6
|
+
const value = data[key];
|
|
7
|
+
let valueString = "";
|
|
8
|
+
valueString += ANSI.color(`${key}:`, ANSI.GREY);
|
|
9
|
+
const useNonGreyAnsiColor =
|
|
10
|
+
typeof value === "string" && value.includes("\x1b");
|
|
11
|
+
valueString += " ";
|
|
12
|
+
valueString += useNonGreyAnsiColor
|
|
13
|
+
? value
|
|
14
|
+
: ANSI.color(String(value), ANSI.GREY);
|
|
15
|
+
details.push(valueString);
|
|
16
|
+
}
|
|
17
|
+
if (details.length === 0) {
|
|
18
|
+
return "";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let string = "";
|
|
22
|
+
string += ` ${ANSI.color("(", ANSI.GREY)}`;
|
|
23
|
+
string += details.join(ANSI.color(", ", ANSI.GREY));
|
|
24
|
+
string += ANSI.color(")", ANSI.GREY);
|
|
25
|
+
return string;
|
|
26
|
+
};
|
package/src/log/dynamic_log.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* see also https://github.com/vadimdemedes/ink
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { measureTextWidth } from "@jsenv/terminal-text-size";
|
|
5
6
|
import ansiEscapes from "ansi-escapes";
|
|
6
|
-
import stringWidth from "string-width";
|
|
7
7
|
|
|
8
8
|
export const createDynamicLog = ({
|
|
9
9
|
stream = process.stdout,
|
|
@@ -35,7 +35,7 @@ export const createDynamicLog = ({
|
|
|
35
35
|
const logLines = lastOutput.split(/\r\n|\r|\n/);
|
|
36
36
|
let visualLineCount = 0;
|
|
37
37
|
for (const logLine of logLines) {
|
|
38
|
-
const width =
|
|
38
|
+
const width = measureTextWidth(logLine);
|
|
39
39
|
if (width === 0) {
|
|
40
40
|
visualLineCount++;
|
|
41
41
|
} else {
|
|
@@ -100,7 +100,8 @@ export const createDynamicLog = ({
|
|
|
100
100
|
update("");
|
|
101
101
|
|
|
102
102
|
writing = true;
|
|
103
|
-
callback();
|
|
103
|
+
callback(update);
|
|
104
|
+
lastOutput = "";
|
|
104
105
|
writing = false;
|
|
105
106
|
|
|
106
107
|
update(ouputAfterCallback);
|
|
@@ -0,0 +1,50 @@
|
|
|
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/main_browser.js
CHANGED
|
@@ -8,3 +8,4 @@ export { humanizeDuration, humanizeEllapsedTime } from "./time/time.js";
|
|
|
8
8
|
export { humanizeFileSize, humanizeMemory } from "./byte/byte.js";
|
|
9
9
|
export { distributePercentages } from "./percentage/distribute_percentages.js";
|
|
10
10
|
export { generateContentFrame } from "./content_frame/content_frame.js";
|
|
11
|
+
export { createCallOrderer } from "./log/call_orderer.js";
|
package/src/main_node.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// tslint:disable:ordered-imports
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export {
|
|
4
|
+
createDetailedMessage,
|
|
5
|
+
renderNamedSections,
|
|
6
|
+
} from "./log/detailed_message.js";
|
|
4
7
|
export { ANSI } from "./ansi/ansi_node.js";
|
|
5
8
|
export { UNICODE } from "./unicode/unicode_node.js";
|
|
6
9
|
export { humanize, humanizeMethodSymbol } from "./js_value/humanize.js";
|
|
@@ -8,8 +11,11 @@ export { humanizeDuration, humanizeEllapsedTime } from "./time/time.js";
|
|
|
8
11
|
export { humanizeFileSize, humanizeMemory } from "./byte/byte.js";
|
|
9
12
|
export { distributePercentages } from "./percentage/distribute_percentages.js";
|
|
10
13
|
export { generateContentFrame } from "./content_frame/content_frame.js";
|
|
14
|
+
export { createCallOrderer } from "./log/call_orderer.js";
|
|
11
15
|
|
|
12
16
|
// node only
|
|
17
|
+
export { renderSection, renderBigSection } from "./log/section.js";
|
|
18
|
+
export { renderDetails } from "./log/details.js";
|
|
13
19
|
export { createLogger } from "./log/logger.js";
|
|
14
20
|
export { createDynamicLog } from "./log/dynamic_log.js";
|
|
15
21
|
export { startSpinner } from "./log/spinner.js";
|
package/dist/node/js/vendors.js
DELETED
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import process from "node:process";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import tty from "node:tty";
|
|
4
|
-
|
|
5
|
-
// From: https://github.com/sindresorhus/has-flag/blob/main/index.js
|
|
6
|
-
/// function hasFlag(flag, argv = globalThis.Deno?.args ?? process.argv) {
|
|
7
|
-
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process.argv) {
|
|
8
|
-
const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
|
|
9
|
-
const position = argv.indexOf(prefix + flag);
|
|
10
|
-
const terminatorPosition = argv.indexOf('--');
|
|
11
|
-
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const {env} = process;
|
|
15
|
-
|
|
16
|
-
let flagForceColor;
|
|
17
|
-
if (
|
|
18
|
-
hasFlag('no-color')
|
|
19
|
-
|| hasFlag('no-colors')
|
|
20
|
-
|| hasFlag('color=false')
|
|
21
|
-
|| hasFlag('color=never')
|
|
22
|
-
) {
|
|
23
|
-
flagForceColor = 0;
|
|
24
|
-
} else if (
|
|
25
|
-
hasFlag('color')
|
|
26
|
-
|| hasFlag('colors')
|
|
27
|
-
|| hasFlag('color=true')
|
|
28
|
-
|| hasFlag('color=always')
|
|
29
|
-
) {
|
|
30
|
-
flagForceColor = 1;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function envForceColor() {
|
|
34
|
-
if (!('FORCE_COLOR' in env)) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (env.FORCE_COLOR === 'true') {
|
|
39
|
-
return 1;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (env.FORCE_COLOR === 'false') {
|
|
43
|
-
return 0;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (env.FORCE_COLOR.length === 0) {
|
|
47
|
-
return 1;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const level = Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
51
|
-
|
|
52
|
-
if (![0, 1, 2, 3].includes(level)) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return level;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function translateLevel(level) {
|
|
60
|
-
if (level === 0) {
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
level,
|
|
66
|
-
hasBasic: true,
|
|
67
|
-
has256: level >= 2,
|
|
68
|
-
has16m: level >= 3,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {
|
|
73
|
-
const noFlagForceColor = envForceColor();
|
|
74
|
-
if (noFlagForceColor !== undefined) {
|
|
75
|
-
flagForceColor = noFlagForceColor;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
79
|
-
|
|
80
|
-
if (forceColor === 0) {
|
|
81
|
-
return 0;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (sniffFlags) {
|
|
85
|
-
if (hasFlag('color=16m')
|
|
86
|
-
|| hasFlag('color=full')
|
|
87
|
-
|| hasFlag('color=truecolor')) {
|
|
88
|
-
return 3;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (hasFlag('color=256')) {
|
|
92
|
-
return 2;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Check for Azure DevOps pipelines.
|
|
97
|
-
// Has to be above the `!streamIsTTY` check.
|
|
98
|
-
if ('TF_BUILD' in env && 'AGENT_NAME' in env) {
|
|
99
|
-
return 1;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (haveStream && !streamIsTTY && forceColor === undefined) {
|
|
103
|
-
return 0;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const min = forceColor || 0;
|
|
107
|
-
|
|
108
|
-
if (env.TERM === 'dumb') {
|
|
109
|
-
return min;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (process.platform === 'win32') {
|
|
113
|
-
// Windows 10 build 10586 is the first Windows release that supports 256 colors.
|
|
114
|
-
// Windows 10 build 14931 is the first release that supports 16m/TrueColor.
|
|
115
|
-
const osRelease = os.release().split('.');
|
|
116
|
-
if (
|
|
117
|
-
Number(osRelease[0]) >= 10
|
|
118
|
-
&& Number(osRelease[2]) >= 10_586
|
|
119
|
-
) {
|
|
120
|
-
return Number(osRelease[2]) >= 14_931 ? 3 : 2;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return 1;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if ('CI' in env) {
|
|
127
|
-
if (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => key in env)) {
|
|
128
|
-
return 3;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
|
|
132
|
-
return 1;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return min;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if ('TEAMCITY_VERSION' in env) {
|
|
139
|
-
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (env.COLORTERM === 'truecolor') {
|
|
143
|
-
return 3;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (env.TERM === 'xterm-kitty') {
|
|
147
|
-
return 3;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if ('TERM_PROGRAM' in env) {
|
|
151
|
-
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
|
|
152
|
-
|
|
153
|
-
switch (env.TERM_PROGRAM) {
|
|
154
|
-
case 'iTerm.app': {
|
|
155
|
-
return version >= 3 ? 3 : 2;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
case 'Apple_Terminal': {
|
|
159
|
-
return 2;
|
|
160
|
-
}
|
|
161
|
-
// No default
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (/-256(color)?$/i.test(env.TERM)) {
|
|
166
|
-
return 2;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
170
|
-
return 1;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if ('COLORTERM' in env) {
|
|
174
|
-
return 1;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return min;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function createSupportsColor(stream, options = {}) {
|
|
181
|
-
const level = _supportsColor(stream, {
|
|
182
|
-
streamIsTTY: stream && stream.isTTY,
|
|
183
|
-
...options,
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
return translateLevel(level);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
({
|
|
190
|
-
stdout: createSupportsColor({isTTY: tty.isatty(1)}),
|
|
191
|
-
stderr: createSupportsColor({isTTY: tty.isatty(2)}),
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
function isUnicodeSupported() {
|
|
195
|
-
const {env} = process;
|
|
196
|
-
const {TERM, TERM_PROGRAM} = env;
|
|
197
|
-
|
|
198
|
-
if (process.platform !== 'win32') {
|
|
199
|
-
return TERM !== 'linux'; // Linux console (kernel)
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return Boolean(env.WT_SESSION) // Windows Terminal
|
|
203
|
-
|| Boolean(env.TERMINUS_SUBLIME) // Terminus (<0.2.27)
|
|
204
|
-
|| env.ConEmuTask === '{cmd::Cmder}' // ConEmu and cmder
|
|
205
|
-
|| TERM_PROGRAM === 'Terminus-Sublime'
|
|
206
|
-
|| TERM_PROGRAM === 'vscode'
|
|
207
|
-
|| TERM === 'xterm-256color'
|
|
208
|
-
|| TERM === 'alacritty'
|
|
209
|
-
|| TERM === 'rxvt-unicode'
|
|
210
|
-
|| TERM === 'rxvt-unicode-256color'
|
|
211
|
-
|| env.TERMINAL_EMULATOR === 'JetBrains-JediTerm';
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/* globals WorkerGlobalScope, DedicatedWorkerGlobalScope, SharedWorkerGlobalScope, ServiceWorkerGlobalScope */
|
|
215
|
-
|
|
216
|
-
const isBrowser = globalThis.window?.document !== undefined;
|
|
217
|
-
|
|
218
|
-
globalThis.process?.versions?.node !== undefined;
|
|
219
|
-
|
|
220
|
-
globalThis.process?.versions?.bun !== undefined;
|
|
221
|
-
|
|
222
|
-
globalThis.Deno?.version?.deno !== undefined;
|
|
223
|
-
|
|
224
|
-
globalThis.process?.versions?.electron !== undefined;
|
|
225
|
-
|
|
226
|
-
globalThis.navigator?.userAgent?.includes('jsdom') === true;
|
|
227
|
-
|
|
228
|
-
typeof WorkerGlobalScope !== 'undefined' && globalThis instanceof WorkerGlobalScope;
|
|
229
|
-
|
|
230
|
-
typeof DedicatedWorkerGlobalScope !== 'undefined' && globalThis instanceof DedicatedWorkerGlobalScope;
|
|
231
|
-
|
|
232
|
-
typeof SharedWorkerGlobalScope !== 'undefined' && globalThis instanceof SharedWorkerGlobalScope;
|
|
233
|
-
|
|
234
|
-
typeof ServiceWorkerGlobalScope !== 'undefined' && globalThis instanceof ServiceWorkerGlobalScope;
|
|
235
|
-
|
|
236
|
-
// Note: I'm intentionally not DRYing up the other variables to keep them "lazy".
|
|
237
|
-
const platform = globalThis.navigator?.userAgentData?.platform;
|
|
238
|
-
|
|
239
|
-
platform === 'macOS'
|
|
240
|
-
|| globalThis.navigator?.platform === 'MacIntel' // Even on Apple silicon Macs.
|
|
241
|
-
|| globalThis.navigator?.userAgent?.includes(' Mac ') === true
|
|
242
|
-
|| globalThis.process?.platform === 'darwin';
|
|
243
|
-
|
|
244
|
-
platform === 'Windows'
|
|
245
|
-
|| globalThis.navigator?.platform === 'Win32'
|
|
246
|
-
|| globalThis.process?.platform === 'win32';
|
|
247
|
-
|
|
248
|
-
platform === 'Linux'
|
|
249
|
-
|| globalThis.navigator?.platform?.startsWith('Linux') === true
|
|
250
|
-
|| globalThis.navigator?.userAgent?.includes(' Linux ') === true
|
|
251
|
-
|| globalThis.process?.platform === 'linux';
|
|
252
|
-
|
|
253
|
-
platform === 'Android'
|
|
254
|
-
|| globalThis.navigator?.platform === 'Android'
|
|
255
|
-
|| globalThis.navigator?.userAgent?.includes(' Android ') === true
|
|
256
|
-
|| globalThis.process?.platform === 'android';
|
|
257
|
-
|
|
258
|
-
const ESC = '\u001B[';
|
|
259
|
-
|
|
260
|
-
!isBrowser && process.env.TERM_PROGRAM === 'Apple_Terminal';
|
|
261
|
-
const isWindows = !isBrowser && process.platform === 'win32';
|
|
262
|
-
|
|
263
|
-
isBrowser ? () => {
|
|
264
|
-
throw new Error('`process.cwd()` only works in Node.js, not the browser.');
|
|
265
|
-
} : process.cwd;
|
|
266
|
-
|
|
267
|
-
const cursorUp = (count = 1) => ESC + count + 'A';
|
|
268
|
-
|
|
269
|
-
const cursorLeft = ESC + 'G';
|
|
270
|
-
|
|
271
|
-
const eraseLines = count => {
|
|
272
|
-
let clear = '';
|
|
273
|
-
|
|
274
|
-
for (let i = 0; i < count; i++) {
|
|
275
|
-
clear += eraseLine + (i < count - 1 ? cursorUp() : '');
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (count) {
|
|
279
|
-
clear += cursorLeft;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
return clear;
|
|
283
|
-
};
|
|
284
|
-
const eraseLine = ESC + '2K';
|
|
285
|
-
const eraseScreen = ESC + '2J';
|
|
286
|
-
|
|
287
|
-
const clearTerminal = isWindows
|
|
288
|
-
? `${eraseScreen}${ESC}0f`
|
|
289
|
-
// 1. Erases the screen (Only done in case `2` is not supported)
|
|
290
|
-
// 2. Erases the whole screen including scrollback buffer
|
|
291
|
-
// 3. Moves cursor to the top-left position
|
|
292
|
-
// More info: https://www.real-world-systems.com/docs/ANSIcode.html
|
|
293
|
-
: `${eraseScreen}${ESC}3J${ESC}H`;
|
|
294
|
-
|
|
295
|
-
export { clearTerminal, createSupportsColor, eraseLines, isUnicodeSupported };
|