Skip to content

Commit

Permalink
Tag Processor: Add bookmark invalidation logic (#47559)
Browse files Browse the repository at this point in the history
Invalidate bookmarks in a `WP_HTML_Tag_Processor` instance if the tags that they're pointing to have been replaced.

While `WP_HTML_Tag_Processor` currently only supports changing a given tag's attributes, we plan to also provide methods to make broader changes (possibly through a subclass of `WP_HTML_Tag_Processor`).

An API like that will have the potential of replacing a tag that a bookmark points to. As a preparation, we thus need to make sure that all bookmarks affected by a HTML replacement are invalidated (i.e. released).

Co-authored-by: Dennis Snell <[email protected]>
  • Loading branch information
ockham and dmsnell authored Feb 21, 2023
1 parent 6095747 commit 0ff570f
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,7 @@ private function class_name_updates_to_attributes_updates() {
* Applies attribute updates to HTML document.
*
* @since 6.2.0
* @since 6.3.0 Invalidate any bookmarks whose targets are overwritten.
*
* @return void
*/
Expand Down Expand Up @@ -1431,7 +1432,7 @@ private function apply_attributes_updates() {
* Adjust bookmark locations to account for how the text
* replacements adjust offsets in the input document.
*/
foreach ( $this->bookmarks as $bookmark ) {
foreach ( $this->bookmarks as $bookmark_name => $bookmark ) {
/*
* Each lexical update which appears before the bookmark's endpoints
* might shift the offsets for those endpoints. Loop through each change
Expand All @@ -1442,20 +1443,22 @@ private function apply_attributes_updates() {
$tail_delta = 0;

foreach ( $this->lexical_updates as $diff ) {
$update_head = $bookmark->start >= $diff->start;
$update_tail = $bookmark->end >= $diff->start;

if ( ! $update_head && ! $update_tail ) {
if ( $bookmark->start < $diff->start && $bookmark->end < $diff->start ) {
break;
}

if ( $bookmark->start >= $diff->start && $bookmark->end < $diff->end ) {
$this->release_bookmark( $bookmark_name );
continue 2;
}

$delta = strlen( $diff->text ) - ( $diff->end - $diff->start );

if ( $update_head ) {
if ( $bookmark->start >= $diff->start ) {
$head_delta += $delta;
}

if ( $update_tail ) {
if ( $bookmark->end >= $diff->end ) {
$tail_delta += $delta;
}
}
Expand All @@ -1467,6 +1470,18 @@ private function apply_attributes_updates() {
$this->lexical_updates = array();
}

/**
* Checks whether a bookmark with the given name exists.
*
* @since 6.3.0
*
* @param string $bookmark_name Name to identify a bookmark that potentially exists.
* @return bool Whether that bookmark exists.
*/
public function has_bookmark( $bookmark_name ) {
return array_key_exists( $bookmark_name, $this->bookmarks );
}

/**
* Move the internal cursor in the Tag Processor to a given bookmark's location.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
/**
* Unit tests covering Gutenberg_HTML_Tag_Processor_6_3 functionality.
*
* @package WordPress
* @subpackage HTML
*/

require_once __DIR__ . '/../../lib/compat/wordpress-6.3/html-api/class-gutenberg-html-tag-processor-6-3.php';

/**
* @group html-api
*
* @coversDefaultClass Gutenberg_HTML_Tag_Processor_6_3
*/
class Gutenberg_HTML_Tag_Processor_6_3_Bookmark_Test extends WP_UnitTestCase {
/**
* @covers has_bookmark
*/
public function test_has_bookmark_returns_false_if_bookmark_does_not_exist() {
$p = new Gutenberg_HTML_Tag_Processor_6_3( '<div>Test</div>' );
$this->assertFalse( $p->has_bookmark( 'my-bookmark' ) );
}

/**
* @covers has_bookmark
*/
public function test_has_bookmark_returns_true_if_bookmark_exists() {
$p = new Gutenberg_HTML_Tag_Processor_6_3( '<div>Test</div>' );
$p->next_tag();
$p->set_bookmark( 'my-bookmark' );
$this->assertTrue( $p->has_bookmark( 'my-bookmark' ) );
}

/**
* @covers has_bookmark
*/
public function test_has_bookmark_returns_false_if_bookmark_has_been_released() {
$p = new Gutenberg_HTML_Tag_Processor_6_3( '<div>Test</div>' );
$p->next_tag();
$p->set_bookmark( 'my-bookmark' );
$p->release_bookmark( 'my-bookmark' );
$this->assertFalse( $p->has_bookmark( 'my-bookmark' ) );
}
}

1 comment on commit 0ff570f

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in 0ff570f.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4233785746
📝 Reported issues:

Please sign in to comment.