From 0164e37873bf45f1cac86b6e995c32bf9e9b9b6e Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Sat, 31 May 2014 01:30:59 +0700 Subject: [PATCH 1/3] Decompose Shared\Html --- samples/Sample_26_Html.php | 6 +- src/PhpWord/Shared/Html.php | 440 ++++++++++++++++++++------------ src/PhpWord/Style/Paragraph.php | 1 + 3 files changed, 280 insertions(+), 167 deletions(-) diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index 58436915..92b3aa49 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -8,7 +8,11 @@ $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $html = '

Adding element via HTML

'; $html .= '

Some well formed HTML snippet needs to be used

'; -$html .= '

With for example some inline formatting

'; +$html .= '

With for example some1 inline formatting1

'; +$html .= '

Unordered (bulleted) list:

'; +$html .= ''; +$html .= '

Ordered (numbered) list:

'; +$html .= '
  1. Item 1
  2. Item 2
'; \PhpOffice\PhpWord\Shared\Html::addHtml($section, $html); diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 171cfa21..bfe64a25 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -17,8 +17,12 @@ namespace PhpOffice\PhpWord\Shared; +use PhpOffice\PhpWord\Element\AbstractContainer; + /** * Common Html functions + * + * @SuppressWarnings(PHPMD.UnusedPrivateMethod) For readWPNode */ class Html { @@ -27,10 +31,10 @@ class Html * * Note: $stylesheet parameter is removed to avoid PHPMD error for unused parameter * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $object Where the parts need to be added + * @param \PhpOffice\PhpWord\Element\AbstractContainer $element Where the parts need to be added * @param string $html the code to parse */ - public static function addHtml($object, $html) + public static function addHtml($element, $html) { /* * @todo parse $stylesheet for default styles. Should result in an array based on id, class and element, @@ -44,17 +48,17 @@ class Html $node = $dom->getElementsByTagName('body'); - self::parseNode($node->item(0), $object); + self::parseNode($node->item(0), $element); } /** * parse Inline style of a node * * @param \DOMNode $node Node to check on attributes and to compile a style array - * @param array $style is supplied, the inline style attributes are added to the already existing style + * @param array $styles is supplied, the inline style attributes are added to the already existing style * @return array */ - protected static function parseInlineStyle($node, $style = array()) + protected static function parseInlineStyle($node, $styles = array()) { if ($node->nodeType == XML_ELEMENT_NODE) { $attributes = $node->attributes; // get all the attributes(eg: id, class) @@ -62,191 +66,295 @@ class Html foreach ($attributes as $attribute) { switch ($attribute->name) { case 'style': - $properties = explode(';', trim($attribute->value, " \t\n\r\0\x0B;")); - foreach ($properties as $property) { - list ($cKey, $cValue) = explode(':', $property, 2); - $cValue = trim($cValue); - switch (trim($cKey)) { - case 'text-decoration': - switch ($cValue) { - case 'underline': - $style['underline'] = 'single'; - break; - case 'line-through': - $style['strikethrough'] = true; - break; - } - break; - case 'text-align': - $style['align'] = $cValue; - break; - case 'color': - $style['color'] = trim($cValue, "#"); - break; - case 'background-color': - $style['bgColor'] = trim($cValue, "#"); - break; - } - } + $styles = self::parseStyle($attribute, $styles); break; } } } - return $style; + return $styles; } /** - * parse a node and add a corresponding element to the object + * Parse a node and add a corresponding element to the parent element * * @param \DOMNode $node node to parse - * @param \PhpOffice\PhpWord\Element\AbstractContainer $object object to add an element corresponding with the node + * @param \PhpOffice\PhpWord\Element\AbstractContainer $element object to add an element corresponding with the node * @param array $styles Array with all styles * @param array $data Array to transport data to a next level in the DOM tree, for example level of listitems */ - protected static function parseNode( - $node, - $object, - $styles = array('fontStyle' => array(), 'paragraphStyle' => array(), 'listStyle' => array()), - $data = array() - ) { - $newobject = null; - switch ($node->nodeName) { - case 'p': - $styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']); - $newobject = $object->addTextRun($styles['paragraphStyle']); - break; - - /** - * @todo Think of a clever way of defining header styles, now it is only based on the assumption, that - * Heading1 - Heading6 are already defined somewhere - */ - case 'h1': - $styles['paragraphStyle'] = 'Heading1'; - $newobject = $object->addTextRun($styles['paragraphStyle']); - break; - case 'h2': - $styles['paragraphStyle'] = 'Heading2'; - $newobject = $object->addTextRun($styles['paragraphStyle']); - break; - case 'h3': - $styles['paragraphStyle'] = 'Heading3'; - $newobject = $object->addTextRun($styles['paragraphStyle']); - break; - case 'h4': - $styles['paragraphStyle'] = 'Heading4'; - $newobject = $object->addTextRun($styles['paragraphStyle']); - break; - case 'h5': - $styles['paragraphStyle'] = 'Heading5'; - $newobject = $object->addTextRun($styles['paragraphStyle']); - break; - case 'h6': - $styles['paragraphStyle'] = 'Heading6'; - $newobject = $object->addTextRun($styles['paragraphStyle']); - break; - case '#text': - $styles['fontStyle'] = self::parseInlineStyle($node, $styles['fontStyle']); - if (method_exists($object, 'addText')) { - $object->addText($node->nodeValue, $styles['fontStyle'], $styles['paragraphStyle']); - } - break; - case 'strong': - $styles['fontStyle']['bold'] = true; - break; - case 'em': - $styles['fontStyle']['italic'] = true; - break; - case 'sup': - $styles['fontStyle']['superScript'] = true; - break; - case 'sub': - $styles['fontStyle']['subScript'] = true; - break; - - /** - * @todo As soon as TableItem, RowItem and CellItem support relative width and height - */ - case 'table': - $styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']); - $newobject = $object->addTable(); - // if ($attributes->getNamedItem('width') !== null) { - // $newobject->setWidth($attributes->getNamedItem('width')->value); - // } - break; - case 'tr': - /** @var \PhpOffice\PhpWord\Element\Table $object Type hint */ - $styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']); - $newobject = $object->addRow(); - // if ($attributes->getNamedItem('height') !== null) { - // $newobject->setHeight($attributes->getNamedItem('height')->value); - // } - break; - case 'td': - /** @var \PhpOffice\PhpWord\Element\Row $object Type hint */ - $styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']); - // if ($attributes->getNamedItem('width') !== null) { - // $newobject=$object->addCell($width=$attributes->getNamedItem('width')->value); - // } else { - // $newobject=$object->addCell(); - // } - $newobject = $object->addCell(); - break; - case 'ul': - if (isset($data['listdepth'])) { - $data['listdepth'] ++; - } else { - $data['listdepth'] = 0; - } - $styles['listStyle']['listType'] = 3; // TYPE_BULLET_FILLED = 3; - break; - case 'ol': - if (isset($data['listdepth'])) { - $data['listdepth'] ++; - } else { - $data['listdepth'] = 0; - } - $styles['listStyle']['listType'] = 7; // TYPE_NUMBER = 7; - break; - - /** - * @todo As soon as ListItem inherits from AbstractContainer or TextRun delete parsing part of childNodes - */ - case 'li': - $cNodes = $node->childNodes; - if (count($cNodes) > 0) { - $text = ''; - foreach ($cNodes as $cNode) { - if ($cNode->nodeName == '#text') { - $text = $cNode->nodeValue; - } - } - $object->addListItem( - $text, - $data['listdepth'], - $styles['fontStyle'], - $styles['listStyle'], - $styles['paragraphStyle'] - ); - } + protected static function parseNode($node, $element, $styles = array(), $data = array()) + { + // Populate styles array + $styleTypes = array('font', 'paragraph', 'list'); + foreach ($styleTypes as $styleType) { + if (!isset($styles[$styleType])) { + $styles[$styleType] = array(); + } } - if ($newobject === null) { - $newobject = $object; + // Node mapping table + $nodes = array( + // $method $node $element $styles $data $argument1 $argument2 + 'p' => array('Paragraph', $node, $element, $styles, null, null, null), + 'h1' => array('Heading', null, $element, $styles, null, 'Heading1', null), + 'h2' => array('Heading', null, $element, $styles, null, 'Heading2', null), + 'h3' => array('Heading', null, $element, $styles, null, 'Heading3', null), + 'h4' => array('Heading', null, $element, $styles, null, 'Heading4', null), + 'h5' => array('Heading', null, $element, $styles, null, 'Heading5', null), + 'h6' => array('Heading', null, $element, $styles, null, 'Heading6', null), + '#text' => array('Text', $node, $element, $styles, null, null, null), + 'strong' => array('Property', null, null, $styles, null, 'bold', true), + 'em' => array('Property', null, null, $styles, null, 'italic', true), + 'sup' => array('Property', null, null, $styles, null, 'superScript', true), + 'sub' => array('Property', null, null, $styles, null, 'subScript', true), + 'table' => array('Table', $node, $element, $styles, null, 'addTable', true), + 'tr' => array('Table', $node, $element, $styles, null, 'addRow', true), + 'td' => array('Table', $node, $element, $styles, null, 'addCell', true), + 'ul' => array('List', null, null, $styles, $data, 3, null), + 'ol' => array('List', null, null, $styles, $data, 7, null), + 'li' => array('ListItem', $node, $element, $styles, $data, null, null), + ); + + $newElement = null; + $keys = array('node', 'element', 'styles', 'data', 'argument1', 'argument2'); + + if (array_key_exists($node->nodeName, $nodes)) { + + // Execute method based on node mapping table and return $newElement or null + // Arguments are passed by reference + $arguments = array(); + $args = array(); + list($method, $args[0], $args[1], $args[2], $args[3], $args[4], $args[5]) = $nodes[$node->nodeName]; + for ($i = 0; $i <= 5; $i++) { + if ($args[$i] !== null) { + $arguments[$keys[$i]] = &$args[$i]; + } + } + $method = "parse{$method}"; + $newElement = call_user_func_array(array('PhpOffice\PhpWord\Shared\Html', $method), $arguments); + + // Retrieve back variables from arguments + foreach ($keys as $key) { + if (array_key_exists($key, $arguments)) { + $$key = $arguments[$key]; + } + } } - /** - * @todo As soon as ListItem inherits from AbstractContainer or TextRun delete condition - */ + if ($newElement === null) { + $newElement = $element; + } + + self::parseChildNodes($node, $newElement, $styles, $data); + } + + /** + * Parse child nodes + * + * @param \DOMNode $node + * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param array $styles + * @param array $data + */ + private static function parseChildNodes($node, $element, $styles, $data) + { if ($node->nodeName != 'li') { $cNodes = $node->childNodes; if (count($cNodes) > 0) { foreach ($cNodes as $cNode) { - if ($newobject instanceof \PhpOffice\PhpWord\Element\AbstractContainer) { - self::parseNode($cNode, $newobject, $styles, $data); + if ($element instanceof AbstractContainer) { + self::parseNode($cNode, $element, $styles, $data); } } } } } + + /** + * Parse paragraph node + * + * @param \DOMNode $node + * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param array $styles + * @return \PhpOffice\PhpWord\Element\TextRun + */ + private static function parseParagraph($node, $element, &$styles) + { + $styles['paragraph'] = self::parseInlineStyle($node, $styles['paragraph']); + $newElement = $element->addTextRun($styles['paragraph']); + + return $newElement; + } + + /** + * Parse heading node + * + * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param array $styles + * @param string $argument1 Name of heading style + * @return \PhpOffice\PhpWord\Element\TextRun + * + * @todo Think of a clever way of defining header styles, now it is only based on the assumption, that + * Heading1 - Heading6 are already defined somewhere + */ + private static function parseHeading($element, &$styles, $argument1) + { + $styles['paragraph'] = $argument1; + $newElement = $element->addTextRun($styles['paragraph']); + + return $newElement; + } + + /** + * Parse text node + * + * @param \DOMNode $node + * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param array $styles + * @return null + */ + private static function parseText($node, $element, &$styles) + { + $styles['font'] = self::parseInlineStyle($node, $styles['font']); + if (method_exists($element, 'addText')) { + $element->addText($node->nodeValue, $styles['font'], $styles['paragraph']); + } + + return null; + } + + /** + * Parse property node + * + * @param array $styles + * @param string $argument1 Style name + * @param string $argument2 Style value + * @return null + */ + private static function parseProperty(&$styles, $argument1, $argument2) + { + $styles['font'][$argument1] = $argument2; + + return null; + } + + /** + * Parse table node + * + * @param \DOMNode $node + * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param array $styles + * @param string $argument1 Method name + * @return \PhpOffice\PhpWord\Element\AbstractContainer $element + * + * @todo As soon as TableItem, RowItem and CellItem support relative width and height + */ + private static function parseTable($node, $element, &$styles, $argument1) + { + $styles['paragraph'] = self::parseInlineStyle($node, $styles['paragraph']); + + $newElement = $element->$argument1(); + + // $attributes = $node->attributes; + // if ($attributes->getNamedItem('width') !== null) { + // $newElement->setWidth($attributes->getNamedItem('width')->value); + // } + + // if ($attributes->getNamedItem('height') !== null) { + // $newElement->setHeight($attributes->getNamedItem('height')->value); + // } + // if ($attributes->getNamedItem('width') !== null) { + // $newElement=$element->addCell($width=$attributes->getNamedItem('width')->value); + // } + + return $newElement; + } + + /** + * Parse list node + * + * @param array $styles + * @param array $data + * @param string $argument1 List type + * @return null + */ + private static function parseList(&$styles, &$data, $argument1) + { + if (isset($data['listdepth'])) { + $data['listdepth']++; + } else { + $data['listdepth'] = 0; + } + $styles['list']['listType'] = $argument1; + + return null; + } + + /** + * Parse list item node + * + * @param \DOMNode $node + * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param array $styles + * @param array $data + * @return null + * + * @todo This function is almost the same like `parseChildNodes`. Merged? + * @todo As soon as ListItem inherits from AbstractContainer or TextRun delete parsing part of childNodes + */ + private static function parseListItem($node, $element, &$styles, $data) + { + $cNodes = $node->childNodes; + if (count($cNodes) > 0) { + $text = ''; + foreach ($cNodes as $cNode) { + if ($cNode->nodeName == '#text') { + $text = $cNode->nodeValue; + } + } + $element->addListItem($text, $data['listdepth'], $styles['font'], $styles['list'], $styles['paragraph']); + } + + return null; + } + + /** + * Parse style + * + * @param \DOMAttr $attribute + * @param array $styles + * @return array + */ + private static function parseStyle($attribute, $styles) + { + $properties = explode(';', trim($attribute->value, " \t\n\r\0\x0B;")); + foreach ($properties as $property) { + list($cKey, $cValue) = explode(':', $property, 2); + $cValue = trim($cValue); + switch (trim($cKey)) { + case 'text-decoration': + switch ($cValue) { + case 'underline': + $styles['underline'] = 'single'; + break; + case 'line-through': + $styles['strikethrough'] = true; + break; + } + break; + case 'text-align': + $styles['align'] = $cValue; + break; + case 'color': + $styles['color'] = trim($cValue, "#"); + break; + case 'background-color': + $styles['bgColor'] = trim($cValue, "#"); + break; + } + } + + return $styles; + } } diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index 32c7f0f8..81673586 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -186,6 +186,7 @@ class Paragraph extends AbstractStyle * reduce function call and increase cohesion between functions. Should be * implemented in all styles. * + * @ignoreScrutinizerPatch * @return array */ public function getStyleValues() From ec85d7d641dc7f6a2f75f0ae81279b0c1c5d23a7 Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Sat, 31 May 2014 03:06:11 +0700 Subject: [PATCH 2/3] #80: Basic HTML reader --- CHANGELOG.md | 3 +- samples/Sample_30_ReadHTML.php | 15 ++++++ samples/resources/Sample_30_ReadHTML.html | 15 ++++++ src/PhpWord/IOFactory.php | 2 +- src/PhpWord/Reader/HTML.php | 50 ++++++++++++++++++ src/PhpWord/Shared/Html.php | 17 +++++-- tests/PhpWord/Tests/Reader/HTMLTest.php | 51 +++++++++++++++++++ .../Tests/_files/documents/reader.html | 15 ++++++ 8 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 samples/Sample_30_ReadHTML.php create mode 100644 samples/resources/Sample_30_ReadHTML.html create mode 100644 src/PhpWord/Reader/HTML.php create mode 100644 tests/PhpWord/Tests/Reader/HTMLTest.php create mode 100644 tests/PhpWord/Tests/_files/documents/reader.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f4e6cf0..8b36f34a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ This is the changelog between releases of PHPWord. Releases are listed in revers ## 0.11.0 - Not yet released -This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four new elements were added: TextBox, ListItemRun, Field, and Line. Relative and absolute positioning for images and textboxes were added. Writer classes were refactored into parts, elements, and styles. ODT and RTF features were enhanced. Ability to add elements to PHPWord object via HTML were implemeted. RTF reader were initiated. +This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four new elements were added: TextBox, ListItemRun, Field, and Line. Relative and absolute positioning for images and textboxes were added. Writer classes were refactored into parts, elements, and styles. ODT and RTF features were enhanced. Ability to add elements to PHPWord object via HTML were implemeted. RTF and HTML reader were initiated. ### Features @@ -33,6 +33,7 @@ This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four - RTF Reader: Basic RTF reader - @ivanlanin GH-72 GH-252 - Element: New `Line` element - @basjan GH-253 - Title: Ability to apply numbering in heading - @ivanlanin GH-193 +- HTML Reader: Basic HTML reader - @ivanlanin GH-80 ### Bugfixes diff --git a/samples/Sample_30_ReadHTML.php b/samples/Sample_30_ReadHTML.php new file mode 100644 index 00000000..029f8c8c --- /dev/null +++ b/samples/Sample_30_ReadHTML.php @@ -0,0 +1,15 @@ + + + +PHPWord + + +

Adding element via HTML

+

Some well formed HTML snippet needs to be used

+

With for example some1 inline formatting1

+

Unordered (bulleted) list:

+ +

Ordered (numbered) list:

+
  1. Item 1
  2. Item 2
+ + diff --git a/src/PhpWord/IOFactory.php b/src/PhpWord/IOFactory.php index 0d5fe689..1d784962 100644 --- a/src/PhpWord/IOFactory.php +++ b/src/PhpWord/IOFactory.php @@ -51,7 +51,7 @@ abstract class IOFactory */ public static function createReader($name = 'Word2007') { - if (!in_array($name, array('ReaderInterface', 'Word2007', 'ODText', 'RTF'))) { + if (!in_array($name, array('ReaderInterface', 'Word2007', 'ODText', 'RTF', 'HTML'))) { throw new Exception("\"{$name}\" is not a valid reader."); } diff --git a/src/PhpWord/Reader/HTML.php b/src/PhpWord/Reader/HTML.php new file mode 100644 index 00000000..a6582a3f --- /dev/null +++ b/src/PhpWord/Reader/HTML.php @@ -0,0 +1,50 @@ +canRead($docFile)) { + $section = $phpWord->addSection(); + HTMLParser::addHtml($section, file_get_contents($docFile), true); + } else { + throw new \Exception("Cannot read {$docFile}."); + } + + return $phpWord; + } +} diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index bfe64a25..83292a3a 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -32,20 +32,27 @@ class Html * Note: $stylesheet parameter is removed to avoid PHPMD error for unused parameter * * @param \PhpOffice\PhpWord\Element\AbstractContainer $element Where the parts need to be added - * @param string $html the code to parse + * @param string $html The code to parse + * @param bool $fullHTML If it's a full HTML, no need to add 'body' tag */ - public static function addHtml($element, $html) + public static function addHtml($element, $html, $fullHTML = false) { /* * @todo parse $stylesheet for default styles. Should result in an array based on id, class and element, * which could be applied when such an element occurs in the parseNode function. */ - $html = str_replace(array("\n", "\r"), '', $html); + // Preprocess: remove all line ends, decode HTML entity, and add body tag for HTML fragments + $html = str_replace(array("\n", "\r"), '', $html); + $html = html_entity_decode($html); + if ($fullHTML === false) { + $html = '' . $html . ''; + } + + // Load DOM $dom = new \DOMDocument(); $dom->preserveWhiteSpace = true; - $dom->loadXML('' . html_entity_decode($html) . ''); - + $dom->loadXML($html); $node = $dom->getElementsByTagName('body'); self::parseNode($node->item(0), $element); diff --git a/tests/PhpWord/Tests/Reader/HTMLTest.php b/tests/PhpWord/Tests/Reader/HTMLTest.php new file mode 100644 index 00000000..cb3dc55c --- /dev/null +++ b/tests/PhpWord/Tests/Reader/HTMLTest.php @@ -0,0 +1,51 @@ +assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + } + + /** + * Test load exception + * + * @expectedException \Exception + * @expectedExceptionMessage Cannot read + */ + public function testLoadException() + { + $filename = __DIR__ . '/../_files/documents/foo.html'; + IOFactory::load($filename, 'HTML'); + } +} diff --git a/tests/PhpWord/Tests/_files/documents/reader.html b/tests/PhpWord/Tests/_files/documents/reader.html new file mode 100644 index 00000000..5593298b --- /dev/null +++ b/tests/PhpWord/Tests/_files/documents/reader.html @@ -0,0 +1,15 @@ + + + +PHPWord + + +

Adding element via HTML

+

Some well formed HTML snippet needs to be used

+

With for example some1 inline formatting1

+

Unordered (bulleted) list:

+ +

Ordered (numbered) list:

+
  1. Item 1
  2. Item 2
+ + From 022cdeb570519e238247afb0a75ff9b5949d3ef7 Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Sat, 31 May 2014 03:28:58 +0700 Subject: [PATCH 3/3] Documentation updates and test fix for #254 --- CHANGELOG.md | 2 +- docs/intro.rst | 110 ++++++++++++------------ docs/src/documentation.md | 56 ++++++------ tests/PhpWord/Tests/Shared/HtmlTest.php | 4 +- 4 files changed, 86 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b36f34a..43b5373d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,7 @@ This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four - RTF Reader: Basic RTF reader - @ivanlanin GH-72 GH-252 - Element: New `Line` element - @basjan GH-253 - Title: Ability to apply numbering in heading - @ivanlanin GH-193 -- HTML Reader: Basic HTML reader - @ivanlanin GH-80 +- HTML Reader: Basic HTML reader - @ivanlanin GH-80 GH-254 ### Bugfixes diff --git a/docs/intro.rst b/docs/intro.rst index 3da729e8..94001237 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -117,61 +117,61 @@ Writers Readers ~~~~~~~ -+---------------------------+----------------------+--------+-------+-------+ -| Features | | DOCX | ODT | RTF | -+===========================+======================+========+=======+=======+ -| **Document Properties** | Standard | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Custom | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| **Element Type** | Text | ✓ | ✓ | ✓ | -+---------------------------+----------------------+--------+-------+-------+ -| | Text Run | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Title | ✓ | ✓ | | -+---------------------------+----------------------+--------+-------+-------+ -| | Link | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Preserve Text | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Text Break | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Page Break | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | List | ✓ | ✓ | | -+---------------------------+----------------------+--------+-------+-------+ -| | Table | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Image | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Object | | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Watermark | | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Table of Contents | | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Header | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Footer | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Footnote | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Endnote | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+ -| **Graphs** | 2D basic graphs | | | | -+---------------------------+----------------------+--------+-------+-------+ -| | 2D advanced graphs | | | | -+---------------------------+----------------------+--------+-------+-------+ -| | 3D graphs | | | | -+---------------------------+----------------------+--------+-------+-------+ -| **Math** | OMML support | | | | -+---------------------------+----------------------+--------+-------+-------+ -| | MathML support | | | | -+---------------------------+----------------------+--------+-------+-------+ -| **Bonus** | Encryption | | | | -+---------------------------+----------------------+--------+-------+-------+ -| | Protection | | | | -+---------------------------+----------------------+--------+-------+-------+ ++---------------------------+----------------------+--------+-------+-------+-------+ +| Features | | DOCX | ODT | RTF | HTML | ++===========================+======================+========+=======+=======+=======+ +| **Document Properties** | Standard | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Custom | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Text Run | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Title | ✓ | ✓ | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Link | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Preserve Text | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Text Break | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Page Break | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | List | ✓ | ✓ | | ✓ | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Table | ✓ | | | ✓ | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Image | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Object | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Watermark | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Table of Contents | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Header | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Footer | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Footnote | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Endnote | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| **Graphs** | 2D basic graphs | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | 2D advanced graphs | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | 3D graphs | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| **Math** | OMML support | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | MathML support | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| **Bonus** | Encryption | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Protection | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ Contributing ------------ diff --git a/docs/src/documentation.md b/docs/src/documentation.md index 9db32c9f..773269a9 100644 --- a/docs/src/documentation.md +++ b/docs/src/documentation.md @@ -111,34 +111,34 @@ Below are the supported features for each file formats. ### Readers -| Features | | DOCX | ODT | RTF | -|-------------------------|--------------------|------|-----|-----| -| **Document Properties** | Standard | ✓ | | | -| | Custom | ✓ | | | -| **Element Type** | Text | ✓ | ✓ | ✓ | -| | Text Run | ✓ | | | -| | Title | ✓ | ✓ | | -| | Link | ✓ | | | -| | Preserve Text | ✓ | | | -| | Text Break | ✓ | | | -| | Page Break | ✓ | | | -| | List | ✓ | ✓ | | -| | Table | ✓ | | | -| | Image | ✓ | | | -| | Object | | | | -| | Watermark | | | | -| | Table of Contents | | | | -| | Header | ✓ | | | -| | Footer | ✓ | | | -| | Footnote | ✓ | | | -| | Endnote | ✓ | | | -| **Graphs** | 2D basic graphs | | | | -| | 2D advanced graphs | | | | -| | 3D graphs | | | | -| **Math** | OMML support | | | | -| | MathML support | | | | -| **Bonus** | Encryption | | | | -| | Protection | | | | +| Features | | DOCX | ODT | RTF | HTML| +|-------------------------|--------------------|------|-----|-----|-----| +| **Document Properties** | Standard | ✓ | | | | +| | Custom | ✓ | | | | +| **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | +| | Text Run | ✓ | | | | +| | Title | ✓ | ✓ | | | +| | Link | ✓ | | | | +| | Preserve Text | ✓ | | | | +| | Text Break | ✓ | | | | +| | Page Break | ✓ | | | | +| | List | ✓ | ✓ | | ✓ | +| | Table | ✓ | | | ✓ | +| | Image | ✓ | | | | +| | Object | | | | | +| | Watermark | | | | | +| | Table of Contents | | | | | +| | Header | ✓ | | | | +| | Footer | ✓ | | | | +| | Footnote | ✓ | | | | +| | Endnote | ✓ | | | | +| **Graphs** | 2D basic graphs | | | | | +| | 2D advanced graphs | | | | | +| | 3D graphs | | | | | +| **Math** | OMML support | | | | | +| | MathML support | | | | | +| **Bonus** | Encryption | | | | | +| | Protection | | | | | ## Contributing diff --git a/tests/PhpWord/Tests/Shared/HtmlTest.php b/tests/PhpWord/Tests/Shared/HtmlTest.php index 81714432..730600d7 100644 --- a/tests/PhpWord/Tests/Shared/HtmlTest.php +++ b/tests/PhpWord/Tests/Shared/HtmlTest.php @@ -58,8 +58,8 @@ class HtmlTest extends \PHPUnit_Framework_TestCase $section = new Section(1); $content = ''; $content .= '
HeaderContent
'; - $content .= '
  • Bullet
'; + $content .= '
  • Bullet
    • Bullet
'; $content .= '
  1. Bullet
'; - Html::addHtml($section, $content, null, array('listdepth' => 2)); + Html::addHtml($section, $content); } }