From 7a4be34e3c785a00448d9b52e3f293a354868c5b Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 01:00:27 +0800 Subject: [PATCH 01/19] feat: generate css file instead of inlined style --- plugin.php | 1 + src/css-file-generator.php | 202 +++++++++++++++++++++++++++++++++++++ src/init.php | 21 ++-- 3 files changed, 218 insertions(+), 6 deletions(-) create mode 100644 src/css-file-generator.php diff --git a/plugin.php b/plugin.php index 66da0c38be..f6b8d37099 100644 --- a/plugin.php +++ b/plugin.php @@ -231,6 +231,7 @@ function is_frontend() { require_once( plugin_dir_path( __FILE__ ) . 'src/jetpack.php' ); require_once( plugin_dir_path( __FILE__ ) . 'src/multisite.php' ); require_once( plugin_dir_path( __FILE__ ) . 'src/kses.php' ); +require_once( plugin_dir_path( __FILE__ ) . 'src/css-file-generator.php' ); require_once( plugin_dir_path( __FILE__ ) . 'src/dynamic-breakpoints.php' ); require_once( plugin_dir_path( __FILE__ ) . 'src/design-library/init.php' ); require_once( plugin_dir_path( __FILE__ ) . 'src/design-library/default-placeholders.php' ); diff --git a/src/css-file-generator.php b/src/css-file-generator.php new file mode 100644 index 0000000000..230a23af4f --- /dev/null +++ b/src/css-file-generator.php @@ -0,0 +1,202 @@ +get_cached_css_file_name(); + if ( $old_file_name ) { + $old_file_path = $this->get_css_file_path() . $old_file_name; + if ( file_exists( $old_file_path ) ) { + unlink( $old_file_path ); + } + } + } + } + + new Stackable_CSS_File_Generator(); +} \ No newline at end of file diff --git a/src/init.php b/src/init.php index 6ae3840430..edb59522c5 100644 --- a/src/init.php +++ b/src/init.php @@ -122,12 +122,21 @@ public function register_frontend_assets() { wp_register_script( 'ugb-block-frontend-js', null, [], STACKABLE_VERSION ); } - // Register inline frontend styles, these are always loaded. - // Register via a dummy style. - wp_register_style( 'ugb-style-css-nodep', false ); - $inline_css = apply_filters( 'stackable_inline_styles_nodep', '' ); - if ( ! empty( $inline_css ) ) { - wp_add_inline_style( 'ugb-style-css-nodep', trim( $inline_css ) ); + // Enqueue the global CSS file in the frontend. + if ( ! is_admin() && + get_option( 'stackable_use_css_files', 'yes' ) === 'yes' && + Stackable_CSS_File_Generator::css_file_exists() + ) { + Stackable_CSS_File_Generator::enqueue_global_css_file(); + } else { + // Keep the old inline style registration as fallback for backward compatibility + // but only use it if CSS file generation is disabled + // Register via a dummy style. + wp_register_style( 'ugb-style-css-nodep', false ); + $inline_css = apply_filters( 'stackable_inline_styles_nodep', '' ); + if ( ! empty( $inline_css ) ) { + wp_add_inline_style( 'ugb-style-css-nodep', trim( $inline_css ) ); + } } // Register inline frontend styles for theme.json block style inheritance From 43a6589b27b0699210f34a88a66f4618f719d599 Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 01:00:37 +0800 Subject: [PATCH 02/19] optimize by not registering patterns anymore --- src/design-library/init.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/design-library/init.php b/src/design-library/init.php index 8559710187..de7599e801 100644 --- a/src/design-library/init.php +++ b/src/design-library/init.php @@ -31,8 +31,11 @@ public function __construct() { add_filter( 'stackable_design_library_get_premium_designs', array( $this, 'get_designs_with_disabled_blocks' ) ); add_filter( 'stackable_design_library_get_premium_designs', array( $this, 'get_premium_designs' ) ); - add_action( 'init', array( $this, 'register_design_pattern' ) ); add_action( 'stackable_delete_design_library_cache', array( $this, 'delete_cache_v3' ) ); + + // DEV NOTE: Commenting this out for now since it is producing server load in the frontend. + // We can re-enable this when we have a better way to register block patterns. + // add_action( 'init', array( $this, 'register_design_pattern' ) ); } public static function validate_string( $value, $request, $param ) { From 5520f9ecd571f09e06bae6d0f3dc11882c522d4d Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 01:12:09 +0800 Subject: [PATCH 03/19] remove checking if file exists --- src/init.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/init.php b/src/init.php index edb59522c5..c942ab9895 100644 --- a/src/init.php +++ b/src/init.php @@ -123,10 +123,7 @@ public function register_frontend_assets() { } // Enqueue the global CSS file in the frontend. - if ( ! is_admin() && - get_option( 'stackable_use_css_files', 'yes' ) === 'yes' && - Stackable_CSS_File_Generator::css_file_exists() - ) { + if ( ! is_admin() && get_option( 'stackable_use_css_files', 'yes' ) === 'yes' ) { Stackable_CSS_File_Generator::enqueue_global_css_file(); } else { // Keep the old inline style registration as fallback for backward compatibility From 833c14ae60bf6e4dd8dfef051d9a85b14b5e435f Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 01:23:31 +0800 Subject: [PATCH 04/19] optimized global typography settings to remove one function call if not needed --- src/global-settings.php | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/global-settings.php b/src/global-settings.php index 0a63fe27ab..c78d1922f2 100644 --- a/src/global-settings.php +++ b/src/global-settings.php @@ -76,10 +76,13 @@ function __construct() { add_action( 'after_setup_theme', array( $this, 'typography_parse_global_styles' ) ); } - // For some native blocks, add a note that they're core blocks. - // Only do this when we need to style native blocks. - if ( in_array( $this->get_apply_typography_to(), array( 'blocks-stackable-native', 'blocks-all' ) ) ) { - add_filter( 'render_block', array( $this, 'typography_detect_native_blocks' ), 10, 2 ); + // Optimize by avoiding repeated calls to get_apply_typography_to() and unnecessary filter registration. + // Only do this if we have global typography. + if ( $this->has_global_typography() ) { + $apply_typography_to = $this->get_apply_typography_to(); + if ( $apply_typography_to === 'blocks-stackable-native' || $apply_typography_to === 'blocks-all' ) { + add_filter( 'render_block', array( $this, 'typography_detect_native_blocks' ), 10, 2 ); + } } // Fixes columns issue with Native Posts block. @@ -563,6 +566,24 @@ public function color_add_global_styles( $current_css ) { * Typography functions *-----------------------------------------------------------------------------*/ + /** + * Fast way to check if the global typography is empty. + * + * @return boolean + */ + public function has_global_typography() { + $typography = get_option( 'stackable_global_typography' ); + if ( empty( $typography ) ) { + return false; + } + + // $typography is an array of arrays. + if ( ! empty( $typography ) && is_array( $typography ) && ! empty( $typography[0] ) && is_array( $typography[0] ) ) { + return ! empty( array_filter( $typography[0] ) ); + } + return true; + } + /** * Add our global typography styles in the frontend. * From 2e73dc81e689987397acfd6061bbc58a964b821d Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 01:39:13 +0800 Subject: [PATCH 05/19] optimized global typography settings to remove one function call if not needed --- src/global-settings.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/global-settings.php b/src/global-settings.php index c78d1922f2..8fa777da55 100644 --- a/src/global-settings.php +++ b/src/global-settings.php @@ -69,9 +69,8 @@ function __construct() { * * @since 2.17.1 */ - // Don't do anything if we don't have any global typography. - $typography = get_option( 'stackable_global_typography' ); - if ( ! empty( $typography ) && is_array( $typography ) ) { + // Only do this if we have global typography. + if ( $this->has_global_typography() ) { $this->force_typography = get_option( 'stackable_global_force_typography' ); add_action( 'after_setup_theme', array( $this, 'typography_parse_global_styles' ) ); } From 74cdffb6f3409b0d51f70a3be473fdca717b4e2a Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 02:43:30 +0800 Subject: [PATCH 06/19] added default values for some get_option --- src/dynamic-breakpoints.php | 2 +- src/global-settings.php | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/dynamic-breakpoints.php b/src/dynamic-breakpoints.php index a83ceaf648..d077164a69 100644 --- a/src/dynamic-breakpoints.php +++ b/src/dynamic-breakpoints.php @@ -67,7 +67,7 @@ public function get_dynamic_breakpoints() { ) ); // Check if there are saved custom breakpoints from our settings. - $saved_breakpoints = get_option( 'stackable_dynamic_breakpoints' ); + $saved_breakpoints = get_option( 'stackable_dynamic_breakpoints', false ); if ( ! empty( $saved_breakpoints ) ) { // Set breakpoints for tablet and mobile if they are set. if ( ! empty( $saved_breakpoints['tablet'] ) ) { diff --git a/src/global-settings.php b/src/global-settings.php index 8fa777da55..3a046cee41 100644 --- a/src/global-settings.php +++ b/src/global-settings.php @@ -73,11 +73,8 @@ function __construct() { if ( $this->has_global_typography() ) { $this->force_typography = get_option( 'stackable_global_force_typography' ); add_action( 'after_setup_theme', array( $this, 'typography_parse_global_styles' ) ); - } - // Optimize by avoiding repeated calls to get_apply_typography_to() and unnecessary filter registration. - // Only do this if we have global typography. - if ( $this->has_global_typography() ) { + // Optimize by avoiding repeated calls to get_apply_typography_to() and unnecessary filter registration. $apply_typography_to = $this->get_apply_typography_to(); if ( $apply_typography_to === 'blocks-stackable-native' || $apply_typography_to === 'blocks-all' ) { add_filter( 'render_block', array( $this, 'typography_detect_native_blocks' ), 10, 2 ); @@ -571,7 +568,7 @@ public function color_add_global_styles( $current_css ) { * @return boolean */ public function has_global_typography() { - $typography = get_option( 'stackable_global_typography' ); + $typography = get_option( 'stackable_global_typography', false ); if ( empty( $typography ) ) { return false; } @@ -589,7 +586,7 @@ public function has_global_typography() { * @return void */ public function typography_parse_global_styles() { - $typography = get_option( 'stackable_global_typography' ); + $typography = get_option( 'stackable_global_typography', false ); if ( ! $typography || ! is_array( $typography ) ) { return; } From 116bf3684716332eb12213f1b2fe569a16e5af88 Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 02:48:48 +0800 Subject: [PATCH 07/19] Added STACKABLE_DISABLE_DEPRECATED_CODE constant to disable ALL deprecated code --- plugin.php | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/plugin.php b/plugin.php index f6b8d37099..5ba63187be 100644 --- a/plugin.php +++ b/plugin.php @@ -290,20 +290,21 @@ function is_frontend() { } } -// Deprecated. -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/editor-settings.php' ); -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/native-global-colors.php' ); -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/navigation-panel-pre-enabled.php' ); -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/font-awesome-version.php' ); -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/global-color-schemes.php' ); -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/block-defaults.php' ); +// Allow users to disable the deprecated code via STACKABLE_DISABLE_DEPRECATED_CODE. +if ( ! defined( 'STACKABLE_DISABLE_DEPRECATED_CODE' ) ) { + // Deprecated. + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/editor-settings.php' ); + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/native-global-colors.php' ); + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/navigation-panel-pre-enabled.php' ); + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/font-awesome-version.php' ); + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/global-color-schemes.php' ); + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/block-defaults.php' ); -/** - * V2 Deprecated - */ -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/init.php' ); -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/blocks.php' ); -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/disabled-blocks.php' ); -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/design-library/init.php' ); -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/optimization-settings.php' ); -require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/global-settings.php' ); + // V2 Deprecated + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/init.php' ); + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/blocks.php' ); + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/disabled-blocks.php' ); + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/design-library/init.php' ); + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/optimization-settings.php' ); + require_once( plugin_dir_path( __FILE__ ) . 'src/deprecated/v2/global-settings.php' ); +} \ No newline at end of file From 43eb4acf930093d6606ccb48198be1b765b8a0fe Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 11:56:53 +0800 Subject: [PATCH 08/19] optimized action calling to remove one class property --- src/init.php | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/init.php b/src/init.php index c942ab9895..d2f952d82d 100644 --- a/src/init.php +++ b/src/init.php @@ -16,12 +16,6 @@ if ( ! class_exists( 'Stackable_Init' ) ) { class Stackable_Init { - /** - * Holds the scripts which are already enqueued, to ensure we only do it once per script. - * @var Array - */ - public $scripts_loaded = array(); - /** * Enqueue the frontend scripts, ensures we only do it once. * @@ -243,15 +237,15 @@ public function load_frontend_scripts_conditionally( $block_content, $block ) { } // Enqueue the block script once. - if ( ! isset( $this->scripts_loaded[ $block['blockName'] ] ) ) { - $stackable_block = substr( $block['blockName'], 10 ); - do_action( 'stackable/' . $stackable_block . '/enqueue_scripts' ); - $this->scripts_loaded[ $block['blockName'] ] = true; + if ( did_action( 'stackable/' . $block['blockName'] . '/enqueue_scripts' ) === 0 ) { + do_action( 'stackable/' . $block['blockName'] . '/enqueue_scripts' ); } // Check whether the current block needs to enqueue some scripts. // This gets called across all the blocks. - do_action( 'stackable/enqueue_scripts', $block_content, $block ); + if ( did_action( 'stackable/enqueue_scripts' ) === 0 ) { + do_action( 'stackable/enqueue_scripts', $block_content, $block ); + } return $block_content; } From e9d69d8611da2f095a530a1dc79597946eca56a7 Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 12:28:19 +0800 Subject: [PATCH 09/19] Moved allow_css only when needed --- src/plugins/theme-block-style-inheritance/index.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/theme-block-style-inheritance/index.php b/src/plugins/theme-block-style-inheritance/index.php index 6d7168e750..5c0ca08a89 100644 --- a/src/plugins/theme-block-style-inheritance/index.php +++ b/src/plugins/theme-block-style-inheritance/index.php @@ -21,8 +21,6 @@ function __construct() { add_action( 'body_class', array( $this, 'add_body_class_block_style_inheritance' ) ); add_filter( 'stackable_block_style_inheritance_inline_styles_nodep', array( $this, 'add_block_style_inheritance' ) ); - - add_filter( 'safecss_filter_attr_allow_css', array( $this, 'allow_css' ), 10, 2 ); } // Register the settings for block style inheritance @@ -324,6 +322,9 @@ function add_block_style_inheritance( $current_css ) { $styles[] = $declaration; } + // Allow some CSS functions like color-mix() to be included in the generated CSS. + add_filter( 'safecss_filter_attr_allow_css', array( $this, 'allow_css' ), 10, 2 ); + $generated_css = wp_style_engine_get_stylesheet_from_css_rules( $styles ); if ( $generated_css ) { $generated_css = "/* Block style inheritance */\n" . $generated_css; From 850a56505b11b0417f78a266df0a9a2bc11477b0 Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 12:52:14 +0800 Subject: [PATCH 10/19] move generation of block style inheritance only when needed --- src/init.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/init.php b/src/init.php index d2f952d82d..fee1e65f33 100644 --- a/src/init.php +++ b/src/init.php @@ -130,13 +130,6 @@ public function register_frontend_assets() { } } - // Register inline frontend styles for theme.json block style inheritance - wp_register_style( 'ugb-block-style-inheritance-nodep', false ); - $block_style_inline_css = apply_filters( 'stackable_block_style_inheritance_inline_styles_nodep', '' ); - if ( ! empty( $block_style_inline_css ) ) { - wp_add_inline_style( 'ugb-block-style-inheritance-nodep', $block_style_inline_css ); - } - // This is needed for the translation strings in our UI. if ( is_admin() ) { stackable_load_js_translations(); @@ -250,6 +243,16 @@ public function load_frontend_scripts_conditionally( $block_content, $block ) { return $block_content; } + // Register inline frontend styles for theme.json block style inheritance + public function enqueue_inline_block_style_inheritance() { + $block_style_inline_css = apply_filters( 'stackable_block_style_inheritance_inline_styles_nodep', '' ); + if ( ! empty( $block_style_inline_css ) ) { + wp_register_style( 'ugb-block-style-inheritance-nodep', false ); + wp_add_inline_style( 'ugb-block-style-inheritance-nodep', $block_style_inline_css ); + wp_enqueue_style( 'ugb-block-style-inheritance-nodep' ); + } + } + /** * Enqueue frontend scripts and styles. * @@ -259,7 +262,7 @@ public function block_enqueue_frontend_assets() { $this->register_frontend_assets(); wp_enqueue_style( 'ugb-style-css' ); if ( is_frontend() ) { - wp_enqueue_style( 'ugb-block-style-inheritance-nodep' ); + $this->enqueue_inline_block_style_inheritance(); } wp_enqueue_style( 'ugb-style-css-nodep' ); wp_enqueue_script( 'ugb-block-frontend-js' ); @@ -382,7 +385,7 @@ public function register_block_editor_assets() { // Ensure that block style inheritance styles comes after the editor block styles. function enqueue_style_in_editor() { wp_enqueue_style( 'ugb-block-editor-css' ); - wp_enqueue_style( 'ugb-block-style-inheritance-nodep' ); + $this->enqueue_inline_block_style_inheritance(); } /** From 5e2cf3d2755568ac61555e37530c6701a70d5691 Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 14:19:31 +0800 Subject: [PATCH 11/19] refactored css file generation --- src/css-file-generator.php | 217 ++++++++++++++++++++++++++++--------- src/init.php | 13 +-- 2 files changed, 170 insertions(+), 60 deletions(-) diff --git a/src/css-file-generator.php b/src/css-file-generator.php index 230a23af4f..75a191fc7b 100644 --- a/src/css-file-generator.php +++ b/src/css-file-generator.php @@ -1,6 +1,6 @@ get_cached_css_file_name(); + $old_file_name = static::get_cached_css_file_name(); if ( $old_file_name ) { - $old_file_path = $this->get_css_file_path() . $old_file_name; + $old_file_path = static::get_css_file_path() . $old_file_name; if ( file_exists( $old_file_path ) ) { unlink( $old_file_path ); } } } + + /** + * Clear all cached CSS files for this generator. + */ + public static function clear_css_cache() { + $css_dir = static::get_css_file_path(); + + if ( file_exists( $css_dir ) ) { + $files = glob( $css_dir . static::get_css_file_prefix() . '*.css' ); + foreach ( $files as $file ) { + unlink( $file ); + } + } + + delete_option( static::get_cache_option_name() ); + } + } +} + +if ( ! class_exists( 'Stackable_Global_Design_System_CSS_Generator' ) ) { + + /** + * Global Design System CSS Generator - Extends the base class for global design system. + */ + class Stackable_Global_Design_System_CSS_Generator extends Stackable_Base_CSS_File_Generator { + + /** + * CSS file handle for the global design system. + */ + protected static function get_css_handle() { + return 'ugb-global-design-system'; + } + + /** + * CSS file name prefix. + */ + protected static function get_css_file_prefix() { + return 'stackable-global-'; + } + + /** + * Option name for caching the CSS file name. + */ + protected static function get_cache_option_name() { + return 'stackable_global_css_file_name'; + } + + /** + * Generate the CSS content from all global design system filters. + * + * @return string + */ + protected static function generate_css_content() { + // Apply all the filters that contribute to the global design system + $css_content = apply_filters( 'stackable_inline_styles_nodep', '' ); + + // Add any additional global styles that might be needed + $css_content = apply_filters( 'stackable_global_css_file_content', $css_content ); + + return trim( $css_content ); + } + + /** + * Initialize + */ + function __construct() { + // Add hooks to regenerate CSS when global settings change + add_action( 'update_option_stackable_global_colors', array( $this, 'invalidate_current_css_file' ) ); + add_action( 'update_option_stackable_global_typography', array( $this, 'invalidate_current_css_file' ) ); + add_action( 'update_option_stackable_global_spacing_and_borders', array( $this, 'invalidate_current_css_file' ) ); + add_action( 'update_option_stackable_global_color_schemes', array( $this, 'invalidate_current_css_file' ) ); + add_action( 'update_option_stackable_global_block_styles', array( $this, 'invalidate_current_css_file' ) ); + add_action( 'update_option_stackable_global_buttons_and_icons', array( $this, 'invalidate_current_css_file' ) ); + add_action( 'update_option_stackable_global_preset_controls', array( $this, 'invalidate_current_css_file' ) ); + } + + /** + * Regenerate the CSS file when global settings change. + */ + public function invalidate_current_css_file() { + static::invalidate_css_file(); + } + + /** + * Enqueue the global CSS file (alias for backward compatibility). + */ + public static function enqueue_global_css_file() { + return static::enqueue_css_file(); + } + + /** + * Enqueue the global CSS as inline styles (useful for debugging or when file generation is disabled). + */ + public static function enqueue_global_css_inline() { + return static::enqueue_inline_css(); + } } - new Stackable_CSS_File_Generator(); + new Stackable_Global_Design_System_CSS_Generator(); } \ No newline at end of file diff --git a/src/init.php b/src/init.php index fee1e65f33..a3d3d08ddc 100644 --- a/src/init.php +++ b/src/init.php @@ -118,16 +118,11 @@ public function register_frontend_assets() { // Enqueue the global CSS file in the frontend. if ( ! is_admin() && get_option( 'stackable_use_css_files', 'yes' ) === 'yes' ) { - Stackable_CSS_File_Generator::enqueue_global_css_file(); + // The enqueue_global_css_file method now has built-in fallback to inline styles + // if CSS file generation fails + Stackable_Global_Design_System_CSS_Generator::enqueue_global_css_file(); } else { - // Keep the old inline style registration as fallback for backward compatibility - // but only use it if CSS file generation is disabled - // Register via a dummy style. - wp_register_style( 'ugb-style-css-nodep', false ); - $inline_css = apply_filters( 'stackable_inline_styles_nodep', '' ); - if ( ! empty( $inline_css ) ) { - wp_add_inline_style( 'ugb-style-css-nodep', trim( $inline_css ) ); - } + Stackable_Global_Design_System_CSS_Generator::enqueue_global_css_inline(); } // This is needed for the translation strings in our UI. From d29b88e433b93b4744c333bd7f290fccf3a576a6 Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 14:41:48 +0800 Subject: [PATCH 12/19] change block style inheritance to css file generation --- src/css-file-generator.php | 78 ++++++++++++++++++++++++++++++++++++++ src/init.php | 10 ++--- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/src/css-file-generator.php b/src/css-file-generator.php index 75a191fc7b..49a918ddfe 100644 --- a/src/css-file-generator.php +++ b/src/css-file-generator.php @@ -314,4 +314,82 @@ public static function enqueue_global_css_inline() { } new Stackable_Global_Design_System_CSS_Generator(); +} + +if ( ! class_exists( 'Stackable_Block_Style_Inheritance_CSS_Generator' ) ) { + + /** + * Block Style Inheritance CSS Generator - Extends the base class for block theme style inheritance. + */ + class Stackable_Block_Style_Inheritance_CSS_Generator extends Stackable_Base_CSS_File_Generator { + + /** + * CSS file handle for block style inheritance. + */ + protected static function get_css_handle() { + return 'ugb-block-style-inheritance'; + } + + /** + * CSS file name prefix. + */ + protected static function get_css_file_prefix() { + return 'stackable-block-inheritance-'; + } + + /** + * Option name for caching the CSS file name. + */ + protected static function get_cache_option_name() { + return 'stackable_block_inheritance_css_file_name'; + } + + /** + * Generate the CSS content from block style inheritance filters. + * + * @return string + */ + protected static function generate_css_content() { + // Apply the filter that contributes to block style inheritance + $css_content = apply_filters( 'stackable_block_style_inheritance_inline_styles_nodep', '' ); + + // Add any additional block inheritance styles that might be needed + $css_content = apply_filters( 'stackable_block_inheritance_css_file_content', $css_content ); + + return trim( $css_content ); + } + + /** + * Initialize + */ + function __construct() { + // Add hooks to regenerate CSS when theme.json or block settings change + add_action( 'switch_theme', array( $this, 'invalidate_current_css_file' ) ); + add_action( 'update_option_theme_mods_' . get_stylesheet(), array( $this, 'invalidate_current_css_file' ) ); + add_action( 'customize_save_after', array( $this, 'invalidate_current_css_file' ) ); + } + + /** + * Regenerate the CSS file when block style inheritance settings change. + */ + public function invalidate_current_css_file() { + static::invalidate_css_file(); + } + + /** + * Enqueue the block inheritance CSS file (alias for backward compatibility). + */ + public static function enqueue_block_inheritance_css_file() { + return static::enqueue_css_file(); + } + + /** + * Enqueue the block inheritance CSS as inline styles (useful for debugging or when file generation is disabled). + */ + public static function enqueue_block_inheritance_css_inline() { + return static::enqueue_inline_css(); + } + } + + new Stackable_Block_Style_Inheritance_CSS_Generator(); } \ No newline at end of file diff --git a/src/init.php b/src/init.php index a3d3d08ddc..161de54356 100644 --- a/src/init.php +++ b/src/init.php @@ -240,11 +240,11 @@ public function load_frontend_scripts_conditionally( $block_content, $block ) { // Register inline frontend styles for theme.json block style inheritance public function enqueue_inline_block_style_inheritance() { - $block_style_inline_css = apply_filters( 'stackable_block_style_inheritance_inline_styles_nodep', '' ); - if ( ! empty( $block_style_inline_css ) ) { - wp_register_style( 'ugb-block-style-inheritance-nodep', false ); - wp_add_inline_style( 'ugb-block-style-inheritance-nodep', $block_style_inline_css ); - wp_enqueue_style( 'ugb-block-style-inheritance-nodep' ); + // Use the new CSS generator class with built-in fallback to inline styles + if ( ! is_admin() && get_option( 'stackable_use_css_files', 'yes' ) === 'yes' ) { + Stackable_Block_Style_Inheritance_CSS_Generator::enqueue_block_inheritance_css_file(); + } else { + Stackable_Block_Style_Inheritance_CSS_Generator::enqueue_block_inheritance_css_inline(); } } From 072b87882784db79fecf125538da60dbee059108 Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 15:27:20 +0800 Subject: [PATCH 13/19] added option for using files --- src/css-file-generator.php | 101 +++++++++++++++++++++++++++++++------ src/init.php | 4 +- src/welcome/admin.js | 38 ++++++++++++++ 3 files changed, 125 insertions(+), 18 deletions(-) diff --git a/src/css-file-generator.php b/src/css-file-generator.php index 49a918ddfe..e312170d3a 100644 --- a/src/css-file-generator.php +++ b/src/css-file-generator.php @@ -215,22 +215,6 @@ public static function invalidate_css_file() { } } } - - /** - * Clear all cached CSS files for this generator. - */ - public static function clear_css_cache() { - $css_dir = static::get_css_file_path(); - - if ( file_exists( $css_dir ) ) { - $files = glob( $css_dir . static::get_css_file_prefix() . '*.css' ); - foreach ( $files as $file ) { - unlink( $file ); - } - } - - delete_option( static::get_cache_option_name() ); - } } } @@ -392,4 +376,89 @@ public static function enqueue_block_inheritance_css_inline() { } new Stackable_Block_Style_Inheritance_CSS_Generator(); +} + +if ( ! class_exists( 'Stackable_CSS_File_Generator' ) ) { + + /** + * REST API endpoints for CSS file generator operations. + */ + class Stackable_CSS_File_Generator { + + /** + * Initialize the REST API endpoints. + */ + public function __construct() { + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + + // Register the setting stackable_use_css_files + add_action( 'admin_init', array( $this, 'register_use_css_files_setting' ) ); + add_action( 'rest_api_init', array( $this, 'register_use_css_files_setting' ) ); + } + + /** + * Register the setting stackable_use_css_files + */ + public function register_use_css_files_setting() { + register_setting( + 'stackable_editor_settings', + 'stackable_use_css_files', + array( + 'type' => 'boolean', + 'description' => __( 'Enables CSS file generation for the global design system and block style inheritance', STACKABLE_I18N ), + 'sanitize_callback' => 'sanitize_text_field', + 'show_in_rest' => true, + 'default' => true, + ) + ); + } + + /** + * Register REST API routes. + */ + public function register_routes() { + register_rest_route( 'stackable/v3', '/invalidate-css-files', array( + 'methods' => 'POST', + 'callback' => array( $this, 'invalidate_all_css_files' ), + 'permission_callback' => array( $this, 'check_permissions' ), + ) ); + } + + /** + * Check if user has permission to invalidate CSS files. + * + * @return bool + */ + public function check_permissions() { + return current_user_can( 'manage_options' ); + } + + /** + * Invalidate all generated CSS files. + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response|WP_Error + */ + public function invalidate_all_css_files( $request ) { + try { + // Clear all CSS caches + Stackable_Global_Design_System_CSS_Generator::invalidate_css_file(); + Stackable_Block_Style_Inheritance_CSS_Generator::invalidate_css_file(); + + return new WP_REST_Response( array( + 'success' => true, + 'message' => 'CSS files invalidated successfully', + ), 200 ); + + } catch ( Exception $e ) { + return new WP_Error( + 'css_invalidation_failed', + 'Failed to invalidate CSS files: ' . $e->getMessage(), + array( 'status' => 500 ) + ); + } + } + } + + new Stackable_CSS_File_Generator(); } \ No newline at end of file diff --git a/src/init.php b/src/init.php index 161de54356..39dce84349 100644 --- a/src/init.php +++ b/src/init.php @@ -117,7 +117,7 @@ public function register_frontend_assets() { } // Enqueue the global CSS file in the frontend. - if ( ! is_admin() && get_option( 'stackable_use_css_files', 'yes' ) === 'yes' ) { + if ( ! is_admin() && ! empty( get_option( 'stackable_use_css_files', true ) ) ) { // The enqueue_global_css_file method now has built-in fallback to inline styles // if CSS file generation fails Stackable_Global_Design_System_CSS_Generator::enqueue_global_css_file(); @@ -241,7 +241,7 @@ public function load_frontend_scripts_conditionally( $block_content, $block ) { // Register inline frontend styles for theme.json block style inheritance public function enqueue_inline_block_style_inheritance() { // Use the new CSS generator class with built-in fallback to inline styles - if ( ! is_admin() && get_option( 'stackable_use_css_files', 'yes' ) === 'yes' ) { + if ( ! is_admin() && ! empty( get_option( 'stackable_use_css_files', true ) ) ) { Stackable_Block_Style_Inheritance_CSS_Generator::enqueue_block_inheritance_css_file(); } else { Stackable_Block_Style_Inheritance_CSS_Generator::enqueue_block_inheritance_css_inline(); diff --git a/src/welcome/admin.js b/src/welcome/admin.js index 63ee636319..4bd45cd094 100644 --- a/src/welcome/admin.js +++ b/src/welcome/admin.js @@ -10,6 +10,7 @@ import SVGSectionIcon from './images/settings-icon-section.svg' * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n' +import apiFetch from '@wordpress/api-fetch' import { useEffect, useState, useCallback, useMemo, Suspense, Fragment, } from '@wordpress/element' @@ -144,6 +145,7 @@ const SEARCH_TREE = [ children: [ __( 'Optimize Inline CSS', i18n ), __( 'Lazy Load Images within Carousels', i18n ), + __( 'Generate CSS Files', i18n ), ], }, ], @@ -1163,6 +1165,8 @@ const Optimizations = props => { filteredSearchTree, } = props + const [ isInvalidatingCssFiles, setIsInvalidatingCssFiles ] = useState( false ) + const groups = filteredSearchTree.find( tab => tab.id === 'optimizations' ).groups const optimizations = groups.find( group => group.id === 'optimizations' ) const groupLength = groups.reduce( ( acc, curr ) => acc + curr.children.length, 0 ) @@ -1195,6 +1199,40 @@ const Optimizations = props => { } } help={ __( 'Disable this if you encounter layout or spacing issues when using images inside carousel-type blocks because of image lazy loading.', i18n ) } /> + { + handleSettingsChange( { stackable_use_css_files: value } ) // eslint-disable-line camelcase + } } + help={ + <> +

{ __( 'Generate CSS files for the global design system and block style inheritance. This can improve performance by reducing the number of inline styles and leverages browser caching. Disabling this loads the CSS inline.', i18n ) }

+ { /* Button to invalidate the CSS files */ } + + + } + /> } From b988a44ba155da5ded817bb43feea4464cda7b60 Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 15:44:25 +0800 Subject: [PATCH 14/19] add upgrade path --- src/css-file-generator.php | 11 +++++++++++ src/init.php | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/css-file-generator.php b/src/css-file-generator.php index e312170d3a..2af4037324 100644 --- a/src/css-file-generator.php +++ b/src/css-file-generator.php @@ -394,6 +394,8 @@ public function __construct() { // Register the setting stackable_use_css_files add_action( 'admin_init', array( $this, 'register_use_css_files_setting' ) ); add_action( 'rest_api_init', array( $this, 'register_use_css_files_setting' ) ); + + add_action( 'stackable_early_version_upgraded', 'register_use_css_files_setting_upgraded', 10, 2 ); } /** @@ -413,6 +415,15 @@ public function register_use_css_files_setting() { ); } + /** + * When upgrading from a lower version, disable use CSS files. + */ + public function register_use_css_files_setting_upgraded( $old_version, $new_version ) { + if ( ! empty( $old_version ) && version_compare( $old_version, "3.19.0", "<" ) ) { + update_option( 'stackable_use_css_files', '', 'no' ); + } + } + /** * Register REST API routes. */ diff --git a/src/init.php b/src/init.php index 39dce84349..79cc4013f6 100644 --- a/src/init.php +++ b/src/init.php @@ -117,7 +117,7 @@ public function register_frontend_assets() { } // Enqueue the global CSS file in the frontend. - if ( ! is_admin() && ! empty( get_option( 'stackable_use_css_files', true ) ) ) { + if ( ! is_admin() && get_option( 'stackable_use_css_files', '1' ) === '1' ) { // The enqueue_global_css_file method now has built-in fallback to inline styles // if CSS file generation fails Stackable_Global_Design_System_CSS_Generator::enqueue_global_css_file(); @@ -241,7 +241,7 @@ public function load_frontend_scripts_conditionally( $block_content, $block ) { // Register inline frontend styles for theme.json block style inheritance public function enqueue_inline_block_style_inheritance() { // Use the new CSS generator class with built-in fallback to inline styles - if ( ! is_admin() && ! empty( get_option( 'stackable_use_css_files', true ) ) ) { + if ( ! is_admin() && get_option( 'stackable_use_css_files', '1' ) === '1' ) { Stackable_Block_Style_Inheritance_CSS_Generator::enqueue_block_inheritance_css_file(); } else { Stackable_Block_Style_Inheritance_CSS_Generator::enqueue_block_inheritance_css_inline(); From 7f2213f6b4d35042493fe60afb2f66c68b5ea62a Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 15:57:31 +0800 Subject: [PATCH 15/19] added cache busting --- src/css-file-generator.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/css-file-generator.php b/src/css-file-generator.php index 2af4037324..e369b0d0ee 100644 --- a/src/css-file-generator.php +++ b/src/css-file-generator.php @@ -60,7 +60,11 @@ public static function get_css_file_url() { public static function get_css_file_name() { $css_content = static::generate_css_content(); $content_hash = md5( $css_content ); - return static::get_css_file_prefix() . $content_hash . '.css'; + + // Add a timestamp as cache buster to ensure unique file names + $timestamp = time(); + + return static::get_css_file_prefix() . $content_hash . '-' . $timestamp . '.css'; } /** @@ -214,6 +218,9 @@ public static function invalidate_css_file() { unlink( $old_file_path ); } } + + // Clear the cached file name - next generation will have a new timestamp + delete_option( static::get_cache_option_name() ); } } } From 48f8fac847b188604a1dbac648f3b5169cc7bd93 Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 16:02:26 +0800 Subject: [PATCH 16/19] fixed error --- src/css-file-generator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/css-file-generator.php b/src/css-file-generator.php index e369b0d0ee..987b671c6a 100644 --- a/src/css-file-generator.php +++ b/src/css-file-generator.php @@ -402,7 +402,7 @@ public function __construct() { add_action( 'admin_init', array( $this, 'register_use_css_files_setting' ) ); add_action( 'rest_api_init', array( $this, 'register_use_css_files_setting' ) ); - add_action( 'stackable_early_version_upgraded', 'register_use_css_files_setting_upgraded', 10, 2 ); + add_action( 'stackable_early_version_upgraded', array( $this, 'register_use_css_files_setting_upgraded' ), 10, 2 ); } /** From 0873097c088b86605dabe8cbc95f5625bc8112c4 Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Fri, 1 Aug 2025 17:03:43 +0800 Subject: [PATCH 17/19] when Stackable is newly activated, delete css files previously generated if any --- src/css-file-generator.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/css-file-generator.php b/src/css-file-generator.php index 987b671c6a..23ae167468 100644 --- a/src/css-file-generator.php +++ b/src/css-file-generator.php @@ -437,7 +437,7 @@ public function register_use_css_files_setting_upgraded( $old_version, $new_vers public function register_routes() { register_rest_route( 'stackable/v3', '/invalidate-css-files', array( 'methods' => 'POST', - 'callback' => array( $this, 'invalidate_all_css_files' ), + 'callback' => array( __CLASS__, 'invalidate_all_css_files' ), 'permission_callback' => array( $this, 'check_permissions' ), ) ); } @@ -457,7 +457,7 @@ public function check_permissions() { * @param WP_REST_Request $request The request object. * @return WP_REST_Response|WP_Error */ - public function invalidate_all_css_files( $request ) { + public static function invalidate_all_css_files( $request ) { try { // Clear all CSS caches Stackable_Global_Design_System_CSS_Generator::invalidate_css_file(); @@ -479,4 +479,7 @@ public function invalidate_all_css_files( $request ) { } new Stackable_CSS_File_Generator(); + + // Run on activation to ensure the CSS files are newly generated. + register_activation_hook( STACKABLE_FILE, array( 'Stackable_CSS_File_Generator', 'invalidate_all_css_files' ) ); } \ No newline at end of file From f736922b7e00410faf1f5b035496210ee2921647 Mon Sep 17 00:00:00 2001 From: Benjamin Intal Date: Tue, 5 Aug 2025 01:55:49 +0800 Subject: [PATCH 18/19] Update src/design-library/init.php --- src/design-library/init.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/design-library/init.php b/src/design-library/init.php index 8a78cdba23..f4ba2fc2dc 100644 --- a/src/design-library/init.php +++ b/src/design-library/init.php @@ -30,10 +30,6 @@ public function __construct() { add_action( 'rest_api_init', array( $this, 'register_route' ) ); add_action( 'stackable_delete_design_library_cache', array( $this, 'delete_cache_v3' ) ); - - // DEV NOTE: Commenting this out for now since it is producing server load in the frontend. - // We can re-enable this when we have a better way to register block patterns. - // add_action( 'init', array( $this, 'register_design_pattern' ) ); } public static function validate_string( $value, $request, $param ) { From 645ea01fa19d9477c6690f0d2833451861733d0b Mon Sep 17 00:00:00 2001 From: "bfintal@gmail.com" <> Date: Tue, 5 Aug 2025 14:37:20 +0800 Subject: [PATCH 19/19] load our scripts in the footer so as not to delay rendering --- src/init.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/init.php b/src/init.php index 79cc4013f6..0efe99ec1f 100644 --- a/src/init.php +++ b/src/init.php @@ -300,7 +300,8 @@ public function register_block_editor_assets() { // wp-util for wp.ajax. // wp-plugins & wp-edit-post for Gutenberg plugins. array( 'code-editor', 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-api-fetch', 'wp-util', 'wp-plugins', 'wp-i18n', 'wp-api', 'lodash' ), - STACKABLE_VERSION + STACKABLE_VERSION, + true ); // Backend editor scripts: blocks. @@ -309,7 +310,8 @@ public function register_block_editor_assets() { plugins_url( 'dist/editor_blocks.js', STACKABLE_FILE ), // Depend on the window.stk API. apply_filters( 'stackable_editor_js_dependencies', array( 'ugb-stk' ) ), - STACKABLE_VERSION + STACKABLE_VERSION, + true // Load in footer to avoid render blocking ); // Add translations.