diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php index 3820fe0277..415ff23eea 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -786,13 +786,15 @@ class WP_HTML_Processor extends WP_HTML_Tag_Processor { * or `null` if not matched on any token. */ public function expects_closer( WP_HTML_Token $node = null ): ?bool { - $token_name = $node->node_name ?? $this->get_token_name(); - $token_namespace = $node->namespace ?? $this->get_namespace(); + $token_name = $node->node_name ?? $this->get_token_name(); if ( ! isset( $token_name ) ) { return null; } + $token_namespace = $node->namespace ?? $this->get_namespace(); + $token_has_self_closing = $node->has_self_closing_flag ?? $this->has_self_closing_flag(); + return ! ( // Comments, text nodes, and other atomic tokens. '#' === $token_name[0] || @@ -803,7 +805,7 @@ class WP_HTML_Processor extends WP_HTML_Tag_Processor { // Special atomic elements. ( 'html' === $token_namespace && in_array( $token_name, array( 'IFRAME', 'NOEMBED', 'NOFRAMES', 'SCRIPT', 'STYLE', 'TEXTAREA', 'TITLE', 'XMP' ), true ) ) || // Self-closing elements in foreign content. - ( isset( $node ) && 'html' !== $node->namespace && $node->has_self_closing_flag ) + ( 'html' !== $token_namespace && $token_has_self_closing ) ); } diff --git a/src/wp-includes/html-api/class-wp-html-tag-processor.php b/src/wp-includes/html-api/class-wp-html-tag-processor.php index fb21c15d1d..95216b08a1 100644 --- a/src/wp-includes/html-api/class-wp-html-tag-processor.php +++ b/src/wp-includes/html-api/class-wp-html-tag-processor.php @@ -2921,7 +2921,7 @@ class WP_HTML_Tag_Processor { return null; } - $namespace = $this->get_namespace(); + $namespace = $this->get_namespace(); $lower_name = strtolower( $attribute_name ); if ( 'math' === $namespace && 'definitionurl' === $lower_name ) { diff --git a/tests/phpunit/tests/html-api/wpHtmlProcessor.php b/tests/phpunit/tests/html-api/wpHtmlProcessor.php index 68c60a1ff8..2b56cefedc 100644 --- a/tests/phpunit/tests/html-api/wpHtmlProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlProcessor.php @@ -503,4 +503,22 @@ class Tests_HtmlApi_WpHtmlProcessor extends WP_UnitTestCase { $subclass_processor = call_user_func( array( get_class( $subclass_instance ), 'create_fragment' ), '' ); $this->assertInstanceOf( get_class( $subclass_instance ), $subclass_processor, '::create_fragment did not return subclass instance.' ); } + + /** + * Ensures that self-closing elements in foreign content properly report + * that they expect no closer. + * + * @ticket 61576 + */ + public function test_expects_closer_foreign_content_self_closing() { + $processor = WP_HTML_Processor::create_fragment( '' ); + + $this->assertTrue( $processor->next_tag() ); + $this->assertSame( 'SVG', $processor->get_tag() ); + $this->assertFalse( $processor->expects_closer() ); + + $this->assertTrue( $processor->next_tag() ); + $this->assertSame( 'MATH', $processor->get_tag() ); + $this->assertTrue( $processor->expects_closer() ); + } } diff --git a/tests/phpunit/tests/html-api/wpHtmlProcessorHtml5lib.php b/tests/phpunit/tests/html-api/wpHtmlProcessorHtml5lib.php index b6213aac8d..4de4ebd1cd 100644 --- a/tests/phpunit/tests/html-api/wpHtmlProcessorHtml5lib.php +++ b/tests/phpunit/tests/html-api/wpHtmlProcessorHtml5lib.php @@ -207,11 +207,7 @@ class Tests_HtmlApi_Html5lib extends WP_UnitTestCase { $tag_indent = $indent_level; - if ( 'html' !== $namespace ) { - if ( ! $processor->has_self_closing_flag() ) { - ++$indent_level; - } - } elseif ( ! WP_HTML_Processor::is_void( $tag_name ) ) { + if ( $processor->expects_closer() ) { ++$indent_level; } @@ -275,7 +271,7 @@ class Tests_HtmlApi_Html5lib extends WP_UnitTestCase { // Self-contained tags contain their inner contents as modifiable text. $modifiable_text = $processor->get_modifiable_text(); if ( '' !== $modifiable_text ) { - $output .= str_repeat( $indent, $indent_level ) . "\"{$modifiable_text}\"\n"; + $output .= str_repeat( $indent, $tag_indent + 1 ) . "\"{$modifiable_text}\"\n"; } if ( 'html' === $namespace && 'TEMPLATE' === $token_name ) { @@ -283,10 +279,6 @@ class Tests_HtmlApi_Html5lib extends WP_UnitTestCase { ++$indent_level; } - if ( ! $processor->is_void( $tag_name ) && ! $processor->expects_closer() ) { - --$indent_level; - } - break; case '#cdata-section':