diff --git a/lib/blocks.php b/lib/blocks.php index 4e8910b536e9a8..4cdd36d268c926 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -512,3 +512,111 @@ function gutenberg_migrate_old_typography_shape( $metadata ) { if ( ! function_exists( 'wp_migrate_old_typography_shape' ) ) { add_filter( 'block_type_metadata', 'gutenberg_migrate_old_typography_shape' ); } + +if ( ! function_exists( 'wp_enqueue_block_style' ) ) { + /** + * Enqueue a stylesheet for a specific block. + * + * If the theme has opted-in to separate-styles loading, + * then the stylesheet will be enqueued on-render, + * otherwise when the block inits. + * + * @param string $block_name The block-name, including namespace. + * @param array $args An array of arguments [handle,src,deps,ver,media]. + * + * @return void + */ + function wp_enqueue_block_style( $block_name, $args ) { + $args = wp_parse_args( + $args, + array( + 'handle' => '', + 'src' => '', + 'deps' => array(), + 'ver' => false, + 'media' => 'all', + ) + ); + + /** + * Callback function to register and enqueue styles. + * + * @param string $content When the callback is used for the render_block filter, + * the content needs to be returned so the function parameter + * is to ensure the content exists. + * + * @return string + */ + $callback = function( $content ) use ( $args ) { + // Register the stylesheet. + if ( ! empty( $args['src'] ) ) { + wp_register_style( $args['handle'], $args['src'], $args['deps'], $args['ver'], $args['media'] ); + } + + // Add `path` data if provided. + if ( isset( $args['path'] ) ) { + wp_style_add_data( $args['handle'], 'path', $args['path'] ); + + // Get the RTL file path. + $rtl_file_path = str_replace( '.css', '-rtl.css', $args['path'] ); + + // Add RTL stylesheet. + if ( file_exists( $rtl_file_path ) ) { + wp_style_add_data( $args['hanle'], 'rtl', 'replace' ); + + if ( is_rtl() ) { + wp_style_add_data( $args['handle'], 'path', $rtl_file_path ); + } + } + } + + // Enqueue the stylesheet. + wp_enqueue_style( $args['handle'] ); + + return $content; + }; + + $hook = did_action( 'wp_enqueue_scripts' ) ? 'wp_footer' : 'wp_enqueue_scripts'; + if ( wp_should_load_separate_core_block_assets() ) { + $hook = "render_block_$block_name"; + } + + // Enqueue assets in the frontend. + add_filter( $hook, $callback ); + + // Enqueue assets in the editor. + add_action( 'enqueue_block_assets', $callback ); + } +} + +/** + * Allow multiple block styles. + * + * @param array $metadata Metadata for registering a block type. + * + * @return array + */ +function gutenberg_multiple_block_styles( $metadata ) { + foreach ( array( 'style', 'editorStyle' ) as $key ) { + if ( ! empty( $metadata[ $key ] ) && is_array( $metadata[ $key ] ) ) { + $default_style = array_shift( $metadata[ $key ] ); + foreach ( $metadata[ $key ] as $handle ) { + $args = array( 'handle' => $handle ); + if ( 0 === strpos( $handle, 'file:' ) && isset( $metadata['file'] ) ) { + $style_path = remove_block_asset_path_prefix( $handle ); + $args = array( + 'handle' => sanitize_key( "{$metadata['name']}-{$style_path}" ), + 'src' => plugins_url( $style_path, $metadata['file'] ), + ); + } + + wp_enqueue_block_style( $metadata['name'], $args ); + } + + // Only return the 1st item in the array. + $metadata[ $key ] = $default_style; + } + } + return $metadata; +} +add_filter( 'block_type_metadata', 'gutenberg_multiple_block_styles' ); diff --git a/packages/block-library/src/post-comments-form/block.json b/packages/block-library/src/post-comments-form/block.json index 38a14829358f09..53ad6a1d42956d 100644 --- a/packages/block-library/src/post-comments-form/block.json +++ b/packages/block-library/src/post-comments-form/block.json @@ -22,5 +22,5 @@ "lineHeight": true } }, - "style": "wp-block-post-comments-form" + "style": [ "wp-block-post-comments-form", "wp-block-buttons", "wp-block-button" ] } diff --git a/packages/block-library/src/post-comments-form/index.php b/packages/block-library/src/post-comments-form/index.php index 8a567cfaaf44f6..0d61951c122460 100644 --- a/packages/block-library/src/post-comments-form/index.php +++ b/packages/block-library/src/post-comments-form/index.php @@ -61,17 +61,3 @@ function gutenberg_comment_form_block_form_defaults( $fields ) { return $fields; } add_filter( 'comment_form_defaults', 'gutenberg_comment_form_block_form_defaults' ); - -add_action( - 'wp_enqueue_scripts', - /** - * Add the button stylesheet as a dependency for the post-comment form stylesheet. - */ - function() { - global $wp_styles; - if ( ! empty( $wp_styles->registered ) && ! empty( $wp_styles->registered['wp-block-post-comments-form'] ) ) { - $wp_styles->registered['wp-block-post-comments-form']->deps[] = 'wp-block-button'; - } - }, - 1 -); diff --git a/packages/e2e-tests/plugins/iframed-multiple-stylesheets.php b/packages/e2e-tests/plugins/iframed-multiple-stylesheets.php new file mode 100644 index 00000000000000..40d7d5040083cf --- /dev/null +++ b/packages/e2e-tests/plugins/iframed-multiple-stylesheets.php @@ -0,0 +1,44 @@ + { + const { createElement: el } = element; + const { registerBlockType } = blocks; + const { useBlockProps } = blockEditor; + + registerBlockType( 'test/iframed-multiple-stylesheets', { + apiVersion: 2, + edit: function Edit() { + return el( 'div', useBlockProps(), 'Edit' ); + }, + save: function Save() { + return el( 'div', useBlockProps.save(), 'Save' ); + }, + } ); +} )( window ); diff --git a/packages/e2e-tests/plugins/iframed-multiple-stylesheets/style.css b/packages/e2e-tests/plugins/iframed-multiple-stylesheets/style.css new file mode 100644 index 00000000000000..351cdb9ca6b284 --- /dev/null +++ b/packages/e2e-tests/plugins/iframed-multiple-stylesheets/style.css @@ -0,0 +1,7 @@ +/** + * The following styles get applied both on the front of your site and in the + * editor. + */ +.wp-block-test-iframed-multiple-stylesheets { + border-style: dashed; +} diff --git a/packages/e2e-tests/plugins/iframed-multiple-stylesheets/style2.css b/packages/e2e-tests/plugins/iframed-multiple-stylesheets/style2.css new file mode 100644 index 00000000000000..f49bf1d2c963b1 --- /dev/null +++ b/packages/e2e-tests/plugins/iframed-multiple-stylesheets/style2.css @@ -0,0 +1,7 @@ +/** + * The following styles get applied both on the front of your site and in the + * editor. + */ +.wp-block-test-iframed-multiple-stylesheets { + border-color: #f00 !important; +} diff --git a/packages/e2e-tests/plugins/iframed-multiple-stylesheets/style3.css b/packages/e2e-tests/plugins/iframed-multiple-stylesheets/style3.css new file mode 100644 index 00000000000000..56c10870e153f6 --- /dev/null +++ b/packages/e2e-tests/plugins/iframed-multiple-stylesheets/style3.css @@ -0,0 +1,7 @@ +/** + * The following styles get applied both on the front of your site and in the + * editor. + */ + .wp-block-test-iframed-multiple-stylesheets { + background-color: #000 !important; +} diff --git a/packages/e2e-tests/specs/editor/plugins/iframed-multiple-block-stylesheets.test.js b/packages/e2e-tests/specs/editor/plugins/iframed-multiple-block-stylesheets.test.js new file mode 100644 index 00000000000000..647614ec75fa6c --- /dev/null +++ b/packages/e2e-tests/specs/editor/plugins/iframed-multiple-block-stylesheets.test.js @@ -0,0 +1,71 @@ +/** + * WordPress dependencies + */ +import { + activatePlugin, + createNewPost, + deactivatePlugin, + insertBlock, + openDocumentSettingsSidebar, + clickButton, + canvas, +} from '@wordpress/e2e-test-utils'; + +async function getComputedStyle( context, property ) { + await context.waitForSelector( + '.wp-block-test-iframed-multiple-stylesheets' + ); + return await context.evaluate( ( prop ) => { + const container = document.querySelector( + '.wp-block-test-iframed-multiple-stylesheets' + ); + return window.getComputedStyle( container )[ prop ]; + }, property ); +} + +describe( 'iframed multiple block stylesheets', () => { + beforeEach( async () => { + await activatePlugin( 'gutenberg-test-iframed-multiple-stylesheets' ); + await createNewPost( { postType: 'page' } ); + } ); + + afterEach( async () => { + await deactivatePlugin( 'gutenberg-test-iframed-multiple-stylesheets' ); + } ); + + it( 'should load multiple block stylesheets in iframe', async () => { + await insertBlock( 'Iframed Multiple Stylesheets' ); + + await page.waitForSelector( + '.wp-block-test-iframed-multiple-stylesheets' + ); + await openDocumentSettingsSidebar(); + await clickButton( 'Page' ); + await clickButton( 'Template' ); + await clickButton( 'New' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.type( 'Iframed Test' ); + await clickButton( 'Create' ); + await page.waitForSelector( 'iframe[name="editor-canvas"]' ); + + // Style loaded from the main stylesheet. + expect( await getComputedStyle( canvas(), 'border-style' ) ).toBe( + 'dashed' + ); + + // Style loaded from the additional stylesheet. + expect( await getComputedStyle( canvas(), 'border-color' ) ).toBe( + 'rgb(255, 0, 0)' + ); + + // Style loaded from the a stylesheet using path instead of handle. + expect( await getComputedStyle( canvas(), 'background-color' ) ).toBe( + 'rgb(0, 0, 0)' + ); + + // Skip errors related to block-styles enqueing and the use of add_editor_style. + // The issue is tracked on https://github.com/WordPress/gutenberg/issues/33212. + expect( console ).toHaveErrored(); + } ); +} );