UNPKG

2.77 kBJavaScriptView Raw
1'use strict';
2const os = require('os');
3const hasFlag = require('has-flag');
4
5const env = process.env;
6
7let forceColor;
8if (hasFlag('no-color') ||
9 hasFlag('no-colors') ||
10 hasFlag('color=false')) {
11 forceColor = false;
12} else if (hasFlag('color') ||
13 hasFlag('colors') ||
14 hasFlag('color=true') ||
15 hasFlag('color=always')) {
16 forceColor = true;
17}
18if ('FORCE_COLOR' in env) {
19 forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0;
20}
21
22function translateLevel(level) {
23 if (level === 0) {
24 return false;
25 }
26
27 return {
28 level,
29 hasBasic: true,
30 has256: level >= 2,
31 has16m: level >= 3
32 };
33}
34
35function supportsColor(stream) {
36 if (forceColor === false) {
37 return 0;
38 }
39
40 if (hasFlag('color=16m') ||
41 hasFlag('color=full') ||
42 hasFlag('color=truecolor')) {
43 return 3;
44 }
45
46 if (hasFlag('color=256')) {
47 return 2;
48 }
49
50 if (stream && !stream.isTTY && forceColor !== true) {
51 return 0;
52 }
53
54 const min = forceColor ? 1 : 0;
55
56 if (process.platform === 'win32') {
57 // Node.js 7.5.0 is the first version of Node.js to include a patch to
58 // libuv that enables 256 color output on Windows. Anything earlier and it
59 // won't work. However, here we target Node.js 8 at minimum as it is an LTS
60 // release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows
61 // release that supports 256 colors. Windows 10 build 14931 is the first release
62 // that supports 16m/TrueColor.
63 const osRelease = os.release().split('.');
64 if (
65 Number(process.versions.node.split('.')[0]) >= 8 &&
66 Number(osRelease[0]) >= 10 &&
67 Number(osRelease[2]) >= 10586
68 ) {
69 return Number(osRelease[2]) >= 14931 ? 3 : 2;
70 }
71
72 return 1;
73 }
74
75 if ('CI' in env) {
76 if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
77 return 1;
78 }
79
80 return min;
81 }
82
83 if ('TEAMCITY_VERSION' in env) {
84 return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
85 }
86
87 if (env.COLORTERM === 'truecolor') {
88 return 3;
89 }
90
91 if ('TERM_PROGRAM' in env) {
92 const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
93
94 switch (env.TERM_PROGRAM) {
95 case 'iTerm.app':
96 return version >= 3 ? 3 : 2;
97 case 'Apple_Terminal':
98 return 2;
99 // No default
100 }
101 }
102
103 if (/-256(color)?$/i.test(env.TERM)) {
104 return 2;
105 }
106
107 if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
108 return 1;
109 }
110
111 if ('COLORTERM' in env) {
112 return 1;
113 }
114
115 if (env.TERM === 'dumb') {
116 return min;
117 }
118
119 return min;
120}
121
122function getSupportLevel(stream) {
123 const level = supportsColor(stream);
124 return translateLevel(level);
125}
126
127module.exports = {
128 supportsColor: getSupportLevel,
129 stdout: getSupportLevel(process.stdout),
130 stderr: getSupportLevel(process.stderr)
131};