mirror of
git://develop.git.wordpress.org/
synced 2025-01-17 12:58:25 +01:00
Embeds: Conditionally enqueue wp-embed
only if needed and send ready
message in case script loads after post embed windows.
* Prevent loading `wp-embed` script unconditionally on every page in favor of conditionally enqueueing when a post embed is detected. The `wp-embed` script is also explicitly marked as being in the footer group. Sites which currently disable post embed scripts from being enqueued via `remove_action( 'wp_head', 'wp_oembed_add_host_js' )` will continue to do so. * Send a `ready` message from the host page to each post embed window in case the `iframe` loads before the `wp-embed` script does. When the `ready` message is received by the post embed window, it sends the same `height` message as it sends when it loads. * Eliminate use of `grunt-include` to inject emoji script and the post embed script. Instead obtain the script contents via `file_get_contents()` (as is done elsewhere in core) and utilize `wp_print_inline_script_tag()`/`wp_get_inline_script_tag()` to construct out the script. This simplifies the logic and allows the running of src without `SCRIPT_DEBUG` enabled. * For the embed code that users are provided to copy for embedding outside of WP, add the `secret` on the `blockquote` and `iframe`. This ensures the `blockquote` will be hidden when the `iframe` loads. The embed code in question is accessed here via `get_post_embed_html()`. Props westonruter, swissspidy, pento, flixos90, ocean90. Fixes #44632, #44306. git-svn-id: https://develop.svn.wordpress.org/trunk@52132 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
1e785fa0c3
commit
02a2f9c9f5
12
Gruntfile.js
12
Gruntfile.js
@ -1020,16 +1020,6 @@ module.exports = function(grunt) {
|
||||
dest: SOURCE_DIR
|
||||
}
|
||||
},
|
||||
includes: {
|
||||
emoji: {
|
||||
src: BUILD_DIR + 'wp-includes/formatting.php',
|
||||
dest: '.'
|
||||
},
|
||||
embed: {
|
||||
src: BUILD_DIR + 'wp-includes/embed.php',
|
||||
dest: '.'
|
||||
}
|
||||
},
|
||||
replace: {
|
||||
'emoji-regex': {
|
||||
options: {
|
||||
@ -1593,8 +1583,6 @@ module.exports = function(grunt) {
|
||||
'build:files',
|
||||
'build:js',
|
||||
'build:css',
|
||||
'includes:emoji',
|
||||
'includes:embed',
|
||||
'replace:emoji-banner-text',
|
||||
'replace:source-maps',
|
||||
'verify:build'
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -13422,12 +13422,6 @@
|
||||
"integrity": "sha1-P376M2lvoFdwsoCU9EUIyvxdLto=",
|
||||
"dev": true
|
||||
},
|
||||
"grunt-includes": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/grunt-includes/-/grunt-includes-1.1.0.tgz",
|
||||
"integrity": "sha512-aZQfL+fiAonPI173QUjGyuCkaUTJci7+a5SkmSAbezUikwLban7Jp6W+vbA/Mnacmy+EPipnuK5kAF6O0SvrDw==",
|
||||
"dev": true
|
||||
},
|
||||
"grunt-jsdoc": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.4.1.tgz",
|
||||
|
@ -49,7 +49,6 @@
|
||||
"grunt-contrib-uglify": "~5.0.1",
|
||||
"grunt-contrib-watch": "~1.1.0",
|
||||
"grunt-file-append": "0.0.7",
|
||||
"grunt-includes": "~1.1.0",
|
||||
"grunt-jsdoc": "2.4.1",
|
||||
"grunt-jsvalidate": "~0.2.2",
|
||||
"grunt-legacy-util": "^2.0.1",
|
||||
|
@ -18,6 +18,13 @@
|
||||
}, '*' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the height message to the parent window.
|
||||
*/
|
||||
function sendHeightMessage() {
|
||||
sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) );
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
if ( loaded ) {
|
||||
return;
|
||||
@ -138,13 +145,11 @@
|
||||
}
|
||||
|
||||
// Send this document's height to the parent (embedding) site.
|
||||
sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) );
|
||||
sendHeightMessage();
|
||||
|
||||
// Send the document's height again after the featured image has been loaded.
|
||||
if ( featured_image ) {
|
||||
featured_image.addEventListener( 'load', function() {
|
||||
sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) );
|
||||
} );
|
||||
featured_image.addEventListener( 'load', sendHeightMessage );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,9 +189,36 @@
|
||||
|
||||
clearTimeout( resizing );
|
||||
|
||||
resizing = setTimeout( function () {
|
||||
sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) );
|
||||
}, 100 );
|
||||
resizing = setTimeout( sendHeightMessage, 100 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Message handler.
|
||||
*
|
||||
* @param {MessageEvent} event
|
||||
*/
|
||||
function onMessage( event ) {
|
||||
var data = event.data;
|
||||
|
||||
if ( ! data ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( event.source !== window.parent ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! ( data.secret || data.message ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( data.secret !== secret ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'ready' === data.message ) {
|
||||
sendHeightMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -212,5 +244,6 @@
|
||||
document.addEventListener( 'DOMContentLoaded', onLoad, false );
|
||||
window.addEventListener( 'load', onLoad, false );
|
||||
window.addEventListener( 'resize', onResize, false );
|
||||
window.addEventListener( 'message', onMessage, false );
|
||||
}
|
||||
})( window, document );
|
||||
|
@ -27,6 +27,11 @@
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive embed message.
|
||||
*
|
||||
* @param {MessageEvent} e
|
||||
*/
|
||||
window.wp.receiveEmbedMessage = function( e ) {
|
||||
var data = e.data;
|
||||
|
||||
@ -102,9 +107,11 @@
|
||||
iframeClone, i, source, secret;
|
||||
|
||||
for ( i = 0; i < iframes.length; i++ ) {
|
||||
/** @var {IframeElement} */
|
||||
source = iframes[ i ];
|
||||
|
||||
if ( ! source.getAttribute( 'data-secret' ) ) {
|
||||
secret = source.getAttribute( 'data-secret' );
|
||||
if ( ! secret ) {
|
||||
/* Add secret to iframe */
|
||||
secret = Math.random().toString( 36 ).substr( 2, 10 );
|
||||
source.src += '#?secret=' + secret;
|
||||
@ -117,6 +124,16 @@
|
||||
iframeClone.removeAttribute( 'security' );
|
||||
source.parentNode.replaceChild( iframeClone, source );
|
||||
}
|
||||
|
||||
/*
|
||||
* Let post embed window know that the parent is ready for receiving the height message, in case the iframe
|
||||
* loaded before wp-embed.js was loaded. When the ready message is received by the post embed window, the
|
||||
* window will then (re-)send the height message right away.
|
||||
*/
|
||||
source.contentWindow.postMessage( {
|
||||
message: 'ready',
|
||||
secret: secret
|
||||
}, '*' );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,7 +359,25 @@ function wp_oembed_add_discovery_links() {
|
||||
* @since 4.4.0
|
||||
*/
|
||||
function wp_oembed_add_host_js() {
|
||||
wp_enqueue_script( 'wp-embed' );
|
||||
add_filter( 'embed_oembed_html', 'wp_maybe_enqueue_oembed_host_js' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue the wp-embed script if the provided oEmbed HTML contains a post embed.
|
||||
*
|
||||
* In order to only enqueue the wp-embed script on pages that actually contain post embeds, this function checks if the
|
||||
* provided HTML contains post embed markup and if so enqueues the script so that it will get printed in the footer.
|
||||
*
|
||||
* @since 5.9.0
|
||||
*
|
||||
* @param string $html Embed markup.
|
||||
* @return string Embed markup (without modifications).
|
||||
*/
|
||||
function wp_maybe_enqueue_oembed_host_js( $html ) {
|
||||
if ( preg_match( '/<blockquote\s[^>]*wp-embedded-content/', $html ) ) {
|
||||
wp_enqueue_script( 'wp-embed' );
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -450,32 +468,22 @@ function get_post_embed_html( $width, $height, $post = null ) {
|
||||
|
||||
$embed_url = get_post_embed_url( $post );
|
||||
|
||||
$output = '<blockquote class="wp-embedded-content"><a href="' . esc_url( get_permalink( $post ) ) . '">' . get_the_title( $post ) . "</a></blockquote>\n";
|
||||
$secret = wp_generate_password( 10, false );
|
||||
$embed_url .= "#?secret={$secret}";
|
||||
|
||||
$output .= "<script type='text/javascript'>\n";
|
||||
$output .= "<!--//--><![CDATA[//><!--\n";
|
||||
if ( SCRIPT_DEBUG ) {
|
||||
$output .= file_get_contents( ABSPATH . WPINC . '/js/wp-embed.js' );
|
||||
} else {
|
||||
/*
|
||||
* If you're looking at a src version of this file, you'll see an "include"
|
||||
* statement below. This is used by the `npm run build` process to directly
|
||||
* include a minified version of wp-embed.js, instead of using the
|
||||
* file_get_contents() method from above.
|
||||
*
|
||||
* If you're looking at a build version of this file, you'll see a string of
|
||||
* minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG
|
||||
* and edit wp-embed.js directly.
|
||||
*/
|
||||
$output .= <<<JS
|
||||
include "js/wp-embed.min.js"
|
||||
JS;
|
||||
}
|
||||
$output .= "\n//--><!]]>";
|
||||
$output .= "\n</script>";
|
||||
$output = wp_get_inline_script_tag(
|
||||
file_get_contents( sprintf( ABSPATH . WPINC . '/js/wp-embed' . wp_scripts_get_suffix() . '.js' ) )
|
||||
);
|
||||
|
||||
$output .= sprintf(
|
||||
'<iframe sandbox="allow-scripts" security="restricted" src="%1$s" width="%2$d" height="%3$d" title="%4$s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" class="wp-embedded-content"></iframe>',
|
||||
'<blockquote class="wp-embedded-content" data-secret="%1$s"><a href="%2$s">%3$s</a></blockquote>',
|
||||
esc_attr( $secret ),
|
||||
esc_url( get_permalink( $post ) ),
|
||||
get_the_title( $post )
|
||||
);
|
||||
|
||||
$output .= sprintf(
|
||||
'<iframe sandbox="allow-scripts" security="restricted" src="%1$s" width="%2$d" height="%3$d" title="%4$s" data-secret="%5$s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" class="wp-embedded-content"></iframe>',
|
||||
esc_url( $embed_url ),
|
||||
absint( $width ),
|
||||
absint( $height ),
|
||||
@ -486,7 +494,8 @@ JS;
|
||||
get_the_title( $post ),
|
||||
get_bloginfo( 'name' )
|
||||
)
|
||||
)
|
||||
),
|
||||
esc_attr( $secret )
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -5756,8 +5756,7 @@ function _print_emoji_detection_script() {
|
||||
'svgExt' => apply_filters( 'emoji_svg_ext', '.svg' ),
|
||||
);
|
||||
|
||||
$version = 'ver=' . get_bloginfo( 'version' );
|
||||
$type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/javascript"';
|
||||
$version = 'ver=' . get_bloginfo( 'version' );
|
||||
|
||||
if ( SCRIPT_DEBUG ) {
|
||||
$settings['source'] = array(
|
||||
@ -5766,36 +5765,17 @@ function _print_emoji_detection_script() {
|
||||
/** This filter is documented in wp-includes/class.wp-scripts.php */
|
||||
'twemoji' => apply_filters( 'script_loader_src', includes_url( "js/twemoji.js?$version" ), 'twemoji' ),
|
||||
);
|
||||
|
||||
?>
|
||||
<script<?php echo $type_attr; ?>>
|
||||
window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>;
|
||||
<?php readfile( ABSPATH . WPINC . '/js/wp-emoji-loader.js' ); ?>
|
||||
</script>
|
||||
<?php
|
||||
} else {
|
||||
$settings['source'] = array(
|
||||
/** This filter is documented in wp-includes/class.wp-scripts.php */
|
||||
'concatemoji' => apply_filters( 'script_loader_src', includes_url( "js/wp-emoji-release.min.js?$version" ), 'concatemoji' ),
|
||||
);
|
||||
|
||||
/*
|
||||
* If you're looking at a src version of this file, you'll see an "include"
|
||||
* statement below. This is used by the `npm run build` process to directly
|
||||
* include a minified version of wp-emoji-loader.js, instead of using the
|
||||
* readfile() method from above.
|
||||
*
|
||||
* If you're looking at a build version of this file, you'll see a string of
|
||||
* minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG
|
||||
* and edit wp-emoji-loader.js directly.
|
||||
*/
|
||||
?>
|
||||
<script<?php echo $type_attr; ?>>
|
||||
window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>;
|
||||
include "js/wp-emoji-loader.min.js"
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
wp_print_inline_script_tag(
|
||||
sprintf( 'window._wpemojiSettings = %s;', wp_json_encode( $settings ) ) .
|
||||
file_get_contents( sprintf( ABSPATH . WPINC . '/js/wp-emoji-loader' . wp_scripts_get_suffix() . '.js' ) )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1247,7 +1247,7 @@ function wp_default_scripts( $scripts ) {
|
||||
)
|
||||
);
|
||||
|
||||
$scripts->add( 'wp-embed', "/wp-includes/js/wp-embed$suffix.js" );
|
||||
$scripts->add( 'wp-embed', "/wp-includes/js/wp-embed$suffix.js", array(), false, 1 );
|
||||
|
||||
// To enqueue media-views or media-editor, call wp_enqueue_media().
|
||||
// Both rely on numerous settings, styles, and templates to operate correctly.
|
||||
|
@ -12,6 +12,24 @@ class Tests_oEmbed_Response_Data extends WP_UnitTestCase {
|
||||
self::touch( ABSPATH . WPINC . '/js/wp-embed.js' );
|
||||
}
|
||||
|
||||
private function normalize_secret_attribute( $data ) {
|
||||
if ( is_array( $data ) ) {
|
||||
$html = $data['html'];
|
||||
} else {
|
||||
$html = $data;
|
||||
}
|
||||
|
||||
$html = preg_replace( '/secret=("?)\w+\1/', 'secret=__SECRET__', $html );
|
||||
|
||||
if ( is_array( $data ) ) {
|
||||
$data['html'] = $html;
|
||||
} else {
|
||||
$data = $html;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function test_get_oembed_response_data_non_existent_post() {
|
||||
$this->assertFalse( get_oembed_response_data( 0, 100 ) );
|
||||
}
|
||||
@ -36,9 +54,9 @@ class Tests_oEmbed_Response_Data extends WP_UnitTestCase {
|
||||
'type' => 'rich',
|
||||
'width' => 400,
|
||||
'height' => 225,
|
||||
'html' => get_post_embed_html( 400, 225, $post ),
|
||||
'html' => $this->normalize_secret_attribute( get_post_embed_html( 400, 225, $post ) ),
|
||||
),
|
||||
$data
|
||||
$this->normalize_secret_attribute( $data )
|
||||
);
|
||||
}
|
||||
|
||||
@ -72,9 +90,9 @@ class Tests_oEmbed_Response_Data extends WP_UnitTestCase {
|
||||
'type' => 'rich',
|
||||
'width' => 400,
|
||||
'height' => 225,
|
||||
'html' => get_post_embed_html( 400, 225, $post ),
|
||||
'html' => $this->normalize_secret_attribute( get_post_embed_html( 400, 225, $post ) ),
|
||||
),
|
||||
$data
|
||||
$this->normalize_secret_attribute( $data )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,21 @@
|
||||
* @group oembed
|
||||
*/
|
||||
class Tests_Embed_Template extends WP_UnitTestCase {
|
||||
|
||||
public function set_up() {
|
||||
parent::set_up();
|
||||
|
||||
global $wp_scripts;
|
||||
$wp_scripts = null;
|
||||
}
|
||||
|
||||
public function tear_down() {
|
||||
parent::tear_down();
|
||||
|
||||
global $wp_scripts;
|
||||
$wp_scripts = null;
|
||||
}
|
||||
|
||||
public function test_oembed_output_post() {
|
||||
$user = self::factory()->user->create_and_get(
|
||||
array(
|
||||
@ -281,15 +296,36 @@ class Tests_Embed_Template extends WP_UnitTestCase {
|
||||
)
|
||||
);
|
||||
|
||||
$expected = '<iframe sandbox="allow-scripts" security="restricted" src="' . esc_url( get_post_embed_url( $post_id ) ) . '" width="200" height="200" title="' . $title . '" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" class="wp-embedded-content"></iframe>';
|
||||
$expected = '<iframe sandbox="allow-scripts" security="restricted" src="' . esc_url( get_post_embed_url( $post_id ) ) . '#?secret=__SECRET__" width="200" height="200" title="' . $title . '" data-secret=__SECRET__ frameborder="0" marginwidth="0" marginheight="0" scrolling="no" class="wp-embedded-content"></iframe>';
|
||||
$actual = get_post_embed_html( 200, 200, $post_id );
|
||||
$actual = preg_replace( '/secret=("?)\w+\1/', 'secret=__SECRET__', $actual );
|
||||
|
||||
$this->assertStringEndsWith( $expected, get_post_embed_html( 200, 200, $post_id ) );
|
||||
$this->assertStringEndsWith( $expected, $actual );
|
||||
}
|
||||
|
||||
/** @covers ::wp_oembed_add_host_js() */
|
||||
public function test_add_host_js() {
|
||||
remove_all_filters( 'embed_oembed_html' );
|
||||
|
||||
wp_oembed_add_host_js();
|
||||
|
||||
$this->assertTrue( wp_script_is( 'wp-embed' ) );
|
||||
$this->assertEquals( 10, has_filter( 'embed_oembed_html', 'wp_maybe_enqueue_oembed_host_js' ) );
|
||||
}
|
||||
|
||||
/** @covers ::wp_maybe_enqueue_oembed_host_js() */
|
||||
function test_wp_maybe_enqueue_oembed_host_js() {
|
||||
$scripts = wp_scripts();
|
||||
|
||||
$this->assertFalse( $scripts->query( 'wp-embed', 'enqueued' ) );
|
||||
|
||||
$post_embed = '<blockquote class="wp-embedded-content" data-secret="S24AQCJW9i"><a href="https://make.wordpress.org/core/2016/03/11/embeds-changes-in-wordpress-4-5/">Embeds Changes in WordPress 4.5</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; clip: rect(1px, 1px, 1px, 1px);" title="“Embeds Changes in WordPress 4.5” — Make WordPress Core" src="https://make.wordpress.org/core/2016/03/11/embeds-changes-in-wordpress-4-5/embed/#?secret=S24AQCJW9i" data-secret="S24AQCJW9i" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>';
|
||||
$non_post_embed = '<iframe title="Zoo Cares For 23 Tiny Pond Turtles" width="750" height="422" src="https://www.youtube.com/embed/6ZXHqUjL6f8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>';
|
||||
|
||||
wp_maybe_enqueue_oembed_host_js( $non_post_embed );
|
||||
$this->assertFalse( $scripts->query( 'wp-embed', 'enqueued' ) );
|
||||
|
||||
wp_maybe_enqueue_oembed_host_js( $post_embed );
|
||||
$this->assertTrue( $scripts->query( 'wp-embed', 'enqueued' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user