WP_HTML_Processor::create_fragment_at_current_node()
Creates a fragment processor at the current node.
HTML Fragment parsing always happens with a context node. HTML Fragment Processors can be instantiated with a BODY context node via WP_HTML_Processor::create_fragment($html).
The context node may impact how a fragment of HTML is parsed. For example, consider the HTML fragment <td />Inside TD?</td>.
A BODY context node will produce the following tree:
└─#text Inside TD?
Notice that the <td> tags are completely ignored.
Compare that with an SVG context node that produces the following tree:
├─svg:td └─#text Inside TD?
Here, a td node in the svg namespace is created, and its self-closing flag is respected. This is a peculiarity of parsing HTML in foreign content like SVG.
Finally, consider the tree produced with a TABLE context node:
└─TBODY └─TR └─TD └─#text Inside TD?
These examples demonstrate how important the context node may be when processing an HTML fragment. Special care must be taken when processing fragments that are expected to appear in specific contexts. SVG and TABLE are good examples, but there are others.
Method of the class: WP_HTML_Processor{}
No Hooks.
Return
static|null
. The created processor if successful, otherwise null.
Usage
// private - for code of main (parent) class only $result = $this->create_fragment_at_current_node( $html );
- $html(string) (required)
- Input HTML fragment to process.
Notes
Changelog
Since 6.8.0 | Introduced. |
WP_HTML_Processor::create_fragment_at_current_node() WP HTML Processor::create fragment at current node code WP 6.8
private function create_fragment_at_current_node( string $html ) { if ( $this->get_token_type() !== '#tag' || $this->is_tag_closer() ) { _doing_it_wrong( __METHOD__, __( 'The context element must be a start tag.' ), '6.8.0' ); return null; } $tag_name = $this->current_element->token->node_name; $namespace = $this->current_element->token->namespace; if ( 'html' === $namespace && self::is_void( $tag_name ) ) { _doing_it_wrong( __METHOD__, sprintf( // translators: %s: A tag name like INPUT or BR. __( 'The context element cannot be a void element, found "%s".' ), $tag_name ), '6.8.0' ); return null; } /* * Prevent creating fragments at nodes that require a special tokenizer state. * This is unsupported by the HTML Processor. */ if ( 'html' === $namespace && in_array( $tag_name, array( 'IFRAME', 'NOEMBED', 'NOFRAMES', 'SCRIPT', 'STYLE', 'TEXTAREA', 'TITLE', 'XMP', 'PLAINTEXT' ), true ) ) { _doing_it_wrong( __METHOD__, sprintf( // translators: %s: A tag name like IFRAME or TEXTAREA. __( 'The context element "%s" is not supported.' ), $tag_name ), '6.8.0' ); return null; } $fragment_processor = new static( $html, self::CONSTRUCTOR_UNLOCK_CODE ); $fragment_processor->compat_mode = $this->compat_mode; // @todo Create "fake" bookmarks for non-existent but implied nodes. $fragment_processor->bookmarks['root-node'] = new WP_HTML_Span( 0, 0 ); $root_node = new WP_HTML_Token( 'root-node', 'HTML', false ); $fragment_processor->state->stack_of_open_elements->push( $root_node ); $fragment_processor->bookmarks['context-node'] = new WP_HTML_Span( 0, 0 ); $fragment_processor->context_node = clone $this->current_element->token; $fragment_processor->context_node->bookmark_name = 'context-node'; $fragment_processor->context_node->on_destroy = null; $fragment_processor->breadcrumbs = array( 'HTML', $fragment_processor->context_node->node_name ); if ( 'TEMPLATE' === $fragment_processor->context_node->node_name ) { $fragment_processor->state->stack_of_template_insertion_modes[] = WP_HTML_Processor_State::INSERTION_MODE_IN_TEMPLATE; } $fragment_processor->reset_insertion_mode_appropriately(); /* * > Set the parser's form element pointer to the nearest node to the context element that * > is a form element (going straight up the ancestor chain, and including the element * > itself, if it is a form element), if any. (If there is no such form element, the * > form element pointer keeps its initial value, null.) */ foreach ( $this->state->stack_of_open_elements->walk_up() as $element ) { if ( 'FORM' === $element->node_name && 'html' === $element->namespace ) { $fragment_processor->state->form_element = clone $element; $fragment_processor->state->form_element->bookmark_name = null; $fragment_processor->state->form_element->on_destroy = null; break; } } $fragment_processor->state->encoding_confidence = 'irrelevant'; /* * Update the parsing namespace near the end of the process. * This is important so that any push/pop from the stack of open * elements does not change the parsing namespace. */ $fragment_processor->change_parsing_namespace( $this->current_element->token->integration_node_type ? 'html' : $namespace ); return $fragment_processor; }