From 6ee4b368a55001bec4515f73a785564419a79e47 Mon Sep 17 00:00:00 2001 From: "Jerome B." Date: Fri, 30 Jan 2026 09:17:58 +0100 Subject: [PATCH] Fixed: get_attribute_names_with_prefix() now agrees with enqueued attribute updates --- .../html-api/class-wp-html-tag-processor.php | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) 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 69e3e5d2c7557..c5e16ef78cdcc 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 @@ -2843,15 +2843,44 @@ public function get_attribute_names_with_prefix( $prefix ): ?array { return null; } + /* + * For the `class` attribute, ensure that enqueued class changes from + * `add_class` and `remove_class` are flushed into attribute updates. + */ + $this->class_name_updates_to_attributes_updates(); + $comparable = strtolower( $prefix ); - $matches = array(); + // Use associative array to efficiently track unique attribute names + $result = array(); + + // First, collect attributes from the parsed HTML. foreach ( array_keys( $this->attributes ) as $attr_name ) { if ( str_starts_with( $attr_name, $comparable ) ) { - $matches[] = $attr_name; + $result[ $attr_name ] = true; } } - return $matches; + + // Then, apply any enqueued attribute updates. + foreach ( $this->lexical_updates as $name => $update ) { + // Skip numeric keys (used for other types of updates). + if ( is_int( $name ) ) { + continue; + } + + // Process only if the name matches the prefix. + if ( str_starts_with( $name, $comparable ) ) { + // If the update text is empty, the attribute is being removed. + if ( '' === $update->text ) { + unset( $result[ $name ] ); + } else { + // Attribute is being added or modified. + $result[ $name ] = true; + } + } + } + + return array_keys( $result ); } /**