Skip to content

Commit

Permalink
Refactor server-side block support flags support (#24351)
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad committed Aug 6, 2020
1 parent 3ef5849 commit 7c3d2ea
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 260 deletions.
47 changes: 47 additions & 0 deletions lib/block-supports/align.php
@@ -0,0 +1,47 @@
<?php
/**
* Align block support flag.
*
* @package gutenberg
*/

/**
* Registers the attributes block attribute for block types that support it.
*
* @param array $block_type Block Type.
*/
function gutenberg_register_alignment_support( $block_type ) {
$has_align_support = gutenberg_experimental_get( $block_type->supports, array( 'align' ), false );
if ( $has_align_support ) {
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}

$block_type->attributes['align'] = array(
'type' => 'string',
'enum' => array( 'left', 'center', 'right', 'wide', 'full', '' ),
);
}
}

/**
* Add CSS classes for block alignment to the incoming attributes array.
* This will be applied to the block markup in the front-end.
*
* @param array $attributes comprehensive list of attributes to be applied.
* @param array $block_attributes block attributes.
* @param array $block_type Block Type.
* @return array Block alignment CSS classes and inline styles.
*/
function gutenberg_apply_alignment_support( $attributes, $block_attributes, $block_type ) {
$has_align_support = gutenberg_experimental_get( $block_type->supports, array( 'align' ), false );
if ( $has_align_support ) {
$has_block_alignment = array_key_exists( 'align', $block_attributes );

if ( $has_block_alignment ) {
$attributes['css_classes'][] = sprintf( 'align%s', $block_attributes['align'] );
}
}

return $attributes;
}
94 changes: 94 additions & 0 deletions lib/block-supports/colors.php
@@ -0,0 +1,94 @@
<?php
/**
* Colors block support flag.
*
* @package gutenberg
*/

/**
* Add CSS classes and inline styles for colors to the incoming attributes array.
* This will be applied to the block markup in the front-end.
*
* @param array $attributes comprehensive list of attributes to be applied.
* @param array $block_attributes block attributes.
* @param array $block_type Block type.
* @return array Colors CSS classes and inline styles.
*/
function gutenberg_apply_colors_support( $attributes, $block_attributes, $block_type ) {
$color_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalColor' ), false );
$has_text_colors_support = is_array( $color_support ) || $color_support;
$has_background_colors_support = $has_text_colors_support;
$has_link_colors_support = $has_text_colors_support && gutenberg_experimental_get( $color_support, array( 'linkColor' ), false );
$has_gradients_support = $has_text_colors_support && gutenberg_experimental_get( $color_support, array( 'gradients' ), false );

// Text Colors.
// Check support for text colors.
if ( $has_text_colors_support ) {
$has_named_text_color = array_key_exists( 'textColor', $block_attributes );
$has_custom_text_color = isset( $block_attributes['style']['color']['text'] );

// Apply required generic class.
if ( $has_custom_text_color || $has_named_text_color ) {
$attributes['css_classes'][] = 'has-text-color';
}
// Apply color class or inline style.
if ( $has_named_text_color ) {
$attributes['css_classes'][] = sprintf( 'has-%s-color', $block_attributes['textColor'] );
} elseif ( $has_custom_text_color ) {
$attributes['inline_styles'][] = sprintf( 'color: %s;', $block_attributes['style']['color']['text'] );
}
}

// Link Colors.
if ( $has_link_colors_support ) {
$has_link_color = isset( $block_attributes['style']['color']['link'] );
// Apply required class and style.
if ( $has_link_color ) {
$attributes['css_classes'][] = 'has-link-color';
// If link is a named color.
if ( strpos( $block_attributes['style']['color']['link'], 'var:preset|color|' ) !== false ) {
// Get the name from the string and add proper styles.
$index_to_splice = strrpos( $block_attributes['style']['color']['link'], '|' ) + 1;
$link_color_name = substr( $block_attributes['style']['color']['link'], $index_to_splice );
$attributes['inline_styles'][] = sprintf( '--wp--style--color--link:var(--wp--preset--color--%s);', $link_color_name );
} else {
$attributes['inline_styles'][] = sprintf( '--wp--style--color--link: %s;', $block_attributes['style']['color']['link'] );
}
}
}

// Background Colors.
if ( $has_background_colors_support ) {
$has_named_background_color = array_key_exists( 'backgroundColor', $block_attributes );
$has_custom_background_color = isset( $block_attributes['style']['color']['background'] );

// Apply required background class.
if ( $has_custom_background_color || $has_named_background_color ) {
$attributes['css_classes'][] = 'has-background';
}
// Apply background color classes or styles.
if ( $has_named_background_color ) {
$attributes['css_classes'][] = sprintf( 'has-%s-background-color', $block_attributes['backgroundColor'] );
} elseif ( $has_custom_background_color ) {
$attributes['inline_styles'][] = sprintf( 'background-color: %s;', $block_attributes['style']['color']['background'] );
}
}

// Gradients.
if ( $has_gradients_support ) {
$has_named_gradient = array_key_exists( 'gradient', $block_attributes );
$has_custom_gradient = isset( $block_attributes['style']['color']['gradient'] );

if ( $has_named_gradient || $has_custom_gradient ) {
$attributes['css_classes'][] = 'has-background';
}
// Apply required background class.
if ( $has_named_gradient ) {
$attributes['css_classes'][] = sprintf( 'has-%s-gradient-background', $block_attributes['gradient'] );
} elseif ( $has_custom_gradient ) {
$attributes['inline_styles'][] = sprintf( 'background: %s;', $block_attributes['style']['color']['gradient'] );
}
}

return $attributes;
}
89 changes: 89 additions & 0 deletions lib/block-supports/index.php
@@ -0,0 +1,89 @@
<?php
/**
* Block support flags.
*
* @package gutenberg
*/

/**
* Filter the registered blocks to apply the block supports attributes registration.
*/
function gutenberg_register_block_supports() {
$block_registry = WP_Block_Type_Registry::get_instance();
$registered_block_types = $block_registry->get_all_registered();
// Ideally we need a hook to extend the block registration
// instead of mutating the block type.
foreach ( $registered_block_types as $block_type ) {
gutenberg_register_alignment_support( $block_type );
}
}

add_action( 'init', 'gutenberg_register_block_supports', 21 );

/**
* Filters the frontend output of blocks and apply the block support flags transformations.
*
* @param string $block_content rendered block content.
* @param array $block block object.
* @return string filtered block content.
*/
function gutenberg_apply_block_supports( $block_content, $block ) {
if ( ! isset( $block['attrs'] ) ) {
return $block_content;
}

$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
// If no render_callback, assume styles have been previously handled.
if ( ! $block_type || ! $block_type->render_callback ) {
return $block_content;
}

$attributes = array();
$attributes = gutenberg_apply_colors_support( $attributes, $block['attrs'], $block_type );
$attributes = gutenberg_apply_typography_support( $attributes, $block['attrs'], $block_type );
$attributes = gutenberg_apply_alignment_support( $attributes, $block['attrs'], $block_type );

if ( ! count( $attributes ) ) {
return $block_content;
}

$dom = new DOMDocument( '1.0', 'utf-8' );

// Suppress warnings from this method from polluting the front-end.
// @codingStandardsIgnoreStart
if ( ! @$dom->loadHTML( $block_content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_COMPACT ) ) {
// @codingStandardsIgnoreEnd
return $block_content;
}

$xpath = new DOMXPath( $dom );
$block_root = $xpath->query( '/*' )[0];

if ( empty( $block_root ) ) {
return $block_content;
}

// Some inline styles may be added without ending ';', add this if necessary.
$current_styles = trim( $block_root->getAttribute( 'style' ), ' ' );
if ( strlen( $current_styles ) > 0 && substr( $current_styles, -1 ) !== ';' ) {
$current_styles = $current_styles . ';';
};

// Merge and dedupe new and existing classes and styles.
$classes_to_add = esc_attr( implode( ' ', array_key_exists( 'css_classes', $attributes ) ? $attributes['css_classes'] : array() ) );
$styles_to_add = esc_attr( implode( ' ', array_key_exists( 'inline_styles', $attributes ) ? $attributes['inline_styles'] : array() ) );
$new_classes = implode( ' ', array_unique( explode( ' ', ltrim( $block_root->getAttribute( 'class' ) . ' ' ) . $classes_to_add ) ) );
$new_styles = implode( ' ', array_unique( explode( ' ', $current_styles . ' ' . $styles_to_add ) ) );

// Apply new styles and classes.
if ( ! empty( $new_classes ) ) {
$block_root->setAttribute( 'class', $new_classes );
}

if ( ! empty( $new_styles ) ) {
$block_root->setAttribute( 'style', $new_styles );
}

return $dom->saveHtml();
}
add_filter( 'render_block', 'gutenberg_apply_block_supports', 10, 2 );
44 changes: 44 additions & 0 deletions lib/block-supports/typography.php
@@ -0,0 +1,44 @@
<?php
/**
* Typography block support flag.
*
* @package gutenberg
*/

/**
* Add CSS classes and inline styles for font sizes to the incoming attributes array.
* This will be applied to the block markup in the front-end.
*
* @param array $attributes comprehensive list of attributes to be applied.
* @param array $block_attributes block attributes.
* @param array $block_type block type.
* @return array Font size CSS classes and inline styles.
*/
function gutenberg_apply_typography_support( $attributes, $block_attributes, $block_type ) {
$has_font_size_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontSize' ), false );
$has_line_height_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalLineHeight' ), false );

// Font Size.
if ( $has_font_size_support ) {
$has_named_font_size = array_key_exists( 'fontSize', $block_attributes );
$has_custom_font_size = isset( $block_attributes['style']['typography']['fontSize'] );

// Apply required class or style.
if ( $has_named_font_size ) {
$attributes['css_classes'][] = sprintf( 'has-%s-font-size', $block_attributes['fontSize'] );
} elseif ( $has_custom_font_size ) {
$attributes['inline_styles'][] = sprintf( 'font-size: %spx;', $block_attributes['style']['typography']['fontSize'] );
}
}

// Line Height.
if ( $has_line_height_support ) {
$has_line_height = isset( $block_attributes['style']['typography']['lineHeight'] );
// Add the style (no classes for line-height).
if ( $has_line_height ) {
$attributes['inline_styles'][] = sprintf( 'line-height: %s;', $block_attributes['style']['typography']['lineHeight'] );
}
}

return $attributes;
}

0 comments on commit 7c3d2ea

Please sign in to comment.