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

[WIP] Style engine: rule class #42061

Closed
wants to merge 1 commit into from
Closed
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
3 changes: 3 additions & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ function gutenberg_is_experiment_enabled( $name ) {
if ( file_exists( __DIR__ . '/../build/style-engine/class-wp-style-engine-gutenberg.php' ) ) {
require_once __DIR__ . '/../build/style-engine/class-wp-style-engine-gutenberg.php';
}
if ( file_exists( __DIR__ . '/../build/style-engine/class-wp-style-engine-rule-gutenberg.php' ) ) {
require_once __DIR__ . '/../build/style-engine/class-wp-style-engine-rule-gutenberg.php';
}

// Block supports overrides.
require __DIR__ . '/block-supports/utils.php';
Expand Down
177 changes: 177 additions & 0 deletions packages/style-engine/class-wp-style-engine-rule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<?php
/**
* WP_Style_Engine_Rule
*
* A
*
* @package Gutenberg
*/

if ( class_exists( 'WP_Style_Engine_Rule' ) ) {
return;
}

abstract class WP_Style_Engine_Rule_Abstraction {
/**
* The CSS rule set's selector.
*
* @var string|null
*/
private string $selector = '';

/**
* The CSS property definitions key value pairs.
*
* @var array
*/
private array $css_definitions = array();

/**
* Creates a string consisting of CSS property declarations suitable for the value of an HTML element's style attribute.
*/
abstract public function get_inline_css_declarations();

/**
* Creates a string consisting of a CSS rule.
*/
abstract public function get_css_rule();

/**
* Gets the CSS rule set's selector.
*
* @access public
*
* @return string A CSS selector, e.g., `.some-class-name`.
*/
public function get_selector() {
return $this->selector;
}

/**
* Gets the CSS property definitions key value pairs.
*
* @access public
*
* @return array A collection of CSS definitions `[ [ 'color' => 'red' ] ]`.
*/
public function get_css_definitions() {
return $this->css_definitions;
}
}

/**
* Singleton class representing the style engine.
*
* Consolidates rendering block styles to reduce duplication and streamline
* 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.
*
* @access private
*/
class WP_Style_Engine_Rule extends WP_Style_Engine_Rule_Abstraction {
/**
* The CSS rule set's selector.
*
* @var string
*/
private string $selector;

/**
* The CSS property definitions key value pairs.
*
* @var array
*/
private array $css_definitions;

/**
* Constructor.
*
* @param string $selector A CSS selector, e.g., `.some-class-name`.
* @param array $css_definitions An collection of CSS definitions `[ [ 'color' => 'red' ] ]`.
*/
public function __construct( $selector = '', $css_definitions = array() ) {
$this->selector = $selector;
$this->css_definitions = $css_definitions;
}

/**
* Filters incoming CSS properties against WordPress Core's allowed CSS attributes in wp-includes/kses.php.
*
* @param string $property_declaration A CSS property declaration, e.g., `color: 'pink'`.
*
* @return string A filtered CSS property. Empty if not allowed.
*/
public static function sanitize_property_declaration( $property_declaration ) {
return esc_html( safecss_filter_attr( $property_declaration ) );
}

/**
* Creates a string consisting of CSS property declarations suitable for the value of an HTML element's style attribute.
*
* @access public
*
* @return string A concatenated string of CSS properties, e.g. `'color: red; font-size:12px'`
*/
public function get_inline_css_declarations() {
$inline_css_declarations = array();

if ( empty( $this->css_definitions ) ) {
return '';
}
foreach ( $this->css_definitions as $css_property => $css_value ) {
$filtered_css_declaration = self::sanitize_property_declaration( "{$css_property}: {$css_value}" );
if ( ! empty( $filtered_css_declaration ) ) {
$inline_css_declarations[] = $filtered_css_declaration . ';';
}
}

if ( empty( $inline_css_declarations ) ) {
return '';
}

return implode( ' ', $inline_css_declarations );
}

/**
* Creates a string consisting of a CSS rule.
*
* @access public
*
* @param array $options array(
* 'prettify' => (boolean) Whether to add carriage returns and indenting.
* 'indent' => (number) The number of tab indents to apply to the rule. Applies if `prettify` is `true`.
* );.
*
* @return string A CSS rule, e.g. `'.some-selector { color: red; font-size:12px }'`
*/
public function get_css_rule( $options = array() ) {
$css_rule_block = '';

if ( ! $this->selector || empty( $this->css_definitions ) ) {
return $css_rule_block;
}

$defaults = array(
'prettify' => false,
'indent' => 0,
);
$options = wp_parse_args( $options, $defaults );
$indent = str_repeat( "\t", $options['indent'] );
$css_rule_block = $options['prettify'] ? "$indent{$this->selector} {\n" : "{$this->selector} { ";

foreach ( $this->css_definitions as $css_property => $css_value ) {
$filtered_css_declaration = self::sanitize_property_declaration( "{$css_property}: {$css_value}" );
if ( ! empty( $filtered_css_declaration ) ) {
if ( $options['prettify'] ) {
$css_rule_block .= "\t$indent$filtered_css_declaration;\n";
} else {
$css_rule_block .= $filtered_css_declaration . '; ';
}
}
}
$css_rule_block .= $options['prettify'] ? "$indent}\n" : '}';
return $css_rule_block;
}
}
40 changes: 15 additions & 25 deletions packages/style-engine/class-wp-style-engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -395,34 +395,24 @@ public function generate( $block_styles, $options ) {
}
}

// Build CSS rules output.
$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();
$css_output = null;

// Return css, if any.
if ( ! empty( $filtered_css_declarations ) ) {
// Return an entire rule if there is a selector.
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( ' ', $filtered_css_declarations );
}
// Build CSS rules output.
$css_selector = isset( $options['selector'] ) ? $options['selector'] : '';
$style_rule = new WP_Style_Engine_Rule( $css_selector, $css_declarations );

// Return an entire rule if there is a selector.
if ( $css_selector ) {
$css_output = $style_rule->get_css_rule();
} else {
$css_output = $style_rule->get_inline_css_declarations();
}

// Return CSS, if any.
if ( ! empty( $css_output ) ) {
$styles_output['css'] = $css_output;
}

// Return classnames, if any.
Expand Down
3 changes: 2 additions & 1 deletion packages/style-engine/phpunit/class-wp-style-engine-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

require __DIR__ . '/../class-wp-style-engine.php';
require __DIR__ . '/../class-wp-style-engine-rule.php';

/**
* Tests for registering, storing and generating styles.
Expand Down Expand Up @@ -139,7 +140,7 @@ public function data_generate_styles_fixtures() {
),
),

'style_block_with_selector' => array(
'style_block_with_selector_unprettified' => array(
'block_styles' => array(
'spacing' => array(
'padding' => array(
Expand Down