first commit

This commit is contained in:
CHIEFSOFT\ameye
2023-12-28 16:20:07 -05:00
commit b114fdf4fa
5377 changed files with 1850677 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
<?php
/**
* Align block support flag.
*
* @package WordPress
* @since 5.6.0
*/
/**
* Registers the align block attribute for block types that support it.
*
* @since 5.6.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_alignment_support( $block_type ) {
$has_align_support = block_has_support( $block_type, array( 'align' ), false );
if ( $has_align_support ) {
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
if ( ! array_key_exists( 'align', $block_type->attributes ) ) {
$block_type->attributes['align'] = array(
'type' => 'string',
'enum' => array( 'left', 'center', 'right', 'wide', 'full', '' ),
);
}
}
}
/**
* Adds CSS classes for block alignment to the incoming attributes array.
* This will be applied to the block markup in the front-end.
*
* @since 5.6.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
* @param array $block_attributes Block attributes.
* @return array Block alignment CSS classes and inline styles.
*/
function wp_apply_alignment_support( $block_type, $block_attributes ) {
$attributes = array();
$has_align_support = block_has_support( $block_type, array( 'align' ), false );
if ( $has_align_support ) {
$has_block_alignment = array_key_exists( 'align', $block_attributes );
if ( $has_block_alignment ) {
$attributes['class'] = sprintf( 'align%s', $block_attributes['align'] );
}
}
return $attributes;
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'align',
array(
'register_attribute' => 'wp_register_alignment_support',
'apply' => 'wp_apply_alignment_support',
)
);
+182
View File
@@ -0,0 +1,182 @@
<?php
/**
* Border block support flag.
*
* @package WordPress
* @since 5.8.0
*/
/**
* Registers the style attribute used by the border feature if needed for block
* types that support borders.
*
* @since 5.8.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_border_support( $block_type ) {
// Determine if any border related features are supported.
$has_border_support = block_has_support( $block_type, array( '__experimentalBorder' ) );
$has_border_color_support = wp_has_border_feature_support( $block_type, 'color' );
// Setup attributes and styles within that if needed.
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
if ( $has_border_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
if ( $has_border_color_support && ! array_key_exists( 'borderColor', $block_type->attributes ) ) {
$block_type->attributes['borderColor'] = array(
'type' => 'string',
);
}
}
/**
* Adds CSS classes and inline styles for border styles to the incoming
* attributes array. This will be applied to the block markup in the front-end.
*
* @since 5.8.0
* @access private
*
* @param WP_Block_Type $block_type Block type.
* @param array $block_attributes Block attributes.
* @return array Border CSS classes and inline styles.
*/
function wp_apply_border_support( $block_type, $block_attributes ) {
if ( wp_should_skip_block_supports_serialization( $block_type, 'border' ) ) {
return array();
}
$classes = array();
$styles = array();
// Border radius.
if (
wp_has_border_feature_support( $block_type, 'radius' ) &&
isset( $block_attributes['style']['border']['radius'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'radius' )
) {
$border_radius = $block_attributes['style']['border']['radius'];
if ( is_array( $border_radius ) ) {
// We have individual border radius corner values.
foreach ( $border_radius as $key => $radius ) {
// Convert CamelCase corner name to kebab-case.
$corner = strtolower( preg_replace( '/(?<!^)[A-Z]/', '-$0', $key ) );
$styles[] = sprintf( 'border-%s-radius: %s;', $corner, $radius );
}
} else {
// This check handles original unitless implementation.
if ( is_numeric( $border_radius ) ) {
$border_radius .= 'px';
}
$styles[] = sprintf( 'border-radius: %s;', $border_radius );
}
}
// Border style.
if (
wp_has_border_feature_support( $block_type, 'style' ) &&
isset( $block_attributes['style']['border']['style'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' )
) {
$border_style = $block_attributes['style']['border']['style'];
$styles[] = sprintf( 'border-style: %s;', $border_style );
}
// Border width.
if (
wp_has_border_feature_support( $block_type, 'width' ) &&
isset( $block_attributes['style']['border']['width'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' )
) {
$border_width = $block_attributes['style']['border']['width'];
// This check handles original unitless implementation.
if ( is_numeric( $border_width ) ) {
$border_width .= 'px';
}
$styles[] = sprintf( 'border-width: %s;', $border_width );
}
// Border color.
if (
wp_has_border_feature_support( $block_type, 'color' ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' )
) {
$has_named_border_color = array_key_exists( 'borderColor', $block_attributes );
$has_custom_border_color = isset( $block_attributes['style']['border']['color'] );
if ( $has_named_border_color || $has_custom_border_color ) {
$classes[] = 'has-border-color';
}
if ( $has_named_border_color ) {
$classes[] = sprintf( 'has-%s-border-color', $block_attributes['borderColor'] );
} elseif ( $has_custom_border_color ) {
$border_color = $block_attributes['style']['border']['color'];
$styles[] = sprintf( 'border-color: %s;', $border_color );
}
}
// Collect classes and styles.
$attributes = array();
if ( ! empty( $classes ) ) {
$attributes['class'] = implode( ' ', $classes );
}
if ( ! empty( $styles ) ) {
$attributes['style'] = implode( ' ', $styles );
}
return $attributes;
}
/**
* Checks whether the current block type supports the border feature requested.
*
* If the `__experimentalBorder` support flag is a boolean `true` all border
* support features are available. Otherwise, the specific feature's support
* flag nested under `experimentalBorder` must be enabled for the feature
* to be opted into.
*
* @since 5.8.0
* @access private
*
* @param WP_Block_Type $block_type Block type to check for support.
* @param string $feature Name of the feature to check support for.
* @param mixed $default_value Fallback value for feature support, defaults to false.
* @return bool Whether the feature is supported.
*/
function wp_has_border_feature_support( $block_type, $feature, $default_value = false ) {
// Check if all border support features have been opted into via `"__experimentalBorder": true`.
if (
property_exists( $block_type, 'supports' ) &&
( true === _wp_array_get( $block_type->supports, array( '__experimentalBorder' ), $default_value ) )
) {
return true;
}
// Check if the specific feature has been opted into individually
// via nested flag under `__experimentalBorder`.
return block_has_support( $block_type, array( '__experimentalBorder', $feature ), $default_value );
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'border',
array(
'register_attribute' => 'wp_register_border_support',
'apply' => 'wp_apply_border_support',
)
);
+158
View File
@@ -0,0 +1,158 @@
<?php
/**
* Colors block support flag.
*
* @package WordPress
* @since 5.6.0
*/
/**
* Registers the style and colors block attributes for block types that support it.
*
* @since 5.6.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_colors_support( $block_type ) {
$color_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$color_support = _wp_array_get( $block_type->supports, array( 'color' ), false );
}
$has_text_colors_support = true === $color_support || ( is_array( $color_support ) && _wp_array_get( $color_support, array( 'text' ), true ) );
$has_background_colors_support = true === $color_support || ( is_array( $color_support ) && _wp_array_get( $color_support, array( 'background' ), true ) );
$has_gradients_support = _wp_array_get( $color_support, array( 'gradients' ), false );
$has_link_colors_support = _wp_array_get( $color_support, array( 'link' ), false );
$has_color_support = $has_text_colors_support ||
$has_background_colors_support ||
$has_gradients_support ||
$has_link_colors_support;
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
if ( $has_color_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
if ( $has_background_colors_support && ! array_key_exists( 'backgroundColor', $block_type->attributes ) ) {
$block_type->attributes['backgroundColor'] = array(
'type' => 'string',
);
}
if ( $has_text_colors_support && ! array_key_exists( 'textColor', $block_type->attributes ) ) {
$block_type->attributes['textColor'] = array(
'type' => 'string',
);
}
if ( $has_gradients_support && ! array_key_exists( 'gradient', $block_type->attributes ) ) {
$block_type->attributes['gradient'] = array(
'type' => 'string',
);
}
}
/**
* 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.
*
* @since 5.6.0
* @access private
*
* @param WP_Block_Type $block_type Block type.
* @param array $block_attributes Block attributes.
*
* @return array Colors CSS classes and inline styles.
*/
function wp_apply_colors_support( $block_type, $block_attributes ) {
$color_support = _wp_array_get( $block_type->supports, array( 'color' ), false );
if (
is_array( $color_support ) &&
wp_should_skip_block_supports_serialization( $block_type, 'color' )
) {
return array();
}
$has_text_colors_support = true === $color_support || ( is_array( $color_support ) && _wp_array_get( $color_support, array( 'text' ), true ) );
$has_background_colors_support = true === $color_support || ( is_array( $color_support ) && _wp_array_get( $color_support, array( 'background' ), true ) );
$has_gradients_support = _wp_array_get( $color_support, array( 'gradients' ), false );
$classes = array();
$styles = array();
// Text colors.
// Check support for text colors.
if ( $has_text_colors_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'text' ) ) {
$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 ) {
$classes[] = 'has-text-color';
}
// Apply color class or inline style.
if ( $has_named_text_color ) {
$classes[] = sprintf( 'has-%s-color', _wp_to_kebab_case( $block_attributes['textColor'] ) );
} elseif ( $has_custom_text_color ) {
$styles[] = sprintf( 'color: %s;', $block_attributes['style']['color']['text'] );
}
}
// Background colors.
if ( $has_background_colors_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'background' ) ) {
$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 ) {
$classes[] = 'has-background';
}
// Apply background color classes or styles.
if ( $has_named_background_color ) {
$classes[] = sprintf( 'has-%s-background-color', _wp_to_kebab_case( $block_attributes['backgroundColor'] ) );
} elseif ( $has_custom_background_color ) {
$styles[] = sprintf( 'background-color: %s;', $block_attributes['style']['color']['background'] );
}
}
// Gradients.
if ( $has_gradients_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'gradients' ) ) {
$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 ) {
$classes[] = 'has-background';
}
// Apply required background class.
if ( $has_named_gradient ) {
$classes[] = sprintf( 'has-%s-gradient-background', _wp_to_kebab_case( $block_attributes['gradient'] ) );
} elseif ( $has_custom_gradient ) {
$styles[] = sprintf( 'background: %s;', $block_attributes['style']['color']['gradient'] );
}
}
$attributes = array();
if ( ! empty( $classes ) ) {
$attributes['class'] = implode( ' ', $classes );
}
if ( ! empty( $styles ) ) {
$attributes['style'] = implode( ' ', $styles );
}
return $attributes;
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'colors',
array(
'register_attribute' => 'wp_register_colors_support',
'apply' => 'wp_apply_colors_support',
)
);
@@ -0,0 +1,65 @@
<?php
/**
* Custom classname block support flag.
*
* @package WordPress
* @since 5.6.0
*/
/**
* Registers the custom classname block attribute for block types that support it.
*
* @since 5.6.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_custom_classname_support( $block_type ) {
$has_custom_classname_support = block_has_support( $block_type, array( 'customClassName' ), true );
if ( $has_custom_classname_support ) {
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
if ( ! array_key_exists( 'className', $block_type->attributes ) ) {
$block_type->attributes['className'] = array(
'type' => 'string',
);
}
}
}
/**
* Add the custom classnames to the output.
*
* @since 5.6.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
* @param array $block_attributes Block attributes.
*
* @return array Block CSS classes and inline styles.
*/
function wp_apply_custom_classname_support( $block_type, $block_attributes ) {
$has_custom_classname_support = block_has_support( $block_type, array( 'customClassName' ), true );
$attributes = array();
if ( $has_custom_classname_support ) {
$has_custom_classnames = array_key_exists( 'className', $block_attributes );
if ( $has_custom_classnames ) {
$attributes['class'] = $block_attributes['className'];
}
}
return $attributes;
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'custom-classname',
array(
'register_attribute' => 'wp_register_custom_classname_support',
'apply' => 'wp_apply_custom_classname_support',
)
);
+73
View File
@@ -0,0 +1,73 @@
<?php
/**
* Dimensions block support flag.
*
* This does not include the `spacing` block support even though that visually
* appears under the "Dimensions" panel in the editor. It remains in its
* original `spacing.php` file for compatibility with core.
*
* @package WordPress
* @since 5.9.0
*/
/**
* Registers the style block attribute for block types that support it.
*
* @since 5.9.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_dimensions_support( $block_type ) {
// Setup attributes and styles within that if needed.
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
// Check for existing style attribute definition e.g. from block.json.
if ( array_key_exists( 'style', $block_type->attributes ) ) {
return;
}
$has_dimensions_support = block_has_support( $block_type, array( '__experimentalDimensions' ), false );
// Future block supports such as height & width will be added here.
if ( $has_dimensions_support ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
}
/**
* Adds CSS classes for block dimensions to the incoming attributes array.
* This will be applied to the block markup in the front-end.
*
* @since 5.9.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
* @param array $block_attributes Block attributes.
* @return array Block dimensions CSS classes and inline styles.
*/
function wp_apply_dimensions_support( $block_type, $block_attributes ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
if ( wp_should_skip_block_supports_serialization( $block_type, '__experimentalDimensions' ) ) {
return array();
}
$styles = array();
// Height support to be added in near future.
// Width support to be added in near future.
return empty( $styles ) ? array() : array( 'style' => implode( ' ', $styles ) );
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'dimensions',
array(
'register_attribute' => 'wp_register_dimensions_support',
'apply' => 'wp_apply_dimensions_support',
)
);
+586
View File
@@ -0,0 +1,586 @@
<?php
/**
* Duotone block support flag.
*
* Parts of this source were derived and modified from TinyColor,
* released under the MIT license.
*
* https://github.com/bgrins/TinyColor
*
* Copyright (c), Brian Grinstead, http://briangrinstead.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @package WordPress
* @since 5.8.0
*/
/**
* Takes input from [0, n] and returns it as [0, 1].
*
* Direct port of TinyColor's function, lightly simplified to maintain
* consistency with TinyColor.
*
* @see https://github.com/bgrins/TinyColor
*
* @since 5.8.0
* @access private
*
* @param mixed $n Number of unknown type.
* @param int $max Upper value of the range to bound to.
* @return float Value in the range [0, 1].
*/
function wp_tinycolor_bound01( $n, $max ) {
if ( 'string' === gettype( $n ) && false !== strpos( $n, '.' ) && 1 === (float) $n ) {
$n = '100%';
}
$n = min( $max, max( 0, (float) $n ) );
// Automatically convert percentage into number.
if ( 'string' === gettype( $n ) && false !== strpos( $n, '%' ) ) {
$n = (int) ( $n * $max ) / 100;
}
// Handle floating point rounding errors.
if ( ( abs( $n - $max ) < 0.000001 ) ) {
return 1.0;
}
// Convert into [0, 1] range if it isn't already.
return ( $n % $max ) / (float) $max;
}
/**
* Direct port of tinycolor's boundAlpha function to maintain consistency with
* how tinycolor works.
*
* @see https://github.com/bgrins/TinyColor
*
* @since 5.9.0
* @access private
*
* @param mixed $n Number of unknown type.
* @return float Value in the range [0,1].
*/
function _wp_tinycolor_bound_alpha( $n ) {
if ( is_numeric( $n ) ) {
$n = (float) $n;
if ( $n >= 0 && $n <= 1 ) {
return $n;
}
}
return 1;
}
/**
* Rounds and converts values of an RGB object.
*
* Direct port of TinyColor's function, lightly simplified to maintain
* consistency with TinyColor.
*
* @see https://github.com/bgrins/TinyColor
*
* @since 5.8.0
* @access private
*
* @param array $rgb_color RGB object.
* @return array Rounded and converted RGB object.
*/
function wp_tinycolor_rgb_to_rgb( $rgb_color ) {
return array(
'r' => wp_tinycolor_bound01( $rgb_color['r'], 255 ) * 255,
'g' => wp_tinycolor_bound01( $rgb_color['g'], 255 ) * 255,
'b' => wp_tinycolor_bound01( $rgb_color['b'], 255 ) * 255,
);
}
/**
* Helper function for hsl to rgb conversion.
*
* Direct port of TinyColor's function, lightly simplified to maintain
* consistency with TinyColor.
*
* @see https://github.com/bgrins/TinyColor
*
* @since 5.8.0
* @access private
*
* @param float $p first component.
* @param float $q second component.
* @param float $t third component.
* @return float R, G, or B component.
*/
function wp_tinycolor_hue_to_rgb( $p, $q, $t ) {
if ( $t < 0 ) {
$t += 1;
}
if ( $t > 1 ) {
$t -= 1;
}
if ( $t < 1 / 6 ) {
return $p + ( $q - $p ) * 6 * $t;
}
if ( $t < 1 / 2 ) {
return $q;
}
if ( $t < 2 / 3 ) {
return $p + ( $q - $p ) * ( 2 / 3 - $t ) * 6;
}
return $p;
}
/**
* Converts an HSL object to an RGB object with converted and rounded values.
*
* Direct port of TinyColor's function, lightly simplified to maintain
* consistency with TinyColor.
*
* @see https://github.com/bgrins/TinyColor
*
* @since 5.8.0
* @access private
*
* @param array $hsl_color HSL object.
* @return array Rounded and converted RGB object.
*/
function wp_tinycolor_hsl_to_rgb( $hsl_color ) {
$h = wp_tinycolor_bound01( $hsl_color['h'], 360 );
$s = wp_tinycolor_bound01( $hsl_color['s'], 100 );
$l = wp_tinycolor_bound01( $hsl_color['l'], 100 );
if ( 0 === $s ) {
// Achromatic.
$r = $l;
$g = $l;
$b = $l;
} else {
$q = $l < 0.5 ? $l * ( 1 + $s ) : $l + $s - $l * $s;
$p = 2 * $l - $q;
$r = wp_tinycolor_hue_to_rgb( $p, $q, $h + 1 / 3 );
$g = wp_tinycolor_hue_to_rgb( $p, $q, $h );
$b = wp_tinycolor_hue_to_rgb( $p, $q, $h - 1 / 3 );
}
return array(
'r' => $r * 255,
'g' => $g * 255,
'b' => $b * 255,
);
}
/**
* Parses hex, hsl, and rgb CSS strings using the same regex as TinyColor v1.4.2
* used in the JavaScript. Only colors output from react-color are implemented.
*
* Direct port of TinyColor's function, lightly simplified to maintain
* consistency with TinyColor.
*
* @see https://github.com/bgrins/TinyColor
* @see https://github.com/casesandberg/react-color/
*
* @since 5.8.0
* @since 5.9.0 Added alpha processing.
* @access private
*
* @param string $color_str CSS color string.
* @return array RGB object.
*/
function wp_tinycolor_string_to_rgb( $color_str ) {
$color_str = strtolower( trim( $color_str ) );
$css_integer = '[-\\+]?\\d+%?';
$css_number = '[-\\+]?\\d*\\.\\d+%?';
$css_unit = '(?:' . $css_number . ')|(?:' . $css_integer . ')';
$permissive_match3 = '[\\s|\\(]+(' . $css_unit . ')[,|\\s]+(' . $css_unit . ')[,|\\s]+(' . $css_unit . ')\\s*\\)?';
$permissive_match4 = '[\\s|\\(]+(' . $css_unit . ')[,|\\s]+(' . $css_unit . ')[,|\\s]+(' . $css_unit . ')[,|\\s]+(' . $css_unit . ')\\s*\\)?';
$rgb_regexp = '/^rgb' . $permissive_match3 . '$/';
if ( preg_match( $rgb_regexp, $color_str, $match ) ) {
$rgb = wp_tinycolor_rgb_to_rgb(
array(
'r' => $match[1],
'g' => $match[2],
'b' => $match[3],
)
);
$rgb['a'] = 1;
return $rgb;
}
$rgba_regexp = '/^rgba' . $permissive_match4 . '$/';
if ( preg_match( $rgba_regexp, $color_str, $match ) ) {
$rgb = wp_tinycolor_rgb_to_rgb(
array(
'r' => $match[1],
'g' => $match[2],
'b' => $match[3],
)
);
$rgb['a'] = _wp_tinycolor_bound_alpha( $match[4] );
return $rgb;
}
$hsl_regexp = '/^hsl' . $permissive_match3 . '$/';
if ( preg_match( $hsl_regexp, $color_str, $match ) ) {
$rgb = wp_tinycolor_hsl_to_rgb(
array(
'h' => $match[1],
's' => $match[2],
'l' => $match[3],
)
);
$rgb['a'] = 1;
return $rgb;
}
$hsla_regexp = '/^hsla' . $permissive_match4 . '$/';
if ( preg_match( $hsla_regexp, $color_str, $match ) ) {
$rgb = wp_tinycolor_hsl_to_rgb(
array(
'h' => $match[1],
's' => $match[2],
'l' => $match[3],
)
);
$rgb['a'] = _wp_tinycolor_bound_alpha( $match[4] );
return $rgb;
}
$hex8_regexp = '/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/';
if ( preg_match( $hex8_regexp, $color_str, $match ) ) {
$rgb = wp_tinycolor_rgb_to_rgb(
array(
'r' => base_convert( $match[1], 16, 10 ),
'g' => base_convert( $match[2], 16, 10 ),
'b' => base_convert( $match[3], 16, 10 ),
)
);
$rgb['a'] = _wp_tinycolor_bound_alpha(
base_convert( $match[4], 16, 10 ) / 255
);
return $rgb;
}
$hex6_regexp = '/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/';
if ( preg_match( $hex6_regexp, $color_str, $match ) ) {
$rgb = wp_tinycolor_rgb_to_rgb(
array(
'r' => base_convert( $match[1], 16, 10 ),
'g' => base_convert( $match[2], 16, 10 ),
'b' => base_convert( $match[3], 16, 10 ),
)
);
$rgb['a'] = 1;
return $rgb;
}
$hex4_regexp = '/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/';
if ( preg_match( $hex4_regexp, $color_str, $match ) ) {
$rgb = wp_tinycolor_rgb_to_rgb(
array(
'r' => base_convert( $match[1] . $match[1], 16, 10 ),
'g' => base_convert( $match[2] . $match[2], 16, 10 ),
'b' => base_convert( $match[3] . $match[3], 16, 10 ),
)
);
$rgb['a'] = _wp_tinycolor_bound_alpha(
base_convert( $match[4] . $match[4], 16, 10 ) / 255
);
return $rgb;
}
$hex3_regexp = '/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/';
if ( preg_match( $hex3_regexp, $color_str, $match ) ) {
$rgb = wp_tinycolor_rgb_to_rgb(
array(
'r' => base_convert( $match[1] . $match[1], 16, 10 ),
'g' => base_convert( $match[2] . $match[2], 16, 10 ),
'b' => base_convert( $match[3] . $match[3], 16, 10 ),
)
);
$rgb['a'] = 1;
return $rgb;
}
/*
* The JS color picker considers the string "transparent" to be a hex value,
* so we need to handle it here as a special case.
*/
if ( 'transparent' === $color_str ) {
return array(
'r' => 0,
'g' => 0,
'b' => 0,
'a' => 0,
);
}
}
/**
* Returns the prefixed id for the duotone filter for use as a CSS id.
*
* @since 5.9.1
* @access private
*
* @param array $preset Duotone preset value as seen in theme.json.
* @return string Duotone filter CSS id.
*/
function wp_get_duotone_filter_id( $preset ) {
if ( ! isset( $preset['slug'] ) ) {
return '';
}
return 'wp-duotone-' . $preset['slug'];
}
/**
* Returns the CSS filter property url to reference the rendered SVG.
*
* @since 5.9.0
* @access private
*
* @param array $preset Duotone preset value as seen in theme.json.
* @return string Duotone CSS filter property url value.
*/
function wp_get_duotone_filter_property( $preset ) {
$filter_id = wp_get_duotone_filter_id( $preset );
return "url('#" . $filter_id . "')";
}
/**
* Returns the duotone filter SVG string for the preset.
*
* @since 5.9.1
* @access private
*
* @param array $preset Duotone preset value as seen in theme.json.
* @return string Duotone SVG filter.
*/
function wp_get_duotone_filter_svg( $preset ) {
$filter_id = wp_get_duotone_filter_id( $preset );
$duotone_values = array(
'r' => array(),
'g' => array(),
'b' => array(),
'a' => array(),
);
if ( ! isset( $preset['colors'] ) || ! is_array( $preset['colors'] ) ) {
$preset['colors'] = array();
}
foreach ( $preset['colors'] as $color_str ) {
$color = wp_tinycolor_string_to_rgb( $color_str );
$duotone_values['r'][] = $color['r'] / 255;
$duotone_values['g'][] = $color['g'] / 255;
$duotone_values['b'][] = $color['b'] / 255;
$duotone_values['a'][] = $color['a'];
}
ob_start();
?>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 0 0"
width="0"
height="0"
focusable="false"
role="none"
style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;"
>
<defs>
<filter id="<?php echo esc_attr( $filter_id ); ?>">
<feColorMatrix
color-interpolation-filters="sRGB"
type="matrix"
values="
.299 .587 .114 0 0
.299 .587 .114 0 0
.299 .587 .114 0 0
.299 .587 .114 0 0
"
/>
<feComponentTransfer color-interpolation-filters="sRGB" >
<feFuncR type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['r'] ) ); ?>" />
<feFuncG type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['g'] ) ); ?>" />
<feFuncB type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['b'] ) ); ?>" />
<feFuncA type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['a'] ) ); ?>" />
</feComponentTransfer>
<feComposite in2="SourceGraphic" operator="in" />
</filter>
</defs>
</svg>
<?php
$svg = ob_get_clean();
if ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) {
// Clean up the whitespace.
$svg = preg_replace( "/[\r\n\t ]+/", ' ', $svg );
$svg = preg_replace( '/> </', '><', $svg );
$svg = trim( $svg );
}
return $svg;
}
/**
* Registers the style and colors block attributes for block types that support it.
*
* @since 5.8.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_duotone_support( $block_type ) {
$has_duotone_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$has_duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
}
if ( $has_duotone_support ) {
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
if ( ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
}
}
/**
* Render out the duotone stylesheet and SVG.
*
* @since 5.8.0
* @access private
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function wp_render_duotone_support( $block_content, $block ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$duotone_support = false;
if ( $block_type && property_exists( $block_type, 'supports' ) ) {
$duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
}
$has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] );
if (
! $duotone_support ||
! $has_duotone_attribute
) {
return $block_content;
}
$filter_preset = array(
'slug' => wp_unique_id( sanitize_key( implode( '-', $block['attrs']['style']['color']['duotone'] ) . '-' ) ),
'colors' => $block['attrs']['style']['color']['duotone'],
);
$filter_property = wp_get_duotone_filter_property( $filter_preset );
$filter_id = wp_get_duotone_filter_id( $filter_preset );
$filter_svg = wp_get_duotone_filter_svg( $filter_preset );
$scope = '.' . $filter_id;
$selectors = explode( ',', $duotone_support );
$scoped = array();
foreach ( $selectors as $sel ) {
$scoped[] = $scope . ' ' . trim( $sel );
}
$selector = implode( ', ', $scoped );
// !important is needed because these styles render before global styles,
// and they should be overriding the duotone filters set by global styles.
$filter_style = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG
? $selector . " {\n\tfilter: " . $filter_property . " !important;\n}\n"
: $selector . '{filter:' . $filter_property . ' !important;}';
wp_register_style( $filter_id, false, array(), true, true );
wp_add_inline_style( $filter_id, $filter_style );
wp_enqueue_style( $filter_id );
add_action(
'wp_footer',
static function () use ( $filter_svg, $selector ) {
echo $filter_svg;
/*
* Safari renders elements incorrectly on first paint when the SVG
* filter comes after the content that it is filtering, so we force
* a repaint with a WebKit hack which solves the issue.
*/
global $is_safari;
if ( $is_safari ) {
printf(
// Simply accessing el.offsetHeight flushes layout and style
// changes in WebKit without having to wait for setTimeout.
'<script>( function() { var el = document.querySelector( %s ); var display = el.style.display; el.style.display = "none"; el.offsetHeight; el.style.display = display; } )();</script>',
wp_json_encode( $selector )
);
}
}
);
// Like the layout hook, this assumes the hook only applies to blocks with a single wrapper.
return preg_replace(
'/' . preg_quote( 'class="', '/' ) . '/',
'class="' . $filter_id . ' ',
$block_content,
1
);
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'duotone',
array(
'register_attribute' => 'wp_register_duotone_support',
)
);
add_filter( 'render_block', 'wp_render_duotone_support', 10, 2 );
+139
View File
@@ -0,0 +1,139 @@
<?php
/**
* Elements styles block support.
*
* @package WordPress
* @since 5.8.0
*/
/**
* Get the elements class names.
*
* @since 6.0.0
* @access private
*
* @param array $block Block object.
* @return string The unique class name.
*/
function wp_get_elements_class_name( $block ) {
return 'wp-elements-' . md5( serialize( $block ) );
}
/**
* Update the block content with elements class names.
*
* @since 5.8.0
* @access private
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function wp_render_elements_support( $block_content, $block ) {
if ( ! $block_content ) {
return $block_content;
}
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
if ( $skip_link_color_serialization ) {
return $block_content;
}
$link_color = null;
if ( ! empty( $block['attrs'] ) ) {
$link_color = _wp_array_get( $block['attrs'], array( 'style', 'elements', 'link', 'color', 'text' ), null );
}
/*
* For now we only care about link color.
* This code in the future when we have a public API
* should take advantage of WP_Theme_JSON::compute_style_properties
* and work for any element and style.
*/
if ( null === $link_color ) {
return $block_content;
}
$class_name = wp_get_elements_class_name( $block );
// Like the layout hook this assumes the hook only applies to blocks with a single wrapper.
// Retrieve the opening tag of the first HTML element.
$html_element_matches = array();
preg_match( '/<[^>]+>/', $block_content, $html_element_matches, PREG_OFFSET_CAPTURE );
$first_element = $html_element_matches[0][0];
// If the first HTML element has a class attribute just add the new class
// as we do on layout and duotone.
if ( strpos( $first_element, 'class="' ) !== false ) {
$content = preg_replace(
'/' . preg_quote( 'class="', '/' ) . '/',
'class="' . $class_name . ' ',
$block_content,
1
);
} else {
// If the first HTML element has no class attribute we should inject the attribute before the attribute at the end.
$first_element_offset = $html_element_matches[0][1];
$content = substr_replace( $block_content, ' class="' . $class_name . '"', $first_element_offset + strlen( $first_element ) - 1, 0 );
}
return $content;
}
/**
* Render the elements stylesheet.
*
* In the case of nested blocks we want the parent element styles to be rendered before their descendants.
* This solves the issue of an element (e.g.: link color) being styled in both the parent and a descendant:
* we want the descendant style to take priority, and this is done by loading it after, in DOM order.
*
* @since 6.0.0
* @access private
*
* @param string|null $pre_render The pre-rendered content. Default null.
* @param array $block The block being rendered.
*
* @return null
*/
function wp_render_elements_support_styles( $pre_render, $block ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
if ( $skip_link_color_serialization ) {
return null;
}
$link_color = null;
if ( ! empty( $block['attrs'] ) ) {
$link_color = _wp_array_get( $block['attrs'], array( 'style', 'elements', 'link', 'color', 'text' ), null );
}
/*
* For now we only care about link color.
* This code in the future when we have a public API
* should take advantage of WP_Theme_JSON::compute_style_properties
* and work for any element and style.
*/
if ( null === $link_color ) {
return null;
}
$class_name = wp_get_elements_class_name( $block );
if ( strpos( $link_color, 'var:preset|color|' ) !== false ) {
// Get the name from the string and add proper styles.
$index_to_splice = strrpos( $link_color, '|' ) + 1;
$link_color_name = substr( $link_color, $index_to_splice );
$link_color = "var(--wp--preset--color--$link_color_name)";
}
$link_color_declaration = esc_html( safecss_filter_attr( "color: $link_color" ) );
$style = ".$class_name a{" . $link_color_declaration . ';}';
wp_enqueue_block_support_styles( $style );
return null;
}
add_filter( 'render_block', 'wp_render_elements_support', 10, 2 );
add_filter( 'pre_render_block', 'wp_render_elements_support_styles', 10, 2 );
@@ -0,0 +1,72 @@
<?php
/**
* Generated classname block support flag.
*
* @package WordPress
* @since 5.6.0
*/
/**
* Get the generated classname from a given block name.
*
* @since 5.6.0
*
* @access private
*
* @param string $block_name Block Name.
* @return string Generated classname.
*/
function wp_get_block_default_classname( $block_name ) {
// Generated HTML classes for blocks follow the `wp-block-{name}` nomenclature.
// Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
$classname = 'wp-block-' . preg_replace(
'/^core-/',
'',
str_replace( '/', '-', $block_name )
);
/**
* Filters the default block className for server rendered blocks.
*
* @since 5.6.0
*
* @param string $class_name The current applied classname.
* @param string $block_name The block name.
*/
$classname = apply_filters( 'block_default_classname', $classname, $block_name );
return $classname;
}
/**
* Add the generated classnames to the output.
*
* @since 5.6.0
*
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*
* @return array Block CSS classes and inline styles.
*/
function wp_apply_generated_classname_support( $block_type ) {
$attributes = array();
$has_generated_classname_support = block_has_support( $block_type, array( 'className' ), true );
if ( $has_generated_classname_support ) {
$block_classname = wp_get_block_default_classname( $block_type->name );
if ( $block_classname ) {
$attributes['class'] = $block_classname;
}
}
return $attributes;
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'generated-classname',
array(
'apply' => 'wp_apply_generated_classname_support',
)
);
+317
View File
@@ -0,0 +1,317 @@
<?php
/**
* Layout block support flag.
*
* @package WordPress
* @since 5.8.0
*/
/**
* Registers the layout block attribute for block types that support it.
*
* @since 5.8.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_layout_support( $block_type ) {
$support_layout = block_has_support( $block_type, array( '__experimentalLayout' ), false );
if ( $support_layout ) {
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
if ( ! array_key_exists( 'layout', $block_type->attributes ) ) {
$block_type->attributes['layout'] = array(
'type' => 'object',
);
}
}
}
/**
* Generates the CSS corresponding to the provided layout.
*
* @since 5.9.0
* @access private
*
* @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.
* @param boolean $should_skip_gap_serialization Whether to skip applying the user-defined value set in the editor.
* @param string $fallback_gap_value The custom fallback value for block gap.
* @return string CSS style.
*/
function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false, $gap_value = null, $should_skip_gap_serialization = false, $fallback_gap_value = '0.5em' ) {
$layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
$style = '';
if ( 'default' === $layout_type ) {
$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.
$all_max_width_value = safecss_filter_attr( explode( ';', $all_max_width_value )[0] );
$wide_max_width_value = safecss_filter_attr( explode( ';', $wide_max_width_value )[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; }";
}
$style .= "$selector > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }";
$style .= "$selector > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }";
$style .= "$selector > .aligncenter { margin-left: auto !important; margin-right: auto !important; }";
if ( $has_block_gap_support ) {
if ( is_array( $gap_value ) ) {
$gap_value = isset( $gap_value['top'] ) ? $gap_value['top'] : null;
}
$gap_style = $gap_value && ! $should_skip_gap_serialization ? $gap_value : 'var( --wp--style--block-gap )';
$style .= "$selector > * { margin-block-start: 0; margin-block-end: 0; }";
$style .= "$selector > * + * { margin-block-start: $gap_style; margin-block-end: 0; }";
}
} elseif ( 'flex' === $layout_type ) {
$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' );
}
$flex_wrap_options = array( 'wrap', 'nowrap' );
$flex_wrap = ! empty( $layout['flexWrap'] ) && in_array( $layout['flexWrap'], $flex_wrap_options, true ) ?
$layout['flexWrap'] :
'wrap';
$style = "$selector {";
$style .= 'display: flex;';
if ( $has_block_gap_support ) {
if ( is_array( $gap_value ) ) {
$gap_row = isset( $gap_value['top'] ) ? $gap_value['top'] : $fallback_gap_value;
$gap_column = isset( $gap_value['left'] ) ? $gap_value['left'] : $fallback_gap_value;
$gap_value = $gap_row === $gap_column ? $gap_row : $gap_row . ' ' . $gap_column;
}
$gap_style = $gap_value && ! $should_skip_gap_serialization ? $gap_value : "var( --wp--style--block-gap, $fallback_gap_value )";
$style .= "gap: $gap_style;";
} else {
$style .= "gap: $fallback_gap_value;";
}
$style .= "flex-wrap: $flex_wrap;";
if ( 'horizontal' === $layout_orientation ) {
$style .= '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'] ]};";
}
} else {
$style .= 'flex-direction: column;';
if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
$style .= "align-items: {$justify_content_options[ $layout['justifyContent'] ]};";
} else {
$style .= 'align-items: flex-start;';
}
}
$style .= '}';
$style .= "$selector > * { margin: 0; }";
}
return $style;
}
/**
* Renders the layout config to the block wrapper.
*
* @since 5.8.0
* @access private
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function wp_render_layout_support_flag( $block_content, $block ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$support_layout = block_has_support( $block_type, array( '__experimentalLayout' ), false );
if ( ! $support_layout ) {
return $block_content;
}
$block_gap = wp_get_global_settings( array( 'spacing', 'blockGap' ) );
$default_layout = wp_get_global_settings( array( 'layout' ) );
$has_block_gap_support = isset( $block_gap ) ? null !== $block_gap : false;
$default_block_layout = _wp_array_get( $block_type->supports, array( '__experimentalLayout', 'default' ), array() );
$used_layout = isset( $block['attrs']['layout'] ) ? $block['attrs']['layout'] : $default_block_layout;
if ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] ) {
if ( ! $default_layout ) {
return $block_content;
}
$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.
if ( is_array( $gap_value ) ) {
foreach ( $gap_value as $key => $value ) {
$gap_value[ $key ] = $value && preg_match( '%[\\\(&=}]|/\*%', $value ) ? null : $value;
}
} else {
$gap_value = $gap_value && preg_match( '%[\\\(&=}]|/\*%', $gap_value ) ? null : $gap_value;
}
$fallback_gap_value = _wp_array_get( $block_type->supports, array( 'spacing', 'blockGap', '__experimentalDefault' ), '0.5em' );
// If a block's block.json skips serialization for spacing or spacing.blockGap,
// don't apply the user-defined value to the styles.
$should_skip_gap_serialization = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'blockGap' );
$style = wp_get_layout_style( ".$class_name", $used_layout, $has_block_gap_support, $gap_value, $should_skip_gap_serialization, $fallback_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 ) . ' ',
$block_content,
1
);
wp_enqueue_block_support_styles( $style );
return $content;
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'layout',
array(
'register_attribute' => 'wp_register_layout_support',
)
);
add_filter( 'render_block', 'wp_render_layout_support_flag', 10, 2 );
/**
* For themes without theme.json file, make sure
* to restore the inner div for the group block
* to avoid breaking styles relying on that div.
*
* @since 5.8.0
* @access private
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function wp_restore_group_inner_container( $block_content, $block ) {
$tag_name = isset( $block['attrs']['tagName'] ) ? $block['attrs']['tagName'] : 'div';
$group_with_inner_container_regex = sprintf(
'/(^\s*<%1$s\b[^>]*wp-block-group(\s|")[^>]*>)(\s*<div\b[^>]*wp-block-group__inner-container(\s|")[^>]*>)((.|\S|\s)*)/U',
preg_quote( $tag_name, '/' )
);
if (
WP_Theme_JSON_Resolver::theme_has_support() ||
1 === preg_match( $group_with_inner_container_regex, $block_content ) ||
( isset( $block['attrs']['layout']['type'] ) && 'default' !== $block['attrs']['layout']['type'] )
) {
return $block_content;
}
$replace_regex = sprintf(
'/(^\s*<%1$s\b[^>]*wp-block-group[^>]*>)(.*)(<\/%1$s>\s*$)/ms',
preg_quote( $tag_name, '/' )
);
$updated_content = preg_replace_callback(
$replace_regex,
static function( $matches ) {
return $matches[1] . '<div class="wp-block-group__inner-container">' . $matches[2] . '</div>' . $matches[3];
},
$block_content
);
return $updated_content;
}
add_filter( 'render_block_core/group', 'wp_restore_group_inner_container', 10, 2 );
/**
* For themes without theme.json file, make sure
* to restore the outer div for the aligned image block
* to avoid breaking styles relying on that div.
*
* @since 6.0.0
* @access private
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function wp_restore_image_outer_container( $block_content, $block ) {
$image_with_align = "
/# 1) everything up to the class attribute contents
(
^\s*
<figure\b
[^>]*
\bclass=
[\"']
)
# 2) the class attribute contents
(
[^\"']*
\bwp-block-image\b
[^\"']*
\b(?:alignleft|alignright|aligncenter)\b
[^\"']*
)
# 3) everything after the class attribute contents
(
[\"']
[^>]*
>
.*
<\/figure>
)/iUx";
if (
WP_Theme_JSON_Resolver::theme_has_support() ||
0 === preg_match( $image_with_align, $block_content, $matches )
) {
return $block_content;
}
$wrapper_classnames = array( 'wp-block-image' );
// If the block has a classNames attribute these classnames need to be removed from the content and added back
// to the new wrapper div also.
if ( ! empty( $block['attrs']['className'] ) ) {
$wrapper_classnames = array_merge( $wrapper_classnames, explode( ' ', $block['attrs']['className'] ) );
}
$content_classnames = explode( ' ', $matches[2] );
$filtered_content_classnames = array_diff( $content_classnames, $wrapper_classnames );
return '<div class="' . implode( ' ', $wrapper_classnames ) . '">' . $matches[1] . implode( ' ', $filtered_content_classnames ) . $matches[3] . '</div>';
}
add_filter( 'render_block_core/image', 'wp_restore_image_outer_container', 10, 2 );
+89
View File
@@ -0,0 +1,89 @@
<?php
/**
* Spacing block support flag.
* For backwards compatibility, this remains separate to the dimensions.php
* block support despite both belonging under a single panel in the editor.
*
* @package WordPress
* @since 5.8.0
*/
/**
* Registers the style block attribute for block types that support it.
*
* @since 5.8.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_spacing_support( $block_type ) {
$has_spacing_support = block_has_support( $block_type, array( 'spacing' ), false );
// Setup attributes and styles within that if needed.
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
if ( $has_spacing_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
}
/**
* Add CSS classes for block spacing to the incoming attributes array.
* This will be applied to the block markup in the front-end.
*
* @since 5.8.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
* @param array $block_attributes Block attributes.
* @return array Block spacing CSS classes and inline styles.
*/
function wp_apply_spacing_support( $block_type, $block_attributes ) {
if ( wp_should_skip_block_supports_serialization( $block_type, 'spacing' ) ) {
return array();
}
$has_padding_support = block_has_support( $block_type, array( 'spacing', 'padding' ), false );
$has_margin_support = block_has_support( $block_type, array( 'spacing', 'margin' ), false );
$skip_padding = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'padding' );
$skip_margin = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'margin' );
$styles = array();
if ( $has_padding_support && ! $skip_padding ) {
$padding_value = _wp_array_get( $block_attributes, array( 'style', 'spacing', 'padding' ), null );
if ( is_array( $padding_value ) ) {
foreach ( $padding_value as $key => $value ) {
$styles[] = sprintf( 'padding-%s: %s;', $key, $value );
}
} elseif ( null !== $padding_value ) {
$styles[] = sprintf( 'padding: %s;', $padding_value );
}
}
if ( $has_margin_support && ! $skip_margin ) {
$margin_value = _wp_array_get( $block_attributes, array( 'style', 'spacing', 'margin' ), null );
if ( is_array( $margin_value ) ) {
foreach ( $margin_value as $key => $value ) {
$styles[] = sprintf( 'margin-%s: %s;', $key, $value );
}
} elseif ( null !== $margin_value ) {
$styles[] = sprintf( 'margin: %s;', $margin_value );
}
}
return empty( $styles ) ? array() : array( 'style' => implode( ' ', $styles ) );
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'spacing',
array(
'register_attribute' => 'wp_register_spacing_support',
'apply' => 'wp_apply_spacing_support',
)
);
+223
View File
@@ -0,0 +1,223 @@
<?php
/**
* Typography block support flag.
*
* @package WordPress
* @since 5.6.0
*/
/**
* Registers the style and typography block attributes for block types that support it.
*
* @since 5.6.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_typography_support( $block_type ) {
if ( ! property_exists( $block_type, 'supports' ) ) {
return;
}
$typography_supports = _wp_array_get( $block_type->supports, array( 'typography' ), false );
if ( ! $typography_supports ) {
return;
}
$has_font_family_support = _wp_array_get( $typography_supports, array( '__experimentalFontFamily' ), false );
$has_font_size_support = _wp_array_get( $typography_supports, array( 'fontSize' ), false );
$has_font_style_support = _wp_array_get( $typography_supports, array( '__experimentalFontStyle' ), false );
$has_font_weight_support = _wp_array_get( $typography_supports, array( '__experimentalFontWeight' ), false );
$has_letter_spacing_support = _wp_array_get( $typography_supports, array( '__experimentalLetterSpacing' ), false );
$has_line_height_support = _wp_array_get( $typography_supports, array( 'lineHeight' ), false );
$has_text_decoration_support = _wp_array_get( $typography_supports, array( '__experimentalTextDecoration' ), false );
$has_text_transform_support = _wp_array_get( $typography_supports, array( '__experimentalTextTransform' ), false );
$has_typography_support = $has_font_family_support
|| $has_font_size_support
|| $has_font_style_support
|| $has_font_weight_support
|| $has_letter_spacing_support
|| $has_line_height_support
|| $has_text_decoration_support
|| $has_text_transform_support;
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
if ( $has_typography_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
if ( $has_font_size_support && ! array_key_exists( 'fontSize', $block_type->attributes ) ) {
$block_type->attributes['fontSize'] = array(
'type' => 'string',
);
}
}
/**
* Adds CSS classes and inline styles for typography features such as font sizes
* to the incoming attributes array. This will be applied to the block markup in
* the front-end.
*
* @since 5.6.0
* @access private
*
* @param WP_Block_Type $block_type Block type.
* @param array $block_attributes Block attributes.
* @return array Typography CSS classes and inline styles.
*/
function wp_apply_typography_support( $block_type, $block_attributes ) {
if ( ! property_exists( $block_type, 'supports' ) ) {
return array();
}
$typography_supports = _wp_array_get( $block_type->supports, array( 'typography' ), false );
if ( ! $typography_supports ) {
return array();
}
if ( wp_should_skip_block_supports_serialization( $block_type, 'typography' ) ) {
return array();
}
$attributes = array();
$classes = array();
$styles = array();
$has_font_family_support = _wp_array_get( $typography_supports, array( '__experimentalFontFamily' ), false );
$has_font_size_support = _wp_array_get( $typography_supports, array( 'fontSize' ), false );
$has_font_style_support = _wp_array_get( $typography_supports, array( '__experimentalFontStyle' ), false );
$has_font_weight_support = _wp_array_get( $typography_supports, array( '__experimentalFontWeight' ), false );
$has_letter_spacing_support = _wp_array_get( $typography_supports, array( '__experimentalLetterSpacing' ), false );
$has_line_height_support = _wp_array_get( $typography_supports, array( 'lineHeight' ), false );
$has_text_decoration_support = _wp_array_get( $typography_supports, array( '__experimentalTextDecoration' ), false );
$has_text_transform_support = _wp_array_get( $typography_supports, array( '__experimentalTextTransform' ), false );
if ( $has_font_size_support && ! wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontSize' ) ) {
$has_named_font_size = array_key_exists( 'fontSize', $block_attributes );
$has_custom_font_size = isset( $block_attributes['style']['typography']['fontSize'] );
if ( $has_named_font_size ) {
$classes[] = sprintf( 'has-%s-font-size', _wp_to_kebab_case( $block_attributes['fontSize'] ) );
} elseif ( $has_custom_font_size ) {
$styles[] = sprintf( 'font-size: %s;', $block_attributes['style']['typography']['fontSize'] );
}
}
if ( $has_font_family_support && ! wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontFamily' ) ) {
$has_named_font_family = array_key_exists( 'fontFamily', $block_attributes );
$has_custom_font_family = isset( $block_attributes['style']['typography']['fontFamily'] );
if ( $has_named_font_family ) {
$classes[] = sprintf( 'has-%s-font-family', _wp_to_kebab_case( $block_attributes['fontFamily'] ) );
} elseif ( $has_custom_font_family ) {
// Before using classes, the value was serialized as a CSS Custom Property.
// We don't need this code path when it lands in core.
$font_family_custom = $block_attributes['style']['typography']['fontFamily'];
if ( strpos( $font_family_custom, 'var:preset|font-family' ) !== false ) {
$index_to_splice = strrpos( $font_family_custom, '|' ) + 1;
$font_family_slug = _wp_to_kebab_case( substr( $font_family_custom, $index_to_splice ) );
$font_family_custom = sprintf( 'var(--wp--preset--font-family--%s)', $font_family_slug );
}
$styles[] = sprintf( 'font-family: %s;', $font_family_custom );
}
}
if ( $has_font_style_support && ! wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontStyle' ) ) {
$font_style = wp_typography_get_css_variable_inline_style( $block_attributes, 'fontStyle', 'font-style' );
if ( $font_style ) {
$styles[] = $font_style;
}
}
if ( $has_font_weight_support && ! wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontWeight' ) ) {
$font_weight = wp_typography_get_css_variable_inline_style( $block_attributes, 'fontWeight', 'font-weight' );
if ( $font_weight ) {
$styles[] = $font_weight;
}
}
if ( $has_line_height_support && ! wp_should_skip_block_supports_serialization( $block_type, 'typography', 'lineHeight' ) ) {
$has_line_height = isset( $block_attributes['style']['typography']['lineHeight'] );
if ( $has_line_height ) {
$styles[] = sprintf( 'line-height: %s;', $block_attributes['style']['typography']['lineHeight'] );
}
}
if ( $has_text_decoration_support && ! wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textDecoration' ) ) {
$text_decoration_style = wp_typography_get_css_variable_inline_style( $block_attributes, 'textDecoration', 'text-decoration' );
if ( $text_decoration_style ) {
$styles[] = $text_decoration_style;
}
}
if ( $has_text_transform_support && ! wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textTransform' ) ) {
$text_transform_style = wp_typography_get_css_variable_inline_style( $block_attributes, 'textTransform', 'text-transform' );
if ( $text_transform_style ) {
$styles[] = $text_transform_style;
}
}
if ( $has_letter_spacing_support && ! wp_should_skip_block_supports_serialization( $block_type, 'typography', 'letterSpacing' ) ) {
$letter_spacing_style = wp_typography_get_css_variable_inline_style( $block_attributes, 'letterSpacing', 'letter-spacing' );
if ( $letter_spacing_style ) {
$styles[] = $letter_spacing_style;
}
}
if ( ! empty( $classes ) ) {
$attributes['class'] = implode( ' ', $classes );
}
if ( ! empty( $styles ) ) {
$attributes['style'] = implode( ' ', $styles );
}
return $attributes;
}
/**
* Generates an inline style for a typography feature e.g. text decoration,
* text transform, and font style.
*
* @since 5.8.0
* @access private
*
* @param array $attributes Block's attributes.
* @param string $feature Key for the feature within the typography styles.
* @param string $css_property Slug for the CSS property the inline style sets.
* @return string CSS inline style.
*/
function wp_typography_get_css_variable_inline_style( $attributes, $feature, $css_property ) {
// Retrieve current attribute value or skip if not found.
$style_value = _wp_array_get( $attributes, array( 'style', 'typography', $feature ), false );
if ( ! $style_value ) {
return;
}
// If we don't have a preset CSS variable, we'll assume it's a regular CSS value.
if ( strpos( $style_value, "var:preset|{$css_property}|" ) === false ) {
return sprintf( '%s:%s;', $css_property, $style_value );
}
// We have a preset CSS variable as the style.
// Get the style value from the string and return CSS style.
$index_to_splice = strrpos( $style_value, '|' ) + 1;
$slug = substr( $style_value, $index_to_splice );
// Return the actual CSS inline style e.g. `text-decoration:var(--wp--preset--text-decoration--underline);`.
return sprintf( '%s:var(--wp--preset--%s--%s);', $css_property, $css_property, $slug );
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'typography',
array(
'register_attribute' => 'wp_register_typography_support',
'apply' => 'wp_apply_typography_support',
)
);
+36
View File
@@ -0,0 +1,36 @@
<?php
/**
* Block support utility functions.
*
* @package WordPress
* @subpackage Block Supports
* @since 6.0.0
*/
/**
* Checks whether serialization of the current block's supported properties
* should occur.
*
* @since 6.0.0
* @access private
*
* @param WP_Block_Type $block_type Block type.
* @param string $feature_set Name of block support feature set..
* @param string $feature Optional name of individual feature to check.
*
* @return boolean Whether to serialize block support styles & classes.
*/
function wp_should_skip_block_supports_serialization( $block_type, $feature_set, $feature = null ) {
if ( ! is_object( $block_type ) || ! $feature_set ) {
return false;
}
$path = array( $feature_set, '__experimentalSkipSerialization' );
$skip_serialization = _wp_array_get( $block_type->supports, $path, false );
if ( is_array( $skip_serialization ) ) {
return in_array( $feature, $skip_serialization, true );
}
return $skip_serialization;
}