Skip to content

Reader HTML: Support font styles for h1/h6 #2737

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changes/1.x/1.4.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- Writer HTML: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2731](https://github.com/PHPOffice/PHPWord/pull/2731)
- Writer ODText: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2735](https://github.com/PHPOffice/PHPWord/pull/2735)
- Add basic ruby text (phonetic guide) support for Word2007 and HTML Reader/Writer, RTF Writer, basic support for ODT writing by [@Deadpikle](https://github.com/Deadpikle) in [#2727](https://github.com/PHPOffice/PHPWord/pull/2727)
- Reader HTML: Support font styles for h1/h6 by [@Progi1984](https://github.com/Progi1984) fixing [#2619](https://github.com/PHPOffice/PHPWord/issues/2619) in [#2737](https://github.com/PHPOffice/PHPWord/pull/2737)

- Added Support for Writer Epub3 by [@Sambit003](https://github.com/Sambit003) in [#2724](https://github.com/PHPOffice/PHPWord/pull/2724)

Expand Down
33 changes: 15 additions & 18 deletions src/PhpWord/Shared/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -211,16 +211,16 @@ protected static function parseNode($node, $element, $styles = [], $data = []):

// Node mapping table
$nodes = [
// $method $node $element $styles $data $argument1 $argument2
'p' => ['Paragraph', $node, $element, $styles, null, null, null],
'h1' => ['Heading', null, $element, $styles, null, 'Heading1', null],
'h2' => ['Heading', null, $element, $styles, null, 'Heading2', null],
'h3' => ['Heading', null, $element, $styles, null, 'Heading3', null],
'h4' => ['Heading', null, $element, $styles, null, 'Heading4', null],
'h5' => ['Heading', null, $element, $styles, null, 'Heading5', null],
'h6' => ['Heading', null, $element, $styles, null, 'Heading6', null],
'#text' => ['Text', $node, $element, $styles, null, null, null],
'strong' => ['Property', null, null, $styles, null, 'bold', true],
// $method $node $element $styles $data $argument1 $argument2
'p' => ['Paragraph', $node, $element, $styles, null, null, null],
'h1' => ['Heading', $node, $element, $styles, null, 'Heading1', null],
'h2' => ['Heading', $node, $element, $styles, null, 'Heading2', null],
'h3' => ['Heading', $node, $element, $styles, null, 'Heading3', null],
'h4' => ['Heading', $node, $element, $styles, null, 'Heading4', null],
'h5' => ['Heading', $node, $element, $styles, null, 'Heading5', null],
'h6' => ['Heading', $node, $element, $styles, null, 'Heading6', null],
'#text' => ['Text', $node, $element, $styles, null, null, null],
'strong' => ['Property', null, null, $styles, null, 'bold', true],
'b' => ['Property', null, null, $styles, null, 'bold', true],
'em' => ['Property', null, null, $styles, null, 'italic', true],
'i' => ['Property', null, null, $styles, null, 'italic', true],
Expand Down Expand Up @@ -345,21 +345,18 @@ protected static function parseInput($node, $element, &$styles): void
/**
* Parse heading node.
*
* @param AbstractContainer $element
* @param array &$styles
* @param string $argument1 Name of heading style
*
* @return 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
*/
protected static function parseHeading($element, &$styles, $argument1)
protected static function parseHeading(DOMNode $node, AbstractContainer $element, array &$styles, string $argument1): TextRun
{
$styles['paragraph'] = $argument1;
$newElement = $element->addTextRun($styles['paragraph']);
$style = new Paragraph();
$style->setStyleName($argument1);
$style->setStyleByArray(self::parseInlineStyle($node, $styles['paragraph']));

return $newElement;
return $element->addTextRun($style);
}

/**
Expand Down
6 changes: 2 additions & 4 deletions src/PhpWord/Style/Font.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class Font extends AbstractStyle
/**
* Font color.
*
* @var string
* @var null|string
*/
private $color;

Expand Down Expand Up @@ -426,10 +426,8 @@ public function setSize($value = null)

/**
* Get font color.
*
* @return string
*/
public function getColor()
public function getColor(): ?string
{
return $this->color;
}
Expand Down
45 changes: 45 additions & 0 deletions tests/PhpWordTests/Shared/HtmlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@
use PhpOffice\PhpWord\ComplexType\RubyProperties;
use PhpOffice\PhpWord\Element\Section;
use PhpOffice\PhpWord\Element\Table;
use PhpOffice\PhpWord\Element\Text;
use PhpOffice\PhpWord\Element\TextRun;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\Converter;
use PhpOffice\PhpWord\Shared\Html;
use PhpOffice\PhpWord\SimpleType\Jc;
use PhpOffice\PhpWord\SimpleType\LineSpacingRule;
use PhpOffice\PhpWord\SimpleType\TblWidth;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
use PhpOffice\PhpWordTests\AbstractWebServerEmbedded;
use PhpOffice\PhpWordTests\TestHelperDOCX;
Expand Down Expand Up @@ -105,6 +108,48 @@ public function testParseFullHtml(): void
self::assertCount(2, $section->getElements());
}

public function testParseHeader(): void
{
$phpWord = new PhpWord();
$section = $phpWord->addSection();
Html::addHtml($section, '<h1>Text</h1>');

self::assertCount(1, $section->getElements());
$element = $section->getElement(0);
self::assertInstanceOf(TextRun::class, $element);
self::assertInstanceOf(Paragraph::class, $element->getParagraphStyle());
self::assertEquals('Heading1', $element->getParagraphStyle()->getStyleName());
self::assertEquals('', $element->getParagraphStyle()->getAlignment());
self::assertEquals('Text', $element->getText());
self::assertCount(1, $element->getElements());
$subElement = $element->getElement(0);
self::assertInstanceOf(Text::class, $subElement);
self::assertInstanceOf(Font::class, $subElement->getFontStyle());
self::assertNull($subElement->getFontStyle()->getColor());
self::assertEquals('Text', $subElement->getText());
}

public function testParseHeaderStyle(): void
{
$phpWord = new PhpWord();
$section = $phpWord->addSection();
Html::addHtml($section, '<h1 style="color: #ff0000; text-align:center">Text</h1>');

self::assertCount(1, $section->getElements());
$element = $section->getElement(0);
self::assertInstanceOf(TextRun::class, $element);
self::assertInstanceOf(Paragraph::class, $element->getParagraphStyle());
self::assertEquals('Heading1', $element->getParagraphStyle()->getStyleName());
self::assertEquals('center', $element->getParagraphStyle()->getAlignment());
self::assertEquals('Text', $element->getText());
self::assertCount(1, $element->getElements());
$subElement = $element->getElement(0);
self::assertInstanceOf(Text::class, $subElement);
self::assertInstanceOf(Font::class, $subElement->getFontStyle());
self::assertEquals('ff0000', $subElement->getFontStyle()->getColor());
self::assertEquals('Text', $subElement->getText());
}

/**
* Test HTML entities.
*/
Expand Down