Skip to content

Commit

Permalink
Add block support to apply block style variation element and inner bl…
Browse files Browse the repository at this point in the history
…ock styles
  • Loading branch information
aaronrobertshaw committed Feb 6, 2024
1 parent e2135e5 commit 5a14cb8
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 1 deletion.
118 changes: 118 additions & 0 deletions lib/block-supports/variations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php
/**
* Block support to enable per-section styling of block types via
* block style variations.
*
* @package gutenberg
*/

/**
* Get the class name for this application of this blocks variation styles.
*
* @param array $block Block object.
* @param string $variation Slug for the variation..
*
* @return string The unique class name.
*/
function gutenberg_get_variation_class_name( $block, $variation ) {
return 'is-style-' . $variation . '-' . md5( serialize( $block ) );
}

/**
* Update the block content with the variation's class name.
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
*
* @return string Filtered block content.
*/
function gutenberg_render_variation_support( $block_content, $block ) {
if ( ! $block_content || empty( $block['attrs'] ) ) {
return $block_content;
}

// Apply the variation's classname. Like the layout hook, this assumes the
// hook only applies to blocks with a single wrapper.
$tags = new WP_HTML_Tag_Processor( $block_content );

if ( $tags->next_tag() ) {
preg_match( '/\bis-style-(\S+)\b/', $tags->get_attribute( 'class' ), $matches );
$variation = $matches[1] ?? null;

if ( $variation ) {
$tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data();
$theme_json = $tree->get_raw_data();

if ( ! empty( $theme_json['styles']['blocks'][ $block['blockName'] ]['variations'][ $variation ] ) ) {
$tags->add_class( gutenberg_get_variation_class_name( $block, $variation ) );
}
}
}

return $tags->get_updated_html();
}

/**
* Render the block style variation's styles.
*
* In the case of nested blocks with variations applies, we want the parent
* variation's styles to be rendered before their descendants. This solves the
* issue of a block type being styled in both the parent and descendant: we want
* the descendant style to take priority, and this is done by loading it after,
* in the DOM order. This is why the variation stylesheet generation is in a
* different filter.
*
* @param string|null $pre_render The pre-rendered content. Default null.
* @param array $block The block being rendered.
*
* @return null
*/
function gutenberg_render_variation_support_styles( $pre_render, $block ) {
$variation = $block['attrs']['style']['variation'] ?? null;

if ( ! $variation ) {
return null;
}

$tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data();
$theme_json = $tree->get_raw_data();
$variation_data = $theme_json['styles']['blocks'][ $block['blockName'] ]['variations'][ $variation ] ?? array();

if ( empty( $variation_data['elements'] ) && empty( $variation_data['blocks'] ) ) {
return null;
}

$config = array(
'version' => 2,
'styles' => $variation_data,
);

$class_name = gutenberg_get_variation_class_name( $block, $variation );
$class_name = ".$class_name";

$variation_theme_json = new WP_Theme_JSON_Gutenberg( $config, 'blocks' );
$variation_styles = $variation_theme_json->get_stylesheet(
array( 'styles' ),
array( 'custom' ),
array(
'root_selector' => $class_name,
'skip_root_layout_styles' => true,
'scope' => $class_name,
)
);

if ( empty( $variation_styles ) ) {
return null;
}

wp_register_style( 'variation-styles', false );
wp_add_inline_style( 'variation-styles', $variation_styles );
wp_enqueue_style( 'variation-styles' );
}


// Register the block support.
WP_Block_Supports::get_instance()->register( 'variation', array() );

add_filter( 'pre_render_block', 'gutenberg_render_variation_support_styles', 10, 2 );
add_filter( 'render_block', 'gutenberg_render_variation_support', 10, 2 );
2 changes: 1 addition & 1 deletion lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -1267,7 +1267,7 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets'
}

if ( in_array( 'styles', $types, true ) ) {
if ( false !== $root_style_key ) {
if ( false !== $root_style_key && empty( $options['skip_root_layout_styles'] ) ) {
$stylesheet .= $this->get_root_layout_rules( $style_nodes[ $root_style_key ]['selector'], $style_nodes[ $root_style_key ] );
}
$stylesheet .= $this->get_block_classes( $style_nodes );
Expand Down
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/block-supports/duotone.php';
require __DIR__ . '/block-supports/shadow.php';
require __DIR__ . '/block-supports/background.php';
require __DIR__ . '/block-supports/variations.php';

// Data views.
require_once __DIR__ . '/experimental/data-views.php';

0 comments on commit 5a14cb8

Please sign in to comment.