diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index afff53f9da..700cb20f7e 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -779,7 +779,7 @@ class WP_Theme_JSON { if ( empty( $result ) ) { unset( $output[ $subtree ] ); } else { - $output[ $subtree ] = $result; + $output[ $subtree ] = static::resolve_custom_css_format( $result ); } } @@ -1958,10 +1958,6 @@ class WP_Theme_JSON { /** * Returns the style property for the given path. * - * It also converts CSS Custom Property stored as - * "var:preset|color|secondary" to the form - * "--wp--preset--color--secondary". - * * It also converts references to a path to the value * stored at that location, e.g. * { "ref": "style.color.background" } => "#fff". @@ -1969,6 +1965,10 @@ class WP_Theme_JSON { * @since 5.8.0 * @since 5.9.0 Added support for values of array type, which are returned as is. * @since 6.1.0 Added the `$theme_json` parameter. + * @since 6.3.0 It no longer converts the internal format "var:preset|color|secondary" + * to the standard form "--wp--preset--color--secondary". + * This is already done by the sanitize method, + * so every property will be in the standard form. * * @param array $styles Styles subtree. * @param array $path Which property to process. @@ -2018,20 +2018,6 @@ class WP_Theme_JSON { return $value; } - // Convert custom CSS properties. - $prefix = 'var:'; - $prefix_len = strlen( $prefix ); - $token_in = '|'; - $token_out = '--'; - if ( 0 === strncmp( $value, $prefix, $prefix_len ) ) { - $unwrapped_name = str_replace( - $token_in, - $token_out, - substr( $value, $prefix_len ) - ); - $value = "var(--wp--$unwrapped_name)"; - } - return $value; } @@ -3488,4 +3474,52 @@ class WP_Theme_JSON { _wp_array_set( $this->theme_json, array( 'settings', 'spacing', 'spacingSizes', 'default' ), $spacing_sizes ); } + + /** + * This is used to convert the internal representation of variables to the CSS representation. + * For example, `var:preset|color|vivid-green-cyan` becomes `var(--wp--preset--color--vivid-green-cyan)`. + * + * @since 6.3.0 + * @param string $value The variable such as var:preset|color|vivid-green-cyan to convert. + * @return string The converted variable. + */ + private static function convert_custom_properties( $value ) { + $prefix = 'var:'; + $prefix_len = strlen( $prefix ); + $token_in = '|'; + $token_out = '--'; + if ( 0 === strpos( $value, $prefix ) ) { + $unwrapped_name = str_replace( + $token_in, + $token_out, + substr( $value, $prefix_len ) + ); + $value = "var(--wp--$unwrapped_name)"; + } + + return $value; + } + + /** + * Given a tree, converts the internal representation of variables to the CSS representation. + * It is recursive and modifies the input in-place. + * + * @since 6.3.0 + * @param array $tree Input to process. + * @return array The modified $tree. + */ + private static function resolve_custom_css_format( $tree ) { + $prefix = 'var:'; + + foreach ( $tree as $key => $data ) { + if ( is_string( $data ) && 0 === strpos( $data, $prefix ) ) { + $tree[ $key ] = self::convert_custom_properties( $data ); + } elseif ( is_array( $data ) ) { + $tree[ $key ] = self::resolve_custom_css_format( $data ); + } + } + + return $tree; + } + } diff --git a/src/wp-includes/global-styles-and-settings.php b/src/wp-includes/global-styles-and-settings.php index f5ea9ed179..4c016930b7 100644 --- a/src/wp-includes/global-styles-and-settings.php +++ b/src/wp-includes/global-styles-and-settings.php @@ -92,6 +92,8 @@ function wp_get_global_settings( $path = array(), $context = array() ) { * Gets the styles resulting of merging core, theme, and user data. * * @since 5.9.0 + * @since 6.3.0 the internal format "var:preset|color|secondary" is always resolved + * to the standard form "var(--wp--preset--font-size--small)". * * @param array $path Path to the specific style to retrieve. Optional. * If empty, will return all styles. @@ -115,7 +117,6 @@ function wp_get_global_styles( $path = array(), $context = array() ) { if ( isset( $context['origin'] ) && 'base' === $context['origin'] ) { $origin = 'theme'; } - $styles = WP_Theme_JSON_Resolver::get_merged_data( $origin )->get_raw_data()['styles']; return _wp_array_get( $styles, $path, $styles ); diff --git a/tests/phpunit/tests/theme/wpThemeJson.php b/tests/phpunit/tests/theme/wpThemeJson.php index 19212bc513..e43f99c969 100644 --- a/tests/phpunit/tests/theme/wpThemeJson.php +++ b/tests/phpunit/tests/theme/wpThemeJson.php @@ -1972,30 +1972,30 @@ class Tests_Theme_wpThemeJson extends WP_UnitTestCase { 'version' => WP_Theme_JSON::LATEST_SCHEMA, 'styles' => array( 'color' => array( - 'text' => 'var:preset|color|dark-red', + 'text' => 'var(--wp--preset--color--dark-red)', ), 'elements' => array( 'link' => array( 'color' => array( - 'text' => 'var:preset|color|dark-pink', - 'background' => 'var:preset|color|dark-red', + 'text' => 'var(--wp--preset--color--dark-pink)', + 'background' => 'var(--wp--preset--color--dark-red)', ), ), ), 'blocks' => array( 'core/image' => array( 'filter' => array( - 'duotone' => 'var:preset|duotone|blue-red', + 'duotone' => 'var(--wp--preset--duotone--blue-red)', ), ), 'core/group' => array( 'color' => array( - 'text' => 'var:preset|color|dark-gray', + 'text' => 'var(--wp--preset--color--dark-gray)', ), 'elements' => array( 'link' => array( 'color' => array( - 'text' => 'var:preset|color|dark-pink', + 'text' => 'var(--wp--preset--color--dark-pink)', ), ), ), @@ -4706,4 +4706,69 @@ class Tests_Theme_wpThemeJson extends WP_UnitTestCase { ), ); } + + public function test_internal_syntax_is_converted_to_css_variables() { + $result = new WP_Theme_JSON( + array( + 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'styles' => array( + 'color' => array( + 'background' => 'var:preset|color|primary', + 'text' => 'var(--wp--preset--color--secondary)', + ), + 'elements' => array( + 'link' => array( + 'color' => array( + 'background' => 'var:preset|color|pri', + 'text' => 'var(--wp--preset--color--sec)', + ), + ), + ), + 'blocks' => array( + 'core/post-terms' => array( + 'typography' => array( 'fontSize' => 'var(--wp--preset--font-size--small)' ), + 'color' => array( 'background' => 'var:preset|color|secondary' ), + ), + 'core/navigation' => array( + 'elements' => array( + 'link' => array( + 'color' => array( + 'background' => 'var:preset|color|p', + 'text' => 'var(--wp--preset--color--s)', + ), + ), + ), + ), + 'core/quote' => array( + 'typography' => array( 'fontSize' => 'var(--wp--preset--font-size--d)' ), + 'color' => array( 'background' => 'var:preset|color|d' ), + 'variations' => array( + 'plain' => array( + 'typography' => array( 'fontSize' => 'var(--wp--preset--font-size--s)' ), + 'color' => array( 'background' => 'var:preset|color|s' ), + ), + ), + ), + ), + ), + ) + ); + $styles = $result->get_raw_data()['styles']; + + $this->assertEquals( 'var(--wp--preset--color--primary)', $styles['color']['background'], 'Top level: Assert the originally correct values are still correct.' ); + $this->assertEquals( 'var(--wp--preset--color--secondary)', $styles['color']['text'], 'Top level: Assert the originally correct values are still correct.' ); + + $this->assertEquals( 'var(--wp--preset--color--pri)', $styles['elements']['link']['color']['background'], 'Element top level: Assert the originally correct values are still correct.' ); + $this->assertEquals( 'var(--wp--preset--color--sec)', $styles['elements']['link']['color']['text'], 'Element top level: Assert the originally correct values are still correct.' ); + + $this->assertEquals( 'var(--wp--preset--font-size--small)', $styles['blocks']['core/post-terms']['typography']['fontSize'], 'Top block level: Assert the originally correct values are still correct.' ); + $this->assertEquals( 'var(--wp--preset--color--secondary)', $styles['blocks']['core/post-terms']['color']['background'], 'Top block level: Assert the internal variables are convert to CSS custom variables.' ); + + $this->assertEquals( 'var(--wp--preset--color--p)', $styles['blocks']['core/navigation']['elements']['link']['color']['background'], 'Elements block level: Assert the originally correct values are still correct.' ); + $this->assertEquals( 'var(--wp--preset--color--s)', $styles['blocks']['core/navigation']['elements']['link']['color']['text'], 'Elements block level: Assert the originally correct values are still correct.' ); + + $this->assertEquals( 'var(--wp--preset--font-size--s)', $styles['blocks']['core/quote']['variations']['plain']['typography']['fontSize'], 'Style variations: Assert the originally correct values are still correct.' ); + $this->assertEquals( 'var(--wp--preset--color--s)', $styles['blocks']['core/quote']['variations']['plain']['color']['background'], 'Style variations: Assert the internal variables are convert to CSS custom variables.' ); + + } }