diff --git a/lib/client-assets.php b/lib/client-assets.php
index ab2cd25426a7ea..7e7f3800b791b2 100644
--- a/lib/client-assets.php
+++ b/lib/client-assets.php
@@ -708,7 +708,8 @@ function gutenberg_extend_block_editor_settings_with_fse_theme_flag( $settings )
* Sets the editor styles to be consumed by JS.
*/
function gutenberg_extend_block_editor_styles_html() {
- $handles = array(
+ $script_handles = array();
+ $style_handles = array(
'wp-block-editor',
'wp-block-library',
'wp-block-library-theme',
@@ -719,26 +720,48 @@ function gutenberg_extend_block_editor_styles_html() {
foreach ( $block_registry->get_all_registered() as $block_type ) {
if ( ! empty( $block_type->style ) ) {
- $handles[] = $block_type->style;
+ $style_handles[] = $block_type->style;
}
if ( ! empty( $block_type->editor_style ) ) {
- $handles[] = $block_type->editor_style;
+ $style_handles[] = $block_type->editor_style;
+ }
+
+ if ( ! empty( $block_type->script ) ) {
+ $script_handles[] = $block_type->script;
}
}
- $handles = array_unique( $handles );
- $done = wp_styles()->done;
+ $style_handles = array_unique( $style_handles );
+ $done = wp_styles()->done;
ob_start();
wp_styles()->done = array();
- wp_styles()->do_items( $handles );
+ wp_styles()->do_items( $style_handles );
wp_styles()->done = $done;
- $editor_styles = wp_json_encode( array( 'html' => ob_get_clean() ) );
+ $styles = ob_get_clean();
+
+ $script_handles = array_unique( $script_handles );
+ $done = wp_scripts()->done;
+
+ ob_start();
+
+ wp_scripts()->done = array();
+ wp_scripts()->do_items( $script_handles );
+ wp_scripts()->done = $done;
+
+ $scripts = ob_get_clean();
+
+ $editor_assets = wp_json_encode(
+ array(
+ 'styles' => $styles,
+ 'scripts' => $scripts,
+ )
+ );
- echo "";
+ echo "";
}
add_action( 'admin_footer-toplevel_page_gutenberg-edit-site', 'gutenberg_extend_block_editor_styles_html' );
add_action( 'admin_footer-post.php', 'gutenberg_extend_block_editor_styles_html' );
diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js
index 3570bb1bd6ad11..93d298632cfab6 100644
--- a/packages/block-editor/src/components/iframe/index.js
+++ b/packages/block-editor/src/components/iframe/index.js
@@ -6,6 +6,8 @@ import {
createPortal,
useCallback,
forwardRef,
+ useEffect,
+ useMemo,
} from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { useMergeRefs } from '@wordpress/compose';
@@ -133,21 +135,33 @@ function setBodyClassName( doc ) {
}
}
-/**
- * Sets the document head and default styles.
- *
- * @param {Document} doc Document to set the head for.
- * @param {string} head HTML to set as the head.
- */
-function setHead( doc, head ) {
- doc.head.innerHTML =
- // Body margin must be overridable by themes.
- '' + head;
+function useParsedAssets( html ) {
+ return useMemo( () => {
+ const doc = document.implementation.createHTMLDocument( '' );
+ doc.body.innerHTML = html;
+ return Array.from( doc.body.children );
+ }, [ html ] );
}
-function Iframe( { contentRef, children, head, headHTML, ...props }, ref ) {
- const [ iframeDocument, setIframeDocument ] = useState();
+async function loadScript( doc, { id, src } ) {
+ return new Promise( ( resolve, reject ) => {
+ const script = doc.createElement( 'script' );
+ script.id = id;
+ if ( src ) {
+ script.src = src;
+ script.onload = () => resolve();
+ script.onerror = () => reject();
+ } else {
+ resolve();
+ }
+ doc.head.appendChild( script );
+ } );
+}
+function Iframe( { contentRef, children, head, ...props }, ref ) {
+ const [ iframeDocument, setIframeDocument ] = useState();
+ const styles = useParsedAssets( window.__editorAssets.styles );
+ const scripts = useParsedAssets( window.__editorAssets.scripts );
const clearerRef = useBlockSelectionClearer();
const setRef = useCallback( ( node ) => {
if ( ! node ) {
@@ -168,15 +182,19 @@ function Iframe( { contentRef, children, head, headHTML, ...props }, ref ) {
contentRef.current = body;
}
- setHead( contentDocument, headHTML );
setBodyClassName( contentDocument );
- styleSheetsCompat( contentDocument );
bubbleEvents( contentDocument );
setBodyClassName( contentDocument );
setIframeDocument( contentDocument );
clearerRef( documentElement );
clearerRef( body );
+ scripts.reduce(
+ ( promise, script ) =>
+ promise.then( () => loadScript( contentDocument, script ) ),
+ Promise.resolve()
+ );
+
return true;
}
@@ -190,6 +208,25 @@ function Iframe( { contentRef, children, head, headHTML, ...props }, ref ) {
} );
}, [] );
+ useEffect( () => {
+ if ( iframeDocument ) {
+ styleSheetsCompat( iframeDocument );
+ }
+ }, [ iframeDocument ] );
+
+ head = (
+ <>
+
+ { styles.map( ( { tagName, href, id, rel, media }, index ) => {
+ const TagName = tagName.toLowerCase();
+ return (
+
+ );
+ } ) }
+ { head }
+ >
+ );
+
return (
}
ref={ ref }
contentRef={ contentRef }
diff --git a/packages/edit-site/src/components/block-editor/index.js b/packages/edit-site/src/components/block-editor/index.js
index e168c40f7f2589..ebe97e3e7ea7b5 100644
--- a/packages/edit-site/src/components/block-editor/index.js
+++ b/packages/edit-site/src/components/block-editor/index.js
@@ -87,7 +87,6 @@ export default function BlockEditor( { setIsInserterOpen } ) {
}
ref={ ref }
contentRef={ mergedRefs }