1818 */
1919class AnsiToHtmlConverter
2020{
21+ /**
22+ * @var array<string, string>
23+ */
2124 protected array $ inlineColors ;
25+
26+ /**
27+ * @var array<string>
28+ */
2229 protected array $ colorNames ;
2330
2431 public function __construct (
@@ -36,24 +43,25 @@ public function __construct(
3643
3744 public function convert (string $ text ): string
3845 {
39- // remove cursor movement sequences
40- $ 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 );
41- // remove character set sequences
42- $ text = preg_replace ('#\e(\(|\))(A|B|[0-2])# ' , '' , $ text );
43-
44- $ text = htmlspecialchars ($ text , \PHP_VERSION_ID >= 50400 ? \ENT_QUOTES | \ENT_SUBSTITUTE : \ENT_QUOTES , $ this ->charset );
46+ $ text = preg_replace ([
47+ // remove cursor movement sequences
48+ '#\e\[(K|s|u|2J|2K|\d+(A|B|C|D|E|F|G|J|K|S|T)|\d+;\d+(H|f))# ' ,
49+ // remove character set sequences
50+ '#\e(\(|\))(A|B|[0-2])# ' ,
51+ // remove carriage return
52+ '#^.*\r(?!\n)#m ' ,
53+ ], '' , $ text ) ?? '' ;
4554
46- // carriage return
47- $ text = preg_replace ('#^.*\r(?!\n)#m ' , '' , $ text );
55+ $ text = htmlspecialchars ($ text , \ENT_QUOTES | \ENT_SUBSTITUTE , $ this ->charset );
4856
4957 $ tokens = $ this ->tokenize ($ text );
5058
5159 // a backspace remove the previous character but only from a text token
5260 foreach ($ tokens as $ i => $ token ) {
53- if ('backspace ' == $ token [0 ]) {
61+ if ('backspace ' === $ token [0 ]) {
5462 $ j = $ i ;
5563 while (--$ j >= 0 ) {
56- if ('text ' == $ tokens [$ j ][0 ] && '' !== $ tokens [$ j ][1 ]) {
64+ if ('text ' === $ tokens [$ j ][0 ] && '' !== $ tokens [$ j ][1 ]) {
5765 $ tokens [$ j ][1 ] = substr ($ tokens [$ j ][1 ], 0 , -1 );
5866
5967 break ;
@@ -64,9 +72,9 @@ public function convert(string $text): string
6472
6573 $ html = '' ;
6674 foreach ($ tokens as $ token ) {
67- if ('text ' == $ token [0 ]) {
75+ if ('text ' === $ token [0 ]) {
6876 $ html .= $ token [1 ];
69- } elseif ('color ' == $ token [0 ]) {
77+ } elseif ('color ' === $ token [0 ]) {
7078 $ html .= $ this ->convertAnsiToColor ($ token [1 ]);
7179 }
7280 }
@@ -78,9 +86,7 @@ public function convert(string $text): string
7886 }
7987
8088 // remove empty span
81- $ html = preg_replace ('#<span[^>]*></span># ' , '' , $ html );
82-
83- return $ html ;
89+ return preg_replace ('#<span[^>]*></span># ' , '' , $ html ) ?? '' ;
8490 }
8591
8692 public function getTheme (): Theme
@@ -95,7 +101,7 @@ protected function convertAnsiToColor(string $ansi): string
95101 $ as = '' ; // inline styles
96102 $ cs = '' ; // css classes
97103 $ hi = false ; // high intensity
98- if ('0 ' != $ ansi && '' != $ ansi ) {
104+ if ('0 ' !== $ ansi && '' != = $ ansi ) {
99105 $ options = explode ('; ' , $ ansi );
100106
101107 foreach ($ options as $ key => $ option ) {
@@ -109,19 +115,21 @@ protected function convertAnsiToColor(string $ansi): string
109115 $ hi = true ;
110116 } elseif ($ option >= 100 && $ option < 108 ) {
111117 $ bg = $ option - 90 ;
112- } elseif (39 == $ option ) {
118+ } elseif (39 === $ option ) {
113119 $ fg = 7 ;
114- } elseif (49 == $ option ) {
120+ } elseif (49 === $ option ) {
115121 $ bg = 0 ;
116122 } elseif ($ option >= 22 && $ option < 30 ) { // 21 has varying effects, best to ignored it
117123 $ unset = $ option - 20 ;
118124
119125 foreach ($ options as $ i => $ v ) {
120- if ($ v == $ unset ) {
126+ $ v = (int ) $ v ;
127+
128+ if ($ v === $ unset ) {
121129 unset($ options [$ i ]);
122130 }
123131
124- if (2 == $ unset && 1 == $ v ) { // 22 also unsets bold
132+ if (2 === $ unset && 1 = == $ v ) { // 22 also unsets bold
125133 unset($ options [$ i ]);
126134 }
127135
@@ -171,6 +179,11 @@ protected function convertAnsiToColor(string $ansi): string
171179 }
172180 }
173181
182+ /**
183+ * Tokenizes the given text into an array of tokens.
184+ *
185+ * @return list<array<int, string>>
186+ */
174187 protected function tokenize (string $ text ): array
175188 {
176189 $ tokens = [];
@@ -184,7 +197,7 @@ protected function tokenize(string $text): array
184197 }
185198
186199 foreach (explode ('; ' , $ matches [1 ][$ i ][0 ]) as $ code ) {
187- if ('0 ' == $ code || '' == $ code ) {
200+ if ('0 ' === $ code || '' = == $ code ) {
188201 $ codes = [];
189202 } else {
190203 // remove existing occurrence to avoid processing duplicate styles
@@ -196,7 +209,7 @@ protected function tokenize(string $text): array
196209 $ codes [] = $ code ;
197210 }
198211
199- $ tokens [] = ["\x08" == $ match [0 ] ? 'backspace ' : 'color ' , implode ('; ' , $ codes )];
212+ $ tokens [] = ["\x08" === $ match [0 ] ? 'backspace ' : 'color ' , implode ('; ' , $ codes )];
200213 $ offset = $ match [1 ] + \strlen ($ match [0 ]);
201214 }
202215
0 commit comments