Skip to content

Commit 53150a8

Browse files
committed
Require Node.js 22
1 parent b98103a commit 53150a8

6 files changed

Lines changed: 35 additions & 24 deletions

File tree

.github/workflows/main.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
node-version:
13-
- 20
14-
- 18
13+
- 26
14+
- 22
1515
steps:
16-
- uses: actions/checkout@v4
17-
- uses: actions/setup-node@v4
16+
- uses: actions/checkout@v7
17+
- uses: actions/setup-node@v6
1818
with:
1919
node-version: ${{ matrix.node-version }}
2020
- run: npm install

browser.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
1-
/* eslint-env browser */
2-
/* eslint-disable n/no-unsupported-features/node-builtins */
3-
41
const level = (() => {
52
if (!('navigator' in globalThis)) {
63
return 0;
74
}
85

9-
if (globalThis.navigator.userAgentData) {
6+
if (navigator.userAgentData) {
107
const brand = navigator.userAgentData.brands.find(({brand}) => brand === 'Chromium');
118
if (brand?.version > 93) {
129
return 3;
1310
}
1411
}
1512

16-
if (/\b(Chrome|Chromium)\//.test(globalThis.navigator.userAgent)) {
13+
// eslint-disable-next-line require-unicode-regexp -- This entry point supports browsers without Unicode Sets.
14+
if (/\b(?:Chrome|Chromium)\//.test(navigator.userAgent)) {
1715
return 1;
1816
}
1917

index.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ function envForceColor() {
4747
return 1;
4848
}
4949

50-
const level = Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
50+
if (!/^\d+$/v.test(env.FORCE_COLOR)) {
51+
return;
52+
}
53+
54+
const level = Math.min(Number(env.FORCE_COLOR), 3);
5155

5256
if (![0, 1, 2, 3].includes(level)) {
5357
return;
@@ -69,6 +73,7 @@ function translateLevel(level) {
6973
};
7074
}
7175

76+
// eslint-disable-next-line complexity -- Color support detection necessarily handles multiple environments.
7277
function _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {
7378
const noFlagForceColor = envForceColor();
7479
if (noFlagForceColor !== undefined) {
@@ -94,7 +99,7 @@ function _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {
9499
}
95100

96101
// A numeric `FORCE_COLOR` requests an exact level, while `FORCE_COLOR=true` and `FORCE_COLOR=` only enable color and let the level be detected.
97-
if (forceColor !== undefined && /^\d+$/.test(env.FORCE_COLOR)) {
102+
if (forceColor !== undefined && /^\d+$/v.test(env.FORCE_COLOR)) {
98103
return forceColor;
99104
}
100105

@@ -129,19 +134,19 @@ function _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {
129134
}
130135

131136
if ('CI' in env) {
132-
if (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => key in env)) {
137+
if (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => Object.hasOwn(env, key))) {
133138
return 3;
134139
}
135140

136-
if (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
141+
if (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => Object.hasOwn(env, sign)) || env.CI_NAME === 'codeship') {
137142
return 1;
138143
}
139144

140145
return min;
141146
}
142147

143148
if ('TEAMCITY_VERSION' in env) {
144-
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
149+
return /^(?:9\.0*[1-9]\d*\.|\d{2,}\.)/v.test(env.TEAMCITY_VERSION) ? 1 : 0;
145150
}
146151

147152
if (env.COLORTERM === 'truecolor') {
@@ -161,7 +166,7 @@ function _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {
161166
}
162167

163168
if ('TERM_PROGRAM' in env) {
164-
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
169+
const version = Number((env.TERM_PROGRAM_VERSION || '').split('.', 1)[0]);
165170

166171
switch (env.TERM_PROGRAM) {
167172
case 'iTerm.app': {
@@ -175,11 +180,11 @@ function _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {
175180
}
176181
}
177182

178-
if (/-256(color)?$/i.test(env.TERM)) {
183+
if (/-256(?:color)?$/iv.test(env.TERM)) {
179184
return 2;
180185
}
181186

182-
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
187+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/iv.test(env.TERM)) {
183188
return 1;
184189
}
185190

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
},
1919
"sideEffects": false,
2020
"engines": {
21-
"node": ">=18"
21+
"node": ">=22"
2222
},
2323
"scripts": {
2424
"test": "xo && ava && tsd"
@@ -52,10 +52,10 @@
5252
"16m"
5353
],
5454
"devDependencies": {
55-
"@types/node": "^22.10.2",
56-
"ava": "^6.2.0",
57-
"tsd": "^0.31.2",
58-
"xo": "^0.60.0"
55+
"@types/node": "^26.1.1",
56+
"ava": "^8.0.1",
57+
"tsd": "^0.33.0",
58+
"xo": "^4.0.0"
5959
},
6060
"ava": {
6161
"serial": true,

readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ The options object supports a single boolean property `sniffFlags`. By default i
5858

5959
It obeys the `--color` and `--no-color` CLI flags.
6060

61-
For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. A numeric `FORCE_COLOR` overrides all other color support checks and is used as-is, meaning the terminal cannot raise it to a higher level. Use `FORCE_COLOR=true` to instead only enable color and let the level be detected.
61+
For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. A numeric `FORCE_COLOR` overrides the detected color support and sets the level directly, meaning the terminal cannot raise it to a higher level. Use `FORCE_COLOR=true` to instead only enable color and let the level be detected.
6262

63-
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
63+
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively. These take precedence over a non-zero numeric `FORCE_COLOR`.
6464

6565
## Related
6666

test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,14 @@ test('a non-numeric FORCE_COLOR is ignored', async t => {
400400
t.false(result.stdout);
401401
});
402402

403+
test('a partially numeric FORCE_COLOR is ignored', async t => {
404+
process.env.FORCE_COLOR = '1abc';
405+
process.env.TERM = 'xterm-256color';
406+
const result = await importMain();
407+
t.truthy(result.stdout);
408+
t.is(result.stdout.level, 2);
409+
});
410+
403411
test('FORCE_COLOR works when set via command line (all values are strings)', async t => {
404412
let result;
405413
process.env.FORCE_COLOR = 'true';

0 commit comments

Comments
 (0)