Skip to content

Commit f31dba3

Browse files
committed
Writer HTML: ListItemRun is now rendered as unordered list (<ul>/<li>) instead of plain paragraph
1 parent 0ab0b49 commit f31dba3

File tree

4 files changed

+96
-12
lines changed

4 files changed

+96
-12
lines changed

docs/changes/1.x/1.5.0.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
### Bug fixes
88

99
- Set writeAttribute return type by [@radarhere](https://github.com/radarhere) fixing [#2204](https://github.com/PHPOffice/PHPWord/issues/2204) in [#2776](https://github.com/PHPOffice/PHPWord/pull/2776)
10+
- Writer HTML: ListItemRun render as unordered lists by [@andomiell](https://github.com/andomiell) partially fixing [#1462](https://github.com/PHPOffice/PHPWord/issues/1462)
1011

1112
### Miscellaneous
1213

src/PhpWord/Writer/HTML/Element/Container.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,41 @@ public function write()
5050
$content = '';
5151

5252
$elements = $container->getElements();
53-
foreach ($elements as $element) {
53+
foreach ($elements as $index => $element) {
54+
if ($element instanceof \PhpOffice\PhpWord\Element\ListItemRun) {
55+
$prevElement = isset($elements[$index - 1]) ? $elements[$index - 1] : null;
56+
57+
if ($prevElement === null) {
58+
$content .= '<ul>';
59+
} elseif (!$prevElement instanceof \PhpOffice\PhpWord\Element\ListItemRun) {
60+
$content .= '<ul>';
61+
} elseif ($prevElement->getDepth() < $element->getDepth()) {
62+
$content = rtrim($content, '</li>');
63+
$content .= '<ul>';
64+
}
65+
}
66+
5467
$elementClass = get_class($element);
5568
$writerClass = str_replace('PhpOffice\\PhpWord\\Element', $this->namespace, $elementClass);
5669
if (class_exists($writerClass)) {
5770
/** @var AbstractElement $writer Type hint */
5871
$writer = new $writerClass($this->parentWriter, $element, $withoutP);
5972
$content .= $writer->write();
6073
}
74+
75+
if ($element instanceof \PhpOffice\PhpWord\Element\ListItemRun) {
76+
$nextElement = isset($elements[$index + 1]) ? $elements[$index + 1] : null;
77+
78+
if ($nextElement === null) {
79+
$content .= '</ul>';
80+
} elseif (!$nextElement instanceof \PhpOffice\PhpWord\Element\ListItemRun) {
81+
$content .= '</ul>';
82+
} elseif ($nextElement->getDepth() < $element->getDepth()) {
83+
for ($i = $element->getDepth() - $nextElement->getDepth(); $i !== 0; $i--) {
84+
$content .= '</ul></li>';
85+
}
86+
}
87+
}
6188
}
6289

6390
return $content;

src/PhpWord/Writer/HTML/Element/ListItemRun.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,22 @@ public function write()
3636
return '';
3737
}
3838

39-
$writer = new Container($this->parentWriter, $this->element);
40-
$content = $writer->write() . PHP_EOL;
39+
$content = '<li>';
4140

42-
return $content;
41+
foreach ($this->element->getElements() as $element) {
42+
$namespace = 'PhpOffice\\PhpWord\\Writer\\HTML\\Element';
43+
$elementClass = get_class($element);
44+
$writerClass = str_replace('PhpOffice\\PhpWord\\Element', $namespace, $elementClass);
45+
46+
if (!class_exists($writerClass)) {
47+
continue;
48+
}
49+
50+
/** @var AbstractElement $writer */
51+
$writer = new $writerClass($this->parentWriter, $element, true);
52+
$content .= $writer->write();
53+
}
54+
55+
return "$content</li>";
4356
}
4457
}

tests/PhpWordTests/Writer/HTML/ElementTest.php

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -200,24 +200,67 @@ public function testWriteTitleTextRun(): void
200200
*/
201201
public function testListItemRun(): void
202202
{
203-
$expected1 = 'List item run 1';
204-
$expected2 = 'List item run 1 in bold';
203+
$expected11 = 'List item run 1.1';
204+
$expected11InBold = 'List item run 1.1 in bold';
205+
$expected12 = 'List item run 1.2';
206+
$expected21 = 'List item run 2.1';
207+
$expected22 = 'List item run 2.2';
208+
$expected31 = 'List item run 3.1';
209+
$expected13 = 'List item run 1.3';
205210

206211
$phpWord = new PhpWord();
207212
$section = $phpWord->addSection();
208213

209-
$listItemRun = $section->addListItemRun(0, null, 'MyParagraphStyle');
210-
$listItemRun->addText($expected1);
211-
$listItemRun->addText($expected2, ['bold' => true]);
214+
$listItemRun11 = $section->addListItemRun(0, null, 'MyParagraphStyle');
215+
$listItemRun11->addText($expected11);
216+
$listItemRun11->addText($expected11InBold, array('bold' => true));
217+
218+
$listItemRun12 = $section->addListItemRun(0);
219+
$listItemRun12->addText($expected12);
220+
221+
$listItemRun21 = $section->addListItemRun(1);
222+
$listItemRun21->addText($expected21);
223+
224+
$listItemRun22 = $section->addListItemRun(1);
225+
$listItemRun22->addText($expected22);
226+
227+
$listItemRun31 = $section->addListItemRun(2);
228+
$listItemRun31->addText($expected31);
229+
230+
$listItemRun13 = $section->addListItemRun(0);
231+
$listItemRun13->addText($expected13);
212232

213233
$htmlWriter = new HTML($phpWord);
214234
$content = $htmlWriter->getContent();
215235

216-
$dom = new DOMDocument();
236+
$dom = new \DOMDocument();
217237
$dom->loadHTML($content);
218238

219-
self::assertEquals($expected1, $dom->getElementsByTagName('p')->item(0)->textContent);
220-
self::assertEquals($expected2, $dom->getElementsByTagName('p')->item(1)->textContent);
239+
$xpath = new \DOMXPath($dom);
240+
241+
$list = $xpath->query('//body/div/ul/li');
242+
243+
$item11 = $list->item(0);
244+
$item12 = $list->item(1);
245+
$item13 = $list->item(2);
246+
247+
$this->assertEquals($expected11, $item11->childNodes->item(0)->textContent);
248+
$this->assertEquals('span', $item11->childNodes->item(1)->nodeName);
249+
$this->assertEquals($expected11InBold, $item11->childNodes->item(1)->textContent);
250+
251+
$this->assertEquals($expected12, $item12->childNodes->item(0)->textContent);
252+
$this->assertEquals('ul', $item12->childNodes->item(1)->nodeName);
253+
254+
$this->assertEquals($expected21, $item12->childNodes->item(1)->childNodes->item(0)->textContent);
255+
256+
$item22 = $item12->childNodes->item(1)->childNodes->item(1);
257+
258+
$this->assertEquals($expected22, $item22->childNodes->item(0)->textContent);
259+
$this->assertEquals('ul', $item22->childNodes->item(1)->nodeName);
260+
261+
$this->assertEquals($expected31, $item22->childNodes->item(1)->childNodes->item(0)->textContent);
262+
263+
$this->assertEquals($expected13, $item13->childNodes->item(0)->textContent);
221264
}
222265

223266
/**

0 commit comments

Comments
 (0)