Skip to content

Commit 0a9ac73

Browse files
committed
Require Node.js 22
1 parent 0895c86 commit 0a9ac73

File tree

5 files changed

+26
-11
lines changed

5 files changed

+26
-11
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
matrix:
1212
node-version:
1313
- 24
14-
- 20
14+
- 22
1515
steps:
1616
- uses: actions/checkout@v6
1717
- uses: actions/setup-node@v6

index.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function applySgrFragments(activeStyles, fragments) {
2929
}
3030

3131
function undoAnsiCodes(activeStyles) {
32-
return [...activeStyles.keys()].reverse().join('');
32+
return [...activeStyles.keys()].toReversed().join('');
3333
}
3434

3535
function closeHyperlink(hyperlinkToken) {
@@ -63,13 +63,21 @@ function hasSgrStartFragment(token) {
6363
return token.fragments.some(fragment => fragment.type === 'start');
6464
}
6565

66-
function clearPendingHyperlink(parameters) {
66+
function discardPendingHyperlink(parameters) {
6767
if (
6868
parameters.activeHyperlink
6969
&& !parameters.activeHyperlinkHasVisibleText
7070
&& parameters.activeHyperlinkOutputIndex !== undefined
7171
) {
72-
parameters.returnValue = parameters.returnValue.slice(0, parameters.activeHyperlinkOutputIndex);
72+
const openCodeLength = parameters.activeHyperlink.code.length;
73+
parameters.returnValue = parameters.returnValue.slice(0, parameters.activeHyperlinkOutputIndex) + parameters.returnValue.slice(parameters.activeHyperlinkOutputIndex + openCodeLength);
74+
75+
if (
76+
parameters.pendingSgrOutputIndex !== undefined
77+
&& parameters.pendingSgrOutputIndex > parameters.activeHyperlinkOutputIndex
78+
) {
79+
parameters.pendingSgrOutputIndex -= openCodeLength;
80+
}
7381
}
7482

7583
parameters.activeHyperlink = undefined;
@@ -126,7 +134,7 @@ function applyHyperlinkToken(parameters) {
126134
&& parameters.activeHyperlink
127135
&& !parameters.activeHyperlinkHasVisibleText
128136
) {
129-
clearPendingHyperlink(parameters);
137+
discardPendingHyperlink(parameters);
130138
return parameters;
131139
}
132140

@@ -255,13 +263,15 @@ export default function sliceAnsi(string, start, end) {
255263
activeHyperlink,
256264
activeHyperlinkHasVisibleText,
257265
activeHyperlinkOutputIndex,
266+
pendingSgrOutputIndex,
258267
returnValue,
259268
};
260-
clearPendingHyperlink(hyperlinkState);
269+
discardPendingHyperlink(hyperlinkState);
261270
({
262271
activeHyperlink,
263272
activeHyperlinkHasVisibleText,
264273
activeHyperlinkOutputIndex,
274+
pendingSgrOutputIndex,
265275
returnValue,
266276
} = hyperlinkState);
267277
}

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
},
1313
"sideEffects": false,
1414
"engines": {
15-
"node": ">=20"
15+
"node": ">=22"
1616
},
1717
"scripts": {
1818
"test": "xo && ava && tsc --lib esnext index.d.ts"
@@ -50,10 +50,10 @@
5050
"is-fullwidth-code-point": "^5.1.0"
5151
},
5252
"devDependencies": {
53-
"ava": "^6.4.1",
53+
"ava": "^7.0.0",
5454
"chalk": "^5.6.2",
5555
"random-item": "^4.0.1",
56-
"strip-ansi": "^7.1.2",
57-
"xo": "^1.2.3"
56+
"strip-ansi": "^7.2.0",
57+
"xo": "^2.0.2"
5858
}
5959
}

test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,11 @@ test('does not include hyperlink escapes when slicing only outside linked text',
643643
t.is(sliceAnsi(input, 14, 19), 'suffi');
644644
});
645645

646+
test('preserves surrounding SGR changes when discarding an empty hyperlink', t => {
647+
const input = '\u001B[31mA\u001B]8;;https://example.com\u0007\u001B[39m\u001B]8;;\u0007B';
648+
t.is(sliceAnsi(input, 0, 2), '\u001B[31mA\u001B[39mB');
649+
});
650+
646651
test('does not include styles that start after end', t => {
647652
const input = `a${chalk.red('b')}`;
648653
t.is(sliceAnsi(input, 0, 1), 'a');

tokenize-ansi.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const SGR_ANSI_256_LAST_PARAMETER_OFFSET = 2;
6464
const SGR_TRUECOLOR_LAST_PARAMETER_OFFSET = 4;
6565
const VARIATION_SELECTOR_16_CODE_POINT = 65_039;
6666
const COMBINING_ENCLOSING_KEYCAP_CODE_POINT = 8419;
67-
const EMOJI_PRESENTATION_GRAPHEME_REGEX = /\p{Emoji_Presentation}/u;
67+
const EMOJI_PRESENTATION_GRAPHEME_REGEX = /\p{Emoji_Presentation}/v;
6868
const GRAPHEME_SEGMENTER = new Intl.Segmenter(undefined, {granularity: 'grapheme'});
6969

7070
const endCodeNumbers = new Set();

0 commit comments

Comments
 (0)