diff --git a/docs/guide/converters.md b/docs/guide/converters.md index d48a1c3..8cc45fe 100644 --- a/docs/guide/converters.md +++ b/docs/guide/converters.md @@ -168,6 +168,8 @@ $djot = $converter->convert($html); | `
` + `` + `
` | Image with `^ caption` | | `
` + `
` + `
` | Block quote with `^ caption` | +Djot can only spell a leading header row, so a `` elsewhere imports as a data cell. + **File Operations:** ```php diff --git a/src/Converter/HtmlToDjot.php b/src/Converter/HtmlToDjot.php index 9c847be..99de9fe 100644 --- a/src/Converter/HtmlToDjot.php +++ b/src/Converter/HtmlToDjot.php @@ -1592,7 +1592,6 @@ protected function processTable(DOMElement $node): string { $rows = []; $headerRow = null; - $headerRowAttrs = ''; $columnCount = 0; $captionText = ''; $alignments = []; @@ -1606,9 +1605,9 @@ protected function processTable(DOMElement $node): string // Find all rows $trElements = $this->getDirectTableRows($node); - foreach ($trElements as $tr) { + foreach ($trElements as $rowIndex => $tr) { $cells = []; - $isHeader = false; + $allCellsAreHeaders = true; $columnIndex = 0; foreach ($tr->childNodes as $cell) { @@ -1624,8 +1623,8 @@ protected function processTable(DOMElement $node): string } else { $cells[] = $cellContent; } - if ($tag === 'th') { - $isHeader = true; + if ($tag !== 'th') { + $allCellsAreHeaders = false; } if (!isset($alignments[$columnIndex])) { $alignments[$columnIndex] = $this->extractTableCellAlignment($cell); @@ -1644,9 +1643,8 @@ protected function processTable(DOMElement $node): string $row = '| ' . implode(' | ', $cells) . ' |' . $rowAttrSuffix; - if ($isHeader && $headerRow === null) { + if ($rowIndex === 0 && $allCellsAreHeaders) { $headerRow = $row; - $headerRowAttrs = $rowAttrSuffix; } else { $rows[] = $row; } diff --git a/tests/TestCase/Converter/HtmlToDjotTest.php b/tests/TestCase/Converter/HtmlToDjotTest.php index 60d6377..19becfd 100644 --- a/tests/TestCase/Converter/HtmlToDjotTest.php +++ b/tests/TestCase/Converter/HtmlToDjotTest.php @@ -389,6 +389,53 @@ public function testTable(): void $this->assertStringContainsString('| Alice | 30 |', $result); } + public function testTableHeaderCellInThirdRowDoesNotReorderRows(): void + { + $html = '
a
b
H
'; + + $djot = $this->converter->convert($html); + + $this->assertSame("| a |\n| b |\n| H |\n", $djot); + $this->assertSame( + "\n\n\n\n\n\n\n\n\n\n
a
b
H
\n", + (new DjotConverter())->convert($djot), + ); + } + + public function testTableMixedFirstRowImportsAsDataCells(): void + { + $html = '
R1
'; + + $djot = $this->converter->convert($html); + + $this->assertSame("| R | 1 |\n", $djot); + $this->assertSame( + "\n\n\n\n\n
R1
\n", + (new DjotConverter())->convert($djot), + ); + } + + public function testTableLeadingAllHeaderRowImportsAsHeader(): void + { + $html = '
AB
12
'; + + $this->assertSame("| A | B |\n|---|---|\n| 1 | 2 |\n", $this->converter->convert($html)); + } + + public function testTableSectionsPreserveLeadingHeaderAndBodyRows(): void + { + $html = '
A
1
'; + + $this->assertSame("| A |\n|---|\n| 1 |\n", $this->converter->convert($html)); + } + + public function testTableWithoutHeaderCellsHasNoSeparator(): void + { + $html = '
a
b
'; + + $this->assertSame("| a |\n| b |\n", $this->converter->convert($html)); + } + public function testNestedTableDoesNotLeakInnerRowsIntoOuterTable(): void { $html = '
outer
inner
';