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

Style engine: remove enqueue flag #43103

Merged
merged 2 commits into from
Aug 12, 2022
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
1 change: 0 additions & 1 deletion lib/block-supports/elements.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) {
array(
'selector' => ".$class_name a",
'context' => 'block-supports',
'enqueue' => true,
)
);

Expand Down
1 change: 0 additions & 1 deletion lib/block-supports/layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
$layout_styles,
array(
'context' => 'block-supports',
'enqueue' => true,
)
);
}
Expand Down
122 changes: 64 additions & 58 deletions packages/style-engine/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

The Style Engine powering global styles and block customizations.

## Important

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.

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...)
- 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)

## Backend API

### wp_style_engine_get_styles()
Expand All @@ -17,8 +38,7 @@ _Parameters_
- _$block_styles_ `array` A block's `attributes.style` object or the top level styles in theme.json
- _$options_ `array<string|boolean>` An array of options to determine the output.
- _context_ `string` An identifier describing the origin of the style object, e.g., 'block-supports' or '
global-styles'. Default is 'block-supports'.
- _enqueue_ `boolean` When `true` will attempt to store and enqueue for rendering in a `style` tag on the site frontend.
global-styles'. Default is 'block-supports'. When both `context` and `selector` are set, the style engine will store the CSS rules using the `context` as a key.
- _convert_vars_to_classnames_ `boolean` Whether to skip converting CSS var:? values to var( --wp--preset--\* )
values. Default is `false`.
- _selector_ `string` When a selector is passed, `generate()` will return a full CSS rule `$selector { ...rules }`,
Expand All @@ -41,8 +61,7 @@ To enqueue a style for rendering in the site's frontend, the `$options` array re

1. **selector (string)** - this is the CSS selector for your block style CSS declarations.
2. **context (string)** - this tells the style engine where to store the styles. Styles in the same context will be
batched together and printed in the same HTML style tag. The default is `'block-supports'`.
3. **enqueue (boolean)** - tells the style engine to store the styles.
stored together.

`wp_style_engine_get_styles` will return the compiled CSS and CSS declarations array.

Expand All @@ -57,7 +76,6 @@ $styles = wp_style_engine_get_styles(
array(
'selector' => '.a-selector',
'context' => 'block-supports',
'enqueue' => true,
)
);
print_r( $styles );
Expand All @@ -81,8 +99,7 @@ _Parameters_
- _$css_rules_ `array<array>`
- _$options_ `array<string|boolean>` An array of options to determine the output.
- _context_ `string` An identifier describing the origin of the style object, e.g., 'block-supports' or '
global-styles'. Default is 'block-supports'.
- _enqueue_ `boolean` When `true` will store using the `context` value as a key.
global-styles'. When set, the style engine will store the CSS rules using the `context` value as a key.

_Returns_
`string` A compiled CSS string based on `$css_rules`.
Expand Down Expand Up @@ -113,7 +130,6 @@ $stylesheet = wp_style_engine_get_stylesheet_from_css_rules(
$styles,
array(
'context' => 'block-supports', // Indicates that these styles should be stored with block supports CSS.
'enqueue' => true, // Render the styles for output.
)
);
print_r( $stylesheet ); // .wp-pumpkin, .wp-kumquat {color:orange}.wp-tomato{color:red;padding:100px}
Expand All @@ -125,13 +141,15 @@ Returns compiled CSS from a store, if found.

_Parameters_

- _$store_key_ `string` An identifier describing the origin of the style object, e.g., 'block-supports' or ' global-styles'. Default is 'block-supports'.
- _$store_name_ `string` An identifier describing the origin of the style object, e.g., 'block-supports' or ' global-styles'. Default is 'block-supports'.

_Returns_
`string` A compiled CSS string from the stored CSS rules.

#### Usage

A use case would be to fetch the stylesheet, which contains all the compiled CSS rules from the store, and enqueue it for rendering on the frontend.

```php
// First register some styles.
$styles = array(
Expand All @@ -152,6 +170,11 @@ $stylesheet = wp_style_engine_get_stylesheet_from_css_rules(
// Later, fetch compiled rules from store.
$stylesheet = gutenberg_style_engine_get_stylesheet_from_store( 'fruit-styles' );
print_r( $stylesheet ); // .wp-apple{color:green;}
if ( ! empty( $stylesheet ) ) {
wp_register_style( 'my-stylesheet', false, array(), true, true );
wp_add_inline_style( 'my-stylesheet', $stylesheet );
wp_enqueue_style( 'my-stylesheet' );
}
```

## Installation (JS only)
Expand All @@ -167,26 +190,37 @@ limited or no support for such language features and APIs, you should
include [the polyfill shipped in `@wordpress/babel-preset-default`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/babel-preset-default#polyfill)
in your code._

## Important
## Usage

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.
<!-- START TOKEN(Autogenerated API docs) -->

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:
### generate

**TODO List:**
Generates a stylesheet for a given style object and selector.

- Add style definitions for all the currently supported styles in blocks and theme.json.
- 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).
_Parameters_

See [Tracking: Add a Style Engine to manage rendering block styles #38167](https://github.com/WordPress/gutenberg/issues/38167)
- _style_ `Style`: Style object.
- _options_ `StyleOptions`: Options object with settings to adjust how the styles are generated.

_Returns_

- `string`: generated stylesheet.

### getCSSRules

Returns a JSON representation of the generated CSS rules.

_Parameters_

- _style_ `Style`: Style object.
- _options_ `StyleOptions`: Options object with settings to adjust how the styles are generated.

_Returns_

- `GeneratedCSSRule[]`: generated styles.

<!-- END TOKEN(Autogenerated API docs) -->

## Glossary

Expand All @@ -195,8 +229,6 @@ A guide to the terms and variable names referenced by the Style Engine package.
<dl>
<dt>Block style (Gutenberg internal)</dt>
<dd>An object comprising a block's style attribute that contains a block's style values. E.g., <code>{ spacing: { margin: '10px' }, color: { ... }, ... }</code></dd>
<dt>Global styles (Gutenberg internal)</dt>
<dd>A merged block styles object containing values from a theme's theme.json and user styles settings.</dd>
<dt>CSS declaration or (CSS property declaration)</dt>
<dd>A CSS property paired with a CSS value. E.g., <code>color: pink</code> </dd>
<dt>CSS declarations block</dt>
Expand All @@ -213,40 +245,14 @@ A guide to the terms and variable names referenced by the Style Engine package.
<dd>The value of a CSS property. The value determines how the property is modified. E.g., the <code>10vw</code> in <code>height: 10vw</code>.</dd>
<dt>CSS variables (vars) or CSS custom properties</dt>
<dd>Properties, whose values can be reused in other CSS declarations. Set using custom property notation (e.g., <code>--wp--preset--olive: #808000;</code>) and accessed using the <code>var()</code> function (e.g., <code>color: var( --wp--preset--olive );</code>). See <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties" target="_blank">MDN article on CSS custom properties</a>.</dd>
<dt>Global styles (Gutenberg internal)</dt>
<dd>A merged block styles object containing values from a theme's theme.json and user styles settings.</dd>
<dt>Inline styles</dt>
<dd>Inline styles are CSS declarations that affect a single HTML element, contained within a style attribute</dd>
<dt>Processor</dt>
<dd>Performs compilation and optimization on stored CSS rules. See the class `WP_Style_Engine_Processor`.</dd>
<dt>Store</dt>
<dd>A data object that contains related styles. See the class `WP_Style_Engine_CSS_Rules_Store`.</dd>
</dl>

## Usage

<!-- START TOKEN(Autogenerated API docs) -->

### generate

Generates a stylesheet for a given style object and selector.

_Parameters_

- _style_ `Style`: Style object.
- _options_ `StyleOptions`: Options object with settings to adjust how the styles are generated.

_Returns_

- `string`: generated stylesheet.

### getCSSRules

Returns a JSON representation of the generated CSS rules.

_Parameters_

- _style_ `Style`: Style object.
- _options_ `StyleOptions`: Options object with settings to adjust how the styles are generated.

_Returns_

- `GeneratedCSSRule[]`: generated styles.

<!-- END TOKEN(Autogenerated API docs) -->

<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,12 @@ class WP_Style_Engine_CSS_Rules_Store {
*
* @param string $store_name The name of the store.
*
* @return WP_Style_Engine_CSS_Rules_Store
* @return WP_Style_Engine_CSS_Rules_Store|void
*/
public static function get_store( $store_name = 'default' ) {
if ( ! is_string( $store_name ) || empty( $store_name ) ) {
return;
}
if ( ! isset( static::$stores[ $store_name ] ) ) {
static::$stores[ $store_name ] = new static();
// Set the store name.
Expand Down Expand Up @@ -111,7 +114,7 @@ public function get_all_rules() {
*
* @param string $selector The CSS selector.
*
* @return WP_Style_Engine_CSS_Rule|null Returns a WP_Style_Engine_CSS_Rule object, or null if the selector is empty.
* @return WP_Style_Engine_CSS_Rule|void Returns a WP_Style_Engine_CSS_Rule object, or null if the selector is empty.
*/
public function add_rule( $selector ) {

Expand Down
51 changes: 22 additions & 29 deletions packages/style-engine/class-wp-style-engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* CSS styles generation.
*
* This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes).
* This is a low-level API that may need to do breaking changes. Please, use gutenberg_style_engine_get_styles instead.
* This is a low-level API that may need to do breaking changes. Please, use wp_style_engine_get_styles instead.
*
* @access private
*/
Expand Down Expand Up @@ -272,30 +272,30 @@ protected static function is_valid_style_value( $style_value ) {
}

/**
* Stores a CSS rule using the provide CSS selector and CSS declarations.
* Stores a CSS rule using the provided CSS selector and CSS declarations.
*
* @param string $store_key A valid store key.
* @param string $store_name A valid store key.
* @param string $css_selector When a selector is passed, the function will return a full CSS rule `$selector { ...rules }`, otherwise a concatenated string of properties and values.
* @param array $css_declarations An array of parsed CSS property => CSS value pairs.
*
* @return void.
*/
public static function store_css_rule( $store_key, $css_selector, $css_declarations ) {
if ( empty( $store_key ) || empty( $css_selector ) || empty( $css_declarations ) ) {
public static function store_css_rule( $store_name, $css_selector, $css_declarations ) {
if ( empty( $store_name ) || empty( $css_selector ) || empty( $css_declarations ) ) {
return;
}
static::get_store( $store_key )->add_rule( $css_selector )->add_declarations( $css_declarations );
static::get_store( $store_name )->add_rule( $css_selector )->add_declarations( $css_declarations );
}

/**
* Returns a store by store key.
*
* @param string $store_key A store key.
* @param string $store_name A store key.
*
* @return WP_Style_Engine_CSS_Rules_Store
*/
public static function get_store( $store_key ) {
return WP_Style_Engine_CSS_Rules_Store::get_store( $store_key );
public static function get_store( $store_name ) {
return WP_Style_Engine_CSS_Rules_Store::get_store( $store_name );
}

/**
Expand Down Expand Up @@ -531,8 +531,8 @@ public static function compile_stylesheet_from_css_rules( $css_rules ) {
*
* @param array $block_styles The style object.
* @param array<string|boolean> $options array(
* 'context' => (string) An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is 'block-supports'.
* 'enqueue' => (boolean) When `true` will attempt to store and enqueue for rendering on the frontend.
* 'context' => (string|null) An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is 'block-supports'.
* When set, the style engine will attempt to store the CSS rules, where a selector is also passed.
* 'convert_vars_to_classnames' => (boolean) Whether to skip converting CSS var:? values to var( --wp--preset--* ) values. Default is `false`.
* 'selector' => (string) When a selector is passed, `generate()` will return a full CSS rule `$selector { ...rules }`, otherwise a concatenated string of properties and values.
* );.
Expand All @@ -549,18 +549,12 @@ function wp_style_engine_get_styles( $block_styles, $options = array() ) {
}
$defaults = array(
'selector' => null,
'context' => 'block-supports',
'context' => null,
'convert_vars_to_classnames' => false,
'enqueue' => false,
);

$options = wp_parse_args( $options, $defaults );
$parsed_styles = null;

// Block supports styles.
if ( 'block-supports' === $options['context'] ) {
$parsed_styles = WP_Style_Engine::parse_block_styles( $block_styles, $options );
}
Comment on lines -560 to -563
Copy link
Contributor

Choose a reason for hiding this comment

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

Just making sure I'm following along — we no longer need the block-supports check, because this function effectively doesn't do anything if it isn't calling WP_Style_Engine::parse_block_styles?

Copy link
Member Author

@ramonjd ramonjd Aug 12, 2022

Choose a reason for hiding this comment

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

Good question! That answer is "yes, and..."

I reasoned that wp_style_engine_get_styles encounters only Gutenberg style objects, which are:

  1. The value of attributes.style (block supports)
  2. In the future
    i. the value of theme.json's root styles properties
    ii. the value of theme.json's styles.blocks[blockName] properties
    iii. the value of theme.json's styles.elements[elementName] properties

These object share the same basic model, although there are some variations in property names and values.

For example, global styles will eventually pass custom CSS properties such as --wp--style--block-gap or dynamic references like { "ref": "styles.color.text" }. These, I think can be dealt with internally when the time comes.

Maybe.

😇

Copy link
Contributor

Choose a reason for hiding this comment

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

All sounds good to me — and removing the check means it encourages us to think holistically about parse_block_styles for the global styles context in addition to the block-level, so I think this is a good direction, too 👍

$parsed_styles = WP_Style_Engine::parse_block_styles( $block_styles, $options );

// Output.
$styles_output = array();
Expand All @@ -572,7 +566,7 @@ function wp_style_engine_get_styles( $block_styles, $options = array() ) {
if ( ! empty( $parsed_styles['declarations'] ) ) {
$styles_output['css'] = WP_Style_Engine::compile_css( $parsed_styles['declarations'], $options['selector'] );
$styles_output['declarations'] = $parsed_styles['declarations'];
if ( true === $options['enqueue'] ) {
if ( ! empty( $options['context'] ) ) {
WP_Style_Engine::store_css_rule( $options['context'], $options['selector'], $parsed_styles['declarations'] );
}
}
Expand All @@ -597,8 +591,8 @@ function wp_style_engine_get_styles( $block_styles, $options = array() ) {
* )
* );.
* @param array<string> $options array(
* 'context' => (string) An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is 'block-supports'.
* 'enqueue' => (boolean) When `true` will attempt to store and enqueue for rendering on the frontend.
* 'context' => (string|null) An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is 'block-supports'.
* When set, the style engine will attempt to store the CSS rules.
* );.
*
* @return string A compiled CSS string.
Expand All @@ -609,8 +603,7 @@ function wp_style_engine_get_stylesheet_from_css_rules( $css_rules, $options = a
}

$defaults = array(
'context' => 'block-supports',
'enqueue' => false,
'context' => null,
);
$options = wp_parse_args( $options, $defaults );
$css_rule_objects = array();
Expand All @@ -620,7 +613,7 @@ function wp_style_engine_get_stylesheet_from_css_rules( $css_rules, $options = a
continue;
}

if ( true === $options['enqueue'] ) {
if ( ! empty( $options['context'] ) ) {
WP_Style_Engine::store_css_rule( $options['context'], $css_rule['selector'], $css_rule['declarations'] );
}

Expand All @@ -639,16 +632,16 @@ function wp_style_engine_get_stylesheet_from_css_rules( $css_rules, $options = a
*
* @access public
*
* @param string $store_key A valid store key.
* @param string $store_name A valid store name.
*
* @return string A compiled CSS string.
*/
function wp_style_engine_get_stylesheet_from_store( $store_key ) {
if ( ! class_exists( 'WP_Style_Engine' ) || empty( $store_key ) ) {
function wp_style_engine_get_stylesheet_from_store( $store_name ) {
if ( ! class_exists( 'WP_Style_Engine' ) || empty( $store_name ) ) {
return '';
}

$store = WP_Style_Engine::get_store( $store_key );
$store = WP_Style_Engine::get_store( $store_name );

return WP_Style_Engine::compile_stylesheet_from_css_rules( $store->get_all_rules() );
}
Loading