From 21d4ecf5fdbb3bf523a24224ac8bfe609805bc37 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/6] 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 59632f3e2bd169..0c94c87f7f414a 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -165,7 +165,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 00000000000000..7eac59ead41630
--- /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 b008f233700714..29a1116b42c8c8 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -120,6 +120,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 7301dee84ca8e1b4abd44ef91199e2b34e043ea1 Mon Sep 17 00:00:00 2001
From: Andrew Serong <14988353+andrewserong@users.noreply.github.com>
Date: Fri, 25 Feb 2022 15:59:39 +1100
Subject: [PATCH 2/6] Try generating unique class names and de-duping styles
for the layout support
---
lib/block-supports/layout.php | 250 ++++++++++++++++++++++++++++------
lib/class-wp-style-engine.php | 38 +++++-
2 files changed, 247 insertions(+), 41 deletions(-)
diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index 0c94c87f7f414a..eba2b621517658 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -28,17 +28,18 @@ 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 boolean $has_block_gap_support Whether the theme has support for the block gap.
* @param string $gap_value The block gap value to apply.
*
* @return string CSS style.
*/
-function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support = false, $gap_value = null ) {
+function gutenberg_get_layout_style( $layout, $has_block_gap_support = false, $gap_value = null ) {
$layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
- $style = '';
+ $style_engine = WP_Style_Engine_Gutenberg::get_instance();
+ $class_names = array();
+
if ( 'default' === $layout_type ) {
$content_size = isset( $layout['contentSize'] ) ? $layout['contentSize'] : '';
$wide_size = isset( $layout['wideSize'] ) ? $layout['wideSize'] : '';
@@ -51,23 +52,118 @@ 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] );
+ // Add universal styles for all default layouts.
+ // Add left align rule;
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default',
+ array(
+ 'selector' => '.alignleft',
+ 'rules' => array(
+ 'float' => 'left',
+ 'margin-right' => '2em',
+ 'margin-left' => '0',
+ ),
+ )
+ );
+
+ // Add right align rule:
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default',
+ array(
+ 'selector' => '.alignright',
+ 'rules' => array(
+ 'float' => 'right',
+ 'margin-left' => '2em',
+ 'margin-right' => '0',
+ ),
+ )
+ );
+
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; }";
+ // Add value specific content size.
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default-content-size',
+ array(
+ 'suffix' => $all_max_width_value,
+ 'selector' => '> :where(:not(.alignleft):not(.alignright))',
+ 'rules' => array(
+ 'max-width' => esc_html( $all_max_width_value ),
+ 'margin-left' => 'auto !important',
+ 'margin-right' => 'auto !important',
+ )
+ )
+ );
+
+ // Add value specific wide size.
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default-wide-size',
+ array(
+ 'suffix' => $wide_max_width_value,
+ 'selector' => '> .alignwide',
+ 'rules' => array(
+ 'max-width' => esc_html( $wide_max_width_value ),
+ )
+ )
+ );
+
+ // Add universal full width.
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default',
+ array(
+ 'selector' => '> .alignfull',
+ 'rules' => 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; }";
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; }";
+ if ( ! $gap_value ) {
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default-global-gap',
+ array(
+ 'selector' => '> *',
+ 'rules' => array(
+ 'margin-top' => '0',
+ 'margin-bottom' => '0',
+ ),
+ )
+ );
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default-global-gap',
+ array(
+ 'selector' => '> * + *',
+ 'rules' => array(
+ 'margin-top' => 'var( --wp--style--block-gap )',
+ 'margin-bottom' => '0',
+ ),
+ )
+ );
+ } else {
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default-custom-gap',
+ array(
+ 'suffix' => $gap_value,
+ 'selector' => '> *',
+ 'rules' => array(
+ 'margin-top' => '0',
+ 'margin-bottom' => '0',
+ ),
+ )
+ );
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default-custom-gap',
+ array(
+ 'suffix' => $gap_value,
+ 'selector' => '> * + *',
+ 'rules' => array(
+ 'margin-top' => $gap_value,
+ 'margin-bottom' => '0',
+ ),
+ )
+ );
+ }
}
} elseif ( 'flex' === $layout_type ) {
$layout_orientation = isset( $layout['orientation'] ) ? $layout['orientation'] : 'horizontal';
@@ -87,39 +183,120 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
$layout['flexWrap'] :
'wrap';
- $style = "$selector {";
- $style .= 'display: flex;';
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex',
+ array(
+ 'rules' => array(
+ 'display' => 'flex',
+ 'gap' => '0.5em',
+ ),
+ )
+ );
+
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex',
+ array(
+ 'selector' => '> *',
+ 'rules' => array(
+ 'margin' => '0',
+ ),
+ )
+ );
+
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex',
+ array(
+ 'suffix' => $flex_wrap,
+ 'rules' => array(
+ '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;";
- } else {
- $style .= 'gap: 0.5em;';
+ if ( ! $gap_value ) {
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex-global-gap',
+ array(
+ 'rules' => array(
+ 'gap' => 'var( --wp--style--block-gap, 0.5em )',
+ ),
+ )
+ );
+ } else {
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex-custom-gap',
+ array(
+ 'suffix' => $gap_value,
+ 'rules' => array(
+ 'gap' => $gap_value,
+ ),
+ )
+ );
+ }
}
- $style .= "flex-wrap: $flex_wrap;";
+
if ( 'horizontal' === $layout_orientation ) {
- $style .= 'align-items: center;';
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex-orientation-horizontal',
+ array(
+ 'rules' => 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'] ]};";
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex-orientation-horizontal',
+ array(
+ 'suffix' => $justify_content_options[ $layout['justifyContent'] ],
+ 'rules' => array(
+ 'justify-content' => $justify_content_options[ $layout['justifyContent'] ],
+ ),
+ )
+ );
}
} else {
- $style .= 'flex-direction: column;';
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex-orientation-vertical',
+ array(
+ 'rules' => array(
+ 'flex-direction' => 'column',
+ ),
+ )
+ );
+
if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
- $style .= "align-items: {$justify_content_options[ $layout['justifyContent'] ]};";
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex-orientation-vertical',
+ array(
+ 'suffix' => $justify_content_options[ $layout['justifyContent'] ],
+ 'rules' => array(
+ 'align-items' => $justify_content_options[ $layout['justifyContent'] ],
+ ),
+ )
+ );
} else {
- $style .= 'align-items: flex-start;';
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex-orientation-vertical',
+ array(
+ 'suffix' => 'flex-start',
+ 'rules' => array(
+ 'align-items' => 'flex-start',
+ ),
+ )
+ );
}
}
- $style .= '}';
-
- $style .= "$selector > * { margin: 0; }";
}
- return $style;
+ return array_unique( $class_names );
}
/**
@@ -149,24 +326,21 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
$used_layout = $default_layout;
}
- $class_name = wp_unique_id( 'wp-container-' );
$gap_value = _wp_array_get( $block, array( 'attrs', 'style', 'spacing', 'blockGap' ) );
// Skip if gap value contains unsupported characters.
// 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 );
+ $gap_value = preg_match( '%[\\\(&=}]|/\*%', $gap_value ) ? null : $gap_value;
+ $class_names = gutenberg_get_layout_style( $used_layout, $has_block_gap_support, $gap_value );
// 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(
'/' . preg_quote( 'class="', '/' ) . '/',
- 'class="' . esc_attr( $class_name ) . ' ',
+ 'class="' . esc_attr( implode( ' ', $class_names ) ) . ' ',
$block_content,
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 7eac59ead41630..c516fb27dfcd35 100644
--- a/lib/class-wp-style-engine.php
+++ b/lib/class-wp-style-engine.php
@@ -58,12 +58,44 @@ public static function get_instance() {
return self::$instance;
}
- public function add_style( $key, $value ) {
- $this->registered_styles[ $key ] = $value;
+ /**
+ * Assemble the style rule from a list of rules, and store based on a key
+ * generated from the class name, the selector, and any values used as a suffix.
+ *
+ * @param string $key A class name used to construct a key.
+ * @param array $options An array of options, rules, and selector for constructing the rules.
+ *
+ * @return string The class name for the added style.
+ */
+ public function add_style( $key, $options ) {
+ $class = ! empty( $options['suffix'] ) ? $key . '-' . sanitize_title( $options['suffix'] ) : $key;
+ $selector = ! empty( $options['selector'] ) ? ' ' . trim( $options['selector'] ) : '';
+ $rules = ! empty( $options['rules'] ) ? $options['rules'] : array();
+ $prefix = ! empty( $options['prefix'] ) ? $options['prefix'] : '.';
+
+ if ( ! $class ) {
+ return;
+ }
+
+ $style = "{$prefix}{$class}{$selector} {\n";
+
+ if ( is_string( $rules ) ) {
+ $style .= ' ';
+ $style .= $rules;
+ } else {
+ foreach( $rules as $rule => $value ) {
+ $style .= " {$rule}: {$value};\n";
+ }
+ }
+ $style .= "}\n";
+
+ $this->registered_styles[ $class . $selector ] = $style;
+
+ return $class;
}
public function output_styles() {
$style = implode( "\n", $this->registered_styles );
- echo "\n";
+ echo "\n";
}
}
From 842b83ddccd62bbb363d738fc477e0a782fbe049 Mon Sep 17 00:00:00 2001
From: Andrew Serong <14988353+andrewserong@users.noreply.github.com>
Date: Wed, 2 Mar 2022 12:21:21 +1100
Subject: [PATCH 3/6] Split out layout style generation by type
---
lib/block-supports/layout.php | 435 ++++++++++++++++++----------------
1 file changed, 235 insertions(+), 200 deletions(-)
diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index eba2b621517658..7d99a07c514759 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -26,276 +26,311 @@ function gutenberg_register_layout_support( $block_type ) {
}
/**
- * Generates the CSS corresponding to the provided layout.
+ * Generates styles for the default flow layout type.
*
- * @param array $layout Layout object. The one that is passed has already checked the existence of default block layout.
+ * @param array $layout Layout object.
* @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 string $gap_value The block gap value to apply.
*
- * @return string CSS style.
+ * @return array An array of class names corresponding to the generated layout CSS.
*/
-function gutenberg_get_layout_style( $layout, $has_block_gap_support = false, $gap_value = null ) {
- $layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
-
+function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support = false, $gap_value = null ) {
$style_engine = WP_Style_Engine_Gutenberg::get_instance();
- $class_names = array();
-
- if ( 'default' === $layout_type ) {
- $content_size = isset( $layout['contentSize'] ) ? $layout['contentSize'] : '';
- $wide_size = isset( $layout['wideSize'] ) ? $layout['wideSize'] : '';
+ $class_names = array();
+
+ $content_size = isset( $layout['contentSize'] ) ? $layout['contentSize'] : '';
+ $wide_size = isset( $layout['wideSize'] ) ? $layout['wideSize'] : '';
+
+ $all_max_width_value = $content_size ? $content_size : $wide_size;
+ $wide_max_width_value = $wide_size ? $wide_size : $content_size;
+
+ // Make sure there is a single CSS rule, and all tags are stripped for security.
+ // TODO: Use `safecss_filter_attr` instead - once https://core.trac.wordpress.org/ticket/46197 is patched.
+ $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] );
+
+ // Add universal styles for all default layouts.
+ // Add left align rule;
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default',
+ array(
+ 'selector' => '.alignleft',
+ 'rules' => array(
+ 'float' => 'left',
+ 'margin-right' => '2em',
+ 'margin-left' => '0',
+ ),
+ )
+ );
- $all_max_width_value = $content_size ? $content_size : $wide_size;
- $wide_max_width_value = $wide_size ? $wide_size : $content_size;
+ // Add right align rule:
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default',
+ array(
+ 'selector' => '.alignright',
+ 'rules' => array(
+ 'float' => 'right',
+ 'margin-left' => '2em',
+ 'margin-right' => '0',
+ ),
+ )
+ );
- // Make sure there is a single CSS rule, and all tags are stripped for security.
- // TODO: Use `safecss_filter_attr` instead - once https://core.trac.wordpress.org/ticket/46197 is patched.
- $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] );
+ if ( $content_size || $wide_size ) {
+ // Add value specific content size.
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default-content-size',
+ array(
+ 'suffix' => $all_max_width_value,
+ 'selector' => '> :where(:not(.alignleft):not(.alignright))',
+ 'rules' => array(
+ 'max-width' => esc_html( $all_max_width_value ),
+ 'margin-left' => 'auto !important',
+ 'margin-right' => 'auto !important',
+ )
+ )
+ );
- // Add universal styles for all default layouts.
- // Add left align rule;
+ // Add value specific wide size.
$class_names[] = $style_engine->add_style(
- 'wp-layout-default',
+ 'wp-layout-default-wide-size',
array(
- 'selector' => '.alignleft',
- 'rules' => array(
- 'float' => 'left',
- 'margin-right' => '2em',
- 'margin-left' => '0',
- ),
+ 'suffix' => $wide_max_width_value,
+ 'selector' => '> .alignwide',
+ 'rules' => array(
+ 'max-width' => esc_html( $wide_max_width_value ),
+ )
)
);
- // Add right align rule:
+ // Add universal full width.
$class_names[] = $style_engine->add_style(
'wp-layout-default',
array(
- 'selector' => '.alignright',
+ 'selector' => '> .alignfull',
'rules' => array(
- 'float' => 'right',
- 'margin-left' => '2em',
- 'margin-right' => '0',
- ),
+ 'max-width' => 'none',
+ )
)
);
+ }
- if ( $content_size || $wide_size ) {
- // Add value specific content size.
+ if ( $has_block_gap_support ) {
+ if ( ! $gap_value ) {
$class_names[] = $style_engine->add_style(
- 'wp-layout-default-content-size',
+ 'wp-layout-default-global-gap',
array(
- 'suffix' => $all_max_width_value,
- 'selector' => '> :where(:not(.alignleft):not(.alignright))',
- 'rules' => array(
- 'max-width' => esc_html( $all_max_width_value ),
- 'margin-left' => 'auto !important',
- 'margin-right' => 'auto !important',
- )
+ 'selector' => '> *',
+ 'rules' => array(
+ 'margin-top' => '0',
+ 'margin-bottom' => '0',
+ ),
)
);
-
- // Add value specific wide size.
$class_names[] = $style_engine->add_style(
- 'wp-layout-default-wide-size',
+ 'wp-layout-default-global-gap',
array(
- 'suffix' => $wide_max_width_value,
- 'selector' => '> .alignwide',
- 'rules' => array(
- 'max-width' => esc_html( $wide_max_width_value ),
- )
+ 'selector' => '> * + *',
+ 'rules' => array(
+ 'margin-top' => 'var( --wp--style--block-gap )',
+ 'margin-bottom' => '0',
+ ),
+ )
+ );
+ } else {
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-default-custom-gap',
+ array(
+ 'suffix' => $gap_value,
+ 'selector' => '> *',
+ 'rules' => array(
+ 'margin-top' => '0',
+ 'margin-bottom' => '0',
+ ),
)
);
-
- // Add universal full width.
$class_names[] = $style_engine->add_style(
- 'wp-layout-default',
+ 'wp-layout-default-custom-gap',
array(
- 'selector' => '> .alignfull',
+ 'suffix' => $gap_value,
+ 'selector' => '> * + *',
'rules' => array(
- 'max-width' => 'none',
- )
+ 'margin-top' => $gap_value,
+ 'margin-bottom' => '0',
+ ),
)
);
}
+ }
- if ( $has_block_gap_support ) {
- if ( ! $gap_value ) {
- $class_names[] = $style_engine->add_style(
- 'wp-layout-default-global-gap',
- array(
- 'selector' => '> *',
- 'rules' => array(
- 'margin-top' => '0',
- 'margin-bottom' => '0',
- ),
- )
- );
- $class_names[] = $style_engine->add_style(
- 'wp-layout-default-global-gap',
- array(
- 'selector' => '> * + *',
- 'rules' => array(
- 'margin-top' => 'var( --wp--style--block-gap )',
- 'margin-bottom' => '0',
- ),
- )
- );
- } else {
- $class_names[] = $style_engine->add_style(
- 'wp-layout-default-custom-gap',
- array(
- 'suffix' => $gap_value,
- 'selector' => '> *',
- 'rules' => array(
- 'margin-top' => '0',
- 'margin-bottom' => '0',
- ),
- )
- );
- $class_names[] = $style_engine->add_style(
- 'wp-layout-default-custom-gap',
- array(
- 'suffix' => $gap_value,
- 'selector' => '> * + *',
- 'rules' => array(
- 'margin-top' => $gap_value,
- 'margin-bottom' => '0',
- ),
- )
- );
- }
- }
- } elseif ( 'flex' === $layout_type ) {
- $layout_orientation = isset( $layout['orientation'] ) ? $layout['orientation'] : 'horizontal';
+ return $class_names;
+}
- $justify_content_options = array(
- 'left' => 'flex-start',
- 'right' => 'flex-end',
- 'center' => 'center',
- );
+/**
+ * Generates styles for the flex layout type.
+ *
+ * @param array $layout Layout object.
+ * @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.
+ *
+ * @return array An array of class names corresponding to the generated layout CSS.
+ */
+function gutenberg_generate_layout_style_flex( $layout, $has_block_gap_support = false, $gap_value = null ) {
+ $style_engine = WP_Style_Engine_Gutenberg::get_instance();
+ $class_names = array();
+ $layout_orientation = isset( $layout['orientation'] ) ? $layout['orientation'] : 'horizontal';
+
+ $justify_content_options = array(
+ 'left' => 'flex-start',
+ 'right' => 'flex-end',
+ 'center' => 'center',
+ );
- if ( 'horizontal' === $layout_orientation ) {
- $justify_content_options += array( 'space-between' => 'space-between' );
- }
+ if ( 'horizontal' === $layout_orientation ) {
+ $justify_content_options += array( 'space-between' => 'space-between' );
+ }
- $flex_wrap_options = array( 'wrap', 'nowrap' );
- $flex_wrap = ! empty( $layout['flexWrap'] ) && in_array( $layout['flexWrap'], $flex_wrap_options, true ) ?
- $layout['flexWrap'] :
- 'wrap';
+ $flex_wrap_options = array( 'wrap', 'nowrap' );
+ $flex_wrap = ! empty( $layout['flexWrap'] ) && in_array( $layout['flexWrap'], $flex_wrap_options, true ) ?
+ $layout['flexWrap'] :
+ 'wrap';
+
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex',
+ array(
+ 'rules' => array(
+ 'display' => 'flex',
+ 'gap' => '0.5em',
+ ),
+ )
+ );
- $class_names[] = $style_engine->add_style(
- 'wp-layout-flex',
- array(
- 'rules' => array(
- 'display' => 'flex',
- 'gap' => '0.5em',
- ),
- )
- );
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex',
+ array(
+ 'selector' => '> *',
+ 'rules' => array(
+ 'margin' => '0',
+ ),
+ )
+ );
+
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex',
+ array(
+ 'suffix' => $flex_wrap,
+ 'rules' => array(
+ 'flex-wrap' => $flex_wrap,
+ ),
+ )
+ );
+
+ if ( $has_block_gap_support ) {
+ if ( ! $gap_value ) {
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex-global-gap',
+ array(
+ 'rules' => array(
+ 'gap' => 'var( --wp--style--block-gap, 0.5em )',
+ ),
+ )
+ );
+ } else {
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex-custom-gap',
+ array(
+ 'suffix' => $gap_value,
+ 'rules' => array(
+ 'gap' => $gap_value,
+ ),
+ )
+ );
+ }
+ }
+ if ( 'horizontal' === $layout_orientation ) {
$class_names[] = $style_engine->add_style(
- 'wp-layout-flex',
+ 'wp-layout-flex-orientation-horizontal',
array(
- 'selector' => '> *',
- 'rules' => array(
- 'margin' => '0',
+ 'rules' => 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 ) ) {
+ $class_names[] = $style_engine->add_style(
+ 'wp-layout-flex-orientation-horizontal',
+ array(
+ 'suffix' => $justify_content_options[ $layout['justifyContent'] ],
+ 'rules' => array(
+ 'justify-content' => $justify_content_options[ $layout['justifyContent'] ],
+ ),
+ )
+ );
+ }
+ } else {
$class_names[] = $style_engine->add_style(
- 'wp-layout-flex',
+ 'wp-layout-flex-orientation-vertical',
array(
- 'suffix' => $flex_wrap,
'rules' => array(
- 'flex-wrap' => $flex_wrap,
+ 'flex-direction' => 'column',
),
)
);
- if ( $has_block_gap_support ) {
- if ( ! $gap_value ) {
- $class_names[] = $style_engine->add_style(
- 'wp-layout-flex-global-gap',
- array(
- 'rules' => array(
- 'gap' => 'var( --wp--style--block-gap, 0.5em )',
- ),
- )
- );
- } else {
- $class_names[] = $style_engine->add_style(
- 'wp-layout-flex-custom-gap',
- array(
- 'suffix' => $gap_value,
- 'rules' => array(
- 'gap' => $gap_value,
- ),
- )
- );
- }
- }
-
- if ( 'horizontal' === $layout_orientation ) {
+ if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
$class_names[] = $style_engine->add_style(
- 'wp-layout-flex-orientation-horizontal',
+ 'wp-layout-flex-orientation-vertical',
array(
+ 'suffix' => $justify_content_options[ $layout['justifyContent'] ],
'rules' => array(
- 'align-items' => 'center',
+ 'align-items' => $justify_content_options[ $layout['justifyContent'] ],
),
)
);
-
- /**
- * 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 ) ) {
- $class_names[] = $style_engine->add_style(
- 'wp-layout-flex-orientation-horizontal',
- array(
- 'suffix' => $justify_content_options[ $layout['justifyContent'] ],
- 'rules' => array(
- 'justify-content' => $justify_content_options[ $layout['justifyContent'] ],
- ),
- )
- );
- }
} else {
$class_names[] = $style_engine->add_style(
'wp-layout-flex-orientation-vertical',
array(
+ 'suffix' => 'flex-start',
'rules' => array(
- 'flex-direction' => 'column',
+ 'align-items' => 'flex-start',
),
)
);
-
- if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
- $class_names[] = $style_engine->add_style(
- 'wp-layout-flex-orientation-vertical',
- array(
- 'suffix' => $justify_content_options[ $layout['justifyContent'] ],
- 'rules' => array(
- 'align-items' => $justify_content_options[ $layout['justifyContent'] ],
- ),
- )
- );
- } else {
- $class_names[] = $style_engine->add_style(
- 'wp-layout-flex-orientation-vertical',
- array(
- 'suffix' => 'flex-start',
- 'rules' => array(
- 'align-items' => 'flex-start',
- ),
- )
- );
- }
}
}
+ return $class_names;
+}
+
+/**
+ * Generates the CSS corresponding to the provided layout.
+ *
+ * @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.
+ *
+ * @return array An array of class names corresponding to the generated layout CSS.
+ */
+function gutenberg_get_layout_style( $layout, $has_block_gap_support = false, $gap_value = null ) {
+ $layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
+
+ $style_engine = WP_Style_Engine_Gutenberg::get_instance();
+ $class_names = array();
+
+ if ( 'default' === $layout_type ) {
+ $class_names = gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support, $gap_value );
+ } elseif ( 'flex' === $layout_type ) {
+ $class_names = gutenberg_generate_layout_style_flex( $layout, $has_block_gap_support, $gap_value );
+ }
+
return array_unique( $class_names );
}
From 66aabccede8995ffbb1a7424bdf409799f3c6c49 Mon Sep 17 00:00:00 2001
From: Andrew Serong <14988353+andrewserong@users.noreply.github.com>
Date: Wed, 2 Mar 2022 12:29:35 +1100
Subject: [PATCH 4/6] Fix linting issues
---
lib/block-supports/layout.php | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index 7d99a07c514759..d57d4744477775 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -50,26 +50,26 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
$wide_max_width_value = wp_strip_all_tags( explode( ';', $wide_max_width_value )[0] );
// Add universal styles for all default layouts.
- // Add left align rule;
+ // Add left align rule.
$class_names[] = $style_engine->add_style(
'wp-layout-default',
array(
'selector' => '.alignleft',
'rules' => array(
- 'float' => 'left',
+ 'float' => 'left',
'margin-right' => '2em',
'margin-left' => '0',
),
)
);
- // Add right align rule:
+ // Add right align rule.
$class_names[] = $style_engine->add_style(
'wp-layout-default',
array(
'selector' => '.alignright',
'rules' => array(
- 'float' => 'right',
+ 'float' => 'right',
'margin-left' => '2em',
'margin-right' => '0',
),
@@ -83,11 +83,11 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
array(
'suffix' => $all_max_width_value,
'selector' => '> :where(:not(.alignleft):not(.alignright))',
- 'rules' => array(
+ 'rules' => array(
'max-width' => esc_html( $all_max_width_value ),
'margin-left' => 'auto !important',
'margin-right' => 'auto !important',
- )
+ ),
)
);
@@ -97,9 +97,9 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
array(
'suffix' => $wide_max_width_value,
'selector' => '> .alignwide',
- 'rules' => array(
+ 'rules' => array(
'max-width' => esc_html( $wide_max_width_value ),
- )
+ ),
)
);
@@ -110,7 +110,7 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
'selector' => '> .alignfull',
'rules' => array(
'max-width' => 'none',
- )
+ ),
)
);
}
@@ -230,7 +230,7 @@ function gutenberg_generate_layout_style_flex( $layout, $has_block_gap_support =
$class_names[] = $style_engine->add_style(
'wp-layout-flex-global-gap',
array(
- 'rules' => array(
+ 'rules' => array(
'gap' => 'var( --wp--style--block-gap, 0.5em )',
),
)
@@ -252,8 +252,8 @@ function gutenberg_generate_layout_style_flex( $layout, $has_block_gap_support =
$class_names[] = $style_engine->add_style(
'wp-layout-flex-orientation-horizontal',
array(
- 'rules' => array(
- 'align-items' => 'center',
+ 'rules' => array(
+ 'align-items' => 'center',
),
)
);
@@ -278,7 +278,7 @@ function gutenberg_generate_layout_style_flex( $layout, $has_block_gap_support =
$class_names[] = $style_engine->add_style(
'wp-layout-flex-orientation-vertical',
array(
- 'rules' => array(
+ 'rules' => array(
'flex-direction' => 'column',
),
)
@@ -321,8 +321,6 @@ function gutenberg_generate_layout_style_flex( $layout, $has_block_gap_support =
*/
function gutenberg_get_layout_style( $layout, $has_block_gap_support = false, $gap_value = null ) {
$layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
-
- $style_engine = WP_Style_Engine_Gutenberg::get_instance();
$class_names = array();
if ( 'default' === $layout_type ) {
@@ -361,7 +359,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
$used_layout = $default_layout;
}
- $gap_value = _wp_array_get( $block, array( 'attrs', 'style', 'spacing', 'blockGap' ) );
+ $gap_value = _wp_array_get( $block, array( 'attrs', 'style', 'spacing', 'blockGap' ) );
// Skip if gap value contains unsupported characters.
// 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.
From 5293512d51d2741e69fc08b58e730741f2451dd6 Mon Sep 17 00:00:00 2001
From: Andrew Serong <14988353+andrewserong@users.noreply.github.com>
Date: Wed, 2 Mar 2022 12:32:50 +1100
Subject: [PATCH 5/6] Fix linting issues with style engine class
---
...le-engine.php => class-wp-style-engine-gutenberg.php} | 9 +++++++--
lib/load.php | 2 +-
2 files changed, 8 insertions(+), 3 deletions(-)
rename lib/{class-wp-style-engine.php => class-wp-style-engine-gutenberg.php} (92%)
diff --git a/lib/class-wp-style-engine.php b/lib/class-wp-style-engine-gutenberg.php
similarity index 92%
rename from lib/class-wp-style-engine.php
rename to lib/class-wp-style-engine-gutenberg.php
index c516fb27dfcd35..7def187b443e0d 100644
--- a/lib/class-wp-style-engine.php
+++ b/lib/class-wp-style-engine-gutenberg.php
@@ -3,7 +3,6 @@
* WP_Style_Engine class
*
* @package Gutenberg
-
*/
/**
@@ -31,6 +30,9 @@ class WP_Style_Engine_Gutenberg {
*/
private static $instance = null;
+ /**
+ * Register action for outputting styles when the class is constructed.
+ */
public function __construct() {
// Borrows the logic from `gutenberg_enqueue_block_support_styles`.
$action_hook_name = 'wp_footer';
@@ -83,7 +85,7 @@ public function add_style( $key, $options ) {
$style .= ' ';
$style .= $rules;
} else {
- foreach( $rules as $rule => $value ) {
+ foreach ( $rules as $rule => $value ) {
$style .= " {$rule}: {$value};\n";
}
}
@@ -94,6 +96,9 @@ public function add_style( $key, $options ) {
return $class;
}
+ /**
+ * Render registered styles for final output.
+ */
public function output_styles() {
$style = implode( "\n", $this->registered_styles );
echo "\n";
diff --git a/lib/load.php b/lib/load.php
index 29a1116b42c8c8..1697629b9a7120 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -123,7 +123,7 @@ function gutenberg_is_experiment_enabled( $name ) {
// 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__ . '/class-wp-style-engine-gutenberg.php';
require __DIR__ . '/block-supports/elements.php';
require __DIR__ . '/block-supports/colors.php';
From c15b9cb5d037a765fe3242f2da4a4a5fcde079d0 Mon Sep 17 00:00:00 2001
From: ramonjd
Date: Wed, 2 Mar 2022 14:25:41 +1100
Subject: [PATCH 6/6] Renaming 'default' to 'flow' to make it more meaningful
on the frontend Storing styles as selector => rules so we can experiment with
operations such as updating styles, retrieving classnames from registered
styles after registrations and other fun.
---
lib/block-supports/layout.php | 22 +++++++--------
lib/class-wp-style-engine-gutenberg.php | 36 ++++++++++++-------------
2 files changed, 29 insertions(+), 29 deletions(-)
diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index d57d4744477775..cfb5fbe36c5f8e 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -52,7 +52,7 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
// Add universal styles for all default layouts.
// Add left align rule.
$class_names[] = $style_engine->add_style(
- 'wp-layout-default',
+ 'wp-layout-flow',
array(
'selector' => '.alignleft',
'rules' => array(
@@ -65,7 +65,7 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
// Add right align rule.
$class_names[] = $style_engine->add_style(
- 'wp-layout-default',
+ 'wp-layout-flow',
array(
'selector' => '.alignright',
'rules' => array(
@@ -79,7 +79,7 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
if ( $content_size || $wide_size ) {
// Add value specific content size.
$class_names[] = $style_engine->add_style(
- 'wp-layout-default-content-size',
+ 'wp-layout-flow-content-size',
array(
'suffix' => $all_max_width_value,
'selector' => '> :where(:not(.alignleft):not(.alignright))',
@@ -93,7 +93,7 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
// Add value specific wide size.
$class_names[] = $style_engine->add_style(
- 'wp-layout-default-wide-size',
+ 'wp-layout-flow-wide-size',
array(
'suffix' => $wide_max_width_value,
'selector' => '> .alignwide',
@@ -105,7 +105,7 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
// Add universal full width.
$class_names[] = $style_engine->add_style(
- 'wp-layout-default',
+ 'wp-layout-flow',
array(
'selector' => '> .alignfull',
'rules' => array(
@@ -118,7 +118,7 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
if ( $has_block_gap_support ) {
if ( ! $gap_value ) {
$class_names[] = $style_engine->add_style(
- 'wp-layout-default-global-gap',
+ 'wp-layout-flow-global-gap',
array(
'selector' => '> *',
'rules' => array(
@@ -128,7 +128,7 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
)
);
$class_names[] = $style_engine->add_style(
- 'wp-layout-default-global-gap',
+ 'wp-layout-flow-global-gap',
array(
'selector' => '> * + *',
'rules' => array(
@@ -139,7 +139,7 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
);
} else {
$class_names[] = $style_engine->add_style(
- 'wp-layout-default-custom-gap',
+ 'wp-layout-flow-custom-gap',
array(
'suffix' => $gap_value,
'selector' => '> *',
@@ -150,7 +150,7 @@ function gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support =
)
);
$class_names[] = $style_engine->add_style(
- 'wp-layout-default-custom-gap',
+ 'wp-layout-flow-custom-gap',
array(
'suffix' => $gap_value,
'selector' => '> * + *',
@@ -320,10 +320,10 @@ function gutenberg_generate_layout_style_flex( $layout, $has_block_gap_support =
* @return array An array of class names corresponding to the generated layout CSS.
*/
function gutenberg_get_layout_style( $layout, $has_block_gap_support = false, $gap_value = null ) {
- $layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
+ $layout_type = isset( $layout['type'] ) ? $layout['type'] : 'flow';
$class_names = array();
- if ( 'default' === $layout_type ) {
+ if ( 'flow' === $layout_type ) {
$class_names = gutenberg_generate_layout_style_flow( $layout, $has_block_gap_support, $gap_value );
} elseif ( 'flex' === $layout_type ) {
$class_names = gutenberg_generate_layout_style_flex( $layout, $has_block_gap_support, $gap_value );
diff --git a/lib/class-wp-style-engine-gutenberg.php b/lib/class-wp-style-engine-gutenberg.php
index 7def187b443e0d..d970727943112f 100644
--- a/lib/class-wp-style-engine-gutenberg.php
+++ b/lib/class-wp-style-engine-gutenberg.php
@@ -61,8 +61,7 @@ public static function get_instance() {
}
/**
- * Assemble the style rule from a list of rules, and store based on a key
- * generated from the class name, the selector, and any values used as a suffix.
+ * Stores style rules for a given CSS selector (the key) and returns an associated classname.
*
* @param string $key A class name used to construct a key.
* @param array $options An array of options, rules, and selector for constructing the rules.
@@ -79,28 +78,29 @@ public function add_style( $key, $options ) {
return;
}
- $style = "{$prefix}{$class}{$selector} {\n";
-
- if ( is_string( $rules ) ) {
- $style .= ' ';
- $style .= $rules;
- } else {
- foreach ( $rules as $rule => $value ) {
- $style .= " {$rule}: {$value};\n";
- }
- }
- $style .= "}\n";
-
- $this->registered_styles[ $class . $selector ] = $style;
+ $this->registered_styles[ $prefix . $class . $selector ] = $rules;
return $class;
}
/**
- * Render registered styles for final output.
+ * Render registered styles as key { ...rules } for final output.
*/
public function output_styles() {
- $style = implode( "\n", $this->registered_styles );
- echo "\n";
+ $output = '';
+ foreach ( $this->registered_styles as $selector => $rules ) {
+ $output .= "{$selector} {\n";
+
+ if ( is_string( $rules ) ) {
+ $output .= ' ';
+ $output .= $rules;
+ } else {
+ foreach ( $rules as $rule => $value ) {
+ $output .= " {$rule}: {$value};\n";
+ }
+ }
+ $output .= "}\n";
+ }
+ echo "\n";
}
}