diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index d63a84353cd46..9c4987719ed7f 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -848,7 +848,7 @@ public static function get_style_variations( $scope = 'theme' ) { * as the value of `_link` object in REST API responses. * * @since 6.6.0 - * @since 6.7.0 Resolve relative paths in block styles. + * @since 6.7.0 Added support for resolving block style and font face URIs. * * @param WP_Theme_JSON $theme_json A theme json instance. * @return array An array of resolved paths. @@ -867,6 +867,35 @@ public static function get_resolved_theme_uris( $theme_json ) { */ $placeholder = 'file:./'; + // Add font URIs. + if ( ! empty( $theme_json_data['settings']['typography']['fontFamilies'] ) ) { + $font_families = array_merge( + $theme_json_data['settings']['typography']['fontFamilies']['theme'] ?? array(), + $theme_json_data['settings']['typography']['fontFamilies']['custom'] ?? array(), + $theme_json_data['settings']['typography']['fontFamilies']['default'] ?? array() + ); + foreach ( $font_families as $font_family ) { + if ( ! empty( $font_family['fontFace'] ) ) { + foreach ( $font_family['fontFace'] as $font_face ) { + if ( ! empty( $font_face['src'] ) ) { + $sources = is_string( $font_face['src'] ) + ? array( $font_face['src'] ) + : $font_face['src']; + foreach ( $sources as $source ) { + if ( str_starts_with( $source, $placeholder ) ) { + $resolved_theme_uris[] = array( + 'name' => $source, + 'href' => sanitize_url( get_theme_file_uri( str_replace( $placeholder, '', $source ) ) ), + 'target' => "typography.fontFamilies.{$font_family['slug']}.fontFace.src", + ); + } + } + } + } + } + } + } + // Top level styles. $background_image_url = $theme_json_data['styles']['background']['backgroundImage']['url'] ?? null; if ( diff --git a/tests/phpunit/tests/theme/wpThemeJsonResolver.php b/tests/phpunit/tests/theme/wpThemeJsonResolver.php index 4fb3784f1a41b..cfe5f1ea28163 100644 --- a/tests/phpunit/tests/theme/wpThemeJsonResolver.php +++ b/tests/phpunit/tests/theme/wpThemeJsonResolver.php @@ -1331,8 +1331,44 @@ public function test_resolve_theme_file_uris() { public function test_get_resolved_theme_uris() { $theme_json = new WP_Theme_JSON( array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, - 'styles' => array( + 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'settings' => array( + 'typography' => array( + 'fontFamilies' => array( + array( + 'fontFace' => array( + array( + 'fontFamily' => 'Tocco', + 'fontStyle' => 'normal', + 'fontWeight' => '400', + 'src' => array( + 'file:./assets/tocco-400-normal.woff2', + ), + ), + ), + 'fontFamily' => 'Tocco, system-ui', + 'name' => 'Tocco', + 'slug' => 'secondary', + ), + array( + 'fontFace' => array( + array( + 'fontFamily' => '"Strozzapreti"', + 'fontStyle' => 'normal', + 'fontWeight' => '400', + 'src' => array( + 'file:./assets/strozzapreti-400-normal.woff2', + ), + ), + ), + 'fontFamily' => '"Strozzapreti", cursive', + 'name' => 'Strozzapreti', + 'slug' => 'primary', + ), + ), + ), + ), + 'styles' => array( 'background' => array( 'backgroundImage' => array( 'url' => 'file:./assets/image.png', @@ -1359,6 +1395,16 @@ public function test_get_resolved_theme_uris() { ); $expected_data = array( + array( + 'name' => 'file:./assets/tocco-400-normal.woff2', + 'href' => 'https://example.org/wp-content/themes/example-theme/assets/tocco-400-normal.woff2', + 'target' => 'typography.fontFamilies.secondary.fontFace.src', + ), + array( + 'name' => 'file:./assets/strozzapreti-400-normal.woff2', + 'href' => 'https://example.org/wp-content/themes/example-theme/assets/strozzapreti-400-normal.woff2', + 'target' => 'typography.fontFamilies.primary.fontFace.src', + ), array( 'name' => 'file:./assets/image.png', 'href' => 'https://example.org/wp-content/themes/example-theme/assets/image.png',