Skip to content

Commit e53e44d

Browse files
authored
Allow Users to Support Additional Tags in Helper/Html (#3752)
* Allow Users to Support Additional Tags in Helper/Html Fix #3751. User wants to add bullets for list items, and possibly handle table rows and other currently unsupported tags where one size might not fit all. * Update CHANGELOG.md
1 parent a713e15 commit e53e44d

File tree

3 files changed

+71
-39
lines changed

3 files changed

+71
-39
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org).
2121
- ListWorksheetInfo/Names for Html/Csv/Slk. [Issue #3706](https://github.com/PHPOffice/PhpSpreadsheet/issues/3706) [PR #3709](https://github.com/PHPOffice/PhpSpreadsheet/pull/3709)
2222
- Methods to determine if cell is actually locked, or hidden on formula bar. [PR #3722](https://github.com/PHPOffice/PhpSpreadsheet/pull/3722)
2323
- Add iterateOnlyExistingCells to Constructors. [Issue #3721](https://github.com/PHPOffice/PhpSpreadsheet/issues/3721) [PR #3727](https://github.com/PHPOffice/PhpSpreadsheet/pull/3727)
24+
- Support for Conditional Formatting Color Scale. [PR #3738](https://github.com/PHPOffice/PhpSpreadsheet/pull/3738)
25+
- Support Additional Tags in Helper/Html. [Issue #3751](https://github.com/PHPOffice/PhpSpreadsheet/issues/3751) [PR #3752](https://github.com/PHPOffice/PhpSpreadsheet/pull/3752)
2426
- Writer ODS : Write Border Style for cells [Issue #3690](https://github.com/PHPOffice/PhpSpreadsheet/issues/3690) [PR #3693](https://github.com/PHPOffice/PhpSpreadsheet/pull/3693)
2527

2628
### Changed
@@ -63,6 +65,8 @@ and this project adheres to [Semantic Versioning](https://semver.org).
6365
- Inconsistency Between Cell Data and Explicitly Declared Type. [Issue #3711](https://github.com/PHPOffice/PhpSpreadsheet/issues/3711) [PR #3715](https://github.com/PHPOffice/PhpSpreadsheet/pull/3715)
6466
- Unexpected Namespacing in rels File. [Issue #3720](https://github.com/PHPOffice/PhpSpreadsheet/issues/3720) [PR #3722](https://github.com/PHPOffice/PhpSpreadsheet/pull/3722)
6567
- Break Some Circular References. [PR #3716](https://github.com/PHPOffice/PhpSpreadsheet/pull/3716) [PR #3707](https://github.com/PHPOffice/PhpSpreadsheet/pull/3707)
68+
- Missing Font Index in Some Xls. [PR #3734](https://github.com/PHPOffice/PhpSpreadsheet/pull/3734)
69+
- Load Tables even with READ_DATA_ONLY. [PR #3726](https://github.com/PHPOffice/PhpSpreadsheet/pull/3726)
6670

6771
## 1.29.0 - 2023-06-15
6872

src/PhpSpreadsheet/Helper/Html.php

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -559,45 +559,46 @@ class Html
559559
/** @var bool */
560560
private $strikethrough = false;
561561

562-
private const START_TAG_CALLBACKS = [
563-
'font' => 'startFontTag',
564-
'b' => 'startBoldTag',
565-
'strong' => 'startBoldTag',
566-
'i' => 'startItalicTag',
567-
'em' => 'startItalicTag',
568-
'u' => 'startUnderlineTag',
569-
'ins' => 'startUnderlineTag',
570-
'del' => 'startStrikethruTag',
571-
'sup' => 'startSuperscriptTag',
572-
'sub' => 'startSubscriptTag',
562+
/** @var callable[] */
563+
private $startTagCallbacks = [
564+
'font' => [self::class, 'startFontTag'],
565+
'b' => [self::class, 'startBoldTag'],
566+
'strong' => [self::class, 'startBoldTag'],
567+
'i' => [self::class, 'startItalicTag'],
568+
'em' => [self::class, 'startItalicTag'],
569+
'u' => [self::class, 'startUnderlineTag'],
570+
'ins' => [self::class, 'startUnderlineTag'],
571+
'del' => [self::class, 'startStrikethruTag'],
572+
'sup' => [self::class, 'startSuperscriptTag'],
573+
'sub' => [self::class, 'startSubscriptTag'],
573574
];
574575

575-
private const END_TAG_CALLBACKS = [
576-
'font' => 'endFontTag',
577-
'b' => 'endBoldTag',
578-
'strong' => 'endBoldTag',
579-
'i' => 'endItalicTag',
580-
'em' => 'endItalicTag',
581-
'u' => 'endUnderlineTag',
582-
'ins' => 'endUnderlineTag',
583-
'del' => 'endStrikethruTag',
584-
'sup' => 'endSuperscriptTag',
585-
'sub' => 'endSubscriptTag',
586-
'br' => 'breakTag',
587-
'p' => 'breakTag',
588-
'h1' => 'breakTag',
589-
'h2' => 'breakTag',
590-
'h3' => 'breakTag',
591-
'h4' => 'breakTag',
592-
'h5' => 'breakTag',
593-
'h6' => 'breakTag',
576+
/** @var callable[] */
577+
private $endTagCallbacks = [
578+
'font' => [self::class, 'endFontTag'],
579+
'b' => [self::class, 'endBoldTag'],
580+
'strong' => [self::class, 'endBoldTag'],
581+
'i' => [self::class, 'endItalicTag'],
582+
'em' => [self::class, 'endItalicTag'],
583+
'u' => [self::class, 'endUnderlineTag'],
584+
'ins' => [self::class, 'endUnderlineTag'],
585+
'del' => [self::class, 'endStrikethruTag'],
586+
'sup' => [self::class, 'endSuperscriptTag'],
587+
'sub' => [self::class, 'endSubscriptTag'],
588+
'br' => [self::class, 'breakTag'],
589+
'p' => [self::class, 'breakTag'],
590+
'h1' => [self::class, 'breakTag'],
591+
'h2' => [self::class, 'breakTag'],
592+
'h3' => [self::class, 'breakTag'],
593+
'h4' => [self::class, 'breakTag'],
594+
'h5' => [self::class, 'breakTag'],
595+
'h6' => [self::class, 'breakTag'],
594596
];
595597

596598
/** @var array */
597599
private $stack = [];
598600

599-
/** @var string */
600-
private $stringData = '';
601+
public string $stringData = '';
601602

602603
/**
603604
* @var RichText
@@ -799,7 +800,7 @@ protected function endStrikethruTag(): void
799800
$this->strikethrough = false;
800801
}
801802

802-
protected function breakTag(): void
803+
public function breakTag(): void
803804
{
804805
$this->stringData .= "\n";
805806
}
@@ -815,14 +816,23 @@ private function parseTextNode(DOMText $textNode): void
815816
$this->buildTextRun();
816817
}
817818

819+
public function addStartTagCallback(string $tag, callable $callback): void
820+
{
821+
$this->startTagCallbacks[$tag] = $callback;
822+
}
823+
824+
public function addEndTagCallback(string $tag, callable $callback): void
825+
{
826+
$this->endTagCallbacks[$tag] = $callback;
827+
}
828+
829+
/** @param callable[] $callbacks */
818830
private function handleCallback(DOMElement $element, string $callbackTag, array $callbacks): void
819831
{
820832
if (isset($callbacks[$callbackTag])) {
821833
$elementHandler = $callbacks[$callbackTag];
822-
if (method_exists($this, $elementHandler)) {
823-
/** @var callable */
824-
$callable = [$this, $elementHandler];
825-
call_user_func($callable, $element);
834+
if (is_callable($elementHandler)) {
835+
call_user_func($elementHandler, $element, $this);
826836
}
827837
}
828838
}
@@ -832,12 +842,12 @@ private function parseElementNode(DOMElement $element): void
832842
$callbackTag = strtolower($element->nodeName);
833843
$this->stack[] = $callbackTag;
834844

835-
$this->handleCallback($element, $callbackTag, self::START_TAG_CALLBACKS);
845+
$this->handleCallback($element, $callbackTag, $this->startTagCallbacks);
836846

837847
$this->parseElements($element);
838848
array_pop($this->stack);
839849

840-
$this->handleCallback($element, $callbackTag, self::END_TAG_CALLBACKS);
850+
$this->handleCallback($element, $callbackTag, $this->endTagCallbacks);
841851
}
842852

843853
private function parseElements(DOMNode $element): void

tests/PhpSpreadsheetTests/Helper/HtmlTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpOffice\PhpSpreadsheetTests\Helper;
66

7+
use DOMElement;
78
use PhpOffice\PhpSpreadsheet\Helper\Html;
89
use PHPUnit\Framework\TestCase;
910

@@ -28,6 +29,23 @@ public static function providerUtf8EncodingSupport(): array
2829
['русский', 'русский'],
2930
["foo\nbar", '<p>foo</p><p>bar</p>'],
3031
'issue2810' => ['0', '0'],
32+
["Hello\nItem 1Item 2Goodbye", 'Hello<ul><li>Item 1</li><li>Item 2</li></ul>Goodbye'],
3133
];
3234
}
35+
36+
public function testLiTag(): void
37+
{
38+
$html = new Html();
39+
/** @var callable */
40+
$htmlBreakTag = [Html::class, 'breakTag'];
41+
$html->addStartTagCallback('li', function (DOMElement $tag, Html $object): void {
42+
$object->stringData .= "\u{00A0}\u{2022} \u{00A0}";
43+
});
44+
$html->addEndTagCallback('li', $htmlBreakTag);
45+
$input = 'Hello<ul><li>Item 1</li><li>Item 2</li></ul>Goodbye';
46+
$expected = "Hello\n\u{00A0}\u{2022} \u{00A0}Item 1\n\u{00A0}\u{2022} \u{00A0}Item 2\nGoodbye";
47+
$actual = $html->toRichTextObject($input);
48+
49+
self::assertSame($expected, $actual->getPlainText());
50+
}
3351
}

0 commit comments

Comments
 (0)