Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the style property of block.json to be an array and add support for object-based block styles #2853

Closed
Closed
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
00bfe03
Allow the style property of block.json to be an array
adamziel Jun 22, 2022
92f6635
Refactor the other use of _register_single_block_style_handle
adamziel Jun 22, 2022
277603c
Filter out arrays of styles before enqueuing them in class-wp-block.php
adamziel Jun 22, 2022
6eb4626
Do not flatten the styles array in block_type_metadata filter
adamziel Jun 23, 2022
2acd65b
Clarify the docstring
adamziel Jun 23, 2022
127aac5
Clarify the intention of not processing arrays
adamziel Jun 23, 2022
b58f2e7
Clarify the intention
adamziel Jun 23, 2022
14116bb
Further clarify the intention
adamziel Jun 23, 2022
61e2828
Handle style arrays in block-editor.php
adamziel Jun 23, 2022
4b668b0
Handle style arrays in script-loader.php
adamziel Jun 23, 2022
eeb8ede
Adjust code style to avoid requesting block name in the test_handle_p…
adamziel Jun 23, 2022
37113d9
Do not assume 'file' is an exisitng key
adamziel Jun 23, 2022
d70e683
Add comments, rename _register_single_block_style_handle to register_…
adamziel Jun 24, 2022
e034805
Register all string style handles, not just the first one
adamziel Jun 27, 2022
7e086ef
Add array sypport to WP_Block_Type and WP_Rest_Block_Types_Controller
adamziel Jun 29, 2022
438a35b
Add support for editor_styles
adamziel Jun 29, 2022
e4fc856
Delete _wp_multiple_block_styles now that multiple styles are handled
adamziel Jun 29, 2022
3bdb544
Normalize styles format to a list
adamziel Jun 29, 2022
da476d2
Add docstring to _wp_normalize_block_styles_from_mixed_format_to_array
adamziel Jun 29, 2022
ce39fb7
Move the argument normalization inside of WP_Block_Type class
adamziel Jun 29, 2022
c9f0d13
Support array-based styles in register_block_style_handle and add uni…
adamziel Jun 29, 2022
81f13cb
Add an empty _wp_multiple_block_styles function
adamziel Jun 29, 2022
994938f
Add debug statement to see the provlem in the CI
adamziel Jun 29, 2022
c44ba77
Update docs
adamziel Jun 29, 2022
b8ab9d0
Fix last test failures
adamziel Jun 29, 2022
124b4ad
Add @since to normalize_block_styles_from_mixed_format_to_array
adamziel Jun 29, 2022
2c396ae
Merge branch 'trunk' into allow-style-arrays-in-block-json
adamziel Jul 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/wp-includes/block-editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,19 @@ function _wp_get_iframed_editor_assets() {

foreach ( $block_registry->get_all_registered() as $block_type ) {
if ( ! empty( $block_type->style ) ) {
$style_handles[] = $block_type->style;
foreach ( $block_type->style as $single_style ) {
if ( is_string( $single_style ) ) {
$style_handles[] = $single_style;
}
}
}

if ( ! empty( $block_type->editor_style ) ) {
$style_handles[] = $block_type->editor_style;
foreach ( $block_type->editor_style as $single_style ) {
if ( is_string( $single_style ) ) {
$style_handles[] = $single_style;
}
}
}

if ( ! empty( $block_type->script ) ) {
Expand Down
119 changes: 59 additions & 60 deletions src/wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,54 +142,96 @@ function register_block_script_handle( $metadata, $field_name ) {
/**
* Finds a style handle for the block metadata field. It detects when a path
* to file was provided and registers the style under automatically
* generated handle name. It returns unprocessed style handle otherwise.
* generated handle name.
*
* @since 5.5.0
* @since 6.1.0 Accepts arrays as $metadata[ $field_name ].
*
* @param array $metadata Block metadata.
* @param string $field_name Field name to pick from metadata.
* @return string|false Style handle provided directly or created through
* style's registration, or false on failure.
* @return array|string|false Style handle provided directly or created through
* style's registration, or false on failure.
* If $metadata[ $field_name ] is an array, this function
* only maps that array to replace the stylesheet paths
* with registered style handles.
*/
function register_block_style_handle( $metadata, $field_name ) {
if ( empty( $metadata[ $field_name ] ) ) {
return false;
}
$style_data = $metadata[ $field_name ];
if ( ! is_array( $style_data ) ) {
return register_single_style_handle_for_block( $metadata, $field_name, $style_data );
}

/*
* $style_data is a list of stylesheet paths and
* style arrays such as { "color": { "text": "#fff" } }.
*
* In here, we replace the stylesheet paths with registered style handles.
*/
$handles = array();
foreach ( $style_data as $style_item ) {
if ( is_array( $style_item ) ) {
$handles[] = $style_item;
} else {
$handles[] = register_single_style_handle_for_block( $metadata, $field_name, $style_item );
}
}

return $handles;
}

/**
* Finds a style handle for the block metadata field. It detects when a path
* to file was provided and registers the style under automatically
* generated handle name. It returns unprocessed style handle otherwise.
*
* @since 6.1.0
*
* @param array $metadata Block metadata.
* @param string $field_name Field name to append to the generated style handle.
* @param string $style_data Style information. Can either be a path or an array of block styles.
* @return string|false Style handle provided directly or created through
* style's registration, or false on failure.
*/
function register_single_style_handle_for_block( $metadata, $field_name, $style_data ) {
$wpinc_path_norm = wp_normalize_path( realpath( ABSPATH . WPINC ) );
$theme_path_norm = wp_normalize_path( get_theme_file_path() );
$is_core_block = isset( $metadata['file'] ) && 0 === strpos( $metadata['file'], $wpinc_path_norm );

$block_json_file_path = isset( $metadata['file'] ) ? $metadata['file'] : null;
$is_core_block = $block_json_file_path && 0 === strpos( $block_json_file_path, $wpinc_path_norm );
$version = ! $is_core_block && isset( $metadata['version'] ) ? $metadata['version'] : false;

if ( $is_core_block && ! wp_should_load_separate_core_block_assets() ) {
return false;
}

// Check whether styles should have a ".min" suffix or not.
$suffix = SCRIPT_DEBUG ? '' : '.min';

$style_handle = $metadata[ $field_name ];
$style_path = remove_block_asset_path_prefix( $metadata[ $field_name ] );

if ( $style_handle === $style_path && ! $is_core_block ) {
return $style_handle;
$suffix = SCRIPT_DEBUG ? '' : '.min';
$style_path = remove_block_asset_path_prefix( $style_data );
if ( $style_data === $style_path && ! $is_core_block ) {
return $style_data;
}

$style_uri = plugins_url( $style_path, $metadata['file'] );
$block_name = $metadata['name'];
$style_uri = plugins_url( $style_path, $block_json_file_path );
if ( $is_core_block ) {
$style_path = "style$suffix.css";
$style_uri = includes_url( 'blocks/' . str_replace( 'core/', '', $metadata['name'] ) . "/style$suffix.css" );
$style_uri = includes_url( 'blocks/' . str_replace( 'core/', '', $block_name ) . "/style$suffix.css" );
}

$style_path_norm = wp_normalize_path( realpath( dirname( $metadata['file'] ) . '/' . $style_path ) );
$style_path_norm = wp_normalize_path( realpath( dirname( $block_json_file_path ) . '/' . $style_path ) );
$is_theme_block = 0 === strpos( $style_path_norm, $theme_path_norm );

if ( $is_theme_block ) {
$style_uri = get_theme_file_uri( str_replace( $theme_path_norm, '', $style_path_norm ) );
}

$style_handle = generate_block_asset_handle( $metadata['name'], $field_name );
$block_dir = dirname( $metadata['file'] );
$style_handle = generate_block_asset_handle( $block_name, $field_name );
$block_dir = dirname( $block_json_file_path );
$style_file = realpath( "$block_dir/$style_path" );
$has_style_file = false !== $style_file;
$version = ! $is_core_block && isset( $metadata['version'] ) ? $metadata['version'] : false;
$style_uri = $has_style_file ? $style_uri : false;
$result = wp_register_style(
$style_handle,
Expand Down Expand Up @@ -1228,49 +1270,6 @@ function get_query_pagination_arrow( $block, $is_next ) {
return null;
}

/**
* Allows multiple block styles.
*
* @since 5.9.0
*
* @param array $metadata Metadata for registering a block type.
* @return array Metadata for registering a block type.
*/
function _wp_multiple_block_styles( $metadata ) {
foreach ( array( 'style', 'editorStyle' ) as $key ) {
if ( ! empty( $metadata[ $key ] ) && is_array( $metadata[ $key ] ) ) {
$default_style = array_shift( $metadata[ $key ] );
foreach ( $metadata[ $key ] as $handle ) {
$args = array( 'handle' => $handle );
if ( 0 === strpos( $handle, 'file:' ) && isset( $metadata['file'] ) ) {
$style_path = remove_block_asset_path_prefix( $handle );
$theme_path_norm = wp_normalize_path( get_theme_file_path() );
$style_path_norm = wp_normalize_path( realpath( dirname( $metadata['file'] ) . '/' . $style_path ) );
$is_theme_block = isset( $metadata['file'] ) && 0 === strpos( $metadata['file'], $theme_path_norm );

$style_uri = plugins_url( $style_path, $metadata['file'] );

if ( $is_theme_block ) {
$style_uri = get_theme_file_uri( str_replace( $theme_path_norm, '', $style_path_norm ) );
}

$args = array(
'handle' => sanitize_key( "{$metadata['name']}-{$style_path}" ),
'src' => $style_uri,
);
}

wp_enqueue_block_style( $metadata['name'], $args );
}

// Only return the 1st item in the array.
$metadata[ $key ] = $default_style;
}
}
return $metadata;
}
add_filter( 'block_type_metadata', '_wp_multiple_block_styles' );

/**
* Helper function that constructs a comment query vars array from the passed
* block properties.
Expand Down
96 changes: 70 additions & 26 deletions src/wp-includes/class-wp-block-type.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,32 +235,32 @@ class WP_Block_Type {
* Optional. Array or string of arguments for registering a block type. Any arguments may be defined,
* however the ones described below are supported by default. Default empty array.
*
* @type string $api_version Block API version.
* @type string $title Human-readable block type label.
* @type string|null $category Block type category classification, used in
* search interfaces to arrange block types by category.
* @type array|null $parent Setting parent lets a block require that it is only
* available when nested within the specified blocks.
* @type array|null $ancestor Setting ancestor makes a block available only inside the specified
* block types at any position of the ancestor's block subtree.
* @type string|null $icon Block type icon.
* @type string $description A detailed block type description.
* @type string[] $keywords Additional keywords to produce block type as
* result in search interfaces.
* @type string|null $textdomain The translation textdomain.
* @type array $styles Alternative block styles.
* @type array $variations Block variations.
* @type array|null $supports Supported features.
* @type array|null $example Structured data for the block preview.
* @type callable|null $render_callback Block type render callback.
* @type array|null $attributes Block type attributes property schemas.
* @type array $uses_context Context values inherited by blocks of this type.
* @type array|null $provides_context Context provided by blocks of this type.
* @type string|null $editor_script Block type editor only script handle.
* @type string|null $script Block type front end and editor script handle.
* @type string|null $view_script Block type front end only script handle.
* @type string|null $editor_style Block type editor only style handle.
* @type string|null $style Block type front end and editor style handle.
* @type string $api_version Block API version.
* @type string $title Human-readable block type label.
* @type string|null $category Block type category classification, used in
* search interfaces to arrange block types by category.
* @type array|null $parent Setting parent lets a block require that it is only
* available when nested within the specified blocks.
* @type array|null $ancestor Setting ancestor makes a block available only inside the specified
* block types at any position of the ancestor's block subtree.
* @type string|null $icon Block type icon.
* @type string $description A detailed block type description.
* @type string[] $keywords Additional keywords to produce block type as
* result in search interfaces.
* @type string|null $textdomain The translation textdomain.
* @type array $styles Alternative block styles.
* @type array $variations Block variations.
* @type array|null $supports Supported features.
* @type array|null $example Structured data for the block preview.
* @type callable|null $render_callback Block type render callback.
* @type array|null $attributes Block type attributes property schemas.
* @type array $uses_context Context values inherited by blocks of this type.
* @type array|null $provides_context Context provided by blocks of this type.
* @type string|null $editor_script Block type editor only script handle.
* @type string|null $script Block type front end and editor script handle.
* @type string|null $view_script Block type front end only script handle.
* @type array|string|null $editor_style Block type editor only style handle.
adamziel marked this conversation as resolved.
Show resolved Hide resolved
* @type array|string|null $style Block type front end and editor style handle.
* }
*/
public function __construct( $block_type, $args = array() ) {
Expand Down Expand Up @@ -405,3 +405,47 @@ public function get_attributes() {
array();
}
}

function _wp_normalize_block_styles_from_mixed_format_to_array( $args ) {
adamziel marked this conversation as resolved.
Show resolved Hide resolved
foreach ( $args as $property_name => $property_value ) {
/*
* The style and editor_style properties may be defined in any of the following ways:
*
* String handle:
* { "style": "my-block" }
*
* Style definition:
* { "style": { "color": { "text": "#fff" } } }
*
* An array with a string handle:
* { "style": [ "my-block" ] }
*
* A mixed array of string handle and style definitions:
* { "style": [ "my-block", { "color": { "text": "#fff" } } ] }
*
* That's a lot of work for the developer to handle, so we'll handle it for them.
* The code below always stores the styles in the mixed array format.
*/
if (
! is_null( $property_value ) &&
in_array( $property_name, array( 'style', 'editor_style' ), true )
) {
/*
* Tests for an associative array.
* * true if the value is like array("color" => ...)
* * false if the value is like array("handle", array())
*/
$is_style_definition = is_array( $property_value ) && count( array_filter( array_keys( $property_value ), 'is_string' ) ) > 0;
$is_style_handle = is_string( $property_value );
$is_style_element = $is_style_definition || $is_style_handle;

if ( $is_style_element ) {
$args[ $property_name ] = array( $property_value );
}
}
}

return $args;
}

add_filter( 'register_block_type_args', '_wp_normalize_block_styles_from_mixed_format_to_array', 10 );
12 changes: 11 additions & 1 deletion src/wp-includes/class-wp-block.php
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,17 @@ public function render( $options = array() ) {
}

if ( ! empty( $this->block_type->style ) ) {
wp_enqueue_style( $this->block_type->style );
/*
* $this->block_type->style is a list of stylesheet handles and
* style arrays such as { "color": { "text": "#fff" } }.
*
* This code enqueues the stylesheet handles and omit the style arrays.
*/
foreach ( $this->block_type->style as $handle_maybe ) {
if ( is_string( $handle_maybe ) ) {
wp_enqueue_style( $handle_maybe );
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -536,14 +536,14 @@ public function get_item_schema() {
),
'editor_style' => array(
'description' => __( 'Editor style handle.' ),
'type' => array( 'string', 'null' ),
'type' => array( 'array', 'string', 'null' ),
'default' => null,
'context' => array( 'embed', 'view', 'edit' ),
'readonly' => true,
),
'style' => array(
'description' => __( 'Public facing and editor style handle.' ),
'type' => array( 'string', 'null' ),
'type' => array( 'array', 'string', 'null' ),
'default' => null,
'context' => array( 'embed', 'view', 'edit' ),
'readonly' => true,
Expand Down
12 changes: 10 additions & 2 deletions src/wp-includes/script-loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -2502,7 +2502,11 @@ function wp_enqueue_registered_block_scripts_and_styles() {
foreach ( $block_registry->get_all_registered() as $block_name => $block_type ) {
// Front-end styles.
if ( ! empty( $block_type->style ) ) {
wp_enqueue_style( $block_type->style );
foreach ( $block_type->style as $single_style ) {
if ( is_string( $single_style ) ) {
wp_enqueue_style( $single_style );
}
}
}

// Front-end script.
Expand All @@ -2512,7 +2516,11 @@ function wp_enqueue_registered_block_scripts_and_styles() {

// Editor styles.
if ( $load_editor_scripts && ! empty( $block_type->editor_style ) ) {
wp_enqueue_style( $block_type->editor_style );
foreach ( $block_type->editor_style as $single_style ) {
if ( is_string( $single_style ) ) {
wp_enqueue_style( $single_style );
}
}
}

// Editor script.
Expand Down