mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2025-10-16 12:05:38 +00:00
This patch introduces the //first// of //many// iterations on the evolution of the HTML API, the HTML Processor, which is built in order to understand HTML structure including nesting, misnesting, and complicated semantic rules. In the first iteration, the HTML Processor is arbitrarily limited to a minimal subset of functionality so that we can review it, ship it, test it, and collect feedback before moving forward. This means that this patch is more or less an extension to the Tag Processor query language, providing the ability not only to scan for a tag of a given name, but also to find an HTML element in a specific nesting path. The HTML Processor also aborts any time it encounters: - a tag that isn't a `P`, `DIV`, `FIGURE`, `FIGCAPTION`, `IMG`, `STRONG`, `B`, `EM`, `I`, `A`, `BIG`, `CODE`, `FONT`, `SMALL`, `STRIKE`, `TT`, or `U` tag. this limit exists because many HTML elements require specific rules and we are trying to limit the number of rules introduced at once. this work is targeted at existing work in places like the image block. - certain misnesting constructs that evoke complicated resolution inside the HTML spec. where possible and where simple to do reliably, certain parse errors are handled. in most cases the HTML Processor aborts. The structure of the HTML Processor is established in this patch. Further spec-compliance comes through filling out //more of the same// kind and nature of code as is found in this patch. Certain critical HTML algorithms are partially supported, and where support requires more than is present, the HTML Processor acknowledges this and refuses to operate. In this patch are explorations for how to verify that new HTML support is fully added (instead of allowing for partial updates that leave some code paths non-compliant). Performance is hard to measure since support is so limited at the current time, but it should generally follow the performance of the Tag Processor somewhat close as the overhead is minimized as much as practical. Props dmsnell, zieladam, costdev. Fixes #58517. git-svn-id: https://develop.svn.wordpress.org/trunk@56274 602fd350-edb4-49c9-b593-d223f7449a82
366 lines
15 KiB
PHP
366 lines
15 KiB
PHP
<?php
|
|
/**
|
|
* Unit tests for the HTML API indicating that changes are needed to the
|
|
* WP_HTML_Open_Elements class before specific features are added to the API.
|
|
*
|
|
* Note! Duplication of test cases and the helper function in this file are intentional.
|
|
* This test file exists to warn developers of related areas of code that need to update
|
|
* together when adding support for new elements to the HTML Processor. For example,
|
|
* when adding support for the BUTTON element it's necessary to update multiple methods
|
|
* in the class governing the stack of open elements as well as the HTML Processor class
|
|
* itself. This is because each element might bring with it semantic rules that impact
|
|
* the way the document should be parsed. BUTTON creates a kind of boundary in the
|
|
* DOM tree and implicitly closes existing open BUTTON elements.
|
|
*
|
|
* Without these tests a developer needs to investigate all possible places they
|
|
* might need to update when adding support for more elements and risks overlooking
|
|
* important parts that, in the absence of the related support, will lead to errors.
|
|
*
|
|
* @package WordPress
|
|
* @subpackage HTML-API
|
|
*
|
|
* @since 6.4.0
|
|
*
|
|
* @group html-api
|
|
*
|
|
* @coversDefaultClass WP_HTML_Processor
|
|
*/
|
|
class Tests_HtmlApi_wpHtmlSupportRequiredOpenElements extends WP_UnitTestCase {
|
|
/**
|
|
* Fails to assert if the HTML Processor handles the given tag.
|
|
*
|
|
* This test helper is used throughout this test file for one purpose only: to
|
|
* fail a test if the HTML Processor handles the given tag. In other words, it
|
|
* ensures that the HTML Processor aborts when encountering the given tag.
|
|
*
|
|
* This is used to ensure that when support for a new tag is added to the
|
|
* HTML Processor it receives full support and not partial support, which
|
|
* could lead to a variety of issues.
|
|
*
|
|
* Do not remove this helper function as it provides semantic meaning to the
|
|
* assertions in the tests in this file and its behavior is incredibly specific
|
|
* and limited and doesn't warrant adding a new abstraction into WP_UnitTestCase.
|
|
*
|
|
* @param string $tag_name the HTML Processor should abort when encountering this tag, e.g. "BUTTON".
|
|
*/
|
|
private function ensure_support_is_added_everywhere( $tag_name ) {
|
|
$p = WP_HTML_Processor::createFragment( "<$tag_name>" );
|
|
|
|
$this->assertFalse( $p->step(), "Must support terminating elements in specific scope check before adding support for the {$tag_name} element." );
|
|
}
|
|
|
|
/**
|
|
* The check for whether an element is in a scope depends on
|
|
* looking for a number of terminating elements in the stack of open
|
|
* elements. Until the listed elements are supported in the HTML
|
|
* processor, there are no terminating elements and there's no
|
|
* point in taking the time to look for them.
|
|
*
|
|
* @since 6.4.0
|
|
*
|
|
* @ticket 58517
|
|
*/
|
|
public function test_has_element_in_scope_needs_support() {
|
|
// These elements impact all scopes.
|
|
$this->ensure_support_is_added_everywhere( 'APPLET' );
|
|
$this->ensure_support_is_added_everywhere( 'CAPTION' );
|
|
$this->ensure_support_is_added_everywhere( 'HTML' );
|
|
$this->ensure_support_is_added_everywhere( 'TABLE' );
|
|
$this->ensure_support_is_added_everywhere( 'TD' );
|
|
$this->ensure_support_is_added_everywhere( 'TH' );
|
|
$this->ensure_support_is_added_everywhere( 'MARQUEE' );
|
|
$this->ensure_support_is_added_everywhere( 'OBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'TEMPLATE' );
|
|
|
|
// MathML Elements
|
|
$this->ensure_support_is_added_everywhere( 'MI' );
|
|
$this->ensure_support_is_added_everywhere( 'MO' );
|
|
$this->ensure_support_is_added_everywhere( 'MN' );
|
|
$this->ensure_support_is_added_everywhere( 'MS' );
|
|
$this->ensure_support_is_added_everywhere( 'MTEXT' );
|
|
$this->ensure_support_is_added_everywhere( 'ANNOTATION-XML' );
|
|
|
|
/*
|
|
* SVG elements: note that TITLE is both an HTML element and an SVG element
|
|
* so care must be taken when adding support for either one.
|
|
*/
|
|
$this->ensure_support_is_added_everywhere( 'FOREIGNOBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'DESC' );
|
|
$this->ensure_support_is_added_everywhere( 'TITLE' );
|
|
}
|
|
|
|
/**
|
|
* The check for whether an element is in list item scope depends on
|
|
* the elements for any scope, plus UL and OL.
|
|
*
|
|
* The method for asserting list item scope doesn't currently exist
|
|
* because the LI element isn't yet supported and the LI element is
|
|
* the only element that needs to know about list item scope.
|
|
*
|
|
* @since 6.4.0
|
|
*
|
|
* @ticket 58517
|
|
*
|
|
* @covers WP_HTML_Open_Elements::has_element_in_list_item_scope
|
|
*/
|
|
public function test_has_element_in_list_item_scope_needs_support() {
|
|
// These elements impact all scopes.
|
|
$this->ensure_support_is_added_everywhere( 'APPLET' );
|
|
$this->ensure_support_is_added_everywhere( 'CAPTION' );
|
|
$this->ensure_support_is_added_everywhere( 'HTML' );
|
|
$this->ensure_support_is_added_everywhere( 'TABLE' );
|
|
$this->ensure_support_is_added_everywhere( 'TD' );
|
|
$this->ensure_support_is_added_everywhere( 'TH' );
|
|
$this->ensure_support_is_added_everywhere( 'MARQUEE' );
|
|
$this->ensure_support_is_added_everywhere( 'OBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'TEMPLATE' );
|
|
|
|
// MathML Elements
|
|
$this->ensure_support_is_added_everywhere( 'MI' );
|
|
$this->ensure_support_is_added_everywhere( 'MO' );
|
|
$this->ensure_support_is_added_everywhere( 'MN' );
|
|
$this->ensure_support_is_added_everywhere( 'MS' );
|
|
$this->ensure_support_is_added_everywhere( 'MTEXT' );
|
|
$this->ensure_support_is_added_everywhere( 'ANNOTATION-XML' );
|
|
|
|
/*
|
|
* SVG elements: note that TITLE is both an HTML element and an SVG element
|
|
* so care must be taken when adding support for either one.
|
|
*/
|
|
$this->ensure_support_is_added_everywhere( 'FOREIGNOBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'DESC' );
|
|
$this->ensure_support_is_added_everywhere( 'TITLE' );
|
|
|
|
// These elements are specific to list item scope.
|
|
$this->ensure_support_is_added_everywhere( 'OL' );
|
|
$this->ensure_support_is_added_everywhere( 'UL' );
|
|
|
|
// This element is the only element that depends on list item scope.
|
|
$this->ensure_support_is_added_everywhere( 'LI' );
|
|
}
|
|
|
|
/**
|
|
* The check for whether an element is in BUTTON scope depends on
|
|
* the elements for any scope, plus BUTTON.
|
|
*
|
|
* @since 6.4.0
|
|
*
|
|
* @ticket 58517
|
|
*
|
|
* @covers WP_HTML_Open_Elements::has_element_in_button_scope
|
|
*/
|
|
public function test_has_element_in_button_scope_needs_support() {
|
|
// These elements impact all scopes.
|
|
$this->ensure_support_is_added_everywhere( 'APPLET' );
|
|
$this->ensure_support_is_added_everywhere( 'CAPTION' );
|
|
$this->ensure_support_is_added_everywhere( 'HTML' );
|
|
$this->ensure_support_is_added_everywhere( 'TABLE' );
|
|
$this->ensure_support_is_added_everywhere( 'TD' );
|
|
$this->ensure_support_is_added_everywhere( 'TH' );
|
|
$this->ensure_support_is_added_everywhere( 'MARQUEE' );
|
|
$this->ensure_support_is_added_everywhere( 'OBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'TEMPLATE' );
|
|
|
|
// MathML Elements
|
|
$this->ensure_support_is_added_everywhere( 'MI' );
|
|
$this->ensure_support_is_added_everywhere( 'MO' );
|
|
$this->ensure_support_is_added_everywhere( 'MN' );
|
|
$this->ensure_support_is_added_everywhere( 'MS' );
|
|
$this->ensure_support_is_added_everywhere( 'MTEXT' );
|
|
$this->ensure_support_is_added_everywhere( 'ANNOTATION-XML' );
|
|
|
|
/*
|
|
* SVG elements: note that TITLE is both an HTML element and an SVG element
|
|
* so care must be taken when adding support for either one.
|
|
*/
|
|
$this->ensure_support_is_added_everywhere( 'FOREIGNOBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'DESC' );
|
|
$this->ensure_support_is_added_everywhere( 'TITLE' );
|
|
|
|
$this->ensure_support_is_added_everywhere( 'BUTTON' );
|
|
}
|
|
|
|
/**
|
|
* The optimization maintaining a flag for "P is in BUTTON scope" requires
|
|
* updating that flag every time an element is popped from the stack of
|
|
* open elements.
|
|
*
|
|
* @since 6.4.0
|
|
*
|
|
* @ticket 58517
|
|
*
|
|
* @covers WP_HTML_Open_Elements::after_element_pop
|
|
*/
|
|
public function test_after_element_pop_must_maintain_p_in_button_scope_flag() {
|
|
// These elements impact all scopes.
|
|
$this->ensure_support_is_added_everywhere( 'APPLET' );
|
|
$this->ensure_support_is_added_everywhere( 'CAPTION' );
|
|
$this->ensure_support_is_added_everywhere( 'HTML' );
|
|
$this->ensure_support_is_added_everywhere( 'TABLE' );
|
|
$this->ensure_support_is_added_everywhere( 'TD' );
|
|
$this->ensure_support_is_added_everywhere( 'TH' );
|
|
$this->ensure_support_is_added_everywhere( 'MARQUEE' );
|
|
$this->ensure_support_is_added_everywhere( 'OBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'TEMPLATE' );
|
|
|
|
// MathML Elements
|
|
$this->ensure_support_is_added_everywhere( 'MI' );
|
|
$this->ensure_support_is_added_everywhere( 'MO' );
|
|
$this->ensure_support_is_added_everywhere( 'MN' );
|
|
$this->ensure_support_is_added_everywhere( 'MS' );
|
|
$this->ensure_support_is_added_everywhere( 'MTEXT' );
|
|
$this->ensure_support_is_added_everywhere( 'ANNOTATION-XML' );
|
|
|
|
/*
|
|
* SVG elements: note that TITLE is both an HTML element and an SVG element
|
|
* so care must be taken when adding support for either one.
|
|
*/
|
|
$this->ensure_support_is_added_everywhere( 'FOREIGNOBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'DESC' );
|
|
$this->ensure_support_is_added_everywhere( 'TITLE' );
|
|
|
|
// This element is specific to BUTTON scope.
|
|
$this->ensure_support_is_added_everywhere( 'BUTTON' );
|
|
}
|
|
|
|
/**
|
|
* The optimization maintaining a flag for "P is in BUTTON scope" requires
|
|
* updating that flag every time an element is pushed onto the stack of
|
|
* open elements.
|
|
*
|
|
* @since 6.4.0
|
|
*
|
|
* @ticket 58517
|
|
*
|
|
* @covers WP_HTML_Open_Elements::after_element_push
|
|
*/
|
|
public function test_after_element_push_must_maintain_p_in_button_scope_flag() {
|
|
// These elements impact all scopes.
|
|
$this->ensure_support_is_added_everywhere( 'APPLET' );
|
|
$this->ensure_support_is_added_everywhere( 'CAPTION' );
|
|
$this->ensure_support_is_added_everywhere( 'HTML' );
|
|
$this->ensure_support_is_added_everywhere( 'TABLE' );
|
|
$this->ensure_support_is_added_everywhere( 'TD' );
|
|
$this->ensure_support_is_added_everywhere( 'TH' );
|
|
$this->ensure_support_is_added_everywhere( 'MARQUEE' );
|
|
$this->ensure_support_is_added_everywhere( 'OBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'TEMPLATE' );
|
|
|
|
// MathML Elements
|
|
$this->ensure_support_is_added_everywhere( 'MI' );
|
|
$this->ensure_support_is_added_everywhere( 'MO' );
|
|
$this->ensure_support_is_added_everywhere( 'MN' );
|
|
$this->ensure_support_is_added_everywhere( 'MS' );
|
|
$this->ensure_support_is_added_everywhere( 'MTEXT' );
|
|
$this->ensure_support_is_added_everywhere( 'ANNOTATION-XML' );
|
|
|
|
/*
|
|
* SVG elements: note that TITLE is both an HTML element and an SVG element
|
|
* so care must be taken when adding support for either one.
|
|
*/
|
|
$this->ensure_support_is_added_everywhere( 'FOREIGNOBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'DESC' );
|
|
$this->ensure_support_is_added_everywhere( 'TITLE' );
|
|
|
|
$this->ensure_support_is_added_everywhere( 'BUTTON' );
|
|
}
|
|
|
|
/**
|
|
* The check for whether an element is in TABLE scope depends on
|
|
* the HTML, TABLE, and TEMPLATE elements.
|
|
*
|
|
* @since 6.4.0
|
|
*
|
|
* @ticket 58517
|
|
*
|
|
* @covers WP_HTML_Open_Elements::has_element_in_table_scope
|
|
*/
|
|
public function test_has_element_in_table_scope_needs_support() {
|
|
// These elements impact all scopes.
|
|
$this->ensure_support_is_added_everywhere( 'APPLET' );
|
|
$this->ensure_support_is_added_everywhere( 'CAPTION' );
|
|
$this->ensure_support_is_added_everywhere( 'HTML' );
|
|
$this->ensure_support_is_added_everywhere( 'TABLE' );
|
|
$this->ensure_support_is_added_everywhere( 'TD' );
|
|
$this->ensure_support_is_added_everywhere( 'TH' );
|
|
$this->ensure_support_is_added_everywhere( 'MARQUEE' );
|
|
$this->ensure_support_is_added_everywhere( 'OBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'TEMPLATE' );
|
|
|
|
// MathML Elements
|
|
$this->ensure_support_is_added_everywhere( 'MI' );
|
|
$this->ensure_support_is_added_everywhere( 'MO' );
|
|
$this->ensure_support_is_added_everywhere( 'MN' );
|
|
$this->ensure_support_is_added_everywhere( 'MS' );
|
|
$this->ensure_support_is_added_everywhere( 'MTEXT' );
|
|
$this->ensure_support_is_added_everywhere( 'ANNOTATION-XML' );
|
|
|
|
/*
|
|
* SVG elements: note that TITLE is both an HTML element and an SVG element
|
|
* so care must be taken when adding support for either one.
|
|
*/
|
|
$this->ensure_support_is_added_everywhere( 'FOREIGNOBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'DESC' );
|
|
$this->ensure_support_is_added_everywhere( 'TITLE' );
|
|
|
|
// These elements are specific to TABLE scope.
|
|
$this->ensure_support_is_added_everywhere( 'HTML' );
|
|
$this->ensure_support_is_added_everywhere( 'TABLE' );
|
|
$this->ensure_support_is_added_everywhere( 'TEMPLATE' );
|
|
|
|
// These elements depend on table scope.
|
|
$this->ensure_support_is_added_everywhere( 'CAPTION' );
|
|
$this->ensure_support_is_added_everywhere( 'COL' );
|
|
$this->ensure_support_is_added_everywhere( 'COLGROUP' );
|
|
$this->ensure_support_is_added_everywhere( 'TBODY' );
|
|
$this->ensure_support_is_added_everywhere( 'TD' );
|
|
$this->ensure_support_is_added_everywhere( 'TFOOT' );
|
|
$this->ensure_support_is_added_everywhere( 'TH' );
|
|
$this->ensure_support_is_added_everywhere( 'THEAD' );
|
|
$this->ensure_support_is_added_everywhere( 'TR' );
|
|
}
|
|
|
|
/**
|
|
* The check for whether an element is in SELECT scope depends on
|
|
* the OPTGROUP and OPTION elements.
|
|
*
|
|
* @since 6.4.0
|
|
*
|
|
* @ticket 58517
|
|
*
|
|
* @covers WP_HTML_Open_Elements::has_element_in_select_scope
|
|
*/
|
|
public function test_has_element_in_select_scope_needs_support() {
|
|
// These elements impact all scopes.
|
|
$this->ensure_support_is_added_everywhere( 'APPLET' );
|
|
$this->ensure_support_is_added_everywhere( 'CAPTION' );
|
|
$this->ensure_support_is_added_everywhere( 'HTML' );
|
|
$this->ensure_support_is_added_everywhere( 'TABLE' );
|
|
$this->ensure_support_is_added_everywhere( 'TD' );
|
|
$this->ensure_support_is_added_everywhere( 'TH' );
|
|
$this->ensure_support_is_added_everywhere( 'MARQUEE' );
|
|
$this->ensure_support_is_added_everywhere( 'OBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'TEMPLATE' );
|
|
|
|
// MathML Elements
|
|
$this->ensure_support_is_added_everywhere( 'MI' );
|
|
$this->ensure_support_is_added_everywhere( 'MO' );
|
|
$this->ensure_support_is_added_everywhere( 'MN' );
|
|
$this->ensure_support_is_added_everywhere( 'MS' );
|
|
$this->ensure_support_is_added_everywhere( 'MTEXT' );
|
|
$this->ensure_support_is_added_everywhere( 'ANNOTATION-XML' );
|
|
|
|
/*
|
|
* SVG elements: note that TITLE is both an HTML element and an SVG element
|
|
* so care must be taken when adding support for either one.
|
|
*/
|
|
$this->ensure_support_is_added_everywhere( 'FOREIGNOBJECT' );
|
|
$this->ensure_support_is_added_everywhere( 'DESC' );
|
|
$this->ensure_support_is_added_everywhere( 'TITLE' );
|
|
|
|
// These elements are specific to SELECT scope.
|
|
$this->ensure_support_is_added_everywhere( 'OPTGROUP' );
|
|
$this->ensure_support_is_added_everywhere( 'OPTION' );
|
|
}
|
|
}
|