Make WordPress Core

Changeset 57657


Ignore:
Timestamp:
02/20/2024 07:09:43 AM (3 years ago)
Author:
youknowriad
Message:

Editor: Format and sanitize font family names according the CSS spec.

This fixes two bugs in the font library.

  • Fonts using special characters were not being rendered properly in the frontend.
  • Allows the ability to use generic() in font family names.

Props mmaattiiaass, nithins53, kafleg, vivekawsm, swissspidy, audrasjb.
Fixes #60537.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/fonts/class-wp-font-collection.php

    r57539 r57657  
    220220                                        'font_family_settings' => array(
    221221                                                'name'       => 'sanitize_text_field',
    222                                                 'slug'       => 'sanitize_title',
    223                                                 'fontFamily' => 'sanitize_text_field',
     222                                                'slug'       => static function ( $value ) {
     223                                                        return _wp_to_kebab_case( sanitize_title( $value ) );
     224                                                },
     225                                                'fontFamily' => 'WP_Font_Utils::sanitize_font_family',
    224226                                                'preview'    => 'sanitize_url',
    225227                                                'fontFace'   => array(
  • trunk/src/wp-includes/fonts/class-wp-font-utils.php

    r57632 r57657  
    2020class WP_Font_Utils {
    2121        /**
     22         * Adds surrounding quotes to font family names that contain special characters.
     23         *
     24         * It follows the recommendations from the CSS Fonts Module Level 4.
     25         * @link https://www.w3.org/TR/css-fonts-4/#font-family-prop
     26         *
     27         * @since 6.5.0
     28         *
     29         * @param string $item A font family name.
     30         * @return string The font family name with surrounding quotes, if necessary.
     31         */
     32        private static function maybe_add_quotes( $item ) {
     33                // Matches strings that are not exclusively alphabetic characters or hyphens, and do not exactly follow the pattern generic(alphabetic characters or hyphens).
     34                $regex = '/^(?!generic\([a-zA-Z\-]+\)$)(?!^[a-zA-Z\-]+$).+/';
     35                $item  = trim( $item );
     36                if ( preg_match( $regex, $item ) ) {
     37                        $item = trim( $item, "\"'" );
     38                        return '"' . $item . '"';
     39                }
     40                return $item;
     41        }
     42
     43        /**
    2244         * Sanitizes and formats font family names.
    2345         *
    24          * - Applies `sanitize_text_field`
    25          * - Adds surrounding quotes to names that contain spaces and are not already quoted
     46         * - Applies `sanitize_text_field`.
     47         * - Adds surrounding quotes to names containing any characters that are not alphabetic or dashes.
     48         *
     49         * It follows the recommendations from the CSS Fonts Module Level 4.
     50         * @link https://www.w3.org/TR/css-fonts-4/#font-family-prop
    2651         *
    2752         * @since 6.5.0
    … …  
    3863                }
    3964
    40                 $font_family           = sanitize_text_field( $font_family );
    41                 $font_families         = explode( ',', $font_family );
    42                 $wrapped_font_families = array_map(
    43                         function ( $family ) {
    44                                 $trimmed = trim( $family );
    45                                 if ( ! empty( $trimmed ) && str_contains( $trimmed, ' ' ) && ! str_contains( $trimmed, "'" ) && ! str_contains( $trimmed, '"' ) ) {
    46                                                 return '"' . $trimmed . '"';
     65                $output          = sanitize_text_field( $font_family );
     66                $formatted_items = array();
     67                if ( str_contains( $output, ',' ) ) {
     68                        $items = explode( ',', $output );
     69                        foreach ( $items as $item ) {
     70                                $formatted_item = self::maybe_add_quotes( $item );
     71                                if ( ! empty( $formatted_item ) ) {
     72                                        $formatted_items[] = $formatted_item;
    4773                                }
    48                                 return $trimmed;
    49                         },
    50                         $font_families
    51                 );
    52 
    53                 if ( count( $wrapped_font_families ) === 1 ) {
    54                         $font_family = $wrapped_font_families[0];
    55                 } else {
    56                         $font_family = implode( ', ', $wrapped_font_families );
    57                 }
    58 
    59                 return $font_family;
     74                        }
     75                        return implode( ', ', $formatted_items );
     76                }
     77                return self::maybe_add_quotes( $output );
    6078        }
    6179
  • trunk/tests/phpunit/tests/fonts/font-library/wpFontCollection/getData.php

    r57539 r57657  
    160160                                                array(
    161161                                                        'font_family_settings' => array(
    162                                                                 'fontFamily' => 'Open Sans, sans-serif',
     162                                                                'fontFamily' => '"Open Sans", sans-serif',
    163163                                                                'slug'       => 'open-sans',
    164164                                                                'name'       => 'Open Sans',
  • trunk/tests/phpunit/tests/fonts/font-library/wpFontUtils/sanitizeFontFamily.php

    r57539 r57657  
    3636                return array(
    3737                        'data_families_with_spaces_and_numbers' => array(
    38                                 'font_family' => 'Rock 3D , Open Sans,serif',
    39                                 'expected'    => '"Rock 3D", "Open Sans", serif',
     38                                'font_family' => 'Arial, Rock 3D , Open Sans,serif',
     39                                'expected'    => 'Arial, "Rock 3D", "Open Sans", serif',
    4040                        ),
    4141                        'data_single_font_family'               => array(
    4242                                'font_family' => 'Rock 3D',
    4343                                'expected'    => '"Rock 3D"',
    44                         ),
    45                         'data_no_spaces'                        => array(
    46                                 'font_family' => 'Rock3D',
    47                                 'expected'    => 'Rock3D',
    4844                        ),
    4945                        'data_many_spaces_and_existing_quotes'  => array(
    … …  
    5955                                'expected'    => '"Rock 3D"',
    6056                        ),
     57                        'data_font_family_with_generic_names'   => array(
     58                                'font_family' => 'generic(kai), generic(font[name]), generic(fangsong), Rock 3D',
     59                                'expected'    => 'generic(kai), "generic(font[name])", generic(fangsong), "Rock 3D"',
     60                        ),
    6161                );
    6262        }
  • trunk/tests/phpunit/tests/fonts/font-library/wpRestFontFamiliesController.php

    r57548 r57657  
    682682                $settings = array(
    683683                        'name'       => 'Open Sans',
    684                         'fontFamily' => '"Open Sans, "Noto Sans", sans-serif',
     684                        'fontFamily' => 'Open Sans, "Noto Sans", sans-serif',
    685685                        'preview'    => 'https://s.w.org/images/fonts/16.9/previews/open-sans/open-sans-400-normal.svg',
    686686                );
    … …  
    701701                        'name'       => $settings['name'],
    702702                        'slug'       => 'open-sans-2',
    703                         'fontFamily' => $settings['fontFamily'],
     703                        'fontFamily' => '"Open Sans", "Noto Sans", sans-serif',
    704704                        'preview'    => $settings['preview'],
    705705                );
Note: See TracChangeset for help on using the changeset viewer.