diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b29f419..93298750 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * Add caster for `WeakMap` * Add support of named arguments to `dd()` and `dump()` to display the argument name * Add support for `Relay\Relay` + * Add display of invisible characters 6.2 --- diff --git a/Dumper/CliDumper.php b/Dumper/CliDumper.php index c52ac4db..7d6810e4 100644 --- a/Dumper/CliDumper.php +++ b/Dumper/CliDumper.php @@ -51,6 +51,7 @@ class CliDumper extends AbstractDumper "\r" => '\r', "\033" => '\e', ]; + protected static $unicodeCharsRx = "/[\u{00A0}\u{00AD}\u{034F}\u{061C}\u{115F}\u{1160}\u{17B4}\u{17B5}\u{180E}\u{2000}-\u{200F}\u{202F}\u{205F}\u{2060}-\u{2064}\u{206A}-\u{206F}\u{3000}\u{2800}\u{3164}\u{FEFF}\u{FFA0}\u{1D159}\u{1D173}-\u{1D17A}]/u"; protected $collapseNextHash = false; protected $expandNextHash = false; @@ -450,6 +451,14 @@ protected function style(string $style, string $value, array $attr = []): string return $s.$endCchr; }, $value, -1, $cchrCount); + if (!($attr['binary'] ?? false)) { + $value = preg_replace_callback(static::$unicodeCharsRx, function ($c) use (&$cchrCount, $startCchr, $endCchr) { + ++$cchrCount; + + return $startCchr.'\u{'.strtoupper(dechex(mb_ord($c[0]))).'}'.$endCchr; + }, $value); + } + if ($this->colors) { if ($cchrCount && "\033" === $value[0]) { $value = substr($value, \strlen($startCchr)); diff --git a/Dumper/HtmlDumper.php b/Dumper/HtmlDumper.php index c818c919..0cc7baab 100644 --- a/Dumper/HtmlDumper.php +++ b/Dumper/HtmlDumper.php @@ -862,7 +862,6 @@ protected function style(string $style, string $value, array $attr = []): string } elseif ('private' === $style) { $style .= sprintf(' title="Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class']))); } - $map = static::$controlCharsMap; if (isset($attr['ellipsis'])) { $class = 'sf-dump-ellipsis'; @@ -881,6 +880,7 @@ protected function style(string $style, string $value, array $attr = []): string } } + $map = static::$controlCharsMap; $v = "".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) { $s = $b = '\u{'.strtoupper(dechex(mb_ord($c[0]))).'}'; + }, $v); + } + if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) { $attr['href'] = $href; } diff --git a/Tests/Dumper/CliDumperTest.php b/Tests/Dumper/CliDumperTest.php index b4780cfe..4993ee32 100644 --- a/Tests/Dumper/CliDumperTest.php +++ b/Tests/Dumper/CliDumperTest.php @@ -51,7 +51,7 @@ public function testGet() $this->assertStringMatchesFormat( << 1 0 => &1 null "const" => 1.1 @@ -66,6 +66,7 @@ public function testGet() é\\x01test\\t\\n ing """ + "bo\\u{FEFF}m" => "te\\u{FEFF}st" "[]" => [] "res" => stream resource {@{$res} %A wrapper_type: "plainfile" diff --git a/Tests/Dumper/HtmlDumperTest.php b/Tests/Dumper/HtmlDumperTest.php index 1fd98640..e48ed5e0 100644 --- a/Tests/Dumper/HtmlDumperTest.php +++ b/Tests/Dumper/HtmlDumperTest.php @@ -54,7 +54,7 @@ public function testGet() $this->assertStringMatchesFormat( <<array:24 [ +array:25 [ "number" => 1 0 => &1 null "const" => 1.1 @@ -69,6 +69,7 @@ public function testGet() é\\x01test\\t\\n ing """ + "bo "te[]" => [] "res" => stream resource @{$res} %A wrapper_type: "plainfile" diff --git a/Tests/Fixtures/dumb-var.php b/Tests/Fixtures/dumb-var.php index fc48012f..3896f310 100644 --- a/Tests/Fixtures/dumb-var.php +++ b/Tests/Fixtures/dumb-var.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\VarDumper\Tests\Fixture; if (!class_exists(\Symfony\Component\VarDumper\Tests\Fixture\DumbFoo::class)) { @@ -17,8 +26,8 @@ class DumbFoo $var = [ 'number' => 1, null, - 'const' => 1.1, true, false, NAN, INF, -INF, PHP_INT_MAX, - 'str' => "déjà\n", "\xE9\x01test\t\ning", + 'const' => 1.1, true, false, \NAN, \INF, -\INF, \PHP_INT_MAX, + 'str' => "déjà\n", "\xE9\x01test\t\ning", "bo\u{feff}m" => "te\u{feff}st", '[]' => [], 'res' => $g, 'obj' => $foo,