From 46a5f96d3b5104aaa6b016e5df0730e4382058e7 Mon Sep 17 00:00:00 2001 From: troosan Date: Tue, 6 Feb 2018 23:16:32 +0100 Subject: [PATCH] fix parsing of table and p inside table cells --- CHANGELOG.md | 2 ++ samples/Sample_26_Html.php | 16 +++++++-- src/PhpWord/Shared/Html.php | 38 +++++++++++++++++++++- src/PhpWord/Writer/Word2007/Style/Font.php | 4 +++ tests/PhpWord/Shared/HtmlTest.php | 6 ++-- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6f8b2da..fca2922c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,11 @@ v0.15.0 (?? ??? 2018) ### Added - Parsing of "align" HTML attribute - @troosan #1231 - Parse formatting inside HTML lists - @troosan @samimussbach #1239 #945 #1215 #508 +- Parsing of CSS `direction` instruction, HTML `lang` attribute, formatting inside table cell - @troosan # ### Fixed - fix reading of docx default style - @troosan #1238 +- fix the size unit of when parsing html images - @troosan #1254 diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index 69d9d131..d54d548c 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -7,11 +7,13 @@ $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $html = '

Adding element via HTML

'; -$html .= '

Some well formed HTML snippet needs to be used

'; +$html .= '

Some well-formed HTML snippet needs to be used

'; $html .= '

With for example some1 inline formatting1

'; $html .= '

A link to Read the docs

'; +$html .= '

היי, זה פסקה מימין לשמאל

'; + $html .= '

Unordered (bulleted) list:

'; $html .= ''; @@ -65,10 +67,20 @@ $html .= ' - +
12
456
This is bold text6
'; +$html .= '

Table inside another table:

'; +$html .= ' + + +
+ + +
column 1column 2
+
Cell in parent table
'; + \PhpOffice\PhpWord\Shared\Html::addHtml($section, $html, false, false); // Save file diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 0f5f446a..2eeaae8b 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -31,6 +31,7 @@ use PhpOffice\PhpWord\SimpleType\NumberFormat; class Html { private static $listIndex = 0; + private static $xpath; /** * Add HTML parts. @@ -65,6 +66,7 @@ class Html $dom = new \DOMDocument(); $dom->preserveWhiteSpace = $preserveWhiteSpace; $dom->loadXML($html); + self::$xpath = new \DOMXpath($dom); $node = $dom->getElementsByTagName('body'); self::parseNode($node->item(0), $element); @@ -89,6 +91,10 @@ class Html break; case 'align': $styles['alignment'] = self::mapAlign($attribute->value); + break; + case 'lang': + $styles['lang'] = $attribute->value; + break; } } } @@ -343,8 +349,33 @@ class Html if (!empty($colspan)) { $cellStyles['gridSpan'] = $colspan - 0; } + $cell = $element->addCell(null, $cellStyles); - return $element->addCell(null, $cellStyles); + if (self::shouldAddTextRun($node)) { + return $cell->addTextRun(self::parseInlineStyle($node, $styles['paragraph'])); + } + + return $cell; + } + + /** + * Checks if $node contains an HTML element that cannot be added to TextRun + * + * @param \DOMNode $node + * @return bool Returns true if the node contains an HTML element that cannot be added to TextRun + */ + private static function shouldAddTextRun(\DOMNode $node) + { + if (!$node->hasChildNodes()) { + return false; + } + + $containsBlockElement = self::$xpath->query('.//table|./p', $node)->length > 0; + if ($containsBlockElement) { + return false; + } + + return true; } /** @@ -469,6 +500,9 @@ class Html case 'text-align': $styles['alignment'] = self::mapAlign($cValue); break; + case 'direction': + $styles['rtl'] = $cValue === 'rtl'; + break; case 'font-size': $styles['size'] = Converter::cssToPoint($cValue); break; @@ -556,10 +590,12 @@ class Html case 'width': $width = $attribute->value; $style['width'] = $width; + $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; break; case 'height': $height = $attribute->value; $style['height'] = $height; + $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; break; case 'style': $styleattr = explode(';', $attribute->value); diff --git a/src/PhpWord/Writer/Word2007/Style/Font.php b/src/PhpWord/Writer/Word2007/Style/Font.php index 9c2714dc..ecaad416 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -90,6 +90,10 @@ class Font extends AbstractStyle $xmlWriter->writeAttributeIf($language->getLatin() !== null, 'w:val', $language->getLatin()); $xmlWriter->writeAttributeIf($language->getEastAsia() !== null, 'w:eastAsia', $language->getEastAsia()); $xmlWriter->writeAttributeIf($language->getBidirectional() !== null, 'w:bidi', $language->getBidirectional()); + //if bidi is not set but we are writing RTL, write the latin language in the bidi tag + if ($style->isRTL() && $language->getBidirectional() === null && $language->getLatin() !== null) { + $xmlWriter->writeAttribute('w:bidi', $language->getLatin()); + } $xmlWriter->endElement(); } diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 97a8fb15..7d5f0b4c 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -259,7 +259,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase Html::addHtml($section, $html, false, false); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); - echo $doc->printXml(); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:numPr/w:numId')); $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:t')); @@ -336,8 +336,8 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $baseXpath = '/w:document/w:body/w:p/w:r'; $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); - $this->assertStringMatchesFormat('%Swidth:150pt%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); - $this->assertStringMatchesFormat('%Sheight:200pt%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + $this->assertStringMatchesFormat('%Swidth:150px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + $this->assertStringMatchesFormat('%Sheight:200px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); $this->assertStringMatchesFormat('%Smso-position-horizontal:right%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); $this->assertStringMatchesFormat('%Smso-position-horizontal:left%S', $doc->getElementAttribute($baseXpath . '[2]/w:pict/v:shape', 'style')); }