-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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 defaultSpacingSizes option (theme.json v3) #61842
Changes from all commits
343fafc
21cf2ba
119bff1
f19da26
9ede3bb
b3f304b
666fc4e
0301b49
f5010ef
6fbb99f
b1126b7
8a5f339
73d63a7
ada604b
882f02e
3415b6a
8529aef
5d2762a
8093334
59eaac3
1aafb16
21e6de7
d42932b
c5778d0
31ac387
17db2d4
25dc819
144dc5a
a592617
1a3d0c2
12edffa
44bf7b8
de077ad
d9c5c85
1dfcaa3
2af96a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
https://github.com/WordPress/wordpress-develop/pull/6616 | ||
|
||
* https://github.com/WordPress/gutenberg/pull/58409 | ||
* https://github.com/WordPress/gutenberg/pull/61328 | ||
* https://github.com/WordPress/gutenberg/pull/61842 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -123,6 +123,7 @@ class WP_Theme_JSON_Gutenberg { | |
* @since 6.0.0 Replaced `override` with `prevent_override` and updated the | ||
* `prevent_override` value for `color.duotone` to use `color.defaultDuotone`. | ||
* @since 6.2.0 Added 'shadow' presets. | ||
* @since 6.6.0 Updated the 'prevent_override' value for font size presets to use 'typography.defaultFontSizes' and spacing size presets to use `spacing.defaultSpacingSizes`. | ||
* @since 6.6.0 Added `aspectRatios`. | ||
* @var array | ||
*/ | ||
|
@@ -187,7 +188,7 @@ class WP_Theme_JSON_Gutenberg { | |
), | ||
array( | ||
'path' => array( 'spacing', 'spacingSizes' ), | ||
'prevent_override' => false, | ||
'prevent_override' => array( 'spacing', 'defaultSpacingSizes' ), | ||
'use_default_names' => true, | ||
'value_key' => 'size', | ||
'css_vars' => '--wp--preset--spacing--$slug', | ||
|
@@ -427,13 +428,14 @@ class WP_Theme_JSON_Gutenberg { | |
'sticky' => null, | ||
), | ||
'spacing' => array( | ||
'customSpacingSize' => null, | ||
'spacingSizes' => null, | ||
'spacingScale' => null, | ||
'blockGap' => null, | ||
'margin' => null, | ||
'padding' => null, | ||
'units' => null, | ||
'customSpacingSize' => null, | ||
'defaultSpacingSizes' => null, | ||
'spacingSizes' => null, | ||
'spacingScale' => null, | ||
'blockGap' => null, | ||
'margin' => null, | ||
'padding' => null, | ||
'units' => null, | ||
), | ||
'shadow' => array( | ||
'presets' => null, | ||
|
@@ -727,6 +729,8 @@ public static function get_element_class_name( $element ) { | |
* Constructor. | ||
* | ||
* @since 5.8.0 | ||
* @since 6.6.0 Key spacingScale by origin, and pre-generate the | ||
* spacingSizes from spacingScale. | ||
* | ||
* @param array $theme_json A structure that follows the theme.json schema. | ||
* @param string $origin Optional. What source of data this object represents. | ||
|
@@ -742,8 +746,8 @@ public function __construct( $theme_json = array( 'version' => WP_Theme_JSON_Gut | |
$valid_block_names = array_keys( $registry->get_all_registered() ); | ||
$valid_element_names = array_keys( static::ELEMENTS ); | ||
$valid_variations = static::get_valid_block_style_variations(); | ||
$theme_json = static::sanitize( $this->theme_json, $valid_block_names, $valid_element_names, $valid_variations ); | ||
$this->theme_json = static::maybe_opt_in_into_settings( $theme_json ); | ||
$this->theme_json = static::sanitize( $this->theme_json, $valid_block_names, $valid_element_names, $valid_variations ); | ||
$this->theme_json = static::maybe_opt_in_into_settings( $this->theme_json ); | ||
|
||
// Internally, presets are keyed by origin. | ||
$nodes = static::get_setting_nodes( $this->theme_json ); | ||
|
@@ -762,6 +766,27 @@ public function __construct( $theme_json = array( 'version' => WP_Theme_JSON_Gut | |
} | ||
} | ||
} | ||
|
||
// In addition to presets, spacingScale (which generates presets) is also keyed by origin. | ||
$scale_path = array( 'settings', 'spacing', 'spacingScale' ); | ||
$spacing_scale = _wp_array_get( $this->theme_json, $scale_path, null ); | ||
if ( null !== $spacing_scale ) { | ||
// If the spacingScale is not already keyed by origin. | ||
if ( empty( array_intersect( array_keys( $spacing_scale ), static::VALID_ORIGINS ) ) ) { | ||
_wp_array_set( $this->theme_json, $scale_path, array( $origin => $spacing_scale ) ); | ||
} | ||
} | ||
|
||
// Pre-generate the spacingSizes from spacingScale. | ||
$scale_path = array( 'settings', 'spacing', 'spacingScale', $origin ); | ||
$spacing_scale = _wp_array_get( $this->theme_json, $scale_path, null ); | ||
if ( isset( $spacing_scale ) ) { | ||
$sizes_path = array( 'settings', 'spacing', 'spacingSizes', $origin ); | ||
$spacing_sizes = _wp_array_get( $this->theme_json, $sizes_path, array() ); | ||
$spacing_scale_sizes = static::compute_spacing_sizes( $spacing_scale ); | ||
$merged_spacing_sizes = static::merge_spacing_sizes( $spacing_scale_sizes, $spacing_sizes ); | ||
_wp_array_set( $this->theme_json, $sizes_path, $merged_spacing_sizes ); | ||
} | ||
} | ||
|
||
/** | ||
|
@@ -2947,13 +2972,49 @@ protected static function get_metadata_boolean( $data, $path, $default_value = f | |
* | ||
* @since 5.8.0 | ||
* @since 5.9.0 Duotone preset also has origins. | ||
* @since 6.6.0 Use the spacingScale keyed by origin, and re-generate the | ||
* spacingSizes from spacingScale. | ||
* | ||
* @param WP_Theme_JSON_Gutenberg $incoming Data to merge. | ||
*/ | ||
public function merge( $incoming ) { | ||
$incoming_data = $incoming->get_raw_data(); | ||
$this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data ); | ||
|
||
/* | ||
* Recompute all the spacing sizes based on the new hierarchy of data. In the constructor | ||
* spacingScale and spacingSizes are both keyed by origin and VALID_ORIGINS is ordered, so | ||
* we can allow partial spacingScale data to inherit missing data from earlier layers when | ||
* computing the spacing sizes. | ||
* | ||
* This happens before the presets are merged to ensure that default spacing sizes can be | ||
* removed from the theme origin if $prevent_override is true. | ||
*/ | ||
$flattened_spacing_scale = array(); | ||
foreach ( static::VALID_ORIGINS as $origin ) { | ||
$scale_path = array( 'settings', 'spacing', 'spacingScale', $origin ); | ||
|
||
// Apply the base spacing scale to the current layer. | ||
$base_spacing_scale = _wp_array_get( $this->theme_json, $scale_path, array() ); | ||
$flattened_spacing_scale = array_replace( $flattened_spacing_scale, $base_spacing_scale ); | ||
|
||
$spacing_scale = _wp_array_get( $incoming_data, $scale_path, null ); | ||
if ( ! isset( $spacing_scale ) ) { | ||
continue; | ||
} | ||
|
||
// Allow partial scale settings by merging with lower layers. | ||
$flattened_spacing_scale = array_replace( $flattened_spacing_scale, $spacing_scale ); | ||
|
||
// Generate and merge the scales for this layer. | ||
$sizes_path = array( 'settings', 'spacing', 'spacingSizes', $origin ); | ||
$spacing_sizes = _wp_array_get( $incoming_data, $sizes_path, array() ); | ||
$spacing_scale_sizes = static::compute_spacing_sizes( $flattened_spacing_scale ); | ||
$merged_spacing_sizes = static::merge_spacing_sizes( $spacing_scale_sizes, $spacing_sizes ); | ||
|
||
_wp_array_set( $incoming_data, $sizes_path, $merged_spacing_sizes ); | ||
} | ||
|
||
/* | ||
* The array_replace_recursive algorithm merges at the leaf level, | ||
* but we don't want leaf arrays to be merged, so we overwrite it. | ||
|
@@ -3733,12 +3794,19 @@ public function get_data() { | |
/** | ||
* Sets the spacingSizes array based on the spacingScale values from theme.json. | ||
* | ||
* No longer used since theme.json version 3 as the spacingSizes are now | ||
* automatically generated during construction and merge instead of manually | ||
* set in the resolver. | ||
* | ||
* @since 6.1.0 | ||
* @deprecated 6.6.0 | ||
* | ||
* @return null|void | ||
*/ | ||
public function set_spacing_sizes() { | ||
$spacing_scale = $this->theme_json['settings']['spacing']['spacingScale'] ?? array(); | ||
_deprecated_function( __METHOD__, '6.6.0' ); | ||
|
||
$spacing_scale = $this->theme_json['settings']['spacing']['spacingScale']['default'] ?? array(); | ||
|
||
// Gutenberg didn't have the 1st isset check. | ||
if ( ! isset( $spacing_scale['steps'] ) | ||
|
@@ -3762,6 +3830,94 @@ public function set_spacing_sizes() { | |
return null; | ||
} | ||
|
||
$spacing_sizes = static::compute_spacing_sizes( $spacing_scale ); | ||
|
||
// If there are 7 or less steps in the scale revert to numbers for labels instead of t-shirt sizes. | ||
if ( $spacing_scale['steps'] <= 7 ) { | ||
for ( $spacing_sizes_count = 0; $spacing_sizes_count < count( $spacing_sizes ); $spacing_sizes_count++ ) { | ||
$spacing_sizes[ $spacing_sizes_count ]['name'] = (string) ( $spacing_sizes_count + 1 ); | ||
} | ||
} | ||
|
||
_wp_array_set( $this->theme_json, array( 'settings', 'spacing', 'spacingSizes', 'default' ), $spacing_sizes ); | ||
} | ||
|
||
/** | ||
* Merges two sets of spacing size presets. | ||
* | ||
* @since 6.6.0 | ||
* | ||
* @param array $base The base set of spacing sizes. | ||
* @param array $incoming The set of spacing sizes to merge with the base. Duplicate slugs will override the base values. | ||
* @return array The merged set of spacing sizes. | ||
*/ | ||
private static function merge_spacing_sizes( $base, $incoming ) { | ||
$merged = array(); | ||
foreach ( $base as $item ) { | ||
$merged[ $item['slug'] ] = $item; | ||
} | ||
foreach ( $incoming as $item ) { | ||
$merged[ $item['slug'] ] = $item; | ||
} | ||
return array_values( $merged ); | ||
} | ||
|
||
/** | ||
* Generates a set of spacing sizes by starting with a medium size and | ||
* applying an operator with an increment value to generate the rest of the | ||
* sizes outward from the medium size. The medium slug is '50' with the rest | ||
* of the slugs being 10 apart. The generated names use t-shirt sizing. | ||
* | ||
* Example: | ||
* | ||
* $spacing_scale = array( | ||
* 'steps' => 4, | ||
* 'mediumStep' => 16, | ||
* 'unit' => 'px', | ||
* 'operator' => '+', | ||
* 'increment' => 2, | ||
* ); | ||
* $spacing_sizes = static::compute_spacing_sizes( $spacing_scale ); | ||
* // -> array( | ||
* // array( 'name' => 'Small', 'slug' => '40', 'size' => '14px' ), | ||
* // array( 'name' => 'Medium', 'slug' => '50', 'size' => '16px' ), | ||
* // array( 'name' => 'Large', 'slug' => '60', 'size' => '18px' ), | ||
* // array( 'name' => 'X-Large', 'slug' => '70', 'size' => '20px' ), | ||
* // ) | ||
* | ||
* @since 6.6.0 | ||
* | ||
* @param array $spacing_scale { | ||
* The spacing scale values. All are required. | ||
* | ||
* @type int $steps The number of steps in the scale. (up to 10 steps are supported.) | ||
* @type float $mediumStep The middle value that gets the slug '50'. (For even number of steps, this becomes the first middle value.) | ||
* @type string $unit The CSS unit to use for the sizes. | ||
* @type string $operator The mathematical operator to apply to generate the other sizes. Either '+' or '*'. | ||
* @type float $increment The value used with the operator to generate the other sizes. | ||
* } | ||
* @return array The spacing sizes presets or an empty array if some spacing scale values are missing or invalid. | ||
*/ | ||
private static function compute_spacing_sizes( $spacing_scale ) { | ||
/* | ||
* This condition is intentionally missing some checks on ranges for the values in order to | ||
* keep backwards compatibility with the previous implementation. | ||
*/ | ||
if ( | ||
! isset( $spacing_scale['steps'] ) || | ||
! is_numeric( $spacing_scale['steps'] ) || | ||
0 === $spacing_scale['steps'] || | ||
! isset( $spacing_scale['mediumStep'] ) || | ||
! is_numeric( $spacing_scale['mediumStep'] ) || | ||
! isset( $spacing_scale['unit'] ) || | ||
! isset( $spacing_scale['operator'] ) || | ||
( '+' !== $spacing_scale['operator'] && '*' !== $spacing_scale['operator'] ) || | ||
! isset( $spacing_scale['increment'] ) || | ||
! is_numeric( $spacing_scale['increment'] ) | ||
Comment on lines
+3907
to
+3916
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a blocker but I wonder if we should have unit tests for this mammoth of a condition? Can be a follow up There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's leave it for a follow-up. There are already some tests for the existence of these conditions, but not the things it doesn't catch like |
||
) { | ||
return array(); | ||
} | ||
|
||
$unit = '%' === $spacing_scale['unit'] ? '%' : sanitize_title( $spacing_scale['unit'] ); | ||
$current_step = $spacing_scale['mediumStep']; | ||
$steps_mid_point = round( $spacing_scale['steps'] / 2, 0 ); | ||
|
@@ -3844,14 +4000,7 @@ public function set_spacing_sizes() { | |
$spacing_sizes[] = $above_sizes_item; | ||
} | ||
|
||
// If there are 7 or less steps in the scale revert to numbers for labels instead of t-shirt sizes. | ||
if ( $spacing_scale['steps'] <= 7 ) { | ||
for ( $spacing_sizes_count = 0; $spacing_sizes_count < count( $spacing_sizes ); $spacing_sizes_count++ ) { | ||
$spacing_sizes[ $spacing_sizes_count ]['name'] = (string) ( $spacing_sizes_count + 1 ); | ||
} | ||
} | ||
|
||
_wp_array_set( $this->theme_json, array( 'settings', 'spacing', 'spacingSizes', 'default' ), $spacing_sizes ); | ||
return $spacing_sizes; | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -600,7 +600,6 @@ public static function get_merged_data( $origin = 'custom' ) { | |
$result = new WP_Theme_JSON_Gutenberg(); | ||
$result->merge( static::get_core_data() ); | ||
if ( 'default' === $origin ) { | ||
$result->set_spacing_sizes(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved to |
||
return $result; | ||
} | ||
|
||
|
@@ -611,12 +610,10 @@ public static function get_merged_data( $origin = 'custom' ) { | |
|
||
$result->merge( static::get_theme_data() ); | ||
if ( 'theme' === $origin ) { | ||
$result->set_spacing_sizes(); | ||
return $result; | ||
} | ||
|
||
$result->merge( static::get_user_data() ); | ||
$result->set_spacing_sizes(); | ||
return $result; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't the documentation page where keys are defined, just the one that explains what gets generated in the stylesheet, so I removed this chunk. The actual documentation exists in the Theme Handbook which isn't part of Gutenberg source code.