From 23c69a89f7d9367395585ebd75a0e9a661bad9d2 Mon Sep 17 00:00:00 2001 From: Audrey Penven Date: Wed, 20 Aug 2025 16:58:50 +0200 Subject: [PATCH] Add v-html text content without modification Prior to this commit, if the value for `v-html` did not begin with an HTML element tag, it would be wrapped in a `

` tag before being added to its node. This introduced inconsistency in rendering, for example: - `'plain text'` became `'

plain text

'` - but `'span content'` would remain as-is An additional problem is that if the string began with plain text, but contained an element not allowed in a `

`, that `

` wrapper would be closed early, potentially creating an even more complex structure than expected. for example: - input: `'beginning

internal text
ending'` - output: `'

beginning

internal text
ending'` This wrapping/modification is prevented by wrapping the string in a `` tag before it is given to the HtmlParser. This `` tag is only used as a temporary container. Before, it was added in the parser as an implied tag. Adding it explicitly serves the same function of providing a temporary node to extract childNodes from, without the `

` side effect. Additionally, the tests for `v-html` are collected into one, using dataProvider function to cover the variations Bug: T402295 --- src/Component.php | 5 +- tests/php/TemplatingTest.php | 89 +++++++++++++++++++----------------- 2 files changed, 52 insertions(+), 42 deletions(-) diff --git a/src/Component.php b/src/Component.php index 97fc18d..cfb06a5 100644 --- a/src/Component.php +++ b/src/Component.php @@ -323,7 +323,10 @@ private function handleFor( DOMNode $node, array $data ) { private function appendHTML( DOMNode $parent, $source ) { $htmlParser = new HtmlParser(); - $tmpDoc = $htmlParser->parseHtml( $source ); + + // Wrapping $source in a tag prevents the addition of an implied

tag when the + // $source starts with plain text + $tmpDoc = $htmlParser->parseHtml( '' . $source . '' ); foreach ( $htmlParser->getBodyElement( $tmpDoc )->childNodes as $node ) { $node = $parent->ownerDocument->importNode( $node, true ); $parent->appendChild( $node ); diff --git a/tests/php/TemplatingTest.php b/tests/php/TemplatingTest.php index 21c04ea..1ea1a97 100644 --- a/tests/php/TemplatingTest.php +++ b/tests/php/TemplatingTest.php @@ -93,49 +93,56 @@ public function testTemplateWithVariableAndValueInKorean_ReplacesVariableWithEnc $this->assertSame( '

한국어

', $result ); } - public function testTemplateWithVhtmlVariable_ReplacesVariableWithGivenValue() { - $result = $this->createAndRender( - '
', - [ 'value' => '

some value

' ] - ); - - $this->assertSame( '

some value

', $result ); - } - - public function testTemplateWithVhtmlVariableNestedData_ReplacesVariableWithGivenValue() { - $result = $this->createAndRender( - '
', - [ 'value' => [ 'html' => '

some value

' ] ] - ); - - $this->assertSame( '

some value

', $result ); - } - - public function testTemplateWithVhtmlVariableAndAttributeBinding_ReplacesBoth(): void { - $result = $this->createAndRender( - '
', - [ 'a' => 'A', 'html' => '

HTML

' ] - ); - - $this->assertSame( '

HTML

', $result ); - } - - public function testTemplateWithVhtmlAndDiacritcsInValue_ReplacesVariableWithEncodedValue() { - $result = $this->createAndRender( - '
', - [ 'value' => '

inglés

' ] - ); - - $this->assertSame( '

inglés

', $result ); + public static function provideVHtmlValues(): iterable { + return [ + 'plain text does not get wrapped' => [ + '
', + [ 'value' => 'plain text' ], + '
plain text
', + ], + 'starting with plain text, containing html tag' => [ + '
', + [ 'value' => 'beginning text
internal div
ending text' ], + '
beginning text
internal div
ending text
', + ], + 'variable in child node is replaced' => [ + '
', + [ 'value' => '

some value

' ], + '

some value

', + ], + 'variable with nested value' => [ + '
', + [ 'value' => [ 'html' => '

some value

' ] ], + '

some value

' + ], + 'template with v-html and attribute binding' => [ + '
', + [ 'a' => 'A', 'html' => '

HTML

' ], + '

HTML

' + ], + 'with diacritics in the value' => [ + '
', + [ 'value' => '

inglés

' ], + '

inglés

' + ], + 'with value in Korean' => [ + '
', + [ 'value' => '

한국어

' ], + '

한국어

' + ] + ]; } - public function testTemplateWithVhtmlAndValueInKorean_ReplacesVariableWithEncodedValue() { - $result = $this->createAndRender( - '
', - [ 'value' => '

한국어

' ] - ); - - $this->assertSame( '

한국어

', $result ); + /** + * @dataProvider provideVHtmlValues + */ + public function testTemplateWithVHtmlVariable( + string $template, + array $data, + string $expected + ) { + $result = $this->createAndRender( $template, $data ); + $this->assertSame( $expected, $result ); } public function testTemplateWithMustacheVariable_VariableIsUndefined_ThrowsException() {