From a8714f59987b1b252aa4fe5670bd164b7be7958d Mon Sep 17 00:00:00 2001 From: ramon Date: Tue, 30 Apr 2024 18:24:04 +1000 Subject: [PATCH] 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 | 44 ++++--------- 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, 145 insertions(+), 101 deletions(-) diff --git a/.wp-env.json b/.wp-env.json index 20d5597e54bbc..bd5399ed0c1ff 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 10169f062039a..edffecdfbc902 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 ef1f9673d601f..a3637308ae260 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 a0d971ca27183..cb5fd8c301cca 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 ( @@ -794,8 +789,7 @@ export const toStyles = ( hasBlockGapSupport, hasFallbackGapSupport, disableLayoutStyles = false, - isTemplate = true, - editorSettings = {} + isTemplate = true ) => { const nodesWithStyles = getNodesWithStyles( tree, blockSelectors ); const nodesWithSettings = getNodesWithSettings( tree, blockSelectors ); @@ -905,8 +899,7 @@ export const toStyles = ( styleVariations, styleVariationSelector, useRootPaddingAlign, - tree, - editorSettings + tree ); if ( styleVariationDeclarations.length ) { ruleset += `${ styleVariationSelector }{${ styleVariationDeclarations.join( @@ -954,8 +947,7 @@ export const toStyles = ( selector, useRootPaddingAlign, tree, - isTemplate, - editorSettings + isTemplate ); if ( declarations?.length ) { ruleset += `:where(${ selector }){${ declarations.join( @@ -1217,17 +1209,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 ); @@ -1257,12 +1244,9 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { hasBlockGapSupport, hasFallbackGapSupport, disableLayoutStyles, - isTemplate, - { - stylesheetURI, - templateURI, - } + isTemplate ); + console.log( 'globalStyles', globalStyles ); const svgs = toSvgFilters( updatedConfig, blockSelectors ); const styles = [ @@ -1310,8 +1294,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 894f621643c57..badaaa4b8a025 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 c008a8efa0970..17190f39868a3 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 120e55bf36dcc..863e25ff8717e 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 f10fcc4df2c72..d3c3e35c1f69d 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 f48612e7491c9..ec29e20a5c91d 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 94de85cbabe70..13d96a99018a8 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -26,6 +26,7 @@ import { unlock } from '../lock-unlock'; import { selectBlockPatternsKey, reusableBlocksSelectKey, + getThemeFileURIKey, } from './private-keys'; export { getBlockSettings } from './get-block-settings'; @@ -388,6 +389,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 6280bb9631963..b5b6b14ebf2a3 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 8e6be42524468..e2dd830b09247 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 7de2c354ba2bf..ef953a1cfc981 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 d238438e10eb1..055be0505eac1 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 9a7ea71f75b9e..34cb647fbe45b 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 2b11af78bffd5..a8c8679888e15 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 ) + ) }' )`, }, ]; }