Skip to content

Commit b9b4a2e

Browse files
committed
minor #39 Add missing type hints & validate PHPStan level 9 (smnandre)
This PR was squashed before being merged into the master branch. Discussion ---------- Add missing type hints & validate PHPStan level 9 **TL;DR;** stricter type checks + PHPDoc annotations = PHPStan level 9 ### AnsiToHtmlConverter * Grouped `preg_replace` calls into a single call in `AnsiToHtmlConverter::convert` * Removed a conditional test case for PHP versions below 5.4 * Strict comparaisons * PHPDoc annotations ### AnsiToHtmlConverterTest * Removed a conditional test case for PHP versions below 5.4 * PHPDoc annotations Commits ------- 2feb096 Add missing type hints & validate PHPStan level 9
2 parents ed00fbe + 2feb096 commit b9b4a2e

File tree

6 files changed

+54
-26
lines changed

6 files changed

+54
-26
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ $twig->addExtension(new AnsiExtension($converter));
9393

9494
Then:
9595

96-
```jinja
96+
```twig
9797
<html>
9898
<head>
9999
<style>

SensioLabs/AnsiConverter/AnsiToHtmlConverter.php

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@
1818
*/
1919
class 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

SensioLabs/AnsiConverter/Bridge/Twig/AnsiExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ public function getFunctions(): array
3737
];
3838
}
3939

40+
/**
41+
* @param string $string
42+
*
43+
* @return string
44+
*/
4045
public function ansiToHtml($string)
4146
{
4247
return $this->converter->convert($string);

SensioLabs/AnsiConverter/Tests/AnsiToHtmlConverterTest.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public function testConvert(string $expected, string $input)
2424
$this->assertEquals($expected, $converter->convert($input));
2525
}
2626

27+
/**
28+
* @return array<list<string>>
29+
*/
2730
public static function getConvertData(): array
2831
{
2932
return [
@@ -73,8 +76,8 @@ public static function getConvertData(): array
7376
// bold and background (high intensity)
7477
['<span style="background-color: red; color: lightcyan">foo</span>', "\e[1;101;96mfoo\e[0m"],
7578

76-
// non valid unicode codepoints substitution (only available with PHP >= 5.4)
77-
\PHP_VERSION_ID < 50400 ?: ['<span style="background-color: black; color: white">foo '."\xEF\xBF\xBD".'</span>', "foo \xF4\xFF\xFF\xFF"],
79+
// non valid unicode codepoints substitution
80+
['<span style="background-color: black; color: white">foo '."\xEF\xBF\xBD".'</span>', "foo \xF4\xFF\xFF\xFF"],
7881

7982
// codes in sequence - remember enabled styling like bold, italic, etc. (until we hit a reset)
8083
['<span style="background-color: black; color: lightgreen">foo</span><span style="background-color: black; color: lightgreen">bar</span><span style="background-color: black; color: white">foo</span>', "\e[1;32mfoo\e[32mbar\e[mfoo"],

SensioLabs/AnsiConverter/Theme/Theme.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ public function asCss(string $prefix = 'ansi_color'): string
3131
return implode("\n", $css);
3232
}
3333

34+
/**
35+
* @return array<string, string>
36+
*/
3437
public function asArray(): array
3538
{
3639
return [

phpstan.neon.dist

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
parameters:
2-
level: 3
2+
level: 9
33
paths:
44
- SensioLabs
5+
ignoreErrors:
6+
-
7+
message: '#Method [a-zA-Z0-9\\_]+Test::[a-zA-Z0-9]+\(\) has no return type specified.#'
8+
path: SensioLabs/AnsiConverter/Tests/*

0 commit comments

Comments
 (0)