Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
560da82
Fonts: Keep font names through CSS validation, storage, and output.
matiasbenedetto Sep 18, 2026
3d3d459
Fonts: Simplify the font family parser and the KSES declaration split…
matiasbenedetto Sep 18, 2026
7c82a49
Fonts: Simplify the CSS parser and validate generic arguments.
matiasbenedetto Sep 18, 2026
c93fcf1
Merge remote-tracking branch 'origin/trunk' into fix-font-chars
matiasbenedetto Oct 1, 2026
9cf4435
Fonts: Simplify the plain name and escape checks in WP_CSS_Font_Family.
matiasbenedetto Oct 2, 2026
f04b9e5
Fonts: Move the CSS font family parser into WP_Font_Utils.
matiasbenedetto Oct 2, 2026
6913a32
Fonts: Fix the KSES split, system font quotes, legacy slugs, and plai…
matiasbenedetto Oct 2, 2026
36d4a20
Merge remote-tracking branch 'origin/trunk' into fix-font-chars
matiasbenedetto Oct 2, 2026
66cbc2e
Fonts: Escape the comma in a serialized font name.
matiasbenedetto Oct 5, 2026
a3ea6b9
Fonts: Reduce the changes in the font face resolver and the slug func…
matiasbenedetto Oct 5, 2026
4d54df7
Merge remote-tracking branch 'origin/trunk' into fix-font-chars
matiasbenedetto Oct 5, 2026
5268214
Fonts: Accept a raw font name that is not valid CSS.
matiasbenedetto Oct 5, 2026
88508e2
Fonts: Test that a raw name with outer spaces uses the trimmed name.
matiasbenedetto Oct 5, 2026
fdc829b
Fonts: Add tests for the cases of the font name test guide.
matiasbenedetto Oct 6, 2026
be5d8ec
Fonts: Reduce the public methods of the font family parser.
matiasbenedetto Oct 6, 2026
1a7bae7
Fonts: Preserve quoted names and detect legacy duplicate faces.
matiasbenedetto Oct 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/wp-includes/fonts/class-wp-font-collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ private static function get_sanitization_schema() {
'preview' => 'sanitize_url',
'fontFace' => array(
array(
'fontFamily' => 'sanitize_text_field',
'fontFamily' => 'WP_Font_Utils::sanitize_font_family',
'fontStyle' => 'sanitize_text_field',
'fontWeight' => 'sanitize_text_field',
'src' => static function ( $value ) {
Expand Down
7 changes: 2 additions & 5 deletions src/wp-includes/fonts/class-wp-font-face-resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,13 @@ private static function parse_settings( array $settings ) {
* parse and return the fist font from the list.
*
* @since 6.4.0
* @since 7.2.0 Returns the name as a quoted CSS string, or an empty string if the value is invalid.
*
* @param string $font_family Font family `fontFamily' to parse.
* @return string Font-family name.
*/
private static function maybe_parse_name_from_comma_separated_list( $font_family ) {
if ( str_contains( $font_family, ',' ) ) {
$font_family = explode( ',', $font_family )[0];
}

return trim( $font_family, "\"'" );
return WP_Font_Utils::get_font_face_family( $font_family );
}

/**
Expand Down
36 changes: 22 additions & 14 deletions src/wp-includes/fonts/class-wp-font-face.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* Font Face generates and prints `@font-face` styles for given fonts.
*
* @since 6.4.0
* @since 7.2.0 Writes the font-family descriptor as a quoted CSS string.
*/
class WP_Font_Face {

Expand Down Expand Up @@ -82,8 +83,9 @@ public function generate_and_print( array $fonts ) {

/*
* The font-face CSS is contained within <style> tags and can only be interpreted
* as CSS in the browser. Using wp_strip_all_tags() is sufficient escaping
* to avoid malicious attempts to close </style> and open a <script>.
* as CSS in the browser. The font-family descriptor escapes `<` as a CSS escape,
* so a font name cannot close the style element. wp_strip_all_tags() removes any
* remaining markup from the other descriptors.
*/
$css = wp_strip_all_tags( $css );

Expand Down Expand Up @@ -146,6 +148,23 @@ private function validate_font_face_declarations( array $font_face ) {
return false;
}

/*
* Write the font-family descriptor as a quoted CSS string. The value
* can be CSS, such as `"ACME, Sans"`, or a plain name, such as
* `O'Reilly Sans`. The decoded name does not change.
*/
$font_face['font-family'] = WP_Font_Utils::get_font_face_family( $font_face['font-family'] );

if ( '' === $font_face['font-family'] ) {
// @todo replace with `wp_trigger_error()`.
_doing_it_wrong(
__METHOD__,
__( 'Font font-family must be a valid CSS font family value or a plain font name.' ),
'7.2.0'
);
return false;
}

// Make sure that local fonts have 'src' defined.
if ( empty( $font_face['src'] ) || ( ! is_string( $font_face['src'] ) && ! is_array( $font_face['src'] ) ) ) {
// @todo replace with `wp_trigger_error()`.
Expand Down Expand Up @@ -307,18 +326,7 @@ private function order_src( array $font_face ) {
private function build_font_face_css( array $font_face ) {
$css = '';

/*
* Wrap font-family in quotes if it contains spaces
* and is not already wrapped in quotes.
*/
if (
str_contains( $font_face['font-family'], ' ' ) &&
! str_contains( $font_face['font-family'], '"' ) &&
! str_contains( $font_face['font-family'], "'" )
) {
$font_face['font-family'] = '"' . $font_face['font-family'] . '"';
}

// The font-family is already a quoted CSS string. See ::validate_font_face_declarations().
foreach ( $font_face as $key => $value ) {
// Compile the "src" parameter.
if ( 'src' === $key ) {
Expand Down
Loading
Loading