* original source: https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js
*
* This file was imported due to lacking support of CJS environments in the original package.
*/
import process from 'node:process'
import os from 'node:os'
import tty from 'node:tty'
function hasFlag(flag: string, argv = process.argv) {
const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--')
const position = argv.indexOf(prefix + flag)
const terminatorPosition = argv.indexOf('--')
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition)
}
interface Options {
* By default it is `true`, which instructs `supportsColor()` to sniff `process.argv`
* for the multitude of `--color` flags (see _Info_ below).
* If `false`, then `process.argv` is not considered when determining color support.
* @default true
*/
sniffFlags?: boolean | undefined;
isTTY?: boolean | undefined;
}
const { env } = process
let flagForceColor: number | undefined
if (
hasFlag('no-color')
|| hasFlag('no-colors')
|| hasFlag('color=false')
|| hasFlag('color=never')
) {
flagForceColor = 0
} else if (
hasFlag('color')
|| hasFlag('colors')
|| hasFlag('color=true')
|| hasFlag('color=always')
) {
flagForceColor = 1
}
function envForceColor() {
if ('FORCE_COLOR' in env) {
if (env.FORCE_COLOR === 'true') {
return 1
}
if (env.FORCE_COLOR === 'false') {
return 0
}
return env.FORCE_COLOR!.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR!, 10), 3)
}
}
function translateLevel(level: number) {
if (level === 0) {
return false
}
return {
level,
hasBasic: true,
has256: level >= 2,
has16m: level >= 3,
}
}
function _supportsColor(haveStream: { isTTY?: boolean }, { streamIsTTY, sniffFlags = true }: { streamIsTTY?: boolean, sniffFlags?: boolean } = {}) {
const noFlagForceColor = envForceColor()
if (noFlagForceColor !== undefined) {
flagForceColor = noFlagForceColor
}
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor
if (forceColor === 0) {
return 0
}
if (sniffFlags) {
if (hasFlag('color=16m')
|| hasFlag('color=full')
|| hasFlag('color=truecolor')) {
return 3
}
if (hasFlag('color=256')) {
return 2
}
}
if ('TF_BUILD' in env && 'AGENT_NAME' in env) {
return 1
}
if (haveStream && !streamIsTTY && forceColor === undefined) {
return 0
}
const min = forceColor || 0
if (env.TERM === 'dumb') {
return min
}
if (process.platform === 'win32') {
const osRelease = os.release().split('.')
if (
Number(osRelease[0]) >= 10
&& Number(osRelease[2]) >= 10_586
) {
return Number(osRelease[2]) >= 14_931 ? 3 : 2
}
return 1
}
if ('CI' in env) {
if ('GITHUB_ACTIONS' in env || 'GITEA_ACTIONS' in env) {
return 3
}
if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
return 1
}
return min
}
if ('TEAMCITY_VERSION' in env) {
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION!) ? 1 : 0
}
if (env.COLORTERM === 'truecolor') {
return 3
}
if (env.TERM === 'xterm-kitty') {
return 3
}
if ('TERM_PROGRAM' in env) {
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10)
switch (env.TERM_PROGRAM) {
case 'iTerm.app': {
return version >= 3 ? 3 : 2
}
case 'Apple_Terminal': {
return 2
}
}
}
if (env.TERM && /-256(color)?$/i.test(env.TERM)) {
return 2
}
if (env.TERM && /^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
return 1
}
if ('COLORTERM' in env) {
return 1
}
return min
}
export function createSupportsColor(stream: { isTTY?: boolean }, options: Options = {}) {
const level = _supportsColor(stream, {
streamIsTTY: stream && stream.isTTY,
...options,
})
return translateLevel(level)
}
const supportsColor = {
stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
stderr: createSupportsColor({ isTTY: tty.isatty(2) }),
}
export default supportsColor