fix parsing of table and p inside table cells

This commit is contained in:
troosan 2018-02-06 23:16:32 +01:00
parent cf6319d7d4
commit 46a5f96d3b
5 changed files with 60 additions and 6 deletions

View File

@ -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

View File

@ -7,11 +7,13 @@ $phpWord = new \PhpOffice\PhpWord\PhpWord();
$section = $phpWord->addSection();
$html = '<h1>Adding element via HTML</h1>';
$html .= '<p>Some well formed HTML snippet needs to be used</p>';
$html .= '<p>Some well-formed HTML snippet needs to be used</p>';
$html .= '<p>With for example <strong>some<sup>1</sup> <em>inline</em> formatting</strong><sub>1</sub></p>';
$html .= '<p>A link to <a href="http://phpword.readthedocs.io/">Read the docs</a></p>';
$html .= '<p lang="he-IL" style="text-align: right; direction: rtl">היי, זה פסקה מימין לשמאל</p>';
$html .= '<p style="margin-top: 240pt;">Unordered (bulleted) list:</p>';
$html .= '<ul><li>Item 1</li><li>Item 2</li><ul><li>Item 2.1</li><li>Item 2.1</li></ul></ul>';
@ -65,10 +67,20 @@ $html .= '<table align="center" style="width: 50%; border: 6px #0000FF double;">
</thead>
<tbody>
<tr><td style="border-style: dotted;">1</td><td colspan="2">2</td></tr>
<tr><td>4</td><td>5</td><td>6</td></tr>
<tr><td>This is <b>bold</b> text</td><td></td><td>6</td></tr>
</tbody>
</table>';
$html .= '<p style="margin-top: 240pt;">Table inside another table:</p>';
$html .= '<table align="center" style="width: 80%; border: 6px #0000FF double;">
<tr><td>
<table style="width: 100%; border: 4px #FF0000 dotted;">
<tr><td>column 1</td><td>column 2</td></tr>
</table>
</td></tr>
<tr><td style="text-align: center;">Cell in parent table</td></tr>
</table>';
\PhpOffice\PhpWord\Shared\Html::addHtml($section, $html, false, false);
// Save file

View File

@ -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);

View File

@ -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();
}

View File

@ -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'));
}