Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Enqueue core and theme colors by using separate structures per origin. #32358

Merged
merged 8 commits into from
Jun 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 73 additions & 73 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,34 @@ private static function append_to_selector( $selector, $to_append ) {
return implode( ',', $new_selectors );
}

/**
* Function that given an array of presets keyed by origin
* and the value key of the preset returns an array where each key is
* the a preset slug and each value is the preset value.
*
* @param array $preset_per_origin Array of presets keyed by origin.
* @param string $value_key The property of the preset that contains its value.
*
* @return array Array of presets where each key is a slug and each value is the preset value.
*/
private static function get_merged_preset_by_slug( $preset_per_origin, $value_key ) {
$origins = array( 'core', 'theme', 'user' );
$result = array();
foreach ( $origins as $origin ) {
if ( ! isset( $preset_per_origin[ $origin ] ) ) {
continue;
}
foreach ( $preset_per_origin[ $origin ] as $preset ) {
// We don't want to use kebabCase here,
// see https://github.com/WordPress/gutenberg/issues/32347
// However, we need to make sure the generated class or css variable
// doesn't contain spaces.
$result[ preg_replace( '/\s+/', '-', $preset['slug'] ) ] = $preset[ $value_key ];
}
}
return $result;
}

/**
* Given a settings array, it returns the generated rulesets
* for the preset classes.
Expand All @@ -664,19 +692,16 @@ private static function compute_preset_classes( $settings, $selector ) {

$stylesheet = '';
foreach ( self::PRESETS_METADATA as $preset ) {
$values = _wp_array_get( $settings, $preset['path'], array() );
foreach ( $values as $value ) {
foreach ( $preset['classes'] as $class ) {
$preset_per_origin = _wp_array_get( $settings, $preset['path'], array() );
$preset_by_slug = self::get_merged_preset_by_slug( $preset_per_origin, $preset['value_key'] );
foreach ( $preset['classes'] as $class ) {
foreach ( $preset_by_slug as $slug => $value ) {
$stylesheet .= self::to_ruleset(
// We don't want to use kebabCase here,
// see https://github.com/WordPress/gutenberg/issues/32347
// However, we need to make sure the generated class
// doesn't contain spaces.
self::append_to_selector( $selector, '.has-' . preg_replace( '/\s+/', '-', $value['slug'] ) . '-' . $class['class_suffix'] ),
self::append_to_selector( $selector, '.has-' . $slug . '-' . $class['class_suffix'] ),
array(
array(
'name' => $class['property_name'],
'value' => $value[ $preset['value_key'] ] . ' !important',
'value' => $value . ' !important',
),
)
);
Expand Down Expand Up @@ -706,11 +731,12 @@ private static function compute_preset_classes( $settings, $selector ) {
private static function compute_preset_vars( $settings ) {
$declarations = array();
foreach ( self::PRESETS_METADATA as $preset ) {
$values = _wp_array_get( $settings, $preset['path'], array() );
foreach ( $values as $value ) {
$preset_per_origin = _wp_array_get( $settings, $preset['path'], array() );
$preset_by_slug = self::get_merged_preset_by_slug( $preset_per_origin, $preset['value_key'] );
foreach ( $preset_by_slug as $slug => $value ) {
$declarations[] = array(
'name' => '--wp--preset--' . $preset['css_var_infix'] . '--' . $value['slug'],
'value' => $value[ $preset['value_key'] ],
'name' => '--wp--preset--' . $preset['css_var_infix'] . '--' . $slug,
'value' => $value,
);
}
}
Expand Down Expand Up @@ -1106,85 +1132,59 @@ public function get_stylesheet( $type = 'all' ) {
/**
* Merge new incoming data.
*
* @param WP_Theme_JSON_Gutenberg $incoming Data to merge.
* @param string $update_or_remove Whether update or remove existing colors
* for which the incoming data has a duplicated slug.
* @param WP_Theme_JSON $incoming Data to merge.
* @param string $origin origin of the incoming data (e.g: core, theme, or user).
*/
public function merge( $incoming, $update_or_remove = 'remove' ) {
$incoming_data = $incoming->get_raw_data();
$existing_data = $this->theme_json;
public function merge( $incoming, $origin ) {

$incoming_data = $incoming->get_raw_data();
$this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data );

// The array_replace_recursive algorithm merges at the leaf level.
// For leaf values that are arrays it will use the numeric indexes for replacement.
$this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data );
// In those cases, what we want is to use the incoming value, if it exists.
//
// These are the cases that have array values at the leaf levels.
$properties = array();
$properties[] = array( 'custom' );
$properties[] = array( 'spacing', 'units' );
$properties[] = array( 'color', 'duotone' );

// There are a few cases in which we want to merge things differently
// from what array_replace_recursive does.

// Some incoming properties should replace the existing.
$to_replace = array();
$to_replace[] = array( 'custom' );
$to_replace[] = array( 'spacing', 'units' );
$to_replace[] = array( 'typography', 'fontSizes' );
$to_replace[] = array( 'typography', 'fontFamilies' );

// Some others should be appended to the existing.
// If the slug is the same than an existing element,
// the $update_or_remove param is used to decide
// what to do with the existing element:
// either remove it and append the incoming,
// or update it with the incoming.
$to_append = array();
$to_append[] = array( 'color', 'duotone' );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're missing duotone from the list.

Naming: with the new behavior for merge to_replace / to_append no longer make sense, we could look for better names to both these. Perhaps $properties and $propertis_per_origin?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think duotone should be part of this list. For the duotone case, we don't have classes or CSS variables it is a server-side dynamic mechanism.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, my point is that we're missing it: it's not in any list at the moment (either $properties or $to_append).

$to_append[] = array( 'color', 'gradients' );
$to_append[] = array( 'color', 'palette' );
$to_append[] = array( 'color', 'gradients' );
$to_append[] = array( 'typography', 'fontSizes' );
$to_append[] = array( 'typography', 'fontFamilies' );

$nodes = self::get_setting_nodes( $this->theme_json );
foreach ( $nodes as $metadata ) {
foreach ( $to_replace as $path_to_replace ) {
$path = array_merge( $metadata['path'], $path_to_replace );
foreach ( $properties as $property_path ) {
$path = array_merge( $metadata['path'], $property_path );
$node = _wp_array_get( $incoming_data, $path, array() );
if ( ! empty( $node ) ) {
gutenberg_experimental_set( $this->theme_json, $path, $node );
}
}
foreach ( $to_append as $path_to_append ) {
$path = array_merge( $metadata['path'], $path_to_append );
$incoming_node = _wp_array_get( $incoming_data, $path, array() );
$existing_node = _wp_array_get( $existing_data, $path, array() );

if ( empty( $incoming_node ) && empty( $existing_node ) ) {
continue;
}

$index_table = array();
$existing_slugs = array();
$merged = array();
foreach ( $existing_node as $key => $value ) {
$index_table[ $value['slug'] ] = $key;
$existing_slugs[] = $value['slug'];
$merged[ $key ] = $value;
}

$to_remove = array();
foreach ( $incoming_node as $value ) {
if ( ! in_array( $value['slug'], $existing_slugs, true ) ) {
$merged[] = $value;
} elseif ( 'update' === $update_or_remove ) {
$merged[ $index_table[ $value['slug'] ] ] = $value;
foreach ( $to_append as $property_path ) {
$path = array_merge( $metadata['path'], $property_path );
$node = _wp_array_get( $incoming_data, $path, null );
if ( null !== $node ) {
$existing_node = _wp_array_get( $this->theme_json, $path, null );
$new_node = array_filter(
$existing_node,
function ( $key ) {
return in_array( $key, array( 'core', 'theme', 'user ' ), true );
},
ARRAY_FILTER_USE_KEY
);
if ( isset( $node[ $origin ] ) ) {
$new_node[ $origin ] = $node[ $origin ];
} else {
$merged[] = $value;
$to_remove[] = $index_table[ $value['slug'] ];
$new_node[ $origin ] = $node;
}
gutenberg_experimental_set( $this->theme_json, $path, $new_node );
}

// Remove the duplicated values and pack the sparsed array.
foreach ( $to_remove as $index ) {
unset( $merged[ $index ] );
}
$merged = array_values( $merged );

gutenberg_experimental_set( $this->theme_json, $path, $merged );
}
}

Expand Down
8 changes: 4 additions & 4 deletions lib/class-wp-theme-json-resolver-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ public static function get_theme_data( $theme_support_data = array() ) {
* to override the ones declared via add_theme_support.
*/
$with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data );
$with_theme_supports->merge( self::$theme );
$with_theme_supports->merge( self::$theme, 'theme' );

return $with_theme_supports;
}
Expand Down Expand Up @@ -415,11 +415,11 @@ public static function get_merged_data( $settings = array(), $origin = 'user' )
$theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $settings );

$result = new WP_Theme_JSON_Gutenberg();
$result->merge( self::get_core_data() );
$result->merge( self::get_theme_data( $theme_support_data ) );
$result->merge( self::get_core_data(), 'core' );
$result->merge( self::get_theme_data( $theme_support_data ), 'theme' );

if ( 'user' === $origin ) {
$result->merge( self::get_user_data(), 'update' );
$result->merge( self::get_user_data(), 'user' );
}

return $result;
Expand Down
72 changes: 24 additions & 48 deletions lib/experimental-default-theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,148 +6,124 @@
{
"name": "Black",
"slug": "black",
"color": "#000000",
"origin": "core"
"color": "#000000"
},
{
"name": "Cyan bluish gray",
"slug": "cyan-bluish-gray",
"color": "#abb8c3",
"origin": "core"
"color": "#abb8c3"
},
{
"name": "White",
"slug": "white",
"color": "#ffffff",
"origin": "core"
"color": "#ffffff"
},
{
"name": "Pale pink",
"slug": "pale-pink",
"color": "#f78da7",
"origin": "core"
"color": "#f78da7"
},
{
"name": "Vivid red",
"slug": "vivid-red",
"color": "#cf2e2e",
"origin": "core"
"color": "#cf2e2e"
},
{
"name": "Luminous vivid orange",
"slug": "luminous-vivid-orange",
"color": "#ff6900",
"origin": "core"
"color": "#ff6900"
},
{
"name": "Luminous vivid amber",
"slug": "luminous-vivid-amber",
"color": "#fcb900",
"origin": "core"
"color": "#fcb900"
},
{
"name": "Light green cyan",
"slug": "light-green-cyan",
"color": "#7bdcb5",
"origin": "core"
"color": "#7bdcb5"
},
{
"name": "Vivid green cyan",
"slug": "vivid-green-cyan",
"color": "#00d084",
"origin": "core"
"color": "#00d084"
},
{
"name": "Pale cyan blue",
"slug": "pale-cyan-blue",
"color": "#8ed1fc",
"origin": "core"
"color": "#8ed1fc"
},
{
"name": "Vivid cyan blue",
"slug": "vivid-cyan-blue",
"color": "#0693e3",
"origin": "core"
"color": "#0693e3"
},
{
"name": "Vivid purple",
"slug": "vivid-purple",
"color": "#9b51e0",
"origin": "core"
"color": "#9b51e0"
}
],
"gradients": [
{
"name": "Vivid cyan blue to vivid purple",
"gradient": "linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)",
"slug": "vivid-cyan-blue-to-vivid-purple",
"origin": "core"
"slug": "vivid-cyan-blue-to-vivid-purple"
},
{
"name": "Light green cyan to vivid green cyan",
"gradient": "linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)",
"slug": "light-green-cyan-to-vivid-green-cyan",
"origin": "core"
"slug": "light-green-cyan-to-vivid-green-cyan"
},
{
"name": "Luminous vivid amber to luminous vivid orange",
"gradient": "linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%)",
"slug": "luminous-vivid-amber-to-luminous-vivid-orange",
"origin": "core"
"slug": "luminous-vivid-amber-to-luminous-vivid-orange"
},
{
"name": "Luminous vivid orange to vivid red",
"gradient": "linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%)",
"slug": "luminous-vivid-orange-to-vivid-red",
"origin": "core"
"slug": "luminous-vivid-orange-to-vivid-red"
},
{
"name": "Very light gray to cyan bluish gray",
"gradient": "linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%)",
"slug": "very-light-gray-to-cyan-bluish-gray",
"origin": "core"
"slug": "very-light-gray-to-cyan-bluish-gray"
},
{
"name": "Cool to warm spectrum",
"gradient": "linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%)",
"slug": "cool-to-warm-spectrum",
"origin": "core"
"slug": "cool-to-warm-spectrum"
},
{
"name": "Blush light purple",
"gradient": "linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%)",
"slug": "blush-light-purple",
"origin": "core"
"slug": "blush-light-purple"
},
{
"name": "Blush bordeaux",
"gradient": "linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%)",
"slug": "blush-bordeaux",
"origin": "core"
"slug": "blush-bordeaux"
},
{
"name": "Luminous dusk",
"gradient": "linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%)",
"slug": "luminous-dusk",
"origin": "core"
"slug": "luminous-dusk"
},
{
"name": "Pale ocean",
"gradient": "linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%)",
"slug": "pale-ocean",
"origin": "core"
"slug": "pale-ocean"
},
{
"name": "Electric grass",
"gradient": "linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%)",
"slug": "electric-grass",
"origin": "core"
"slug": "electric-grass"
},
{
"name": "Midnight",
"gradient": "linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%)",
"slug": "midnight",
"origin": "core"
"slug": "midnight"
}
],
"duotone": [
Expand Down
Loading