@node-core/utils 7.1.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 (232) hide show
  1. package/components/metadata.js +2 -1
  2. package/lib/ci/build-types/test_build.js +3 -3
  3. package/lib/ci/failure_aggregator.js +2 -2
  4. package/lib/ci/run_ci.js +3 -2
  5. package/lib/cli.js +6 -6
  6. package/lib/figures.js +6 -6
  7. package/lib/prepare_security.js +20 -21
  8. package/lib/request.js +1 -1
  9. package/lib/update-v8/backport.js +3 -4
  10. package/lib/utils.js +4 -2
  11. package/lib/verbosity.js +2 -4
  12. package/node_modules/@listr2/{prompt-adapter-enquirer → prompt-adapter-inquirer}/README.md +4 -4
  13. package/node_modules/@listr2/prompt-adapter-inquirer/dist/index.d.mts +21 -0
  14. package/node_modules/@listr2/prompt-adapter-inquirer/dist/index.mjs +46 -0
  15. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/LICENSE +22 -0
  16. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/index.d.ts +2 -0
  17. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/index.js +2 -0
  18. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/inquirer.d.ts +35 -0
  19. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/inquirer.js +1 -0
  20. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/utils.d.ts +34 -0
  21. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/dist/utils.js +2 -0
  22. package/node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type/package.json +88 -0
  23. package/node_modules/@listr2/{prompt-adapter-enquirer → prompt-adapter-inquirer}/package.json +25 -20
  24. package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/base.d.ts +48 -3
  25. package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/base.js +58 -19
  26. package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/package.json +1 -1
  27. package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/readme.md +36 -1
  28. package/node_modules/ansi-regex/index.js +9 -4
  29. package/node_modules/ansi-regex/package.json +1 -1
  30. package/node_modules/ansi-regex/readme.md +6 -0
  31. package/node_modules/ansi-styles/index.d.ts +12 -12
  32. package/node_modules/ansi-styles/index.js +3 -3
  33. package/node_modules/ansi-styles/package.json +4 -4
  34. package/node_modules/cli-truncate/index.d.ts +3 -3
  35. package/node_modules/cli-truncate/index.js +40 -14
  36. package/node_modules/cli-truncate/node_modules/string-width/index.js +133 -15
  37. package/node_modules/cli-truncate/node_modules/string-width/package.json +4 -4
  38. package/node_modules/cli-truncate/node_modules/string-width/readme.md +1 -1
  39. package/node_modules/cli-truncate/package.json +7 -7
  40. package/node_modules/cli-truncate/readme.md +2 -3
  41. package/node_modules/ghauth/.github/dependabot.yml +11 -3
  42. package/node_modules/ghauth/.github/workflows/depsound.yml +33 -0
  43. package/node_modules/ghauth/.github/workflows/test-and-release.yml +4 -4
  44. package/node_modules/ghauth/CHANGELOG.md +60 -0
  45. package/node_modules/ghauth/package.json +30 -6
  46. package/node_modules/js-yaml/README.md +20 -187
  47. package/node_modules/js-yaml/dist/browser/js-yaml.esm.min.mjs +1008 -946
  48. package/node_modules/js-yaml/dist/browser/js-yaml.esm.min.mjs.map +1 -1
  49. package/node_modules/js-yaml/dist/browser/js-yaml.umd.min.js +29 -23
  50. package/node_modules/js-yaml/dist/browser/js-yaml.umd.min.js.map +1 -1
  51. package/node_modules/js-yaml/dist/js-yaml.cjs.js +1043 -583
  52. package/node_modules/js-yaml/dist/js-yaml.cjs.js.map +1 -1
  53. package/node_modules/js-yaml/dist/js-yaml.d.ts +877 -133
  54. package/node_modules/js-yaml/dist/js-yaml.mjs +995 -556
  55. package/node_modules/js-yaml/dist/js-yaml.mjs.map +1 -1
  56. package/node_modules/js-yaml/package.json +8 -7
  57. package/node_modules/listr2/dist/{index.d.cts → index.d.mts} +90 -60
  58. package/node_modules/listr2/dist/{index.js → index.mjs} +496 -373
  59. package/node_modules/listr2/node_modules/string-width/index.d.ts +39 -0
  60. package/node_modules/listr2/node_modules/string-width/index.js +207 -0
  61. package/node_modules/listr2/node_modules/string-width/package.json +65 -0
  62. package/node_modules/listr2/node_modules/string-width/readme.md +66 -0
  63. package/node_modules/listr2/node_modules/wrap-ansi/index.d.ts +1 -1
  64. package/node_modules/listr2/node_modules/wrap-ansi/index.js +544 -116
  65. package/node_modules/listr2/node_modules/wrap-ansi/package.json +10 -13
  66. package/node_modules/listr2/node_modules/wrap-ansi/readme.md +2 -0
  67. package/node_modules/listr2/package.json +16 -19
  68. package/node_modules/log-update/index.d.ts +64 -1
  69. package/node_modules/log-update/index.js +268 -18
  70. package/node_modules/log-update/node_modules/string-width/index.d.ts +39 -0
  71. package/node_modules/log-update/node_modules/string-width/index.js +207 -0
  72. package/node_modules/log-update/node_modules/string-width/package.json +65 -0
  73. package/node_modules/log-update/node_modules/string-width/readme.md +66 -0
  74. package/node_modules/log-update/node_modules/wrap-ansi/index.d.ts +1 -1
  75. package/node_modules/log-update/node_modules/wrap-ansi/index.js +544 -116
  76. package/node_modules/log-update/node_modules/wrap-ansi/package.json +10 -13
  77. package/node_modules/log-update/node_modules/wrap-ansi/readme.md +2 -0
  78. package/node_modules/log-update/package.json +14 -12
  79. package/node_modules/log-update/readme.md +61 -0
  80. package/node_modules/slice-ansi/index.d.ts +2 -2
  81. package/node_modules/slice-ansi/index.js +260 -112
  82. package/node_modules/slice-ansi/package.json +10 -9
  83. package/node_modules/slice-ansi/readme.md +3 -2
  84. package/node_modules/slice-ansi/tokenize-ansi.js +752 -0
  85. package/node_modules/smol-toml/README.md +205 -191
  86. package/node_modules/smol-toml/dist/date.d.ts +0 -1
  87. package/node_modules/smol-toml/dist/date.js +0 -1
  88. package/node_modules/smol-toml/dist/error.d.ts +0 -1
  89. package/node_modules/smol-toml/dist/error.js +0 -1
  90. package/node_modules/smol-toml/dist/extract.js +32 -65
  91. package/node_modules/smol-toml/dist/index.cjs +302 -288
  92. package/node_modules/smol-toml/dist/index.d.ts +0 -1
  93. package/node_modules/smol-toml/dist/index.js +0 -1
  94. package/node_modules/smol-toml/dist/parse.d.ts +1 -3
  95. package/node_modules/smol-toml/dist/parse.js +22 -21
  96. package/node_modules/smol-toml/dist/primitive.js +75 -76
  97. package/node_modules/smol-toml/dist/stringify.d.ts +0 -1
  98. package/node_modules/smol-toml/dist/stringify.js +43 -30
  99. package/node_modules/smol-toml/dist/struct.js +90 -93
  100. package/node_modules/smol-toml/dist/util.d.ts +1 -1
  101. package/node_modules/smol-toml/dist/util.js +36 -39
  102. package/node_modules/smol-toml/package.json +6 -6
  103. package/node_modules/strip-ansi/index.js +5 -0
  104. package/node_modules/strip-ansi/package.json +5 -5
  105. package/package.json +3 -9
  106. package/node_modules/@listr2/prompt-adapter-enquirer/dist/index.cjs +0 -127
  107. package/node_modules/@listr2/prompt-adapter-enquirer/dist/index.d.cts +0 -152
  108. package/node_modules/@listr2/prompt-adapter-enquirer/dist/index.d.ts +0 -152
  109. package/node_modules/@listr2/prompt-adapter-enquirer/dist/index.js +0 -92
  110. package/node_modules/chalk/package.json +0 -92
  111. package/node_modules/chalk/readme.md +0 -331
  112. package/node_modules/chalk/source/index.d.ts +0 -437
  113. package/node_modules/chalk/source/index.js +0 -261
  114. package/node_modules/chalk/source/utilities.js +0 -33
  115. package/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +0 -299
  116. package/node_modules/chalk/source/vendor/ansi-styles/index.js +0 -261
  117. package/node_modules/chalk/source/vendor/supports-color/browser.d.ts +0 -1
  118. package/node_modules/chalk/source/vendor/supports-color/browser.js +0 -32
  119. package/node_modules/chalk/source/vendor/supports-color/index.d.ts +0 -55
  120. package/node_modules/chalk/source/vendor/supports-color/index.js +0 -206
  121. package/node_modules/colorette/LICENSE.md +0 -7
  122. package/node_modules/colorette/README.md +0 -134
  123. package/node_modules/colorette/index.cjs +0 -218
  124. package/node_modules/colorette/index.d.ts +0 -93
  125. package/node_modules/colorette/index.js +0 -150
  126. package/node_modules/colorette/package.json +0 -40
  127. package/node_modules/eventemitter3/LICENSE +0 -21
  128. package/node_modules/eventemitter3/README.md +0 -94
  129. package/node_modules/eventemitter3/dist/eventemitter3.esm.js +0 -347
  130. package/node_modules/eventemitter3/dist/eventemitter3.esm.min.js +0 -1
  131. package/node_modules/eventemitter3/dist/eventemitter3.esm.min.js.map +0 -1
  132. package/node_modules/eventemitter3/dist/eventemitter3.umd.js +0 -355
  133. package/node_modules/eventemitter3/dist/eventemitter3.umd.min.js +0 -1
  134. package/node_modules/eventemitter3/dist/eventemitter3.umd.min.js.map +0 -1
  135. package/node_modules/eventemitter3/index.d.ts +0 -135
  136. package/node_modules/eventemitter3/index.js +0 -336
  137. package/node_modules/eventemitter3/index.mjs +0 -4
  138. package/node_modules/eventemitter3/package.json +0 -67
  139. package/node_modules/figures/index.d.ts +0 -279
  140. package/node_modules/figures/index.js +0 -292
  141. package/node_modules/figures/package.json +0 -49
  142. package/node_modules/figures/readme.md +0 -337
  143. package/node_modules/isexe/LICENSE.md +0 -55
  144. package/node_modules/isexe/README.md +0 -80
  145. package/node_modules/isexe/dist/commonjs/index.d.ts +0 -14
  146. package/node_modules/isexe/dist/commonjs/index.d.ts.map +0 -1
  147. package/node_modules/isexe/dist/commonjs/index.js +0 -56
  148. package/node_modules/isexe/dist/commonjs/index.js.map +0 -1
  149. package/node_modules/isexe/dist/commonjs/index.min.js +0 -2
  150. package/node_modules/isexe/dist/commonjs/index.min.js.map +0 -7
  151. package/node_modules/isexe/dist/commonjs/options.d.ts +0 -32
  152. package/node_modules/isexe/dist/commonjs/options.d.ts.map +0 -1
  153. package/node_modules/isexe/dist/commonjs/options.js +0 -3
  154. package/node_modules/isexe/dist/commonjs/options.js.map +0 -1
  155. package/node_modules/isexe/dist/commonjs/package.json +0 -3
  156. package/node_modules/isexe/dist/commonjs/posix.d.ts +0 -18
  157. package/node_modules/isexe/dist/commonjs/posix.d.ts.map +0 -1
  158. package/node_modules/isexe/dist/commonjs/posix.js +0 -67
  159. package/node_modules/isexe/dist/commonjs/posix.js.map +0 -1
  160. package/node_modules/isexe/dist/commonjs/win32.d.ts +0 -18
  161. package/node_modules/isexe/dist/commonjs/win32.d.ts.map +0 -1
  162. package/node_modules/isexe/dist/commonjs/win32.js +0 -63
  163. package/node_modules/isexe/dist/commonjs/win32.js.map +0 -1
  164. package/node_modules/isexe/dist/esm/index.d.ts +0 -14
  165. package/node_modules/isexe/dist/esm/index.d.ts.map +0 -1
  166. package/node_modules/isexe/dist/esm/index.js +0 -16
  167. package/node_modules/isexe/dist/esm/index.js.map +0 -1
  168. package/node_modules/isexe/dist/esm/index.min.js +0 -2
  169. package/node_modules/isexe/dist/esm/index.min.js.map +0 -7
  170. package/node_modules/isexe/dist/esm/options.d.ts +0 -32
  171. package/node_modules/isexe/dist/esm/options.d.ts.map +0 -1
  172. package/node_modules/isexe/dist/esm/options.js +0 -2
  173. package/node_modules/isexe/dist/esm/options.js.map +0 -1
  174. package/node_modules/isexe/dist/esm/package.json +0 -3
  175. package/node_modules/isexe/dist/esm/posix.d.ts +0 -18
  176. package/node_modules/isexe/dist/esm/posix.d.ts.map +0 -1
  177. package/node_modules/isexe/dist/esm/posix.js +0 -62
  178. package/node_modules/isexe/dist/esm/posix.js.map +0 -1
  179. package/node_modules/isexe/dist/esm/win32.d.ts +0 -18
  180. package/node_modules/isexe/dist/esm/win32.d.ts.map +0 -1
  181. package/node_modules/isexe/dist/esm/win32.js +0 -58
  182. package/node_modules/isexe/dist/esm/win32.js.map +0 -1
  183. package/node_modules/isexe/package.json +0 -78
  184. package/node_modules/listr2/dist/index.cjs +0 -2189
  185. package/node_modules/listr2/dist/index.d.ts +0 -1528
  186. package/node_modules/rfdc/.github/workflows/ci.yml +0 -21
  187. package/node_modules/rfdc/LICENSE +0 -15
  188. package/node_modules/rfdc/default.js +0 -3
  189. package/node_modules/rfdc/index.d.ts +0 -13
  190. package/node_modules/rfdc/index.js +0 -198
  191. package/node_modules/rfdc/index.test-d.ts +0 -13
  192. package/node_modules/rfdc/package.json +0 -73
  193. package/node_modules/rfdc/readme.md +0 -181
  194. package/node_modules/rfdc/test/index.js +0 -306
  195. package/node_modules/smol-toml/dist/date.d.ts.map +0 -1
  196. package/node_modules/smol-toml/dist/date.js.map +0 -1
  197. package/node_modules/smol-toml/dist/error.d.ts.map +0 -1
  198. package/node_modules/smol-toml/dist/error.js.map +0 -1
  199. package/node_modules/smol-toml/dist/extract.js.map +0 -1
  200. package/node_modules/smol-toml/dist/index.cjs.map +0 -1
  201. package/node_modules/smol-toml/dist/index.d.ts.map +0 -1
  202. package/node_modules/smol-toml/dist/index.js.map +0 -1
  203. package/node_modules/smol-toml/dist/parse.d.ts.map +0 -1
  204. package/node_modules/smol-toml/dist/parse.js.map +0 -1
  205. package/node_modules/smol-toml/dist/primitive.d.ts +0 -29
  206. package/node_modules/smol-toml/dist/primitive.d.ts.map +0 -1
  207. package/node_modules/smol-toml/dist/primitive.js.map +0 -1
  208. package/node_modules/smol-toml/dist/stringify.d.ts.map +0 -1
  209. package/node_modules/smol-toml/dist/stringify.js.map +0 -1
  210. package/node_modules/smol-toml/dist/struct.js.map +0 -1
  211. package/node_modules/smol-toml/dist/util.d.ts.map +0 -1
  212. package/node_modules/smol-toml/dist/util.js.map +0 -1
  213. package/node_modules/smol-toml/src/date.ts +0 -152
  214. package/node_modules/smol-toml/src/error.ts +0 -77
  215. package/node_modules/smol-toml/src/extract.ts +0 -113
  216. package/node_modules/smol-toml/src/index.ts +0 -42
  217. package/node_modules/smol-toml/src/parse.ts +0 -184
  218. package/node_modules/smol-toml/src/primitive.ts +0 -249
  219. package/node_modules/smol-toml/src/stringify.ts +0 -191
  220. package/node_modules/smol-toml/src/struct.ts +0 -202
  221. package/node_modules/smol-toml/src/util.ts +0 -106
  222. package/node_modules/which/LICENSE +0 -15
  223. package/node_modules/which/README.md +0 -51
  224. package/node_modules/which/bin/which.js +0 -52
  225. package/node_modules/which/lib/index.js +0 -111
  226. package/node_modules/which/package.json +0 -52
  227. /package/node_modules/@listr2/{prompt-adapter-enquirer → prompt-adapter-inquirer}/LICENSE +0 -0
  228. /package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/index.d.ts +0 -0
  229. /package/node_modules/{log-update/node_modules/ansi-escapes → ansi-escapes}/index.js +0 -0
  230. /package/node_modules/{chalk → ansi-escapes}/license +0 -0
  231. /package/node_modules/{figures → listr2/node_modules/string-width}/license +0 -0
  232. /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
  }