diff --git a/src/wp-includes/html-api/class-wp-html-tag-processor.php b/src/wp-includes/html-api/class-wp-html-tag-processor.php index 79d96dc8be3f1..e6ac98daae6ab 100644 --- a/src/wp-includes/html-api/class-wp-html-tag-processor.php +++ b/src/wp-includes/html-api/class-wp-html-tag-processor.php @@ -378,6 +378,15 @@ class WP_HTML_Tag_Processor { */ private $is_closing_tag; + /** + * Stores the position of the last-matched tag, or the start of the document if not matched yet. + * + * @var WP_HTML_Span + */ + private $last_position = null; + + private $last_token_end = 0; + /** * Lazily-built index of attributes found within an HTML tag, keyed by the attribute name. * @@ -507,6 +516,8 @@ class WP_HTML_Tag_Processor { */ public function __construct( $html ) { $this->html = $html; + + $this->last_position = new WP_HTML_Span( 0, 0 ); } /** @@ -530,6 +541,16 @@ public function next_tag( $query = null ) { $this->parse_query( $query ); $already_found = 0; + if ( null !== $this->tag_name_starts_at ) { + $rewind_amount = $this->is_closing_tag ? 2 : 1; + $before_tag = $this->tag_name_starts_at - $rewind_amount; + $end_of_tag = $this->tag_ends_at; + + $this->last_position->start = $before_tag; + $this->last_position->end = $end_of_tag; + $this->last_token_end = $this->tag_ends_at + 1; + } + do { if ( $this->bytes_already_parsed >= strlen( $this->html ) ) { return false; @@ -1876,6 +1897,74 @@ public function is_tag_closer() { return $this->is_closing_tag; } + /** + * Returns the chunk of text from the end of the preceding tag or token to the + * start of the matched tag or token, with decoded character references. + * + * Example: + * + * $q = array( 'tag_closers' => 'visit' ); + * $processor = new WP_HTML_Tag_Processor( 'Before