@@ -0,0 +1,471 @@
// Vendored and converted to TS, source: https://github.com/xpl/ansicolor/blob/b82360563ed29de444dc7618b9236191e0a77096/ansicolor.js
// License: Unlicense, author: https://github.com/xpl
const O = Object ;
/* See https://misc.flogisoft.com/bash/tip_colors_and_formatting
------------------------------------------------------------------------ */
const colorCodes = [ 'black' , 'red' , 'green' , 'yellow' , 'blue' , 'magenta' , 'cyan' , 'lightGray' , '' , 'default' ] ,
colorCodesLight = [
'darkGray' ,
'lightRed' ,
'lightGreen' ,
'lightYellow' ,
'lightBlue' ,
'lightMagenta' ,
'lightCyan' ,
'white' ,
'' ,
] ,
styleCodes = [ '' , 'bright' , 'dim' , 'italic' , 'underline' , '' , '' , 'inverse' ] ,
asBright = {
red : 'lightRed' ,
green : 'lightGreen' ,
yellow : 'lightYellow' ,
blue : 'lightBlue' ,
magenta : 'lightMagenta' ,
cyan : 'lightCyan' ,
black : 'darkGray' ,
lightGray : 'white' ,
} ,
types = {
0 : 'style' ,
2 : 'unstyle' ,
3 : 'color' ,
9 : 'colorLight' ,
4 : 'bgColor' ,
10 : 'bgColorLight' ,
} ,
subtypes = {
color : colorCodes ,
colorLight : colorCodesLight ,
bgColor : colorCodes ,
bgColorLight : colorCodesLight ,
style : styleCodes ,
unstyle : styleCodes ,
} ;
/* ------------------------------------------------------------------------ */
const clean = obj = > {
for ( const k in obj ) {
if ( ! obj [ k ] ) {
delete obj [ k ] ;
}
}
return O . keys ( obj ) . length === 0 ? undefined : obj ;
} ;
/* ------------------------------------------------------------------------ */
class Color {
background : string ;
name : string ;
brightness : number ;
constructor ( background ? , name ? , brightness ? ) {
this . background = background ;
this . name = name ;
this . brightness = brightness ;
}
get inverse() {
return new Color ( ! this . background , this . name || ( this . background ? 'black' : 'white' ) , this . brightness ) ;
}
get clean() {
return clean ( {
name : this.name === 'default' ? '' : this . name ,
bright : this.brightness === Code . bright ,
dim : this.brightness === Code . dim ,
} ) ;
}
defaultBrightness ( value ) {
return new Color ( this . background , this . name , this . brightness || value ) ;
}
css ( inverted ) {
const color = inverted ? this . inverse : this ;
const rgbName = ( color . brightness === Code . bright && asBright [ color . name ] ) || color . name ;
const prop = color . background ? 'background:' : 'color:' ,
rgb = Colors . rgb [ rgbName ] ,
alpha = this . brightness === Code . dim ? 0.5 : 1 ;
return rgb
? prop + 'rgba(' + [ . . . rgb , alpha ] . join ( ',' ) + ');'
: ! color . background && alpha < 1 ? 'color:rgba(0,0,0,0.5);' : '' ; // Chrome does not support 'opacity' property...
}
}
/* ------------------------------------------------------------------------ */
class Code {
static reset = 0 ;
static bright = 1 ;
static dim = 2 ;
static inverse = 7 ;
static noBrightness = 22 ;
static noItalic = 23 ;
static noUnderline = 24 ;
static noInverse = 27 ;
static noColor = 39 ;
static noBgColor = 49 ;
value : number ;
constructor ( n ? ) {
if ( n !== undefined ) {
this . value = Number ( n ) ;
}
}
get type ( ) {
return types [ Math . floor ( this . value / 10 ) ] ;
}
get subtype() {
return subtypes [ this . type ] [ this . value % 10 ] ;
}
get str() {
return this . value ? '\u001b[' + this . value + 'm' : '' ;
}
static str ( x ) {
return new Code ( x ) . str ;
}
get isBrightness() {
return this . value === Code . noBrightness || this . value === Code . bright || this . value === Code . dim ;
}
}
/* ------------------------------------------------------------------------ */
const replaceAll = ( str , a , b ) = > str . split ( a ) . join ( b ) ;
/* ANSI brightness codes do not overlap, e.g. "{bright}{dim}foo" will be rendered bright (not dim).
So we fix it by adding brightness canceling before each brightness code, so the former example gets
converted to "{noBrightness}{bright}{noBrightness}{dim}foo" – this way it gets rendered as expected.
*/
const denormalizeBrightness = s = > s . replace ( /(\u001b\[(1|2)m)/g , '\u001b[22m$1' ) ;
const normalizeBrightness = s = > s . replace ( /\u001b\[22m(\u001b\[(1|2)m)/g , '$1' ) ;
const wrap = ( x , openCode , closeCode ) = > {
const open = Code . str ( openCode ) ,
close = Code . str ( closeCode ) ;
return String ( x )
. split ( '\n' )
. map ( line = > denormalizeBrightness ( open + replaceAll ( normalizeBrightness ( line ) , close , open ) + close ) )
. join ( '\n' ) ;
} ;
/* ------------------------------------------------------------------------ */
const camel = ( a , b ) = > a + b . charAt ( 0 ) . toUpperCase ( ) + b . slice ( 1 ) ;
const stringWrappingMethods = ( ( ) = >
[
. . . colorCodes . map (
( k , i ) = >
! k
? [ ]
: [
// color methods
[ k , 30 + i , Code . noColor ] ,
[ camel ( 'bg' , k ) , 40 + i , Code . noBgColor ] ,
]
) ,
. . . colorCodesLight . map (
( k , i ) = >
! k
? [ ]
: [
// light color methods
[ k , 90 + i , Code . noColor ] ,
[ camel ( 'bg' , k ) , 100 + i , Code . noBgColor ] ,
]
) ,
/* THIS ONE IS FOR BACKWARDS COMPATIBILITY WITH PREVIOUS VERSIONS (had 'bright' instead of 'light' for backgrounds)
*/
. . . [ '' , 'BrightRed' , 'BrightGreen' , 'BrightYellow' , 'BrightBlue' , 'BrightMagenta' , 'BrightCyan' ] . map (
( k , i ) = > ( ! k ? [ ] : [ [ 'bg' + k , 100 + i , Code . noBgColor ] ] )
) ,
. . . styleCodes . map (
( k , i ) = >
! k
? [ ]
: [
// style methods
[ k , i , k === 'bright' || k === 'dim' ? Code.noBrightness : 20 + i ] ,
]
) ,
] . reduce ( ( a , b ) = > a . concat ( b ) ) ) ( ) ;
/* ------------------------------------------------------------------------ */
const assignStringWrappingAPI = ( target , wrapBefore = target ) = >
stringWrappingMethods . reduce (
( memo , [ k , open , close ] ) = >
O . defineProperty ( memo , k , {
get : ( ) = > assignStringWrappingAPI ( str = > wrapBefore ( wrap ( str , open , close ) ) ) ,
} ) ,
target
) ;
/* ------------------------------------------------------------------------ */
const TEXT = 0 ,
BRACKET = 1 ,
CODE = 2 ;
function rawParse ( s ) {
let state = TEXT ,
buffer = '' ,
text = '' ,
code = '' ,
codes = [ ] ;
const spans = [ ] ;
for ( let i = 0 , n = s . length ; i < n ; i ++ ) {
const c = s [ i ] ;
buffer += c ;
switch ( state ) {
case TEXT : {
if ( c === '\u001b' ) {
state = BRACKET ;
buffer = c ;
} else {
text += c ;
}
break ;
}
case BRACKET :
if ( c === '[' ) {
state = CODE ;
code = '' ;
codes = [ ] ;
} else {
state = TEXT ;
text += buffer ;
}
break ;
case CODE :
if ( c >= '0' && c <= '9' ) {
code += c ;
} else if ( c === ';' ) {
codes . push ( new Code ( code ) ) ;
code = '' ;
} else if ( c === 'm' && code . length ) {
codes . push ( new Code ( code ) ) ;
for ( const code of codes ) {
spans . push ( { text , code } ) ;
text = '' ;
}
state = TEXT ;
} else {
state = TEXT ;
text += buffer ;
}
}
}
if ( state !== TEXT ) {
text += buffer ;
}
if ( text ) {
spans . push ( { text , code : new Code ( ) } ) ;
}
return spans ;
}
/* ------------------------------------------------------------------------ */
/**
* Represents an ANSI-escaped string.
*/
export default class Colors {
spans : any [ ] ;
static names = stringWrappingMethods . map ( ( [ k ] ) = > k ) ;
static rgb = {
black : [ 0 , 0 , 0 ] ,
darkGray : [ 100 , 100 , 100 ] ,
lightGray : [ 200 , 200 , 200 ] ,
white : [ 255 , 255 , 255 ] ,
red : [ 204 , 0 , 0 ] ,
lightRed : [ 255 , 51 , 0 ] ,
green : [ 0 , 204 , 0 ] ,
lightGreen : [ 51 , 204 , 51 ] ,
yellow : [ 204 , 102 , 0 ] ,
lightYellow : [ 255 , 153 , 51 ] ,
blue : [ 0 , 0 , 255 ] ,
lightBlue : [ 26 , 140 , 255 ] ,
magenta : [ 204 , 0 , 204 ] ,
lightMagenta : [ 255 , 0 , 255 ] ,
cyan : [ 0 , 153 , 255 ] ,
lightCyan : [ 0 , 204 , 255 ] ,
} ;
/**
* @param {string} s a string containing ANSI escape codes.
*/
constructor ( s ? ) {
this . spans = s ? rawParse ( s ) : [ ] ;
}
get str() {
return this . spans . reduce ( ( str , p ) = > str + p . text + p . code . str , '' ) ;
}
get parsed() {
let color , bgColor , brightness , styles ;
function reset() {
( color = new Color ( ) ) ,
( bgColor = new Color ( true /* background */ ) ) ,
( brightness = undefined ) ,
( styles = new Set ( ) ) ;
}
reset ( ) ;
return O . assign ( new Colors ( ) , {
spans : this.spans
. map ( span = > {
const c = span . code ;
const inverted = styles . has ( 'inverse' ) ,
underline = styles . has ( 'underline' ) ? 'text-decoration: underline;' : '' ,
italic = styles . has ( 'italic' ) ? 'font-style: italic;' : '' ,
bold = brightness === Code . bright ? 'font-weight: bold;' : '' ;
const foreColor = color . defaultBrightness ( brightness ) ;
const styledSpan = O . assign (
{ css : bold + italic + underline + foreColor . css ( inverted ) + bgColor . css ( inverted ) } ,
clean ( { bold : ! ! bold , color : foreColor.clean , bgColor : bgColor.clean } ) ,
span
) ;
for ( const k of styles ) {
styledSpan [ k ] = true ;
}
if ( c . isBrightness ) {
brightness = c . value ;
} else if ( span . code . value !== undefined ) {
if ( span . code . value === Code . reset ) {
reset ( ) ;
} else {
switch ( span . code . type ) {
case 'color' :
case 'colorLight' :
color = new Color ( false , c . subtype ) ;
break ;
case 'bgColor' :
case 'bgColorLight' :
bgColor = new Color ( true , c . subtype ) ;
break ;
case 'style' :
styles . add ( c . subtype ) ;
break ;
case 'unstyle' :
styles . delete ( c . subtype ) ;
break ;
}
}
}
return styledSpan ;
} )
. filter ( s = > s . text . length > 0 ) ,
} ) ;
}
/* Outputs with Chrome DevTools-compatible format */
get asChromeConsoleLogArguments() {
const spans = this . parsed . spans ;
return [ spans . map ( s = > '%c' + s . text ) . join ( '' ) , . . . spans . map ( s = > s . css ) ] ;
}
get browserConsoleArguments ( ) /* LEGACY, DEPRECATED */ {
return this . asChromeConsoleLogArguments ;
}
/**
* @desc installs String prototype extensions
* @example
* require ('ansicolor').nice
* console.log ('foo'.bright.red)
*/
static get nice() {
Colors . names . forEach ( k = > {
if ( ! ( k in String . prototype ) ) {
O . defineProperty ( String . prototype , k , {
get : function ( ) {
return Colors [ k ] ( this ) ;
} ,
} ) ;
}
} ) ;
return Colors ;
}
/**
* @desc parses a string containing ANSI escape codes
* @return {Colors} parsed representation.
*/
static parse ( s ) {
return new Colors ( s ) . parsed ;
}
/**
* @desc strips ANSI codes from a string
* @param {string} s a string containing ANSI escape codes.
* @return {string} clean string.
*/
static strip ( s ) {
return s . replace ( /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]/g , '' ) ; // hope V8 caches the regexp
}
/**
* @example
* const spans = [...ansi.parse ('\u001b[7m\u001b[7mfoo\u001b[7mbar\u001b[27m')]
*/
[ Symbol . iterator ] ( ) {
return this . spans [ Symbol . iterator ] ( ) ;
}
}
/* ------------------------------------------------------------------------ */
assignStringWrappingAPI ( Colors , str = > str ) ;