Make WordPress Core


Ignore:
Timestamp:
08/08/2024 07:23:53 AM (15 months ago)
Author:
dmsnell
Message:

HTML API: Add support for SVG and MathML (Foreign content)

As part of work to add more spec support to the HTML API, this patch adds
support for SVG and MathML elements, or more generally, "foreign content."

The rules in foreign content are a mix of XML and HTML parsing rules and
introduce additional complexity into the processor, but is important in
order to avoid getting lost when inside these elements.

Developed in https://github.com/wordpress/wordpress-develop/pull/6006
Discussed in https://core.trac.wordpress.org/ticket/61576

Props: dmsnell, jonsurrell, westonruter.
See #61576.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/html-api/wpHtmlSupportRequiredOpenElements.php

    r58779 r58867  
    1 <?php
    2 /**
    3  * Unit tests for the HTML API indicating that changes are needed to the
    4  * WP_HTML_Open_Elements class before specific features are added to the API.
    5  *
    6  * Note! Duplication of test cases and the helper function in this file are intentional.
    7  * This test file exists to warn developers of related areas of code that need to update
    8  * together when adding support for new elements to the HTML Processor. For example,
    9  * when adding support for the BUTTON element it's necessary to update multiple methods
    10  * in the class governing the stack of open elements as well as the HTML Processor class
    11  * itself. This is because each element might bring with it semantic rules that impact
    12  * the way the document should be parsed. BUTTON creates a kind of boundary in the
    13  * DOM tree and implicitly closes existing open BUTTON elements.
    14  *
    15  * Without these tests a developer needs to investigate all possible places they
    16  * might need to update when adding support for more elements and risks overlooking
    17  * important parts that, in the absence of the related support, will lead to errors.
    18  *
    19  * @package WordPress
    20  * @subpackage HTML-API
    21  *
    22  * @since 6.4.0
    23  *
    24  * @group html-api
    25  *
    26  * @coversDefaultClass WP_HTML_Processor
    27  */
    28 class Tests_HtmlApi_WpHtmlSupportRequiredOpenElements extends WP_UnitTestCase {
    29     /**
    30      * Fails to assert if the HTML Processor handles the given tag.
    31      *
    32      * This test helper is used throughout this test file for one purpose only: to
    33      * fail a test if the HTML Processor handles the given tag. In other words, it
    34      * ensures that the HTML Processor aborts when encountering the given tag.
    35      *
    36      * This is used to ensure that when support for a new tag is added to the
    37      * HTML Processor it receives full support and not partial support, which
    38      * could lead to a variety of issues.
    39      *
    40      * Do not remove this helper function as it provides semantic meaning to the
    41      * assertions in the tests in this file and its behavior is incredibly specific
    42      * and limited and doesn't warrant adding a new abstraction into WP_UnitTestCase.
    43      *
    44      * @param string $tag_name the HTML Processor should abort when encountering this tag, e.g. "BUTTON".
    45      */
    46     private function ensure_support_is_added_everywhere( $tag_name ) {
    47         $processor = WP_HTML_Processor::create_fragment( "<$tag_name>" );
    48 
    49         $this->assertFalse( $processor->step(), "Must support terminating elements in specific scope check before adding support for the {$tag_name} element." );
    50     }
    51 
    52     /**
    53      * The check for whether an element is in a scope depends on
    54      * looking for a number of terminating elements in the stack of open
    55      * elements. Until the listed elements are supported in the HTML
    56      * processor, there are no terminating elements and there's no
    57      * point in taking the time to look for them.
    58      *
    59      * @since 6.4.0
    60      *
    61      * @ticket 58517
    62      */
    63     public function test_has_element_in_scope_needs_support() {
    64         // MathML Elements: MI, MO, MN, MS, MTEXT, ANNOTATION-XML.
    65         $this->ensure_support_is_added_everywhere( 'MATH' );
    66 
    67         /*
    68          * SVG elements: note that TITLE is both an HTML element and an SVG element
    69          * so care must be taken when adding support for either one.
    70          *
    71          * FOREIGNOBJECT, DESC, TITLE.
    72          */
    73         $this->ensure_support_is_added_everywhere( 'SVG' );
    74     }
    75 
    76     /**
    77      * The check for whether an element is in list item scope depends on
    78      * the elements for any scope, plus UL and OL.
    79      *
    80      * The method for asserting list item scope doesn't currently exist
    81      * because the LI element isn't yet supported and the LI element is
    82      * the only element that needs to know about list item scope.
    83      *
    84      * @since 6.4.0
    85      *
    86      * @ticket 58517
    87      *
    88      * @covers WP_HTML_Open_Elements::has_element_in_list_item_scope
    89      */
    90     public function test_has_element_in_list_item_scope_needs_support() {
    91         // MathML Elements: MI, MO, MN, MS, MTEXT, ANNOTATION-XML.
    92         $this->ensure_support_is_added_everywhere( 'MATH' );
    93 
    94         /*
    95          * SVG elements: note that TITLE is both an HTML element and an SVG element
    96          * so care must be taken when adding support for either one.
    97          *
    98          * FOREIGNOBJECT, DESC, TITLE.
    99          */
    100         $this->ensure_support_is_added_everywhere( 'SVG' );
    101     }
    102 
    103     /**
    104      * The check for whether an element is in BUTTON scope depends on
    105      * the elements for any scope, plus BUTTON.
    106      *
    107      * @since 6.4.0
    108      *
    109      * @ticket 58517
    110      *
    111      * @covers WP_HTML_Open_Elements::has_element_in_button_scope
    112      */
    113     public function test_has_element_in_button_scope_needs_support() {
    114         // MathML Elements: MI, MO, MN, MS, MTEXT, ANNOTATION-XML.
    115         $this->ensure_support_is_added_everywhere( 'MATH' );
    116 
    117         /*
    118          * SVG elements: note that TITLE is both an HTML element and an SVG element
    119          * so care must be taken when adding support for either one.
    120          *
    121          * FOREIGNOBJECT, DESC, TITLE.
    122          */
    123         $this->ensure_support_is_added_everywhere( 'SVG' );
    124     }
    125 
    126     /**
    127      * The optimization maintaining a flag for "P is in BUTTON scope" requires
    128      * updating that flag every time an element is popped from the stack of
    129      * open elements.
    130      *
    131      * @since 6.4.0
    132      *
    133      * @ticket 58517
    134      *
    135      * @covers WP_HTML_Open_Elements::after_element_pop
    136      */
    137     public function test_after_element_pop_must_maintain_p_in_button_scope_flag() {
    138         // MathML Elements: MI, MO, MN, MS, MTEXT, ANNOTATION-XML.
    139         $this->ensure_support_is_added_everywhere( 'MATH' );
    140 
    141         /*
    142          * SVG elements: note that TITLE is both an HTML element and an SVG element
    143          * so care must be taken when adding support for either one.
    144          *
    145          * FOREIGNOBJECT, DESC, TITLE.
    146          */
    147         $this->ensure_support_is_added_everywhere( 'SVG' );
    148     }
    149 
    150     /**
    151      * The optimization maintaining a flag for "P is in BUTTON scope" requires
    152      * updating that flag every time an element is pushed onto the stack of
    153      * open elements.
    154      *
    155      * @since 6.4.0
    156      *
    157      * @ticket 58517
    158      *
    159      * @covers WP_HTML_Open_Elements::after_element_push
    160      */
    161     public function test_after_element_push_must_maintain_p_in_button_scope_flag() {
    162         // MathML Elements: MI, MO, MN, MS, MTEXT, ANNOTATION-XML.
    163         $this->ensure_support_is_added_everywhere( 'MATH' );
    164 
    165         /*
    166          * SVG elements: note that TITLE is both an HTML element and an SVG element
    167          * so care must be taken when adding support for either one.
    168          *
    169          * FOREIGNOBJECT, DESC, TITLE.
    170          */
    171         $this->ensure_support_is_added_everywhere( 'SVG' );
    172     }
    173 
    174     /**
    175      * The check for whether an element is in TABLE scope depends on
    176      * the HTML, TABLE, and TEMPLATE elements.
    177      *
    178      * @since 6.4.0
    179      *
    180      * @ticket 58517
    181      *
    182      * @covers WP_HTML_Open_Elements::has_element_in_table_scope
    183      */
    184     public function test_has_element_in_table_scope_needs_support() {
    185         // MathML Elements: MI, MO, MN, MS, MTEXT, ANNOTATION-XML.
    186         $this->ensure_support_is_added_everywhere( 'MATH' );
    187 
    188         /*
    189          * SVG elements: note that TITLE is both an HTML element and an SVG element
    190          * so care must be taken when adding support for either one.
    191          *
    192          * FOREIGNOBJECT, DESC, TITLE.
    193          */
    194         $this->ensure_support_is_added_everywhere( 'SVG' );
    195     }
    196 
    197     /**
    198      * The check for whether an element is in SELECT scope depends on
    199      * the OPTGROUP and OPTION elements.
    200      *
    201      * @since 6.4.0
    202      *
    203      * @ticket 58517
    204      *
    205      * @covers WP_HTML_Open_Elements::has_element_in_select_scope
    206      */
    207     public function test_has_element_in_select_scope_needs_support() {
    208         // MathML Elements: MI, MO, MN, MS, MTEXT, ANNOTATION-XML.
    209         $this->ensure_support_is_added_everywhere( 'MATH' );
    210 
    211         /*
    212          * SVG elements: note that TITLE is both an HTML element and an SVG element
    213          * so care must be taken when adding support for either one.
    214          *
    215          * FOREIGNOBJECT, DESC, TITLE.
    216          */
    217         $this->ensure_support_is_added_everywhere( 'SVG' );
    218     }
    219 }
Note: See TracChangeset for help on using the changeset viewer.