Skip to content

Commit 3066d47

Browse files
committed
Html parser (addHtml) - support vertical-align, valign
1 parent 108c1cd commit 3066d47

File tree

2 files changed

+86
-4
lines changed

2 files changed

+86
-4
lines changed

src/PhpWord/Shared/Html.php

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,19 @@ protected static function parseInlineStyle($node, $styles = array())
9696
$attributes = $node->attributes; // get all the attributes(eg: id, class)
9797

9898
foreach ($attributes as $attribute) {
99+
$val = trim($attribute->value);
99100
switch (strtolower($attribute->name)) {
100101
case 'style':
101102
$styles = self::parseStyle($attribute, $styles);
102103
break;
103104
case 'align':
104-
$styles['alignment'] = self::mapAlign($attribute->value);
105+
$styles['alignment'] = self::mapAlign($val);
105106
break;
106107
case 'lang':
107-
$styles['lang'] = $attribute->value;
108+
$styles['lang'] = $val;
108109
break;
109110
case 'width':
110111
// tables, cells
111-
$val = trim($attribute->value);
112112
if(false !== strpos($val, '%')){
113113
// e.g. <table width="100%"> or <td width=50%>
114114
$styles['width'] = intval($val) * 50;
@@ -126,7 +126,13 @@ protected static function parseInlineStyle($node, $styles = array())
126126
break;
127127
case 'bgcolor':
128128
// tables, rows, cells e.g. <tr bgColor="#FF0000">
129-
$styles['bgColor'] = trim($attribute->value, '# ');
129+
$styles['bgColor'] = trim($val, '# ');
130+
break;
131+
case 'valign':
132+
// cells e.g. <td valign="middle">
133+
if (preg_match('#(?:top|bottom|middle|baseline)#i', $val, $matches)) {
134+
$styles['valign'] = self::mapAlignVertical($matches[0]);
135+
}
130136
break;
131137
}
132138
}
@@ -678,6 +684,12 @@ protected static function parseStyle($attribute, $styles)
678684
$styles["border{$which}Style"] = self::mapBorderStyle($matches[3]);
679685
}
680686
break;
687+
case 'vertical-align':
688+
// https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align
689+
if (preg_match('#(?:top|bottom|middle|sub|baseline)#i', $cValue, $matches)) {
690+
$styles['valign'] = self::mapAlignVertical($matches[0]);
691+
}
692+
break;
681693
}
682694
}
683695

@@ -842,6 +854,32 @@ protected static function mapAlign($cssAlignment)
842854
}
843855
}
844856

857+
/**
858+
* Transforms a HTML/CSS alignment into a \PhpOffice\PhpWord\SimpleType\Jc
859+
*
860+
* @param string $cssAlignment
861+
* @return string|null
862+
*/
863+
protected static function mapAlignVertical($alignment)
864+
{
865+
$alignment = strtolower($alignment);
866+
switch ($alignment) {
867+
case 'top':
868+
case 'baseline':
869+
case 'bottom':
870+
return $alignment;
871+
case 'middle':
872+
return 'center';
873+
case 'sub':
874+
return 'bottom';
875+
case 'text-top':
876+
case 'baseline':
877+
return 'top';
878+
default:
879+
return '';
880+
}
881+
}
882+
845883
/**
846884
* Map list style for ordered list
847885
*

tests/PhpWord/Shared/HtmlTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,4 +844,48 @@ public function testParseOrderedList()
844844
$this->assertTrue($doc->elementExists($xpath, $xmlFile));
845845
$this->assertEquals('lowerRoman', $doc->getElement($xpath, $xmlFile)->getAttribute('w:val'));
846846
}
847+
848+
/**
849+
* Parse ordered list start & numbering style
850+
*/
851+
public function testParseVerticalAlign()
852+
{
853+
$phpWord = new \PhpOffice\PhpWord\PhpWord();
854+
$section = $phpWord->addSection();
855+
856+
// borders & backgrounds are here just for better visual comparison
857+
$html = <<<HTML
858+
<table width="100%">
859+
<tr>
860+
<td width="20%" style="border: 1px #666666 solid;">default</td>
861+
<td width="20%" style="vertical-align: top; border: 1px #666666 solid;">top</td>
862+
<td width="20%" style="vertical-align: middle; border: 1px #666666 solid;">middle</td>
863+
<td width="20%" valign="bottom" style="border: 1px #666666 solid;">bottom</td>
864+
<td bgcolor="#DDDDDD"><br/><br/><br/><br/><br/><br/><br/></td>
865+
</tr>
866+
</table>
867+
HTML;
868+
869+
Html::addHtml($section, $html);
870+
$doc = TestHelperDOCX::getDocument($phpWord, 'Word2007');
871+
872+
// uncomment to see results
873+
file_put_contents('./table_src.html', $html);
874+
file_put_contents('./table_result_'.time().'.docx', file_get_contents( TestHelperDOCX::getFile() ) );
875+
876+
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc[1]/w:tcPr/w:vAlign';
877+
$this->assertFalse($doc->elementExists($xpath));
878+
879+
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc[2]/w:tcPr/w:vAlign';
880+
$this->assertTrue($doc->elementExists($xpath));
881+
$this->assertEquals('top', $doc->getElement($xpath)->getAttribute('w:val'));
882+
883+
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc[3]/w:tcPr/w:vAlign';
884+
$this->assertTrue($doc->elementExists($xpath));
885+
$this->assertEquals('center', $doc->getElement($xpath)->getAttribute('w:val'));
886+
887+
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc[4]/w:tcPr/w:vAlign';
888+
$this->assertTrue($doc->elementExists($xpath));
889+
$this->assertEquals('bottom', $doc->getElement($xpath)->getAttribute('w:val'));
890+
}
847891
}

0 commit comments

Comments
 (0)