Changeset 3743505 for optimazz/trunk/includes/Modules/Fonts/FontsModule.php
- Timestamp:
- 10/13/2026 10:00:51 AM (2 weeks ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
optimazz/trunk/includes/Modules/Fonts/FontsModule.php
r3715895 r3743505 21 21 22 22 class FontsModule extends AbstractModule { 23 24 /** 25 * Whether parse_css2() repaired an invalid (CSS1-style) family request on 26 * the current page, so the rebuilt URL must be output even when nothing 27 * else changes. 28 * 29 * @var bool 30 */ 31 private static $repaired = false; 23 32 24 33 public function id() { … … 157 166 return $html; 158 167 } 168 self::$repaired = false; 159 169 160 170 $links = array(); // Tags we will merge (in document order). … … 173 183 } 174 184 $query = (string) wp_parse_url( html_entity_decode( $m[2], ENT_QUOTES ), PHP_URL_QUERY ); // decode first: "&" contains a "#" that would truncate the query. 185 $was = self::$repaired; 175 186 $parsed = 'css2' === strtolower( $m[3] ) ? self::parse_css2( $query ) : self::parse_css1( $query ); 176 187 if ( null === $parsed ) { 188 self::$repaired = $was; // This link is left as-is, so nothing was repaired. 177 189 continue; // unsupported form — keep as-is. 178 190 } … … 197 209 } 198 210 $trim = (bool) $this->option( 'trim_weights', true ); 199 // One link and nothing to trim — nothing to gain. 200 if ( 1 === count( $links ) && ! $trim ) { 211 $disp = '' !== $display ? $display : $orig_display; 212 // Non-blocking load only with swap / fallback. Those swap the font in 213 // anyway; 'optional' is chosen for zero layout shift, and loading its 214 // stylesheet late would make a cached font swap in after first paint. 215 $async = in_array( $disp, array( 'swap', 'fallback' ), true ) && $this->option( 'async_google', true ); 216 // One link, nothing to trim, nothing repaired and no async loading — 217 // rebuilding the URL would gain nothing (and would drop its other 218 // attributes and parameters). 219 if ( 1 === count( $links ) && ! $trim && ! $async && ! self::$repaired ) { 201 220 return $html; 202 221 } … … 208 227 $params[] = 'family=' . str_replace( '%20', '+', rawurlencode( $name ) ) . self::css2_axis( $spec, $used ); 209 228 } 210 $disp = '' !== $display ? $display : $orig_display;211 229 if ( '' !== $disp ) { 212 230 $params[] = 'display=' . $disp; 213 231 } 214 $url = 'https://fonts.googleapis.com/css2?' . implode( '&', $params ); 215 // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet -- rewriting existing output-buffer markup, not enqueueing. 216 $new = '<link rel="stylesheet" id="optimazz-google-fonts" href="' . esc_url( $url ) . '" media="all">'; 232 $url = esc_url( 'https://fonts.googleapis.com/css2?' . implode( '&', $params ) ); 233 // phpcs:disable WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet -- rewriting existing output-buffer markup, not enqueueing. 234 if ( $async ) { 235 // With swap/fallback the text renders in a fallback font first 236 // anyway, so the font stylesheet need not block the page: on 237 // mobile it otherwise holds back the first paint by the full round 238 // trip to Google. Preload it, apply it when loaded, and keep a 239 // <noscript> copy for visitors without JavaScript. 240 $new = '<link rel="preload" as="style" href="' . $url . '">' 241 . '<link rel="stylesheet" id="optimazz-google-fonts" href="' . $url . '" media="print" onload="this.media=\'all\'">' 242 . '<noscript><link rel="stylesheet" href="' . $url . '"></noscript>'; 243 } else { 244 $new = '<link rel="stylesheet" id="optimazz-google-fonts" href="' . $url . '" media="all">'; 245 } 246 // phpcs:enable WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet 217 247 218 248 // Swap the first link for the merged one; remove the rest (each once). … … 252 282 continue; 253 283 } 254 $spec = array( 'normal' => array(), 'italic' => array(), 'raw' => null ); 255 $vars = isset( $parts[1] ) ? explode( ',', $parts[1] ) : array( '400' ); 256 foreach ( $vars as $v ) { 257 $v = strtolower( trim( $v ) ); 258 if ( '' === $v ) { 259 continue; 260 } 261 $v = strtr( $v, array( 'regular' => '400', 'bold' => '700' ) ); 262 $ital = (bool) preg_match( '/(italic|i)$/', $v ); 263 $w = (int) preg_replace( '/\D/', '', $v ); 264 $w = $w ? $w : 400; // bare "italic". 265 if ( $w < 100 || $w > 900 ) { 266 continue; 267 } 268 $spec[ $ital ? 'italic' : 'normal' ][ $w ] = 1; 269 } 270 if ( empty( $spec['normal'] ) && empty( $spec['italic'] ) ) { 271 $spec['normal'][400] = 1; 272 } 273 $out[ $name ] = $spec; 284 $out[ $name ] = self::parse_variants( isset( $parts[1] ) ? $parts[1] : '400' ); 274 285 } 275 286 } 276 287 return $out ? $out : null; 288 } 289 290 /** 291 * Parse a CSS1-style variant list ("400,700i,bold,italic") into a spec. 292 * 293 * @param string $list Comma-separated variants. 294 * @return array{normal:array,italic:array,raw:null} 295 */ 296 private static function parse_variants( $list ) { 297 $spec = array( 'normal' => array(), 'italic' => array(), 'raw' => null ); 298 foreach ( explode( ',', $list ) as $v ) { 299 $v = strtolower( trim( $v ) ); 300 if ( '' === $v ) { 301 continue; 302 } 303 $v = strtr( $v, array( 'regular' => '400', 'bold' => '700' ) ); 304 $ital = (bool) preg_match( '/(italic|i)$/', $v ); 305 $w = (int) preg_replace( '/\D/', '', $v ); 306 $w = $w ? $w : 400; // bare "italic". 307 if ( $w < 100 || $w > 900 ) { 308 continue; 309 } 310 $spec[ $ital ? 'italic' : 'normal' ][ $w ] = 1; 311 } 312 if ( empty( $spec['normal'] ) && empty( $spec['italic'] ) ) { 313 $spec['normal'][400] = 1; 314 } 315 return $spec; 277 316 } 278 317 … … 314 353 $spec['normal'][ (int) $w ] = 1; 315 354 } 355 } elseif ( preg_match( '/^(?:w?\d{3}i?|regular|bold|italic|bolditalic|\d{3}italic)(?:,(?:w?\d{3}i?|regular|bold|italic|bolditalic|\d{3}italic))*$/i', trim( $parts[1] ) ) ) { 356 // Old CSS1-style weights ("400,700", or the "w400,700" some themes 357 // print) sent to the CSS2 API. Google rejects these with HTTP 400, so 358 // the font never loads while the broken stylesheet still blocks 359 // rendering. Read them the CSS1 way so a valid request is built. 360 $spec = self::parse_variants( str_ireplace( 'w', '', $parts[1] ) ); 361 self::$repaired = true; 316 362 } else { 317 363 $spec['raw'] = $parts[1]; // variable ranges / other axes — keep verbatim.
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)