Skip to content

Commit f2028e1

Browse files
HTML API: Add bookmark invalidation logic.
While `WP_HTML_Tag_Processor` currently only supports changing a given tag's attributes, the plan is to provide methods to make broader changes (possibly through a subclass of `WP_HTML_Tag_Processor`). The API will have the potential of replacing a tag that a bookmark points to. To prepare, this changeset makes sure that all bookmarks affected by a HTML replacement are invalidated (i.e. released). Changes: * Extends the existing loop in `WP_HTML_Tag_Processor::apply_attributes_updates()` that adjusts bookmarks' start and end positions upon HTML changes to check if the entire bookmark is within a portion of the HTML that has been replaced. * Adds `WP_HTML_Tag_Processor::has_bookmark() to check whether the given bookmark name exists. References: * [WordPress/gutenberg#47559 Gutenberg PR 47559] * [https://github.com/WordPress/gutenberg/releases/tag/v15.3.0 Released in Gutenberg 15.3.0] Follow-up to [55203]. Props bernhard-reiter, dmsnell, zieladam. Fixes #57788. git-svn-id: https://develop.svn.wordpress.org/trunk@55555 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 6222a11 commit f2028e1

2 files changed

Lines changed: 57 additions & 7 deletions

File tree

src/wp-includes/html-api/class-wp-html-tag-processor.php

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,7 @@ private function class_name_updates_to_attributes_updates() {
14041404
* Applies attribute updates to HTML document.
14051405
*
14061406
* @since 6.2.0
1407+
* @since 6.3.0 Invalidate any bookmarks whose targets are overwritten.
14071408
*
14081409
* @return void
14091410
*/
@@ -1434,7 +1435,7 @@ private function apply_attributes_updates() {
14341435
* Adjust bookmark locations to account for how the text
14351436
* replacements adjust offsets in the input document.
14361437
*/
1437-
foreach ( $this->bookmarks as $bookmark ) {
1438+
foreach ( $this->bookmarks as $bookmark_name => $bookmark ) {
14381439
/*
14391440
* Each lexical update which appears before the bookmark's endpoints
14401441
* might shift the offsets for those endpoints. Loop through each change
@@ -1445,20 +1446,22 @@ private function apply_attributes_updates() {
14451446
$tail_delta = 0;
14461447

14471448
foreach ( $this->lexical_updates as $diff ) {
1448-
$update_head = $bookmark->start >= $diff->start;
1449-
$update_tail = $bookmark->end >= $diff->start;
1450-
1451-
if ( ! $update_head && ! $update_tail ) {
1449+
if ( $bookmark->start < $diff->start && $bookmark->end < $diff->start ) {
14521450
break;
14531451
}
14541452

1453+
if ( $bookmark->start >= $diff->start && $bookmark->end < $diff->end ) {
1454+
$this->release_bookmark( $bookmark_name );
1455+
continue 2;
1456+
}
1457+
14551458
$delta = strlen( $diff->text ) - ( $diff->end - $diff->start );
14561459

1457-
if ( $update_head ) {
1460+
if ( $bookmark->start >= $diff->start ) {
14581461
$head_delta += $delta;
14591462
}
14601463

1461-
if ( $update_tail ) {
1464+
if ( $bookmark->end >= $diff->end ) {
14621465
$tail_delta += $delta;
14631466
}
14641467
}
@@ -1470,6 +1473,18 @@ private function apply_attributes_updates() {
14701473
$this->lexical_updates = array();
14711474
}
14721475

1476+
/**
1477+
* Checks whether a bookmark with the given name exists.
1478+
*
1479+
* @since 6.3.0
1480+
*
1481+
* @param string $bookmark_name Name to identify a bookmark that potentially exists.
1482+
* @return bool Whether that bookmark exists.
1483+
*/
1484+
public function has_bookmark( $bookmark_name ) {
1485+
return array_key_exists( $bookmark_name, $this->bookmarks );
1486+
}
1487+
14731488
/**
14741489
* Move the internal cursor in the Tag Processor to a given bookmark's location.
14751490
*

tests/phpunit/tests/html-api/wpHtmlTagProcessor-bookmark.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,41 @@ public function test_release_bookmark() {
4040
$this->assertTrue( $p->release_bookmark( 'first li' ), 'Could not release a bookmark' );
4141
}
4242

43+
/**
44+
* @ticket 57788
45+
*
46+
* @covers WP_HTML_Tag_Processor::has_bookmark
47+
*/
48+
public function test_has_bookmark_returns_false_if_bookmark_does_not_exist() {
49+
$p = new WP_HTML_Tag_Processor( '<div>Test</div>' );
50+
$this->assertFalse( $p->has_bookmark( 'my-bookmark' ) );
51+
}
52+
53+
/**
54+
* @ticket 57788
55+
*
56+
* @covers WP_HTML_Tag_Processor::has_bookmark
57+
*/
58+
public function test_has_bookmark_returns_true_if_bookmark_exists() {
59+
$p = new WP_HTML_Tag_Processor( '<div>Test</div>' );
60+
$p->next_tag();
61+
$p->set_bookmark( 'my-bookmark' );
62+
$this->assertTrue( $p->has_bookmark( 'my-bookmark' ) );
63+
}
64+
65+
/**
66+
* @ticket 57788
67+
*
68+
* @covers WP_HTML_Tag_Processor::has_bookmark
69+
*/
70+
public function test_has_bookmark_returns_false_if_bookmark_has_been_released() {
71+
$p = new WP_HTML_Tag_Processor( '<div>Test</div>' );
72+
$p->next_tag();
73+
$p->set_bookmark( 'my-bookmark' );
74+
$p->release_bookmark( 'my-bookmark' );
75+
$this->assertFalse( $p->has_bookmark( 'my-bookmark' ) );
76+
}
77+
4378
/**
4479
* @ticket 56299
4580
*

0 commit comments

Comments
 (0)