WP_Theme_JSON::process_blocks_custom_css()protectedWP 6.2.0

Processes the CSS, to apply nesting.

Method of the class: WP_Theme_JSON{}

No Hooks.

Return

String. The processed CSS.

Usage

// protected - for code of main (parent) or child class
$result = $this->process_blocks_custom_css( $css, $selector );
$css(string) (required)
The CSS to process.
$selector(string) (required)
The selector to nest.

Changelog

Since 6.2.0 Introduced.
Since 6.6.0 Enforced 0-1-0 specificity for block custom CSS selectors.

WP_Theme_JSON::process_blocks_custom_css() code WP 6.6.2

protected function process_blocks_custom_css( $css, $selector ) {
	$processed_css = '';

	if ( empty( $css ) ) {
		return $processed_css;
	}

	// Split CSS nested rules.
	$parts = explode( '&', $css );
	foreach ( $parts as $part ) {
		if ( empty( $part ) ) {
			continue;
		}
		$is_root_css = ( ! str_contains( $part, '{' ) );
		if ( $is_root_css ) {
			// If the part doesn't contain braces, it applies to the root level.
			$processed_css .= ':root :where(' . trim( $selector ) . '){' . trim( $part ) . '}';
		} else {
			// If the part contains braces, it's a nested CSS rule.
			$part = explode( '{', str_replace( '}', '', $part ) );
			if ( count( $part ) !== 2 ) {
				continue;
			}
			$nested_selector = $part[0];
			$css_value       = $part[1];

			/*
			 * Handle pseudo elements such as ::before, ::after etc. Regex will also
			 * capture any leading combinator such as >, +, or ~, as well as spaces.
			 * This allows pseudo elements as descendants e.g. `.parent ::before`.
			 */
			$matches            = array();
			$has_pseudo_element = preg_match( '/([>+~\s]*::[a-zA-Z-]+)/', $nested_selector, $matches );
			$pseudo_part        = $has_pseudo_element ? $matches[1] : '';
			$nested_selector    = $has_pseudo_element ? str_replace( $pseudo_part, '', $nested_selector ) : $nested_selector;

			// Finalize selector and re-append pseudo element if required.
			$part_selector  = str_starts_with( $nested_selector, ' ' )
				? static::scope_selector( $selector, $nested_selector )
				: static::append_to_selector( $selector, $nested_selector );
			$final_selector = ":root :where($part_selector)$pseudo_part";

			$processed_css .= $final_selector . '{' . trim( $css_value ) . '}';
		}
	}
	return $processed_css;
}