public static function ansiToHtml($string, $styleMap = [])
    {
        $styleMap = [
            // http://www.w3.org/TR/CSS2/syndata.html#value-def-color
            self::FG_BLACK => ['color' => 'black'],
            self::FG_BLUE => ['color' => 'blue'],
            self::FG_CYAN => ['color' => 'aqua'],
            self::FG_GREEN => ['color' => 'lime'],
            self::FG_GREY => ['color' => 'silver'],
            // http://meyerweb.com/eric/thoughts/2014/06/19/rebeccapurple/
            // http://dev.w3.org/csswg/css-color/#valuedef-rebeccapurple
            self::FG_PURPLE => ['color' => 'rebeccapurple'],
            self::FG_RED => ['color' => 'red'],
            self::FG_YELLOW => ['color' => 'yellow'],
            self::BG_BLACK => ['background-color' => 'black'],
            self::BG_BLUE => ['background-color' => 'blue'],
            self::BG_CYAN => ['background-color' => 'aqua'],
            self::BG_GREEN => ['background-color' => 'lime'],
            self::BG_GREY => ['background-color' => 'silver'],
            self::BG_PURPLE => ['background-color' => 'rebeccapurple'],
            self::BG_RED => ['background-color' => 'red'],
            self::BG_YELLOW => ['background-color' => 'yellow'],
            self::BOLD => ['font-weight' => 'bold'],
            self::ITALIC => ['font-style' => 'italic'],
            self::UNDERLINE => ['text-decoration' => ['underline']],
            self::OVERLINED => ['text-decoration' => ['overline']],
            self::CROSSED_OUT => ['text-decoration' => ['line-through']],
            self::BLINK => ['text-decoration' => ['blink']],
            self::CONCEALED => ['visibility' => 'hidden'],
        ] + $styleMap;

        $tags = 0;
        $result = preg_replace_callback(
            '/\033\[([\d;]+)m/',
            function ($ansi) use (&$tags, $styleMap) {
                $style = [];
                $reset = false;
                $negative = false;
                foreach (explode(';', $ansi[1]) as $controlCode) {
                    if ($controlCode == 0) {
                        $style = [];
                        $reset = true;
                    } elseif ($controlCode == self::NEGATIVE) {
                        $negative = true;
                    } elseif (isset($styleMap[$controlCode])) {
                        $style[] = $styleMap[$controlCode];
                    }
                }

                $return = '';
                while ($reset && $tags > 0) {
                    $return .= '</span>';
                    $tags--;
                }
                if (empty($style)) {
                    return $return;
                }

                $currentStyle = [];
                foreach ($style as $content) {
                    $currentStyle = ArrayHelper::merge($currentStyle, $content);
                }

                // if negative is set, invert background and foreground
                if ($negative) {
                    if (isset($currentStyle['color'])) {
                        $fgColor = $currentStyle['color'];
                        unset($currentStyle['color']);
                    }
                    if (isset($currentStyle['background-color'])) {
                        $bgColor = $currentStyle['background-color'];
                        unset($currentStyle['background-color']);
                    }
                    if (isset($fgColor)) {
                        $currentStyle['background-color'] = $fgColor;
                    }
                    if (isset($bgColor)) {
                        $currentStyle['color'] = $bgColor;
                    }
                }

                $styleString = '';
                foreach ($currentStyle as $name => $value) {
                    if (is_array($value)) {
                        $value = implode(' ', $value);
                    }
                    $styleString .= "$name: $value;";
                }
                $tags++;
                return "$return<span style=\"$styleString\">";
            },
            $string
        );
        while ($tags > 0) {
            $result .= '</span>';
            $tags--;
        }

        return $result;
    }
public static function ansiToHtml($string, $styleMap = [])
    {
        $styleMap = [
            
            self::FG_BLACK => ['color' => 'black'],
            self::FG_BLUE => ['color' => 'blue'],
            self::FG_CYAN => ['color' => 'aqua'],
            self::FG_GREEN => ['color' => 'lime'],
            self::FG_GREY => ['color' => 'silver'],
            
            
            self::FG_PURPLE => ['color' => 'rebeccapurple'],
            self::FG_RED => ['color' => 'red'],
            self::FG_YELLOW => ['color' => 'yellow'],
            self::BG_BLACK => ['background-color' => 'black'],
            self::BG_BLUE => ['background-color' => 'blue'],
            self::BG_CYAN => ['background-color' => 'aqua'],
            self::BG_GREEN => ['background-color' => 'lime'],
            self::BG_GREY => ['background-color' => 'silver'],
            self::BG_PURPLE => ['background-color' => 'rebeccapurple'],
            self::BG_RED => ['background-color' => 'red'],
            self::BG_YELLOW => ['background-color' => 'yellow'],
            self::BOLD => ['font-weight' => 'bold'],
            self::ITALIC => ['font-style' => 'italic'],
            self::UNDERLINE => ['text-decoration' => ['underline']],
            self::OVERLINED => ['text-decoration' => ['overline']],
            self::CROSSED_OUT => ['text-decoration' => ['line-through']],
            self::BLINK => ['text-decoration' => ['blink']],
            self::CONCEALED => ['visibility' => 'hidden'],
        ] + $styleMap;

        $tags = 0;
        $result = preg_replace_callback(
            '/\033\[([\d;]+)m/',
            function ($ansi) use (&$tags, $styleMap) {
                $style = [];
                $reset = false;
                $negative = false;
                foreach (explode(';', $ansi[1]) as $controlCode) {
                    if ($controlCode == 0) {
                        $style = [];
                        $reset = true;
                    } elseif ($controlCode == self::NEGATIVE) {
                        $negative = true;
                    } elseif (isset($styleMap[$controlCode])) {
                        $style[] = $styleMap[$controlCode];
                    }
                }

                $return = '';
                while ($reset && $tags > 0) {
                    $return .= '</span>';
                    $tags--;
                }
                if (empty($style)) {
                    return $return;
                }

                $currentStyle = [];
                foreach ($style as $content) {
                    $currentStyle = ArrayHelper::merge($currentStyle, $content);
                }

                
                if ($negative) {
                    if (isset($currentStyle['color'])) {
                        $fgColor = $currentStyle['color'];
                        unset($currentStyle['color']);
                    }
                    if (isset($currentStyle['background-color'])) {
                        $bgColor = $currentStyle['background-color'];
                        unset($currentStyle['background-color']);
                    }
                    if (isset($fgColor)) {
                        $currentStyle['background-color'] = $fgColor;
                    }
                    if (isset($bgColor)) {
                        $currentStyle['color'] = $bgColor;
                    }
                }

                $styleString = '';
                foreach ($currentStyle as $name => $value) {
                    if (is_array($value)) {
                        $value = implode(' ', $value);
                    }
                    $styleString .= "$name: $value;";
                }
                $tags++;
                return "$return<span style=\"$styleString\">";
            },
            $string
        );
        while ($tags > 0) {
            $result .= '</span>';
            $tags--;
        }

        return $result;
    }
public static function ansiToHtml ( $ string , $ styleMap = [ ] ) { $ styleMap = [ // http://www.w3.org/TR/CSS2/syndata.html#value-def-color self :: FG_BLACK => [ 'color' => 'black' ] , self :: FG_BLUE => [ 'color' => 'blue' ] , self :: FG_CYAN => [ 'color' => 'aqua' ] , self :: FG_GREEN => [ 'color' => 'lime' ] , self :: FG_GREY => [ 'color' => 'silver' ] , // http://meyerweb.com/eric/thoughts/2014/06/19/rebeccapurple/ // http://dev.w3.org/csswg/css-color/#valuedef-rebeccapurple self :: FG_PURPLE => [ 'color' => 'rebeccapurple' ] , self :: FG_RED => [ 'color' => 'red' ] , self :: FG_YELLOW => [ 'color' => 'yellow' ] , self :: BG_BLACK => [ 'background-color' => 'black' ] , self :: BG_BLUE => [ 'background-color' => 'blue' ] , self :: BG_CYAN => [ 'background-color' => 'aqua' ] , self :: BG_GREEN => [ 'background-color' => 'lime' ] , self :: BG_GREY => [ 'background-color' => 'silver' ] , self :: BG_PURPLE => [ 'background-color' => 'rebeccapurple' ] , self :: BG_RED => [ 'background-color' => 'red' ] , self :: BG_YELLOW => [ 'background-color' => 'yellow' ] , self :: BOLD => [ 'font-weight' => 'bold' ] , self :: ITALIC => [ 'font-style' => 'italic' ] , self :: UNDERLINE => [ 'text-decoration' => [ 'underline' ] ] , self :: OVERLINED => [ 'text-decoration' => [ 'overline' ] ] , self :: CROSSED_OUT => [ 'text-decoration' => [ 'line-through' ] ] , self :: BLINK => [ 'text-decoration' => [ 'blink' ] ] , self :: CONCEALED => [ 'visibility' => 'hidden' ] , ] + $ styleMap ; $ tags = 0 ; $ result = preg_replace_callback ( '/\033\[([\d;]+)m/' , function ( $ ansi ) use ( & $ tags , $ styleMap ) { $ style = [ ] ; $ reset = false ; $ negative = false ; foreach ( explode ( ';' , $ ansi [ 1 ] ) as $ controlCode ) { if ( $ controlCode == 0 ) { $ style = [ ] ; $ reset = true ; } elseif ( $ controlCode == self :: NEGATIVE ) { $ negative = true ; } elseif ( isset ( $ styleMap [ $ controlCode ] ) ) { $ style [ ] = $ styleMap [ $ controlCode ] ; } } $ return = '' ; while ( $ reset && $ tags > 0 ) { $ return .= '</span>' ; $ tags -- ; } if ( empty ( $ style ) ) { return $ return ; } $ currentStyle = [ ] ; foreach ( $ style as $ content ) { $ currentStyle = ArrayHelper :: merge ( $ currentStyle , $ content ) ; } // if negative is set, invert background and foreground if ( $ negative ) { if ( isset ( $ currentStyle [ 'color' ] ) ) { $ fgColor = $ currentStyle [ 'color' ] ; unset ( $ currentStyle [ 'color' ] ) ; } if ( isset ( $ currentStyle [ 'background-color' ] ) ) { $ bgColor = $ currentStyle [ 'background-color' ] ; unset ( $ currentStyle [ 'background-color' ] ) ; } if ( isset ( $ fgColor ) ) { $ currentStyle [ 'background-color' ] = $ fgColor ; } if ( isset ( $ bgColor ) ) { $ currentStyle [ 'color' ] = $ bgColor ; } } $ styleString = '' ; foreach ( $ currentStyle as $ name => $ value ) { if ( is_array ( $ value ) ) { $ value = implode ( ' ' , $ value ) ; } $ styleString .= "$name: $value;" ; } $ tags ++ ; return "$return<span style=\"$styleString\">" ; } , $ string ) ; while ( $ tags > 0 ) { $ result .= '</span>' ; $ tags -- ; } return $ result ; }
Converts an ANSI formatted string to HTML.

Note: xTerm 256 bit colors are currently not supported.

@param string $string the string to convert.
@param array $styleMap an optional mapping of ANSI control codes such as
FG\_*COLOR* or [[BOLD]] to a set of css style definitions.
The CSS style definitions are represented as an array where the array keys correspond
to the css style attribute names and the values are the css values.
values may be arrays that will be merged and imploded with `' '` when rendered.
@return string HTML representation of the ANSI formatted string
Converts an ANSI formatted string to HTML .