Skip to content

Commit 49e4a4f

Browse files
authored
Do not render global styles coming from the server in the site editor (#40185)
1 parent 39172d1 commit 49e4a4f

File tree

3 files changed

+99
-39
lines changed

3 files changed

+99
-39
lines changed

lib/compat/wordpress-6.0/block-editor-settings.php

+56-29
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,49 @@
55
* @package gutenberg
66
*/
77

8+
/**
9+
* Returns true if the style is coming from global styles.
10+
*
11+
* @param array $style Array containing a '__unstableType' key.
12+
* @return boolean
13+
*/
14+
function gutenberg_is_global_styles_in_5_8( $style ) {
15+
if ( isset( $style['__unstableType'] ) && ( 'globalStyles' === $style['__unstableType'] ) ) {
16+
return true;
17+
}
18+
19+
return false;
20+
}
21+
22+
/**
23+
* Returns true if the style is coming from global styles.
24+
*
25+
* @param array $style Array containing a '__unstableType' key and a 'css' key with the actual CSS.
26+
* @return boolean
27+
*/
28+
function gutenberg_is_global_styles_in_5_9( $style ) {
29+
/*
30+
* In WordPress 5.9 we don't have a mechanism to distinguish block styles generated via theme.json
31+
* from styles that come from the stylesheet of a theme.
32+
*
33+
* We do know that the block styles generated via theme.json have some rules for alignment.
34+
* Hence, by detecting the presence of these rules, we can tell with high certainty
35+
* whether or not the incoming $style has been generated from theme.json.
36+
*/
37+
$root_styles = '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }';
38+
$root_styles .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }';
39+
$root_styles .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
40+
41+
if (
42+
( isset( $style['__unstableType'] ) && ( 'presets' === $style['__unstableType'] ) ) ||
43+
( isset( $style['__unstableType'] ) && ( 'theme' === $style['__unstableType'] ) && str_contains( $style['css'], $root_styles ) )
44+
) {
45+
return true;
46+
}
47+
48+
return false;
49+
}
50+
851
/**
952
* Adds styles and __experimentalFeatures to the block editor settings.
1053
*
@@ -15,15 +58,6 @@
1558
function gutenberg_get_block_editor_settings( $settings ) {
1659
// Set what is the context for this data request.
1760
$context = 'other';
18-
if (
19-
is_callable( 'get_current_screen' ) &&
20-
function_exists( 'gutenberg_is_edit_site_page' ) &&
21-
is_object( get_current_screen() ) &&
22-
gutenberg_is_edit_site_page( get_current_screen()->id )
23-
) {
24-
$context = 'site-editor';
25-
}
26-
2761
if (
2862
defined( 'REST_REQUEST' ) &&
2963
REST_REQUEST &&
@@ -34,49 +68,41 @@ function_exists( 'gutenberg_is_edit_site_page' ) &&
3468
}
3569

3670
if ( 'other' === $context ) {
71+
global $wp_version;
72+
$is_wp_5_8 = version_compare( $wp_version, '5.8', '>=' ) && version_compare( $wp_version, '5.9', '<' );
73+
$is_wp_5_9 = version_compare( $wp_version, '5.9', '>=' ) && version_compare( $wp_version, '6.0-beta1', '<' );
74+
$is_wp_6_0 = version_compare( $wp_version, '6.0-beta1', '>=' );
75+
3776
// Make sure the styles array exists.
3877
// In some contexts, like the navigation editor, it doesn't.
3978
if ( ! isset( $settings['styles'] ) ) {
4079
$settings['styles'] = array();
4180
}
4281

82+
// Remove existing global styles provided by core.
4383
$styles_without_existing_global_styles = array();
4484
foreach ( $settings['styles'] as $style ) {
4585
if (
46-
! isset( $style['__unstableType'] ) ||
47-
// '__unstableType' is 'globalStyles' for WordPress 5.8 and 'presets' for WordPress 5.9.
48-
//
49-
// Note that styles classified as'theme', can be from the theme stylesheet
50-
// or from the theme.json (the styles section).
51-
// We are unable to identify which is which, so we can't remove and recreate those.
52-
// Instead, we reload the theme.json styles from the plugin.
53-
// Because they'll use the same selectors and load later,
54-
// they'll have higher priority than core's.
55-
//
56-
// Theoretically, this approach with 'theme' styles could be problematic:
57-
// if we remove style properties in the plugin, if selectors change, etc.
58-
// We need to address this issue directly in core by alowing to identify
59-
// styles coming from theme.json.
60-
//
61-
// A final note about 'theme' styles: this flag is used to identify theme
62-
// styles that may need to be removed if the user toggles
63-
// "Preferences > Use theme styles" in the preferences modal.
64-
//
65-
! in_array( $style['__unstableType'], array( 'globalStyles', 'presets' ), true )
86+
( $is_wp_5_8 && ! gutenberg_is_global_styles_in_5_8( $style ) ) || // Can be removed when plugin minimum version is 5.9.
87+
( $is_wp_5_9 && ! gutenberg_is_global_styles_in_5_9( $style ) ) || // Can be removed when plugin minimum version is 6.0.
88+
( $is_wp_6_0 && ( ! isset( $style['isGlobalStyles'] ) || ! $style['isGlobalStyles'] ) )
6689
) {
6790
$styles_without_existing_global_styles[] = $style;
6891
}
6992
}
7093

94+
// Recreate global styles.
7195
$new_global_styles = array();
7296
$presets = array(
7397
array(
7498
'css' => 'variables',
7599
'__unstableType' => 'presets',
100+
'isGlobalStyles' => true,
76101
),
77102
array(
78103
'css' => 'presets',
79104
'__unstableType' => 'presets',
105+
'isGlobalStyles' => true,
80106
),
81107
);
82108
foreach ( $presets as $preset_style ) {
@@ -91,6 +117,7 @@ function_exists( 'gutenberg_is_edit_site_page' ) &&
91117
$block_classes = array(
92118
'css' => 'styles',
93119
'__unstableType' => 'theme',
120+
'isGlobalStyles' => true,
94121
);
95122
$actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'] ) );
96123
if ( '' !== $actual_css ) {

packages/edit-site/src/components/global-styles/test/use-global-styles-output.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,10 @@ describe( 'global styles renderer', () => {
377377
};
378378

379379
expect( toStyles( tree, blockSelectors ) ).toEqual(
380-
'.wp-site-blocks > * { margin-top: 0; margin-bottom: 0; }.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); }body{background-color: red;margin: 10px;padding: 10px;}h1{font-size: 42px;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}'
380+
'body {margin: 0;}' +
381+
'body{background-color: red;margin: 10px;padding: 10px;}h1{font-size: 42px;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}' +
382+
'.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' +
383+
'.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}'
381384
);
382385
} );
383386
} );

packages/edit-site/src/components/global-styles/use-global-styles-output.js

+39-9
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,12 @@ import {
2525
import { useEffect, useState, useContext } from '@wordpress/element';
2626
import { getCSSRules } from '@wordpress/style-engine';
2727

28-
/**
29-
* Internal dependencies
30-
*/
31-
3228
/**
3329
* Internal dependencies
3430
*/
3531
import { PRESET_METADATA, ROOT_BLOCK_SELECTOR } from './utils';
3632
import { GlobalStylesContext } from './context';
33+
import { useSetting } from './hooks';
3734

3835
function compileStyleValue( uncompiledValue ) {
3936
const VARIABLE_REFERENCE_PREFIX = 'var:';
@@ -329,12 +326,19 @@ export const toCustomProperties = ( tree, blockSelectors ) => {
329326
return ruleset;
330327
};
331328

332-
export const toStyles = ( tree, blockSelectors ) => {
329+
export const toStyles = ( tree, blockSelectors, hasBlockGapSupport ) => {
333330
const nodesWithStyles = getNodesWithStyles( tree, blockSelectors );
334331
const nodesWithSettings = getNodesWithSettings( tree, blockSelectors );
335332

336-
let ruleset =
337-
'.wp-site-blocks > * { margin-top: 0; margin-bottom: 0; }.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); }';
333+
/*
334+
* Reset default browser margin on the root body element.
335+
* This is set on the root selector **before** generating the ruleset
336+
* from the `theme.json`. This is to ensure that if the `theme.json` declares
337+
* `margin` in its `spacing` declaration for the `body` element then these
338+
* user-generated values take precedence in the CSS cascade.
339+
* @link https://github.com/WordPress/gutenberg/issues/36147.
340+
*/
341+
let ruleset = 'body {margin: 0;}';
338342
nodesWithStyles.forEach( ( { selector, styles } ) => {
339343
const declarations = getStylesDeclarations( styles );
340344
if ( declarations.length === 0 ) {
@@ -343,6 +347,26 @@ export const toStyles = ( tree, blockSelectors ) => {
343347
ruleset = ruleset + `${ selector }{${ declarations.join( ';' ) };}`;
344348
} );
345349

350+
/* Add alignment / layout styles */
351+
ruleset =
352+
ruleset +
353+
'.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }';
354+
ruleset =
355+
ruleset +
356+
'.wp-site-blocks > .alignright { float: right; margin-left: 2em; }';
357+
ruleset =
358+
ruleset +
359+
'.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
360+
361+
if ( hasBlockGapSupport ) {
362+
ruleset =
363+
ruleset +
364+
'.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }';
365+
ruleset =
366+
ruleset +
367+
'.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }';
368+
}
369+
346370
nodesWithSettings.forEach( ( { selector, presets } ) => {
347371
if ( ROOT_BLOCK_SELECTOR === selector ) {
348372
// Do not add extra specificity for top-level classes.
@@ -378,6 +402,8 @@ export function useGlobalStylesOutput() {
378402
const [ stylesheets, setStylesheets ] = useState( [] );
379403
const [ settings, setSettings ] = useState( {} );
380404
const { merged: mergedConfig } = useContext( GlobalStylesContext );
405+
const [ blockGap ] = useSetting( 'spacing.blockGap' );
406+
const hasBlockGapSupport = blockGap !== null;
381407

382408
useEffect( () => {
383409
if ( ! mergedConfig?.styles || ! mergedConfig?.settings ) {
@@ -389,7 +415,11 @@ export function useGlobalStylesOutput() {
389415
mergedConfig,
390416
blockSelectors
391417
);
392-
const globalStyles = toStyles( mergedConfig, blockSelectors );
418+
const globalStyles = toStyles(
419+
mergedConfig,
420+
blockSelectors,
421+
hasBlockGapSupport
422+
);
393423
setStylesheets( [
394424
{
395425
css: customProperties,
@@ -403,5 +433,5 @@ export function useGlobalStylesOutput() {
403433
setSettings( mergedConfig.settings );
404434
}, [ mergedConfig ] );
405435

406-
return [ stylesheets, settings ];
436+
return [ stylesheets, settings, hasBlockGapSupport ];
407437
}

0 commit comments

Comments
 (0)