sensiolabs / ansi-to-html

An ANSI to HTML5 converter
MIT License
238 stars 31 forks source link

Foreground color is set to background color if sequence lists background first #17

Open kiler129 opened 7 years ago

kiler129 commented 7 years ago

I came across a weird behavior while using the library - if background color (e.g. 42 - green) is specified before foreground (e.g. 30 - black) the render will contain black text on black background. Weirdly enough this happens only for separated sequences (e.g. ^[[0m^[[42m^[[30m) and not while parsing their short forms (e.g. ^[[42;30m).

I used following example to demonstrate the problem (also attached): Download raw

^[[30;42mWORKS1^[[0m
^[[0m^[[42m^[[30mDOESNT1^[[0m
^[[0m^[[30m^[[42mWORKS2^[[0m
^[[42;30mWORKS1^[[0m

Rendering in GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu) bash-render

HTML from ansi-to-html v1.1.3

<?php
$output = (new AnsiToHtmlConverter())->convert($test);
<span style="background-color: green; color: black">WORKS1</span><span style="background-color: black; color: white"><br />
</span><span style="background-color: black; color: black">DOESNT1</span><span style="background-color: black; color: white"><br />
</span><span style="background-color: green; color: white">WORKS2</span><span style="background-color: black; color: white"><br />
</span><span style="background-color: green; color: black">WORKS1</span><span style="background-color: black; color: white"><br />
</span>
ellisgl commented 6 years ago

^[[0m is reset, so the colors should back to white-on-black, then convert at the next sequence...

fctr commented 4 years ago
    public function convert($text)
    {
        // remove cursor movement sequences
        $text = preg_replace('#\e\[(K|s|u|2J|2K|\d+(A|B|C|D|E|F|G|J|K|S|T)|\d+;\d+(H|f))#', '', $text);
        // remove character set sequences
        $text = preg_replace('#\e(\(|\))(A|B|[0-2])#', '', $text);

        $text = htmlspecialchars($text, PHP_VERSION_ID >= 50400 ? ENT_QUOTES | ENT_SUBSTITUTE : ENT_QUOTES, $this->charset);

        // carriage return
        $text = preg_replace('#^.*\r(?!\n)#m', '', $text);

        // Add the follow line
        $text = preg_replace('/m\e\[/', ';', $text);