@node-core/utils 7.2.0 → 7.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/lib/ci/build-types/test_build.js +3 -3
  2. package/lib/ci/failure_aggregator.js +2 -2
  3. package/lib/ci/run_ci.js +3 -2
  4. package/lib/cli.js +6 -6
  5. package/lib/figures.js +6 -6
  6. package/lib/update-v8/backport.js +3 -4
  7. package/lib/verbosity.js +2 -4
  8. package/node_modules/@listr2/{prompt-adapter-enquirer → prompt-adapter-inquirer}/README.md +4 -4
  9. package/node_modules/@listr2/prompt-adapter-inquirer/dist/index.d.mts +21 -0
  10. package/node_modules/@listr2/prompt-adapter-inquirer/dist/index.mjs +46 -0
  11. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/LICENSE +22 -0
  12. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/index.d.ts +2 -0
  13. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/index.js +2 -0
  14. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/inquirer.d.ts +35 -0
  15. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/inquirer.js +1 -0
  16. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/utils.d.ts +34 -0
  17. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/utils.js +2 -0
  18. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/package.json +88 -0
  19. package/node_modules/@listr2/{prompt-adapter-enquirer → prompt-adapter-inquirer}/package.json +25 -20
  20. package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/base.d.ts +48 -3
  21. package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/base.js +58 -19
  22. package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/package.json +1 -1
  23. package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/readme.md +36 -1
  24. package/node_modules/ansi-regex/index.js +9 -4
  25. package/node_modules/ansi-regex/package.json +1 -1
  26. package/node_modules/ansi-regex/readme.md +6 -0
  27. package/node_modules/ansi-styles/index.d.ts +12 -12
  28. package/node_modules/ansi-styles/index.js +3 -3
  29. package/node_modules/ansi-styles/package.json +4 -4
  30. package/node_modules/cli-truncate/index.d.ts +3 -3
  31. package/node_modules/cli-truncate/index.js +40 -14
  32. package/node_modules/cli-truncate/node_modules/string-width/index.js +133 -15
  33. package/node_modules/cli-truncate/node_modules/string-width/package.json +4 -4
  34. package/node_modules/cli-truncate/node_modules/string-width/readme.md +1 -1
  35. package/node_modules/cli-truncate/package.json +7 -7
  36. package/node_modules/cli-truncate/readme.md +2 -3
  37. package/node_modules/ghauth/.github/dependabot.yml +11 -3
  38. package/node_modules/ghauth/.github/workflows/depsound.yml +33 -0
  39. package/node_modules/ghauth/.github/workflows/test-and-release.yml +4 -4
  40. package/node_modules/ghauth/CHANGELOG.md +60 -0
  41. package/node_modules/ghauth/package.json +30 -6
  42. package/node_modules/js-yaml/README.md +20 -187
  43. package/node_modules/js-yaml/dist/browser/js-yaml.esm.min.mjs +1008 -946
  44. package/node_modules/js-yaml/dist/browser/js-yaml.esm.min.mjs.map +1 -1
  45. package/node_modules/js-yaml/dist/browser/js-yaml.umd.min.js +29 -23
  46. package/node_modules/js-yaml/dist/browser/js-yaml.umd.min.js.map +1 -1
  47. package/node_modules/js-yaml/dist/js-yaml.cjs.js +1043 -583
  48. package/node_modules/js-yaml/dist/js-yaml.cjs.js.map +1 -1
  49. package/node_modules/js-yaml/dist/js-yaml.d.ts +877 -133
  50. package/node_modules/js-yaml/dist/js-yaml.mjs +995 -556
  51. package/node_modules/js-yaml/dist/js-yaml.mjs.map +1 -1
  52. package/node_modules/js-yaml/package.json +8 -7
  53. package/node_modules/listr2/dist/{index.d.cts → index.d.mts} +90 -60
  54. package/node_modules/listr2/dist/{index.js → index.mjs} +496 -373
  55. package/node_modules/listr2/node_modules/string-width/index.d.ts +39 -0
  56. package/node_modules/listr2/node_modules/string-width/index.js +207 -0
  57. package/node_modules/listr2/node_modules/string-width/package.json +65 -0
  58. package/node_modules/listr2/node_modules/string-width/readme.md +66 -0
  59. package/node_modules/listr2/node_modules/wrap-ansi/index.d.ts +1 -1
  60. package/node_modules/listr2/node_modules/wrap-ansi/index.js +544 -116
  61. package/node_modules/listr2/node_modules/wrap-ansi/package.json +10 -13
  62. package/node_modules/listr2/node_modules/wrap-ansi/readme.md +2 -0
  63. package/node_modules/listr2/package.json +16 -19
  64. package/node_modules/log-update/index.d.ts +64 -1
  65. package/node_modules/log-update/index.js +268 -18
  66. package/node_modules/log-update/node_modules/string-width/index.d.ts +39 -0
  67. package/node_modules/log-update/node_modules/string-width/index.js +207 -0
  68. package/node_modules/log-update/node_modules/string-width/package.json +65 -0
  69. package/node_modules/log-update/node_modules/string-width/readme.md +66 -0
  70. package/node_modules/log-update/node_modules/wrap-ansi/index.d.ts +1 -1
  71. package/node_modules/log-update/node_modules/wrap-ansi/index.js +544 -116
  72. package/node_modules/log-update/node_modules/wrap-ansi/package.json +10 -13
  73. package/node_modules/log-update/node_modules/wrap-ansi/readme.md +2 -0
  74. package/node_modules/log-update/package.json +14 -12
  75. package/node_modules/log-update/readme.md +61 -0
  76. package/node_modules/slice-ansi/index.d.ts +2 -2
  77. package/node_modules/slice-ansi/index.js +260 -112
  78. package/node_modules/slice-ansi/package.json +10 -9
  79. package/node_modules/slice-ansi/readme.md +3 -2
  80. package/node_modules/slice-ansi/tokenize-ansi.js +752 -0
  81. package/node_modules/smol-toml/README.md +205 -191
  82. package/node_modules/smol-toml/dist/date.d.ts +0 -1
  83. package/node_modules/smol-toml/dist/date.js +0 -1
  84. package/node_modules/smol-toml/dist/error.d.ts +0 -1
  85. package/node_modules/smol-toml/dist/error.js +0 -1
  86. package/node_modules/smol-toml/dist/extract.js +32 -65
  87. package/node_modules/smol-toml/dist/index.cjs +302 -288
  88. package/node_modules/smol-toml/dist/index.d.ts +0 -1
  89. package/node_modules/smol-toml/dist/index.js +0 -1
  90. package/node_modules/smol-toml/dist/parse.d.ts +1 -3
  91. package/node_modules/smol-toml/dist/parse.js +22 -21
  92. package/node_modules/smol-toml/dist/primitive.js +75 -76
  93. package/node_modules/smol-toml/dist/stringify.d.ts +0 -1
  94. package/node_modules/smol-toml/dist/stringify.js +43 -30
  95. package/node_modules/smol-toml/dist/struct.js +90 -93
  96. package/node_modules/smol-toml/dist/util.d.ts +1 -1
  97. package/node_modules/smol-toml/dist/util.js +36 -39
  98. package/node_modules/smol-toml/package.json +6 -6
  99. package/node_modules/strip-ansi/index.js +5 -0
  100. package/node_modules/strip-ansi/package.json +5 -5
  101. package/package.json +3 -5
  102. package/node_modules/@listr2/prompt-adapter-enquirer/dist/index.cjs +0 -127
  103. package/node_modules/@listr2/prompt-adapter-enquirer/dist/index.d.cts +0 -152
  104. package/node_modules/@listr2/prompt-adapter-enquirer/dist/index.d.ts +0 -152
  105. package/node_modules/@listr2/prompt-adapter-enquirer/dist/index.js +0 -92
  106. package/node_modules/chalk/package.json +0 -92
  107. package/node_modules/chalk/readme.md +0 -331
  108. package/node_modules/chalk/source/index.d.ts +0 -437
  109. package/node_modules/chalk/source/index.js +0 -261
  110. package/node_modules/chalk/source/utilities.js +0 -33
  111. package/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +0 -299
  112. package/node_modules/chalk/source/vendor/ansi-styles/index.js +0 -261
  113. package/node_modules/chalk/source/vendor/supports-color/browser.d.ts +0 -1
  114. package/node_modules/chalk/source/vendor/supports-color/browser.js +0 -32
  115. package/node_modules/chalk/source/vendor/supports-color/index.d.ts +0 -55
  116. package/node_modules/chalk/source/vendor/supports-color/index.js +0 -206
  117. package/node_modules/colorette/LICENSE.md +0 -7
  118. package/node_modules/colorette/README.md +0 -134
  119. package/node_modules/colorette/index.cjs +0 -218
  120. package/node_modules/colorette/index.d.ts +0 -93
  121. package/node_modules/colorette/index.js +0 -150
  122. package/node_modules/colorette/package.json +0 -40
  123. package/node_modules/eventemitter3/LICENSE +0 -21
  124. package/node_modules/eventemitter3/README.md +0 -94
  125. package/node_modules/eventemitter3/dist/eventemitter3.esm.js +0 -347
  126. package/node_modules/eventemitter3/dist/eventemitter3.esm.min.js +0 -1
  127. package/node_modules/eventemitter3/dist/eventemitter3.esm.min.js.map +0 -1
  128. package/node_modules/eventemitter3/dist/eventemitter3.umd.js +0 -355
  129. package/node_modules/eventemitter3/dist/eventemitter3.umd.min.js +0 -1
  130. package/node_modules/eventemitter3/dist/eventemitter3.umd.min.js.map +0 -1
  131. package/node_modules/eventemitter3/index.d.ts +0 -135
  132. package/node_modules/eventemitter3/index.js +0 -336
  133. package/node_modules/eventemitter3/index.mjs +0 -4
  134. package/node_modules/eventemitter3/package.json +0 -67
  135. package/node_modules/figures/index.d.ts +0 -279
  136. package/node_modules/figures/index.js +0 -292
  137. package/node_modules/figures/package.json +0 -49
  138. package/node_modules/figures/readme.md +0 -337
  139. package/node_modules/listr2/dist/index.cjs +0 -2189
  140. package/node_modules/listr2/dist/index.d.ts +0 -1528
  141. package/node_modules/rfdc/.github/workflows/ci.yml +0 -21
  142. package/node_modules/rfdc/LICENSE +0 -15
  143. package/node_modules/rfdc/default.js +0 -3
  144. package/node_modules/rfdc/index.d.ts +0 -13
  145. package/node_modules/rfdc/index.js +0 -198
  146. package/node_modules/rfdc/index.test-d.ts +0 -13
  147. package/node_modules/rfdc/package.json +0 -73
  148. package/node_modules/rfdc/readme.md +0 -181
  149. package/node_modules/rfdc/test/index.js +0 -306
  150. package/node_modules/smol-toml/dist/date.d.ts.map +0 -1
  151. package/node_modules/smol-toml/dist/date.js.map +0 -1
  152. package/node_modules/smol-toml/dist/error.d.ts.map +0 -1
  153. package/node_modules/smol-toml/dist/error.js.map +0 -1
  154. package/node_modules/smol-toml/dist/extract.js.map +0 -1
  155. package/node_modules/smol-toml/dist/index.cjs.map +0 -1
  156. package/node_modules/smol-toml/dist/index.d.ts.map +0 -1
  157. package/node_modules/smol-toml/dist/index.js.map +0 -1
  158. package/node_modules/smol-toml/dist/parse.d.ts.map +0 -1
  159. package/node_modules/smol-toml/dist/parse.js.map +0 -1
  160. package/node_modules/smol-toml/dist/primitive.d.ts +0 -29
  161. package/node_modules/smol-toml/dist/primitive.d.ts.map +0 -1
  162. package/node_modules/smol-toml/dist/primitive.js.map +0 -1
  163. package/node_modules/smol-toml/dist/stringify.d.ts.map +0 -1
  164. package/node_modules/smol-toml/dist/stringify.js.map +0 -1
  165. package/node_modules/smol-toml/dist/struct.js.map +0 -1
  166. package/node_modules/smol-toml/dist/util.d.ts.map +0 -1
  167. package/node_modules/smol-toml/dist/util.js.map +0 -1
  168. package/node_modules/smol-toml/src/date.ts +0 -152
  169. package/node_modules/smol-toml/src/error.ts +0 -77
  170. package/node_modules/smol-toml/src/extract.ts +0 -113
  171. package/node_modules/smol-toml/src/index.ts +0 -42
  172. package/node_modules/smol-toml/src/parse.ts +0 -184
  173. package/node_modules/smol-toml/src/primitive.ts +0 -249
  174. package/node_modules/smol-toml/src/stringify.ts +0 -191
  175. package/node_modules/smol-toml/src/struct.ts +0 -202
  176. package/node_modules/smol-toml/src/util.ts +0 -106
  177. /package/node_modules/@listr2/{prompt-adapter-enquirer → prompt-adapter-inquirer}/LICENSE +0 -0
  178. /package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/index.d.ts +0 -0
  179. /package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/index.js +0 -0
  180. /package/node_modules/{chalk → ansi-escapes}/license +0 -0
  181. /package/node_modules/{figures → listr2/node_modules/string-width}/license +0 -0
  182. /package/node_modules/log-update/node_modules/{ansi-escapes → string-width}/license +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrap-ansi",
3
- "version": "9.0.0",
3
+ "version": "10.0.1",
4
4
  "description": "Wordwrap a string with ANSI escape codes",
5
5
  "license": "MIT",
6
6
  "repository": "chalk/wrap-ansi",
@@ -16,10 +16,10 @@
16
16
  "default": "./index.js"
17
17
  },
18
18
  "engines": {
19
- "node": ">=18"
19
+ "node": ">=20"
20
20
  },
21
21
  "scripts": {
22
- "test": "xo && nyc ava && tsd"
22
+ "test": "xo && node --test && tsd"
23
23
  },
24
24
  "files": [
25
25
  "index.js",
@@ -53,17 +53,14 @@
53
53
  "text"
54
54
  ],
55
55
  "dependencies": {
56
- "ansi-styles": "^6.2.1",
57
- "string-width": "^7.0.0",
58
- "strip-ansi": "^7.1.0"
56
+ "ansi-styles": "^6.2.3",
57
+ "string-width": "^8.2.0"
59
58
  },
60
59
  "devDependencies": {
61
- "ava": "^5.3.1",
62
- "chalk": "^5.3.0",
63
- "coveralls": "^3.1.1",
64
- "has-ansi": "^5.0.1",
65
- "nyc": "^15.1.0",
66
- "tsd": "^0.29.0",
67
- "xo": "^0.56.0"
60
+ "chalk": "^5.6.2",
61
+ "has-ansi": "^6.0.2",
62
+ "strip-ansi": "^7.1.2",
63
+ "tsd": "^0.33.0",
64
+ "xo": "^1.2.3"
68
65
  }
69
66
  }
@@ -36,6 +36,8 @@ A string with ANSI escape codes, like one styled by [`chalk`](https://github.com
36
36
 
37
37
  Newline characters will be normalized to `\n`.
38
38
 
39
+ Tab characters are expanded to spaces using 8-column tab stops before wrapping.
40
+
39
41
  #### columns
40
42
 
41
43
  Type: `number`
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "log-update",
3
- "version": "6.1.0",
3
+ "version": "8.0.0",
4
4
  "description": "Log by overwriting the previous output in the terminal. Useful for rendering progress bars, animations, etc.",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/log-update",
@@ -17,10 +17,10 @@
17
17
  },
18
18
  "sideEffects": false,
19
19
  "engines": {
20
- "node": ">=18"
20
+ "node": ">=22"
21
21
  },
22
22
  "scripts": {
23
- "test": "xo && ava && tsd"
23
+ "test": "xo && node --test && tsd"
24
24
  },
25
25
  "files": [
26
26
  "index.js",
@@ -45,23 +45,25 @@
45
45
  "animation"
46
46
  ],
47
47
  "dependencies": {
48
- "ansi-escapes": "^7.0.0",
48
+ "ansi-escapes": "^7.3.0",
49
49
  "cli-cursor": "^5.0.0",
50
- "slice-ansi": "^7.1.0",
51
- "strip-ansi": "^7.1.0",
52
- "wrap-ansi": "^9.0.0"
50
+ "slice-ansi": "^9.0.0",
51
+ "string-width": "^8.2.0",
52
+ "strip-ansi": "^7.2.0",
53
+ "wrap-ansi": "^10.0.0"
53
54
  },
54
55
  "devDependencies": {
55
- "@types/node": "^20.14.12",
56
- "ava": "^6.1.3",
56
+ "@types/node": "^25.5.2",
57
57
  "terminal.js": "^1.0.11",
58
- "tsd": "^0.31.1",
58
+ "tsd": "^0.33.0",
59
59
  "wcwidth": "^1.0.1",
60
- "xo": "^0.59.2"
60
+ "xo": "^2.0.2"
61
61
  },
62
62
  "xo": {
63
63
  "rules": {
64
- "@typescript-eslint/no-unsafe-argument": "off"
64
+ "@typescript-eslint/no-unsafe-argument": "off",
65
+ "import-x/no-extraneous-dependencies": "off",
66
+ "n/no-extraneous-import": "off"
65
67
  }
66
68
  }
67
69
  }
@@ -5,6 +5,8 @@
5
5
 
6
6
  ![](screenshot.gif)
7
7
 
8
+ It performs partial redraws when possible to reduce flicker.
9
+
8
10
  ## Install
9
11
 
10
12
  ```sh
@@ -32,6 +34,8 @@ setInterval(() => {
32
34
  }, 80);
33
35
  ```
34
36
 
37
+ You can use [yoctocolors](https://github.com/sindresorhus/yoctocolors) or [chalk](https://github.com/chalk/chalk) to colorize the output.
38
+
35
39
  ## API
36
40
 
37
41
  ### logUpdate(text…)
@@ -48,12 +52,33 @@ Persist the logged output.
48
52
 
49
53
  Useful if you want to start a new log session below the current one.
50
54
 
55
+ ### logUpdate.persist(text…)
56
+
57
+ Write text to the terminal that persists, similar to `console.log()`.
58
+
59
+ Unlike the main `logUpdate()` method which updates in place, `persist()` writes to the terminal in a way that preserves the output in the scrollback history.
60
+
61
+ ```js
62
+ import logUpdate from 'log-update';
63
+
64
+ // Update in place
65
+ logUpdate('Processing...');
66
+ logUpdate('Still processing...');
67
+
68
+ // Write permanent output
69
+ logUpdate.persist('✓ Task complete');
70
+
71
+ // Continue updating
72
+ logUpdate('Next task...');
73
+ ```
74
+
51
75
  ### logUpdateStderr(text…)
52
76
 
53
77
  Log to stderr.
54
78
 
55
79
  ### logUpdateStderr.clear()
56
80
  ### logUpdateStderr.done()
81
+ ### logUpdateStderr.persist(text…)
57
82
 
58
83
  ### createLogUpdate(stream, options?)
59
84
 
@@ -79,6 +104,42 @@ const log = createLogUpdate(process.stdout, {
79
104
  });
80
105
  ```
81
106
 
107
+ ##### defaultWidth
108
+
109
+ Type: `number`\
110
+ Default: `80`
111
+
112
+ The width to use when the stream doesn't provide a `columns` property.
113
+
114
+ This is useful when the output is piped, redirected, or in environments where the terminal size is not available.
115
+
116
+ ```js
117
+ import {createLogUpdate} from 'log-update';
118
+
119
+ // Use custom width when the stream doesn't provide columns
120
+ const log = createLogUpdate(process.stdout, {
121
+ defaultWidth: 120
122
+ });
123
+ ```
124
+
125
+ ##### defaultHeight
126
+
127
+ Type: `number`\
128
+ Default: `24`
129
+
130
+ The height to use when the stream doesn't provide a `rows` property.
131
+
132
+ This is useful when the output is piped, redirected, or in environments where the terminal size is not available.
133
+
134
+ ```js
135
+ import {createLogUpdate} from 'log-update';
136
+
137
+ // Use custom height when the stream doesn't provide rows
138
+ const log = createLogUpdate(process.stdout, {
139
+ defaultHeight: 50
140
+ });
141
+ ```
142
+
82
143
  ## Examples
83
144
 
84
145
  - [listr](https://github.com/SamVerschueren/listr) - Uses this module to render an interactive task list
@@ -2,8 +2,8 @@
2
2
  Slice a string with [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles)
3
3
 
4
4
  @param string - A string with ANSI escape codes. Like one styled by [`chalk`](https://github.com/chalk/chalk).
5
- @param startSlice - Zero-based index at which to start the slice.
6
- @param endSlice - Zero-based index at which to end the slice.
5
+ @param startSlice - Zero-based visible-column index at which to start the slice. Grapheme clusters are kept intact.
6
+ @param endSlice - Zero-based visible-column index at which to end the slice. If a full grapheme cluster would cross `endSlice`, it is excluded.
7
7
 
8
8
  @example
9
9
  ```
@@ -1,169 +1,317 @@
1
- import ansiStyles from 'ansi-styles';
2
- import isFullwidthCodePoint from 'is-fullwidth-code-point';
1
+ import tokenizeAnsi from './tokenize-ansi.js';
3
2
 
4
- // \x1b and \x9b
5
- const ESCAPES = new Set([27, 155]);
3
+ function applySgrFragments(activeStyles, fragments) {
4
+ for (const fragment of fragments) {
5
+ switch (fragment.type) {
6
+ case 'reset': {
7
+ activeStyles.clear();
8
+ break;
9
+ }
10
+
11
+ case 'end': {
12
+ activeStyles.delete(fragment.endCode);
13
+ break;
14
+ }
15
+
16
+ case 'start': {
17
+ activeStyles.delete(fragment.endCode);
18
+ activeStyles.set(fragment.endCode, fragment.code);
19
+ break;
20
+ }
21
+
22
+ default: {
23
+ break;
24
+ }
25
+ }
26
+ }
27
+
28
+ return activeStyles;
29
+ }
30
+
31
+ function undoAnsiCodes(activeStyles) {
32
+ return [...activeStyles.keys()].toReversed().join('');
33
+ }
34
+
35
+ function closeHyperlink(hyperlinkToken) {
36
+ return `${hyperlinkToken.closePrefix}${hyperlinkToken.terminator}`;
37
+ }
6
38
 
7
- const CODE_POINT_0 = '0'.codePointAt(0);
8
- const CODE_POINT_9 = '9'.codePointAt(0);
39
+ function shouldIncludeSgrAfterEnd(token, activeStyles) {
40
+ let hasStartFragment = false;
41
+ let hasClosingEffect = false;
9
42
 
10
- const MAX_ANSI_SEQUENCE_LENGTH = 19;
43
+ for (const fragment of token.fragments) {
44
+ if (fragment.type === 'start') {
45
+ hasStartFragment = true;
46
+ continue;
47
+ }
48
+
49
+ if (fragment.type === 'reset' && activeStyles.size > 0) {
50
+ hasClosingEffect = true;
51
+ continue;
52
+ }
53
+
54
+ if (fragment.type === 'end' && activeStyles.has(fragment.endCode)) {
55
+ hasClosingEffect = true;
56
+ }
57
+ }
58
+
59
+ return hasClosingEffect && !hasStartFragment;
60
+ }
11
61
 
12
- const endCodesSet = new Set();
13
- const endCodesMap = new Map();
14
- for (const [start, end] of ansiStyles.codes) {
15
- endCodesSet.add(ansiStyles.color.ansi(end));
16
- endCodesMap.set(ansiStyles.color.ansi(start), ansiStyles.color.ansi(end));
62
+ function hasSgrStartFragment(token) {
63
+ return token.fragments.some(fragment => fragment.type === 'start');
17
64
  }
18
65
 
19
- function getEndCode(code) {
20
- if (endCodesSet.has(code)) {
21
- return code;
66
+ function discardPendingHyperlink(parameters) {
67
+ if (
68
+ parameters.activeHyperlink
69
+ && !parameters.activeHyperlinkHasVisibleText
70
+ && parameters.activeHyperlinkOutputIndex !== undefined
71
+ ) {
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
+ }
22
81
  }
23
82
 
24
- if (endCodesMap.has(code)) {
25
- return endCodesMap.get(code);
83
+ parameters.activeHyperlink = undefined;
84
+ parameters.activeHyperlinkHasVisibleText = false;
85
+ parameters.activeHyperlinkOutputIndex = undefined;
86
+ }
87
+
88
+ function applySgrToken(parameters) {
89
+ if (
90
+ parameters.isPastEnd
91
+ && !shouldIncludeSgrAfterEnd(parameters.token, parameters.activeStyles)
92
+ ) {
93
+ return parameters;
26
94
  }
27
95
 
28
- code = code.slice(2);
29
- if (code.includes(';')) {
30
- code = code[0] + '0';
96
+ if (
97
+ parameters.include
98
+ && hasSgrStartFragment(parameters.token)
99
+ && parameters.pendingSgrOutputIndex === undefined
100
+ ) {
101
+ parameters.pendingSgrOutputIndex = parameters.returnValue.length;
102
+ parameters.pendingSgrActiveStyles = new Map(parameters.activeStyles);
31
103
  }
32
104
 
33
- const returnValue = ansiStyles.codes.get(Number.parseInt(code, 10));
34
- if (returnValue) {
35
- return ansiStyles.color.ansi(returnValue);
105
+ parameters.activeStyles = applySgrFragments(parameters.activeStyles, parameters.token.fragments);
106
+ if (parameters.include) {
107
+ parameters.returnValue += parameters.token.code;
36
108
  }
37
109
 
38
- return ansiStyles.reset.open;
110
+ return parameters;
39
111
  }
40
112
 
41
- function findNumberIndex(string) {
42
- for (let index = 0; index < string.length; index++) {
43
- const codePoint = string.codePointAt(index);
44
- if (codePoint >= CODE_POINT_0 && codePoint <= CODE_POINT_9) {
45
- return index;
113
+ function applyHyperlinkToken(parameters) {
114
+ if (
115
+ parameters.isPastEnd
116
+ && (
117
+ parameters.token.action !== 'close'
118
+ || !parameters.activeHyperlink
119
+ )
120
+ ) {
121
+ return parameters;
122
+ }
123
+
124
+ if (parameters.token.action === 'open') {
125
+ parameters.activeHyperlink = parameters.token;
126
+ parameters.activeHyperlinkHasVisibleText = false;
127
+ parameters.activeHyperlinkOutputIndex = undefined;
128
+ if (parameters.include) {
129
+ parameters.activeHyperlinkOutputIndex = parameters.returnValue.length;
130
+ }
131
+ } else if (parameters.token.action === 'close') {
132
+ if (
133
+ parameters.include
134
+ && parameters.activeHyperlink
135
+ && !parameters.activeHyperlinkHasVisibleText
136
+ ) {
137
+ discardPendingHyperlink(parameters);
138
+ return parameters;
46
139
  }
140
+
141
+ parameters.activeHyperlink = undefined;
142
+ parameters.activeHyperlinkHasVisibleText = false;
143
+ parameters.activeHyperlinkOutputIndex = undefined;
47
144
  }
48
145
 
49
- return -1;
50
- }
146
+ if (parameters.include) {
147
+ parameters.returnValue += parameters.token.code;
148
+ }
51
149
 
52
- function parseAnsiCode(string, offset) {
53
- string = string.slice(offset, offset + MAX_ANSI_SEQUENCE_LENGTH);
54
- const startIndex = findNumberIndex(string);
55
- if (startIndex !== -1) {
56
- let endIndex = string.indexOf('m', startIndex);
57
- if (endIndex === -1) {
58
- endIndex = string.length;
59
- }
150
+ return parameters;
151
+ }
60
152
 
61
- return string.slice(0, endIndex + 1);
153
+ function applyControlToken(parameters) {
154
+ if (!parameters.isPastEnd && parameters.include) {
155
+ parameters.returnValue += parameters.token.code;
62
156
  }
157
+
158
+ return parameters;
63
159
  }
64
160
 
65
- function tokenize(string, endCharacter = Number.POSITIVE_INFINITY) {
66
- const returnValue = [];
67
-
68
- let index = 0;
69
- let visibleCount = 0;
70
- while (index < string.length) {
71
- const codePoint = string.codePointAt(index);
72
-
73
- if (ESCAPES.has(codePoint)) {
74
- const code = parseAnsiCode(string, index);
75
- if (code) {
76
- returnValue.push({
77
- type: 'ansi',
78
- code,
79
- endCode: getEndCode(code),
80
- });
81
- index += code.length;
82
- continue;
83
- }
161
+ function applyCharacterToken(parameters) {
162
+ if (
163
+ !parameters.include
164
+ && parameters.position >= parameters.start
165
+ && !parameters.token.isGraphemeContinuation
166
+ ) {
167
+ parameters.include = true;
168
+ parameters.returnValue = [...parameters.activeStyles.values()].join('');
169
+ if (parameters.activeHyperlink) {
170
+ parameters.activeHyperlinkOutputIndex = parameters.returnValue.length;
171
+ parameters.returnValue += parameters.activeHyperlink.code;
84
172
  }
173
+ }
85
174
 
86
- const isFullWidth = isFullwidthCodePoint(codePoint);
87
- const character = String.fromCodePoint(codePoint);
175
+ if (parameters.include) {
176
+ parameters.returnValue += parameters.token.value;
177
+ parameters.pendingSgrOutputIndex = undefined;
178
+ parameters.pendingSgrActiveStyles = undefined;
179
+ if (parameters.activeHyperlink) {
180
+ parameters.activeHyperlinkHasVisibleText = true;
181
+ }
182
+ }
88
183
 
89
- returnValue.push({
90
- type: 'character',
91
- value: character,
92
- isFullWidth,
93
- });
184
+ parameters.position += parameters.token.visibleWidth;
185
+ return parameters;
186
+ }
94
187
 
95
- index += character.length;
96
- visibleCount += isFullWidth ? 2 : character.length;
188
+ const tokenHandlers = {
189
+ sgr: applySgrToken,
190
+ hyperlink: applyHyperlinkToken,
191
+ control: applyControlToken,
192
+ character: applyCharacterToken,
193
+ };
97
194
 
98
- if (visibleCount >= endCharacter) {
99
- break;
100
- }
195
+ function applyToken(parameters) {
196
+ const tokenHandler = tokenHandlers[parameters.token.type];
197
+ if (!tokenHandler) {
198
+ return parameters;
101
199
  }
102
200
 
103
- return returnValue;
201
+ return tokenHandler(parameters);
104
202
  }
105
203
 
106
- function reduceAnsiCodes(codes) {
107
- let returnValue = [];
108
-
109
- for (const code of codes) {
110
- if (code.code === ansiStyles.reset.open) {
111
- // Reset code, disable all codes
112
- returnValue = [];
113
- } else if (endCodesSet.has(code.code)) {
114
- // This is an end code, disable all matching start codes
115
- returnValue = returnValue.filter(returnValueCode => returnValueCode.endCode !== code.code);
116
- } else {
117
- // This is a start code. Disable all styles this "overrides", then enable it
118
- returnValue = returnValue.filter(returnValueCode => returnValueCode.endCode !== code.endCode);
119
- returnValue.push(code);
204
+ function createHasContinuationAheadMap(tokens) {
205
+ const hasContinuationAhead = Array.from({length: tokens.length}, () => false);
206
+ let nextCharacterIsContinuation = false;
207
+
208
+ for (let tokenIndex = tokens.length - 1; tokenIndex >= 0; tokenIndex--) {
209
+ const token = tokens[tokenIndex];
210
+ hasContinuationAhead[tokenIndex] = nextCharacterIsContinuation;
211
+ if (token.type === 'character') {
212
+ nextCharacterIsContinuation = Boolean(token.isGraphemeContinuation);
120
213
  }
121
214
  }
122
215
 
123
- return returnValue;
216
+ return hasContinuationAhead;
124
217
  }
125
218
 
126
- function undoAnsiCodes(codes) {
127
- const reduced = reduceAnsiCodes(codes);
128
- const endCodes = reduced.map(({endCode}) => endCode);
129
- return endCodes.reverse().join('');
219
+ function isPastEndBoundary(token, position, end) {
220
+ if (end === undefined) {
221
+ return false;
222
+ }
223
+
224
+ if (position >= end) {
225
+ return true;
226
+ }
227
+
228
+ return token.type === 'character'
229
+ && !token.isGraphemeContinuation
230
+ && position + token.visibleWidth > end;
130
231
  }
131
232
 
132
233
  export default function sliceAnsi(string, start, end) {
133
- const tokens = tokenize(string, end);
134
- let activeCodes = [];
234
+ const tokens = tokenizeAnsi(string, {endCharacter: end});
235
+ const hasContinuationAhead = createHasContinuationAheadMap(tokens);
236
+ let activeStyles = new Map();
237
+ let activeHyperlink;
238
+ let activeHyperlinkHasVisibleText = false;
239
+ let activeHyperlinkOutputIndex;
240
+ let pendingSgrOutputIndex;
241
+ let pendingSgrActiveStyles;
135
242
  let position = 0;
136
243
  let returnValue = '';
137
244
  let include = false;
138
245
 
139
- for (const token of tokens) {
140
- if (end !== undefined && position >= end) {
141
- break;
246
+ for (const [tokenIndex, token] of tokens.entries()) {
247
+ let isPastEnd = isPastEndBoundary(token, position, end);
248
+ if (
249
+ isPastEnd
250
+ && token.type !== 'character'
251
+ && hasContinuationAhead[tokenIndex]
252
+ ) {
253
+ isPastEnd = false;
142
254
  }
143
255
 
144
- if (token.type === 'ansi') {
145
- activeCodes.push(token);
146
- if (include) {
147
- returnValue += token.code;
148
- }
149
- } else {
150
- // Character
151
- if (!include && position >= start) {
152
- include = true;
153
- // Simplify active codes
154
- activeCodes = reduceAnsiCodes(activeCodes);
155
- returnValue = activeCodes.map(({code}) => code).join('');
256
+ if (
257
+ isPastEnd
258
+ && token.type === 'character'
259
+ && !token.isGraphemeContinuation
260
+ ) {
261
+ if (activeHyperlink && !activeHyperlinkHasVisibleText) {
262
+ const hyperlinkState = {
263
+ activeHyperlink,
264
+ activeHyperlinkHasVisibleText,
265
+ activeHyperlinkOutputIndex,
266
+ pendingSgrOutputIndex,
267
+ returnValue,
268
+ };
269
+ discardPendingHyperlink(hyperlinkState);
270
+ ({
271
+ activeHyperlink,
272
+ activeHyperlinkHasVisibleText,
273
+ activeHyperlinkOutputIndex,
274
+ pendingSgrOutputIndex,
275
+ returnValue,
276
+ } = hyperlinkState);
156
277
  }
157
278
 
158
- if (include) {
159
- returnValue += token.value;
279
+ if (pendingSgrOutputIndex !== undefined) {
280
+ returnValue = returnValue.slice(0, pendingSgrOutputIndex);
281
+ activeStyles = pendingSgrActiveStyles;
282
+ pendingSgrOutputIndex = undefined;
283
+ pendingSgrActiveStyles = undefined;
160
284
  }
161
285
 
162
- position += token.isFullWidth ? 2 : token.value.length;
286
+ break;
163
287
  }
288
+
289
+ ({activeStyles, activeHyperlink, activeHyperlinkHasVisibleText, activeHyperlinkOutputIndex, pendingSgrOutputIndex, pendingSgrActiveStyles, position, returnValue, include} = applyToken({
290
+ token,
291
+ isPastEnd,
292
+ start,
293
+ activeStyles,
294
+ activeHyperlink,
295
+ activeHyperlinkHasVisibleText,
296
+ activeHyperlinkOutputIndex,
297
+ pendingSgrOutputIndex,
298
+ pendingSgrActiveStyles,
299
+ position,
300
+ returnValue,
301
+ include,
302
+ }));
303
+ }
304
+
305
+ if (!include) {
306
+ return '';
307
+ }
308
+
309
+ if (activeHyperlink) {
310
+ returnValue += closeHyperlink(activeHyperlink);
164
311
  }
165
312
 
166
313
  // Disable active codes at the end
167
- returnValue += undoAnsiCodes(activeCodes);
314
+ returnValue += undoAnsiCodes(activeStyles);
315
+
168
316
  return returnValue;
169
317
  }