@@ -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 *
0 commit comments