From e095c6206c3a32279016e35c8f909eb270ce3fd7 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 4 Jul 2024 20:36:01 +0200 Subject: [PATCH 1/3] Add current_node_is method --- .../html-api/class-wp-html-open-elements.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/wp-includes/html-api/class-wp-html-open-elements.php b/src/wp-includes/html-api/class-wp-html-open-elements.php index 15479801dda10..9ba5a0cf4aa70 100644 --- a/src/wp-includes/html-api/class-wp-html-open-elements.php +++ b/src/wp-includes/html-api/class-wp-html-open-elements.php @@ -144,6 +144,28 @@ public function current_node() { return $current_node ? $current_node : null; } + /** + * Checks if the node at the top of the stack matches provided node name. + * + * @example + * // Is the current node a text node: + * $stack->current_node_is( '#text' ); + * + * // Is the current node a DIV element: + * $stack->current_node_is( 'DIV' ); + * + * @since 6.7.0 + * + * @param string $node_name The node name to match. Provide a tag name for tags or a + * token name for other types of tokens. + * @return bool True if there are nodes on the stack and the top node has + * a matching node_name. + */ + public function current_node_is( string $node_name ): bool { + $current_node = end( $this->stack ); + return $current_node && $current_node->node_name === $node_name; + } + /** * Returns whether an element is in a specific scope. * From 20e0ed902aee1f8d8b51014ad6c27c174dbe210f Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Thu, 4 Jul 2024 15:47:43 -0700 Subject: [PATCH 2/3] Update docblock, add support for mmatching based on node type. --- .../html-api/class-wp-html-open-elements.php | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/wp-includes/html-api/class-wp-html-open-elements.php b/src/wp-includes/html-api/class-wp-html-open-elements.php index 9ba5a0cf4aa70..b1ca2a5dfa918 100644 --- a/src/wp-includes/html-api/class-wp-html-open-elements.php +++ b/src/wp-includes/html-api/class-wp-html-open-elements.php @@ -145,25 +145,45 @@ public function current_node() { } /** - * Checks if the node at the top of the stack matches provided node name. + * Indicates if the current node is of a given type or name. * - * @example - * // Is the current node a text node: - * $stack->current_node_is( '#text' ); + * It's possible to pass either a node type or a node name to this function. + * In the case there is no current element it will always return `false`. * - * // Is the current node a DIV element: - * $stack->current_node_is( 'DIV' ); + * Example: + * + * // Is the current node a text node? + * $stack->current_node_is( '#text' ); + * + * // Is the current node a DIV element? + * $stack->current_node_is( 'DIV' ); + * + * // Is the current node any element/tag? + * $stack->current_node_is( '#tag' ); + * + * @see WP_HTML_Tag_Processor::get_token_type + * @see WP_HTML_Tag_Processor::get_token_name * * @since 6.7.0 * - * @param string $node_name The node name to match. Provide a tag name for tags or a - * token name for other types of tokens. - * @return bool True if there are nodes on the stack and the top node has - * a matching node_name. + * @access private + * + * @param string $identity Check if the current node has this name or type (depending on what is provided). + * @return bool Whether there is a current element that matches the given identity, whether a token name or type. */ - public function current_node_is( string $node_name ): bool { + public function current_node_is( string $identity ): bool { $current_node = end( $this->stack ); - return $current_node && $current_node->node_name === $node_name; + if ( false === $current_node ) { + return false; + } + + $current_node_name = $current_node->node_name; + + return ( + $current_node_name === $identity || + ( '#doctype' === $identity && 'html' === $current_node_name ) || + ( '#tag' === $identity && ctype_upper( $current_node_name ) ) + ); } /** From 5403e6bb56f9cba2fc025f86551f7d8f2e82ca7c Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Thu, 4 Jul 2024 15:56:27 -0700 Subject: [PATCH 3/3] Rely on `current_node_is()` in HTML Processor --- src/wp-includes/html-api/class-wp-html-processor.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 32800218f6404..f187ef7fd1b66 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -1029,7 +1029,7 @@ private function step_in_body() { } $this->generate_implied_end_tags(); - if ( $this->state->stack_of_open_elements->current_node()->node_name !== $token_name ) { + if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) { // @todo Record parse error: this error doesn't impact parsing. } $this->state->stack_of_open_elements->pop_until( $token_name ); @@ -1094,7 +1094,7 @@ private function step_in_body() { $this->generate_implied_end_tags(); - if ( $this->state->stack_of_open_elements->current_node()->node_name !== $token_name ) { + if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) { // @todo Record parse error: this error doesn't impact parsing. } @@ -1120,7 +1120,7 @@ private function step_in_body() { if ( $is_li ? 'LI' === $node->node_name : ( 'DD' === $node->node_name || 'DT' === $node->node_name ) ) { $node_name = $is_li ? 'LI' : $node->node_name; $this->generate_implied_end_tags( $node_name ); - if ( $node_name !== $this->state->stack_of_open_elements->current_node()->node_name ) { + if ( ! $this->state->stack_of_open_elements->current_node_is( $node_name ) ) { // @todo Indicate a parse error once it's possible. This error does not impact the logic here. } @@ -1197,7 +1197,7 @@ private function step_in_body() { $this->generate_implied_end_tags( $token_name ); - if ( $token_name !== $this->state->stack_of_open_elements->current_node()->node_name ) { + if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) { // @todo Indicate a parse error once it's possible. This error does not impact the logic here. }