Make WordPress Core

Changeset 57649

Timestamp:
02/17/2024 03:26:43 PM (5 months ago)
Author:
swissspidy
Message:

Interactivity API: Skip instead of bail out if HTML contains SVG or MATH.

Addresses an issue with server-side processing of directives when there is e.g. an SVG icon a navigation menu.

Props cbravobernal, westonruter, dmsnell, swissspidy.
Fixes #60517.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/interactivity-api/class-wp-interactivity-api-directives-processor.php

    r57563 r57649  
    182182
    183183    /**
     184
     185
     186
     187
     188
     189
     190
     191
     192
     193
     194
     195
     196
     197
     198
     199
     200
     201
     202
     203
     204
     205
     206
     207
     208
     209
     210
     211
     212
     213
     214
     215
     216
    184217     * Finds the matching closing tag for an opening tag.
    185218     *
  • trunk/src/wp-includes/interactivity-api/class-wp-interactivity-api.php

    r57646 r57649  
    236236            $tag_name = $p->get_tag();
    237237
     238
     239
     240
     241
     242
    238243            if ( 'SVG' === $tag_name || 'MATH' === $tag_name ) {
    239                 $unbalanced = true;
    240                 break;
     244                $;
     245                ;
    241246            }
    242247
  • trunk/tests/phpunit/tests/interactivity-api/wpInteractivityAPI.php

    r57563 r57649  
    1212 * @coversDefaultClass WP_Interactivity_API
    1313 */
    14 class Tests_WP_Interactivity_API extends WP_UnitTestCase {
     14class Tests_API extends WP_UnitTestCase {
    1515    /**
    1616     * Instance of WP_Interactivity_API.
     
    509509
    510510    /**
    511      * Tests that the `process_directives` returns the same HTML if it finds an
    512      * SVG tag.
    513      *
    514      * @ticket 60356
    515      *
    516      * @covers ::process_directives
    517      */
    518     public function test_process_directives_doesnt_change_html_if_contains_svgs() {
    519         $this->interactivity->state( 'myPlugin', array( 'id' => 'some-id' ) );
     511     * Tests that the `process_directives` process the HTML outside a SVG tag.
     512     *
     513     * @ticket 60517
     514     *
     515     * @covers ::process_directives
     516     */
     517    public function test_process_directives_changes_html_if_contains_svgs() {
     518        $this->interactivity->state(
     519            'myPlugin',
     520            array(
     521                'id'    => 'some-id',
     522                'width' => '100',
     523            )
     524        );
    520525        $html           = '
    521             <div data-wp-bind--id="myPlugin::state.id">
    522                 <svg height="100" width="100">
     526            <header>
     527                <svg height="100" data-wp-bind--width="myPlugin::state.width">
     528                    <title>Red Circle</title>
    523529                    <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
    524                 </svg>
    525             </div>
     530                </svg>
     531                <div data-wp-bind--id="myPlugin::state.id"></div>
     532                <div data-wp-bind--id="myPlugin::state.width"></div>
     533            </header>
    526534        ';
    527535        $processed_html = $this->interactivity->process_directives( $html );
    528536        $p              = new WP_HTML_Tag_Processor( $processed_html );
    529         $p->next_tag();
     537        $p->next_tag( 'svg' );
     538        $this->assertNull( $p->get_attribute( 'width' ) );
     539        $p->next_tag( 'div' );
     540        $this->assertEquals( 'some-id', $p->get_attribute( 'id' ) );
     541        $p->next_tag( 'div' );
     542        $this->assertEquals( '100', $p->get_attribute( 'id' ) );
     543    }
     544
     545    /**
     546     * Tests that the `process_directives` does not process the HTML
     547     * inside SVG tags.
     548     *
     549     * @ticket 60517
     550     *
     551     * @covers ::process_directives
     552     */
     553    public function test_process_directives_does_not_change_inner_html_in_svgs() {
     554        $this->interactivity->state(
     555            'myPlugin',
     556            array(
     557                'id' => 'some-id',
     558            )
     559        );
     560        $html           = '
     561            <header>
     562                <svg height="100">
     563                    <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
     564                    <g data-wp-bind--id="myPlugin::state.id" />
     565                </svg>
     566            </header>
     567        ';
     568        $processed_html = $this->interactivity->process_directives( $html );
     569        $p              = new WP_HTML_Tag_Processor( $processed_html );
     570        $p->next_tag( 'div' );
    530571        $this->assertNull( $p->get_attribute( 'id' ) );
    531572    }
    532573
    533574    /**
    534      * Tests that the `process_directives` returns the same HTML if it finds an
     575     * Tests that the `process_directives`
    535576     * MathML tag.
    536577     *
    537      * @ticket 60356
    538      *
    539      * @covers ::process_directives
    540      */
    541     public function test_process_directives_doesnt_change_html_if_contains_math() {
    542         $this->interactivity->state( 'myPlugin', array( 'id' => 'some-id' ) );
     578     * @ticket 60517
     579     *
     580     * @covers ::process_directives
     581     */
     582    public function test_process_directives_change_html_if_contains_math() {
     583        $this->interactivity->state(
     584            'myPlugin',
     585            array(
     586                'id'   => 'some-id',
     587                'math' => 'ml-id',
     588            )
     589        );
    543590        $html           = '
    544             <div data-wp-bind--id="myPlugin::state.id">
    545                 <math>
     591            <>
     592                <math>
    546593                    <mi>x</mi>
    547594                    <mo>=</mo>
    548595                    <mi>1</mi>
    549596                </math>
    550             </div>
     597                <div data-wp-bind--id="myPlugin::state.id"></div>
     598            </header>
    551599        ';
    552600        $processed_html = $this->interactivity->process_directives( $html );
    553601        $p              = new WP_HTML_Tag_Processor( $processed_html );
    554         $p->next_tag();
     602        $p->next_tag( 'math' );
     603        $this->assertNull( $p->get_attribute( 'id' ) );
     604        $p->next_tag( 'div' );
     605        $this->assertEquals( 'some-id', $p->get_attribute( 'id' ) );
     606    }
     607
     608    /**
     609     * Tests that the `process_directives` does not process the HTML
     610     * inside MathML tags.
     611     *
     612     * @ticket 60517
     613     *
     614     * @covers ::process_directives
     615     */
     616    public function test_process_directives_does_not_change_inner_html_in_math() {
     617        $this->interactivity->state(
     618            'myPlugin',
     619            array(
     620                'id' => 'some-id',
     621            )
     622        );
     623        $html           = '
     624            <header>
     625                <math data-wp-bind--id="myPlugin::state.math">
     626                    <mrow data-wp-bind--id="myPlugin::state.id" />
     627                    <mi>x</mi>
     628                    <mo>=</mo>
     629                    <mi>1</mi>
     630                </math>
     631            </header>
     632        ';
     633        $processed_html = $this->interactivity->process_directives( $html );
     634        $p              = new WP_HTML_Tag_Processor( $processed_html );
     635        $p->next_tag( 'div' );
    555636        $this->assertNull( $p->get_attribute( 'id' ) );
    556637    }
  • trunk/tests/phpunit/tests/interactivity-api/wpInteractivityAPIDirectivesProcessor.php

    r57563 r57649  
    1212 * @coversDefaultClass WP_Interactivity_API_Directives_Processor
    1313 */
    14 class Tests_WP_Interactivity_API_Directives_Processor extends WP_UnitTestCase {
     14class Tests_Processor extends WP_UnitTestCase {
    1515    /**
    1616     * Tests the `get_content_between_balanced_template_tags` method on template
     
    779779        $this->assertFalse( $p->next_balanced_tag_closer_tag() );
    780780    }
     781
     782
     783
     784
     785
     786
     787
     788
     789
     790
     791
     792
     793
     794
     795
     796
     797
     798
     799
     800
     801
     802
     803
     804
     805
     806
     807
     808
     809
     810
     811
     812
     813
     814
     815
     816
     817
     818
     819
     820
     821
     822
     823
     824
     825
     826
     827
    781828}
Note: See TracChangeset for help on using the changeset viewer.