export interface AnsiItem { foreground ? : string ; background ? : string ; bold ? : boolean ; italic ? : boolean ; underline ? : boolean ; text : string ; } const foregroundColors = { 30 : 'black' , 31 : 'red' , 32 : 'green' , 33 : 'yellow' , 34 : 'blue' , 35 : 'magenta' , 36 : 'cyan' , 37 : 'white' , 90 : 'grey' } ; const backgroundColors = { 40 : 'black' , 41 : 'red' , 42 : 'green' , 43 : 'yellow' , 44 : 'blue' , 45 : 'magenta' , 46 : 'cyan' , 47 : 'white' } ; const styles = { 1 : 'bold' , 3 : 'italic' , 4 : 'underline' } ; export function ansiparse ( str ) { let matchingControl = null ; let matchingData = null ; let matchingText = '' ; let ansiState = [ ] ; let result = [ ] ; let state = { } ; let eraseChar ; eraseChar = ( ) => { let index ; let text ; if ( matchingText . length ) { matchingText = matchingText . substr ( 0 , matchingText . length - 1 ) ; } else if ( result . length ) { index = result . length - 1 ; text = result [ index ] . text ; if ( text . length === 1 ) { result . pop ( ) ; } else { result [ index ] . text = text . substr ( 0 , text . length - 1 ) ; } } } ; for ( let i = 0 ; i < str . length ; i ++ ) { if ( matchingControl != null ) { if ( matchingControl == '\x1b' && str [ i ] == '\[' ) { if ( matchingText ) { state . text = matchingText ; result . push ( state ) ; state = { } ; matchingText = '' ; } matchingControl = null ; matchingData = '' ; } else { matchingText += matchingControl + str [ i ] ; matchingControl = null ; } continue ; } else if ( matchingData != null ) { if ( str [ i ] == ';' ) { ansiState . push ( matchingData ) ; matchingData = '' ; } else if ( str [ i ] == 'm' || str [ i ] == 'K' ) { ansiState . push ( matchingData ) ; matchingData = null ; matchingText = '' ; ansiState . forEach ( ansiCode => { if ( foregroundColors [ ansiCode ] ) { state . foreground = foregroundColors [ ansiCode ] ; } else if ( backgroundColors [ ansiCode ] ) { state . background = backgroundColors [ ansiCode ] ; } else if ( ansiCode == 39 ) { delete state . foreground ; } else if ( ansiCode == 49 ) { delete state . background ; } else if ( styles [ ansiCode ] ) { state [ styles [ ansiCode ] ] = true ; } else if ( ansiCode == 22 ) { state . bold = false ; } else if ( ansiCode == 23 ) { state . italic = false ; } else if ( ansiCode == 24 ) { state . underline = false ; } } ) ; ansiState = [ ] ; } else { matchingData += str [ i ] ; } continue ; } if ( str [ i ] == '\x1b' ) { matchingControl = str [ i ] ; } else if ( str [ i ] == '\u0008' ) { eraseChar ( ) ; } else { matchingText += str [ i ] ; } } if ( matchingText ) { state . text = matchingText + ( matchingControl ? matchingControl : '' ) ; result . push ( state ) ; } return result ; }