Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load fonts from style variations in the editor and the admin #7581

1 change: 1 addition & 0 deletions src/wp-admin/includes/admin-filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,4 @@

// Font management.
add_action( 'admin_print_styles', 'wp_print_font_faces', 50 );
add_action( 'admin_print_styles', 'wp_print_font_faces_from_style_variations', 50 );
1 change: 1 addition & 0 deletions src/wp-includes/block-editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ function _wp_get_iframed_editor_assets() {
ob_start();
wp_print_styles();
wp_print_font_faces();
wp_print_font_faces_from_style_variations();
$styles = ob_get_clean();

if ( $has_emoji_styles ) {
Expand Down
16 changes: 16 additions & 0 deletions src/wp-includes/fonts.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ function wp_print_font_faces( $fonts = array() ) {
$wp_font_face->generate_and_print( $fonts );
}

/**
* Generates and prints font-face styles defined the the theme style variations.
*
* @since 6.7.0
*
*/
function wp_print_font_faces_from_style_variations() {
$fonts = WP_Font_Face_Resolver::get_fonts_from_style_variations();

if ( empty( $fonts ) ) {
return;
}

wp_print_font_faces( $fonts );
}

/**
* Registers a new font collection in the font library.
*
Expand Down
32 changes: 32 additions & 0 deletions src/wp-includes/fonts/class-wp-font-face-resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,38 @@ public static function get_fonts_from_theme_json() {
return static::parse_settings( $settings );
}

/**
* Gets fonts defined in style variations.
*
* @since 6.7.0
*
* @return array Returns an array of font-families.
*/
public static function get_fonts_from_style_variations() {
$variations = WP_Theme_JSON_Resolver::get_style_variations();
$fonts = array();

if ( empty( $variations ) ) {
return $fonts;
}

foreach ( $variations as $variation ) {
if ( ! empty( $variation['settings']['typography']['fontFamilies']['theme'] ) ) {
$fonts = array_merge( $fonts, $variation['settings']['typography']['fontFamilies']['theme'] );
}
}

$settings = array(
'typography' => array(
'fontFamilies' => array(
'theme' => $fonts,
),
),
);

return static::parse_settings( $settings );
}

/**
* Parse theme.json settings to extract font definitions with variations grouped by font-family.
*
Expand Down
91 changes: 91 additions & 0 deletions tests/phpunit/tests/fonts/font-face/wp-font-face-tests-dataset.php
Original file line number Diff line number Diff line change
Expand Up @@ -403,4 +403,95 @@ public static function get_custom_font_families( $key = '' ) {

return $data;
}

public static function get_custom_style_variations( $key = '' ) {
static $data = null;

$path = get_stylesheet_directory() . '/assets/fonts/';
$uri = get_stylesheet_directory_uri() . '/assets/fonts/';
$expected_font_families = array(
array(
array(
'src' => array(
"{$path}dm-sans/DMSans-Regular.woff2",
),
'font-family' => 'DM Sans',
'font-stretch' => 'normal',
'font-style' => 'normal',
'font-weight' => '400',
),
array(
'src' => array(
"{$path}dm-sans/DMSans-Bold.woff2",
),
'font-family' => 'DM Sans',
'font-stretch' => 'normal',
'font-style' => 'normal',
'font-weight' => '700',
),
),
array(
array(
'src' => array(
"{$path}open-sans/OpenSans-VariableFont_wdth,wght.ttf",
),
'font-family' => 'Open Sans',
'font-stretch' => 'normal',
'font-style' => 'normal',
'font-weight' => '400',
),
array(
'src' => array(
"{$path}open-sans/OpenSans-Italic-VariableFont_wdth,wght.ttf",
),
'font-family' => 'Open Sans',
'font-stretch' => 'normal',
'font-style' => 'italic',
'font-weight' => '400',
),
),
array(
array(
'src' => array(
"{$path}dm-sans/DMSans-Medium.woff2",
),
'font-family' => 'DM Sans',
'font-stretch' => 'normal',
'font-style' => 'normal',
'font-weight' => '500',
),
array(
'src' => array(
"{$path}dm-sans/DMSans-Medium-Italic.woff2",
),
'font-family' => 'DM Sans',
'font-stretch' => 'normal',
'font-style' => 'italic',
'font-weight' => '500',
),
),
);

$expected_styles = <<<CSS
@font-face{font-family:"DM Sans";font-style:normal;font-weight:400;font-display:fallback;src:url('{$uri}dm-sans/DMSans-Regular.woff2') format('woff2');font-stretch:normal;}
@font-face{font-family:"DM Sans";font-style:normal;font-weight:700;font-display:fallback;src:url('{$uri}dm-sans/DMSans-Bold.woff2') format('woff2');font-stretch:normal;}
@font-face{font-family:"Open Sans";font-style:normal;font-weight:400;font-display:fallback;src:url('{$uri}open-sans/OpenSans-VariableFont_wdth,wght.ttf') format('truetype');font-stretch:normal;}
@font-face{font-family:"Open Sans";font-style:italic;font-weight:400;font-display:fallback;src:url('{$uri}open-sans/OpenSans-Italic-VariableFont_wdth,wght.ttf') format('truetype');font-stretch:normal;}
@font-face{font-family:"DM Sans";font-style:normal;font-weight:500;font-display:fallback;src:url('{$uri}dm-sans/DMSans-Medium.woff2') format('woff2');font-stretch:normal;}
@font-face{font-family:"DM Sans";font-style:italic;font-weight:500;font-display:fallback;src:url('{$uri}dm-sans/DMSans-Medium-Italic.woff2') format('woff2');font-stretch:normal;}
CSS;

if ( null === $data ) {
$data = array(
'expected' => $expected_font_families,
'expected_styles' => $expected_styles,
);
}

if ( isset( $data[ $key ] ) ) {
return $data[ $key ];
}

return $data;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php
/**
* Test case for WP_Font_Face_Resolver::get_fonts_from_style_variations().
*
* @package WordPress
* @subpackage Fonts
*
* @since 6.7.0
*
* @group fonts
* @group fontface
*
* @covers WP_Font_Face_Resolver::get_fonts_from_style_variations
*/
class Tests_Fonts_WPFontFaceResolver_GetFontsFromStyleVariations extends WP_Font_Face_UnitTestCase {
const FONTS_THEME = 'fonts-block-theme';

public static function set_up_before_class() {
self::$requires_switch_theme_fixtures = true;

parent::set_up_before_class();
}

/**
* Ensure that an empty array is returned when the theme has no style variations.
*
* @ticket 62231
*/
public function test_should_return_empty_array_when_theme_has_no_style_variations() {
switch_theme( 'block-theme' );

$fonts = WP_Font_Face_Resolver::get_fonts_from_style_variations();
$this->assertIsArray( $fonts, 'Should return an array data type' );
$this->assertEmpty( $fonts, 'Should return an empty array' );
}

/**
* Ensure that all variations are loaded from a theme.
*
* @ticket 62231
*/
public function test_should_return_all_fonts_from_all_style_variations() {
switch_theme( static::FONTS_THEME );

$actual = WP_Font_Face_Resolver::get_fonts_from_style_variations();
$expected = self::get_custom_style_variations( 'expected' );

$this->assertSame( $expected, $actual, 'All the fonts from the theme variations should be returned.' );
}

/**
* Ensure that file:./ is replaced in the src list.
*
* @ticket 62231
*/
public function test_should_replace_src_file_placeholder() {
switch_theme( static::FONTS_THEME );

$fonts = WP_Font_Face_Resolver::get_fonts_from_style_variations();

// Check that the there is no theme relative url in the src list.
foreach ( $fonts as $family ) {
foreach ( $family as $font ) {
foreach ( $font['src'] as $src ) {
$src_basename = basename( $src );
$this->assertStringNotContainsString( 'file:./', $src, "Font $src_basename should not contain the 'file:./' placeholder" );
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
/**
* Test case for wp_print_font_faces_from_style_variations().
*
* @package WordPress
* @subpackage Fonts
*
* @since 6.7.0
*
* @group fonts
* @group fontface
*
* @covers wp_print_font_faces_from_style_variations
*/
class Tests_Fonts_WpPrintFontFacesFromStyleVariations extends WP_Font_Face_UnitTestCase {
const FONTS_THEME = 'fonts-block-theme';

public static function set_up_before_class() {
parent::set_up_before_class();
self::$requires_switch_theme_fixtures = true;
}

/**
* Ensure that no fonts are printed when the theme has no fonts.
*
* @ticket 62231
*/
public function test_should_not_print_when_no_fonts() {
switch_theme( 'block-theme' );

$this->expectOutputString( '' );
wp_print_font_faces_from_style_variations();
}

/**
* Ensure that all fonts are printed from the theme style variations.
*
* @ticket 62231
*/
public function test_should_print_fonts_in_style_variations() {
switch_theme( static::FONTS_THEME );

$expected = $this->get_custom_style_variations( 'expected_styles' );
$expected_output = $this->get_expected_styles_output( $expected );

$this->expectOutputString( $expected_output );
wp_print_font_faces_from_style_variations();
}

private function get_expected_styles_output( $styles ) {
$style_element = "<style class='wp-fonts-local' type='text/css'>\n%s\n</style>\n";
return sprintf( $style_element, $styles );
}
}
Loading