11// Import Node.js Dependencies
22import { EventEmitter } from "node:events" ;
33import { performance } from "node:perf_hooks" ;
4+ import { inspect , styleText } from "node:util" ;
45import readline from "node:readline" ;
56import * as TTY from "node:tty" ;
67
78// Import Third-party Dependencies
89import * as cliSpinners from "cli-spinners" ;
9- import stripAnsi from "strip-ansi" ;
10- import ansiRegex from "ansi-regex" ;
11- import wcwidth from "@topcli/wcwidth" ;
12- import kleur from "kleur" ;
10+
11+ // Import Internal Dependencies
12+ import {
13+ stringLength ,
14+ type Color
15+ } from "./utils/index.js" ;
1316
1417// VARS
1518let internalSpinnerCount = 0 ;
1619
1720// CONSTANTS
1821const kDefaultSpinnerName = "dots" satisfies cliSpinners . SpinnerName ;
22+ const kAvailableColors = new Set < Color > (
23+ Object . keys ( inspect . colors ) as Color [ ]
24+ ) ;
25+
1926const kLogSymbols = process . platform !== "win32" || process . env . CI || process . env . TERM === "xterm-256color" ?
20- { success : kleur . bold ( ) . green ( " ✔") , error : kleur . bold ( ) . red ( "✖" ) } :
21- { success : kleur . bold ( ) . green ( " √") , error : kleur . bold ( ) . red ( "×" ) } ;
27+ { success : styleText ( " green" , " ✔") , error : styleText ( " red" , "✖" ) } :
28+ { success : styleText ( " green" , " √") , error : styleText ( " red" , "×" ) } ;
2229
2330export interface ISpinnerOptions {
2431 /**
@@ -32,7 +39,7 @@ export interface ISpinnerOptions {
3239 *
3340 * @default "white"
3441 */
35- color ?: string ;
42+ color ?: Color ;
3643 /**
3744 * Do not log anything when disabled
3845 *
@@ -73,12 +80,18 @@ export class Spinner extends EventEmitter {
7380
7481 const { name = kDefaultSpinnerName , color = null } = options ;
7582
76- this . #spinner = name in cliSpinners ? cliSpinners [ name ] : cliSpinners [ kDefaultSpinnerName ] ;
83+ this . #spinner = name in cliSpinners ?
84+ cliSpinners . default [ name ] :
85+ cliSpinners . default [ kDefaultSpinnerName ] ;
7786 if ( color === null ) {
7887 this . #color = ( str : string ) => str ;
7988 }
8089 else {
81- this . #color = color in kleur ? kleur [ color ] : kleur . white ;
90+ const colorArr = Array . isArray ( color ) ? color : [ color ] ;
91+
92+ this . #color = colorArr . every ( ( color ) => kAvailableColors . has ( color ) ) ?
93+ ( str ) => styleText ( color , str ) :
94+ ( str ) => styleText ( "white" , str ) ;
8295 }
8396 }
8497
@@ -135,9 +148,9 @@ export class Spinner extends EventEmitter {
135148 }
136149 count = regexArray . length ;
137150 }
138- count += regexArray ! . reduce ( ( prev , curr ) => prev + wcwidth ( curr ) , 0 ) ;
151+ count += regexArray ! . reduce ( ( prev , curr ) => prev + stringLength ( curr ) , 0 ) ;
139152
140- return wcwidth ( stripAnsi ( defaultRaw ) ) > terminalCol ?
153+ return stringLength ( defaultRaw ) > terminalCol ?
141154 `${ defaultRaw . slice ( 0 , terminalCol + count ) } \x1B[0m` :
142155 defaultRaw ;
143156 }
@@ -153,7 +166,7 @@ export class Spinner extends EventEmitter {
153166 const line = this . #lineToRender( spinnerSymbol ) ;
154167 readline . clearLine ( this . stream , 0 ) ;
155168 this . stream . write ( line ) ;
156- readline . moveCursor ( this . stream , - ( wcwidth ( line ) ) , moveCursorPos ) ;
169+ readline . moveCursor ( this . stream , - ( stringLength ( line ) ) , moveCursorPos ) ;
157170 }
158171
159172 start ( text ?: string , options : IStartOptions = { } ) {
@@ -210,3 +223,17 @@ export class Spinner extends EventEmitter {
210223 return this ;
211224 }
212225}
226+
227+ /**
228+ * @note code copy-pasted from https://github.com/chalk/ansi-regex#readme
229+ */
230+ function ansiRegex ( ) {
231+ // Valid string terminator sequences are BEL, ESC\, and 0x9c
232+ const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)" ;
233+ const pattern = [
234+ `[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?${ ST } )` ,
235+ "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"
236+ ] . join ( "|" ) ;
237+
238+ return new RegExp ( pattern , "g" ) ;
239+ }
0 commit comments