1 | import process from 'node:process';
|
2 | import os from 'node:os';
|
3 | import tty from 'node:tty';
|
4 |
|
5 |
|
6 | function hasFlag(flag, argv = process.argv) {
|
7 | const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
|
8 | const position = argv.indexOf(prefix + flag);
|
9 | const terminatorPosition = argv.indexOf('--');
|
10 | return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
11 | }
|
12 |
|
13 | const {env} = process;
|
14 |
|
15 | let flagForceColor;
|
16 | if (
|
17 | hasFlag('no-color')
|
18 | || hasFlag('no-colors')
|
19 | || hasFlag('color=false')
|
20 | || hasFlag('color=never')
|
21 | ) {
|
22 | flagForceColor = 0;
|
23 | } else if (
|
24 | hasFlag('color')
|
25 | || hasFlag('colors')
|
26 | || hasFlag('color=true')
|
27 | || hasFlag('color=always')
|
28 | ) {
|
29 | flagForceColor = 1;
|
30 | }
|
31 |
|
32 | function envForceColor() {
|
33 | if ('FORCE_COLOR' in env) {
|
34 | if (env.FORCE_COLOR === 'true') {
|
35 | return 1;
|
36 | }
|
37 |
|
38 | if (env.FORCE_COLOR === 'false') {
|
39 | return 0;
|
40 | }
|
41 |
|
42 | return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
43 | }
|
44 | }
|
45 |
|
46 | function translateLevel(level) {
|
47 | if (level === 0) {
|
48 | return false;
|
49 | }
|
50 |
|
51 | return {
|
52 | level,
|
53 | hasBasic: true,
|
54 | has256: level >= 2,
|
55 | has16m: level >= 3,
|
56 | };
|
57 | }
|
58 |
|
59 | function _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {
|
60 | const noFlagForceColor = envForceColor();
|
61 | if (noFlagForceColor !== undefined) {
|
62 | flagForceColor = noFlagForceColor;
|
63 | }
|
64 |
|
65 | const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
66 |
|
67 | if (forceColor === 0) {
|
68 | return 0;
|
69 | }
|
70 |
|
71 | if (sniffFlags) {
|
72 | if (hasFlag('color=16m')
|
73 | || hasFlag('color=full')
|
74 | || hasFlag('color=truecolor')) {
|
75 | return 3;
|
76 | }
|
77 |
|
78 | if (hasFlag('color=256')) {
|
79 | return 2;
|
80 | }
|
81 | }
|
82 |
|
83 | if (haveStream && !streamIsTTY && forceColor === undefined) {
|
84 | return 0;
|
85 | }
|
86 |
|
87 | const min = forceColor || 0;
|
88 |
|
89 | if (env.TERM === 'dumb') {
|
90 | return min;
|
91 | }
|
92 |
|
93 | if (process.platform === 'win32') {
|
94 |
|
95 |
|
96 | const osRelease = os.release().split('.');
|
97 | if (
|
98 | Number(osRelease[0]) >= 10
|
99 | && Number(osRelease[2]) >= 10_586
|
100 | ) {
|
101 | return Number(osRelease[2]) >= 14_931 ? 3 : 2;
|
102 | }
|
103 |
|
104 | return 1;
|
105 | }
|
106 |
|
107 | if ('CI' in env) {
|
108 | if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
|
109 | return 1;
|
110 | }
|
111 |
|
112 | return min;
|
113 | }
|
114 |
|
115 | if ('TEAMCITY_VERSION' in env) {
|
116 | return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
117 | }
|
118 |
|
119 |
|
120 | if ('TF_BUILD' in env && 'AGENT_NAME' in env) {
|
121 | return 1;
|
122 | }
|
123 |
|
124 | if (env.COLORTERM === 'truecolor') {
|
125 | return 3;
|
126 | }
|
127 |
|
128 | if ('TERM_PROGRAM' in env) {
|
129 | const version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
|
130 |
|
131 | switch (env.TERM_PROGRAM) {
|
132 | case 'iTerm.app':
|
133 | return version >= 3 ? 3 : 2;
|
134 | case 'Apple_Terminal':
|
135 | return 2;
|
136 |
|
137 | }
|
138 | }
|
139 |
|
140 | if (/-256(color)?$/i.test(env.TERM)) {
|
141 | return 2;
|
142 | }
|
143 |
|
144 | if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
145 | return 1;
|
146 | }
|
147 |
|
148 | if ('COLORTERM' in env) {
|
149 | return 1;
|
150 | }
|
151 |
|
152 | return min;
|
153 | }
|
154 |
|
155 | export function createSupportsColor(stream, options = {}) {
|
156 | const level = _supportsColor(stream, {
|
157 | streamIsTTY: stream && stream.isTTY,
|
158 | ...options,
|
159 | });
|
160 |
|
161 | return translateLevel(level);
|
162 | }
|
163 |
|
164 | const supportsColor = {
|
165 | stdout: createSupportsColor({isTTY: tty.isatty(1)}),
|
166 | stderr: createSupportsColor({isTTY: tty.isatty(2)}),
|
167 | };
|
168 |
|
169 | export default supportsColor;
|