Skip to content

Commit

Permalink
Allow handling of non-attribute lexical updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ockham committed Feb 21, 2023
1 parent cfb54a7 commit 3985596
Showing 1 changed file with 59 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,18 @@ class Gutenberg_HTML_Tag_Processor_6_3 {
*/
protected $lexical_updates = array();

/**
* Attribute replacements to apply to input HTML document.
*
* Unlike more generic lexical updates, attribute updates are stored
* in an associative array, where the keys are (lowercase-normalized)
* attribute names, in order to avoid duplication.
*
* @since 6.3.0
* @var WP_HTML_Text_Replacement[]
*/
private $attribute_updates = array();

/**
* Tracks and limits `seek()` calls to prevent accidental infinite loops.
*
Expand Down Expand Up @@ -1237,15 +1249,16 @@ private function skip_whitespace() {
}

/**
* Applies attribute updates and cleans up once a tag is fully parsed.
* Applies lexical updates and cleans up once a tag is fully parsed.
*
* @since 6.2.0
*
* @return void
*/
private function after_tag() {
$this->class_name_updates_to_attributes_updates();
$this->apply_attributes_updates();
$this->class_name_updates_to_attribute_updates();
$this->attribute_updates_to_lexical_updates();
$this->apply_lexical_updates();
$this->tag_name_starts_at = null;
$this->tag_name_length = null;
$this->tag_ends_at = null;
Expand All @@ -1254,17 +1267,17 @@ private function after_tag() {
}

/**
* Converts class name updates into tag attributes updates
* Converts class name updates into tag attribute updates
* (they are accumulated in different data formats for performance).
*
* @see $lexical_updates
* @see $attribute_updates
* @see $classname_updates
*
* @since 6.2.0
*
* @return void
*/
private function class_name_updates_to_attributes_updates() {
private function class_name_updates_to_attribute_updates() {
if ( count( $this->classname_updates ) === 0 ) {
return;
}
Expand Down Expand Up @@ -1398,14 +1411,33 @@ private function class_name_updates_to_attributes_updates() {
}

/**
* Applies attribute updates to HTML document.
* Converts attribute updates into lexical updates.
*
* This method is only meant to run right before the attribute updates are applied.
* The behavior in all other cases is undefined.
*
* @return void
* @since 6.3.0
*
* @see $attribute_updates
* @see $lexical_updates
*/
private function attribute_updates_to_lexical_updates() {
foreach ( $this->attribute_updates as $update ) {
$this->lexical_updates[] = $update;
}
$this->attribute_updates = array();
}

/**
* Applies lexical updates to HTML document.
*
* @since 6.2.0
* @since 6.3.0 Invalidate any bookmarks whose targets are overwritten.
*
* @return void
*/
private function apply_attributes_updates() {
private function apply_lexical_updates() {
if ( ! count( $this->lexical_updates ) ) {
return;
}
Expand Down Expand Up @@ -1527,8 +1559,8 @@ public function seek( $bookmark_name ) {
*
* @since 6.2.0
*
* @param WP_HTML_Text_Replacement $a First attribute update.
* @param WP_HTML_Text_Replacement $b Second attribute update.
* @param WP_HTML_Text_Replacement $a First lexical update.
* @param WP_HTML_Text_Replacement $b Second lexical update.
* @return int Comparison value for string order.
*/
private static function sort_start_ascending( $a, $b ) {
Expand Down Expand Up @@ -1564,11 +1596,11 @@ private static function sort_start_ascending( $a, $b ) {
* @return string|boolean|null Value of enqueued update if present, otherwise false.
*/
private function get_enqueued_attribute_value( $comparable_name ) {
if ( ! isset( $this->lexical_updates[ $comparable_name ] ) ) {
if ( ! isset( $this->attribute_updates[ $comparable_name ] ) ) {
return false;
}

$enqueued_text = $this->lexical_updates[ $comparable_name ]->text;
$enqueued_text = $this->attribute_updates[ $comparable_name ]->text;

// Removed attributes erase the entire span.
if ( '' === $enqueued_text ) {
Expand Down Expand Up @@ -1641,7 +1673,7 @@ public function get_attribute( $name ) {

/*
* For every attribute other than `class` it's possible to perform a quick check if
* there's an enqueued lexical update whose value takes priority over what's found in
* there's an enqueued attribute update whose value takes priority over what's found in
* the input document.
*
* The `class` attribute is special though because of the exposed helpers `add_class`
Expand All @@ -1651,7 +1683,7 @@ public function get_attribute( $name ) {
* into an attribute value update.
*/
if ( 'class' === $name ) {
$this->class_name_updates_to_attributes_updates();
$this->class_name_updates_to_attribute_updates();
}

// Return any enqueued attribute value updates if they exist.
Expand Down Expand Up @@ -1879,8 +1911,8 @@ public function set_attribute( $name, $value ) {
*
* Result: <div id="new"/>
*/
$existing_attribute = $this->attributes[ $comparable_name ];
$this->lexical_updates[ $name ] = new WP_HTML_Text_Replacement(
$existing_attribute = $this->attributes[ $comparable_name ];
$this->attribute_updates[ $name ] = new WP_HTML_Text_Replacement(
$existing_attribute->start,
$existing_attribute->end,
$updated_attribute
Expand All @@ -1897,7 +1929,7 @@ public function set_attribute( $name, $value ) {
*
* Result: <div id="new"/>
*/
$this->lexical_updates[ $comparable_name ] = new WP_HTML_Text_Replacement(
$this->attribute_updates[ $comparable_name ] = new WP_HTML_Text_Replacement(
$this->tag_name_starts_at + $this->tag_name_length,
$this->tag_name_starts_at + $this->tag_name_length,
' ' . $updated_attribute
Expand Down Expand Up @@ -1955,8 +1987,8 @@ public function remove_attribute( $name ) {
* and when that attribute wasn't originally present.
*/
if ( ! isset( $this->attributes[ $name ] ) ) {
if ( isset( $this->lexical_updates[ $name ] ) ) {
unset( $this->lexical_updates[ $name ] );
if ( isset( $this->attribute_updates[ $name ] ) ) {
unset( $this->attribute_updates[ $name ] );
}
return false;
}
Expand All @@ -1972,7 +2004,7 @@ public function remove_attribute( $name ) {
*
* Result: <div />
*/
$this->lexical_updates[ $name ] = new WP_HTML_Text_Replacement(
$this->attribute_updates[ $name ] = new WP_HTML_Text_Replacement(
$this->attributes[ $name ]->start,
$this->attributes[ $name ]->end,
''
Expand Down Expand Up @@ -2041,7 +2073,10 @@ public function __toString() {
* @return string The processed HTML.
*/
public function get_updated_html() {
$requires_no_updating = 0 === count( $this->classname_updates ) && 0 === count( $this->lexical_updates );
$requires_no_updating =
0 === count( $this->classname_updates ) &&
0 === count( $this->attribute_updates ) &&
0 === count( $this->lexical_updates );

/*
* When there is nothing more to update and nothing has already been
Expand Down Expand Up @@ -2072,8 +2107,9 @@ public function get_updated_html() {
*
* Note: `apply_attributes_updates()` modifies `$this->output_buffer`.
*/
$this->class_name_updates_to_attributes_updates();
$this->apply_attributes_updates();
$this->class_name_updates_to_attribute_updates();
$this->attribute_updates_to_lexical_updates();
$this->apply_lexical_updates();

/*
* 2. Replace the original HTML with the now-updated HTML so that it's possible to
Expand Down

0 comments on commit 3985596

Please sign in to comment.