From bfe153572b09e04edd2120360406d0fdbc4c0124 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Fri, 2 Feb 2024 16:15:35 +0100 Subject: [PATCH] Implement insertion mode algorithm --- .../class-wp-html-processor-state.php | 108 ++++++++++++++++++ .../html-api/class-wp-html-processor.php | 80 +++++++++++++ 2 files changed, 188 insertions(+) diff --git a/src/wp-includes/html-api/class-wp-html-processor-state.php b/src/wp-includes/html-api/class-wp-html-processor-state.php index 9cf10c344107a..f72b6ebd765c9 100644 --- a/src/wp-includes/html-api/class-wp-html-processor-state.php +++ b/src/wp-includes/html-api/class-wp-html-processor-state.php @@ -59,6 +59,114 @@ class WP_HTML_Processor_State { */ const INSERTION_MODE_IN_BODY = 'insertion-mode-in-body'; + /** + * In select insertion mode for full HTML parser. + * + * @since 6.5.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inselect + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_SELECT = 'insertion-mode-in-select'; + + /** + * In select in table insertion mode for full HTML parser. + * + * @since 6.5.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inselectintable + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_SELECT_IN_TABLE = 'insertion-mode-in-select-in-table'; + + /** + * In table insertion mode for full HTML parser. + * + * @since 6.5.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-intable + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_TABLE = 'insertion-mode-in-table'; + + /** + * In caption insertion mode for full HTML parser. + * + * @since 6.5.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-incaption + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_CAPTION = 'insertion-mode-in-caption'; + + /** + * In table body insertion mode for full HTML parser. + * + * @since 6.5.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-intablebody + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_TABLE_BODY = 'insertion-mode-in-table-body'; + + /** + * In row insertion mode for full HTML parser. + * + * @since 6.5.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inrow + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_ROW = 'insertion-mode-in-row'; + + /** + * In cell insertion mode for full HTML parser. + * + * @since 6.5.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-incell + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_CELL = 'insertion-mode-in-cell'; + + /** + * In column group insertion mode for full HTML parser. + * + * @since 6.5.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-incolumngroup + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_COLUMN_GROUP = 'insertion-mode-in-column-group'; + + /** + * In frameset insertion mode for full HTML parser. + * + * @since 6.5.0 + * + * @see https://html.spec.whatwg.org/#parsing-main-inframeset + * @see WP_HTML_Processor_State::$insertion_mode + * + * @var string + */ + const INSERTION_MODE_IN_FRAMESET = 'insertion-mode-in-frameset'; + /** * Tracks open elements while scanning HTML. * 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 528c222335b75..f12afaec3bba5 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -1971,6 +1971,86 @@ private function reconstruct_active_formatting_elements() { throw new WP_HTML_Unsupported_Exception( 'Cannot reconstruct active formatting elements when advancing and rewinding is required.' ); } + /** + * Runs the reset the insertion mode appropriately algorithm. + * + * @since 6.5.0 + * + * @throws WP_HTML_Unsupported_Exception When encoutering unsupported nodes. + * + * @see https://html.spec.whatwg.org/multipage/parsing.html#reset-the-insertion-mode-appropriately + */ + private function reset_insertion_mode() { + foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { + switch ( $node->node_name ) { + case 'SELECT': + foreach ( $this->state->stack_of_open_elements->walk_up( $node ) as $ancestor ) { + switch ( $ancestor ) { + // > If ancestor is a table node, switch the insertion mode to "in select in table" and return. + case 'TABLE': + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT_IN_TABLE; + return; + // > If ancestor is a template node, jump to the step below labeled done. + case 'TEMPLATE': + break 2; + } + } + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT; + return; + + case 'TD': + case 'TH': + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_CELL; + return; + + case 'TR': + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_ROW; + return; + + case 'TBODY': + case 'THEAD': + case 'TFOOT': + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE_BODY; + return; + + case 'CAPTION': + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_CAPTION; + return; + + case 'COLGROUP': + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_COLUMN_GROUP; + return; + + case 'TABLE': + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE; + return; + + case 'TEMPLATE': + $this->last_error = self::ERROR_UNSUPPORTED; + throw new WP_HTML_Unsupported_Exception( 'Cannot reset insertion mode at TEMPLATE node.' ); + + case 'HEAD': + $this->last_error = self::ERROR_UNSUPPORTED; + throw new WP_HTML_Unsupported_Exception( 'Cannot reset insertion mode at HEAD node.' ); + + case 'BODY': + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_BODY; + return; + + case 'FRAMESET': + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_FRAMESET; + return; + + case 'HTML': + $this->last_error = self::ERROR_UNSUPPORTED; + throw new WP_HTML_Unsupported_Exception( 'Cannot reset insertion mode at HTML node.' ); + } + } + + $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_BODY; + return; + } + /** * Runs the adoption agency algorithm. *