Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add/background image theme source #61401

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion lib/block-supports/background.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,30 @@ 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() ) {
/*
* Styles backgrounds.
* Where a URL is not absolute (has no host fragment), it is assumed to be relative to the theme directory.
* Blocks, elements, and block variations are not yet supported.
*/
if (
isset( $background_styles['backgroundImage']['url'] ) &&
is_string( $background_styles['backgroundImage']['url'] ) &&
! isset( wp_parse_url( $background_styles['backgroundImage']['url'] )['host'] ) ) {
$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
Expand Down Expand Up @@ -66,7 +90,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.
Expand Down
10 changes: 5 additions & 5 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -488,10 +488,10 @@ class WP_Theme_JSON_Gutenberg {
*/
const VALID_STYLES = array(
'background' => array(
'backgroundImage' => 'top',
'backgroundPosition' => 'top',
'backgroundRepeat' => 'top',
'backgroundSize' => 'top',
'backgroundImage' => null,
'backgroundPosition' => null,
'backgroundRepeat' => null,
'backgroundSize' => null,
),
'border' => array(
'color' => null,
Expand Down Expand Up @@ -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;
}

Expand Down
72 changes: 72 additions & 0 deletions lib/compat/wordpress-6.6/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,75 @@ function gutenberg_add_class_list_to_public_post_types() {
}
}
add_action( 'rest_api_init', 'gutenberg_add_class_list_to_public_post_types' );

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' );
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -293,15 +311,15 @@ function BackgroundImageToolsPanelItem( {
>
<MediaReplaceFlow
mediaId={ id }
mediaURL={ url }
mediaURL={ backgroundImageURL }
allowedTypes={ [ IMAGE_BACKGROUND_TYPE ] }
accept="image/*"
onSelect={ onSelectMedia }
name={
<InspectorImagePreview
label={ title }
filename={ title || __( 'Untitled' ) }
url={ url }
url={ backgroundImageURL }
/>
}
variant="secondary"
Expand Down
9 changes: 9 additions & 0 deletions packages/block-editor/src/components/global-styles/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,15 @@ export function useSettingsForBlockElement(
}
} );

[ 'backgroundImage', 'backgroundSize' ].forEach( ( key ) => {
if ( ! supportedStyles.includes( key ) ) {
updatedSettings.background = {
...updatedSettings.background,
[ key ]: false,
};
}
} );

updatedSettings.shadow = supportedStyles.includes( 'shadow' )
? updatedSettings.shadow
: false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,34 @@
'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( [

Check failure on line 1016 in packages/block-editor/src/components/global-styles/test/use-global-styles-output.js

View workflow job for this annotation

GitHub Actions / JavaScript (Node.js 20) 4/4

Error: expect(received).toEqual(expected) // deep equality - Expected - 2 + Received + 1 Array [ - "background-image: url( 'http://example.com/theme/image.jpg' )", - "background-size: cover", + "background-image: url( 'image.jpg' )", ] at Object.toEqual (/home/runner/work/gutenberg/gutenberg/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js:1016:6) at Promise.then.completed (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/utils.js:300:28) at new Promise (<anonymous>) at callAsyncCircusFn (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/utils.js:233:10) at _callCircusTest (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:315:40) at processTicksAndRejections (node:internal/process/task_queues:95:5) at _runTest (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:251:3) at _runTestsForDescribeBlock (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:125:9) at _runTestsForDescribeBlock (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:120:9) at _runTestsForDescribeBlock (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:120:9) at run (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:70:3) at runAndTransformResultsToJestFormat (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21) at jestAdapter (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19) at runTestInternal (/home/runner/work/gutenberg/gutenberg/node_modules/jest-runner/build/runTest.js:367:16) at runTest (/home/runner/work/gutenberg/gutenberg/node_modules/jest-runner/build/runTest.js:444:34) at Object.worker (/home/runner/work/gutenberg/gutenberg/node_modules/jest-runner/build/testWorker.js:106:12)

Check failure on line 1016 in packages/block-editor/src/components/global-styles/test/use-global-styles-output.js

View workflow job for this annotation

GitHub Actions / JavaScript (Node.js 21) 4/4

Error: expect(received).toEqual(expected) // deep equality - Expected - 2 + Received + 1 Array [ - "background-image: url( 'http://example.com/theme/image.jpg' )", - "background-size: cover", + "background-image: url( 'image.jpg' )", ] at Object.toEqual (/home/runner/work/gutenberg/gutenberg/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js:1016:6) at Promise.then.completed (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/utils.js:300:28) at new Promise (<anonymous>) at callAsyncCircusFn (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/utils.js:233:10) at _callCircusTest (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:315:40) at processTicksAndRejections (node:internal/process/task_queues:95:5) at _runTest (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:251:3) at _runTestsForDescribeBlock (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:125:9) at _runTestsForDescribeBlock (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:120:9) at _runTestsForDescribeBlock (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:120:9) at run (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/run.js:70:3) at runAndTransformResultsToJestFormat (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21) at jestAdapter (/home/runner/work/gutenberg/gutenberg/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19) at runTestInternal (/home/runner/work/gutenberg/gutenberg/node_modules/jest-runner/build/runTest.js:367:16) at runTest (/home/runner/work/gutenberg/gutenberg/node_modules/jest-runner/build/runTest.js:444:34) at Object.worker (/home/runner/work/gutenberg/gutenberg/node_modules/jest-runner/build/testWorker.js:106:12)
"background-image: url( 'http://example.com/theme/image.jpg' )",
'background-size: cover',
] );
} );
} );

describe( 'processCSSNesting', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useSelect } from '@wordpress/data';
import { useContext, useMemo } from '@wordpress/element';
import { getCSSRules } from '@wordpress/style-engine';
import { privateApis as componentsPrivateApis } from '@wordpress/components';
import { isURL } from '@wordpress/url';

/**
* Internal dependencies
Expand All @@ -35,6 +36,7 @@ import { LAYOUT_DEFINITIONS } from '../../layouts/definitions';
import { getValueFromObjectPath, setImmutably } from '../../utils/object';
import BlockContext from '../block-context';
import { unlock } from '../../lock-unlock';
import useResolveThemeFileURIs from './use-resolve-theme-file-uris';

// List of block support features that can have their related styles
// generated under their own feature level selector rather than the block's.
Expand Down Expand Up @@ -314,6 +316,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(
Expand Down Expand Up @@ -947,19 +950,19 @@ 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
);
if ( declarations?.length ) {
ruleset += `:where(${ selector }){${ declarations.join(
';'
) };}`;
}

// Check for pseudo selector in `styles` and handle separately.
const pseudoSelectorStyles = Object.entries( styles ).filter(
Expand Down Expand Up @@ -1217,11 +1220,15 @@ export function processCSSNesting( css, blockSelector ) {
*/
export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) {
const [ blockGap ] = useGlobalSetting( 'spacing.blockGap' );
const resolvedConfig = useResolveThemeFileURIs( 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 disableLayoutStyles = useSelect( ( select ) => {
const { getSettings } = select( blockEditorStore );
return !! getSettings().disableLayoutStyles;

const { disableLayoutStyles } = useSelect( ( select ) => {
const _settings = select( blockEditorStore ).getSettings();
return {
disableLayoutStyles: !! _settings.disableLayoutStyles,
};
} );

const blockContext = useContext( BlockContext );
Expand All @@ -1231,10 +1238,10 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) {
const { getBlockStyles } = useSelect( blocksStore );

return useMemo( () => {
if ( ! mergedConfig?.styles || ! mergedConfig?.settings ) {
if ( ! resolvedConfig?.styles || ! resolvedConfig?.settings ) {
return [];
}
const updatedConfig = updateConfigWithSeparator( mergedConfig );
const updatedConfig = updateConfigWithSeparator( resolvedConfig );

const blockSelectors = getBlockSelectors(
getBlockTypes(),
Expand Down Expand Up @@ -1297,7 +1304,7 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) {
}, [
hasBlockGapSupport,
hasFallbackGapSupport,
mergedConfig,
resolvedConfig,
disableLayoutStyles,
isTemplate,
getBlockStyles,
Expand Down
Loading
Loading