From 5c83713c2676dcfc757558bfca6215f31bb71d22 Mon Sep 17 00:00:00 2001 From: ramon Date: Tue, 9 Apr 2024 11:39:49 +1000 Subject: [PATCH 01/15] Supporting background.backgroundImage.source === "theme" relative paths --- lib/block-supports/background.php | 23 ++++++++++++- lib/class-wp-theme-json-gutenberg.php | 4 +-- phpunit/block-supports/background-test.php | 40 ++++++++++++++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index 70957897229595..90fa38f410a407 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -30,6 +30,27 @@ function gutenberg_register_background_support( $block_type ) { } } +/** + * Given a theme.json or block background styles, returns the background styles for a block. + * + * @since 6.6.0 + * + * @param array $background_styles Background style properties. + * @return array Style engine array of CSS string and style declarations. + */ +function gutenberg_get_background_support_styles( $background_styles = array() ) { + $background_image_source = ! empty( $background_styles['backgroundImage']['source'] ) ? $background_styles['backgroundImage']['source'] : null; + + /* + * "theme" source implies relative path to the theme directory + */ + if ( 'theme' === $background_image_source ) { + $background_styles['backgroundImage']['url'] = esc_url( get_theme_file_uri( $background_styles['backgroundImage']['url'] ) ); + } + return gutenberg_style_engine_get_styles( array( 'background' => $background_styles ) ); +} + + /** * Renders the background styles to the block wrapper. * This block support uses the `render_block` hook to ensure that @@ -66,7 +87,7 @@ function gutenberg_render_background_support( $block_content, $block ) { } } - $styles = gutenberg_style_engine_get_styles( array( 'background' => $background_styles ) ); + $styles = gutenberg_get_background_support_styles( $background_styles ); if ( ! empty( $styles['css'] ) ) { // Inject background styles to the first element, presuming it's the wrapper, if it exists. diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index d73e7aa8566c8d..76dcf7057e2bfb 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2131,7 +2131,7 @@ protected static function flatten_tree( $tree, $prefix = '', $token = '--' ) { return $result; } - /** + /** * Given a styles array, it extracts the style properties * and adds them to the $declarations array following the format: * @@ -2198,7 +2198,7 @@ protected static function compute_style_properties( $styles, $settings = array() // Processes background styles. if ( 'background' === $value_path[0] && isset( $styles['background'] ) ) { - $background_styles = gutenberg_style_engine_get_styles( array( 'background' => $styles['background'] ) ); + $background_styles = gutenberg_get_background_support_styles( $styles['background'] ); $value = $background_styles['declarations'][ $css_property ] ?? $value; } diff --git a/phpunit/block-supports/background-test.php b/phpunit/block-supports/background-test.php index 165a65204793d1..11a276711b54af 100644 --- a/phpunit/block-supports/background-test.php +++ b/phpunit/block-supports/background-test.php @@ -213,4 +213,44 @@ public function data_background_block_support() { ), ); } + + /** + * Tests generating background styles. + * + * @covers ::gutenberg_get_background_support_styles + * + * @dataProvider data_get_background_support_styles + * + * @param mixed $background_style The background styles within the block attributes. + * @param string $expected_css Expected markup for the block wrapper. + */ + public function test_get_background_support_styles( $background_style, $expected_css ) { + switch_theme( 'block-theme' ); + $actual = gutenberg_get_background_support_styles( $background_style )['css']; + + $this->assertEquals( + $expected_css, + $actual, + 'Background CSS should be correct.' + ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_get_background_support_styles() { + return array( + 'css generated with theme source 2' => array( + 'background_style' => array( + 'backgroundImage' => array( + 'url' => 'assets/image/not_there.png', + 'source' => 'theme', + ), + ), + 'expected_css' => "background-image:url('http://localhost:8889/wp-content/plugins/gutenberg/phpunit/data/themedir1/block-theme/assets/image/not_there.png');", + ), + ); + } } From 5b277735f88b5a08cccf911d5322ffda26d74f41 Mon Sep 17 00:00:00 2001 From: ramon Date: Tue, 9 Apr 2024 14:25:49 +1000 Subject: [PATCH 02/15] This is an experimental commit to test out how to: - get the theme directory URI, and - ensure background styles are parsed for theme.json and pattern/template files --- lib/block-supports/background.php | 2 +- lib/compat/wordpress-6.6/rest-api.php | 33 +++++++++ .../global-styles/use-global-styles-output.js | 68 +++++++++++++------ packages/block-editor/src/hooks/background.js | 18 ++++- packages/block-editor/src/hooks/style.js | 34 +++++++++- .../provider/use-block-editor-settings.js | 10 ++- .../src/styles/background/index.ts | 6 +- 7 files changed, 140 insertions(+), 31 deletions(-) diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index 90fa38f410a407..92a707c183700d 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -44,7 +44,7 @@ function gutenberg_get_background_support_styles( $background_styles = array() ) /* * "theme" source implies relative path to the theme directory */ - if ( 'theme' === $background_image_source ) { + if ( ! empty( $background_styles['backgroundImage']['url'] ) && 'theme' === $background_image_source ) { $background_styles['backgroundImage']['url'] = esc_url( get_theme_file_uri( $background_styles['backgroundImage']['url'] ) ); } return gutenberg_style_engine_get_styles( array( 'background' => $background_styles ) ); diff --git a/lib/compat/wordpress-6.6/rest-api.php b/lib/compat/wordpress-6.6/rest-api.php index bf462cd11ca4b4..9fa7ceb3e5373b 100644 --- a/lib/compat/wordpress-6.6/rest-api.php +++ b/lib/compat/wordpress-6.6/rest-api.php @@ -29,3 +29,36 @@ function wp_api_template_access_controller( $args, $post_type ) { } } add_filter( 'register_post_type_args', 'wp_api_template_access_controller', 10, 2 ); + + +/** + * Registers additional fields for WP_REST_Themes_Controller class. + * https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php + */ +function gutenberg_register_wp_theme_directory_uri_field() { + register_rest_field( + 'theme', + 'theme_directory_uri', + array( + 'get_callback' => function ( $item ) { + /* + * In the rest controller, we can use the WP_Theme object methods to get the theme directory URI. + * See: https://developer.wordpress.org/reference/classes/wp_theme/ + */ + if ( ! empty( $item['stylesheet'] ) ) { + $theme = wp_get_theme( $item['stylesheet'] ); + return $theme->get_stylesheet_directory_uri(); + } + return null; + }, + 'schema' => array( + 'type' => 'string', + 'description' => __( 'URL to the directory of the theme root.', 'gutenberg' ), + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ) + ); +} + +add_action( 'rest_api_init', 'gutenberg_register_wp_theme_directory_uri_field' ); diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index e321ea9744e876..8d19558f1fd732 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -35,6 +35,7 @@ import { LAYOUT_DEFINITIONS } from '../../layouts/definitions'; import { getValueFromObjectPath, setImmutably } from '../../utils/object'; import BlockContext from '../block-context'; import { unlock } from '../../lock-unlock'; +import { getBackgroundSupportStyles } from '../../hooks/background'; // List of block support features that can have their related styles // generated under their own feature level selector rather than the block's. @@ -321,7 +322,8 @@ export function getStylesDeclarations( selector = '', useRootPaddingAlign, tree = {}, - isTemplate = true + isTemplate = true, + settings ) { const { kebabCase } = unlock( componentsPrivateApis ); const isRoot = ROOT_BLOCK_SELECTOR === selector; @@ -391,6 +393,21 @@ export function getStylesDeclarations( [] ); + // Set background defaults. + // Applies to all blocks/global styles. + if ( !! blockStyles.background ) { + blockStyles = { + ...blockStyles, + background: { + ...blockStyles.background, + ...getBackgroundSupportStyles( + blockStyles.background, + settings + ), + }, + }; + } + // The goal is to move everything to server side generated engine styles // This is temporary as we absorb more and more styles into the engine. const extraRules = getCSSRules( blockStyles ); @@ -777,7 +794,8 @@ export const toStyles = ( hasFallbackGapSupport, disableLayoutStyles = false, isTemplate = true, - styleOptions = undefined + styleOptions = undefined, + settings = {} ) => { // These allow opting out of certain sets of styles. const options = { @@ -905,7 +923,8 @@ export const toStyles = ( styleVariations, styleVariationSelector, useRootPaddingAlign, - tree + tree, + settings ); if ( styleVariationDeclarations.length ) { ruleset += `${ styleVariationSelector }{${ styleVariationDeclarations.join( @@ -947,19 +966,20 @@ export const toStyles = ( } ); } - // Process the remaining block styles (they use either normal block class or __experimentalSelector). - const declarations = getStylesDeclarations( - styles, - selector, - useRootPaddingAlign, - tree, - isTemplate - ); - if ( declarations?.length ) { - ruleset += `:where(${ selector }){${ declarations.join( - ';' - ) };}`; - } + // Process the remaining block styles (they use either normal block class or __experimentalSelector). + const declarations = getStylesDeclarations( + styles, + selector, + useRootPaddingAlign, + tree, + isTemplate, + settings + ); + if ( declarations?.length ) { + ruleset += `:where(${ selector }){${ declarations.join( + ';' + ) };}`; + } // Check for pseudo selector in `styles` and handle separately. const pseudoSelectorStyles = Object.entries( styles ).filter( @@ -1219,9 +1239,13 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { const [ blockGap ] = useGlobalSetting( 'spacing.blockGap' ); const hasBlockGapSupport = blockGap !== null; const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support. - const disableLayoutStyles = useSelect( ( select ) => { - const { getSettings } = select( blockEditorStore ); - return !! getSettings().disableLayoutStyles; + + const { themeDirURI, disableLayoutStyles } = useSelect( ( select ) => { + const _settings = select( blockEditorStore ).getSettings(); + return { + themeDirURI: _settings?.currentTheme?.theme_directory_uri, + disableLayoutStyles: !! _settings.disableLayoutStyles, + }; } ); const blockContext = useContext( BlockContext ); @@ -1252,7 +1276,10 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { hasBlockGapSupport, hasFallbackGapSupport, disableLayoutStyles, - isTemplate + isTemplate, + { + themeDirURI, + } ); const svgs = toSvgFilters( updatedConfig, blockSelectors ); @@ -1301,6 +1328,7 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { disableLayoutStyles, isTemplate, getBlockStyles, + themeDirURI, ] ); } diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 3d47f42645afca..5cbb9fde485563 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -50,6 +50,22 @@ export function hasBackgroundSupport( blockName, feature = 'any' ) { return !! support?.[ feature ]; } +export function getBackgroundSupportStyles( backgroundStyle, options ) { + const backgroundImage = backgroundStyle?.backgroundImage; + if ( + backgroundImage?.source === 'theme' && + !! backgroundImage?.url && + options?.themeDirURI + ) { + return { + backgroundImage: { + url: `${ options.themeDirURI }${ backgroundImage.url }`, + source: 'file', + }, + }; + } +} + export function setBackgroundStyleDefaults( backgroundStyle ) { if ( ! backgroundStyle ) { return; @@ -59,7 +75,7 @@ export function setBackgroundStyleDefaults( backgroundStyle ) { let backgroundStylesWithDefaults; // Set block background defaults. - if ( backgroundImage?.source === 'file' && !! backgroundImage?.url ) { + if ( !! backgroundImage?.url ) { if ( ! backgroundStyle?.backgroundSize ) { backgroundStylesWithDefaults = { backgroundSize: 'cover', diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index dad62bc0594a75..1a96c77dd0582c 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -10,11 +10,16 @@ import { } from '@wordpress/blocks'; import { useInstanceId } from '@wordpress/compose'; import { getCSSRules, compileCSS } from '@wordpress/style-engine'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ -import { BACKGROUND_SUPPORT_KEY, BackgroundImagePanel } from './background'; +import { + BACKGROUND_SUPPORT_KEY, + BackgroundImagePanel, + getBackgroundSupportStyles, +} from './background'; import { BORDER_SUPPORT_KEY, BorderPanel, SHADOW_SUPPORT_KEY } from './border'; import { COLOR_SUPPORT_KEY, ColorEdit } from './color'; import { @@ -34,6 +39,7 @@ import { } from './utils'; import { scopeSelector } from '../components/global-styles/utils'; import { useBlockEditingMode } from '../components/block-editing-mode'; +import { store as blockEditorStore } from '../store'; const styleSupportKeys = [ ...TYPOGRAPHY_SUPPORT_KEYS, @@ -288,7 +294,8 @@ export function addSaveProps( props, blockNameOrType, attributes, - skipPaths = skipSerializationPathsSave + skipPaths = skipSerializationPathsSave, + settings, ) { if ( ! hasStyleSupport( blockNameOrType ) ) { return props; @@ -312,6 +319,18 @@ export function addSaveProps( } } ); + // Set background defaults. + // Applies to all blocks/global styles. + if ( !! style.background ) { + style = { + ...style, + background: { + ...style.background, + ...getBackgroundSupportStyles( style.background, settings ), + }, + }; + } + props.style = { ...getInlineStyles( style ), ...props.style, @@ -369,6 +388,12 @@ const elementTypes = [ ]; function useBlockProps( { name, style } ) { + const { themeDirURI } = useSelect( ( select ) => { + const _settings = select( blockEditorStore ).getSettings(); + return { + themeDirURI: _settings?.currentTheme?.theme_directory_uri, + }; + } ); const blockElementsContainerIdentifier = `wp-elements-${ useInstanceId( useBlockProps ) }`; @@ -455,7 +480,10 @@ function useBlockProps( { name, style } ) { { className: blockElementsContainerIdentifier }, name, { style }, - skipSerializationPathsEdit + skipSerializationPathsEdit, + { + themeDirURI, + } ); } diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index bcd08856141831..4fafba288ac451 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -101,6 +101,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { const { allowRightClickOverrides, blockTypes, + currentTheme, focusMode, hasFixedToolbar, isDistractionFree, @@ -122,6 +123,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { getEntityRecord, getUserPatternCategories, getBlockPatternCategories, + getCurrentTheme, } = select( coreStore ); const { get } = select( preferencesStore ); const { getBlockTypes } = select( blocksStore ); @@ -130,7 +132,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { const siteSettings = canUser( 'read', 'settings' ) ? getEntityRecord( 'root', 'site' ) : undefined; - + const _currentTheme = getCurrentTheme(); function getSectionRootBlock() { if ( renderingMode === 'template-locked' ) { return getBlocksByName( 'core/post-content' )?.[ 0 ] ?? ''; @@ -150,6 +152,10 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { 'allowRightClickOverrides' ), blockTypes: getBlockTypes(), + currentTheme: { + name: _currentTheme?.name, + theme_directory_uri: _currentTheme?.theme_directory_uri, + }, canUseUnfilteredHTML: getRawEntityRecord( 'postType', postType, @@ -261,6 +267,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { ), allowedBlockTypes, allowRightClickOverrides, + currentTheme, focusMode: focusMode && ! forceDisableFocusMode, hasFixedToolbar, isDistractionFree, @@ -327,6 +334,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { postType, setIsInserterOpened, sectionRootClientId, + currentTheme, ] ); } diff --git a/packages/style-engine/src/styles/background/index.ts b/packages/style-engine/src/styles/background/index.ts index 748cb15b4f3099..a8c8679888e153 100644 --- a/packages/style-engine/src/styles/background/index.ts +++ b/packages/style-engine/src/styles/background/index.ts @@ -8,11 +8,7 @@ const backgroundImage = { name: 'backgroundImage', generate: ( style: Style, options: StyleOptions ) => { const _backgroundImage = style?.background?.backgroundImage; - if ( - typeof _backgroundImage === 'object' && - _backgroundImage?.source === 'file' && - _backgroundImage?.url - ) { + if ( typeof _backgroundImage === 'object' && _backgroundImage?.url ) { return [ { selector: options.selector, From 6bf575a27fe8ba674c341c5b0eb40f9783c3d958 Mon Sep 17 00:00:00 2001 From: ramon Date: Wed, 10 Apr 2024 11:49:20 +1000 Subject: [PATCH 03/15] Roll back API changes and insert into editor settings under `currentTheme` both parent and child dir Update tests to check for image paths with leading slash Revert rogue tab --- lib/block-editor-settings.php | 7 ++++ lib/block-supports/background.php | 7 ++-- lib/class-wp-theme-json-gutenberg.php | 2 +- lib/compat/wordpress-6.6/rest-api.php | 33 ------------------- .../global-styles/use-global-styles-output.js | 11 ++++--- packages/block-editor/src/hooks/style.js | 11 ++++--- .../provider/use-block-editor-settings.js | 10 ++---- phpunit/block-supports/background-test.php | 11 ++++++- 8 files changed, 38 insertions(+), 54 deletions(-) diff --git a/lib/block-editor-settings.php b/lib/block-editor-settings.php index 53668e114e04cb..bc0bb278d8c209 100644 --- a/lib/block-editor-settings.php +++ b/lib/block-editor-settings.php @@ -76,6 +76,13 @@ function gutenberg_get_block_editor_settings( $settings ) { } } + // Could house also `__unstableIsBlockBasedTheme` as 'isBlockTheme' => $current_theme->is_block_theme(). + $current_theme = wp_get_theme(); + $settings['currentTheme'] = array( + 'parentDirectoryURI' => $current_theme->get_template_directory_uri(), + 'directoryURI' => $current_theme->get_stylesheet_directory_uri(), + ); + $settings['styles'] = array_merge( $global_styles, get_block_editor_theme_styles() ); $settings['__experimentalFeatures'] = gutenberg_get_global_settings(); diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index 92a707c183700d..71089468b57475 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -44,8 +44,11 @@ function gutenberg_get_background_support_styles( $background_styles = array() ) /* * "theme" source implies relative path to the theme directory */ - if ( ! empty( $background_styles['backgroundImage']['url'] ) && 'theme' === $background_image_source ) { - $background_styles['backgroundImage']['url'] = esc_url( get_theme_file_uri( $background_styles['backgroundImage']['url'] ) ); + if ( ! empty( $background_styles['backgroundImage']['url'] ) && is_string( $background_styles['backgroundImage']['url'] ) && 'theme' === $background_image_source ) { + if ( ! str_starts_with( $background_styles['backgroundImage']['url'], '/' ) ) { + $background_styles['backgroundImage']['url'] = '/' . $background_styles['backgroundImage']['url']; + } + $background_styles['backgroundImage']['url'] = esc_url( get_stylesheet_directory_uri() . $background_styles['backgroundImage']['url'] ); } return gutenberg_style_engine_get_styles( array( 'background' => $background_styles ) ); } diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 76dcf7057e2bfb..1b0d314f6dc39a 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2131,7 +2131,7 @@ protected static function flatten_tree( $tree, $prefix = '', $token = '--' ) { return $result; } - /** + /** * Given a styles array, it extracts the style properties * and adds them to the $declarations array following the format: * diff --git a/lib/compat/wordpress-6.6/rest-api.php b/lib/compat/wordpress-6.6/rest-api.php index 9fa7ceb3e5373b..bf462cd11ca4b4 100644 --- a/lib/compat/wordpress-6.6/rest-api.php +++ b/lib/compat/wordpress-6.6/rest-api.php @@ -29,36 +29,3 @@ function wp_api_template_access_controller( $args, $post_type ) { } } add_filter( 'register_post_type_args', 'wp_api_template_access_controller', 10, 2 ); - - -/** - * Registers additional fields for WP_REST_Themes_Controller class. - * https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php - */ -function gutenberg_register_wp_theme_directory_uri_field() { - register_rest_field( - 'theme', - 'theme_directory_uri', - array( - 'get_callback' => function ( $item ) { - /* - * In the rest controller, we can use the WP_Theme object methods to get the theme directory URI. - * See: https://developer.wordpress.org/reference/classes/wp_theme/ - */ - if ( ! empty( $item['stylesheet'] ) ) { - $theme = wp_get_theme( $item['stylesheet'] ); - return $theme->get_stylesheet_directory_uri(); - } - return null; - }, - 'schema' => array( - 'type' => 'string', - 'description' => __( 'URL to the directory of the theme root.', 'gutenberg' ), - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - ) - ); -} - -add_action( 'rest_api_init', 'gutenberg_register_wp_theme_directory_uri_field' ); diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 8d19558f1fd732..66f3c44f79536a 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -315,6 +315,7 @@ const getFeatureDeclarations = ( selectors, styles ) => { * @param {Object} tree A theme.json tree containing layout definitions. * * @param {boolean} isTemplate Whether the entity being edited is a full template or a pattern. + * @param {Object} editorSettings Current editor settings. * @return {Array} An array of style declarations. */ export function getStylesDeclarations( @@ -323,7 +324,7 @@ export function getStylesDeclarations( useRootPaddingAlign, tree = {}, isTemplate = true, - settings + editorSettings ) { const { kebabCase } = unlock( componentsPrivateApis ); const isRoot = ROOT_BLOCK_SELECTOR === selector; @@ -402,7 +403,7 @@ export function getStylesDeclarations( ...blockStyles.background, ...getBackgroundSupportStyles( blockStyles.background, - settings + editorSettings ), }, }; @@ -795,7 +796,7 @@ export const toStyles = ( disableLayoutStyles = false, isTemplate = true, styleOptions = undefined, - settings = {} + editorSettings = {} ) => { // These allow opting out of certain sets of styles. const options = { @@ -973,7 +974,7 @@ export const toStyles = ( useRootPaddingAlign, tree, isTemplate, - settings + editorSettings ); if ( declarations?.length ) { ruleset += `:where(${ selector }){${ declarations.join( @@ -1243,7 +1244,7 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { const { themeDirURI, disableLayoutStyles } = useSelect( ( select ) => { const _settings = select( blockEditorStore ).getSettings(); return { - themeDirURI: _settings?.currentTheme?.theme_directory_uri, + themeDirURI: _settings?.currentTheme?.directoryURI, disableLayoutStyles: !! _settings.disableLayoutStyles, }; } ); diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 1a96c77dd0582c..82c16ef29ac709 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -287,7 +287,7 @@ export function omitStyle( style, paths, preserveReference = false ) { * @param {Object|string} blockNameOrType Block type. * @param {Object} attributes Block attributes. * @param {?Record} skipPaths An object of keys and paths to skip serialization. - * + * @param {Object} editorSettings Current editor settings. * @return {Object} Filtered props applied to save element. */ export function addSaveProps( @@ -295,7 +295,7 @@ export function addSaveProps( blockNameOrType, attributes, skipPaths = skipSerializationPathsSave, - settings, + editorSettings ) { if ( ! hasStyleSupport( blockNameOrType ) ) { return props; @@ -326,7 +326,10 @@ export function addSaveProps( ...style, background: { ...style.background, - ...getBackgroundSupportStyles( style.background, settings ), + ...getBackgroundSupportStyles( + style.background, + editorSettings + ), }, }; } @@ -391,7 +394,7 @@ function useBlockProps( { name, style } ) { const { themeDirURI } = useSelect( ( select ) => { const _settings = select( blockEditorStore ).getSettings(); return { - themeDirURI: _settings?.currentTheme?.theme_directory_uri, + themeDirURI: _settings?.currentTheme?.directoryURI, }; } ); const blockElementsContainerIdentifier = `wp-elements-${ useInstanceId( diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 4fafba288ac451..d0785dca56acb2 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -50,6 +50,7 @@ const BLOCK_EDITOR_SETTINGS = [ 'clearBlockSelection', 'codeEditingEnabled', 'colors', + 'currentTheme', 'disableCustomColors', 'disableCustomFontSizes', 'disableCustomSpacingSizes', @@ -101,7 +102,6 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { const { allowRightClickOverrides, blockTypes, - currentTheme, focusMode, hasFixedToolbar, isDistractionFree, @@ -123,7 +123,6 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { getEntityRecord, getUserPatternCategories, getBlockPatternCategories, - getCurrentTheme, } = select( coreStore ); const { get } = select( preferencesStore ); const { getBlockTypes } = select( blocksStore ); @@ -132,6 +131,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { const siteSettings = canUser( 'read', 'settings' ) ? getEntityRecord( 'root', 'site' ) : undefined; + const _currentTheme = getCurrentTheme(); function getSectionRootBlock() { if ( renderingMode === 'template-locked' ) { @@ -152,10 +152,6 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { 'allowRightClickOverrides' ), blockTypes: getBlockTypes(), - currentTheme: { - name: _currentTheme?.name, - theme_directory_uri: _currentTheme?.theme_directory_uri, - }, canUseUnfilteredHTML: getRawEntityRecord( 'postType', postType, @@ -267,7 +263,6 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { ), allowedBlockTypes, allowRightClickOverrides, - currentTheme, focusMode: focusMode && ! forceDisableFocusMode, hasFixedToolbar, isDistractionFree, @@ -334,7 +329,6 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { postType, setIsInserterOpened, sectionRootClientId, - currentTheme, ] ); } diff --git a/phpunit/block-supports/background-test.php b/phpunit/block-supports/background-test.php index 11a276711b54af..c11531c7916722 100644 --- a/phpunit/block-supports/background-test.php +++ b/phpunit/block-supports/background-test.php @@ -242,7 +242,16 @@ public function test_get_background_support_styles( $background_style, $expected */ public function data_get_background_support_styles() { return array( - 'css generated with theme source 2' => array( + 'css generated with theme background image path' => array( + 'background_style' => array( + 'backgroundImage' => array( + 'url' => '/assets/image/not_there.png', + 'source' => 'theme', + ), + ), + 'expected_css' => "background-image:url('http://localhost:8889/wp-content/plugins/gutenberg/phpunit/data/themedir1/block-theme/assets/image/not_there.png');", + ), + 'css generated with theme background image path and no preceding slash' => array( 'background_style' => array( 'backgroundImage' => array( 'url' => 'assets/image/not_there.png', From 967bbacf290110991f0c0b67816b0f6029c933d4 Mon Sep 17 00:00:00 2001 From: ramon Date: Thu, 11 Apr 2024 14:59:14 +1000 Subject: [PATCH 04/15] If we pass a 'baseUrl' to the style engine, it will it append it to all url-like paths. Revert rogue space --- lib/block-editor-settings.php | 4 ++- lib/block-supports/background.php | 8 ++--- .../global-styles/use-global-styles-output.js | 20 ++---------- packages/block-editor/src/hooks/background.js | 16 ---------- packages/block-editor/src/hooks/style.js | 32 +++++-------------- .../style-engine/class-wp-style-engine.php | 23 +++++++++---- .../src/styles/background/index.ts | 12 +++++-- packages/style-engine/src/types.ts | 1 + packages/style-engine/style-engine.php | 1 + 9 files changed, 45 insertions(+), 72 deletions(-) diff --git a/lib/block-editor-settings.php b/lib/block-editor-settings.php index bc0bb278d8c209..58d4384e4245ff 100644 --- a/lib/block-editor-settings.php +++ b/lib/block-editor-settings.php @@ -76,11 +76,13 @@ function gutenberg_get_block_editor_settings( $settings ) { } } - // Could house also `__unstableIsBlockBasedTheme` as 'isBlockTheme' => $current_theme->is_block_theme(). $current_theme = wp_get_theme(); $settings['currentTheme'] = array( + // Directory of the current or parent theme. If a child theme is active, it's the parent theme directory. 'parentDirectoryURI' => $current_theme->get_template_directory_uri(), + // Directory of the current theme. Will be the child theme directory if a child theme is active. 'directoryURI' => $current_theme->get_stylesheet_directory_uri(), + // `__unstableIsBlockBasedTheme` could also be relocated here, e.g., 'isBlockTheme' => $current_theme->is_block_theme(). ); $settings['styles'] = array_merge( $global_styles, get_block_editor_theme_styles() ); diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index 71089468b57475..b66f23b7c2f259 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -39,18 +39,16 @@ function gutenberg_register_background_support( $block_type ) { * @return array Style engine array of CSS string and style declarations. */ function gutenberg_get_background_support_styles( $background_styles = array() ) { + $style_engine_options = array(); $background_image_source = ! empty( $background_styles['backgroundImage']['source'] ) ? $background_styles['backgroundImage']['source'] : null; /* * "theme" source implies relative path to the theme directory */ if ( ! empty( $background_styles['backgroundImage']['url'] ) && is_string( $background_styles['backgroundImage']['url'] ) && 'theme' === $background_image_source ) { - if ( ! str_starts_with( $background_styles['backgroundImage']['url'], '/' ) ) { - $background_styles['backgroundImage']['url'] = '/' . $background_styles['backgroundImage']['url']; - } - $background_styles['backgroundImage']['url'] = esc_url( get_stylesheet_directory_uri() . $background_styles['backgroundImage']['url'] ); + $style_engine_options['base_url'] = esc_url( get_stylesheet_directory_uri() ); } - return gutenberg_style_engine_get_styles( array( 'background' => $background_styles ) ); + return gutenberg_style_engine_get_styles( array( 'background' => $background_styles ), $style_engine_options ); } diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 66f3c44f79536a..87125f927019f4 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -35,7 +35,6 @@ import { LAYOUT_DEFINITIONS } from '../../layouts/definitions'; import { getValueFromObjectPath, setImmutably } from '../../utils/object'; import BlockContext from '../block-context'; import { unlock } from '../../lock-unlock'; -import { getBackgroundSupportStyles } from '../../hooks/background'; // List of block support features that can have their related styles // generated under their own feature level selector rather than the block's. @@ -394,24 +393,11 @@ export function getStylesDeclarations( [] ); - // Set background defaults. - // Applies to all blocks/global styles. - if ( !! blockStyles.background ) { - blockStyles = { - ...blockStyles, - background: { - ...blockStyles.background, - ...getBackgroundSupportStyles( - blockStyles.background, - editorSettings - ), - }, - }; - } - // The goal is to move everything to server side generated engine styles // This is temporary as we absorb more and more styles into the engine. - const extraRules = getCSSRules( blockStyles ); + const extraRules = getCSSRules( blockStyles, { + baseUrl: editorSettings?.themeDirURI, + } ); extraRules.forEach( ( rule ) => { // Don't output padding properties if padding variables are set or if we're not editing a full template. if ( diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 5cbb9fde485563..3e23efcbf5fc96 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -50,22 +50,6 @@ export function hasBackgroundSupport( blockName, feature = 'any' ) { return !! support?.[ feature ]; } -export function getBackgroundSupportStyles( backgroundStyle, options ) { - const backgroundImage = backgroundStyle?.backgroundImage; - if ( - backgroundImage?.source === 'theme' && - !! backgroundImage?.url && - options?.themeDirURI - ) { - return { - backgroundImage: { - url: `${ options.themeDirURI }${ backgroundImage.url }`, - source: 'file', - }, - }; - } -} - export function setBackgroundStyleDefaults( backgroundStyle ) { if ( ! backgroundStyle ) { return; diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 82c16ef29ac709..c96c128a58c790 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -15,11 +15,7 @@ import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ -import { - BACKGROUND_SUPPORT_KEY, - BackgroundImagePanel, - getBackgroundSupportStyles, -} from './background'; +import { BACKGROUND_SUPPORT_KEY, BackgroundImagePanel } from './background'; import { BORDER_SUPPORT_KEY, BorderPanel, SHADOW_SUPPORT_KEY } from './border'; import { COLOR_SUPPORT_KEY, ColorEdit } from './color'; import { @@ -57,15 +53,16 @@ const hasStyleSupport = ( nameOrType ) => /** * Returns the inline styles to add depending on the style object * - * @param {Object} styles Styles configuration. + * @param {Object} styles Styles configuration. + * @param {Object} options Style engine options. * * @return {Object} Flattened CSS variables declaration. */ -export function getInlineStyles( styles = {} ) { +export function getInlineStyles( styles = {}, options ) { const output = {}; // The goal is to move everything to server side generated engine styles // This is temporary as we absorb more and more styles into the engine. - getCSSRules( styles ).forEach( ( rule ) => { + getCSSRules( styles, options ).forEach( ( rule ) => { output[ rule.key ] = rule.value; } ); @@ -319,23 +316,10 @@ export function addSaveProps( } } ); - // Set background defaults. - // Applies to all blocks/global styles. - if ( !! style.background ) { - style = { - ...style, - background: { - ...style.background, - ...getBackgroundSupportStyles( - style.background, - editorSettings - ), - }, - }; - } - props.style = { - ...getInlineStyles( style ), + ...getInlineStyles( style, { + baseUrl: editorSettings?.themeDirURI, + } ), ...props.style, }; diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php index 272c12705bf880..cc38c778e7f00d 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -355,7 +355,7 @@ protected static function is_valid_style_value( $style_value ) { * @param string $store_name A valid store key. * @param string $css_selector When a selector is passed, the function will return a full CSS rule `$selector { ...rules }`, otherwise a concatenated string of properties and values. * @param string[] $css_declarations An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ). - * @param string $rules_group Optional. A parent CSS selector in the case of nested CSS, or a CSS nested @rule, such as `@media (min-width: 80rem)` or `@layer module`. + * @param string $rules_group Optional. A parent CSS selector in the case of nested CSS, or a CSS nested @rule, such as `@media (min-width: 80rem)` or `@layer module`. * * @return void. */ @@ -589,14 +589,19 @@ protected static function get_individual_property_css_declarations( $style_value * Style value parser that constructs a CSS definition array comprising a single CSS property and value. * If the provided value is an array containing a `url` property, the function will return a CSS definition array * with a single property and value, with `url` escaped and injected into a CSS `url()` function, - * e.g., array( 'background-image' => "url( '...' )" ). + * e.g., array( 'background-image' => "url( '...' )" ). If a $base_url exists, it will be appended to the URL. * * @param array $style_value A single raw style value from $block_styles array. * @param array $style_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA. + * @param array $options { + * Optional. An array of options. Default empty array. + * + * @type string $base_url A URL to the theme directory to be used as a base for relative URLs. + * } * * @return string[] An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ). */ - protected static function get_url_or_value_css_declaration( $style_value, $style_definition ) { + protected static function get_url_or_value_css_declaration( $style_value, $style_definition, $options = array() ) { if ( empty( $style_value ) ) { return array(); } @@ -605,9 +610,15 @@ protected static function get_url_or_value_css_declaration( $style_value, $style if ( isset( $style_definition['property_keys']['default'] ) ) { $value = null; - - if ( ! empty( $style_value['url'] ) ) { - $value = "url('" . $style_value['url'] . "')"; + if ( ! empty( $style_value['url'] ) && is_string( $style_value['url'] ) ) { + $url = $style_value['url']; + if ( ! empty( $options['base_url'] ) ) { + if ( ! str_starts_with( $url, '/' ) ) { + $url = '/' . $url; + } + $url = esc_url( $options['base_url'] . $url ); + } + $value = "url('" . $url . "')"; } elseif ( is_string( $style_value ) ) { $value = $style_value; } diff --git a/packages/style-engine/src/styles/background/index.ts b/packages/style-engine/src/styles/background/index.ts index a8c8679888e153..98338e22a2c34c 100644 --- a/packages/style-engine/src/styles/background/index.ts +++ b/packages/style-engine/src/styles/background/index.ts @@ -9,14 +9,20 @@ const backgroundImage = { generate: ( style: Style, options: StyleOptions ) => { const _backgroundImage = style?.background?.backgroundImage; if ( typeof _backgroundImage === 'object' && _backgroundImage?.url ) { + const url = !! options?.baseUrl + ? `${ options.baseUrl }${ + _backgroundImage.url.startsWith( '/' ) + ? _backgroundImage.url + : `/${ _backgroundImage.url }` + }` + : _backgroundImage.url; + return [ { selector: options.selector, key: 'backgroundImage', // Passed `url` may already be encoded. To prevent double encoding, decodeURI is executed to revert to the original string. - value: `url( '${ encodeURI( - safeDecodeURI( _backgroundImage.url ) - ) }' )`, + value: `url( '${ encodeURI( safeDecodeURI( url ) ) }' )`, }, ]; } diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index 5b361836a8e375..f8b90acb21058e 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -90,6 +90,7 @@ export interface StyleOptions { * CSS selector for the generated style. */ selector?: string; + baseUrl?: string; } export interface GeneratedCSSRule { diff --git a/packages/style-engine/style-engine.php b/packages/style-engine/style-engine.php index 74df1b1040f6c7..56ac211cdb6bed 100644 --- a/packages/style-engine/style-engine.php +++ b/packages/style-engine/style-engine.php @@ -30,6 +30,7 @@ * @type bool $convert_vars_to_classnames Whether to skip converting incoming CSS var patterns, e.g., `var:preset||`, to var( --wp--preset--* ) values. Default `false`. * @type string $selector Optional. When a selector is passed, the value of `$css` in the return value will comprise a full CSS rule `$selector { ...$css_declarations }`, * otherwise, the value will be a concatenated string of CSS declarations. + * @type string $base_url A URL to the theme directory to be used as a base for relative URLs. * } * * @return array { From e65bf84a1ea9ecebe1b8cc2d96b517a6353116b9 Mon Sep 17 00:00:00 2001 From: ramon Date: Thu, 11 Apr 2024 16:54:18 +1000 Subject: [PATCH 05/15] Rolls back f7bf075d4a0b143008f1809c8254ebab61492e00 --- lib/block-supports/background.php | 8 +++-- .../global-styles/use-global-styles-output.js | 20 ++++++++++-- packages/block-editor/src/hooks/background.js | 16 ++++++++++ packages/block-editor/src/hooks/style.js | 32 ++++++++++++++----- .../style-engine/class-wp-style-engine.php | 23 ++++--------- .../src/styles/background/index.ts | 12 ++----- packages/style-engine/src/types.ts | 1 - packages/style-engine/style-engine.php | 1 - 8 files changed, 71 insertions(+), 42 deletions(-) diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index b66f23b7c2f259..71089468b57475 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -39,16 +39,18 @@ function gutenberg_register_background_support( $block_type ) { * @return array Style engine array of CSS string and style declarations. */ function gutenberg_get_background_support_styles( $background_styles = array() ) { - $style_engine_options = array(); $background_image_source = ! empty( $background_styles['backgroundImage']['source'] ) ? $background_styles['backgroundImage']['source'] : null; /* * "theme" source implies relative path to the theme directory */ if ( ! empty( $background_styles['backgroundImage']['url'] ) && is_string( $background_styles['backgroundImage']['url'] ) && 'theme' === $background_image_source ) { - $style_engine_options['base_url'] = esc_url( get_stylesheet_directory_uri() ); + if ( ! str_starts_with( $background_styles['backgroundImage']['url'], '/' ) ) { + $background_styles['backgroundImage']['url'] = '/' . $background_styles['backgroundImage']['url']; + } + $background_styles['backgroundImage']['url'] = esc_url( get_stylesheet_directory_uri() . $background_styles['backgroundImage']['url'] ); } - return gutenberg_style_engine_get_styles( array( 'background' => $background_styles ), $style_engine_options ); + return gutenberg_style_engine_get_styles( array( 'background' => $background_styles ) ); } diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 87125f927019f4..66f3c44f79536a 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -35,6 +35,7 @@ import { LAYOUT_DEFINITIONS } from '../../layouts/definitions'; import { getValueFromObjectPath, setImmutably } from '../../utils/object'; import BlockContext from '../block-context'; import { unlock } from '../../lock-unlock'; +import { getBackgroundSupportStyles } from '../../hooks/background'; // List of block support features that can have their related styles // generated under their own feature level selector rather than the block's. @@ -393,11 +394,24 @@ export function getStylesDeclarations( [] ); + // Set background defaults. + // Applies to all blocks/global styles. + if ( !! blockStyles.background ) { + blockStyles = { + ...blockStyles, + background: { + ...blockStyles.background, + ...getBackgroundSupportStyles( + blockStyles.background, + editorSettings + ), + }, + }; + } + // The goal is to move everything to server side generated engine styles // This is temporary as we absorb more and more styles into the engine. - const extraRules = getCSSRules( blockStyles, { - baseUrl: editorSettings?.themeDirURI, - } ); + const extraRules = getCSSRules( blockStyles ); extraRules.forEach( ( rule ) => { // Don't output padding properties if padding variables are set or if we're not editing a full template. if ( diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 3e23efcbf5fc96..5cbb9fde485563 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -50,6 +50,22 @@ export function hasBackgroundSupport( blockName, feature = 'any' ) { return !! support?.[ feature ]; } +export function getBackgroundSupportStyles( backgroundStyle, options ) { + const backgroundImage = backgroundStyle?.backgroundImage; + if ( + backgroundImage?.source === 'theme' && + !! backgroundImage?.url && + options?.themeDirURI + ) { + return { + backgroundImage: { + url: `${ options.themeDirURI }${ backgroundImage.url }`, + source: 'file', + }, + }; + } +} + export function setBackgroundStyleDefaults( backgroundStyle ) { if ( ! backgroundStyle ) { return; diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index c96c128a58c790..82c16ef29ac709 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -15,7 +15,11 @@ import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ -import { BACKGROUND_SUPPORT_KEY, BackgroundImagePanel } from './background'; +import { + BACKGROUND_SUPPORT_KEY, + BackgroundImagePanel, + getBackgroundSupportStyles, +} from './background'; import { BORDER_SUPPORT_KEY, BorderPanel, SHADOW_SUPPORT_KEY } from './border'; import { COLOR_SUPPORT_KEY, ColorEdit } from './color'; import { @@ -53,16 +57,15 @@ const hasStyleSupport = ( nameOrType ) => /** * Returns the inline styles to add depending on the style object * - * @param {Object} styles Styles configuration. - * @param {Object} options Style engine options. + * @param {Object} styles Styles configuration. * * @return {Object} Flattened CSS variables declaration. */ -export function getInlineStyles( styles = {}, options ) { +export function getInlineStyles( styles = {} ) { const output = {}; // The goal is to move everything to server side generated engine styles // This is temporary as we absorb more and more styles into the engine. - getCSSRules( styles, options ).forEach( ( rule ) => { + getCSSRules( styles ).forEach( ( rule ) => { output[ rule.key ] = rule.value; } ); @@ -316,10 +319,23 @@ export function addSaveProps( } } ); + // Set background defaults. + // Applies to all blocks/global styles. + if ( !! style.background ) { + style = { + ...style, + background: { + ...style.background, + ...getBackgroundSupportStyles( + style.background, + editorSettings + ), + }, + }; + } + props.style = { - ...getInlineStyles( style, { - baseUrl: editorSettings?.themeDirURI, - } ), + ...getInlineStyles( style ), ...props.style, }; diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php index cc38c778e7f00d..272c12705bf880 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -355,7 +355,7 @@ protected static function is_valid_style_value( $style_value ) { * @param string $store_name A valid store key. * @param string $css_selector When a selector is passed, the function will return a full CSS rule `$selector { ...rules }`, otherwise a concatenated string of properties and values. * @param string[] $css_declarations An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ). - * @param string $rules_group Optional. A parent CSS selector in the case of nested CSS, or a CSS nested @rule, such as `@media (min-width: 80rem)` or `@layer module`. + * @param string $rules_group Optional. A parent CSS selector in the case of nested CSS, or a CSS nested @rule, such as `@media (min-width: 80rem)` or `@layer module`. * * @return void. */ @@ -589,19 +589,14 @@ protected static function get_individual_property_css_declarations( $style_value * Style value parser that constructs a CSS definition array comprising a single CSS property and value. * If the provided value is an array containing a `url` property, the function will return a CSS definition array * with a single property and value, with `url` escaped and injected into a CSS `url()` function, - * e.g., array( 'background-image' => "url( '...' )" ). If a $base_url exists, it will be appended to the URL. + * e.g., array( 'background-image' => "url( '...' )" ). * * @param array $style_value A single raw style value from $block_styles array. * @param array $style_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA. - * @param array $options { - * Optional. An array of options. Default empty array. - * - * @type string $base_url A URL to the theme directory to be used as a base for relative URLs. - * } * * @return string[] An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ). */ - protected static function get_url_or_value_css_declaration( $style_value, $style_definition, $options = array() ) { + protected static function get_url_or_value_css_declaration( $style_value, $style_definition ) { if ( empty( $style_value ) ) { return array(); } @@ -610,15 +605,9 @@ protected static function get_url_or_value_css_declaration( $style_value, $style if ( isset( $style_definition['property_keys']['default'] ) ) { $value = null; - if ( ! empty( $style_value['url'] ) && is_string( $style_value['url'] ) ) { - $url = $style_value['url']; - if ( ! empty( $options['base_url'] ) ) { - if ( ! str_starts_with( $url, '/' ) ) { - $url = '/' . $url; - } - $url = esc_url( $options['base_url'] . $url ); - } - $value = "url('" . $url . "')"; + + if ( ! empty( $style_value['url'] ) ) { + $value = "url('" . $style_value['url'] . "')"; } elseif ( is_string( $style_value ) ) { $value = $style_value; } diff --git a/packages/style-engine/src/styles/background/index.ts b/packages/style-engine/src/styles/background/index.ts index 98338e22a2c34c..a8c8679888e153 100644 --- a/packages/style-engine/src/styles/background/index.ts +++ b/packages/style-engine/src/styles/background/index.ts @@ -9,20 +9,14 @@ const backgroundImage = { generate: ( style: Style, options: StyleOptions ) => { const _backgroundImage = style?.background?.backgroundImage; if ( typeof _backgroundImage === 'object' && _backgroundImage?.url ) { - const url = !! options?.baseUrl - ? `${ options.baseUrl }${ - _backgroundImage.url.startsWith( '/' ) - ? _backgroundImage.url - : `/${ _backgroundImage.url }` - }` - : _backgroundImage.url; - return [ { selector: options.selector, key: 'backgroundImage', // Passed `url` may already be encoded. To prevent double encoding, decodeURI is executed to revert to the original string. - value: `url( '${ encodeURI( safeDecodeURI( url ) ) }' )`, + value: `url( '${ encodeURI( + safeDecodeURI( _backgroundImage.url ) + ) }' )`, }, ]; } diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index f8b90acb21058e..5b361836a8e375 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -90,7 +90,6 @@ export interface StyleOptions { * CSS selector for the generated style. */ selector?: string; - baseUrl?: string; } export interface GeneratedCSSRule { diff --git a/packages/style-engine/style-engine.php b/packages/style-engine/style-engine.php index 56ac211cdb6bed..74df1b1040f6c7 100644 --- a/packages/style-engine/style-engine.php +++ b/packages/style-engine/style-engine.php @@ -30,7 +30,6 @@ * @type bool $convert_vars_to_classnames Whether to skip converting incoming CSS var patterns, e.g., `var:preset||`, to var( --wp--preset--* ) values. Default `false`. * @type string $selector Optional. When a selector is passed, the value of `$css` in the return value will comprise a full CSS rule `$selector { ...$css_declarations }`, * otherwise, the value will be a concatenated string of CSS declarations. - * @type string $base_url A URL to the theme directory to be used as a base for relative URLs. * } * * @return array { From 9e517d3e03dc7c8bc029a77dee8dc231281f4e32 Mon Sep 17 00:00:00 2001 From: ramon Date: Thu, 11 Apr 2024 17:37:59 +1000 Subject: [PATCH 06/15] Removed useBlockProps and now editing style object directly --- .../global-styles/use-global-styles-output.js | 25 +++---- packages/block-editor/src/hooks/background.js | 71 +++++++------------ packages/block-editor/src/hooks/index.js | 2 - packages/block-editor/src/hooks/style.js | 20 ++---- 4 files changed, 42 insertions(+), 76 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 66f3c44f79536a..1a86ea92a4a423 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -35,7 +35,7 @@ import { LAYOUT_DEFINITIONS } from '../../layouts/definitions'; import { getValueFromObjectPath, setImmutably } from '../../utils/object'; import BlockContext from '../block-context'; import { unlock } from '../../lock-unlock'; -import { getBackgroundSupportStyles } from '../../hooks/background'; +import { setBackgroundStyleDefaults } from '../../hooks/background'; // List of block support features that can have their related styles // generated under their own feature level selector rather than the block's. @@ -394,19 +394,16 @@ export function getStylesDeclarations( [] ); - // Set background defaults. - // Applies to all blocks/global styles. - if ( !! blockStyles.background ) { - blockStyles = { - ...blockStyles, - background: { - ...blockStyles.background, - ...getBackgroundSupportStyles( - blockStyles.background, - editorSettings - ), - }, - }; + /* + * Set styles defaults. + * Applies default values to the style object based on the block settings. + * Only applies to background styles for now. + */ + if ( !! blockStyles?.background ) { + blockStyles = setBackgroundStyleDefaults( blockStyles, { + ...editorSettings, + isRoot, + } ); } // The goal is to move everything to server side generated engine styles diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 5cbb9fde485563..09d33eb01be5bc 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -50,68 +50,46 @@ export function hasBackgroundSupport( blockName, feature = 'any' ) { return !! support?.[ feature ]; } -export function getBackgroundSupportStyles( backgroundStyle, options ) { - const backgroundImage = backgroundStyle?.backgroundImage; +export function setBackgroundStyleDefaults( blockStyles, options ) { + const backgroundImage = blockStyles?.background?.backgroundImage; + const newBackgroundStyles = {}; + if ( backgroundImage?.source === 'theme' && !! backgroundImage?.url && - options?.themeDirURI + !! options?.themeDirURI ) { - return { - backgroundImage: { - url: `${ options.themeDirURI }${ backgroundImage.url }`, - source: 'file', - }, + const url = `${ options.themeDirURI }${ + backgroundImage.url.startsWith( '/' ) + ? backgroundImage.url + : `/${ backgroundImage.url }` + }`; + + newBackgroundStyles.backgroundImage = { + ...backgroundImage, + url, }; } -} - -export function setBackgroundStyleDefaults( backgroundStyle ) { - if ( ! backgroundStyle ) { - return; - } - - const backgroundImage = backgroundStyle?.backgroundImage; - let backgroundStylesWithDefaults; // Set block background defaults. - if ( !! backgroundImage?.url ) { - if ( ! backgroundStyle?.backgroundSize ) { - backgroundStylesWithDefaults = { - backgroundSize: 'cover', - }; + if ( ! options?.isRoot && !! backgroundImage?.url ) { + if ( ! blockStyles?.background?.backgroundSize ) { + newBackgroundStyles.backgroundSize = 'cover'; } if ( - 'contain' === backgroundStyle?.backgroundSize && - ! backgroundStyle?.backgroundPosition + 'contain' === blockStyles?.background?.backgroundSize && + ! blockStyles?.background?.backgroundPosition ) { - backgroundStylesWithDefaults = { - backgroundPosition: 'center', - }; + newBackgroundStyles.backgroundPosition = 'center'; } } - return backgroundStylesWithDefaults; -} - -function useBlockProps( { name, style } ) { - if ( - ! hasBackgroundSupport( name ) || - ! style?.background?.backgroundImage - ) { - return; - } - - const backgroundStyles = setBackgroundStyleDefaults( style?.background ); - - if ( ! backgroundStyles ) { - return; - } - return { - style: { - ...backgroundStyles, + ...blockStyles, + background: { + ...blockStyles.background, + ...newBackgroundStyles, }, }; } @@ -198,7 +176,6 @@ export function BackgroundImagePanel( { } export default { - useBlockProps, attributeKeys: [ 'style' ], hasSupport: hasBackgroundSupport, }; diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index ec5cf29b49c5a6..c008a8efa0970b 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -8,7 +8,6 @@ import { } from './utils'; import './compat'; import align from './align'; -import background from './background'; import './lock'; import anchor from './anchor'; import ariaLabel from './aria-label'; @@ -50,7 +49,6 @@ createBlockEditFilter( createBlockListBlockFilter( [ align, textAlign, - background, style, color, dimensions, diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 82c16ef29ac709..4d9fcfbd370fbb 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -18,7 +18,7 @@ import { useSelect } from '@wordpress/data'; import { BACKGROUND_SUPPORT_KEY, BackgroundImagePanel, - getBackgroundSupportStyles, + setBackgroundStyleDefaults, } from './background'; import { BORDER_SUPPORT_KEY, BorderPanel, SHADOW_SUPPORT_KEY } from './border'; import { COLOR_SUPPORT_KEY, ColorEdit } from './color'; @@ -319,19 +319,13 @@ export function addSaveProps( } } ); - // Set background defaults. - // Applies to all blocks/global styles. + /* + * Set styles defaults. + * Applies default values to the style object based on the block settings. + * Only applies to background styles for now. + */ if ( !! style.background ) { - style = { - ...style, - background: { - ...style.background, - ...getBackgroundSupportStyles( - style.background, - editorSettings - ), - }, - }; + style = setBackgroundStyleDefaults( style, editorSettings ); } props.style = { From bbddc1889ba336bf91f37dd41f1500291057dd6f Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 15 Apr 2024 11:28:40 +1000 Subject: [PATCH 07/15] Remove unused "parentDirectoryURI" prop in block editor settings Added/updated unit tests Bad horsie --- lib/block-editor-settings.php | 2 - .../test/use-global-styles-output.js | 28 +++++++ .../global-styles/use-global-styles-output.js | 2 +- packages/block-editor/src/hooks/background.js | 22 ++++- .../block-editor/src/hooks/test/background.js | 83 +++++++++++++++++++ .../provider/use-block-editor-settings.js | 1 - packages/style-engine/src/test/index.js | 1 - 7 files changed, 132 insertions(+), 7 deletions(-) create mode 100644 packages/block-editor/src/hooks/test/background.js diff --git a/lib/block-editor-settings.php b/lib/block-editor-settings.php index 58d4384e4245ff..401ed25c445044 100644 --- a/lib/block-editor-settings.php +++ b/lib/block-editor-settings.php @@ -78,8 +78,6 @@ function gutenberg_get_block_editor_settings( $settings ) { $current_theme = wp_get_theme(); $settings['currentTheme'] = array( - // Directory of the current or parent theme. If a child theme is active, it's the parent theme directory. - 'parentDirectoryURI' => $current_theme->get_template_directory_uri(), // Directory of the current theme. Will be the child theme directory if a child theme is active. 'directoryURI' => $current_theme->get_stylesheet_directory_uri(), // `__unstableIsBlockBasedTheme` could also be relocated here, e.g., 'isBlockTheme' => $current_theme->is_block_theme(). diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js index d835eb0d9a6bbb..3a2b789008da02 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js @@ -990,6 +990,34 @@ describe( 'global styles renderer', () => { 'letter-spacing: 2px', ] ); } ); + + it( 'should process styles and set CSS default values', () => { + const styles = { + background: { + backgroundImage: { + url: 'image.jpg', + source: 'theme', + }, + }, + }; + const editorSettings = { + themeDirURI: 'http://example.com/theme', + }; + + expect( + getStylesDeclarations( + styles, + '.wp-block', + false, + {}, + false, + editorSettings + ) + ).toEqual( [ + "background-image: url( 'http://example.com/theme/image.jpg' )", + 'background-size: cover', + ] ); + } ); } ); describe( 'processCSSNesting', () => { diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 1a86ea92a4a423..23485c1ca464a2 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -402,7 +402,7 @@ export function getStylesDeclarations( if ( !! blockStyles?.background ) { blockStyles = setBackgroundStyleDefaults( blockStyles, { ...editorSettings, - isRoot, + selector, } ); } diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 09d33eb01be5bc..9f2aa5266db910 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -4,6 +4,7 @@ import { getBlockSupport } from '@wordpress/blocks'; import { useSelect } from '@wordpress/data'; import { useCallback } from '@wordpress/element'; +import { safeDecodeURI } from '@wordpress/url'; /** * Internal dependencies @@ -16,6 +17,7 @@ import { useHasBackgroundPanel, hasBackgroundImageValue, } from '../components/global-styles/background-panel'; +import { ROOT_BLOCK_SELECTOR } from '../components/global-styles/utils'; export const BACKGROUND_SUPPORT_KEY = 'background'; @@ -50,7 +52,23 @@ export function hasBackgroundSupport( blockName, feature = 'any' ) { return !! support?.[ feature ]; } +/** + * Updates a styles object with default background values. + * + * @param {Object} blockStyles A styles object. + * @param {Object} options Optional settings. + * @param {string} options.themeDirURI The URI of the current theme directory. + * @param {string} options.selector The block selector. + * @return {Object} Updated styles. + */ export function setBackgroundStyleDefaults( blockStyles, options ) { + if ( + typeof blockStyles?.background !== 'object' || + Object.keys( blockStyles?.background ).length === 0 + ) { + return blockStyles; + } + const backgroundImage = blockStyles?.background?.backgroundImage; const newBackgroundStyles = {}; @@ -67,12 +85,12 @@ export function setBackgroundStyleDefaults( blockStyles, options ) { newBackgroundStyles.backgroundImage = { ...backgroundImage, - url, + url: encodeURI( safeDecodeURI( url ) ), }; } // Set block background defaults. - if ( ! options?.isRoot && !! backgroundImage?.url ) { + if ( options?.selector !== ROOT_BLOCK_SELECTOR && !! backgroundImage ) { if ( ! blockStyles?.background?.backgroundSize ) { newBackgroundStyles.backgroundSize = 'cover'; } diff --git a/packages/block-editor/src/hooks/test/background.js b/packages/block-editor/src/hooks/test/background.js new file mode 100644 index 00000000000000..79be30d3eefb7a --- /dev/null +++ b/packages/block-editor/src/hooks/test/background.js @@ -0,0 +1,83 @@ +/** + * Internal dependencies + */ +import { setBackgroundStyleDefaults } from '../background'; +import { ROOT_BLOCK_SELECTOR } from '../../components/global-styles/utils'; + +describe( 'background', () => { + describe( 'setBackgroundStyleDefaults', () => { + it( 'should return the block styles if the block styles do not have a background', () => { + const blockStyles = { color: 'red' }; + expect( setBackgroundStyleDefaults( blockStyles ) ).toEqual( + blockStyles + ); + } ); + + it( 'should return the block styles if `background` is not an object', () => { + const blockStyles = { background: 'red' }; + expect( setBackgroundStyleDefaults( blockStyles ) ).toEqual( + blockStyles + ); + } ); + + it( 'should return the background size defaults', () => { + const blockStyles = { + background: { backgroundImage: 'some-image.jpg' }, + }; + expect( setBackgroundStyleDefaults( blockStyles ) ).toEqual( { + background: { + backgroundImage: 'some-image.jpg', + backgroundSize: 'cover', + }, + } ); + } ); + + it( 'should return an absolute theme URL path', () => { + const blockStyles = { + background: { + backgroundImage: { + source: 'theme', + url: '/some-image.jpg', + }, + }, + }; + const options = { themeDirURI: 'http://example.com' }; + expect( + setBackgroundStyleDefaults( blockStyles, options ) + ).toEqual( { + background: { + backgroundImage: { + source: 'theme', + url: 'http://example.com/some-image.jpg', + }, + backgroundSize: 'cover', + }, + } ); + } ); + + it( 'should not add background size defaults for root selector', () => { + const blockStyles = { + background: { + backgroundImage: { + source: 'theme', + url: '/some-image.jpg', + }, + }, + }; + const options = { + themeDirURI: 'http://example.com', + selector: ROOT_BLOCK_SELECTOR, + }; + expect( + setBackgroundStyleDefaults( blockStyles, options ) + ).toEqual( { + background: { + backgroundImage: { + source: 'theme', + url: 'http://example.com/some-image.jpg', + }, + }, + } ); + } ); + } ); +} ); diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index d0785dca56acb2..f7f973a6a722bc 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -132,7 +132,6 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { ? getEntityRecord( 'root', 'site' ) : undefined; - const _currentTheme = getCurrentTheme(); function getSectionRootBlock() { if ( renderingMode === 'template-locked' ) { return getBlocksByName( 'core/post-content' )?.[ 0 ] ?? ''; diff --git a/packages/style-engine/src/test/index.js b/packages/style-engine/src/test/index.js index 5869c4a349baab..fbccc8c48bc92b 100644 --- a/packages/style-engine/src/test/index.js +++ b/packages/style-engine/src/test/index.js @@ -226,7 +226,6 @@ describe( 'getCSSRules', () => { { background: { backgroundImage: { - source: 'file', url: 'https://example.com/image.jpg', }, backgroundPosition: '50% 50%', From 1827703193691155886b251270ef1936c8abc741 Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 15 Apr 2024 11:43:02 +1000 Subject: [PATCH 08/15] Yes, spacing. --- lib/block-editor-settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/block-editor-settings.php b/lib/block-editor-settings.php index 401ed25c445044..39b2317cd240db 100644 --- a/lib/block-editor-settings.php +++ b/lib/block-editor-settings.php @@ -79,7 +79,7 @@ function gutenberg_get_block_editor_settings( $settings ) { $current_theme = wp_get_theme(); $settings['currentTheme'] = array( // Directory of the current theme. Will be the child theme directory if a child theme is active. - 'directoryURI' => $current_theme->get_stylesheet_directory_uri(), + 'directoryURI' => $current_theme->get_stylesheet_directory_uri(), // `__unstableIsBlockBasedTheme` could also be relocated here, e.g., 'isBlockTheme' => $current_theme->is_block_theme(). ); From 39b87839d350501885af9526a6e97332d433e43e Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 15 Apr 2024 11:46:45 +1000 Subject: [PATCH 09/15] Unit test no styles --- phpunit/block-supports/background-test.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/phpunit/block-supports/background-test.php b/phpunit/block-supports/background-test.php index c11531c7916722..78aa2cc56a672f 100644 --- a/phpunit/block-supports/background-test.php +++ b/phpunit/block-supports/background-test.php @@ -226,7 +226,7 @@ public function data_background_block_support() { */ public function test_get_background_support_styles( $background_style, $expected_css ) { switch_theme( 'block-theme' ); - $actual = gutenberg_get_background_support_styles( $background_style )['css']; + $actual = gutenberg_get_background_support_styles( $background_style )['css'] ?? null; $this->assertEquals( $expected_css, @@ -242,6 +242,12 @@ public function test_get_background_support_styles( $background_style, $expected */ public function data_get_background_support_styles() { return array( + 'no css generated with no block styles' => array( + 'background_style' => array( + 'backgroundImage' => array(), + ), + 'expected_css' => null, + ), 'css generated with theme background image path' => array( 'background_style' => array( 'backgroundImage' => array( From 8b27b57b2eb20d4eb4890b521f3a40145c42c013 Mon Sep 17 00:00:00 2001 From: ramon Date: Thu, 18 Apr 2024 15:53:35 +1000 Subject: [PATCH 10/15] Getting URI from themes API response --- lib/block-editor-settings.php | 7 -- lib/compat/wordpress-6.6/rest-api.php | 73 +++++++++++++++++++ .../global-styles/use-global-styles-output.js | 2 +- packages/block-editor/src/hooks/style.js | 2 +- packages/core-data/src/entity-types/theme.ts | 8 ++ .../provider/use-block-editor-settings.js | 7 ++ 6 files changed, 90 insertions(+), 9 deletions(-) diff --git a/lib/block-editor-settings.php b/lib/block-editor-settings.php index 39b2317cd240db..53668e114e04cb 100644 --- a/lib/block-editor-settings.php +++ b/lib/block-editor-settings.php @@ -76,13 +76,6 @@ function gutenberg_get_block_editor_settings( $settings ) { } } - $current_theme = wp_get_theme(); - $settings['currentTheme'] = array( - // Directory of the current theme. Will be the child theme directory if a child theme is active. - 'directoryURI' => $current_theme->get_stylesheet_directory_uri(), - // `__unstableIsBlockBasedTheme` could also be relocated here, e.g., 'isBlockTheme' => $current_theme->is_block_theme(). - ); - $settings['styles'] = array_merge( $global_styles, get_block_editor_theme_styles() ); $settings['__experimentalFeatures'] = gutenberg_get_global_settings(); diff --git a/lib/compat/wordpress-6.6/rest-api.php b/lib/compat/wordpress-6.6/rest-api.php index bf462cd11ca4b4..b1d287723a4659 100644 --- a/lib/compat/wordpress-6.6/rest-api.php +++ b/lib/compat/wordpress-6.6/rest-api.php @@ -29,3 +29,76 @@ function wp_api_template_access_controller( $args, $post_type ) { } } add_filter( 'register_post_type_args', 'wp_api_template_access_controller', 10, 2 ); + + +if ( ! function_exists( 'gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field' ) ) { + /** + * Adds `stylesheet_uri` fields to WP_REST_Themes_Controller class. + * Core ticket: https://core.trac.wordpress.org/ticket/61021 + */ + function gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field() { + register_rest_field( + 'theme', + 'stylesheet_uri', + array( + 'get_callback' => function ( $item ) { + if ( ! empty( $item['stylesheet'] ) ) { + $theme = wp_get_theme( $item['stylesheet'] ); + $current_theme = wp_get_theme(); + if ( $theme->get_stylesheet() === $current_theme->get_stylesheet() ) { + return get_stylesheet_directory_uri(); + } else { + return $theme->get_stylesheet_directory_uri(); + } + } + + return null; + }, + 'schema' => array( + 'type' => 'string', + 'description' => __( 'The uri for the theme\'s stylesheet directory.', 'gutenberg' ), + 'format' => 'uri', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ) + ); + } +} +add_action( 'rest_api_init', 'gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field' ); + +if ( ! function_exists( 'gutenberg_register_wp_rest_themes_template_directory_uri_field' ) ) { + /** + * Adds `template_uri` fields to WP_REST_Themes_Controller class. + * Core ticket: https://core.trac.wordpress.org/ticket/61021 + */ + function gutenberg_register_wp_rest_themes_template_directory_uri_field() { + register_rest_field( + 'theme', + 'template_uri', + array( + 'get_callback' => function ( $item ) { + if ( ! empty( $item['stylesheet'] ) ) { + $theme = wp_get_theme( $item['stylesheet'] ); + $current_theme = wp_get_theme(); + if ( $theme->get_stylesheet() === $current_theme->get_stylesheet() ) { + return get_template_directory_uri(); + } else { + return $theme->get_template_directory_uri(); + } + } + + return null; + }, + 'schema' => array( + 'type' => 'string', + 'description' => __( 'The uri for the theme\'s template directory. If this is a child theme, this refers to the parent theme, otherwise this is the same as the theme\'s stylesheet directory.', 'gutenberg' ), + 'format' => 'uri', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ) + ); + } +} +add_action( 'rest_api_init', 'gutenberg_register_wp_rest_themes_template_directory_uri_field' ); diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 23485c1ca464a2..0fbd49ce05602d 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -1241,7 +1241,7 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { const { themeDirURI, disableLayoutStyles } = useSelect( ( select ) => { const _settings = select( blockEditorStore ).getSettings(); return { - themeDirURI: _settings?.currentTheme?.directoryURI, + themeDirURI: _settings?.currentTheme?.stylesheetURI, disableLayoutStyles: !! _settings.disableLayoutStyles, }; } ); diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 4d9fcfbd370fbb..e05e0c70775836 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -388,7 +388,7 @@ function useBlockProps( { name, style } ) { const { themeDirURI } = useSelect( ( select ) => { const _settings = select( blockEditorStore ).getSettings(); return { - themeDirURI: _settings?.currentTheme?.directoryURI, + themeDirURI: _settings?.currentTheme?.stylesheetURI, }; } ); const blockElementsContainerIdentifier = `wp-elements-${ useInstanceId( diff --git a/packages/core-data/src/entity-types/theme.ts b/packages/core-data/src/entity-types/theme.ts index 761c6461d4aca8..ed78906220723d 100644 --- a/packages/core-data/src/entity-types/theme.ts +++ b/packages/core-data/src/entity-types/theme.ts @@ -12,10 +12,18 @@ declare module './base-entity-records' { * The theme's stylesheet. This uniquely identifies the theme. */ stylesheet: string; + /** + * The uri for the theme's stylesheet directory + */ + stylesheet_uri: string; /** * The theme's template. If this is a child theme, this refers to the parent theme, otherwise this is the same as the theme's stylesheet. */ template: string; + /** + * The uri for the theme's template directory. If this is a child theme, this refers to the parent theme, otherwise this is the same as the theme's stylesheet directory. + */ + temnplate_uri: string; /** * The theme author. */ diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index f7f973a6a722bc..887c60bf18ffea 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -102,6 +102,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { const { allowRightClickOverrides, blockTypes, + currentTheme, focusMode, hasFixedToolbar, isDistractionFree, @@ -123,7 +124,9 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { getEntityRecord, getUserPatternCategories, getBlockPatternCategories, + getCurrentTheme, } = select( coreStore ); + const _currentTheme = getCurrentTheme(); const { get } = select( preferencesStore ); const { getBlockTypes } = select( blocksStore ); const { getBlocksByName, getBlockAttributes } = @@ -156,6 +159,9 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { postType, postId )?._links?.hasOwnProperty( 'wp:action-unfiltered-html' ), + currentTheme: { + stylesheetURI: _currentTheme?.stylesheet_uri, + }, focusMode: get( 'core', 'focusMode' ), hasFixedToolbar: get( 'core', 'fixedToolbar' ) || ! isLargeViewport, @@ -262,6 +268,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { ), allowedBlockTypes, allowRightClickOverrides, + currentTheme, focusMode: focusMode && ! forceDisableFocusMode, hasFixedToolbar, isDistractionFree, From f8cda05965eb458c43eb108f4dad46d1957f2b67 Mon Sep 17 00:00:00 2001 From: ramon Date: Thu, 18 Apr 2024 16:23:19 +1000 Subject: [PATCH 11/15] Switching to experimental --- .../global-styles/use-global-styles-output.js | 2 +- packages/block-editor/src/hooks/style.js | 2 +- .../components/provider/use-block-editor-settings.js | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 0fbd49ce05602d..e7f397560c969b 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -1241,7 +1241,7 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { const { themeDirURI, disableLayoutStyles } = useSelect( ( select ) => { const _settings = select( blockEditorStore ).getSettings(); return { - themeDirURI: _settings?.currentTheme?.stylesheetURI, + themeDirURI: _settings?.__experimentalCurrentTheme?.stylesheetURI, disableLayoutStyles: !! _settings.disableLayoutStyles, }; } ); diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index e05e0c70775836..3c482eef848f9e 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -388,7 +388,7 @@ function useBlockProps( { name, style } ) { const { themeDirURI } = useSelect( ( select ) => { const _settings = select( blockEditorStore ).getSettings(); return { - themeDirURI: _settings?.currentTheme?.stylesheetURI, + themeDirURI: _settings?.__experimentalCurrentTheme?.stylesheetURI, }; } ); const blockElementsContainerIdentifier = `wp-elements-${ useInstanceId( diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 887c60bf18ffea..93c2d53632571f 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -50,7 +50,6 @@ const BLOCK_EDITOR_SETTINGS = [ 'clearBlockSelection', 'codeEditingEnabled', 'colors', - 'currentTheme', 'disableCustomColors', 'disableCustomFontSizes', 'disableCustomSpacingSizes', @@ -159,9 +158,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { postType, postId )?._links?.hasOwnProperty( 'wp:action-unfiltered-html' ), - currentTheme: { - stylesheetURI: _currentTheme?.stylesheet_uri, - }, + currentTheme: _currentTheme, focusMode: get( 'core', 'focusMode' ), hasFixedToolbar: get( 'core', 'fixedToolbar' ) || ! isLargeViewport, @@ -268,7 +265,6 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { ), allowedBlockTypes, allowRightClickOverrides, - currentTheme, focusMode: focusMode && ! forceDisableFocusMode, hasFixedToolbar, isDistractionFree, @@ -298,6 +294,9 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { // Check these two properties: they were not present in the site editor. __experimentalCreatePageEntity: createPageEntity, __experimentalUserCanCreatePages: userCanCreatePages, + __experimentalCurrentTheme: { + stylesheetURI: currentTheme?.stylesheet_uri, + }, pageOnFront, pageForPosts, __experimentalPreferPatternsOnRoot: postType === 'wp_template', @@ -316,6 +315,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { }, [ allowedBlockTypes, allowRightClickOverrides, + currentTheme, focusMode, forceDisableFocusMode, hasFixedToolbar, From df2ffb1b9a71d9b7852adef496d208fdbd5d495d Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 29 Apr 2024 19:16:38 +1000 Subject: [PATCH 12/15] Testing get_theme_file_uri on the backend and duping the background image on the frontend. --- lib/block-supports/background.php | 2 +- .../global-styles/use-global-styles-output.js | 29 ++++++++++++------- packages/block-editor/src/hooks/background.js | 27 +++++++++++------ packages/block-editor/src/hooks/style.js | 16 ++++++---- .../provider/use-block-editor-settings.js | 1 + .../src/styles/background/index.ts | 29 +++++++++++++++++-- packages/style-engine/src/types.ts | 3 ++ 7 files changed, 78 insertions(+), 29 deletions(-) diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index 71089468b57475..10169f062039a3 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -48,7 +48,7 @@ function gutenberg_get_background_support_styles( $background_styles = array() ) if ( ! str_starts_with( $background_styles['backgroundImage']['url'], '/' ) ) { $background_styles['backgroundImage']['url'] = '/' . $background_styles['backgroundImage']['url']; } - $background_styles['backgroundImage']['url'] = esc_url( get_stylesheet_directory_uri() . $background_styles['backgroundImage']['url'] ); + $background_styles['backgroundImage']['url'] = esc_url( get_theme_file_uri( $background_styles['backgroundImage']['url'] ) ); } return gutenberg_style_engine_get_styles( array( 'background' => $background_styles ) ); } diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index e7f397560c969b..aa377023dd859a 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -408,7 +408,10 @@ export function getStylesDeclarations( // The goal is to move everything to server side generated engine styles // This is temporary as we absorb more and more styles into the engine. - const extraRules = getCSSRules( blockStyles ); + const extraRules = getCSSRules( blockStyles, { + ...editorSettings, + isRoot, + } ); extraRules.forEach( ( rule ) => { // Don't output padding properties if padding variables are set or if we're not editing a full template. if ( @@ -1238,13 +1241,17 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { const hasBlockGapSupport = blockGap !== null; const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support. - const { themeDirURI, disableLayoutStyles } = useSelect( ( select ) => { - const _settings = select( blockEditorStore ).getSettings(); - return { - themeDirURI: _settings?.__experimentalCurrentTheme?.stylesheetURI, - disableLayoutStyles: !! _settings.disableLayoutStyles, - }; - } ); + const { stylesheetURI, templateURI, disableLayoutStyles } = useSelect( + ( select ) => { + const _settings = select( blockEditorStore ).getSettings(); + return { + stylesheetURI: + _settings?.__experimentalCurrentTheme?.stylesheetURI, + templateURI: _settings?.__experimentalCurrentTheme?.templateURI, + disableLayoutStyles: !! _settings.disableLayoutStyles, + }; + } + ); const blockContext = useContext( BlockContext ); @@ -1276,7 +1283,8 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { disableLayoutStyles, isTemplate, { - themeDirURI, + stylesheetURI, + templateURI, } ); const svgs = toSvgFilters( updatedConfig, blockSelectors ); @@ -1326,7 +1334,8 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { disableLayoutStyles, isTemplate, getBlockStyles, - themeDirURI, + stylesheetURI, + templateURI, ] ); } diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 9f2aa5266db910..894f621643c574 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -55,10 +55,10 @@ export function hasBackgroundSupport( blockName, feature = 'any' ) { /** * Updates a styles object with default background values. * - * @param {Object} blockStyles A styles object. - * @param {Object} options Optional settings. - * @param {string} options.themeDirURI The URI of the current theme directory. - * @param {string} options.selector The block selector. + * @param {Object} blockStyles A styles object. + * @param {Object} options Optional settings. + * @param {string} options.stylesheetURI The URI of the current theme directory. + * @param {string} options.selector The block selector. * @return {Object} Updated styles. */ export function setBackgroundStyleDefaults( blockStyles, options ) { @@ -72,12 +72,19 @@ export function setBackgroundStyleDefaults( blockStyles, options ) { const backgroundImage = blockStyles?.background?.backgroundImage; const newBackgroundStyles = {}; - if ( +/* if ( backgroundImage?.source === 'theme' && !! backgroundImage?.url && - !! options?.themeDirURI + !! options?.stylesheetURI && + !! options?.templateURI ) { - const url = `${ options.themeDirURI }${ + const activeThemeImageResource = `${ options.stylesheetURI }${ + backgroundImage.url.startsWith( '/' ) + ? backgroundImage.url + : `/${ backgroundImage.url }` + }`; + + const parentThemeImageResource = `${ options.templateURI }${ backgroundImage.url.startsWith( '/' ) ? backgroundImage.url : `/${ backgroundImage.url }` @@ -85,9 +92,11 @@ export function setBackgroundStyleDefaults( blockStyles, options ) { newBackgroundStyles.backgroundImage = { ...backgroundImage, - url: encodeURI( safeDecodeURI( url ) ), + url: `${ encodeURI( + safeDecodeURI( activeThemeImageResource ) + ) }, ${ encodeURI( safeDecodeURI( parentThemeImageResource ) ) }`, }; - } + }*/ // Set block background defaults. if ( options?.selector !== ROOT_BLOCK_SELECTOR && !! backgroundImage ) { diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 3c482eef848f9e..120e55bf36dcc5 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -61,11 +61,11 @@ const hasStyleSupport = ( nameOrType ) => * * @return {Object} Flattened CSS variables declaration. */ -export function getInlineStyles( styles = {} ) { +export function getInlineStyles( styles = {}, options ) { const output = {}; // The goal is to move everything to server side generated engine styles // This is temporary as we absorb more and more styles into the engine. - getCSSRules( styles ).forEach( ( rule ) => { + getCSSRules( styles, options ).forEach( ( rule ) => { output[ rule.key ] = rule.value; } ); @@ -329,7 +329,9 @@ export function addSaveProps( } props.style = { - ...getInlineStyles( style ), + ...getInlineStyles( style, { + ...editorSettings, + } ), ...props.style, }; @@ -385,10 +387,11 @@ const elementTypes = [ ]; function useBlockProps( { name, style } ) { - const { themeDirURI } = useSelect( ( select ) => { + const { stylesheetURI, templateURI } = useSelect( ( select ) => { const _settings = select( blockEditorStore ).getSettings(); return { - themeDirURI: _settings?.__experimentalCurrentTheme?.stylesheetURI, + stylesheetURI: _settings?.__experimentalCurrentTheme?.stylesheetURI, + templateURI: _settings?.__experimentalCurrentTheme?.templateURI, }; } ); const blockElementsContainerIdentifier = `wp-elements-${ useInstanceId( @@ -479,7 +482,8 @@ function useBlockProps( { name, style } ) { { style }, skipSerializationPathsEdit, { - themeDirURI, + stylesheetURI, + templateURI, } ); } diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 93c2d53632571f..9a7ea71f75b9ec 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -296,6 +296,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { __experimentalUserCanCreatePages: userCanCreatePages, __experimentalCurrentTheme: { stylesheetURI: currentTheme?.stylesheet_uri, + templateURI: currentTheme?.template_uri, }, pageOnFront, pageForPosts, diff --git a/packages/style-engine/src/styles/background/index.ts b/packages/style-engine/src/styles/background/index.ts index a8c8679888e153..2b11af78bffd59 100644 --- a/packages/style-engine/src/styles/background/index.ts +++ b/packages/style-engine/src/styles/background/index.ts @@ -8,15 +8,38 @@ const backgroundImage = { name: 'backgroundImage', generate: ( style: Style, options: StyleOptions ) => { const _backgroundImage = style?.background?.backgroundImage; + if ( typeof _backgroundImage === 'object' && _backgroundImage?.url ) { + let url = _backgroundImage.url; + if ( + _backgroundImage?.source === 'theme' && + !! options?.stylesheetURI && + !! options?.templateURI + ) { + const activeThemeImageResource = `${ options.stylesheetURI }${ + url.startsWith( '/' ) ? url : `/${ url }` + }`; + + const parentThemeImageResource = `${ options.templateURI }${ + url.startsWith( '/' ) ? url : `/${ url }` + }`; + + url = `url('${ encodeURI( + safeDecodeURI( activeThemeImageResource ) + ) }'), url('${ encodeURI( + safeDecodeURI( parentThemeImageResource ) + ) }')`; + } else { + url = `url( '${ encodeURI( + safeDecodeURI( _backgroundImage.url ) + ) }' )`; + } return [ { selector: options.selector, key: 'backgroundImage', // Passed `url` may already be encoded. To prevent double encoding, decodeURI is executed to revert to the original string. - value: `url( '${ encodeURI( - safeDecodeURI( _backgroundImage.url ) - ) }' )`, + value: url, }, ]; } diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index 5b361836a8e375..a3e18b7f24f1cd 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -90,6 +90,9 @@ export interface StyleOptions { * CSS selector for the generated style. */ selector?: string; + templateURI?: string; + stylesheetURI?: string; + isRoot: boolean; } export interface GeneratedCSSRule { From eca8d3cacc96efb30a6da73e05aef0bf302b0c74 Mon Sep 17 00:00:00 2001 From: ramon Date: Tue, 30 Apr 2024 18:24:04 +1000 Subject: [PATCH 13/15] Just a commit to explore adding a private selector to mimic get_theme_file_uri (would be extracted into a new PR) Haven't worked out global styles yet. CSS rules might need to be injected into the DOM??? --- .wp-env.json | 2 +- lib/block-supports/background.php | 3 - .../global-styles/background-panel.js | 22 ++++++- .../global-styles/use-global-styles-output.js | 43 ++++--------- packages/block-editor/src/hooks/background.js | 64 +++++++++++-------- packages/block-editor/src/hooks/index.js | 2 + packages/block-editor/src/hooks/style.js | 16 ++--- packages/block-editor/src/private-apis.js | 2 + .../block-editor/src/store/private-keys.js | 1 + .../src/store/private-selectors.js | 10 +++ packages/core-data/src/private-selectors.ts | 4 ++ packages/core-data/src/reducer.js | 13 ++++ packages/core-data/src/resolvers.js | 31 +++++++++ packages/core-data/src/selectors.ts | 1 + .../provider/use-block-editor-settings.js | 2 + .../src/styles/background/index.ts | 29 +-------- 16 files changed, 144 insertions(+), 101 deletions(-) diff --git a/.wp-env.json b/.wp-env.json index 20d5597e54bbc9..bd5399ed0c1ff7 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -1,7 +1,7 @@ { "core": "WordPress/WordPress", "plugins": [ "." ], - "themes": [ "./test/emptytheme" ], + "themes": [ "./test/emptytheme", "./test/emptytheme-child" ], "env": { "tests": { "mappings": { diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index 10169f062039a3..edffecdfbc902c 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -45,9 +45,6 @@ function gutenberg_get_background_support_styles( $background_styles = array() ) * "theme" source implies relative path to the theme directory */ if ( ! empty( $background_styles['backgroundImage']['url'] ) && is_string( $background_styles['backgroundImage']['url'] ) && 'theme' === $background_image_source ) { - if ( ! str_starts_with( $background_styles['backgroundImage']['url'], '/' ) ) { - $background_styles['backgroundImage']['url'] = '/' . $background_styles['backgroundImage']['url']; - } $background_styles['backgroundImage']['url'] = esc_url( get_theme_file_uri( $background_styles['backgroundImage']['url'] ) ); } return gutenberg_style_engine_get_styles( array( 'background' => $background_styles ) ); diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index ef1f9673d601f9..a3637308ae260e 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -38,6 +38,7 @@ import { TOOLSPANEL_DROPDOWNMENU_PROPS } from './utils'; import { setImmutably } from '../../utils/object'; import MediaReplaceFlow from '../media-replace-flow'; import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; const IMAGE_BACKGROUND_TYPE = 'image'; const DEFAULT_CONTROLS = { @@ -201,6 +202,23 @@ function BackgroundImageToolsPanelItem( { ...inheritedValue?.background?.backgroundImage, }; + const { backgroundImageURL } = useSelect( + ( select ) => { + const { getThemeFileURI } = unlock( select( blockEditorStore ) ); + let file = url; + if ( + !! style?.background?.backgroundImage?.url && + style?.background?.backgroundImage?.source === 'theme' + ) { + file = getThemeFileURI( style.background.backgroundImage.url ); + } + return { + backgroundImageURL: file, + }; + }, + [ url ] + ); + const replaceContainerRef = useRef(); const { createErrorNotice } = useDispatch( noticesStore ); @@ -295,7 +313,7 @@ function BackgroundImageToolsPanelItem( { > } variant="secondary" diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index aa377023dd859a..57d09157fbf3ec 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -323,8 +323,7 @@ export function getStylesDeclarations( selector = '', useRootPaddingAlign, tree = {}, - isTemplate = true, - editorSettings + isTemplate = true ) { const { kebabCase } = unlock( componentsPrivateApis ); const isRoot = ROOT_BLOCK_SELECTOR === selector; @@ -401,17 +400,13 @@ export function getStylesDeclarations( */ if ( !! blockStyles?.background ) { blockStyles = setBackgroundStyleDefaults( blockStyles, { - ...editorSettings, selector, } ); } // The goal is to move everything to server side generated engine styles // This is temporary as we absorb more and more styles into the engine. - const extraRules = getCSSRules( blockStyles, { - ...editorSettings, - isRoot, - } ); + const extraRules = getCSSRules( blockStyles ); extraRules.forEach( ( rule ) => { // Don't output padding properties if padding variables are set or if we're not editing a full template. if ( @@ -795,8 +790,7 @@ export const toStyles = ( hasFallbackGapSupport, disableLayoutStyles = false, isTemplate = true, - styleOptions = undefined, - editorSettings = {} + styleOptions = undefined ) => { // These allow opting out of certain sets of styles. const options = { @@ -924,8 +918,7 @@ export const toStyles = ( styleVariations, styleVariationSelector, useRootPaddingAlign, - tree, - settings + tree ); if ( styleVariationDeclarations.length ) { ruleset += `${ styleVariationSelector }{${ styleVariationDeclarations.join( @@ -973,8 +966,7 @@ export const toStyles = ( selector, useRootPaddingAlign, tree, - isTemplate, - editorSettings + isTemplate ); if ( declarations?.length ) { ruleset += `:where(${ selector }){${ declarations.join( @@ -1241,17 +1233,12 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { const hasBlockGapSupport = blockGap !== null; const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support. - const { stylesheetURI, templateURI, disableLayoutStyles } = useSelect( - ( select ) => { - const _settings = select( blockEditorStore ).getSettings(); - return { - stylesheetURI: - _settings?.__experimentalCurrentTheme?.stylesheetURI, - templateURI: _settings?.__experimentalCurrentTheme?.templateURI, - disableLayoutStyles: !! _settings.disableLayoutStyles, - }; - } - ); + const { disableLayoutStyles } = useSelect( ( select ) => { + const _settings = select( blockEditorStore ).getSettings(); + return { + disableLayoutStyles: !! _settings.disableLayoutStyles, + }; + } ); const blockContext = useContext( BlockContext ); @@ -1281,11 +1268,7 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { hasBlockGapSupport, hasFallbackGapSupport, disableLayoutStyles, - isTemplate, - { - stylesheetURI, - templateURI, - } + isTemplate ); const svgs = toSvgFilters( updatedConfig, blockSelectors ); @@ -1334,8 +1317,6 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { disableLayoutStyles, isTemplate, getBlockStyles, - stylesheetURI, - templateURI, ] ); } diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 894f621643c574..badaaa4b8a025d 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -18,6 +18,7 @@ import { hasBackgroundImageValue, } from '../components/global-styles/background-panel'; import { ROOT_BLOCK_SELECTOR } from '../components/global-styles/utils'; +import { unlock } from '../lock-unlock'; export const BACKGROUND_SUPPORT_KEY = 'background'; @@ -72,32 +73,6 @@ export function setBackgroundStyleDefaults( blockStyles, options ) { const backgroundImage = blockStyles?.background?.backgroundImage; const newBackgroundStyles = {}; -/* if ( - backgroundImage?.source === 'theme' && - !! backgroundImage?.url && - !! options?.stylesheetURI && - !! options?.templateURI - ) { - const activeThemeImageResource = `${ options.stylesheetURI }${ - backgroundImage.url.startsWith( '/' ) - ? backgroundImage.url - : `/${ backgroundImage.url }` - }`; - - const parentThemeImageResource = `${ options.templateURI }${ - backgroundImage.url.startsWith( '/' ) - ? backgroundImage.url - : `/${ backgroundImage.url }` - }`; - - newBackgroundStyles.backgroundImage = { - ...backgroundImage, - url: `${ encodeURI( - safeDecodeURI( activeThemeImageResource ) - ) }, ${ encodeURI( safeDecodeURI( parentThemeImageResource ) ) }`, - }; - }*/ - // Set block background defaults. if ( options?.selector !== ROOT_BLOCK_SELECTOR && !! backgroundImage ) { if ( ! blockStyles?.background?.backgroundSize ) { @@ -202,7 +177,44 @@ export function BackgroundImagePanel( { ); } +function useBlockProps( { name, style } ) { + const { backgroundImageURL } = useSelect( + ( select ) => { + const { getThemeFileURI } = unlock( select( blockEditorStore ) ); + let file; + if ( + !! style?.background?.backgroundImage?.url && + style?.background?.backgroundImage?.source === 'theme' + ) { + file = getThemeFileURI( style.background.backgroundImage.url ); + } + return { + backgroundImageURL: file, + }; + }, + [ style?.background?.backgroundImage ] + ); + + if ( + ! hasBackgroundSupport( name, 'backgroundImage' ) || + ! backgroundImageURL + ) { + return; + } + + return { + style: { + // @TODO this should be backgroundImage. How to do that? + // Also, maybe consider reinstating https://github.com/WordPress/gutenberg/blob/fc98542a7dbba194bb4096d49cd0bd093b63f43e/packages/block-editor/src/hooks/background.js#L82 + background: `url( '${ encodeURI( + safeDecodeURI( backgroundImageURL ) + ) }' )`, + }, + }; +} + export default { attributeKeys: [ 'style' ], hasSupport: hasBackgroundSupport, + useBlockProps, }; diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index c008a8efa0970b..17190f39868a32 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -8,6 +8,7 @@ import { } from './utils'; import './compat'; import align from './align'; +import background from './background'; import './lock'; import anchor from './anchor'; import ariaLabel from './aria-label'; @@ -48,6 +49,7 @@ createBlockEditFilter( ); createBlockListBlockFilter( [ align, + background, textAlign, style, color, diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 120e55bf36dcc5..863e25ff8717e5 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -61,11 +61,11 @@ const hasStyleSupport = ( nameOrType ) => * * @return {Object} Flattened CSS variables declaration. */ -export function getInlineStyles( styles = {}, options ) { +export function getInlineStyles( styles = {} ) { const output = {}; // The goal is to move everything to server side generated engine styles // This is temporary as we absorb more and more styles into the engine. - getCSSRules( styles, options ).forEach( ( rule ) => { + getCSSRules( styles ).forEach( ( rule ) => { output[ rule.key ] = rule.value; } ); @@ -287,7 +287,6 @@ export function omitStyle( style, paths, preserveReference = false ) { * @param {Object|string} blockNameOrType Block type. * @param {Object} attributes Block attributes. * @param {?Record} skipPaths An object of keys and paths to skip serialization. - * @param {Object} editorSettings Current editor settings. * @return {Object} Filtered props applied to save element. */ export function addSaveProps( @@ -295,7 +294,6 @@ export function addSaveProps( blockNameOrType, attributes, skipPaths = skipSerializationPathsSave, - editorSettings ) { if ( ! hasStyleSupport( blockNameOrType ) ) { return props; @@ -325,13 +323,11 @@ export function addSaveProps( * Only applies to background styles for now. */ if ( !! style.background ) { - style = setBackgroundStyleDefaults( style, editorSettings ); + style = setBackgroundStyleDefaults( style ); } props.style = { - ...getInlineStyles( style, { - ...editorSettings, - } ), + ...getInlineStyles( style ), ...props.style, }; @@ -481,10 +477,6 @@ function useBlockProps( { name, style } ) { name, { style }, skipSerializationPathsEdit, - { - stylesheetURI, - templateURI, - } ); } diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index f10fcc4df2c726..d3c3e35c1f69dd 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -35,6 +35,7 @@ import { useFlashEditableBlocks } from './components/use-flash-editable-blocks'; import { selectBlockPatternsKey, reusableBlocksSelectKey, + getThemeFileURIKey, } from './store/private-keys'; import { requiresWrapperOnCopy } from './components/writing-flow/utils'; import { PrivateRichText } from './components/rich-text/'; @@ -76,4 +77,5 @@ lock( privateApis, { requiresWrapperOnCopy, PrivateRichText, reusableBlocksSelectKey, + getThemeFileURIKey, } ); diff --git a/packages/block-editor/src/store/private-keys.js b/packages/block-editor/src/store/private-keys.js index f48612e7491c9c..ec29e20a5c91d8 100644 --- a/packages/block-editor/src/store/private-keys.js +++ b/packages/block-editor/src/store/private-keys.js @@ -1,2 +1,3 @@ export const selectBlockPatternsKey = Symbol( 'selectBlockPatternsKey' ); export const reusableBlocksSelectKey = Symbol( 'reusableBlocksSelect' ); +export const getThemeFileURIKey = Symbol( 'getThemeFileURI' ); diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index bb7f8fed189549..ddea83e4b611d0 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -27,6 +27,7 @@ import { unlock } from '../lock-unlock'; import { selectBlockPatternsKey, reusableBlocksSelectKey, + getThemeFileURIKey, } from './private-keys'; export { getBlockSettings } from './get-block-settings'; @@ -412,6 +413,15 @@ export const getReusableBlocks = createRegistrySelector( } ); +export const getThemeFileURI = createRegistrySelector( + ( select ) => ( state, file ) => { + const getThemeFileURISelect = state.settings[ getThemeFileURIKey ]; + return getThemeFileURISelect + ? getThemeFileURISelect( select, file ) + : ''; + } +); + /** * Returns the element of the last element that had focus when focus left the editor canvas. * diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 6280bb96319634..b5b6b14ebf2a38 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -50,3 +50,7 @@ export const getBlockPatternsForPostType = createRegistrySelector( () => [ select( STORE_NAME ).getBlockPatterns() ] ) ); + +export function getThemeFileURI( state: State, file: string ) { + return state.themeFileURIs?.[ file ]; +} diff --git a/packages/core-data/src/reducer.js b/packages/core-data/src/reducer.js index 8e6be425244687..e2dd830b092475 100644 --- a/packages/core-data/src/reducer.js +++ b/packages/core-data/src/reducer.js @@ -623,6 +623,18 @@ export function defaultTemplates( state = {}, action ) { return state; } +export function themeFileURIs( state = {}, action ) { + switch ( action.type ) { + case 'RECEIVE_THEME_FILE_URI': + return { + ...state, + [ action.file ]: action.url, + }; + } + + return state; +} + export default combineReducers( { terms, users, @@ -644,4 +656,5 @@ export default combineReducers( { userPatternCategories, navigationFallbackId, defaultTemplates, + themeFileURIs, } ); diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 7de2c354ba2bf8..ef953a1cfc981c 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -896,3 +896,34 @@ export const getRevision = dispatch.receiveRevisions( kind, name, recordKey, record, query ); } }; + +export const getThemeFileURI = + ( file ) => + async ( { resolveSelect, dispatch } ) => { + if ( typeof file !== 'string' ) { + return; + } + + let trimmedFile = file.trim(); + trimmedFile = trimmedFile.startsWith( '/' ) ? trimmedFile : `/${ trimmedFile }`; + + const { stylesheet_uri, template_uri } = + await resolveSelect.getCurrentTheme(); + const url = `${ stylesheet_uri }${ trimmedFile }`; + + apiFetch( { url, method: 'HEAD', parse: false } ) + .then( () => { + dispatch( { + type: 'RECEIVE_THEME_FILE_URI', + file, + url, + } ); + } ) + .catch( () => { + dispatch( { + type: 'RECEIVE_THEME_FILE_URI', + file, + url: `${ template_uri }${ trimmedFile }`, + } ); + } ); + }; diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 242d516170d27d..462227acd8b9f8 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -46,6 +46,7 @@ export interface State { navigationFallbackId: EntityRecordKey; userPatternCategories: Array< UserPatternCategory >; defaultTemplates: Record< string, string >; + themeFileURIs: Record< string, string >; } type EntityRecordKey = string | number; diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 9a7ea71f75b9ec..34cb647fbe45bc 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -277,6 +277,8 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { ), [ unlock( privateApis ).reusableBlocksSelectKey ]: __experimentalReusableBlocksSelect, + [ unlock( privateApis ).getThemeFileURIKey ]: ( select, file ) => + unlock( select( coreStore ) ).getThemeFileURI( file ), __experimentalBlockPatternCategories: blockPatternCategories, __experimentalUserPatternCategories: userPatternCategories, __experimentalFetchLinkSuggestions: ( search, searchOptions ) => diff --git a/packages/style-engine/src/styles/background/index.ts b/packages/style-engine/src/styles/background/index.ts index 2b11af78bffd59..a8c8679888e153 100644 --- a/packages/style-engine/src/styles/background/index.ts +++ b/packages/style-engine/src/styles/background/index.ts @@ -8,38 +8,15 @@ const backgroundImage = { name: 'backgroundImage', generate: ( style: Style, options: StyleOptions ) => { const _backgroundImage = style?.background?.backgroundImage; - if ( typeof _backgroundImage === 'object' && _backgroundImage?.url ) { - let url = _backgroundImage.url; - if ( - _backgroundImage?.source === 'theme' && - !! options?.stylesheetURI && - !! options?.templateURI - ) { - const activeThemeImageResource = `${ options.stylesheetURI }${ - url.startsWith( '/' ) ? url : `/${ url }` - }`; - - const parentThemeImageResource = `${ options.templateURI }${ - url.startsWith( '/' ) ? url : `/${ url }` - }`; - - url = `url('${ encodeURI( - safeDecodeURI( activeThemeImageResource ) - ) }'), url('${ encodeURI( - safeDecodeURI( parentThemeImageResource ) - ) }')`; - } else { - url = `url( '${ encodeURI( - safeDecodeURI( _backgroundImage.url ) - ) }' )`; - } return [ { selector: options.selector, key: 'backgroundImage', // Passed `url` may already be encoded. To prevent double encoding, decodeURI is executed to revert to the original string. - value: url, + value: `url( '${ encodeURI( + safeDecodeURI( _backgroundImage.url ) + ) }' )`, }, ]; } From 7e9e4c55ded4d8af3d9a990163e113d460c32a05 Mon Sep 17 00:00:00 2001 From: ramon Date: Tue, 30 Apr 2024 18:24:48 +1000 Subject: [PATCH 14/15] whoops --- .wp-env.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.wp-env.json b/.wp-env.json index bd5399ed0c1ff7..20d5597e54bbc9 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -1,7 +1,7 @@ { "core": "WordPress/WordPress", "plugins": [ "." ], - "themes": [ "./test/emptytheme", "./test/emptytheme-child" ], + "themes": [ "./test/emptytheme" ], "env": { "tests": { "mappings": { From 1aa8f6a6fe1c8c8f555ed0af722815847f38094a Mon Sep 17 00:00:00 2001 From: ramon Date: Wed, 1 May 2024 13:06:45 +1000 Subject: [PATCH 15/15] Resolving urls in theme.json Feature complete, but hacky --- lib/block-supports/background.php | 23 +- lib/class-wp-theme-json-gutenberg.php | 21 +- ...class-wp-theme-json-resolver-gutenberg.php | 3 + packages/block-editor/src/hooks/background.js | 16 +- packages/block-editor/src/hooks/index.js | 2 +- packages/block-editor/src/hooks/style.js | 29 +- packages/style-engine/src/types.ts | 3 - phpunit/block-supports/background-test.php | 271 ------------------ 8 files changed, 42 insertions(+), 326 deletions(-) delete mode 100644 phpunit/block-supports/background-test.php diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index edffecdfbc902c..70957897229595 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -30,27 +30,6 @@ function gutenberg_register_background_support( $block_type ) { } } -/** - * Given a theme.json or block background styles, returns the background styles for a block. - * - * @since 6.6.0 - * - * @param array $background_styles Background style properties. - * @return array Style engine array of CSS string and style declarations. - */ -function gutenberg_get_background_support_styles( $background_styles = array() ) { - $background_image_source = ! empty( $background_styles['backgroundImage']['source'] ) ? $background_styles['backgroundImage']['source'] : null; - - /* - * "theme" source implies relative path to the theme directory - */ - if ( ! empty( $background_styles['backgroundImage']['url'] ) && is_string( $background_styles['backgroundImage']['url'] ) && 'theme' === $background_image_source ) { - $background_styles['backgroundImage']['url'] = esc_url( get_theme_file_uri( $background_styles['backgroundImage']['url'] ) ); - } - return gutenberg_style_engine_get_styles( array( 'background' => $background_styles ) ); -} - - /** * Renders the background styles to the block wrapper. * This block support uses the `render_block` hook to ensure that @@ -87,7 +66,7 @@ function gutenberg_render_background_support( $block_content, $block ) { } } - $styles = gutenberg_get_background_support_styles( $background_styles ); + $styles = gutenberg_style_engine_get_styles( array( 'background' => $background_styles ) ); if ( ! empty( $styles['css'] ) ) { // Inject background styles to the first element, presuming it's the wrapper, if it exists. diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 1b0d314f6dc39a..cb2c7279f38dfd 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2196,9 +2196,9 @@ protected static function compute_style_properties( $styles, $settings = array() } } - // Processes background styles. + // Processes background styles in order to build any `url()` functions. if ( 'background' === $value_path[0] && isset( $styles['background'] ) ) { - $background_styles = gutenberg_get_background_support_styles( $styles['background'] ); + $background_styles = gutenberg_style_engine_get_styles( array( 'background' => $styles['background'] ) ); $value = $background_styles['declarations'][ $css_property ] ?? $value; } @@ -4085,4 +4085,21 @@ protected static function get_valid_block_style_variations() { return $valid_variations; } + + // @TODO abstract and test this. + public function resolve_relative_paths() { + // Styles backgrounds. + /* + * "theme" source implies relative path to the theme directory + */ + if ( ! empty( $this->theme_json['styles']['background']['backgroundImage']['url'] ) && is_string( $this->theme_json['styles']['background']['backgroundImage']['url'] ) ) { + $background_image_source = ! empty( $this->theme_json['styles']['background']['backgroundImage']['source'] ) ? $this->theme_json['styles']['background']['backgroundImage']['source'] : null; + if ( 'theme' === $background_image_source ) { + $this->theme_json['styles']['background']['backgroundImage']['url'] = esc_url( get_theme_file_uri( $this->theme_json['styles']['background']['backgroundImage']['url'] ) ); + } + } + // Elements... (backgrounds not yet supported) + + // Block variations... (backgrounds not yet supported) + } } diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index dcc0bf8b099c3b..62266d863f62f7 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -355,6 +355,7 @@ public static function get_theme_data( $deprecated = array(), $options = array() $theme_support_data['settings']['appearanceTools'] = true; } } + $with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data ); $with_theme_supports->merge( static::$theme ); return $with_theme_supports; @@ -615,11 +616,13 @@ public static function get_merged_data( $origin = 'custom' ) { $result->merge( static::get_theme_data() ); if ( 'theme' === $origin ) { $result->set_spacing_sizes(); + $result->resolve_relative_paths(); return $result; } $result->merge( static::get_user_data() ); $result->set_spacing_sizes(); + $result->resolve_relative_paths(); return $result; } diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index badaaa4b8a025d..a96cd520f9c690 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -181,7 +181,7 @@ function useBlockProps( { name, style } ) { const { backgroundImageURL } = useSelect( ( select ) => { const { getThemeFileURI } = unlock( select( blockEditorStore ) ); - let file; + let file = style?.background?.backgroundImage?.url; if ( !! style?.background?.backgroundImage?.url && style?.background?.backgroundImage?.source === 'theme' @@ -201,14 +201,26 @@ function useBlockProps( { name, style } ) { ) { return; } + const newBackgroundStyles = {}; + if ( ! style?.background?.backgroundSize ) { + newBackgroundStyles.backgroundSize = 'cover'; + } + + if ( + 'contain' === style?.background?.backgroundSize && + ! style?.background?.backgroundPosition + ) { + newBackgroundStyles.backgroundPosition = 'center'; + } return { style: { // @TODO this should be backgroundImage. How to do that? // Also, maybe consider reinstating https://github.com/WordPress/gutenberg/blob/fc98542a7dbba194bb4096d49cd0bd093b63f43e/packages/block-editor/src/hooks/background.js#L82 - background: `url( '${ encodeURI( + backgroundImage: `url( '${ encodeURI( safeDecodeURI( backgroundImageURL ) ) }' )`, + ...newBackgroundStyles, }, }; } diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 17190f39868a32..d2f4f5fb5ed1ce 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -49,7 +49,6 @@ createBlockEditFilter( ); createBlockListBlockFilter( [ align, - background, textAlign, style, color, @@ -60,6 +59,7 @@ createBlockListBlockFilter( [ border, position, childLayout, + background, ] ); createBlockSaveFilter( [ align, diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 863e25ff8717e5..dad62bc0594a75 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -10,16 +10,11 @@ import { } from '@wordpress/blocks'; import { useInstanceId } from '@wordpress/compose'; import { getCSSRules, compileCSS } from '@wordpress/style-engine'; -import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ -import { - BACKGROUND_SUPPORT_KEY, - BackgroundImagePanel, - setBackgroundStyleDefaults, -} from './background'; +import { BACKGROUND_SUPPORT_KEY, BackgroundImagePanel } from './background'; import { BORDER_SUPPORT_KEY, BorderPanel, SHADOW_SUPPORT_KEY } from './border'; import { COLOR_SUPPORT_KEY, ColorEdit } from './color'; import { @@ -39,7 +34,6 @@ import { } from './utils'; import { scopeSelector } from '../components/global-styles/utils'; import { useBlockEditingMode } from '../components/block-editing-mode'; -import { store as blockEditorStore } from '../store'; const styleSupportKeys = [ ...TYPOGRAPHY_SUPPORT_KEYS, @@ -287,13 +281,14 @@ export function omitStyle( style, paths, preserveReference = false ) { * @param {Object|string} blockNameOrType Block type. * @param {Object} attributes Block attributes. * @param {?Record} skipPaths An object of keys and paths to skip serialization. + * * @return {Object} Filtered props applied to save element. */ export function addSaveProps( props, blockNameOrType, attributes, - skipPaths = skipSerializationPathsSave, + skipPaths = skipSerializationPathsSave ) { if ( ! hasStyleSupport( blockNameOrType ) ) { return props; @@ -317,15 +312,6 @@ export function addSaveProps( } } ); - /* - * Set styles defaults. - * Applies default values to the style object based on the block settings. - * Only applies to background styles for now. - */ - if ( !! style.background ) { - style = setBackgroundStyleDefaults( style ); - } - props.style = { ...getInlineStyles( style ), ...props.style, @@ -383,13 +369,6 @@ const elementTypes = [ ]; function useBlockProps( { name, style } ) { - const { stylesheetURI, templateURI } = useSelect( ( select ) => { - const _settings = select( blockEditorStore ).getSettings(); - return { - stylesheetURI: _settings?.__experimentalCurrentTheme?.stylesheetURI, - templateURI: _settings?.__experimentalCurrentTheme?.templateURI, - }; - } ); const blockElementsContainerIdentifier = `wp-elements-${ useInstanceId( useBlockProps ) }`; @@ -476,7 +455,7 @@ function useBlockProps( { name, style } ) { { className: blockElementsContainerIdentifier }, name, { style }, - skipSerializationPathsEdit, + skipSerializationPathsEdit ); } diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index a3e18b7f24f1cd..5b361836a8e375 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -90,9 +90,6 @@ export interface StyleOptions { * CSS selector for the generated style. */ selector?: string; - templateURI?: string; - stylesheetURI?: string; - isRoot: boolean; } export interface GeneratedCSSRule { diff --git a/phpunit/block-supports/background-test.php b/phpunit/block-supports/background-test.php deleted file mode 100644 index 78aa2cc56a672f..00000000000000 --- a/phpunit/block-supports/background-test.php +++ /dev/null @@ -1,271 +0,0 @@ -test_block_name = null; - $this->theme_root = realpath( __DIR__ . '/../data/themedir1' ); - $this->orig_theme_dir = $GLOBALS['wp_theme_directories']; - - // /themes is necessary as theme.php functions assume /themes is the root if there is only one root. - $GLOBALS['wp_theme_directories'] = array( WP_CONTENT_DIR . '/themes', $this->theme_root ); - - add_filter( 'theme_root', array( $this, 'filter_set_theme_root' ) ); - add_filter( 'stylesheet_root', array( $this, 'filter_set_theme_root' ) ); - add_filter( 'template_root', array( $this, 'filter_set_theme_root' ) ); - - // Clear caches. - wp_clean_themes_cache(); - unset( $GLOBALS['wp_themes'] ); - WP_Style_Engine_CSS_Rules_Store::remove_all_stores(); - } - - public function tear_down() { - $GLOBALS['wp_theme_directories'] = $this->orig_theme_dir; - - // Clear up the filters to modify the theme root. - remove_filter( 'theme_root', array( $this, 'filter_set_theme_root' ) ); - remove_filter( 'stylesheet_root', array( $this, 'filter_set_theme_root' ) ); - remove_filter( 'template_root', array( $this, 'filter_set_theme_root' ) ); - - wp_clean_themes_cache(); - unset( $GLOBALS['wp_themes'] ); - WP_Style_Engine_CSS_Rules_Store::remove_all_stores(); - unregister_block_type( $this->test_block_name ); - $this->test_block_name = null; - parent::tear_down(); - } - - public function filter_set_theme_root() { - return $this->theme_root; - } - - /** - * Tests that background image block support works as expected. - * - * @covers ::gutenberg_render_background_support - * - * @dataProvider data_background_block_support - * - * @param string $theme_name The theme to switch to. - * @param string $block_name The test block name to register. - * @param mixed $background_settings The background block support settings. - * @param mixed $background_style The background styles within the block attributes. - * @param string $expected_wrapper Expected markup for the block wrapper. - * @param string $wrapper Existing markup for the block wrapper. - */ - public function test_background_block_support( $theme_name, $block_name, $background_settings, $background_style, $expected_wrapper, $wrapper ) { - switch_theme( $theme_name ); - $this->test_block_name = $block_name; - - register_block_type( - $this->test_block_name, - array( - 'api_version' => 2, - 'attributes' => array( - 'style' => array( - 'type' => 'object', - ), - ), - 'supports' => array( - 'background' => $background_settings, - ), - ) - ); - - $block = array( - 'blockName' => $block_name, - 'attrs' => array( - 'style' => array( - 'background' => $background_style, - ), - ), - ); - - $actual = gutenberg_render_background_support( $wrapper, $block ); - - $this->assertEquals( - $expected_wrapper, - $actual, - 'Background block wrapper markup should be correct' - ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_background_block_support() { - return array( - 'background image style is applied' => array( - 'theme_name' => 'block-theme-child-with-fluid-typography', - 'block_name' => 'test/background-rules-are-output', - 'background_settings' => array( - 'backgroundImage' => true, - ), - 'background_style' => array( - 'backgroundImage' => array( - 'url' => 'https://example.com/image.jpg', - 'source' => 'file', - ), - ), - 'expected_wrapper' => '
Content
', - 'wrapper' => '
Content
', - ), - 'background image style is applied when backgroundImage is a string' => array( - 'theme_name' => 'block-theme-child-with-fluid-typography', - 'block_name' => 'test/background-rules-are-output', - 'background_settings' => array( - 'backgroundImage' => true, - ), - 'background_style' => array( - 'backgroundImage' => "url('https://example.com/image.jpg')", - ), - 'expected_wrapper' => '
Content
', - 'wrapper' => '
Content
', - ), - 'background image style with contain, position, and repeat is applied' => array( - 'theme_name' => 'block-theme-child-with-fluid-typography', - 'block_name' => 'test/background-rules-are-output', - 'background_settings' => array( - 'backgroundImage' => true, - ), - 'background_style' => array( - 'backgroundImage' => array( - 'url' => 'https://example.com/image.jpg', - 'source' => 'file', - ), - 'backgroundRepeat' => 'no-repeat', - 'backgroundSize' => 'contain', - ), - 'expected_wrapper' => '
Content
', - 'wrapper' => '
Content
', - ), - 'background image style is appended if a style attribute already exists' => array( - 'theme_name' => 'block-theme-child-with-fluid-typography', - 'block_name' => 'test/background-rules-are-output', - 'background_settings' => array( - 'backgroundImage' => true, - ), - 'background_style' => array( - 'backgroundImage' => array( - 'url' => 'https://example.com/image.jpg', - 'source' => 'file', - ), - ), - 'expected_wrapper' => '
Content
', - 'wrapper' => '
Content
', - ), - 'background image style is appended if a style attribute containing multiple styles already exists' => array( - 'theme_name' => 'block-theme-child-with-fluid-typography', - 'block_name' => 'test/background-rules-are-output', - 'background_settings' => array( - 'backgroundImage' => true, - ), - 'background_style' => array( - 'backgroundImage' => array( - 'url' => 'https://example.com/image.jpg', - 'source' => 'file', - ), - ), - 'expected_wrapper' => '
Content
', - 'wrapper' => '
Content
', - ), - 'background image style is not applied if the block does not support background image' => array( - 'theme_name' => 'block-theme-child-with-fluid-typography', - 'block_name' => 'test/background-rules-are-not-output', - 'background_settings' => array( - 'backgroundImage' => false, - ), - 'background_style' => array( - 'backgroundImage' => array( - 'url' => 'https://example.com/image.jpg', - 'source' => 'file', - ), - ), - 'expected_wrapper' => '
Content
', - 'wrapper' => '
Content
', - ), - ); - } - - /** - * Tests generating background styles. - * - * @covers ::gutenberg_get_background_support_styles - * - * @dataProvider data_get_background_support_styles - * - * @param mixed $background_style The background styles within the block attributes. - * @param string $expected_css Expected markup for the block wrapper. - */ - public function test_get_background_support_styles( $background_style, $expected_css ) { - switch_theme( 'block-theme' ); - $actual = gutenberg_get_background_support_styles( $background_style )['css'] ?? null; - - $this->assertEquals( - $expected_css, - $actual, - 'Background CSS should be correct.' - ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_get_background_support_styles() { - return array( - 'no css generated with no block styles' => array( - 'background_style' => array( - 'backgroundImage' => array(), - ), - 'expected_css' => null, - ), - 'css generated with theme background image path' => array( - 'background_style' => array( - 'backgroundImage' => array( - 'url' => '/assets/image/not_there.png', - 'source' => 'theme', - ), - ), - 'expected_css' => "background-image:url('http://localhost:8889/wp-content/plugins/gutenberg/phpunit/data/themedir1/block-theme/assets/image/not_there.png');", - ), - 'css generated with theme background image path and no preceding slash' => array( - 'background_style' => array( - 'backgroundImage' => array( - 'url' => 'assets/image/not_there.png', - 'source' => 'theme', - ), - ), - 'expected_css' => "background-image:url('http://localhost:8889/wp-content/plugins/gutenberg/phpunit/data/themedir1/block-theme/assets/image/not_there.png');", - ), - ); - } -}