fix: account for Phred tags in TableAdapter width calculation and alignment
Some checks failed
CI / tasker-bridges (8.2) (push) Has been cancelled
CI / tasker-bridges (8.3) (push) Has been cancelled

This commit is contained in:
Funky Waddle 2026-02-22 04:10:30 -06:00
parent da1efaba55
commit a657802c70
2 changed files with 67 additions and 3 deletions

View file

@ -86,12 +86,12 @@ class TableAdapter implements TableInterface
$widths = []; $widths = [];
foreach ($this->headers as $index => $header) { foreach ($this->headers as $index => $header) {
$widths[$index] = mb_strlen((string)$header); $widths[$index] = $this->getContentLength((string)$header);
} }
foreach ($this->rows as $row) { foreach ($this->rows as $row) {
foreach ($row as $index => $value) { foreach ($row as $index => $value) {
$width = mb_strlen((string)$value); $width = $this->getContentLength((string)$value);
if (!isset($widths[$index]) || $width > $widths[$index]) { if (!isset($widths[$index]) || $width > $widths[$index]) {
$widths[$index] = $width; $widths[$index] = $width;
} }
@ -118,11 +118,54 @@ class TableAdapter implements TableInterface
default => STR_PAD_RIGHT, default => STR_PAD_RIGHT,
}; };
$formatted .= ' ' . str_pad($value, $width, ' ', $padType) . ' |'; // We need to account for tags in the value when padding
$displayValue = $this->stripTags($value);
$displayLength = mb_strlen($displayValue);
$paddingLength = $width - $displayLength;
if ($paddingLength < 0) {
$paddingLength = 0;
}
$leftPadding = 0;
$rightPadding = 0;
if ($padType === STR_PAD_LEFT) {
$leftPadding = $paddingLength;
} elseif ($padType === STR_PAD_BOTH) {
$leftPadding = (int) floor($paddingLength / 2);
$rightPadding = (int) ceil($paddingLength / 2);
} else {
$rightPadding = $paddingLength;
}
$formatted .= ' ' . str_repeat(' ', $leftPadding) . $value . str_repeat(' ', $rightPadding) . ' |';
} }
$this->output->writeln($formatted); $this->output->writeln($formatted);
} }
/**
* Strips Phred console tags from a string.
*
* @param string $text
* @return string
*/
private function stripTags(string $text): string
{
return preg_replace('/<[a-z]+>(.*?)<\/.*?>/i', '$1', $text) ?? $text;
}
/**
* Gets the length of a string without console tags.
*
* @param string $text
* @return int
*/
private function getContentLength(string $text): int
{
return mb_strlen($this->stripTags($text));
}
/** /**
* @param array<int, int> $widths * @param array<int, int> $widths
*/ */

View file

@ -71,6 +71,27 @@ class PhredBridgeTest extends TestCase
$this->assertStringContainsString('| Active |', $content); $this->assertStringContainsString('| Active |', $content);
} }
public function testTableAdapterWithTags(): void
{
$output = new OutputAdapter(false);
$table = new TableAdapter($output);
// Header with tags (8 chars displayed, more in raw string)
$table->setHeaders(['<info>ID</info>', 'Name']);
$table->addRow(['1', 'John']);
ob_start();
$table->render();
$content = ob_get_clean();
// If bug exists, the ID column width will be 13 (mb_strlen('<info>ID</info>'))
// but it should be 2 (length of 'ID')
// The separator line will have '-' x (width + 2)
// Correct width 2 -> "+----+"
// Buggy width 13 -> "+---------------+"
$this->assertStringContainsString('+----+', $content);
}
public function testMarkdownConverter(): void public function testMarkdownConverter(): void
{ {
$output = new OutputAdapter(false); $output = new OutputAdapter(false);