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 168b8ace4c394..302b524e96902 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -800,7 +800,7 @@ public function expects_closer( WP_HTML_Token $node = null ): ?bool { // Void elements. self::is_void( $token_name ) || // Special atomic elements. - ( 'html' === $token_namespace && in_array( $token_name, array( 'IFRAME', 'NOEMBED', 'NOFRAMES', 'SCRIPT', 'STYLE', 'TEXTAREA', 'TITLE', 'XMP' ), true ) ) || + parent::is_self_contained_tag() || // Self-closing elements in foreign content. ( '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 72307cb3920b6..6be123fdc3774 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 @@ -3179,6 +3179,31 @@ public function has_self_closing_flag(): bool { return '/' === $this->html[ $this->token_starts_at + $this->token_length - 2 ]; } + /** + * Indicates if the currently-matched token is a self-contained element, + * i.e. a SCRIPT, STYLE, TEXTAREA, or TITLE element etc… + * + * When the HTML API finds one of these elements it will consume the entire + * content up to and including the closing tag. They act like void tags, even + * though they expect closing tags in input HTML. They are treated this way + * because they cannot contain other HTML tags inside of them; their input is + * always text content only, with or without replacement of character + * references depending on which element it is. + * + * To get the contents of these elements, call {@see static::get_modifiable_text}. + * + * @since 6.7.0 + * + * @return bool Whether the currently-matched token is a self-contained element. + */ + public function is_self_contained_tag(): bool { + return ( + self::STATE_MATCHED_TAG === $this->parser_state && + 'html' === $this->get_namespace() && + in_array( $this->get_tag(), array( 'IFRAME', 'NOEMBED', 'NOFRAMES', 'SCRIPT', 'STYLE', 'TEXTAREA', 'TITLE', 'XMP' ), true ) + ); + } + /** * Indicates if the current tag token is a tag closer. *