diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 08004b7a..9e5d84b1 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -183,6 +183,7 @@ class Html 'img' => array('Image', $node, $element, $styles, null, null, null), 'br' => array('LineBreak', null, $element, $styles, null, null, null), 'a' => array('Link', $node, $element, $styles, null, null, null), + 'hr' => array('HorizRule', $node, $element, $styles, null, null, null), ); $newElement = null; @@ -630,10 +631,27 @@ class Html } break; case 'border': - if (preg_match('/([0-9]+[^0-9]*)\s+(\#[a-fA-F0-9]+)\s+([a-z]+)/', $cValue, $matches)) { - $styles['borderSize'] = Converter::cssToPoint($matches[1]); - $styles['borderColor'] = trim($matches[2], '#'); - $styles['borderStyle'] = self::mapBorderStyle($matches[3]); + case 'border-top': + case 'border-bottom': + case 'border-right': + case 'border-left': + // must have exact order [width color style], e.g. "1px #0011CC solid" or "2pt green solid" + // Word does not accept shortened hex colors e.g. #CCC, only full e.g. #CCCCCC + if (preg_match('/([0-9]+[^0-9]*)\s+(\#[a-fA-F0-9]+|[a-zA-Z]+)\s+([a-z]+)/', $cValue, $matches)) { + if(false !== strpos($cKey, '-')){ + $which = explode('-', $cKey)[1]; + $which = ucfirst($which); // e.g. bottom -> Bottom + }else{ + $which = ''; + } + // normalization: in HTML 1px means tinest possible line width, so we cannot convert 1px -> 15 twips, coz line'd be bold, we use smallest twip instead + $size = strtolower(trim($matches[1])); + // (!) BC change: up to ver. 0.17.0 Converter was incorrectly converting to points - Converter::cssToPoint($matches[1]) + $size = ($size == '1px') ? 1 : Converter::cssToTwip($size); + // valid variants may be e.g. borderSize, borderTopSize, borderLeftColor, etc .. + $styles["border{$which}Size"] = $size; // twips + $styles["border{$which}Color"] = trim($matches[2], '#'); + $styles["border{$which}Style"] = self::mapBorderStyle($matches[3]); } break; } @@ -835,4 +853,39 @@ class Html return $element->addLink($target, $node->textContent, $styles['font'], $styles['paragraph']); } + + /** + * Render horizontal rule + * Note: Word rule is not the same as HTML's
Custom style rule:
+END
+HTML; + + Html::addHtml($section, $html); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + // default rule + $xpath = '/w:document/w:body/w:p[2]/w:pPr/w:pBdr/w:bottom'; + $this->assertTrue($doc->elementExists($xpath)); + $this->assertEquals('single', $doc->getElement($xpath)->getAttribute('w:val')); // solid + $this->assertEquals('1', $doc->getElement($xpath)->getAttribute('w:sz')); // 1 twip + $this->assertEquals('000000', $doc->getElement($xpath)->getAttribute('w:color')); // black + + // custom style rule + $xpath = '/w:document/w:body/w:p[4]/w:pPr/w:pBdr/w:bottom'; + $this->assertTrue($doc->elementExists($xpath)); + $this->assertEquals('single', $doc->getElement($xpath)->getAttribute('w:val')); + $this->assertEquals(5 * 15, $doc->getElement($xpath)->getAttribute('w:sz')); + $this->assertEquals('lightblue', $doc->getElement($xpath)->getAttribute('w:color')); + + $xpath = '/w:document/w:body/w:p[4]/w:pPr/w:spacing'; + $this->assertTrue($doc->elementExists($xpath)); + $this->assertEquals(22.5, $doc->getElement($xpath)->getAttribute('w:before')); + $this->assertEquals(0, $doc->getElement($xpath)->getAttribute('w:after')); + $this->assertEquals(240, $doc->getElement($xpath)->getAttribute('w:line')); + } + }