diff --git a/packages/style-engine/README.md b/packages/style-engine/README.md index b414a4bc5370f..4a2990c6b5f66 100644 --- a/packages/style-engine/README.md +++ b/packages/style-engine/README.md @@ -16,17 +16,49 @@ _This package assumes that your code will run in an **ES2015+** environment. If This Package is considered experimental at the moment. The idea is to have a package used to generate styles based on a style object that is consistent between: backend, frontend, block style object and theme.json. -Currently it's not a package that generates a wp.styleEngine global because it's not ready yet, it's still a bundled package but ultimately, we want it to be so, once the roadmap is finished: +Because this package is experimental and still in development it does not yet generate a `wp.styleEngine` global. To get there, the following tasks need to be completed: **TODO List:** - Add style definitions for all the currently supported styles in blocks and theme.json. -- the CSS variable shortcuts for values (for presets...) +- The CSS variable shortcuts for values (for presets...) - Support generating styles in the frontend. (Ongoing) - Support generating styles in the backend (block supports and theme.json stylesheet). (Ongoing) - Refactor all block styles to use the style engine server side. (Ongoing) +- Consolidate global and block style rendering and enqueuing - Refactor all blocks to consistently use the "style" attribute for all customizations (get rid of the preset specific attributes). +See [Tracking: Add a Style Engine to manage rendering block styles #38167](https://github.com/WordPress/gutenberg/issues/38167) + +## Glossary + +A guide to the terms and variable names referenced by the Style Engine package. + +
+
Block style (Gutenberg internal)
+
An object comprising a block's style attribute that contains a block's style values. E.g., { spacing: { margin: '10px' }, color: { ... }, ... }
+
Global styles (Gutenberg internal)
+
A merged block styles object containing values from a theme's theme.json and user styles settings.
+
CSS declaration or (CSS property declaration)
+
A CSS property paired with a CSS value. E.g., color: pink
+
CSS declarations block
+
A set of CSS declarations usually paired with a CSS selector to create a CSS rule.
+
CSS property
+
Identifiers that describe stylistic, modifiable features of an HTML element. E.g., border, font-size, width...
+
CSS rule
+
A CSS selector followed by a CSS declarations block inside a set of curly braces. Usually found in a CSS stylesheet.
+
CSS selector
+
The first component of a CSS rule, a CSS selector is a pattern of elements, classnames or other terms that define the element to which the rule’s CSS definitions apply. E.g., p.my-cool-classname > span. See MDN CSS selectors article.
+
CSS stylesheet
+
A collection of CSS rules contained within a file or within an HTML style tag.
+
CSS value
+
The value of a CSS property. The value determines how the property is modified. E.g., the 10vw in height: 10vw.
+
CSS variables (vars) or CSS custom properties
+
Properties, whose values can be reused in other CSS declarations. Set using custom property notation (e.g., --wp--preset--olive: #808000;) and accessed using the var() function (e.g., color: var( --wp--preset--olive );). See MDN article on CSS custom properties.
+
Inline styles
+
Inline styles are CSS declarations that affect a single HTML element, contained within a style attribute
+
+ ## Usage diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php index a196124104721..c4cdd0c19419c 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -41,7 +41,7 @@ class WP_Style_Engine { * The value should be a valid CSS property (string) to match the incoming value, e.g., "color" to match var:preset|color|somePresetSlug. * - property_keys => (array) array of keys whose values represent a valid CSS property, e.g., "margin" or "border". * - path => (array) a path that accesses the corresponding style value in the block style object. - * - value_func => (string) the name of a function to generate an array of valid CSS rules for a particular style object. + * - value_func => (string) the name of a function to generate a CSS definition array for a particular style object. The output of this function should be `array( "$property" => "$value", ... )`. */ const BLOCK_STYLE_DEFINITIONS_METADATA = array( 'color' => array( @@ -113,28 +113,28 @@ class WP_Style_Engine { 'path' => array( 'border', 'width' ), ), 'top' => array( - 'value_func' => 'static::get_css_individual_property_rules', + 'value_func' => 'static::get_individual_property_css_declarations', 'path' => array( 'border', 'top' ), 'css_vars' => array( 'color' => '--wp--preset--color--$slug', ), ), 'right' => array( - 'value_func' => 'static::get_css_individual_property_rules', + 'value_func' => 'static::get_individual_property_css_declarations', 'path' => array( 'border', 'right' ), 'css_vars' => array( 'color' => '--wp--preset--color--$slug', ), ), 'bottom' => array( - 'value_func' => 'static::get_css_individual_property_rules', + 'value_func' => 'static::get_individual_property_css_declarations', 'path' => array( 'border', 'bottom' ), 'css_vars' => array( 'color' => '--wp--preset--color--$slug', ), ), 'left' => array( - 'value_func' => 'static::get_css_individual_property_rules', + 'value_func' => 'static::get_individual_property_css_declarations', 'path' => array( 'border', 'left' ), 'css_vars' => array( 'color' => '--wp--preset--color--$slug', @@ -247,7 +247,7 @@ protected static function get_slug_from_preset_value( $style_value, $property_ke } /** - * Checks whether an incoming style value is valid. + * Checks whether an incoming block style value is valid. * * @param string? $style_value A single css preset value. * @@ -302,17 +302,15 @@ protected static function get_classnames( $style_value, $style_definition ) { } /** - * Returns CSS rules based on valid block style values. + * Returns an array of CSS declarations based on valid block style values. * * @param array $style_value A single raw style value from the generate() $block_styles array. * @param array $style_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA. * @param boolean $should_return_css_vars Whether to try to build and return CSS var values. * - * @return array An array of CSS rules. + * @return array An array of CSS definitions, e.g., array( "$property" => "$value" ). */ - protected static function get_css( $style_value, $style_definition, $should_return_css_vars ) { - $rules = array(); - + protected static function get_css_declarations( $style_value, $style_definition, $should_return_css_vars ) { if ( isset( $style_definition['value_func'] ) && is_callable( $style_definition['value_func'] ) @@ -320,7 +318,8 @@ protected static function get_css( $style_value, $style_definition, $should_retu return call_user_func( $style_definition['value_func'], $style_value, $style_definition ); } - $style_properties = $style_definition['property_keys']; + $css_declarations = array(); + $style_property_keys = $style_definition['property_keys']; // Build CSS var values from var:? values, e.g, `var(--wp--css--rule-slug )` // Check if the value is a CSS preset and there's a corresponding css_var pattern in the style definition. @@ -329,15 +328,15 @@ protected static function get_css( $style_value, $style_definition, $should_retu foreach ( $style_definition['css_vars'] as $css_var_pattern => $property_key ) { $slug = static::get_slug_from_preset_value( $style_value, $property_key ); if ( $slug ) { - $css_var = strtr( + $css_var = strtr( $css_var_pattern, array( '$slug' => $slug ) ); - $rules[ $style_properties['default'] ] = "var($css_var)"; + $css_declarations[ $style_property_keys['default'] ] = "var($css_var)"; } } } - return $rules; + return $css_declarations; } // Default rule builder. @@ -345,19 +344,19 @@ protected static function get_css( $style_value, $style_definition, $should_retu // for styles such as margins and padding. if ( is_array( $style_value ) ) { foreach ( $style_value as $key => $value ) { - $individual_property = sprintf( $style_properties['individual'], _wp_to_kebab_case( $key ) ); - $rules[ $individual_property ] = $value; + $individual_property = sprintf( $style_property_keys['individual'], _wp_to_kebab_case( $key ) ); + $css_declarations[ $individual_property ] = $value; } } else { - $rules[ $style_properties['default'] ] = $style_value; + $css_declarations[ $style_property_keys['default'] ] = $style_value; } - return $rules; + return $css_declarations; } /** - * Returns an CSS ruleset. - * Styles are bundled based on the instructions in BLOCK_STYLE_DEFINITIONS_METADATA. + * Returns classname and CSS from a block styles object. + * Return values are parsed based on the instructions in BLOCK_STYLE_DEFINITIONS_METADATA. * * @param array $block_styles An array of styles from a block's attributes. * @param array $options array( @@ -375,7 +374,7 @@ public function generate( $block_styles, $options ) { return null; } - $css_rules = array(); + $css_declarations = array(); $classnames = array(); $should_return_css_vars = isset( $options['css_vars'] ) && true === $options['css_vars']; @@ -391,36 +390,38 @@ public function generate( $block_styles, $options ) { continue; } - $classnames = array_merge( $classnames, static::get_classnames( $style_value, $style_definition ) ); - $css_rules = array_merge( $css_rules, static::get_css( $style_value, $style_definition, $should_return_css_vars ) ); + $classnames = array_merge( $classnames, static::get_classnames( $style_value, $style_definition ) ); + $css_declarations = array_merge( $css_declarations, static::get_css_declarations( $style_value, $style_definition, $should_return_css_vars ) ); } } // Build CSS rules output. - $selector = isset( $options['selector'] ) ? $options['selector'] : null; - $css = array(); - $styles_output = array(); - - if ( ! empty( $css_rules ) ) { - // Generate inline style rules. - foreach ( $css_rules as $rule => $value ) { - $filtered_css = esc_html( safecss_filter_attr( "{$rule}: {$value}" ) ); - if ( ! empty( $filtered_css ) ) { - $css[] = $filtered_css . ';'; + $css_selector = isset( $options['selector'] ) ? $options['selector'] : null; + $filtered_css_declarations = array(); + + if ( ! empty( $css_declarations ) ) { + // Generate inline style declarations. + foreach ( $css_declarations as $css_property => $css_value ) { + $filtered_css_declaration = esc_html( safecss_filter_attr( "{$css_property}: {$css_value}" ) ); + if ( ! empty( $filtered_css_declaration ) ) { + $filtered_css_declarations[] = $filtered_css_declaration . ';'; } } } + // The return object. + $styles_output = array(); + // Return css, if any. - if ( ! empty( $css ) ) { + if ( ! empty( $filtered_css_declarations ) ) { // Return an entire rule if there is a selector. - if ( $selector ) { - $style_block = "$selector { "; - $style_block .= implode( ' ', $css ); - $style_block .= ' }'; - $styles_output['css'] = $style_block; + if ( $css_selector ) { + $css_rule = "$css_selector { "; + $css_rule .= implode( ' ', $filtered_css_declarations ); + $css_rule .= ' }'; + $styles_output['css'] = $css_rule; } else { - $styles_output['css'] = implode( ' ', $css ); + $styles_output['css'] = implode( ' ', $filtered_css_declarations ); } } @@ -434,7 +435,7 @@ public function generate( $block_styles, $options ) { /** - * Style value parser that returns a CSS ruleset of style properties for style definition groups + * Style value parser that returns a CSS definition array comprising style properties * that have keys representing individual style properties, otherwise known as longhand CSS properties. * e.g., "$style_property-$individual_feature: $value;", which could represent the following: * "border-{top|right|bottom|left}-{color|width|style}: {value};" or, @@ -443,13 +444,13 @@ public function generate( $block_styles, $options ) { * @param array $style_value A single raw Gutenberg style attributes value for a CSS property. * @param array $individual_property_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA. * - * @return array The class name for the added style. + * @return array An array of CSS definitions, e.g., array( "$property" => "$value" ). */ - protected static function get_css_individual_property_rules( $style_value, $individual_property_definition ) { - $rules = array(); + protected static function get_individual_property_css_declarations( $style_value, $individual_property_definition ) { + $css_declarations = array(); if ( ! is_array( $style_value ) || empty( $style_value ) || empty( $individual_property_definition['path'] ) ) { - return $rules; + return $css_declarations; } // The first item in $individual_property_definition['path'] array tells us the style property, e.g., "border". @@ -477,11 +478,11 @@ protected static function get_css_individual_property_rules( $style_value, $indi ); $value = "var($css_var)"; } - $individual_css_property = sprintf( $style_definition['property_keys']['individual'], $individual_property_key ); - $rules[ $individual_css_property ] = $value; + $individual_css_property = sprintf( $style_definition['property_keys']['individual'], $individual_property_key ); + $css_declarations[ $individual_css_property ] = $value; } } - return $rules; + return $css_declarations; } }