Skip to content

Commit f412732

Browse files
committed
HTML API: Implement active format reconstruction
1 parent 8818c97 commit f412732

2 files changed

Lines changed: 53 additions & 4 deletions

File tree

src/wp-includes/html-api/class-wp-html-active-formatting-elements.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ class WP_HTML_Active_Formatting_Elements {
4343
*/
4444
private $stack = array();
4545

46+
/**
47+
* Returns the node at the given index in the list of active formatting elements.
48+
*
49+
* Do not use this method; it is meant to be used only by the HTML Processor.
50+
*
51+
* @access private
52+
*
53+
* @param int $index Number of nodes from the top node to return.
54+
* @return WP_HTML_Token|null Node at the given index in the stack, if one exists, otherwise null.
55+
*/
56+
public function at( $index ) {
57+
return $this->stack[ $index ];
58+
}
59+
4660
/**
4761
* Reports if a specific node is in the stack of active formatting elements.
4862
*

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

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,15 +1472,19 @@ private function generate_implied_end_tags_thoroughly() {
14721472
* @return bool Whether any formatting elements needed to be reconstructed.
14731473
*/
14741474
private function reconstruct_active_formatting_elements() {
1475+
$count = $this->state->active_formatting_elements->count();
1476+
14751477
/*
14761478
* > If there are no entries in the list of active formatting elements, then there is nothing
14771479
* > to reconstruct; stop this algorithm.
14781480
*/
1479-
if ( 0 === $this->state->active_formatting_elements->count() ) {
1481+
if ( 0 === $count ) {
14801482
return false;
14811483
}
14821484

1483-
$last_entry = $this->state->active_formatting_elements->current_node();
1485+
// Start at the last node in the list of active formatting elements.
1486+
$currently_at = $count - 1;
1487+
$last_entry = $this->state->active_formatting_elements->at( $currently_at );
14841488
if (
14851489

14861490
/*
@@ -1499,8 +1503,39 @@ private function reconstruct_active_formatting_elements() {
14991503
return false;
15001504
}
15011505

1502-
$this->last_error = self::ERROR_UNSUPPORTED;
1503-
throw new WP_HTML_Unsupported_Exception( 'Cannot reconstruct active formatting elements when advancing and rewinding is required.' );
1506+
$entry = $last_entry;
1507+
1508+
while ( $currently_at >= 0 ) {
1509+
if ( 0 === $currently_at ) {
1510+
goto create;
1511+
}
1512+
$entry = $this->state->active_formatting_elements->at( --$currently_at );
1513+
1514+
/*
1515+
* > If entry is neither a marker nor an element that is also in the stack of open elements,
1516+
* > go to the step labeled rewind.
1517+
*/
1518+
if ( 'marker' === $entry->node_name || $this->state->stack_of_open_elements->contains_node( $entry ) ) {
1519+
break;
1520+
}
1521+
}
1522+
1523+
advance:
1524+
$entry = $this->state->active_formatting_elements->at( ++$currently_at );
1525+
1526+
create:
1527+
$this->insert_html_element( $entry );
1528+
1529+
/*
1530+
* > Replace the entry for entry in the list with an entry for new element.
1531+
* This doesn't need to happen here since no DOM is being created.
1532+
*/
1533+
1534+
if ( $count - 1 !== $currently_at ) {
1535+
goto advance;
1536+
}
1537+
1538+
return true;
15041539
}
15051540

15061541
/**

0 commit comments

Comments
 (0)