From 55e92f5f0773dd00c3cf9584f657310e303b5052 Mon Sep 17 00:00:00 2001
From: Andrew Serong <14988353+andrewserong@users.noreply.github.com>
Date: Tue, 22 Feb 2022 16:53:04 +1100
Subject: [PATCH 1/2] Style Engine: Try simple approach for consolidating
styles into a single style tag
---
lib/block-supports/layout.php | 2 +-
lib/class-wp-style-engine.php | 69 +++++++++++++++++++++++++++++++++++
lib/load.php | 5 +++
3 files changed, 75 insertions(+), 1 deletion(-)
create mode 100644 lib/class-wp-style-engine.php
diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index 05c1a7883057a..3afd6cd6b877a 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -166,7 +166,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
1
);
- gutenberg_enqueue_block_support_styles( $style );
+ WP_Style_Engine_Gutenberg::get_instance()->add_style( $class_name, $style );
return $content;
}
diff --git a/lib/class-wp-style-engine.php b/lib/class-wp-style-engine.php
new file mode 100644
index 0000000000000..7eac59ead4163
--- /dev/null
+++ b/lib/class-wp-style-engine.php
@@ -0,0 +1,69 @@
+registered_styles[ $key ] = $value;
+ }
+
+ public function output_styles() {
+ $style = implode( "\n", $this->registered_styles );
+ echo "\n";
+ }
+}
diff --git a/lib/load.php b/lib/load.php
index 443942c98ee80..1d4e82ca01c48 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -112,6 +112,11 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/global-styles.php';
require __DIR__ . '/pwa.php';
+// TODO: Before this PR merges, move this to be a part of the style engine package.
+// Part of the build process should be to copy the PHP file to the correct location,
+// similar to the loading behaviour in `blocks.php`.
+require __DIR__ . '/class-wp-style-engine.php';
+
require __DIR__ . '/block-supports/elements.php';
require __DIR__ . '/block-supports/colors.php';
require __DIR__ . '/block-supports/typography.php';
From 2ba2f4d8f97fff0c059f3a63fdf1a6849eb8f0a7 Mon Sep 17 00:00:00 2001
From: ramonjd
Date: Fri, 25 Feb 2022 16:12:11 +1100
Subject: [PATCH 2/2] Deduping Using array as style registry model
---
lib/block-supports/layout.php | 109 +++++++++++++++++++++++-----------
lib/class-wp-style-engine.php | 53 +++++++++++++++--
2 files changed, 121 insertions(+), 41 deletions(-)
diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index 3afd6cd6b877a..9dc8c278c56ee 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -28,17 +28,17 @@ function gutenberg_register_layout_support( $block_type ) {
/**
* Generates the CSS corresponding to the provided layout.
*
- * @param string $selector CSS selector.
- * @param array $layout Layout object. The one that is passed has already checked the existence of default block layout.
+ * @param string $selector CSS selector.
+ * @param array $layout Layout object. The one that is passed has already checked the existence of default block layout.
* @param boolean $has_block_gap_support Whether the theme has support for the block gap.
- * @param string $gap_value The block gap value to apply.
+ * @param array $gap_value The block gap value to apply.
*
- * @return string CSS style.
+ * @return string CSS style.
*/
function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support = false, $gap_value = null ) {
$layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
- $style = '';
+ $styles = array();
if ( 'default' === $layout_type ) {
$content_size = isset( $layout['contentSize'] ) ? $layout['contentSize'] : '';
$wide_size = isset( $layout['wideSize'] ) ? $layout['wideSize'] : '';
@@ -51,24 +51,44 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
$all_max_width_value = wp_strip_all_tags( explode( ';', $all_max_width_value )[0] );
$wide_max_width_value = wp_strip_all_tags( explode( ';', $wide_max_width_value )[0] );
- $style = '';
if ( $content_size || $wide_size ) {
- $style = "$selector > :where(:not(.alignleft):not(.alignright)) {";
- $style .= 'max-width: ' . esc_html( $all_max_width_value ) . ';';
- $style .= 'margin-left: auto !important;';
- $style .= 'margin-right: auto !important;';
- $style .= '}';
-
- $style .= "$selector > .alignwide { max-width: " . esc_html( $wide_max_width_value ) . ';}';
- $style .= "$selector .alignfull { max-width: none; }";
+ $styles[ "$selector > :where(:not(.alignleft):not(.alignright))" ] = array(
+ 'max-width' => esc_html( $all_max_width_value ),
+ 'margin-left' => 'auto !important',
+ 'margin-right' => 'auto !important',
+ );
+
+ $styles[ "$selector > .alignwide" ] = array(
+ 'max-width' => esc_html( $wide_max_width_value ),
+ );
+
+ $styles[ "$selector > .alignfull" ] = array(
+ 'max-width' => 'none',
+ );
}
- $style .= "$selector .alignleft { float: left; margin-right: 2em; margin-left: 0; }";
- $style .= "$selector .alignright { float: right; margin-left: 2em; margin-right: 0; }";
+ $styles[ "$selector .alignleft" ] = array(
+ 'float' => 'left',
+ 'margin-right' => '2em',
+ 'margin-left' => '0',
+ );
+
+ $styles[ "$selector .alignright" ] = array(
+ 'float' => 'right',
+ 'margin-right' => '0',
+ 'margin-left' => '2em',
+ );
+
if ( $has_block_gap_support ) {
- $gap_style = $gap_value ? $gap_value : 'var( --wp--style--block-gap )';
- $style .= "$selector > * { margin-top: 0; margin-bottom: 0; }";
- $style .= "$selector > * + * { margin-top: $gap_style; margin-bottom: 0; }";
+ $gap_style = $gap_value ? $gap_value : 'var( --wp--style--block-gap )';
+ $styles[ "$selector > *" ] = array(
+ 'margin-top' => '0',
+ 'margin-bottom' => '0',
+ );
+ $styles[ "$selector > * + *" ] = array(
+ 'margin-top' => $gap_style,
+ 'margin-bottom' => '0',
+ );
}
} elseif ( 'flex' === $layout_type ) {
$layout_orientation = isset( $layout['orientation'] ) ? $layout['orientation'] : 'horizontal';
@@ -88,39 +108,57 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
$layout['flexWrap'] :
'wrap';
- $style = "$selector {";
- $style .= 'display: flex;';
+ $styles[ "$selector" ] = array(
+ 'display' => 'flex',
+ 'flex-wrap' => $flex_wrap,
+ );
+
if ( $has_block_gap_support ) {
- $gap_style = $gap_value ? $gap_value : 'var( --wp--style--block-gap, 0.5em )';
- $style .= "gap: $gap_style;";
+ $gap_style = $gap_value ? $gap_value : 'var( --wp--style--block-gap, 0.5em )';
+ $styles[ "$selector" ] = array(
+ 'gap' => $gap_style,
+ );
} else {
- $style .= 'gap: 0.5em;';
+ $styles[ "$selector" ] = array(
+ 'gap' => '0.5em',
+ );
}
- $style .= "flex-wrap: $flex_wrap;";
+
if ( 'horizontal' === $layout_orientation ) {
- $style .= 'align-items: center;';
+ $styles[ "$selector" ] = array(
+ 'align-items' => 'center',
+ );
/**
* Add this style only if is not empty for backwards compatibility,
* since we intend to convert blocks that had flex layout implemented
* by custom css.
*/
if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
- $style .= "justify-content: {$justify_content_options[ $layout['justifyContent'] ]};";
+ $styles[ "$selector" ] = array(
+ 'justify-content' => $justify_content_options[ $layout['justifyContent'] ],
+ );
}
} else {
- $style .= 'flex-direction: column;';
+ $styles[ "$selector" ] = array(
+ 'flex-direction' => 'column',
+ );
if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
- $style .= "align-items: {$justify_content_options[ $layout['justifyContent'] ]};";
+ $styles[ "$selector" ] = array(
+ 'align-items' => $justify_content_options[ $layout['justifyContent'] ],
+ );
} else {
- $style .= 'align-items: flex-start;';
+ $styles[ "$selector" ] = array(
+ 'align-items' => 'flex-start',
+ );
}
}
- $style .= '}';
- $style .= "$selector > * { margin: 0; }";
+ $styles[ "$selector > *" ] = array(
+ 'margin' => '0',
+ );
}
- return $style;
+ return $styles;
}
/**
@@ -156,7 +194,8 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
// Regex for CSS value borrowed from `safecss_filter_attr`, and used here
// because we only want to match against the value, not the CSS attribute.
$gap_value = preg_match( '%[\\\(&=}]|/\*%', $gap_value ) ? null : $gap_value;
- $style = gutenberg_get_layout_style( ".$class_name", $used_layout, $has_block_gap_support, $gap_value );
+ $styles = gutenberg_get_layout_style( ".$class_name", $used_layout, $has_block_gap_support, $gap_value );
+ WP_Style_Engine_Gutenberg::get_instance()->add_styles( $styles );
// This assumes the hook only applies to blocks with a single wrapper.
// I think this is a reasonable limitation for that particular hook.
$content = preg_replace(
@@ -166,8 +205,6 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
1
);
- WP_Style_Engine_Gutenberg::get_instance()->add_style( $class_name, $style );
-
return $content;
}
diff --git a/lib/class-wp-style-engine.php b/lib/class-wp-style-engine.php
index 7eac59ead4163..e47858c4a88c8 100644
--- a/lib/class-wp-style-engine.php
+++ b/lib/class-wp-style-engine.php
@@ -3,7 +3,6 @@
* WP_Style_Engine class
*
* @package Gutenberg
-
*/
/**
@@ -58,12 +57,56 @@ public static function get_instance() {
return self::$instance;
}
- public function add_style( $key, $value ) {
- $this->registered_styles[ $key ] = $value;
+ public function add_styles( $styles ) {
+ if ( ! is_array( $styles ) ) {
+ return array();
+ }
+
+ foreach ( $styles as $key => $value ) {
+ $value = is_array( $value ) ? $value : array();
+ if ( isset( $this->registered_styles[ $key ] ) ) {
+ $this->registered_styles[ $key ] = array_merge( $this->registered_styles[ $key ], $value );
+ } else {
+ $this->registered_styles[ $key ] = $value;
+ }
+ }
+ }
+
+ protected function deduplicate_styles() {
+ $result = array();
+ $unique_styles = array();
+ array_walk(
+ $this->registered_styles,
+ function( $value, $key ) use ( &$result, &$unique_styles ) {
+ $stringified_value = json_encode( $value );
+ if ( array_key_exists( $stringified_value, $unique_styles ) ) {
+ $new_key = $unique_styles[ $stringified_value ] . ",\n" . $key;
+ unset( $result[ $unique_styles[ $stringified_value ] ] );
+ $unique_styles[ $stringified_value ] = $new_key;
+ $result[ $new_key ] = $value;
+ } else {
+ $unique_styles[ $stringified_value ] = $key;
+ $result[ $key ] = $value;
+ }
+ }
+ );
+ return $result;
}
public function output_styles() {
- $style = implode( "\n", $this->registered_styles );
- echo "\n";
+ $deduped_styles = $this->deduplicate_styles();
+ $callback = function( $css_selector, $css_ruleset ) {
+ $style = "{$css_selector} {\n";
+ foreach ( $css_ruleset as $css_property => $css_value ) {
+ $style .= " {$css_property}: {$css_value};\n";
+ }
+ $style .= "}\n";
+ return $style;
+ };
+
+ $output = array_map( $callback, array_keys( $deduped_styles ), array_values( $deduped_styles ) );
+ $output = implode( "\n", $output );
+
+ echo "\n";
}
}