Changeset 58806
- Timestamp:
- 07/24/2024 06:39:46 PM (10 months ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/html-api/class-wp-html-open-elements.php
r58779 r58806 722 722 723 723 /** 724 * Clear the stack back to a table context. 725 * 726 * > When the steps above require the UA to clear the stack back to a table context, it means 727 * > that the UA must, while the current node is not a table, template, or html element, pop 728 * > elements from the stack of open elements. 729 * 730 * @see https://html.spec.whatwg.org/multipage/parsing.html#clear-the-stack-back-to-a-table-context 731 * 732 * @since 6.7.0 733 */ 734 public function clear_to_table_context(): void { 735 foreach ( $this->walk_up() as $item ) { 736 if ( 737 'TABLE' === $item->node_name || 738 'TEMPLATE' === $item->node_name || 739 'HTML' === $item->node_name 740 ) { 741 break; 742 } 743 $this->pop(); 744 } 745 } 746 747 /** 748 * Clear the stack back to a table body context. 749 * 750 * > When the steps above require the UA to clear the stack back to a table body context, it 751 * > means that the UA must, while the current node is not a tbody, tfoot, thead, template, or 752 * > html element, pop elements from the stack of open elements. 753 * 754 * @see https://html.spec.whatwg.org/multipage/parsing.html#clear-the-stack-back-to-a-table-body-context 755 * 756 * @since 6.7.0 757 */ 758 public function clear_to_table_body_context(): void { 759 foreach ( $this->walk_up() as $item ) { 760 if ( 761 'TBODY' === $item->node_name || 762 'TFOOT' === $item->node_name || 763 'THEAD' === $item->node_name || 764 'TEMPLATE' === $item->node_name || 765 'HTML' === $item->node_name 766 ) { 767 break; 768 } 769 $this->pop(); 770 } 771 } 772 773 /** 774 * Clear the stack back to a table row context. 775 * 776 * > When the steps above require the UA to clear the stack back to a table row context, it 777 * > means that the UA must, while the current node is not a tr, template, or html element, pop 778 * > elements from the stack of open elements. 779 * 780 * @see https://html.spec.whatwg.org/multipage/parsing.html#clear-the-stack-back-to-a-table-row-context 781 * 782 * @since 6.7.0 783 */ 784 public function clear_to_table_row_context(): void { 785 foreach ( $this->walk_up() as $item ) { 786 if ( 787 'TR' === $item->node_name || 788 'TEMPLATE' === $item->node_name || 789 'HTML' === $item->node_name 790 ) { 791 break; 792 } 793 $this->pop(); 794 } 795 } 796 797 /** 724 798 * Wakeup magic method. 725 799 * -
trunk/src/wp-includes/html-api/class-wp-html-processor.php
r58781 r58806 1787 1787 */ 1788 1788 case '+TABLE': 1789 /* 1790 * > If the Document is not set to quirks mode, and the stack of open elements 1791 * > has a p element in button scope, then close a p element. 1792 */ 1789 1793 if ( 1790 1794 WP_HTML_Processor_State::QUIRKS_MODE !== $this->state->document_mode && … … 2118 2122 * logic for the generalized WP_HTML_Processor::step() function. 2119 2123 * 2120 * @since 6.7.0 Stub implementation.2124 * @since 6.7.0 2121 2125 * 2122 2126 * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. … … 2128 2132 */ 2129 2133 private function step_in_table(): bool { 2130 $this->bail( 'No support for parsing in the ' . WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE . ' state.' ); 2134 $token_name = $this->get_token_name(); 2135 $token_type = $this->get_token_type(); 2136 $op_sigil = '#tag' === $token_type ? ( parent::is_tag_closer() ? '-' : '+' ) : ''; 2137 $op = "{$op_sigil}{$token_name}"; 2138 2139 switch ( $op ) { 2140 /* 2141 * > A character token, if the current node is table, 2142 * > tbody, template, tfoot, thead, or tr element 2143 */ 2144 case '#text': 2145 $current_node = $this->state->stack_of_open_elements->current_node(); 2146 $current_node_name = $current_node ? $current_node->node_name : null; 2147 if ( 2148 $current_node_name && ( 2149 'TABLE' === $current_node_name || 2150 'TBODY' === $current_node_name || 2151 'TEMPLATE' === $current_node_name || 2152 'TFOOT' === $current_node_name || 2153 'THEAD' === $current_node_name || 2154 'TR' === $current_node_name 2155 ) 2156 ) { 2157 $text = $this->get_modifiable_text(); 2158 /* 2159 * If the text is empty after processing HTML entities and stripping 2160 * U+0000 NULL bytes then ignore the token. 2161 */ 2162 if ( '' === $text ) { 2163 return $this->step(); 2164 } 2165 2166 /* 2167 * This follows the rules for "in table text" insertion mode. 2168 * 2169 * Whitespace-only text nodes are inserted in-place. Otherwise 2170 * foster parenting is enabled and the nodes would be 2171 * inserted out-of-place. 2172 * 2173 * > If any of the tokens in the pending table character tokens 2174 * > list are character tokens that are not ASCII whitespace, 2175 * > then this is a parse error: reprocess the character tokens 2176 * > in the pending table character tokens list using the rules 2177 * > given in the "anything else" entry in the "in table" 2178 * > insertion mode. 2179 * > 2180 * > Otherwise, insert the characters given by the pending table 2181 * > character tokens list. 2182 * 2183 * @see https://html.spec.whatwg.org/#parsing-main-intabletext 2184 */ 2185 if ( strlen( $text ) === strspn( $text, " \t\f\r\n" ) ) { 2186 $this->insert_html_element( $this->state->current_token ); 2187 return true; 2188 } 2189 2190 // Non-whitespace would trigger fostering, unsupported at this time. 2191 $this->bail( 'Foster parenting is not supported.' ); 2192 break; 2193 } 2194 break; 2195 2196 /* 2197 * > A comment token 2198 */ 2199 case '#comment': 2200 case '#funky-comment': 2201 case '#presumptuous-tag': 2202 $this->insert_html_element( $this->state->current_token ); 2203 return true; 2204 2205 /* 2206 * > A DOCTYPE token 2207 */ 2208 case 'html': 2209 // Parse error: ignore the token. 2210 return $this->step(); 2211 2212 /* 2213 * > A start tag whose tag name is "caption" 2214 */ 2215 case '+CAPTION': 2216 $this->state->stack_of_open_elements->clear_to_table_context(); 2217 $this->state->active_formatting_elements->insert_marker(); 2218 $this->insert_html_element( $this->state->current_token ); 2219 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_CAPTION; 2220 return true; 2221 2222 /* 2223 * > A start tag whose tag name is "colgroup" 2224 */ 2225 case '+COLGROUP': 2226 $this->state->stack_of_open_elements->clear_to_table_context(); 2227 $this->insert_html_element( $this->state->current_token ); 2228 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_COLUMN_GROUP; 2229 return true; 2230 2231 /* 2232 * > A start tag whose tag name is "col" 2233 */ 2234 case '+COL': 2235 $this->state->stack_of_open_elements->clear_to_table_context(); 2236 2237 /* 2238 * > Insert an HTML element for a "colgroup" start tag token with no attributes, 2239 * > then switch the insertion mode to "in column group". 2240 */ 2241 $this->insert_virtual_node( 'COLGROUP' ); 2242 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_COLUMN_GROUP; 2243 return $this->step( self::REPROCESS_CURRENT_NODE ); 2244 2245 /* 2246 * > A start tag whose tag name is one of: "tbody", "tfoot", "thead" 2247 */ 2248 case '+TBODY': 2249 case '+TFOOT': 2250 case '+THEAD': 2251 $this->state->stack_of_open_elements->clear_to_table_context(); 2252 $this->insert_html_element( $this->state->current_token ); 2253 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE_BODY; 2254 return true; 2255 2256 /* 2257 * > A start tag whose tag name is one of: "td", "th", "tr" 2258 */ 2259 case '+TD': 2260 case '+TH': 2261 case '+TR': 2262 $this->state->stack_of_open_elements->clear_to_table_context(); 2263 /* 2264 * > Insert an HTML element for a "tbody" start tag token with no attributes, 2265 * > then switch the insertion mode to "in table body". 2266 */ 2267 $this->insert_virtual_node( 'TBODY' ); 2268 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE_BODY; 2269 return $this->step( self::REPROCESS_CURRENT_NODE ); 2270 2271 /* 2272 * > A start tag whose tag name is "table" 2273 * 2274 * This tag in the IN TABLE insertion mode is a parse error. 2275 */ 2276 case '+TABLE': 2277 if ( ! $this->state->stack_of_open_elements->has_element_in_table_scope( 'TABLE' ) ) { 2278 return $this->step(); 2279 } 2280 2281 $this->state->stack_of_open_elements->pop_until( 'TABLE' ); 2282 $this->reset_insertion_mode(); 2283 return $this->step( self::REPROCESS_CURRENT_NODE ); 2284 2285 /* 2286 * > An end tag whose tag name is "table" 2287 */ 2288 case '-TABLE': 2289 if ( ! $this->state->stack_of_open_elements->has_element_in_table_scope( 'TABLE' ) ) { 2290 // @todo Indicate a parse error once it's possible. 2291 return $this->step(); 2292 } 2293 2294 $this->state->stack_of_open_elements->pop_until( 'TABLE' ); 2295 $this->reset_insertion_mode(); 2296 return true; 2297 2298 /* 2299 * > An end tag whose tag name is one of: "body", "caption", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr" 2300 */ 2301 case '-BODY': 2302 case '-CAPTION': 2303 case '-COL': 2304 case '-COLGROUP': 2305 case '-HTML': 2306 case '-TBODY': 2307 case '-TD': 2308 case '-TFOOT': 2309 case '-TH': 2310 case '-THEAD': 2311 case '-TR': 2312 // Parse error: ignore the token. 2313 return $this->step(); 2314 2315 /* 2316 * > A start tag whose tag name is one of: "style", "script", "template" 2317 * > An end tag whose tag name is "template" 2318 */ 2319 case '+STYLE': 2320 case '+SCRIPT': 2321 case '+TEMPLATE': 2322 case '-TEMPLATE': 2323 /* 2324 * > Process the token using the rules for the "in head" insertion mode. 2325 */ 2326 return $this->step_in_head(); 2327 2328 /* 2329 * > A start tag whose tag name is "input" 2330 * 2331 * > If the token does not have an attribute with the name "type", or if it does, but 2332 * > that attribute's value is not an ASCII case-insensitive match for the string 2333 * > "hidden", then: act as described in the "anything else" entry below. 2334 */ 2335 case '+INPUT': 2336 $type_attribute = $this->get_attribute( 'type' ); 2337 if ( ! is_string( $type_attribute ) || 'hidden' !== strtolower( $type_attribute ) ) { 2338 goto anything_else; 2339 } 2340 // @todo Indicate a parse error once it's possible. 2341 $this->insert_html_element( $this->state->current_token ); 2342 return true; 2343 2344 /* 2345 * > A start tag whose tag name is "form" 2346 * 2347 * This tag in the IN TABLE insertion mode is a parse error. 2348 */ 2349 case '+FORM': 2350 if ( 2351 $this->state->stack_of_open_elements->has_element_in_scope( 'TEMPLATE' ) || 2352 isset( $this->state->form_element ) 2353 ) { 2354 return $this->step(); 2355 } 2356 2357 // This FORM is special because it immediately closes and cannot have other children. 2358 $this->insert_html_element( $this->state->current_token ); 2359 $this->state->form_element = $this->state->current_token; 2360 $this->state->stack_of_open_elements->pop(); 2361 return true; 2362 } 2363 2364 /* 2365 * > Anything else 2366 * > Parse error. Enable foster parenting, process the token using the rules for the 2367 * > "in body" insertion mode, and then disable foster parenting. 2368 * 2369 * @todo Indicate a parse error once it's possible. 2370 */ 2371 anything_else: 2372 $this->bail( 'Foster parenting is not supported.' ); 2131 2373 } 2132 2374 … … 2194 2436 * logic for the generalized WP_HTML_Processor::step() function. 2195 2437 * 2196 * @since 6.7.0 Stub implementation.2438 * @since 6.7.0 2197 2439 * 2198 2440 * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. … … 2204 2446 */ 2205 2447 private function step_in_table_body(): bool { 2206 $this->bail( 'No support for parsing in the ' . WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE_BODY . ' state.' ); 2448 $tag_name = $this->get_tag(); 2449 $op_sigil = $this->is_tag_closer() ? '-' : '+'; 2450 $op = "{$op_sigil}{$tag_name}"; 2451 2452 switch ( $op ) { 2453 /* 2454 * > A start tag whose tag name is "tr" 2455 */ 2456 case '+TR': 2457 $this->state->stack_of_open_elements->clear_to_table_body_context(); 2458 $this->insert_html_element( $this->state->current_token ); 2459 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_ROW; 2460 return true; 2461 2462 /* 2463 * > A start tag whose tag name is one of: "th", "td" 2464 */ 2465 case '+TH': 2466 case '+TD': 2467 // @todo Indicate a parse error once it's possible. 2468 $this->state->stack_of_open_elements->clear_to_table_body_context(); 2469 $this->insert_virtual_node( 'TR' ); 2470 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_ROW; 2471 return $this->step( self::REPROCESS_CURRENT_NODE ); 2472 2473 /* 2474 * > An end tag whose tag name is one of: "tbody", "tfoot", "thead" 2475 */ 2476 case '-TBODY': 2477 case '-TFOOT': 2478 case '-THEAD': 2479 /* 2480 * @todo This needs to check if the element in scope is an HTML element, meaning that 2481 * when SVG and MathML support is added, this needs to differentiate between an 2482 * HTML element of the given name, such as `<center>`, and a foreign element of 2483 * the same given name. 2484 */ 2485 if ( ! $this->state->stack_of_open_elements->has_element_in_table_scope( $tag_name ) ) { 2486 // Parse error: ignore the token. 2487 return $this->step(); 2488 } 2489 2490 $this->state->stack_of_open_elements->clear_to_table_body_context(); 2491 $this->state->stack_of_open_elements->pop(); 2492 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE; 2493 return true; 2494 2495 /* 2496 * > A start tag whose tag name is one of: "caption", "col", "colgroup", "tbody", "tfoot", "thead" 2497 * > An end tag whose tag name is "table" 2498 */ 2499 case '+CAPTION': 2500 case '+COL': 2501 case '+COLGROUP': 2502 case '+TBODY': 2503 case '+TFOOT': 2504 case '+THEAD': 2505 case '-TABLE': 2506 if ( 2507 ! $this->state->stack_of_open_elements->has_element_in_table_scope( 'TBODY' ) && 2508 ! $this->state->stack_of_open_elements->has_element_in_table_scope( 'THEAD' ) && 2509 ! $this->state->stack_of_open_elements->has_element_in_table_scope( 'TFOOT' ) 2510 ) { 2511 // Parse error: ignore the token. 2512 return $this->step(); 2513 } 2514 $this->state->stack_of_open_elements->clear_to_table_body_context(); 2515 $this->state->stack_of_open_elements->pop(); 2516 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE; 2517 return $this->step( self::REPROCESS_CURRENT_NODE ); 2518 2519 /* 2520 * > An end tag whose tag name is one of: "body", "caption", "col", "colgroup", "html", "td", "th", "tr" 2521 */ 2522 case '-BODY': 2523 case '-CAPTION': 2524 case '-COL': 2525 case '-COLGROUP': 2526 case '-HTML': 2527 case '-TD': 2528 case '-TH': 2529 case '-TR': 2530 // Parse error: ignore the token. 2531 return $this->step(); 2532 } 2533 2534 /* 2535 * > Anything else 2536 * > Process the token using the rules for the "in table" insertion mode. 2537 */ 2538 return $this->step_in_table(); 2207 2539 } 2208 2540 … … 2213 2545 * logic for the generalized WP_HTML_Processor::step() function. 2214 2546 * 2215 * @since 6.7.0 Stub implementation.2547 * @since 6.7.0 2216 2548 * 2217 2549 * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. … … 2223 2555 */ 2224 2556 private function step_in_row(): bool { 2225 $this->bail( 'No support for parsing in the ' . WP_HTML_Processor_State::INSERTION_MODE_IN_ROW . ' state.' ); 2557 $tag_name = $this->get_tag(); 2558 $op_sigil = $this->is_tag_closer() ? '-' : '+'; 2559 $op = "{$op_sigil}{$tag_name}"; 2560 2561 switch ( $op ) { 2562 /* 2563 * > A start tag whose tag name is one of: "th", "td" 2564 */ 2565 case '+TH': 2566 case '+TD': 2567 $this->state->stack_of_open_elements->clear_to_table_row_context(); 2568 $this->insert_html_element( $this->state->current_token ); 2569 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_CELL; 2570 $this->state->active_formatting_elements->insert_marker(); 2571 return true; 2572 2573 /* 2574 * > An end tag whose tag name is "tr" 2575 */ 2576 case '-TR': 2577 if ( ! $this->state->stack_of_open_elements->has_element_in_table_scope( 'TR' ) ) { 2578 // Parse error: ignore the token. 2579 return $this->step(); 2580 } 2581 2582 $this->state->stack_of_open_elements->clear_to_table_row_context(); 2583 $this->state->stack_of_open_elements->pop(); 2584 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE_BODY; 2585 return true; 2586 2587 /* 2588 * > A start tag whose tag name is one of: "caption", "col", "colgroup", "tbody", "tfoot", "thead", "tr" 2589 * > An end tag whose tag name is "table" 2590 */ 2591 case '+CAPTION': 2592 case '+COL': 2593 case '+COLGROUP': 2594 case '+TBODY': 2595 case '+TFOOT': 2596 case '+THEAD': 2597 case '+TR': 2598 case '-TABLE': 2599 if ( ! $this->state->stack_of_open_elements->has_element_in_table_scope( 'TR' ) ) { 2600 // Parse error: ignore the token. 2601 return $this->step(); 2602 } 2603 2604 $this->state->stack_of_open_elements->clear_to_table_row_context(); 2605 $this->state->stack_of_open_elements->pop(); 2606 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE_BODY; 2607 return $this->step( self::REPROCESS_CURRENT_NODE ); 2608 2609 /* 2610 * > An end tag whose tag name is one of: "tbody", "tfoot", "thead" 2611 */ 2612 case '-TBODY': 2613 case '-TFOOT': 2614 case '-THEAD': 2615 /* 2616 * @todo This needs to check if the element in scope is an HTML element, meaning that 2617 * when SVG and MathML support is added, this needs to differentiate between an 2618 * HTML element of the given name, such as `<center>`, and a foreign element of 2619 * the same given name. 2620 */ 2621 if ( ! $this->state->stack_of_open_elements->has_element_in_table_scope( $tag_name ) ) { 2622 // Parse error: ignore the token. 2623 return $this->step(); 2624 } 2625 2626 if ( ! $this->state->stack_of_open_elements->has_element_in_table_scope( 'TR' ) ) { 2627 // Ignore the token. 2628 return $this->step(); 2629 } 2630 2631 $this->state->stack_of_open_elements->clear_to_table_row_context(); 2632 $this->state->stack_of_open_elements->pop(); 2633 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE_BODY; 2634 return $this->step( self::REPROCESS_CURRENT_NODE ); 2635 2636 /* 2637 * > An end tag whose tag name is one of: "body", "caption", "col", "colgroup", "html", "td", "th" 2638 */ 2639 case '-BODY': 2640 case '-CAPTION': 2641 case '-COL': 2642 case '-COLGROUP': 2643 case '-HTML': 2644 case '-TD': 2645 case '-TH': 2646 // Parse error: ignore the token. 2647 return $this->step(); 2648 } 2649 2650 /* 2651 * > Anything else 2652 * > Process the token using the rules for the "in table" insertion mode. 2653 */ 2654 return $this->step_in_table(); 2226 2655 } 2227 2656 … … 2232 2661 * logic for the generalized WP_HTML_Processor::step() function. 2233 2662 * 2234 * @since 6.7.0 Stub implementation.2663 * @since 6.7.0 2235 2664 * 2236 2665 * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input. … … 2242 2671 */ 2243 2672 private function step_in_cell(): bool { 2244 $this->bail( 'No support for parsing in the ' . WP_HTML_Processor_State::INSERTION_MODE_IN_CELL . ' state.' ); 2673 $tag_name = $this->get_tag(); 2674 $op_sigil = $this->is_tag_closer() ? '-' : '+'; 2675 $op = "{$op_sigil}{$tag_name}"; 2676 2677 switch ( $op ) { 2678 /* 2679 * > An end tag whose tag name is one of: "td", "th" 2680 */ 2681 case '-TD': 2682 case '-TH': 2683 /* 2684 * @todo This needs to check if the element in scope is an HTML element, meaning that 2685 * when SVG and MathML support is added, this needs to differentiate between an 2686 * HTML element of the given name, such as `<center>`, and a foreign element of 2687 * the same given name. 2688 */ 2689 if ( ! $this->state->stack_of_open_elements->has_element_in_table_scope( $tag_name ) ) { 2690 // Parse error: ignore the token. 2691 return $this->step(); 2692 } 2693 2694 $this->generate_implied_end_tags(); 2695 2696 /* 2697 * @todo This needs to check if the current node is an HTML element, meaning that 2698 * when SVG and MathML support is added, this needs to differentiate between an 2699 * HTML element of the given name, such as `<center>`, and a foreign element of 2700 * the same given name. 2701 */ 2702 if ( ! $this->state->stack_of_open_elements->current_node_is( $tag_name ) ) { 2703 // @todo Indicate a parse error once it's possible. 2704 } 2705 2706 $this->state->stack_of_open_elements->pop_until( $tag_name ); 2707 $this->state->active_formatting_elements->clear_up_to_last_marker(); 2708 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_ROW; 2709 return true; 2710 2711 /* 2712 * > A start tag whose tag name is one of: "caption", "col", "colgroup", "tbody", "td", 2713 * > "tfoot", "th", "thead", "tr" 2714 */ 2715 case '+CAPTION': 2716 case '+COL': 2717 case '+COLGROUP': 2718 case '+TBODY': 2719 case '+TD': 2720 case '+TFOOT': 2721 case '+TH': 2722 case '+THEAD': 2723 case '+TR': 2724 /* 2725 * > Assert: The stack of open elements has a td or th element in table scope. 2726 * 2727 * Nothing to do here, except to verify in tests that this never appears. 2728 */ 2729 2730 $this->close_cell(); 2731 return $this->step( self::REPROCESS_CURRENT_NODE ); 2732 2733 /* 2734 * > An end tag whose tag name is one of: "body", "caption", "col", "colgroup", "html" 2735 */ 2736 case '-BODY': 2737 case '-CAPTION': 2738 case '-COL': 2739 case '-COLGROUP': 2740 case '-HTML': 2741 // Parse error: ignore the token. 2742 return $this->step(); 2743 2744 /* 2745 * > An end tag whose tag name is one of: "table", "tbody", "tfoot", "thead", "tr" 2746 */ 2747 case '-TABLE': 2748 case '-TBODY': 2749 case '-TFOOT': 2750 case '-THEAD': 2751 case '-TR': 2752 /* 2753 * @todo This needs to check if the element in scope is an HTML element, meaning that 2754 * when SVG and MathML support is added, this needs to differentiate between an 2755 * HTML element of the given name, such as `<center>`, and a foreign element of 2756 * the same given name. 2757 */ 2758 if ( ! $this->state->stack_of_open_elements->has_element_in_table_scope( $tag_name ) ) { 2759 // Parse error: ignore the token. 2760 return $this->step(); 2761 } 2762 $this->close_cell(); 2763 return $this->step( self::REPROCESS_CURRENT_NODE ); 2764 } 2765 2766 /* 2767 * > Anything else 2768 * > Process the token using the rules for the "in body" insertion mode. 2769 */ 2770 return $this->step_in_body(); 2245 2771 } 2246 2772 … … 3578 4104 3579 4105 /** 4106 * Runs the "close the cell" algorithm. 4107 * 4108 * > Where the steps above say to close the cell, they mean to run the following algorithm: 4109 * > 1. Generate implied end tags. 4110 * > 2. If the current node is not now a td element or a th element, then this is a parse error. 4111 * > 3. Pop elements from the stack of open elements stack until a td element or a th element has been popped from the stack. 4112 * > 4. Clear the list of active formatting elements up to the last marker. 4113 * > 5. Switch the insertion mode to "in row". 4114 * 4115 * @see https://html.spec.whatwg.org/multipage/parsing.html#close-the-cell 4116 * 4117 * @since 6.7.0 4118 */ 4119 private function close_cell(): void { 4120 $this->generate_implied_end_tags(); 4121 // @todo Parse error if the current node is a "td" or "th" element. 4122 foreach ( $this->state->stack_of_open_elements->walk_up() as $element ) { 4123 $this->state->stack_of_open_elements->pop(); 4124 if ( 'TD' === $element->node_name || 'TH' === $element->node_name ) { 4125 break; 4126 } 4127 } 4128 $this->state->active_formatting_elements->clear_up_to_last_marker(); 4129 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_ROW; 4130 } 4131 4132 /** 3580 4133 * Inserts an HTML element on the stack of open elements. 3581 4134 * … … 3588 4141 private function insert_html_element( WP_HTML_Token $token ): void { 3589 4142 $this->state->stack_of_open_elements->push( $token ); 4143 } 4144 4145 /** 4146 * Inserts a virtual element on the stack of open elements. 4147 * 4148 * @since 6.7.0 4149 * 4150 * @param string $token_name Name of token to create and insert into the stack of open elements. 4151 * @param string|null $bookmark_name Optional. Name to give bookmark for created virtual node. 4152 * Defaults to auto-creating a bookmark name. 4153 */ 4154 private function insert_virtual_node( $token_name, $bookmark_name = null ): void { 4155 $here = $this->bookmarks[ $this->state->current_token->bookmark_name ]; 4156 $name = $bookmark_name ?? $this->bookmark_token(); 4157 4158 $this->bookmarks[ $name ] = new WP_HTML_Span( $here->start, 0 ); 4159 4160 $this->insert_html_element( new WP_HTML_Token( $name, $token_name, false ) ); 3590 4161 } 3591 4162 -
trunk/tests/phpunit/tests/html-api/wpHtmlProcessorBreadcrumbs.php
r58779 r58806 182 182 'BGSOUND', // Deprecated; self-closing if self-closing flag provided, otherwise normal. 183 183 'BODY', 184 'CAPTION',185 'COL',186 'COLGROUP',187 184 'FRAME', 188 185 'FRAMESET', … … 199 196 'STYLE', 200 197 'SVG', 201 'TBODY',202 'TD',203 198 'TEMPLATE', 204 199 'TEXTAREA', 205 'TFOOT',206 'TH',207 'THEAD',208 200 'TITLE', 209 'TR',210 201 'XMP', // Deprecated, use PRE instead. 211 202 ); -
trunk/tests/phpunit/tests/html-api/wpHtmlProcessorSemanticRules.php
r58779 r58806 425 425 $this->assertNull( $processor->get_attribute_names_with_prefix( '' ), 'Should have ignored any attributes on the tag.' ); 426 426 } 427 428 /******************************************************************* 429 * RULES FOR "IN TABLE" MODE 430 *******************************************************************/ 431 432 /** 433 * Ensure that form elements in tables (but not cells) are immediately popped off the stack. 434 * 435 * @ticket 61576 436 */ 437 public function test_table_form_element_immediately_popped() { 438 $processor = WP_HTML_Processor::create_fragment( '<table><form><!--comment-->' ); 439 440 // There should be a FORM opener and a (virtual) FORM closer. 441 $this->assertTrue( $processor->next_tag( 'FORM' ) ); 442 $this->assertTrue( $processor->next_token() ); 443 $this->assertSame( 'FORM', $processor->get_token_name() ); 444 $this->assertTrue( $processor->is_tag_closer() ); 445 446 // Followed by the comment token. 447 $this->assertTrue( $processor->next_token() ); 448 $this->assertSame( '#comment', $processor->get_token_name() ); 449 $this->assertsame( array( 'HTML', 'BODY', 'TABLE', '#comment' ), $processor->get_breadcrumbs() ); 450 } 427 451 }
Note: See TracChangeset
for help on using the changeset viewer.