Skip to content
Permalink
Browse files

tty: add NO_COLOR and FORCE_COLOR support

This adds support to enforce a specific color depth by checking the
`FORCE_COLOR` environment variable similar to `chalk`.

On top of that we also add support for the `NO_COLOR` environment
variable as suggested by https://no-color.org/.

PR-URL: #26485
Refs: #26248
Reviewed-By: Roman Reiss <me@silverwind.io>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
  • Loading branch information...
BridgeAR authored and targos committed Mar 7, 2019
1 parent 1073e54 commit 8cafd83ba7dee3dd43a41e74f03082818c8fe99d
Showing with 70 additions and 9 deletions.
  1. +14 −6 doc/api/tty.md
  2. +39 −1 lib/internal/tty.js
  3. +9 −2 test/pseudo-tty/test-tty-color-support.js
  4. +8 −0 test/pseudo-tty/test-tty-color-support.out
@@ -144,8 +144,9 @@ position.
added: v9.9.0
-->

* `env` {Object} An object containing the environment variables to check.
**Default:** `process.env`.
* `env` {Object} An object containing the environment variables to check. This
enables simulating the usage of a specific terminal. **Default:**
`process.env`.
* Returns: {number}

Returns:
@@ -159,11 +160,18 @@ Use this to determine what colors the terminal supports. Due to the nature of
colors in terminals it is possible to either have false positives or false
negatives. It depends on process information and the environment variables that
may lie about what terminal is used.
To enforce a specific behavior without relying on `process.env` it is possible
to pass in an object with different settings.
It is possible to pass in an `env` object to simulate the usage of a specific
terminal. This can be useful to check how specific environment settings behave.

To enforce a specific color support, use one of the below environment settings.

* 2 colors: `FORCE_COLOR = 0` (Disables colors)
* 16 colors: `FORCE_COLOR = 1`
* 256 colors: `FORCE_COLOR = 2`
* 16,777,216 colors: `FORCE_COLOR = 3`

Use the `NODE_DISABLE_COLORS` environment variable to enforce this function to
always return 1.
Disabling color support is also possible by using the `NO_COLOR` and
`NODE_DISABLE_COLORS` environment variables.

### writeStream.getWindowSize()
<!-- YAML
@@ -72,11 +72,49 @@ const TERM_ENVS_REG_EXP = [
/^vt100/
];

function warnOnDeactivatedColors(env) {
let name;
if (env.NODE_DISABLE_COLORS !== undefined)
name = 'NODE_DISABLE_COLORS';
if (env.NO_COLOR !== undefined)
name = 'NO_COLOR';

if (name !== undefined) {
process.emitWarning(
`The '${name}' env is ignored due to the 'FORCE_COLOR' env being set.`,
'Warning'
);
}
}

// The `getColorDepth` API got inspired by multiple sources such as
// https://github.com/chalk/supports-color,
// https://github.com/isaacs/color-support.
function getColorDepth(env = process.env) {
if (env.NODE_DISABLE_COLORS || env.TERM === 'dumb') {
// Use level 0-3 to support the same levels as `chalk` does. This is done for
// consistency throughout the ecosystem.
if (env.FORCE_COLOR !== undefined) {
switch (env.FORCE_COLOR) {
case '':
case '1':
case 'true':
warnOnDeactivatedColors(env);
return COLORS_16;
case '2':
warnOnDeactivatedColors(env);
return COLORS_256;
case '3':
warnOnDeactivatedColors(env);
return COLORS_16m;
default:
return COLORS_2;
}
}

if (env.NODE_DISABLE_COLORS !== undefined ||
// See https://no-color.org/
env.NO_COLOR !== undefined ||
env.TERM === 'dumb') {
return COLORS_2;
}

@@ -59,11 +59,18 @@ const writeStream = new WriteStream(fd);
[{ TERM: 'color' }, 4],
[{ TERM: 'linux' }, 4],
[{ TERM: 'fail' }, 1],
[{ NODE_DISABLE_COLORS: '1' }, 1],
[{ TERM: 'color', NODE_DISABLE_COLORS: '1' }, 1],
[{ TERM: 'dumb' }, 1],
[{ TERM: 'dumb', COLORTERM: '1' }, 1],
[{ TERM: 'terminator' }, 24],
[{ TERM: 'console' }, 4]
[{ TERM: 'console' }, 4],
[{ COLORTERM: '24bit', FORCE_COLOR: '' }, 4],
[{ NO_COLOR: '1', FORCE_COLOR: '2' }, 8],
[{ NODE_DISABLE_COLORS: '1', FORCE_COLOR: '3' }, 24],
[{ NO_COLOR: '1', COLORTERM: '24bit' }, 1],
[{ NO_COLOR: '', COLORTERM: '24bit' }, 1],
[{ TMUX: '1', FORCE_COLOR: 0 }, 1],
[{ NO_COLOR: 'true', FORCE_COLOR: 0, COLORTERM: 'truecolor' }, 1],
].forEach(([env, depth], i) => {
const actual = writeStream.getColorDepth(env);
assert.strictEqual(
@@ -0,0 +1,8 @@
(node:*) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(node:*) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(node:*) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(node:*) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
(node:*) Warning: The 'NODE_DISABLE_COLORS' env is ignored due to the 'FORCE_COLOR' env being set.
(node:*) Warning: The 'NODE_DISABLE_COLORS' env is ignored due to the 'FORCE_COLOR' env being set.
(node:*) Warning: The 'NODE_DISABLE_COLORS' env is ignored due to the 'FORCE_COLOR' env being set.
(node:*) Warning: The 'NODE_DISABLE_COLORS' env is ignored due to the 'FORCE_COLOR' env being set.

0 comments on commit 8cafd83

Please sign in to comment.
You can’t perform that action at this time.