From b86c60694ca074ef5cb629794f77b0041ba8211f Mon Sep 17 00:00:00 2001 From: Julien Aupart Date: Sun, 8 Nov 2020 20:58:06 +0100 Subject: [PATCH] feat: Update addHtml to handle style inheritance The aim is to get the output closer to the source html --- src/PhpWord/Element/AbstractContainer.php | 1 + src/PhpWord/Shared/Html.php | 44 ++++++++++++++++++++--- tests/PhpWord/Shared/HtmlTest.php | 14 +++++--- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index 0c773dbe69..6a1ed93013 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -109,6 +109,7 @@ public function __call($function, $args) } else { // All other elements array_unshift($args, $element); // Prepend element name to the beginning of args array + return call_user_func_array(array($this, 'addElement'), $args); } } diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 54e9509e5f..b29c9a1bbd 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -364,7 +364,7 @@ protected static function parseCell($node, $element, &$styles) $cell = $element->addCell(null, $cellStyles); if (self::shouldAddTextRun($node)) { - return $cell->addTextRun(self::parseInlineStyle($node, $styles['paragraph'])); + return $cell->addTextRun(self::filterOutNonInheritedStyles(self::parseInlineStyle($node, $styles['paragraph']))); } return $cell; @@ -395,15 +395,51 @@ protected static function shouldAddTextRun(\DOMNode $node) */ protected static function recursiveParseStylesInHierarchy(\DOMNode $node, array $style) { - $parentStyle = self::parseInlineStyle($node, array()); - $style = array_merge($parentStyle, $style); + $parentStyle = array(); if ($node->parentNode != null && XML_ELEMENT_NODE == $node->parentNode->nodeType) { - $style = self::recursiveParseStylesInHierarchy($node->parentNode, $style); + $parentStyle = self::recursiveParseStylesInHierarchy($node->parentNode, array()); } + if ($node->nodeName === '#text') { + $parentStyle = array_merge($parentStyle, $style); + } else { + $parentStyle = self::filterOutNonInheritedStyles($parentStyle); + } + $style = self::parseInlineStyle($node, $parentStyle); return $style; } + /** + * Removes non-inherited styles from array + * + * @param array &$styles + */ + protected static function filterOutNonInheritedStyles(array $styles) + { + $nonInheritedStyles = array( + 'borderSize', + 'borderTopSize', + 'borderRightSize', + 'borderBottomSize', + 'borderLeftSize', + 'borderColor', + 'borderTopColor', + 'borderRightColor', + 'borderBottomColor', + 'borderLeftColor', + 'borderStyle', + 'spaceAfter', + 'spaceBefore', + 'underline', + 'strikethrough', + 'hidden', + ); + + $styles = array_diff_key($styles, array_flip($nonInheritedStyles)); + + return $styles; + } + /** * Parse list node * diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 5bc9e2411a..0dfef405d1 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -293,11 +293,11 @@ public function testParseTable() { $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); - $html = ' + $html = '
- - - + + + @@ -324,6 +324,12 @@ public function testParseTable() $this->assertEquals('00BB00', $doc->getElementAttribute('/w:document/w:body/w:tbl/w:tr[1]/w:tc[3]/w:tcPr/w:tcBorders/w:right', 'w:color')); $this->assertEquals('00CC00', $doc->getElementAttribute('/w:document/w:body/w:tbl/w:tr[1]/w:tc[3]/w:tcPr/w:tcBorders/w:bottom', 'w:color')); $this->assertEquals('00DD00', $doc->getElementAttribute('/w:document/w:body/w:tbl/w:tr[1]/w:tc[3]/w:tcPr/w:tcBorders/w:left', 'w:color')); + + //check borders are not propagated inside cells + $this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p')); + $this->assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p/w:pPr/w:pBdr')); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[2]/w:p')); + $this->assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[2]/w:p/w:pPr/w:pBdr')); } /**
header aheader b

header a

header b header c