Skip to content

Commit b83d5b4

Browse files
committed
Implement noah's ark active format reconstruction
1 parent 24a837c commit b83d5b4

2 files changed

Lines changed: 46 additions & 2 deletions

File tree

src/wp-includes/html-api/class-wp-html-active-formatting-elements.php

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ public function insert_marker(): void {
128128
* @param AFE_Element|AFE_Marker $token Push this node onto the stack.
129129
*/
130130
public function push( AFE_Element|AFE_Marker $afe ): void {
131+
if ( $afe instanceof AFE_Marker ) {
132+
$this->stack[] = $afe;
133+
return;
134+
}
135+
131136
/*
132137
* > If there are already three elements in the list of active formatting elements after the last marker,
133138
* > if any, or anywhere in the list if there are no markers, that have the same tag name, namespace, and
@@ -136,9 +141,19 @@ public function push( AFE_Element|AFE_Marker $afe ): void {
136141
* > created by the parser; two elements have the same attributes if all their parsed attributes can be
137142
* > paired such that the two attributes in each pair have identical names, namespaces, and values
138143
* > (the order of the attributes does not matter).
139-
*
140-
* @todo Implement the "Noah's Ark clause" to only add up to three of any given kind of formatting elements to the stack.
141144
*/
145+
$count = 0;
146+
foreach ( $this->walk_up_until_marker() as $item ) {
147+
if (
148+
$item->namespace === $afe->namespace &&
149+
$item->tag_name === $afe->tag_name &&
150+
$item->attributes === $afe->attributes
151+
) {
152+
if ( ++$count >= 3 ) {
153+
return;
154+
}
155+
}
156+
}
142157
$this->stack[] = $afe;
143158
}
144159

@@ -216,6 +231,31 @@ public function walk_up() {
216231
}
217232
}
218233

234+
/**
235+
* Steps through the stack starting from the last added and stopping at the first marker, if present.
236+
*
237+
* This generator function is designed to be used inside a "foreach" loop.
238+
*
239+
* Example:
240+
*
241+
* $html = '<em><table><td><i>We are here';
242+
* foreach ( $stack->walk_up_until_marker() as $node ) {
243+
* echo "{$node->node_name} -> ";
244+
* }
245+
* > I
246+
*
247+
* @since 6.7.0
248+
*/
249+
public function walk_up_until_marker() {
250+
foreach ( $this->walk_up() as $item ) {
251+
if ( $item instanceof AFE_Marker ) {
252+
break;
253+
}
254+
255+
yield $item;
256+
}
257+
}
258+
219259
/**
220260
* Clears the list of active formatting elements up to the last marker.
221261
*

src/wp-includes/html-api/class-wp-html-processor.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5451,6 +5451,9 @@ private function reconstruct_active_formatting_elements(): bool {
54515451
* > element entry was created, to obtain new element.
54525452
*/
54535453
create:
5454+
if ( array() !== $entry->attributes ) {
5455+
$this->bail( 'Cannot create active formatting elements with attributes.' );
5456+
}
54545457
$this->insert_html_element( $entry->token );
54555458

54565459
/*
@@ -6223,6 +6226,7 @@ private function push_active_formatting_element( WP_HTML_Token $token ) {
62236226
foreach ( $proc->get_attribute_names_with_prefix( '' ) as $name ) {
62246227
$attributes[ $name ] = $proc->get_attribute( $name );
62256228
}
6229+
sort( $attributes );
62266230
$afe = new AFE_Element(
62276231
$token->namespace,
62286232
$token->node_name,

0 commit comments

Comments
 (0)