-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Webfonts API #37140
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
Merged
Merged
Webfonts API #37140
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
325d4d2
rebase - combining 46 commits to 1 and resolving lots of conflicts
aristath c513718
Revert changes to resolver class
oandregal c335778
Override the parts we need
oandregal f9cc7d2
Rename file for a better description
oandregal 32193e4
Add webfonts to the parent theme
aristath bfe756b
indentation fix
aristath 699ab2f
Update Global Styles endpoint to use Gutenberg callback and theme jso…
creativecoder c8144fd
rebase - combining 46 commits to 1 and resolving lots of conflicts
aristath a51d2af
Add missing textdomain
aristath 2e56ef5
add missing inline docs
aristath 42fd092
inline doc (copy from 5.9 class)
aristath 6fe2971
Remove extra blank line
aristath fc44a08
Remove non-applicable docs
aristath ddb51ce
This already exists in the parent
aristath 524d8af
add full item
aristath 32770bc
add missing global styles
aristath 151effe
remove multiples
aristath bbd3d27
update test
aristath 938771d
remove extra comma
aristath 5aa2217
Missed this in previous commit
aristath 0112e50
Remove old docs (no longer applicable)
aristath 51bcf85
doc
aristath 38d9cb3
revert 5.9 changes
aristath 33bcfd6
get_merged_data no longer needs to be overriden
aristath 9d3dd5d
use static instead of self
aristath 447daac
simplify
aristath 8a6dec7
add an explanation for when porting to wp-core
aristath f6e58dd
Revert adding fonts to the webfonts stylesheet
oandregal 19248d2
Update test
oandregal af8eb3d
explain why we skip the provider
aristath 5ed7aa1
Move webfonts-API files to the compat/wordpress-6.0 folder
aristath 0376a3e
Remove out-of-date comment
aristath 2f865fc
Trigger a notice when an unregistered provider is used.
aristath 8b63574
use error_log instead of trigger_error
aristath 88f86de
typo
aristath File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
lib/compat/wordpress-6.0/class-wp-theme-json-resolver-gutenberg.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| <?php | ||
| /** | ||
| * WP_Theme_JSON_Resolver_Gutenberg class | ||
| * | ||
| * @package gutenberg | ||
| */ | ||
|
|
||
| /** | ||
| * Class that abstracts the processing of the different data sources | ||
| * for site-level config and offers an API to work with them. | ||
| * | ||
| * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes). | ||
| * This is a low-level API that may need to do breaking changes. Please, | ||
| * use get_global_settings, get_global_styles, and get_global_stylesheet instead. | ||
| * | ||
| * @access private | ||
| */ | ||
| class WP_Theme_JSON_Resolver_Gutenberg extends WP_Theme_JSON_Resolver_5_9 { | ||
|
|
||
| /** | ||
| * Returns the theme's data. | ||
| * | ||
| * Data from theme.json will be backfilled from existing | ||
| * theme supports, if any. Note that if the same data | ||
| * is present in theme.json and in theme supports, | ||
| * the theme.json takes precedence. | ||
| * | ||
| * @param array $deprecated Deprecated argument. | ||
| * @return WP_Theme_JSON_Gutenberg Entity that holds theme data. | ||
| */ | ||
| public static function get_theme_data( $deprecated = array() ) { | ||
| if ( ! empty( $deprecated ) ) { | ||
| _deprecated_argument( __METHOD__, '5.9' ); | ||
| } | ||
| if ( null === static::$theme ) { | ||
| $theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) ); | ||
| $theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) ); | ||
| $theme_json_data = gutenberg_add_registered_webfonts_to_theme_json( $theme_json_data ); | ||
aristath marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| static::$theme = new WP_Theme_JSON_Gutenberg( $theme_json_data ); | ||
|
|
||
| if ( wp_get_theme()->parent() ) { | ||
| // Get parent theme.json. | ||
| $parent_theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json', true ) ); | ||
| $parent_theme_json_data = static::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) ); | ||
| $parent_theme_json_data = gutenberg_add_registered_webfonts_to_theme_json( $parent_theme_json_data ); | ||
| $parent_theme = new WP_Theme_JSON_Gutenberg( $parent_theme_json_data ); | ||
|
|
||
| // Merge the child theme.json into the parent theme.json. | ||
| // The child theme takes precedence over the parent. | ||
| $parent_theme->merge( static::$theme ); | ||
| static::$theme = $parent_theme; | ||
| } | ||
| } | ||
|
|
||
| /* | ||
| * We want the presets and settings declared in theme.json | ||
| * to override the ones declared via theme supports. | ||
| * So we take theme supports, transform it to theme.json shape | ||
| * and merge the static::$theme upon that. | ||
| */ | ||
| $theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_default_block_editor_settings() ); | ||
| if ( ! static::theme_has_support() ) { | ||
| if ( ! isset( $theme_support_data['settings']['color'] ) ) { | ||
| $theme_support_data['settings']['color'] = array(); | ||
| } | ||
|
|
||
| $default_palette = false; | ||
| if ( current_theme_supports( 'default-color-palette' ) ) { | ||
| $default_palette = true; | ||
| } | ||
| if ( ! isset( $theme_support_data['settings']['color']['palette'] ) ) { | ||
| // If the theme does not have any palette, we still want to show the core one. | ||
| $default_palette = true; | ||
| } | ||
| $theme_support_data['settings']['color']['defaultPalette'] = $default_palette; | ||
|
|
||
| $default_gradients = false; | ||
| if ( current_theme_supports( 'default-gradient-presets' ) ) { | ||
| $default_gradients = true; | ||
| } | ||
| if ( ! isset( $theme_support_data['settings']['color']['gradients'] ) ) { | ||
| // If the theme does not have any gradients, we still want to show the core ones. | ||
| $default_gradients = true; | ||
| } | ||
| $theme_support_data['settings']['color']['defaultGradients'] = $default_gradients; | ||
| } | ||
| $with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data ); | ||
| $with_theme_supports->merge( static::$theme ); | ||
|
|
||
| return $with_theme_supports; | ||
| } | ||
| } | ||
259 changes: 259 additions & 0 deletions
259
lib/compat/wordpress-6.0/class-wp-webfonts-provider-local.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,259 @@ | ||
| <?php | ||
| /** | ||
| * Webfonts API: Provider for locally-hosted fonts. | ||
| * | ||
| * @package WordPress | ||
| * @subpackage WebFonts | ||
| * @since 6.0.0 | ||
| */ | ||
|
|
||
| /** | ||
| * A core bundled provider for generating `@font-face` styles | ||
| * from locally-hosted font files. | ||
| * | ||
| * This provider builds an optimized `src` (for browser support) | ||
| * and then generates the `@font-face` styles. | ||
| * | ||
| * All know-how (business logic) for how to interact with and | ||
| * generate styles from locally-hosted font files is contained | ||
| * in this provider. | ||
| * | ||
| * @since 6.0.0 | ||
| */ | ||
| class WP_Webfonts_Provider_Local extends WP_Webfonts_Provider { | ||
|
|
||
| /** | ||
| * The provider's unique ID. | ||
| * | ||
| * @since 6.0.0 | ||
| * | ||
| * @var string | ||
| */ | ||
| protected $id = 'local'; | ||
|
|
||
| /** | ||
| * Gets the `@font-face` CSS styles for locally-hosted font files. | ||
| * | ||
| * This method does the following processing tasks: | ||
| * 1. Orchestrates an optimized `src` (with format) for browser support. | ||
| * 2. Generates the `@font-face` for all its webfonts. | ||
| * | ||
| * For example, when given these webfonts: | ||
| * <code> | ||
| * array( | ||
| * 'source-serif-pro.normal.200 900' => array( | ||
| * 'provider' => 'local', | ||
| * 'font_family' => 'Source Serif Pro', | ||
| * 'font_weight' => '200 900', | ||
| * 'font_style' => 'normal', | ||
| * 'src' => 'https://example.com/wp-content/themes/twentytwentytwo/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2' ), | ||
| * ), | ||
| * 'source-serif-pro.italic.400 900' => array( | ||
| * 'provider' => 'local', | ||
| * 'font_family' => 'Source Serif Pro', | ||
| * 'font_weight' => '200 900', | ||
| * 'font_style' => 'italic', | ||
| * 'src' => 'https://example.com/wp-content/themes/twentytwentytwo/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2' ), | ||
| * ), | ||
| * ) | ||
| * </code> | ||
| * | ||
| * the following `@font-face` styles are generated and returned: | ||
| * <code> | ||
| * | ||
| * @font-face{ | ||
| * font-family:"Source Serif Pro"; | ||
| * font-style:normal; | ||
| * font-weight:200 900; | ||
| * font-stretch:normal; | ||
| * src:local("Source Serif Pro"), url('/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2') format('woff2'); | ||
| * } | ||
| * @font-face{ | ||
| * font-family:"Source Serif Pro"; | ||
| * font-style:italic; | ||
| * font-weight:200 900; | ||
| * font-stretch:normal; | ||
| * src:local("Source Serif Pro"), url('/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2') format('woff2'); | ||
| * } | ||
| * </code> | ||
| * | ||
| * @since 6.0.0 | ||
| * | ||
| * @return string The `@font-face` CSS. | ||
| */ | ||
| public function get_css() { | ||
| $css = ''; | ||
|
|
||
| foreach ( $this->webfonts as $webfont ) { | ||
| // Order the webfont's `src` items to optimize for browser support. | ||
| $webfont = $this->order_src( $webfont ); | ||
|
|
||
| // Build the @font-face CSS for this webfont. | ||
| $css .= '@font-face{' . $this->build_font_face_css( $webfont ) . '}'; | ||
| } | ||
|
|
||
| return $css; | ||
| } | ||
|
|
||
| /** | ||
| * Order `src` items to optimize for browser support. | ||
| * | ||
| * @since 6.0.0 | ||
| * | ||
| * @param array $webfont Webfont to process. | ||
| * @return array | ||
| */ | ||
| private function order_src( array $webfont ) { | ||
| if ( ! is_array( $webfont['src'] ) ) { | ||
| $webfont['src'] = (array) $webfont['src']; | ||
| } | ||
|
|
||
| $src = array(); | ||
| $src_ordered = array(); | ||
|
|
||
| foreach ( $webfont['src'] as $url ) { | ||
| // Add data URIs first. | ||
| if ( 0 === strpos( trim( $url ), 'data:' ) ) { | ||
| $src_ordered[] = array( | ||
| 'url' => $url, | ||
| 'format' => 'data', | ||
| ); | ||
| continue; | ||
| } | ||
| $format = pathinfo( $url, PATHINFO_EXTENSION ); | ||
| $src[ $format ] = $url; | ||
| } | ||
|
|
||
| // Add woff2. | ||
| if ( ! empty( $src['woff2'] ) ) { | ||
| $src_ordered[] = array( | ||
| 'url' => $src['woff2'], | ||
| 'format' => 'woff2', | ||
| ); | ||
| } | ||
|
|
||
| // Add woff. | ||
| if ( ! empty( $src['woff'] ) ) { | ||
| $src_ordered[] = array( | ||
| 'url' => $src['woff'], | ||
| 'format' => 'woff', | ||
| ); | ||
| } | ||
|
|
||
| // Add ttf. | ||
| if ( ! empty( $src['ttf'] ) ) { | ||
| $src_ordered[] = array( | ||
| 'url' => $src['ttf'], | ||
| 'format' => 'truetype', | ||
| ); | ||
| } | ||
|
|
||
| // Add eot. | ||
| if ( ! empty( $src['eot'] ) ) { | ||
| $src_ordered[] = array( | ||
| 'url' => $src['eot'], | ||
| 'format' => 'embedded-opentype', | ||
| ); | ||
| } | ||
|
|
||
| // Add otf. | ||
| if ( ! empty( $src['otf'] ) ) { | ||
| $src_ordered[] = array( | ||
| 'url' => $src['otf'], | ||
| 'format' => 'opentype', | ||
| ); | ||
| } | ||
| $webfont['src'] = $src_ordered; | ||
|
|
||
| return $webfont; | ||
| } | ||
|
|
||
| /** | ||
| * Builds the font-family's CSS. | ||
| * | ||
| * @since 6.0.0 | ||
| * | ||
| * @param array $webfont Webfont to process. | ||
| * @return string This font-family's CSS. | ||
| */ | ||
| private function build_font_face_css( array $webfont ) { | ||
| $css = ''; | ||
|
|
||
| // Wrap font-family in quotes if it contains spaces. | ||
| if ( | ||
| false !== strpos( $webfont['font-family'], ' ' ) && | ||
| false === strpos( $webfont['font-family'], '"' ) && | ||
| false === strpos( $webfont['font-family'], "'" ) | ||
| ) { | ||
| $webfont['font-family'] = '"' . $webfont['font-family'] . '"'; | ||
| } | ||
|
|
||
| foreach ( $webfont as $key => $value ) { | ||
|
|
||
| // Skip "provider", since it's for internal API use, | ||
| // and not a valid CSS property. | ||
| if ( 'provider' === $key ) { | ||
| continue; | ||
| } | ||
|
|
||
| // Compile the "src" parameter. | ||
| if ( 'src' === $key ) { | ||
| $value = $this->compile_src( $webfont['font-family'], $value ); | ||
| } | ||
|
|
||
| // If font-variation-settings is an array, convert it to a string. | ||
| if ( 'font-variation-settings' === $key && is_array( $value ) ) { | ||
| $value = $this->compile_variations( $value ); | ||
| } | ||
|
|
||
| if ( ! empty( $value ) ) { | ||
| $css .= "$key:$value;"; | ||
| } | ||
| } | ||
|
|
||
| return $css; | ||
| } | ||
|
|
||
| /** | ||
| * Compiles the `src` into valid CSS. | ||
| * | ||
| * @since 6.0.0 | ||
| * | ||
| * @param string $font_family Font family. | ||
| * @param array $value Value to process. | ||
| * @return string The CSS. | ||
| */ | ||
| private function compile_src( $font_family, array $value ) { | ||
| $src = "local($font_family)"; | ||
|
|
||
| foreach ( $value as $item ) { | ||
|
|
||
| if ( 0 === strpos( $item['url'], get_site_url() ) ) { | ||
| $item['url'] = wp_make_link_relative( $item['url'] ); | ||
| } | ||
|
|
||
| $src .= ( 'data' === $item['format'] ) | ||
| ? ", url({$item['url']})" | ||
| : ", url('{$item['url']}') format('{$item['format']}')"; | ||
| } | ||
| return $src; | ||
| } | ||
|
|
||
| /** | ||
| * Compiles the font variation settings. | ||
| * | ||
| * @since 6.0.0 | ||
| * | ||
| * @param array $font_variation_settings Array of font variation settings. | ||
| * @return string The CSS. | ||
| */ | ||
| private function compile_variations( array $font_variation_settings ) { | ||
| $variations = ''; | ||
|
|
||
| foreach ( $font_variation_settings as $key => $value ) { | ||
| $variations .= "$key $value"; | ||
| } | ||
|
|
||
| return $variations; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.