diff --git a/composer.json b/composer.json index 46cc81b28acb2..10873fcee5c3b 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,9 @@ "require": { "php": ">=7.0" }, + "suggest": { + "ext-dom": "*" + }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", "squizlabs/php_codesniffer": "3.6.0", diff --git a/src/wp-includes/class-wp-customize-manager.php b/src/wp-includes/class-wp-customize-manager.php index 0bceee3454224..aebcfeb892dfb 100644 --- a/src/wp-includes/class-wp-customize-manager.php +++ b/src/wp-includes/class-wp-customize-manager.php @@ -464,6 +464,8 @@ protected function wp_die( $ajax_message, $message = null ) { ), 'error' => $ajax_message, ); + $message .= ob_get_clean(); + ob_start(); ?> ', '' ), '', ob_get_clean() ) ); } wp_die( $message ); @@ -2083,6 +2085,7 @@ public function remove_frameless_preview_messenger_channel() { if ( ! $this->messenger_channel ) { return; } + ob_start(); ?> ', '' ), '', ob_get_clean() ) ); } /** @@ -2201,8 +2205,9 @@ public function customize_preview_settings() { } } + ob_start(); ?> - ', '' ), '', ob_get_clean() ) ); } /** @@ -4976,8 +4982,9 @@ public function customize_pane_settings() { } } + ob_start(); ?> - ', '' ), '', ob_get_clean() ) ); } /** diff --git a/src/wp-includes/class-wp-customize-nav-menus.php b/src/wp-includes/class-wp-customize-nav-menus.php index bbda8b51b3795..20f88f8440fc7 100644 --- a/src/wp-includes/class-wp-customize-nav-menus.php +++ b/src/wp-includes/class-wp-customize-nav-menus.php @@ -1559,7 +1559,7 @@ public function export_preview_data() { $exports = array( 'navMenuInstanceArgs' => $this->preview_nav_menu_instance_args, ); - printf( '', wp_json_encode( $exports ) ); + wp_print_inline_script_tag( sprintf( 'var _wpCustomizePreviewNavMenusExports = %s;', wp_json_encode( $exports ) ) ); } /** diff --git a/src/wp-includes/class-wp-customize-widgets.php b/src/wp-includes/class-wp-customize-widgets.php index 93006ef91671e..c8a00c741ff8a 100644 --- a/src/wp-includes/class-wp-customize-widgets.php +++ b/src/wp-includes/class-wp-customize-widgets.php @@ -1310,12 +1310,9 @@ public function export_preview_data() { foreach ( $settings['registeredWidgets'] as &$registered_widget ) { unset( $registered_widget['callback'] ); // May not be JSON-serializeable. } - - ?> - - type_attr = " type='text/javascript'"; - } - /** * Fires when the WP_Scripts instance is initialized. * @@ -245,20 +226,7 @@ public function print_extra_script( $handle, $display = true ) { return $output; } - printf( "\n", $this->type_attr, esc_attr( $handle ) ); - - // CDATA is not needed for HTML 5. - if ( $this->type_attr ) { - echo "/* type_attr ) { - echo "/* ]]> */\n"; - } - - echo "\n"; + wp_print_inline_script_tag( $output, array( 'id' => "{$handle}-js-extra" ) ); return true; } @@ -335,7 +303,7 @@ public function do_item( $handle, $group = false ) { $translations = $this->print_translations( $handle, false ); if ( $translations ) { - $translations = sprintf( "\n%s\n\n", $this->type_attr, esc_attr( $handle ), $translations ); + $translations = wp_get_inline_script_tag( $translations, array( 'id' => "{$handle}-js-translations" ) ); } if ( $this->do_concat ) { @@ -403,21 +371,24 @@ public function do_item( $handle, $group = false ) { } /** This filter is documented in wp-includes/class-wp-scripts.php */ - $src = esc_url( apply_filters( 'script_loader_src', $src, $handle ) ); + $src = esc_url_raw( apply_filters( 'script_loader_src', $src, $handle ) ); if ( ! $src ) { return true; } - $tag = $translations . $cond_before . $before_script; - $tag .= sprintf( - "\n", - $this->type_attr, - $src, // Value is escaped above. - esc_attr( $handle ), - $strategy ? " {$strategy}" : '', - $intended_strategy ? " data-wp-strategy='{$intended_strategy}'" : '' + $attr = array( + 'src' => $src, + 'id' => "{$handle}-js", ); + if ( $strategy ) { + $attr[ $strategy ] = true; + } + if ( $intended_strategy ) { + $attr['data-wp-strategy'] = $intended_strategy; + } + $tag = $translations . $cond_before . $before_script; + $tag .= wp_get_script_tag( $attr ); $tag .= $after_script . $cond_after; /** @@ -720,7 +691,7 @@ public function print_translations( $handle, $display = true ) { JS; if ( $display ) { - printf( "\n%s\n\n", $this->type_attr, esc_attr( $handle ), $output ); + wp_print_inline_script_tag( $output, array( 'id' => "{$handle}-js-translations" ) ); } return $output; diff --git a/src/wp-includes/comment-template.php b/src/wp-includes/comment-template.php index a80dc60e41fd6..a1005d56e2393 100644 --- a/src/wp-includes/comment-template.php +++ b/src/wp-includes/comment-template.php @@ -1366,7 +1366,7 @@ function wp_comment_form_unfiltered_html_nonce() { if ( current_user_can( 'unfiltered_html' ) ) { wp_nonce_field( 'unfiltered-html-comment_' . $post_id, '_wp_unfiltered_html_comment_disabled', false ); - echo "\n"; + wp_print_inline_script_tag( "(function(){if(window===window.parent){document.getElementById('_wp_unfiltered_html_comment_disabled').name='_wp_unfiltered_html_comment';}})();" ); } } diff --git a/src/wp-includes/customize/class-wp-customize-selective-refresh.php b/src/wp-includes/customize/class-wp-customize-selective-refresh.php index f75baff3e4af0..d20e8ab0a76ad 100644 --- a/src/wp-includes/customize/class-wp-customize-selective-refresh.php +++ b/src/wp-includes/customize/class-wp-customize-selective-refresh.php @@ -193,7 +193,7 @@ public function export_preview_data() { ); // Export data to JS. - printf( '', wp_json_encode( $exports ) ); + wp_print_inline_script_tag( sprintf( 'var _customizePartialRefreshExports = %s;', wp_json_encode( $exports ) ) ); } /** diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index ab49f8f405e7a..a86d8eaa274d6 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -7655,6 +7655,7 @@ function wp_post_preview_js() { // Has to match the window name used in post_submit_meta_box(). $name = 'wp-preview-' . (int) $post->ID; + ob_start(); ?> ', '' ), '', ob_get_clean() ) ); } /** diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index b039536c1d8b7..299f99815d00c 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -2797,7 +2797,11 @@ function wp_sanitize_script_attributes( $attributes ) { */ function wp_get_script_tag( $attributes ) { if ( ! isset( $attributes['type'] ) && ! is_admin() && ! current_theme_supports( 'html5', 'script' ) ) { - $attributes['type'] = 'text/javascript'; + // Keep the type attribute as the first for legacy reasons (it has always been this way in core). + $attributes = array_merge( + array( 'type' => 'text/javascript' ), + $attributes + ); } /** * Filters attributes to be added to a script tag. @@ -2840,9 +2844,23 @@ function wp_print_script_tag( $attributes ) { * @return string String containing inline JavaScript code wrapped around `\n", wp_sanitize_script_attributes( $attributes ), $javascript ); } diff --git a/src/wp-includes/theme-templates.php b/src/wp-includes/theme-templates.php index 3604dc6dbea1b..8f0ee9a69f448 100644 --- a/src/wp-includes/theme-templates.php +++ b/src/wp-includes/theme-templates.php @@ -160,8 +160,9 @@ function the_block_template_skip_link() { wp_enqueue_style( $handle ); /** - * Print the skip-link script. + * Enqueue the skip-link script. */ + ob_start(); ?> ', '' ), '', ob_get_clean() ); + $script_handle = 'wp-block-template-skip-link'; + wp_register_script( $script_handle, false ); + wp_add_inline_script( $script_handle, $skip_link_script ); + wp_enqueue_script( $script_handle ); } /** diff --git a/src/wp-includes/theme.php b/src/wp-includes/theme.php index 6be2ad700aeb3..ba88a83fded1a 100644 --- a/src/wp-includes/theme.php +++ b/src/wp-includes/theme.php @@ -3783,9 +3783,9 @@ function wp_customize_support_script() { $admin_origin = parse_url( admin_url() ); $home_origin = parse_url( home_url() ); $cross_domain = ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) ); - $type_attr = current_theme_supports( 'html5', 'script' ) ? '' : ' type="text/javascript"'; + ob_start(); ?> - > + ', '' ), '', ob_get_clean() ) ); } /** diff --git a/src/wp-includes/widgets/class-wp-widget-archives.php b/src/wp-includes/widgets/class-wp-widget-archives.php index f32aa9bbb0254..21d3a7b67293a 100644 --- a/src/wp-includes/widgets/class-wp-widget-archives.php +++ b/src/wp-includes/widgets/class-wp-widget-archives.php @@ -100,8 +100,6 @@ public function widget( $args, $instance ) { $label = __( 'Select Post' ); break; } - - $type_attr = current_theme_supports( 'html5', 'script' ) ? '' : ' type="text/javascript"'; ?> @@ -109,8 +107,8 @@ public function widget( $args, $instance ) { -> -/* + ', '' ), '', ob_get_clean() ) ); } else { $format = current_theme_supports( 'html5', 'navigation-widgets' ) ? 'html5' : 'xhtml'; diff --git a/src/wp-includes/widgets/class-wp-widget-categories.php b/src/wp-includes/widgets/class-wp-widget-categories.php index 3c009709ba9f5..e00ce7f9605a3 100644 --- a/src/wp-includes/widgets/class-wp-widget-categories.php +++ b/src/wp-includes/widgets/class-wp-widget-categories.php @@ -92,11 +92,10 @@ public function widget( $args, $instance ) { echo ''; - $type_attr = current_theme_supports( 'html5', 'script' ) ? '' : ' type="text/javascript"'; + ob_start(); ?> -> -/* (function() { var dropdown = document.getElementById( "" ); function onCatChange() { @@ -106,10 +105,10 @@ function onCatChange() { } dropdown.onchange = onCatChange; })(); -/* ]]> */ ', '' ), '', ob_get_clean() ) ); } else { $format = current_theme_supports( 'html5', 'navigation-widgets' ) ? 'html5' : 'xhtml'; diff --git a/src/wp-login.php b/src/wp-login.php index 60877bdb702d7..80887f042084f 100644 --- a/src/wp-login.php +++ b/src/wp-login.php @@ -101,9 +101,11 @@ function login_header( $title = 'Log In', $message = '', $wp_error = null ) { * but maybe better if it's not removable by plugins. */ if ( 'loggedout' === $wp_error->get_error_code() ) { + ob_start(); ?> ', '' ), '', ob_get_clean() ) ); } /** @@ -193,9 +195,10 @@ function login_header( $title = 'Log In', $message = '', $wp_error = null ) { ?> - + + - ', '' ), '', ob_get_clean() ) ); } /** @@ -441,11 +446,7 @@ function login_footer( $input_id = '' ) { * @since 3.0.0 */ function wp_shake_js() { - ?> - - - + ', '' ), '', ob_get_clean() ) ); } ?> @@ -1605,15 +1608,12 @@ function wp_login_viewport_meta() { // Run `wpOnload()` if defined. $login_script .= "if ( typeof wpOnload === 'function' ) { wpOnload() }"; - ?> - - - ', '' ), '', ob_get_clean() ) ); } login_footer(); diff --git a/tests/phpunit/tests/customize/manager.php b/tests/phpunit/tests/customize/manager.php index 4a64db964d8ee..d375bff3f6497 100644 --- a/tests/phpunit/tests/customize/manager.php +++ b/tests/phpunit/tests/customize/manager.php @@ -3136,7 +3136,7 @@ public function test_remove_frameless_preview_messenger_channel() { ob_start(); $manager->remove_frameless_preview_messenger_channel(); $output = ob_get_clean(); - $this->assertStringContainsString( ' JS; $this->wp_scripts_print_translations_output .= "\n"; @@ -77,7 +79,7 @@ public function test_wp_enqueue_script() { $expected .= "\n"; $expected .= "\n"; - $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); // No scripts left to print. $this->assertSame( '', get_echo( 'wp_print_scripts' ) ); @@ -118,12 +120,12 @@ public function test_after_inline_script_with_delayed_main_script( $strategy ) { $output = get_echo( 'wp_print_scripts' ); $expected = "\n"; $expected .= wp_get_inline_script_tag( - "console.log(\"after one\");\n", + 'console.log("after one");', array( 'id' => 'ms-isa-1-js-after', ) ); - $this->assertSame( $expected, $output, 'Inline scripts in the "after" position, that are attached to a deferred main script, are failing to print/execute.' ); + $this->assertEqualMarkup( $expected, $output, 'Inline scripts in the "after" position, that are attached to a deferred main script, are failing to print/execute.' ); } /** @@ -146,13 +148,13 @@ public function test_after_inline_script_with_blocking_main_script() { $expected = "\n"; $expected .= wp_get_inline_script_tag( - "console.log(\"after one\");\n", + 'console.log("after one");', array( 'id' => 'ms-insa-3-js-after', ) ); - $this->assertSame( $expected, $output, 'Inline scripts in the "after" position, that are attached to a blocking main script, are failing to print/execute.' ); + $this->assertEqualMarkup( $expected, $output, 'Inline scripts in the "after" position, that are attached to a blocking main script, are failing to print/execute.' ); } /** @@ -180,7 +182,7 @@ public function test_before_inline_scripts_with_delayed_main_script( $strategy ) $output = get_echo( 'wp_print_scripts' ); $expected = wp_get_inline_script_tag( - "console.log(\"before first\");\n", + 'console.log("before first");', array( 'id' => 'ds-i1-1-js-before', ) @@ -189,7 +191,7 @@ public function test_before_inline_scripts_with_delayed_main_script( $strategy ) $expected .= "\n"; $expected .= "\n"; $expected .= wp_get_inline_script_tag( - "console.log(\"before last\");\n", + 'console.log("before last");', array( 'id' => 'ms-i1-1-js-before', 'type' => 'text/javascript', @@ -197,7 +199,7 @@ public function test_before_inline_scripts_with_delayed_main_script( $strategy ) ); $expected .= "\n"; - $this->assertSame( $expected, $output, 'Inline scripts in the "before" position, that are attached to a deferred main script, are failing to print/execute.' ); + $this->assertEqualMarkup( $expected, $output, 'Inline scripts in the "before" position, that are attached to a deferred main script, are failing to print/execute.' ); } /** @@ -215,7 +217,7 @@ public function test_loading_strategy_with_valid_async_registration() { wp_enqueue_script( 'main-script-a1', '/main-script-a1.js', array(), null, array( 'strategy' => 'async' ) ); $output = get_echo( 'wp_print_scripts' ); $expected = "\n"; - $this->assertSame( $expected, $output, 'Scripts enqueued with an async loading strategy are failing to have the async attribute applied to the script handle when being printed.' ); + $this->assertEqualMarkup( $expected, $output, 'Scripts enqueued with an async loading strategy are failing to have the async attribute applied to the script handle when being printed.' ); } /** @@ -235,9 +237,10 @@ public function test_loading_strategy_with_valid_async_registration() { public function test_delayed_dependent_with_blocking_dependency( $strategy ) { wp_enqueue_script( 'dependency-script-a2', '/dependency-script-a2.js', array(), null ); wp_enqueue_script( 'main-script-a2', '/main-script-a2.js', array( 'dependency-script-a2' ), null, compact( 'strategy' ) ); - $output = get_echo( 'wp_print_scripts' ); - $expected = ""; - $this->assertStringContainsString( $expected, $output, 'Dependents of a blocking dependency are free to have any strategy.' ); + $output = get_echo( 'wp_print_scripts' ); + $expected = "\n"; + $expected .= ""; + $this->assertEqualMarkup( $expected, $output, 'Dependents of a blocking dependency are free to have any strategy.' ); } /** @@ -257,7 +260,7 @@ public function test_blocking_dependent_with_delayed_dependency( $strategy ) { wp_enqueue_script( 'main-script-a3', '/main-script-a3.js', array(), null, compact( 'strategy' ) ); wp_enqueue_script( 'dependent-script-a3', '/dependent-script-a3.js', array( 'main-script-a3' ), null ); $output = get_echo( 'wp_print_scripts' ); - $expected = ""; + $expected = str_replace( "'", '"', "" ); $this->assertStringContainsString( $expected, $output, 'Blocking dependents must force delayed dependencies to become blocking.' ); } @@ -275,11 +278,12 @@ public function test_blocking_dependent_with_delayed_dependency( $strategy ) { * @param string $strategy Strategy. */ public function test_delayed_dependent_with_blocking_dependency_not_enqueued( $strategy ) { + $this->add_html5_script_theme_support(); wp_enqueue_script( 'main-script-a4', '/main-script-a4.js', array(), null, compact( 'strategy' ) ); // This dependent is registered but not enqueued, so it should not factor into the eligible loading strategy. wp_register_script( 'dependent-script-a4', '/dependent-script-a4.js', array( 'main-script-a4' ), null ); $output = get_echo( 'wp_print_scripts' ); - $expected = ""; + $expected = str_replace( "'", '"', "" ); $this->assertStringContainsString( $expected, $output, 'Only enqueued dependents should affect the eligible strategy.' ); } @@ -964,9 +968,10 @@ public function test_various_strategy_dependency_chains( $set_up, $expected_mark * @covers ::wp_enqueue_script */ public function test_loading_strategy_with_defer_having_no_dependents_nor_dependencies() { + $this->add_html5_script_theme_support(); wp_enqueue_script( 'main-script-d1', 'http://example.com/main-script-d1.js', array(), null, array( 'strategy' => 'defer' ) ); $output = get_echo( 'wp_print_scripts' ); - $expected = "\n"; + $expected = str_replace( "'", '"', "\n" ); $this->assertStringContainsString( $expected, $output, 'Expected defer, as there is no dependent or dependency' ); } @@ -980,12 +985,13 @@ public function test_loading_strategy_with_defer_having_no_dependents_nor_depend * @covers ::wp_enqueue_script */ public function test_loading_strategy_with_defer_dependent_and_varied_dependencies() { + $this->add_html5_script_theme_support(); wp_enqueue_script( 'dependency-script-d2-1', 'http://example.com/dependency-script-d2-1.js', array(), null, array( 'strategy' => 'defer' ) ); wp_enqueue_script( 'dependency-script-d2-2', 'http://example.com/dependency-script-d2-2.js', array(), null ); wp_enqueue_script( 'dependency-script-d2-3', 'http://example.com/dependency-script-d2-3.js', array( 'dependency-script-d2-2' ), null, array( 'strategy' => 'defer' ) ); wp_enqueue_script( 'main-script-d2', 'http://example.com/main-script-d2.js', array( 'dependency-script-d2-1', 'dependency-script-d2-3' ), null, array( 'strategy' => 'defer' ) ); $output = get_echo( 'wp_print_scripts' ); - $expected = "\n"; + $expected = ''; $this->assertStringContainsString( $expected, $output, 'Expected defer, as all dependencies are either deferred or blocking' ); } @@ -999,12 +1005,13 @@ public function test_loading_strategy_with_defer_dependent_and_varied_dependenci * @covers ::wp_enqueue_script */ public function test_loading_strategy_with_all_defer_dependencies() { + $this->add_html5_script_theme_support(); wp_enqueue_script( 'main-script-d3', 'http://example.com/main-script-d3.js', array(), null, array( 'strategy' => 'defer' ) ); wp_enqueue_script( 'dependent-script-d3-1', 'http://example.com/dependent-script-d3-1.js', array( 'main-script-d3' ), null, array( 'strategy' => 'defer' ) ); wp_enqueue_script( 'dependent-script-d3-2', 'http://example.com/dependent-script-d3-2.js', array( 'dependent-script-d3-1' ), null, array( 'strategy' => 'defer' ) ); wp_enqueue_script( 'dependent-script-d3-3', 'http://example.com/dependent-script-d3-3.js', array( 'dependent-script-d3-2' ), null, array( 'strategy' => 'defer' ) ); $output = get_echo( 'wp_print_scripts' ); - $expected = "\n"; + $expected = ''; $this->assertStringContainsString( $expected, $output, 'Expected defer, as all dependents have defer loading strategy' ); } @@ -1029,7 +1036,7 @@ public function test_defer_with_async_dependent() { $expected .= "\n"; $expected .= "\n"; - $this->assertSame( $expected, $output, 'Scripts registered as defer but that have dependents that are async are expected to have said dependents deferred.' ); + $this->assertEqualMarkup( $expected, $output, 'Scripts registered as defer but that have dependents that are async are expected to have said dependents deferred.' ); } /** @@ -1049,7 +1056,7 @@ public function test_loading_strategy_with_invalid_defer_registration() { wp_enqueue_script( 'dependent-script-d4-2', '/dependent-script-d4-2.js', array( 'dependent-script-d4-1' ), null ); wp_enqueue_script( 'dependent-script-d4-3', '/dependent-script-d4-3.js', array( 'dependent-script-d4-2' ), null, array( 'strategy' => 'defer' ) ); $output = get_echo( 'wp_print_scripts' ); - $expected = "\n"; + $expected = str_replace( "'", '"', "\n" ); $this->assertStringContainsString( $expected, $output, 'Scripts registered as defer but that have all dependents with no strategy, should become blocking (no strategy).' ); } @@ -1067,12 +1074,14 @@ public function test_loading_strategy_with_valid_blocking_registration() { wp_enqueue_script( 'main-script-b1', '/main-script-b1.js', array(), null ); $output = get_echo( 'wp_print_scripts' ); $expected = "\n"; + $expected = str_replace( "'", '"', $expected ); $this->assertSame( $expected, $output, 'Scripts registered with a "blocking" strategy, and who have no dependencies, should have no loading strategy attributes printed.' ); // strategy args not set. wp_enqueue_script( 'main-script-b2', '/main-script-b2.js', array(), null, array() ); $output = get_echo( 'wp_print_scripts' ); $expected = "\n"; + $expected = str_replace( "'", '"', $expected ); $this->assertSame( $expected, $output, 'Scripts registered with no strategy assigned, and who have no dependencies, should have no loading strategy attributes printed.' ); } @@ -1099,7 +1108,7 @@ public function test_scripts_targeting_head() { $expected_header .= "\n"; $expected_header .= "\n"; - $this->assertSame( $expected_header, $actual_header, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' ); + $this->assertEqualMarkup( $expected_header, $actual_header, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' ); $this->assertEmpty( $actual_footer, 'Expected footer to be empty since all scripts were for head.' ); } @@ -1127,7 +1136,7 @@ public function test_scripts_targeting_footer() { $expected_footer .= "\n"; $this->assertEmpty( $actual_header, 'Expected header to be empty since all scripts targeted footer.' ); - $this->assertSame( $expected_footer, $actual_footer, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' ); + $this->assertEqualMarkup( $expected_footer, $actual_footer, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' ); } /** @@ -1246,7 +1255,7 @@ public function test_script_strategy_doing_it_wrong_via_register() { wp_register_script( 'invalid-strategy', '/defaults.js', array(), null, array( 'strategy' => 'random-strategy' ) ); wp_enqueue_script( 'invalid-strategy' ); - $this->assertSame( + $this->assertEqualMarkup( "\n", get_echo( 'wp_print_scripts' ) ); @@ -1271,7 +1280,7 @@ public function test_script_strategy_doing_it_wrong_via_add_data() { wp_script_add_data( 'invalid-strategy', 'strategy', 'random-strategy' ); wp_enqueue_script( 'invalid-strategy' ); - $this->assertSame( + $this->assertEqualMarkup( "\n", get_echo( 'wp_print_scripts' ) ); @@ -1292,7 +1301,7 @@ public function test_script_strategy_doing_it_wrong_via_add_data() { public function test_script_strategy_doing_it_wrong_via_enqueue() { wp_enqueue_script( 'invalid-strategy', '/defaults.js', array(), null, array( 'strategy' => 'random-strategy' ) ); - $this->assertSame( + $this->assertEqualMarkup( "\n", get_echo( 'wp_print_scripts' ) ); @@ -1330,7 +1339,7 @@ public function test_concatenate_with_defer_strategy() { $expected = "\n"; $expected .= "\n"; - $this->assertSame( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with a "defer" loading strategy. Deferred scripts should not be part of the script concat loading query.' ); + $this->assertEqualMarkup( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with a "defer" loading strategy. Deferred scripts should not be part of the script concat loading query.' ); } /** @@ -1365,7 +1374,7 @@ public function test_concatenate_with_async_strategy() { $expected = "\n"; $expected .= "\n"; - $this->assertSame( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with an "async" loading strategy. Async scripts should not be part of the script concat loading query.' ); + $this->assertEqualMarkup( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with an "async" loading strategy. Async scripts should not be part of the script concat loading query.' ); } /** @@ -1404,7 +1413,7 @@ public function test_concatenate_with_blocking_script_before_and_after_script_wi $expected = "\n"; $expected .= "\n"; - $this->assertSame( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered as deferred after other blocking scripts are registered. Deferred scripts should not be part of the script concat loader query string. ' ); + $this->assertEqualMarkup( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered as deferred after other blocking scripts are registered. Deferred scripts should not be part of the script concat loader query string. ' ); } /** @@ -1412,7 +1421,6 @@ public function test_concatenate_with_blocking_script_before_and_after_script_wi */ public function test_wp_enqueue_script_with_html5_support_does_not_contain_type_attribute() { global $wp_version; - add_theme_support( 'html5', array( 'script' ) ); $GLOBALS['wp_scripts'] = new WP_Scripts(); $GLOBALS['wp_scripts']->default_version = get_bloginfo( 'version' ); @@ -1421,7 +1429,7 @@ public function test_wp_enqueue_script_with_html5_support_does_not_contain_type_ $expected = "\n"; - $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); } /** @@ -1460,7 +1468,7 @@ public function test_protocols() { $expected .= "\n"; // Go! - $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); // No scripts left to print. $this->assertSame( '', get_echo( 'wp_print_scripts' ) ); @@ -1503,7 +1511,7 @@ public function test_wp_script_add_data_with_data_key() { $expected .= "\n"; // Go! - $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); // No scripts left to print. $this->assertSame( '', get_echo( 'wp_print_scripts' ) ); @@ -1521,7 +1529,7 @@ public function test_wp_script_add_data_with_conditional_key() { $expected = "\n"; // Go! - $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); // No scripts left to print. $this->assertSame( '', get_echo( 'wp_print_scripts' ) ); @@ -1539,9 +1547,10 @@ public function test_wp_script_add_data_with_data_and_conditional_keys() { wp_script_add_data( 'test-conditional-with-data', 'conditional', 'lt IE 9' ); $expected = "\n"; $expected .= "\n"; + $expected = str_replace( "'", '"', $expected ); // Go! - $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); // No scripts left to print. $this->assertSame( '', get_echo( 'wp_print_scripts' ) ); @@ -1559,10 +1568,10 @@ public function test_wp_script_add_data_with_invalid_key() { $expected = "\n"; // Go! - $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); // No scripts left to print. - $this->assertSame( '', get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( '', get_echo( 'wp_print_scripts' ) ); } /** @@ -1588,7 +1597,7 @@ public function test_wp_register_script_with_handle_without_source() { wp_enqueue_script( 'handle-three' ); - $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); } /** @@ -1676,8 +1685,8 @@ public function test_wp_register_script_with_dependencies_in_head_and_footer() { $expected_header .= "\n"; $expected_footer = "\n"; - $this->assertSame( $expected_header, $header, 'Expected same header markup.' ); - $this->assertSame( $expected_footer, $footer, 'Expected same footer markup.' ); + $this->assertEqualMarkup( $expected_header, $header, 'Expected same header markup.' ); + $this->assertEqualMarkup( $expected_footer, $footer, 'Expected same footer markup.' ); } /** @@ -1697,8 +1706,8 @@ public function test_wp_register_script_with_dependencies_in_head_and_footer_in_ $expected_footer = "\n"; $expected_footer .= "\n"; - $this->assertSame( $expected_header, $header, 'Expected same header markup.' ); - $this->assertSame( $expected_footer, $footer, 'Expected same footer markup.' ); + $this->assertEqualMarkup( $expected_header, $header, 'Expected same header markup.' ); + $this->assertEqualMarkup( $expected_footer, $footer, 'Expected same footer markup.' ); } /** @@ -1728,8 +1737,8 @@ public function test_wp_register_script_with_dependencies_in_head_and_footer_in_ $expected_footer .= "\n"; $expected_footer .= "\n"; - $this->assertSame( $expected_header, $header, 'Expected same header markup.' ); - $this->assertSame( $expected_footer, $footer, 'Expected same footer markup.' ); + $this->assertEqualMarkup( $expected_header, $header, 'Expected same header markup.' ); + $this->assertEqualMarkup( $expected_footer, $footer, 'Expected same footer markup.' ); } /** @@ -1952,12 +1961,14 @@ public function test_wp_add_inline_script_after_and_before_with_concat_and_condi $expected_localized = "\n"; + $expected_localized = str_replace( "'", '"', $expected_localized ); $expected = "\n"; + $expected = str_replace( "'", '"', $expected ); wp_enqueue_script( 'test-example', 'example.com', array(), null ); wp_localize_script( 'test-example', 'testExample', array( 'foo' => 'bar' ) ); @@ -2124,7 +2135,8 @@ public function test_wp_add_inline_script_customize_dependency() { _print_scripts(); $print_scripts = $this->getActualOutput(); - $tail = substr( $print_scripts, strrpos( $print_scripts, "\n"; - $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); } /** @@ -2331,7 +2343,7 @@ public function test_wp_set_script_translations_for_plugin() { ); $expected .= "\n"; - $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); } /** @@ -2358,7 +2370,7 @@ public function test_wp_set_script_translations_for_theme() { ); $expected .= "\n"; - $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); } /** @@ -2385,7 +2397,7 @@ public function test_wp_set_script_translations_with_handle_file() { ); $expected .= "\n"; - $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); } /** @@ -2415,7 +2427,7 @@ public function test_wp_set_script_translations_when_translation_file_does_not_e $expected = "\n"; $expected .= "\n"; - $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); } /** @@ -2444,7 +2456,7 @@ public function test_wp_set_script_translations_after_register() { ); $expected .= "\n"; - $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); } /** @@ -2474,7 +2486,7 @@ public function test_wp_set_script_translations_dependency() { $expected .= "\n"; $expected .= "\n"; - $this->assertSameIgnoreEOL( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); } /** @@ -2863,7 +2875,7 @@ public function test_wp_localize_script_data_formats( $l10n_data, $expected ) { $expected = "\n"; $expected .= "\n"; - $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) ); + $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) ); } /** @@ -2928,7 +2940,7 @@ static function () { $expected .= "\n"; $expected .= "\n"; - $this->assertSame( $expected, $print_scripts ); + $this->assertEqualMarkup( $expected, $print_scripts ); } /** @@ -2967,7 +2979,7 @@ public function test_printing_non_enqueued_scripts( $strategy ) { * Parse an HTML markup fragment. * * @param string $markup Markup. - * @return DOMElement Body element wrapping supplied markup fragment. + * @return DOMDocument Document containing the normalized markup fragment. */ protected function parse_markup_fragment( $markup ) { $dom = new DOMDocument(); @@ -2985,21 +2997,60 @@ protected function parse_markup_fragment( $markup ) { } } - return $body; + return $dom; } /** - * Assert markup is equal. + * Assert markup is equal after normalizing script tags. * * @param string $expected Expected markup. * @param string $actual Actual markup. * @param string $message Message. */ protected function assertEqualMarkup( $expected, $actual, $message = '' ) { + $expected_dom = $this->parse_markup_fragment( $expected ); + $actual_dom = $this->parse_markup_fragment( $actual ); + foreach ( array( $expected_dom, $actual_dom ) as $dom ) { + $xpath = new DOMXPath( $dom ); + /** @var DOMElement $script */ + + // Normalize type attribute. When missing, it defaults to text/javascript. + foreach ( $xpath->query( '//script[ not( @type ) ]' ) as $script ) { + $script->setAttribute( 'type', 'text/javascript' ); + } + + // Normalize script contents to remove CDATA wrapper. + foreach ( $xpath->query( '//script[ contains( text(), "textContent = str_replace( + array( + "/* */", + ), + '', + $script->textContent + ); + } + + // Normalize XHTML-compatible boolean attributes to HTML5 ones. + foreach ( array( 'async', 'defer' ) as $attribute ) { + foreach ( iterator_to_array( $xpath->query( "//script[ @{$attribute} = '{$attribute}' ]" ) ) as $script ) { + $script->removeAttribute( $attribute ); + $script->setAttributeNode( $dom->createAttribute( $attribute ) ); + } + } + } + $this->assertEquals( - $this->parse_markup_fragment( $expected ), - $this->parse_markup_fragment( $actual ), + $expected_dom->getElementsByTagName( 'body' )->item( 0 ), + $actual_dom->getElementsByTagName( 'body' )->item( 0 ), $message ); } + + /** + * Adds html5 script theme support. + */ + protected function add_html5_script_theme_support() { + add_theme_support( 'html5', array( 'script' ) ); + } } diff --git a/tests/phpunit/tests/dependencies/wpInlineScriptTag.php b/tests/phpunit/tests/dependencies/wpInlineScriptTag.php index 1e517b637ddaf..2bbb665d395f6 100644 --- a/tests/phpunit/tests/dependencies/wpInlineScriptTag.php +++ b/tests/phpunit/tests/dependencies/wpInlineScriptTag.php @@ -119,4 +119,18 @@ static function ( $attributes ) { ) ); } + + /** + * Tests that CDATA wrapper duplication is handled. + * + * @ticket 58664 + */ + public function test_get_inline_script_tag_with_duplicated_cdata_wrappers() { + remove_theme_support( 'html5' ); + + $this->assertSame( + "\n", + wp_get_inline_script_tag( "/* */" ) + ); + } }