diff --git a/src/wp-includes/block-editor.php b/src/wp-includes/block-editor.php index 94e9079fc7..17506842af 100644 --- a/src/wp-includes/block-editor.php +++ b/src/wp-includes/block-editor.php @@ -209,7 +209,6 @@ function get_default_block_editor_settings() { 'disableCustomColors' => get_theme_support( 'disable-custom-colors' ), 'disableCustomFontSizes' => get_theme_support( 'disable-custom-font-sizes' ), 'disableCustomGradients' => get_theme_support( 'disable-custom-gradients' ), - 'disableLayoutStyles' => get_theme_support( 'disable-layout-styles' ), 'enableCustomLineHeight' => get_theme_support( 'custom-line-height' ), 'enableCustomSpacing' => get_theme_support( 'custom-spacing' ), 'enableCustomUnits' => get_theme_support( 'custom-units' ), @@ -418,18 +417,6 @@ function get_block_editor_settings( array $custom_settings, $block_editor_contex $block_classes['css'] = $actual_css; $global_styles[] = $block_classes; } - } else { - // If there is no `theme.json` file, ensure base layout styles are still available. - $block_classes = array( - 'css' => 'base-layout-styles', - '__unstableType' => 'base-layout', - 'isGlobalStyles' => true, - ); - $actual_css = wp_get_global_stylesheet( array( $block_classes['css'] ) ); - if ( '' !== $actual_css ) { - $block_classes['css'] = $actual_css; - $global_styles[] = $block_classes; - } } $editor_settings['styles'] = array_merge( $global_styles, get_block_editor_theme_styles() ); @@ -487,23 +474,9 @@ function get_block_editor_settings( array $custom_settings, $block_editor_contex $editor_settings['enableCustomSpacing'] = $editor_settings['__experimentalFeatures']['spacing']['padding']; unset( $editor_settings['__experimentalFeatures']['spacing']['padding'] ); } - if ( isset( $editor_settings['__experimentalFeatures']['spacing']['customSpacingSize'] ) ) { - $editor_settings['disableCustomSpacingSizes'] = ! $editor_ettings['__experimentalFeatures']['spacing']['customSpacingSize']; - unset( $editor_settings['__experimentalFeatures']['spacing']['customSpacingSize'] ); - } - if ( isset( $editor_settings['__experimentalFeatures']['spacing']['spacingSizes'] ) ) { - $spacing_sizes_by_origin = $editor_settings['__experimentalFeatures']['spacing']['spacingSizes']; - $editor_settings['spacingSizes'] = isset( $spacing_sizes_by_origin['custom'] ) ? - $spacing_sizes_by_origin['custom'] : ( - isset( $spacing_sizes_by_origin['theme'] ) ? - $spacing_sizes_by_origin['theme'] : - $spacing_sizes_by_origin['default'] - ); - } $editor_settings['__unstableResolvedAssets'] = _wp_get_iframed_editor_assets(); $editor_settings['localAutosaveInterval'] = 15; - $editor_settings['disableLayoutStyles'] = current_theme_supports( 'disable-layout-styles' ); $editor_settings['__experimentalDiscussionSettings'] = array( 'commentOrder' => get_option( 'comment_order' ), 'commentsPerPage' => get_option( 'comments_per_page' ), diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index 5d0dd099c2..cf5ffa2e2b 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -232,54 +232,6 @@ class WP_Theme_JSON_Resolver { return $with_theme_supports; } - /** - * Gets the styles for blocks from the block.json file. - * - * @since 6.1.0 - * - * @return WP_Theme_JSON - */ - public static function get_block_data() { - $registry = WP_Block_Type_Registry::get_instance(); - $blocks = $registry->get_all_registered(); - $config = array( 'version' => 1 ); - foreach ( $blocks as $block_name => $block_type ) { - if ( isset( $block_type->supports['__experimentalStyle'] ) ) { - $config['styles']['blocks'][ $block_name ] = static::remove_json_comments( $block_type->supports['__experimentalStyle'] ); - } - - if ( - isset( $block_type->supports['spacing']['blockGap']['__experimentalDefault'] ) && - null === _wp_array_get( $config, array( 'styles', 'blocks', $block_name, 'spacing', 'blockGap' ), null ) - ) { - // Ensure an empty placeholder value exists for the block, if it provides a default blockGap value. - // The real blockGap value to be used will be determined when the styles are rendered for output. - $config['styles']['blocks'][ $block_name ]['spacing']['blockGap'] = null; - } - } - - // Core here means it's the lower level part of the styles chain. - // It can be a core or a third-party block. - return new WP_Theme_JSON( $config, 'core' ); - } - - /** - * When given an array, this will remove any keys with the name `//`. - * - * @param array $array The array to filter. - * @return array The filtered array. - */ - private static function remove_json_comments( $array ) { - unset( $array['//'] ); - foreach ( $array as $k => $v ) { - if ( is_array( $v ) ) { - $array[ $k ] = static::remove_json_comments( $v ); - } - } - - return $array; - } - /** * Returns the custom post type that contains the user's origin config * for the active theme or a void array if none are found. @@ -418,7 +370,6 @@ class WP_Theme_JSON_Resolver { * @since 5.8.0 * @since 5.9.0 Added user data, removed the `$settings` parameter, * added the `$origin` parameter. - * @since 6.1.0 Added block data. * * @param string $origin Optional. To what level should we merge data. * Valid values are 'theme' or 'custom'. Default 'custom'. @@ -431,7 +382,6 @@ class WP_Theme_JSON_Resolver { $result = new WP_Theme_JSON(); $result->merge( static::get_core_data() ); - $result->merge( static::get_block_data() ); $result->merge( static::get_theme_data() ); if ( 'custom' === $origin ) { diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index 43566cda96..e5eb5a7391 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -177,60 +177,40 @@ class WP_Theme_JSON { * `letter-spacing`, `margin-*`, `padding-*`, `--wp--style--block-gap`, * `text-decoration`, `text-transform`, and `filter` properties, * simplified the metadata structure. - * @since 6.1.0 Added the `border-*-color`, `border-*-width`, `border-*-style`, - * `--wp--style--root--padding-*`, and `box-shadow` properties, - * removed the `--wp--style--block-gap` property. * @var array */ const PROPERTIES_METADATA = array( - 'background' => array( 'color', 'gradient' ), - 'background-color' => array( 'color', 'background' ), - 'border-radius' => array( 'border', 'radius' ), - 'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ), - 'border-top-right-radius' => array( 'border', 'radius', 'topRight' ), - 'border-bottom-left-radius' => array( 'border', 'radius', 'bottomLeft' ), - 'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ), - 'border-color' => array( 'border', 'color' ), - 'border-width' => array( 'border', 'width' ), - 'border-style' => array( 'border', 'style' ), - 'border-top-color' => array( 'border', 'top', 'color' ), - 'border-top-width' => array( 'border', 'top', 'width' ), - 'border-top-style' => array( 'border', 'top', 'style' ), - 'border-right-color' => array( 'border', 'right', 'color' ), - 'border-right-width' => array( 'border', 'right', 'width' ), - 'border-right-style' => array( 'border', 'right', 'style' ), - 'border-bottom-color' => array( 'border', 'bottom', 'color' ), - 'border-bottom-width' => array( 'border', 'bottom', 'width' ), - 'border-bottom-style' => array( 'border', 'bottom', 'style' ), - 'border-left-color' => array( 'border', 'left', 'color' ), - 'border-left-width' => array( 'border', 'left', 'width' ), - 'border-left-style' => array( 'border', 'left', 'style' ), - 'color' => array( 'color', 'text' ), - 'font-family' => array( 'typography', 'fontFamily' ), - 'font-size' => array( 'typography', 'fontSize' ), - 'font-style' => array( 'typography', 'fontStyle' ), - 'font-weight' => array( 'typography', 'fontWeight' ), - 'letter-spacing' => array( 'typography', 'letterSpacing' ), - 'line-height' => array( 'typography', 'lineHeight' ), - 'margin' => array( 'spacing', 'margin' ), - 'margin-top' => array( 'spacing', 'margin', 'top' ), - 'margin-right' => array( 'spacing', 'margin', 'right' ), - 'margin-bottom' => array( 'spacing', 'margin', 'bottom' ), - 'margin-left' => array( 'spacing', 'margin', 'left' ), - 'padding' => array( 'spacing', 'padding' ), - 'padding-top' => array( 'spacing', 'padding', 'top' ), - 'padding-right' => array( 'spacing', 'padding', 'right' ), - 'padding-bottom' => array( 'spacing', 'padding', 'bottom' ), - 'padding-left' => array( 'spacing', 'padding', 'left' ), - '--wp--style--root--padding' => array( 'spacing', 'padding' ), - '--wp--style--root--padding-top' => array( 'spacing', 'padding', 'top' ), - '--wp--style--root--padding-right' => array( 'spacing', 'padding', 'right' ), - '--wp--style--root--padding-bottom' => array( 'spacing', 'padding', 'bottom' ), - '--wp--style--root--padding-left' => array( 'spacing', 'padding', 'left' ), - 'text-decoration' => array( 'typography', 'textDecoration' ), - 'text-transform' => array( 'typography', 'textTransform' ), - 'filter' => array( 'filter', 'duotone' ), - 'box-shadow' => array( 'shadow' ), + 'background' => array( 'color', 'gradient' ), + 'background-color' => array( 'color', 'background' ), + 'border-radius' => array( 'border', 'radius' ), + 'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ), + 'border-top-right-radius' => array( 'border', 'radius', 'topRight' ), + 'border-bottom-left-radius' => array( 'border', 'radius', 'bottomLeft' ), + 'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ), + 'border-color' => array( 'border', 'color' ), + 'border-width' => array( 'border', 'width' ), + 'border-style' => array( 'border', 'style' ), + 'color' => array( 'color', 'text' ), + 'font-family' => array( 'typography', 'fontFamily' ), + 'font-size' => array( 'typography', 'fontSize' ), + 'font-style' => array( 'typography', 'fontStyle' ), + 'font-weight' => array( 'typography', 'fontWeight' ), + 'letter-spacing' => array( 'typography', 'letterSpacing' ), + 'line-height' => array( 'typography', 'lineHeight' ), + 'margin' => array( 'spacing', 'margin' ), + 'margin-top' => array( 'spacing', 'margin', 'top' ), + 'margin-right' => array( 'spacing', 'margin', 'right' ), + 'margin-bottom' => array( 'spacing', 'margin', 'bottom' ), + 'margin-left' => array( 'spacing', 'margin', 'left' ), + 'padding' => array( 'spacing', 'padding' ), + 'padding-top' => array( 'spacing', 'padding', 'top' ), + 'padding-right' => array( 'spacing', 'padding', 'right' ), + 'padding-bottom' => array( 'spacing', 'padding', 'bottom' ), + 'padding-left' => array( 'spacing', 'padding', 'left' ), + '--wp--style--block-gap' => array( 'spacing', 'blockGap' ), + 'text-decoration' => array( 'typography', 'textDecoration' ), + 'text-transform' => array( 'typography', 'textTransform' ), + 'filter' => array( 'filter', 'duotone' ), ); /** @@ -274,19 +254,17 @@ class WP_Theme_JSON { * added new properties for `border`, `color`, `spacing`, * and `typography`, and renamed others according to the new schema. * @since 6.0.0 Added `color.defaultDuotone`. - * @since 6.1.0 Added `layout.definitions` and `useRootPaddingAwareAlignments`. * @var array */ const VALID_SETTINGS = array( - 'appearanceTools' => null, - 'useRootPaddingAwareAlignments' => null, - 'border' => array( + 'appearanceTools' => null, + 'border' => array( 'color' => null, 'radius' => null, 'style' => null, 'width' => null, ), - 'color' => array( + 'color' => array( 'background' => null, 'custom' => null, 'customDuotone' => null, @@ -300,18 +278,18 @@ class WP_Theme_JSON { 'palette' => null, 'text' => null, ), - 'custom' => null, - 'layout' => array( + 'custom' => null, + 'layout' => array( 'contentSize' => null, 'wideSize' => null, ), - 'spacing' => array( + 'spacing' => array( 'blockGap' => null, 'margin' => null, 'padding' => null, 'units' => null, ), - 'typography' => array( + 'typography' => array( 'customFontSize' => null, 'dropCap' => null, 'fontFamilies' => null, @@ -332,8 +310,6 @@ class WP_Theme_JSON { * @since 5.9.0 Renamed from `ALLOWED_STYLES` to `VALID_STYLES`, * added new properties for `border`, `filter`, `spacing`, * and `typography`. - * @since 6.1.0 Added new side properties for `border`, - * updated `blockGap` to be allowed at any level. * @var array */ const VALID_STYLES = array( @@ -342,10 +318,6 @@ class WP_Theme_JSON { 'radius' => null, 'style' => null, 'width' => null, - 'top' => null, - 'right' => null, - 'bottom' => null, - 'left' => null, ), 'color' => array( 'background' => null, @@ -358,7 +330,7 @@ class WP_Theme_JSON { 'spacing' => array( 'margin' => null, 'padding' => null, - 'blockGap' => null, + 'blockGap' => 'top', ), 'typography' => array( 'fontFamily' => null, @@ -411,20 +383,6 @@ class WP_Theme_JSON { 'caption' => 'wp-element-caption', ); - /** - * List of block support features that can have their related styles - * generated under their own feature level selector rather than the block's. - * - * @since 6.1.0 - * @var string[] - */ - const BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS = array( - '__experimentalBorder' => 'border', - 'color' => 'color', - 'spacing' => 'spacing', - 'typography' => 'typography', - ); - /** * Returns a class name by an element name. * @@ -698,7 +656,6 @@ class WP_Theme_JSON { * * @since 5.8.0 * @since 5.9.0 Added `duotone` key with CSS selector. - * @since 6.1.0 Added `features` key with block support feature level selectors. * * @return array Block metadata. */ @@ -728,25 +685,6 @@ class WP_Theme_JSON { static::$blocks_metadata[ $block_name ]['duotone'] = $block_type->supports['color']['__experimentalDuotone']; } - // Generate block support feature level selectors if opted into - // for the current block. - $features = array(); - foreach ( static::BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS as $key => $feature ) { - if ( - isset( $block_type->supports[ $key ]['__experimentalSelector'] ) && - $block_type->supports[ $key ]['__experimentalSelector'] - ) { - $features[ $feature ] = static::scope_selector( - static::$blocks_metadata[ $block_name ]['selector'], - $block_type->supports[ $key ]['__experimentalSelector'] - ); - } - } - - if ( ! empty( $features ) ) { - static::$blocks_metadata[ $block_name ]['features'] = $features; - } - // Assign defaults, then overwrite those that the block sets by itself. // If the block selector is compounded, will append the element to each // individual block selector. @@ -872,30 +810,7 @@ class WP_Theme_JSON { } if ( in_array( 'styles', $types, true ) ) { - $root_block_key = array_search( static::ROOT_BLOCK_SELECTOR, array_column( $style_nodes, 'selector' ), true ); - - if ( false !== $root_block_key ) { - $stylesheet .= $this->get_root_layout_rules( static::ROOT_BLOCK_SELECTOR, $style_nodes[ $root_block_key ] ); - } $stylesheet .= $this->get_block_classes( $style_nodes ); - } elseif ( in_array( 'base-layout-styles', $types, true ) ) { - // Base layout styles are provided as part of `styles`, so only output separately if explicitly requested. - // For backwards compatibility, the Columns block is explicitly included, to support a different default gap value. - $base_styles_nodes = array( - array( - 'path' => array( 'styles' ), - 'selector' => static::ROOT_BLOCK_SELECTOR, - ), - array( - 'path' => array( 'styles', 'blocks', 'core/columns' ), - 'selector' => '.wp-block-columns', - 'name' => 'core/columns', - ), - ); - - foreach ( $base_styles_nodes as $base_style_node ) { - $stylesheet .= $this->get_layout_styles( $base_style_node ); - } } if ( in_array( 'presets', $types, true ) ) { @@ -969,7 +884,6 @@ class WP_Theme_JSON { * @since 5.9.0 Renamed from `get_block_styles()` to `get_block_classes()` * and no longer returns preset classes. * Removed the `$setting_nodes` parameter. - * @since 6.1.0 Moved most internal logic to `get_styles_for_block()`. * * @param array $style_nodes Nodes with styles. * @return string The new stylesheet. @@ -987,190 +901,6 @@ class WP_Theme_JSON { return $block_rules; } - /** - * Get the CSS layout rules for a particular block from theme.json layout definitions. - * - * @since 6.1.0 - * - * @param array $block_metadata Metadata about the block to get styles for. - * - * @return string Layout styles for the block. - */ - protected function get_layout_styles( $block_metadata ) { - $block_rules = ''; - $block_type = null; - - // Skip outputting layout styles if explicitly disabled. - if ( current_theme_supports( 'disable-layout-styles' ) ) { - return $block_rules; - } - - if ( isset( $block_metadata['name'] ) ) { - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_metadata['name'] ); - if ( ! block_has_support( $block_type, array( '__experimentalLayout' ), false ) ) { - return $block_rules; - } - } - - $selector = isset( $block_metadata['selector'] ) ? $block_metadata['selector'] : ''; - $has_block_gap_support = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null; - $has_fallback_gap_support = ! $has_block_gap_support; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback gap styles support. - $node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() ); - $layout_definitions = _wp_array_get( $this->theme_json, array( 'settings', 'layout', 'definitions' ), array() ); - $layout_selector_pattern = '/^[a-zA-Z0-9\-\.\ *+>:\(\)]*$/'; // Allow alphanumeric classnames, spaces, wildcard, sibling, child combinator and pseudo class selectors. - - // Gap styles will only be output if the theme has block gap support, or supports a fallback gap. - // Default layout gap styles will be skipped for themes that do not explicitly opt-in to blockGap with a `true` or `false` value. - if ( $has_block_gap_support || $has_fallback_gap_support ) { - $block_gap_value = null; - // Use a fallback gap value if block gap support is not available. - if ( ! $has_block_gap_support ) { - $block_gap_value = static::ROOT_BLOCK_SELECTOR === $selector ? '0.5em' : null; - if ( ! empty( $block_type ) ) { - $block_gap_value = _wp_array_get( $block_type->supports, array( 'spacing', 'blockGap', '__experimentalDefault' ), null ); - } - } else { - $block_gap_value = static::get_property_value( $node, array( 'spacing', 'blockGap' ) ); - } - - // Support split row / column values and concatenate to a shorthand value. - if ( is_array( $block_gap_value ) ) { - if ( isset( $block_gap_value['top'] ) && isset( $block_gap_value['left'] ) ) { - $gap_row = static::get_property_value( $node, array( 'spacing', 'blockGap', 'top' ) ); - $gap_column = static::get_property_value( $node, array( 'spacing', 'blockGap', 'left' ) ); - $block_gap_value = $gap_row === $gap_column ? $gap_row : $gap_row . ' ' . $gap_column; - } else { - // Skip outputting gap value if not all sides are provided. - $block_gap_value = null; - } - } - - // If the block should have custom gap, add the gap styles. - if ( null !== $block_gap_value && false !== $block_gap_value && '' !== $block_gap_value ) { - foreach ( $layout_definitions as $layout_definition_key => $layout_definition ) { - // Allow outputting fallback gap styles for flex layout type when block gap support isn't available. - if ( ! $has_block_gap_support && 'flex' !== $layout_definition_key ) { - continue; - } - - $class_name = sanitize_title( _wp_array_get( $layout_definition, array( 'className' ), false ) ); - $spacing_rules = _wp_array_get( $layout_definition, array( 'spacingStyles' ), array() ); - - if ( - ! empty( $class_name ) && - ! empty( $spacing_rules ) - ) { - foreach ( $spacing_rules as $spacing_rule ) { - $declarations = array(); - if ( - isset( $spacing_rule['selector'] ) && - preg_match( $layout_selector_pattern, $spacing_rule['selector'] ) && - ! empty( $spacing_rule['rules'] ) - ) { - // Iterate over each of the styling rules and substitute non-string values such as `null` with the real `blockGap` value. - foreach ( $spacing_rule['rules'] as $css_property => $css_value ) { - $current_css_value = is_string( $css_value ) ? $css_value : $block_gap_value; - if ( static::is_safe_css_declaration( $css_property, $current_css_value ) ) { - $declarations[] = array( - 'name' => $css_property, - 'value' => $current_css_value, - ); - } - } - - if ( ! $has_block_gap_support ) { - // For fallback gap styles, use lower specificity, to ensure styles do not unintentionally override theme styles. - $format = static::ROOT_BLOCK_SELECTOR === $selector ? ':where(.%2$s%3$s)' : ':where(%1$s.%2$s%3$s)'; - $layout_selector = sprintf( - $format, - $selector, - $class_name, - $spacing_rule['selector'] - ); - } else { - $format = static::ROOT_BLOCK_SELECTOR === $selector ? '%s .%s%s' : '%s.%s%s'; - $layout_selector = sprintf( - $format, - $selector, - $class_name, - $spacing_rule['selector'] - ); - } - $block_rules .= static::to_ruleset( $layout_selector, $declarations ); - } - } - } - } - } - } - - // Output base styles. - if ( - static::ROOT_BLOCK_SELECTOR === $selector - ) { - $valid_display_modes = array( 'block', 'flex', 'grid' ); - foreach ( $layout_definitions as $layout_definition ) { - $class_name = sanitize_title( _wp_array_get( $layout_definition, array( 'className' ), false ) ); - $base_style_rules = _wp_array_get( $layout_definition, array( 'baseStyles' ), array() ); - - if ( - ! empty( $class_name ) && - ! empty( $base_style_rules ) - ) { - // Output display mode. This requires special handling as `display` is not exposed in `safe_style_css_filter`. - if ( - ! empty( $layout_definition['displayMode'] ) && - is_string( $layout_definition['displayMode'] ) && - in_array( $layout_definition['displayMode'], $valid_display_modes, true ) - ) { - $layout_selector = sprintf( - '%s .%s', - $selector, - $class_name - ); - $block_rules .= static::to_ruleset( - $layout_selector, - array( - array( - 'name' => 'display', - 'value' => $layout_definition['displayMode'], - ), - ) - ); - } - - foreach ( $base_style_rules as $base_style_rule ) { - $declarations = array(); - - if ( - isset( $base_style_rule['selector'] ) && - preg_match( $layout_selector_pattern, $base_style_rule['selector'] ) && - ! empty( $base_style_rule['rules'] ) - ) { - foreach ( $base_style_rule['rules'] as $css_property => $css_value ) { - if ( static::is_safe_css_declaration( $css_property, $css_value ) ) { - $declarations[] = array( - 'name' => $css_property, - 'value' => $css_value, - ); - } - } - - $layout_selector = sprintf( - '%s .%s%s', - $selector, - $class_name, - $base_style_rule['selector'] - ); - $block_rules .= static::to_ruleset( $layout_selector, $declarations ); - } - } - } - } - } - return $block_rules; - } - /** * Creates new rulesets as classes for each preset value such as: * @@ -1597,17 +1327,15 @@ class WP_Theme_JSON { * * @since 5.8.0 * @since 5.9.0 Added the `$settings` and `$properties` parameters. - * @since 6.1.0 Added `$theme_json`, `$selector`, and `$use_root_padding` parameters. + * @since 6.1.0 Added the `$theme_json` parameter. * - * @param array $styles Styles to process. - * @param array $settings Theme settings. - * @param array $properties Properties metadata. - * @param array $theme_json Theme JSON array. - * @param string $selector The style block selector. - * @param boolean $use_root_padding Whether to add custom properties at root level. - * @return array Returns the modified $declarations. + * @param array $styles Styles to process. + * @param array $settings Theme settings. + * @param array $properties Properties metadata. + * @param array $theme_json Theme JSON array. + * @return array Returns the modified $declarations. */ - protected static function compute_style_properties( $styles, $settings = array(), $properties = null, $theme_json = null, $selector = null, $use_root_padding = null ) { + protected static function compute_style_properties( $styles, $settings = array(), $properties = null, $theme_json = null ) { if ( null === $properties ) { $properties = static::PROPERTIES_METADATA; } @@ -1617,24 +1345,9 @@ class WP_Theme_JSON { return $declarations; } - $root_variable_duplicates = array(); - foreach ( $properties as $css_property => $value_path ) { $value = static::get_property_value( $styles, $value_path, $theme_json ); - if ( str_starts_with( $css_property, '--wp--style--root--' ) && ( static::ROOT_BLOCK_SELECTOR !== $selector || ! $use_root_padding ) ) { - continue; - } - // Root-level padding styles don't currently support strings with CSS shorthand values. - // This may change: https://github.com/WordPress/gutenberg/issues/40132. - if ( '--wp--style--root--padding' === $css_property && is_string( $value ) ) { - continue; - } - - if ( str_starts_with( $css_property, '--wp--style--root--' ) && $use_root_padding ) { - $root_variable_duplicates[] = substr( $css_property, strlen( '--wp--style--root--' ) ); - } - // Look up protected properties, keyed by value path. // Skip protected properties that are explicitly set to `null`. if ( is_array( $value_path ) ) { @@ -1659,14 +1372,6 @@ class WP_Theme_JSON { ); } - // If a variable value is added to the root, the corresponding property should be removed. - foreach ( $root_variable_duplicates as $duplicate ) { - $discard = array_search( $duplicate, array_column( $declarations, 'name' ), true ); - if ( is_numeric( $discard ) ) { - array_splice( $declarations, $discard, 1 ); - } - } - return $declarations; } @@ -1691,7 +1396,7 @@ class WP_Theme_JSON { * @return string|array Style property value. */ protected static function get_property_value( $styles, $path, $theme_json = null ) { - $value = _wp_array_get( $styles, $path ); + $value = _wp_array_get( $styles, $path, '' ); /* * This converts references to a path to the value at that path @@ -1724,7 +1429,7 @@ class WP_Theme_JSON { } } - if ( is_array( $value ) ) { + if ( '' === $value || is_array( $value ) ) { return $value; } @@ -1917,17 +1622,11 @@ class WP_Theme_JSON { $duotone_selector = $selectors[ $name ]['duotone']; } - $feature_selectors = null; - if ( isset( $selectors[ $name ]['features'] ) ) { - $feature_selectors = $selectors[ $name ]['features']; - } - $nodes[] = array( 'name' => $name, 'path' => array( 'styles', 'blocks', $name ), 'selector' => $selector, 'duotone' => $duotone_selector, - 'features' => $feature_selectors, ); if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'] ) ) { @@ -1960,47 +1659,15 @@ class WP_Theme_JSON { * * @since 6.1.0 * - * @param array $block_metadata Metadata about the block to get styles for. - * + * @param array $block_metadata Meta data about the block to get styles for. * @return array Styles for the block. */ public function get_styles_for_block( $block_metadata ) { - $node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() ); - $use_root_padding = isset( $this->theme_json['settings']['useRootPaddingAwareAlignments'] ) && true === $this->theme_json['settings']['useRootPaddingAwareAlignments']; - $selector = $block_metadata['selector']; - $settings = _wp_array_get( $this->theme_json, array( 'settings' ) ); - /* - * Process style declarations for block support features the current - * block contains selectors for. Values for a feature with a custom - * selector are filtered from the theme.json node before it is - * processed as normal. - */ - $feature_declarations = array(); + $node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() ); - if ( ! empty( $block_metadata['features'] ) ) { - foreach ( $block_metadata['features'] as $feature_name => $feature_selector ) { - if ( ! empty( $node[ $feature_name ] ) ) { - // Create temporary node containing only the feature data - // to leverage existing `compute_style_properties` function. - $feature = array( $feature_name => $node[ $feature_name ] ); - // Generate the feature's declarations only. - $new_feature_declarations = static::compute_style_properties( $feature, $settings, null, $this->theme_json ); - - // Merge new declarations with any that already exist for - // the feature selector. This may occur when multiple block - // support features use the same custom selector. - if ( isset( $feature_declarations[ $feature_selector ] ) ) { - $feature_declarations[ $feature_selector ] = array_merge( $feature_declarations[ $feature_selector ], $new_feature_declarations ); - } else { - $feature_declarations[ $feature_selector ] = $new_feature_declarations; - } - // Remove the feature from the block's node now the - // styles will be included under the feature level selector. - unset( $node[ $feature_name ] ); - } - } - } + $selector = $block_metadata['selector']; + $settings = _wp_array_get( $this->theme_json, array( 'settings' ) ); /* * Get a reference to element name from path. @@ -2042,9 +1709,9 @@ class WP_Theme_JSON { array_key_exists( $current_element, static::VALID_ELEMENT_PSEUDO_SELECTORS ) && in_array( $pseudo_selector, static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ], true ) ) { - $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, $this->theme_json, $selector, $use_root_padding ); + $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, $this->theme_json ); } else { - $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json, $selector, $use_root_padding ); + $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json ); } $block_rules = ''; @@ -2061,6 +1728,18 @@ class WP_Theme_JSON { } } + /* + * Reset default browser margin on the root body element. + * This is set on the root selector **before** generating the ruleset + * from the `theme.json`. This is to ensure that if the `theme.json` declares + * `margin` in its `spacing` declaration for the `body` element then these + * user-generated values take precedence in the CSS cascade. + * @link https://github.com/WordPress/gutenberg/issues/36147. + */ + if ( static::ROOT_BLOCK_SELECTOR === $selector ) { + $block_rules .= 'body { margin: 0; }'; + } + // 2. Generate and append the rules that use the general selector. $block_rules .= static::to_ruleset( $selector, $declarations ); @@ -2070,97 +1749,21 @@ class WP_Theme_JSON { $block_rules .= static::to_ruleset( $selector_duotone, $declarations_duotone ); } - // 4. Generate Layout block gap styles. - if ( - static::ROOT_BLOCK_SELECTOR !== $selector && - ! empty( $block_metadata['name'] ) - ) { - $block_rules .= $this->get_layout_styles( $block_metadata ); - } + if ( static::ROOT_BLOCK_SELECTOR === $selector ) { + $block_rules .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }'; + $block_rules .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }'; + $block_rules .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - // 5. Generate and append the feature level rulesets. - foreach ( $feature_declarations as $feature_selector => $individual_feature_declarations ) { - $block_rules .= static::to_ruleset( $feature_selector, $individual_feature_declarations ); + $has_block_gap_support = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null; + if ( $has_block_gap_support ) { + $block_rules .= '.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }'; + $block_rules .= '.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }'; + } } return $block_rules; } - /** - * Outputs the CSS for layout rules on the root. - * - * @since 6.1.0 - * - * @param string $selector The root node selector. - * @param array $block_metadata The metadata for the root block. - * @return string The additional root rules CSS. - */ - public function get_root_layout_rules( $selector, $block_metadata ) { - $css = ''; - $settings = _wp_array_get( $this->theme_json, array( 'settings' ) ); - $use_root_padding = isset( $this->theme_json['settings']['useRootPaddingAwareAlignments'] ) && true === $this->theme_json['settings']['useRootPaddingAwareAlignments']; - - /* - * Reset default browser margin on the root body element. - * This is set on the root selector **before** generating the ruleset - * from the `theme.json`. This is to ensure that if the `theme.json` declares - * `margin` in its `spacing` declaration for the `body` element then these - * user-generated values take precedence in the CSS cascade. - * @link https://github.com/WordPress/gutenberg/issues/36147. - */ - $css .= 'body { margin: 0;'; - - /* - * If there are content and wide widths in theme.json, output them - * as custom properties on the body element so all blocks can use them. - */ - if ( isset( $settings['layout']['contentSize'] ) || isset( $settings['layout']['wideSize'] ) ) { - $content_size = isset( $settings['layout']['contentSize'] ) ? $settings['layout']['contentSize'] : $settings['layout']['wideSize']; - $content_size = static::is_safe_css_declaration( 'max-width', $content_size ) ? $content_size : 'initial'; - $wide_size = isset( $settings['layout']['wideSize'] ) ? $settings['layout']['wideSize'] : $settings['layout']['contentSize']; - $wide_size = static::is_safe_css_declaration( 'max-width', $wide_size ) ? $wide_size : 'initial'; - $css .= '--wp--style--global--content-size: ' . $content_size . ';'; - $css .= '--wp--style--global--wide-size: ' . $wide_size . ';'; - } - - $css .= ' }'; - - if ( $use_root_padding ) { - // Top and bottom padding are applied to the outer block container. - $css .= '.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }'; - // Right and left padding are applied to the first container with `.has-global-padding` class. - $css .= '.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }'; - // Nested containers with `.has-global-padding` class do not get padding. - $css .= '.has-global-padding :where(.has-global-padding) { padding-right: 0; padding-left: 0; }'; - // Alignfull children of the container with left and right padding have negative margins so they can still be full width. - $css .= '.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }'; - // The above rule is negated for alignfull children of nested containers. - $css .= '.has-global-padding :where(.has-global-padding) > .alignfull { margin-right: 0; margin-left: 0; }'; - // Some of the children of alignfull blocks without content width should also get padding: text blocks and non-alignfull container blocks. - $css .= '.has-global-padding > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }'; - // The above rule also has to be negated for blocks inside nested `.has-global-padding` blocks. - $css .= '.has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0; }'; - } - - $css .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }'; - $css .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }'; - $css .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - - $block_gap_value = _wp_array_get( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ), '0.5em' ); - $has_block_gap_support = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null; - if ( $has_block_gap_support ) { - $block_gap_value = static::get_property_value( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ) ); - $css .= '.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }'; - $css .= ".wp-site-blocks > * + * { margin-block-start: $block_gap_value; }"; - - // For backwards compatibility, ensure the legacy block gap CSS variable is still available. - $css .= "$selector { --wp--style--block-gap: $block_gap_value; }"; - } - $css .= $this->get_layout_styles( $block_metadata ); - - return $css; - } - /** * For metadata values that can either be booleans or paths to booleans, gets the value. * diff --git a/src/wp-includes/global-styles-and-settings.php b/src/wp-includes/global-styles-and-settings.php index 1187837ed6..2e642cc2b1 100644 --- a/src/wp-includes/global-styles-and-settings.php +++ b/src/wp-includes/global-styles-and-settings.php @@ -107,7 +107,7 @@ function wp_get_global_stylesheet( $types = array() ) { $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support(); if ( empty( $types ) && ! $supports_theme_json ) { - $types = array( 'variables', 'presets', 'base-layout-styles' ); + $types = array( 'variables', 'presets' ); } elseif ( empty( $types ) ) { $types = array( 'variables', 'styles', 'presets' ); } diff --git a/src/wp-includes/theme.json b/src/wp-includes/theme.json index 40432cedf3..1ef000559b 100644 --- a/src/wp-includes/theme.json +++ b/src/wp-includes/theme.json @@ -2,7 +2,6 @@ "version": 2, "settings": { "appearanceTools": false, - "useRootPaddingAwareAlignments": false, "border": { "color": false, "radius": false, @@ -13,8 +12,8 @@ "background": true, "custom": true, "customDuotone": true, - "customGradient": true, - "defaultDuotone": true, + "customGradient": true, + "defaultDuotone": true, "defaultGradients": true, "defaultPalette": true, "duotone": [ @@ -186,158 +185,11 @@ ], "text": true }, - "layout": { - "definitions": { - "default": { - "name": "default", - "slug": "flow", - "className": "is-layout-flow", - "baseStyles": [ - { - "selector": " > .alignleft", - "rules": { - "float": "left", - "margin-inline-start": "0", - "margin-inline-end": "2em" - } - }, - { - "selector": " > .alignright", - "rules": { - "float": "right", - "margin-inline-start": "2em", - "margin-inline-end": "0" - } - }, - { - "selector": " > .aligncenter", - "rules": { - "margin-left": "auto !important", - "margin-right": "auto !important" - } - } - ], - "spacingStyles": [ - { - "selector": " > *", - "rules": { - "margin-block-start": "0", - "margin-block-end": "0" - } - }, - { - "selector": " > * + *", - "rules": { - "margin-block-start": null, - "margin-block-end": "0" - } - } - ] - }, - "constrained": { - "name": "constrained", - "slug": "constrained", - "className": "is-layout-constrained", - "baseStyles": [ - { - "selector": " > .alignleft", - "rules": { - "float": "left", - "margin-inline-start": "0", - "margin-inline-end": "2em" - } - }, - { - "selector": " > .alignright", - "rules": { - "float": "right", - "margin-inline-start": "2em", - "margin-inline-end": "0" - } - }, - { - "selector": " > .aligncenter", - "rules": { - "margin-left": "auto !important", - "margin-right": "auto !important" - } - }, - { - "selector": " > :where(:not(.alignleft):not(.alignright):not(.alignfull))", - "rules": { - "max-width": "var(--wp--style--global--content-size)", - "margin-left": "auto !important", - "margin-right": "auto !important" - } - }, - { - "selector": " > .alignwide", - "rules": { - "max-width": "var(--wp--style--global--wide-size)" - } - } - ], - "spacingStyles": [ - { - "selector": " > *", - "rules": { - "margin-block-start": "0", - "margin-block-end": "0" - } - }, - { - "selector": " > * + *", - "rules": { - "margin-block-start": null, - "margin-block-end": "0" - } - } - ] - }, - "flex": { - "name": "flex", - "slug": "flex", - "className": "is-layout-flex", - "displayMode": "flex", - "baseStyles": [ - { - "selector": "", - "rules": { - "flex-wrap": "wrap", - "align-items": "center" - } - }, - { - "selector": " > *", - "rules": { - "margin": "0" - } - } - ], - "spacingStyles": [ - { - "selector": "", - "rules": { - "gap": null - } - } - ] - } - } - }, "spacing": { "blockGap": null, "margin": false, "padding": false, - "customSpacingSize": true, - "units": [ "px", "em", "rem", "vh", "vw", "%" ], - "spacingScale": { - "operator": "*", - "increment": 1.5, - "steps": 7, - "mediumStep": 1.5, - "unit": "rem" - } + "units": [ "px", "em", "rem", "vh", "vw", "%" ] }, "typography": { "customFontSize": true, @@ -388,39 +240,6 @@ } }, "styles": { - "elements": { - "button": { - "color": { - "text": "#fff", - "background": "#32373c" - }, - "spacing": { - "padding": "calc(0.667em + 2px) calc(1.333em + 2px)" - }, - "typography": { - "fontSize": "inherit", - "fontFamily": "inherit", - "lineHeight": "inherit", - "textDecoration": "none" - }, - "border": { - "width": "0" - } - }, - "link": { - "typography": { - "textDecoration": "underline" - } - } - }, - "spacing": { - "blockGap": "24px", - "padding": { - "top": "0px", - "right": "0px", - "bottom": "0px", - "left": "0px" - } - } + "spacing": { "blockGap": "24px" } } } diff --git a/src/wp-includes/theme.php b/src/wp-includes/theme.php index 18afee3abd..3c7b297b2a 100644 --- a/src/wp-includes/theme.php +++ b/src/wp-includes/theme.php @@ -4026,13 +4026,6 @@ function create_initial_theme_features() { 'show_in_rest' => true, ) ); - register_theme_feature( - 'disable-layout-styles', - array( - 'description' => __( 'Whether the theme disables generated layout styles.' ), - 'show_in_rest' => true, - ) - ); register_theme_feature( 'editor-color-palette', array( diff --git a/tests/phpunit/tests/blocks/editor.php b/tests/phpunit/tests/blocks/editor.php index 53b8d96956..f08c350168 100644 --- a/tests/phpunit/tests/blocks/editor.php +++ b/tests/phpunit/tests/blocks/editor.php @@ -202,7 +202,7 @@ class Tests_Blocks_Editor extends WP_UnitTestCase { public function test_get_default_block_editor_settings() { $settings = get_default_block_editor_settings(); - $this->assertCount( 19, $settings ); + $this->assertCount( 18, $settings ); $this->assertFalse( $settings['alignWide'] ); $this->assertIsArray( $settings['allowedMimeTypes'] ); $this->assertTrue( $settings['allowedBlockTypes'] ); @@ -249,7 +249,6 @@ class Tests_Blocks_Editor extends WP_UnitTestCase { $this->assertFalse( $settings['disableCustomColors'] ); $this->assertFalse( $settings['disableCustomFontSizes'] ); $this->assertFalse( $settings['disableCustomGradients'] ); - $this->assertFalse( $settings['disableLayoutStyles'] ); $this->assertFalse( $settings['enableCustomLineHeight'] ); $this->assertFalse( $settings['enableCustomSpacing'] ); $this->assertFalse( $settings['enableCustomUnits'] ); diff --git a/tests/phpunit/tests/rest-api/rest-themes-controller.php b/tests/phpunit/tests/rest-api/rest-themes-controller.php index 8055e95116..da03319286 100644 --- a/tests/phpunit/tests/rest-api/rest-themes-controller.php +++ b/tests/phpunit/tests/rest-api/rest-themes-controller.php @@ -396,7 +396,6 @@ class WP_Test_REST_Themes_Controller extends WP_Test_REST_Controller_Testcase { $this->assertArrayHasKey( 'dark-editor-style', $theme_supports ); $this->assertArrayHasKey( 'disable-custom-font-sizes', $theme_supports ); $this->assertArrayHasKey( 'disable-custom-gradients', $theme_supports ); - $this->assertArrayHasKey( 'disable-layout-styles', $theme_supports ); $this->assertArrayHasKey( 'editor-color-palette', $theme_supports ); $this->assertArrayHasKey( 'editor-font-sizes', $theme_supports ); $this->assertArrayHasKey( 'editor-gradient-presets', $theme_supports ); @@ -407,7 +406,7 @@ class WP_Test_REST_Themes_Controller extends WP_Test_REST_Controller_Testcase { $this->assertArrayHasKey( 'responsive-embeds', $theme_supports ); $this->assertArrayHasKey( 'title-tag', $theme_supports ); $this->assertArrayHasKey( 'wp-block-styles', $theme_supports ); - $this->assertCount( 22, $theme_supports ); + $this->assertCount( 21, $theme_supports ); } /** diff --git a/tests/phpunit/tests/theme/wpThemeJson.php b/tests/phpunit/tests/theme/wpThemeJson.php index 7154b6d4d0..740ea4a6d7 100644 --- a/tests/phpunit/tests/theme/wpThemeJson.php +++ b/tests/phpunit/tests/theme/wpThemeJson.php @@ -423,7 +423,7 @@ class Tests_Theme_wpThemeJson extends WP_UnitTestCase { ) ); - $expected = 'body { margin: 0; }.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; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: 1em; }body { --wp--style--block-gap: 1em; }'; + $expected = 'body { margin: 0; }body{--wp--style--block-gap: 1em;}.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; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }'; $this->assertSame( $expected, $theme_json->get_stylesheet() ); $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } @@ -544,16 +544,13 @@ class Tests_Theme_wpThemeJson extends WP_UnitTestCase { ), ), ), - 'spacing' => array( - 'blockGap' => '24px', - ), ), 'misc' => 'value', ) ); $variables = 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}'; - $styles = 'body { margin: 0; }.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; }body{color: var(--wp--preset--color--grey);}a:where(:not(.wp-element-button)){background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a:where(:not(.wp-element-button)){color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button)){background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a:where(:not(.wp-element-button)){background-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}'; + $styles = 'body { margin: 0; }body{color: var(--wp--preset--color--grey);}.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; }a:where(:not(.wp-element-button)){background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a:where(:not(.wp-element-button)){color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button)){background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a:where(:not(.wp-element-button)){background-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}'; $presets = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-small-font-family{font-family: var(--wp--preset--font-family--small) !important;}.has-big-font-family{font-family: var(--wp--preset--font-family--big) !important;}'; $all = $variables . $styles . $presets; $this->assertSame( $all, $theme_json->get_stylesheet() ); @@ -2678,8 +2675,8 @@ class Tests_Theme_wpThemeJson extends WP_UnitTestCase { 'blocks' => array( 'core/group' => array( 'spacing' => array( - 'margin' => 'valid value', - 'display' => 'none', + 'margin' => 'valid value', + 'blockGap' => 'invalid value', ), ), ), @@ -2992,7 +2989,7 @@ class Tests_Theme_wpThemeJson extends WP_UnitTestCase { ) ); - $expected = 'body { margin: 0; }.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; }body{background-color: #ffffff;color: #000000;}.wp-element-button, .wp-block-button__link{background-color: #000000;color: #ffffff;}'; + $expected = 'body { margin: 0; }body{background-color: #ffffff;color: #000000;}.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; }.wp-element-button, .wp-block-button__link{background-color: #000000;color: #ffffff;}'; $this->assertSame( $expected, $theme_json->get_stylesheet() ); } @@ -3024,7 +3021,7 @@ class Tests_Theme_wpThemeJson extends WP_UnitTestCase { ) ); - $expected = 'body { margin: 0; }.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; }body{background-color: #ffffff;}.wp-element-button, .wp-block-button__link{color: #ffffff;}'; + $expected = 'body { margin: 0; }body{background-color: #ffffff;}.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; }.wp-element-button, .wp-block-button__link{color: #ffffff;}'; $this->assertSame( $expected, $theme_json->get_stylesheet() ); } @@ -3056,7 +3053,7 @@ class Tests_Theme_wpThemeJson extends WP_UnitTestCase { ) ); - $expected = 'body { margin: 0; }.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; }body{background-color: #ffffff;color: #ffffff;}.wp-element-button, .wp-block-button__link{color: #ffffff;}'; + $expected = 'body { margin: 0; }body{background-color: #ffffff;color: #ffffff;}.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; }.wp-element-button, .wp-block-button__link{color: #ffffff;}'; $this->assertSame( $expected, $theme_json->get_stylesheet() ); } @@ -3080,416 +3077,8 @@ class Tests_Theme_wpThemeJson extends WP_UnitTestCase { ) ); - $expected = 'body { margin: 0; }.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; }body{background-color: #ffffff;}'; + $expected = 'body { margin: 0; }body{background-color: #ffffff;}.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; }'; $this->assertSame( $expected, $theme_json->get_stylesheet() ); } - /** - * @dataProvider data_get_layout_definitions - * - * @ticket 56467 - * - * @param array $layout_definitions Layout definitions as stored in core theme.json. - */ - public function test_get_stylesheet_generates_layout_styles( $layout_definitions ) { - $theme_json = new WP_Theme_JSON( - array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, - 'settings' => array( - 'layout' => array( - 'definitions' => $layout_definitions, - ), - 'spacing' => array( - 'blockGap' => true, - ), - ), - 'styles' => array( - 'spacing' => array( - 'blockGap' => '1em', - ), - ), - ), - 'default' - ); - - // Results also include root site blocks styles. - $this->assertSame( - 'body { margin: 0; }.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; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: 1em; }body { --wp--style--block-gap: 1em; }body .is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}body .is-layout-flow > * + *{margin-block-start: 1em;margin-block-end: 0;}body .is-layout-flex{gap: 1em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}', - $theme_json->get_stylesheet( array( 'styles' ) ) - ); - } - - /** - * @dataProvider data_get_layout_definitions - * - * @ticket 56467 - * - * @param array $layout_definitions Layout definitions as stored in core theme.json. - */ - public function test_get_stylesheet_generates_layout_styles_with_spacing_presets( $layout_definitions ) { - $theme_json = new WP_Theme_JSON( - array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, - 'settings' => array( - 'layout' => array( - 'definitions' => $layout_definitions, - ), - 'spacing' => array( - 'blockGap' => true, - ), - ), - 'styles' => array( - 'spacing' => array( - 'blockGap' => 'var:preset|spacing|60', - ), - ), - ), - 'default' - ); - - // Results also include root site blocks styles. - $this->assertSame( - 'body { margin: 0; }.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; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var(--wp--preset--spacing--60); }body { --wp--style--block-gap: var(--wp--preset--spacing--60); }body .is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}body .is-layout-flow > * + *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}body .is-layout-flex{gap: var(--wp--preset--spacing--60);}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}', - $theme_json->get_stylesheet( array( 'styles' ) ) - ); - } - - /** - * @dataProvider data_get_layout_definitions - * - * @ticket 56467 - * - * @param array $layout_definitions Layout definitions as stored in core theme.json. - */ - public function test_get_stylesheet_generates_fallback_gap_layout_styles( $layout_definitions ) { - $theme_json = new WP_Theme_JSON( - array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, - 'settings' => array( - 'layout' => array( - 'definitions' => $layout_definitions, - ), - 'spacing' => array( - 'blockGap' => null, - ), - ), - 'styles' => array( - 'spacing' => array( - 'blockGap' => '1em', - ), - ), - ), - 'default' - ); - $stylesheet = $theme_json->get_stylesheet( array( 'styles' ) ); - - // Results also include root site blocks styles. - $this->assertSame( - 'body { margin: 0; }.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; }:where(.is-layout-flex){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}', - $stylesheet - ); - } - - /** - * @dataProvider data_get_layout_definitions - * - * @ticket 56467 - * - * @param array $layout_definitions Layout definitions as stored in core theme.json. - */ - public function test_get_stylesheet_generates_base_fallback_gap_layout_styles( $layout_definitions ) { - $theme_json = new WP_Theme_JSON( - array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, - 'settings' => array( - 'layout' => array( - 'definitions' => $layout_definitions, - ), - 'spacing' => array( - 'blockGap' => null, - ), - ), - ), - 'default' - ); - $stylesheet = $theme_json->get_stylesheet( array( 'base-layout-styles' ) ); - - // Note the `base-layout-styles` includes a fallback gap for the Columns block for backwards compatibility. - $this->assertSame( - ':where(.is-layout-flex){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}', - $stylesheet - ); - } - - /** - * @dataProvider data_get_layout_definitions - * - * @ticket 56467 - * - * @param array $layout_definitions Layout definitions as stored in core theme.json. - */ - public function test_get_stylesheet_skips_layout_styles( $layout_definitions ) { - add_theme_support( 'disable-layout-styles' ); - $theme_json = new WP_Theme_JSON( - array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, - 'settings' => array( - 'layout' => array( - 'definitions' => $layout_definitions, - ), - 'spacing' => array( - 'blockGap' => null, - ), - ), - ), - 'default' - ); - $stylesheet = $theme_json->get_stylesheet( array( 'base-layout-styles' ) ); - remove_theme_support( 'disable-layout-styles' ); - - // All Layout styles should be skipped. - $this->assertSame( - '', - $stylesheet - ); - } - - /** - * @dataProvider data_get_layout_definitions - * - * @ticket 56467 - * - * @param array $layout_definitions Layout definitions as stored in core theme.json. - */ - public function test_get_stylesheet_generates_valid_block_gap_values_and_skips_null_or_false_values( $layout_definitions ) { - $theme_json = new WP_Theme_JSON( - array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, - 'settings' => array( - 'layout' => array( - 'definitions' => $layout_definitions, - ), - 'spacing' => array( - 'blockGap' => true, - ), - ), - 'styles' => array( - 'spacing' => array( - 'blockGap' => '1rem', - ), - 'blocks' => array( - 'core/post-content' => array( - 'color' => array( - 'text' => 'gray', // This value should not render block layout styles. - ), - ), - 'core/social-links' => array( - 'spacing' => array( - 'blockGap' => '0', // This value should render block layout gap as zero. - ), - ), - 'core/buttons' => array( - 'spacing' => array( - 'blockGap' => 0, // This value should render block layout gap as zero. - ), - ), - 'core/columns' => array( - 'spacing' => array( - 'blockGap' => false, // This value should be ignored. The block will use the global layout value. - ), - ), - ), - ), - ), - 'default' - ); - - $this->assertEquals( - 'body { margin: 0; }.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; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: 1rem; }body { --wp--style--block-gap: 1rem; }body .is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}body .is-layout-flow > * + *{margin-block-start: 1rem;margin-block-end: 0;}body .is-layout-flex{gap: 1rem;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}.wp-block-post-content{color: gray;}.wp-block-social-links.is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links.is-layout-flow > * + *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links.is-layout-flex{gap: 0;}.wp-block-buttons.is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons.is-layout-flow > * + *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons.is-layout-flex{gap: 0;}', - $theme_json->get_stylesheet() - ); - } - - /** - * Data provider for layout tests. - * - * @ticket 56467 - * - * @return array - */ - public function data_get_layout_definitions() { - return array( - 'layout definitions' => array( - array( - 'default' => array( - 'name' => 'default', - 'slug' => 'flow', - 'className' => 'is-layout-flow', - 'baseStyles' => array( - array( - 'selector' => ' > .alignleft', - 'rules' => array( - 'float' => 'left', - 'margin-inline-start' => '0', - 'margin-inline-end' => '2em', - ), - ), - array( - 'selector' => ' > .alignright', - 'rules' => array( - 'float' => 'right', - 'margin-inline-start' => '2em', - 'margin-inline-end' => '0', - ), - ), - array( - 'selector' => ' > .aligncenter', - 'rules' => array( - 'margin-left' => 'auto !important', - 'margin-right' => 'auto !important', - ), - ), - ), - 'spacingStyles' => array( - array( - 'selector' => ' > *', - 'rules' => array( - 'margin-block-start' => '0', - 'margin-block-end' => '0', - ), - ), - array( - 'selector' => ' > * + *', - 'rules' => array( - 'margin-block-start' => null, - 'margin-block-end' => '0', - ), - ), - ), - ), - 'flex' => array( - 'name' => 'flex', - 'slug' => 'flex', - 'className' => 'is-layout-flex', - 'displayMode' => 'flex', - 'baseStyles' => array( - array( - 'selector' => '', - 'rules' => array( - 'flex-wrap' => 'wrap', - 'align-items' => 'center', - ), - ), - ), - 'spacingStyles' => array( - array( - 'selector' => '', - 'rules' => array( - 'gap' => null, - ), - ), - ), - ), - ), - ), - ); - } - - /** - * @ticket 56467 - */ - function test_get_styles_for_block_with_padding_aware_alignments() { - $theme_json = new WP_Theme_JSON( - array( - 'version' => 2, - 'styles' => array( - 'spacing' => array( - 'padding' => array( - 'top' => '10px', - 'right' => '12px', - 'bottom' => '10px', - 'left' => '12px', - ), - ), - ), - 'settings' => array( - 'useRootPaddingAwareAlignments' => true, - ), - ) - ); - - $metadata = array( - 'path' => array( - '0' => 'styles', - ), - 'selector' => 'body', - ); - - $expected = 'body { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding) { padding-right: 0; padding-left: 0; }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(.has-global-padding) > .alignfull { margin-right: 0; margin-left: 0; }.has-global-padding > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0; }.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; }body{--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}'; - $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata ); - $style_rules = $theme_json->get_styles_for_block( $metadata ); - $this->assertSame( $expected, $root_rules . $style_rules ); - } - - /** - * @ticket 56467 - */ - function test_get_styles_for_block_without_padding_aware_alignments() { - $theme_json = new WP_Theme_JSON( - array( - 'version' => 2, - 'styles' => array( - 'spacing' => array( - 'padding' => array( - 'top' => '10px', - 'right' => '12px', - 'bottom' => '10px', - 'left' => '12px', - ), - ), - ), - ) - ); - - $metadata = array( - 'path' => array( - '0' => 'styles', - ), - 'selector' => 'body', - ); - - $expected = 'body { margin: 0; }.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; }body{padding-top: 10px;padding-right: 12px;padding-bottom: 10px;padding-left: 12px;}'; - $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata ); - $style_rules = $theme_json->get_styles_for_block( $metadata ); - $this->assertSame( $expected, $root_rules . $style_rules ); - } - - /** - * @ticket 56467 - */ - function test_get_styles_for_block_with_content_width() { - $theme_json = new WP_Theme_JSON( - array( - 'version' => 2, - 'settings' => array( - 'layout' => array( - 'contentSize' => '800px', - 'wideSize' => '1000px', - ), - ), - ) - ); - - $metadata = array( - 'path' => array( - '0' => 'settings', - ), - 'selector' => 'body', - ); - - $expected = 'body { margin: 0;--wp--style--global--content-size: 800px;--wp--style--global--wide-size: 1000px; }.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; }'; - $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata ); - $style_rules = $theme_json->get_styles_for_block( $metadata ); - $this->assertSame( $expected, $root_rules . $style_rules ); - } }