Skip to content

Commit

Permalink
Add Font Face and its tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hellofromtonya committed Aug 22, 2023
1 parent 5a99ab4 commit dc41ea2
Show file tree
Hide file tree
Showing 34 changed files with 1,750 additions and 0 deletions.
1 change: 1 addition & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@
<element value="WP_Test_Adjacent_Image_Link_TestCase"/>
<element value="WP_Tests_Image_Resize_UnitTestCase"/>
<element value="WP_Theme_UnitTestCase"/>
<element value="WP_Font_Face_UnitTestCase"/>

<!-- Mock classes. -->
<element value="Spy_REST_Server"/>
Expand Down
3 changes: 3 additions & 0 deletions src/wp-admin/includes/admin-filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,6 @@

// Append '(Draft)' to draft page titles in the privacy page dropdown.
add_filter( 'list_pages', '_wp_privacy_settings_filter_draft_page_titles', 10, 2 );

// Font management.
add_action( 'admin_print_styles', 'wp_print_font_faces', 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 @@ -361,6 +361,7 @@ function _wp_get_iframed_editor_assets() {

ob_start();
wp_print_styles();
wp_print_font_faces();
$styles = ob_get_clean();

ob_start();
Expand Down
3 changes: 3 additions & 0 deletions src/wp-includes/default-filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -719,4 +719,7 @@
// CPT wp_block custom postmeta field.
add_action( 'init', 'wp_create_initial_post_meta' );

// Font management.
add_action( 'wp_head', 'wp_print_font_faces', 50 );

unset( $filter, $action );
154 changes: 154 additions & 0 deletions src/wp-includes/fonts/font-face/class-wp-font-face-resolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?php
/**
* WP_Font_Face_Resolver class.
*
* @package WordPress
* @subpackage Fonts
* @since 6.4.0
*/

/**
* The Font Face Resolver abstracts the processing of different data sources
* (such as theme.json) for processing within the Font Face.
*
* This class is for internal core usage and is not supposed to be used by
* extenders (plugins and/or themes).
*
* @access private
*/
class WP_Font_Face_Resolver {

/**
* Gets fonts defined in theme.json.
*
* @since 6.4.0
*
* @return array Returns the font-families, each with their font-face variations.
*/
public static function get_fonts_from_theme_json() {
$settings = WP_Theme_JSON_Resolver::get_merged_data()->get_settings();

// Bail out early if there are no font settings.
if ( empty( $settings['typography'] ) || empty( $settings['typography']['fontFamilies'] ) ) {
return array();
}

return static::parse_settings( $settings );
}

/**
* Parse theme.json settings to extract font definitions with variations grouped by font-family.
*
* @since 6.4.0
*
* @param array $settings Font settings to parse.
* @return array Returns an array of fonts, grouped by font-family.
*/
private static function parse_settings( array $settings ) {
$fonts = array();

foreach ( $settings['typography']['fontFamilies'] as $font_families ) {
foreach ( $font_families as $definition ) {

// Skip if font-family "name" is not defined.
if ( empty( $definition['name'] ) ) {
continue;
}

// Skip if "fontFace" is not defined, meaning there are no variations.
if ( empty( $definition['fontFace'] ) ) {
continue;
}

$font_family = $definition['name'];

// Prepare the fonts array structure for this font-family.
if ( ! array_key_exists( $font_family, $fonts ) ) {
$fonts[ $font_family ] = array();
}

$fonts[ $font_family ] = static::convert_font_face_properties( $definition['fontFace'], $font_family );
}
}

return $fonts;
}

/**
* Converts font-face properties from theme.json format.
*
* @since 6.4.0
*
* @param array $font_face_definition The font-face definitions to convert.
* @param string $font_family_property The value to store in the font-face font-family property.
* @return array Converted font-face properties.
*/
private static function convert_font_face_properties( array $font_face_definition, $font_family_property ) {
$converted_font_faces = array();

foreach ( $font_face_definition as $font_face ) {
// Add the font-family property to the font-face.
$font_face['font-family'] = $font_family_property;

// Converts the "file:./" src placeholder into a theme font file URI.
if ( ! empty( $font_face['src'] ) ) {
$font_face['src'] = static::to_theme_file_uri( (array) $font_face['src'] );
}

// Convert camelCase properties into kebab-case.
$font_face = static::to_kebab_case( $font_face );

$converted_font_faces[] = $font_face;
}

return $converted_font_faces;
}

/**
* Converts each 'file:./' placeholder into a URI to the font file in the theme.
*
* The 'file:./' is specified in the theme's `theme.json` as a placeholder to be
* replaced with the URI to the font file's location in the theme. When a "src"
* beings with this placeholder, it is replaced, converting the src into a URI.
*
* @since 6.4.0
*
* @param array $src An array of font file sources to process.
* @return array An array of font file src URI(s).
*/
private static function to_theme_file_uri( array $src ) {
$placeholder = 'file:./';

foreach ( $src as $src_key => $src_url ) {
// Skip if the src doesn't start with the placeholder, as there's nothing to replace.
if ( ! str_starts_with( $src_url, $placeholder ) ) {
continue;
}

$src_file = str_replace( $placeholder, '', $src_url );
$src[ $src_key ] = get_theme_file_uri( $src_file );
}

return $src;
}

/**
* Converts all first dimension keys into kebab-case.
*
* @since 6.4.0
*
* @param array $data The array to process.
* @return array Data with first dimension keys converted into kebab-case.
*/
private static function to_kebab_case( array $data ) {
foreach ( $data as $key => $value ) {
$kebab_case = _wp_to_kebab_case( $key );
$data[ $kebab_case ] = $value;
if ( $kebab_case !== $key ) {
unset( $data[ $key ] );
}
}

return $data;
}
}
Loading

0 comments on commit dc41ea2

Please sign in to comment.