feat: Update addHtml to handle style inheritance

The aim is to get the output closer to the source html
This commit is contained in:
Julien Aupart 2020-11-08 20:58:06 +01:00
parent ec1b3d35ee
commit b86c60694c
3 changed files with 51 additions and 8 deletions

View File

@ -109,6 +109,7 @@ abstract class AbstractContainer extends AbstractElement
} else { } else {
// All other elements // All other elements
array_unshift($args, $element); // Prepend element name to the beginning of args array array_unshift($args, $element); // Prepend element name to the beginning of args array
return call_user_func_array(array($this, 'addElement'), $args); return call_user_func_array(array($this, 'addElement'), $args);
} }
} }

View File

@ -364,7 +364,7 @@ class Html
$cell = $element->addCell(null, $cellStyles); $cell = $element->addCell(null, $cellStyles);
if (self::shouldAddTextRun($node)) { if (self::shouldAddTextRun($node)) {
return $cell->addTextRun(self::parseInlineStyle($node, $styles['paragraph'])); return $cell->addTextRun(self::filterOutNonInheritedStyles(self::parseInlineStyle($node, $styles['paragraph'])));
} }
return $cell; return $cell;
@ -395,15 +395,51 @@ class Html
*/ */
protected static function recursiveParseStylesInHierarchy(\DOMNode $node, array $style) protected static function recursiveParseStylesInHierarchy(\DOMNode $node, array $style)
{ {
$parentStyle = self::parseInlineStyle($node, array()); $parentStyle = array();
$style = array_merge($parentStyle, $style);
if ($node->parentNode != null && XML_ELEMENT_NODE == $node->parentNode->nodeType) { 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; 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 * Parse list node
* *

View File

@ -293,11 +293,11 @@ class HtmlTest extends AbstractWebServerEmbeddedTest
{ {
$phpWord = new \PhpOffice\PhpWord\PhpWord(); $phpWord = new \PhpOffice\PhpWord\PhpWord();
$section = $phpWord->addSection(); $section = $phpWord->addSection();
$html = '<table align="left" style="width: 50%; border: 6px #0000FF solid;"> $html = '<table align="left" style="width: 50%; border: 12px #0000FF double">
<thead> <thead>
<tr style="background-color: #FF0000; text-align: center; color: #FFFFFF; font-weight: bold; "> <tr style="background-color: #FF0000; text-align: center; color: #FFFFFF; font-weight: bold">
<th style="width: 50pt">header a</th> <th style="width: 50pt"><p>header a</p></th>
<th style="width: 50; border-color: #00EE00">header b</th> <th style="width: 50; border-color: #00EE00; border-width: 3px"><span>header b</span></th>
<th style="border-color: #00AA00 #00BB00 #00CC00 #00DD00; border-width: 3px">header c</th> <th style="border-color: #00AA00 #00BB00 #00CC00 #00DD00; border-width: 3px">header c</th>
</tr> </tr>
</thead> </thead>
@ -324,6 +324,12 @@ class HtmlTest extends AbstractWebServerEmbeddedTest
$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('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('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')); $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'));
} }
/** /**