From 0ab1c751aa2f8edec45dd81a7d47694c346433c3 Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Tue, 1 Mar 2022 14:43:48 +1000 Subject: [PATCH 01/18] Add a CDNise mu-plugin. --- mu-plugins/cdn/cdn-assets.php | 118 ++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 mu-plugins/cdn/cdn-assets.php diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php new file mode 100644 index 00000000..67ae7d65 --- /dev/null +++ b/mu-plugins/cdn/cdn-assets.php @@ -0,0 +1,118 @@ +[^&]+)$!i', $url_args, $url_cachebuster ) + ) { + return $link; + } + + $version = false; + // Set the version to the file modification time, for consistency. + if ( ! is_timestamp( $url_cachebuster['version'] ) ) { + $version = filemtime( ABSPATH . $filepath ); + } + if ( ! $version ) { + $version = $url_cachebuster['version']; + } + + // Chunk the cache buster on a ~2 minute rolling window. + // This allows for the production deploy process taking a few minutes, setting different modification times on different servers. + if ( + 'production' === wp_get_environment_type() && + is_timestamp( $version ) + ) { + $window = 2 * MINUTE_IN_SECONDS; + $version = floor( $version / $window ) * $window; + } + + $use_cdn = ( + // CDN is used in production by default. + 'production' === wp_get_environment_type() || + + // Allow other environments to opt-in via constant. + ( defined( 'USE_WPORG_CDN' ) && USE_WPORG_CDN ) + ); + + // These scripts/styles break if loaded from the CDN without CORS headers. + // See https://make.wordpress.org/systems/2022/02/22/cors-headers-for-s-w-org/ + $blocked_handles = [ + 'wporg-news-style', // Mask images + 'wporg-global-fonts-css', 'jetpack-icons', 'wp-stream-icons', // Fonts + ]; + if ( in_array( $handle, $blocked_handles, true ) ) { + $use_cdn = false; + } + + $link = 'https://' . ( $use_cdn ? 's.w.org' : $_SERVER['HTTP_HOST'] ) . '/' . $filepath; + + // Add the version back onto the URL. + $link = add_query_arg( 'ver', $version, $link ); + + return $link; +} +add_filter( 'style_loader_src', __NAMESPACE__ . '\cdnise_with_filemtime_cachebuster', 5, 2 ); +add_filter( 'script_loader_src', __NAMESPACE__ . '\cdnise_with_filemtime_cachebuster', 5, 2 ); + +/** + * Determine if a string appears to be a timestamp. + * + * Due to the use-case here, we're assuming that the timestamp will occur + * between Y2.01K and now. + * + * @param string|int $string The string to check. + * @return bool Whether the input appears to be a UTC timestamp. + */ +function is_timestamp( $string ) { + return ( + is_numeric( $string ) && + $string >= 1262304000 /* Y2.01K - 2010-01-01 */ && + $string <= time() + ); +} From 68d17c7b6e62f8de57b55cf376f559eb5c98d5f5 Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Tue, 1 Mar 2022 14:45:36 +1000 Subject: [PATCH 02/18] Fix whitespace. --- mu-plugins/cdn/cdn-assets.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php index 67ae7d65..7f5093b8 100644 --- a/mu-plugins/cdn/cdn-assets.php +++ b/mu-plugins/cdn/cdn-assets.php @@ -25,7 +25,7 @@ function cdnise_with_filemtime_cachebuster( $link, $handle = '' ) { if ( ! str_starts_with( $link, site_url( '/' ) ) || ! str_contains( $link, 'wordpress.org' ) || - str_contains( $link, 'profiles.wordpress.org' ) + str_contains( $link, 'profiles.wordpress.org' ) ) { return $link; } From f198491e91186ce990094be8fa7c4addfa956f68 Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Tue, 1 Mar 2022 14:59:02 +1000 Subject: [PATCH 03/18] Use `parse_str()` instead of `preg_match()`. --- mu-plugins/cdn/cdn-assets.php | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php index 7f5093b8..a0bb3461 100644 --- a/mu-plugins/cdn/cdn-assets.php +++ b/mu-plugins/cdn/cdn-assets.php @@ -20,7 +20,7 @@ * @param string $handle The asset handle, used to skip certain assets. * @return string The potentially CDNised URL. */ -function cdnise_with_filemtime_cachebuster( $link, $handle = '' ) { +function with_filemtime_cachebuster( $link, $handle = '' ) { // Only same-host resources, and WordPress.org domains. if ( ! str_starts_with( $link, site_url( '/' ) ) || @@ -30,36 +30,41 @@ function cdnise_with_filemtime_cachebuster( $link, $handle = '' ) { return $link; } + $url_args = []; $relative_url = str_replace( site_url( '/' ), '', $link ); if ( str_contains( $relative_url, '?' ) ) { - list( $filepath, $url_args ) = explode( '?', $relative_url, 2 ); + list( $filepath, $url_part_args ) = explode( '?', $relative_url, 2 ); + + parse_str( $url_part_args, $url_args ); } else { $filepath = $relative_url; - $url_args = ''; + // No `$url_args` here. // Webpack files often include the cache-buster in the filename, 'react' does this. // Pretend that's the cache buster for the rest of the function. if ( preg_match( '!\.([a-f0-9]{8})\.(min\.)?js$!', $filepath, $m ) ) { - $url_args = 'ver=' . $m[1]; + $url_args = [ + 'ver' => $m[1] + ]; } } - // If the link doesn't have a cache-buster already, or has extra args, abort. + // If the link doesn't have a cache-buster, or has extra args, abort. if ( - ! $url_args || - ! preg_match( '!^ver=(?P[^&]+)$!i', $url_args, $url_cachebuster ) + empty( $url_args['ver'] ) || + count( $url_args ) > 1 ) { return $link; } - $version = false; // Set the version to the file modification time, for consistency. - if ( ! is_timestamp( $url_cachebuster['version'] ) ) { + $version = false; + if ( ! is_timestamp( $url_args['ver'] ) ) { $version = filemtime( ABSPATH . $filepath ); } if ( ! $version ) { - $version = $url_cachebuster['version']; + $version = $url_args['ver']; } // Chunk the cache buster on a ~2 minute rolling window. @@ -97,8 +102,8 @@ function cdnise_with_filemtime_cachebuster( $link, $handle = '' ) { return $link; } -add_filter( 'style_loader_src', __NAMESPACE__ . '\cdnise_with_filemtime_cachebuster', 5, 2 ); -add_filter( 'script_loader_src', __NAMESPACE__ . '\cdnise_with_filemtime_cachebuster', 5, 2 ); +add_filter( 'style_loader_src', __NAMESPACE__ . '\with_filemtime_cachebuster', 5, 2 ); +add_filter( 'script_loader_src', __NAMESPACE__ . '\with_filemtime_cachebuster', 5, 2 ); /** * Determine if a string appears to be a timestamp. From 12f03497fd5e9210d65755014f73220e1f7058eb Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Thu, 12 May 2022 14:01:04 +1000 Subject: [PATCH 04/18] Remove the blocked handles, as the production CDN now serves appropriate CORS headers --- mu-plugins/cdn/cdn-assets.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php index a0bb3461..ac26d163 100644 --- a/mu-plugins/cdn/cdn-assets.php +++ b/mu-plugins/cdn/cdn-assets.php @@ -85,15 +85,6 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { ( defined( 'USE_WPORG_CDN' ) && USE_WPORG_CDN ) ); - // These scripts/styles break if loaded from the CDN without CORS headers. - // See https://make.wordpress.org/systems/2022/02/22/cors-headers-for-s-w-org/ - $blocked_handles = [ - 'wporg-news-style', // Mask images - 'wporg-global-fonts-css', 'jetpack-icons', 'wp-stream-icons', // Fonts - ]; - if ( in_array( $handle, $blocked_handles, true ) ) { - $use_cdn = false; - } $link = 'https://' . ( $use_cdn ? 's.w.org' : $_SERVER['HTTP_HOST'] ) . '/' . $filepath; From 51fd6af359bfc6b0374430275a6d67971049f819 Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Thu, 12 May 2022 04:04:44 +0000 Subject: [PATCH 05/18] Load the CDN plugin. --- mu-plugins/loader.php | 1 + 1 file changed, 1 insertion(+) diff --git a/mu-plugins/loader.php b/mu-plugins/loader.php index 407eeacb..21d8fa3f 100644 --- a/mu-plugins/loader.php +++ b/mu-plugins/loader.php @@ -8,3 +8,4 @@ require_once __DIR__ . '/plugin-tweaks/index.php'; require_once __DIR__ . '/rest-api/index.php'; require_once __DIR__ . '/skip-to/skip-to.php'; +require_once __DIR__ . '/cdn/cdn-assets.php.php'; From 16597346c9862de30c77edd6b0e0511d3ebd33b0 Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Thu, 12 May 2022 04:12:05 +0000 Subject: [PATCH 06/18] Reformat coding style. --- mu-plugins/cdn/cdn-assets.php | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php index ac26d163..aefe0025 100644 --- a/mu-plugins/cdn/cdn-assets.php +++ b/mu-plugins/cdn/cdn-assets.php @@ -51,13 +51,12 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { } // If the link doesn't have a cache-buster, or has extra args, abort. - if ( - empty( $url_args['ver'] ) || - count( $url_args ) > 1 - ) { + if ( empty( $url_args['ver'] ) || count( $url_args ) > 1 ) { return $link; } + $is_production = ( 'production' === wp_get_environment_type() ); + // Set the version to the file modification time, for consistency. $version = false; if ( ! is_timestamp( $url_args['ver'] ) ) { @@ -69,27 +68,21 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { // Chunk the cache buster on a ~2 minute rolling window. // This allows for the production deploy process taking a few minutes, setting different modification times on different servers. - if ( - 'production' === wp_get_environment_type() && - is_timestamp( $version ) - ) { + if ( $is_production && is_timestamp( $version ) ) { $window = 2 * MINUTE_IN_SECONDS; $version = floor( $version / $window ) * $window; } - $use_cdn = ( - // CDN is used in production by default. - 'production' === wp_get_environment_type() || + // CDN is used in production by default. + $use_cdn = $is_production; - // Allow other environments to opt-in via constant. - ( defined( 'USE_WPORG_CDN' ) && USE_WPORG_CDN ) - ); - - - $link = 'https://' . ( $use_cdn ? 's.w.org' : $_SERVER['HTTP_HOST'] ) . '/' . $filepath; + // Allow other environments to opt-in via constant. + if ( defined( 'USE_WPORG_CDN' ) && USE_WPORG_CDN ) { + $use_cdn = true; + } - // Add the version back onto the URL. - $link = add_query_arg( 'ver', $version, $link ); + // Generate the new link. + $link = 'https://' . ( $use_cdn ? 's.w.org' : $_SERVER['HTTP_HOST'] ) . '/' . $filepath . '?ver=' . urlencode( $version ); return $link; } From eb981f359db4575b1d136f09864c6c05d2abab87 Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Thu, 12 May 2022 04:23:25 +0000 Subject: [PATCH 07/18] Change the resource matching to be based on domain, rather than substrings. --- mu-plugins/cdn/cdn-assets.php | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php index aefe0025..feb5c165 100644 --- a/mu-plugins/cdn/cdn-assets.php +++ b/mu-plugins/cdn/cdn-assets.php @@ -21,12 +21,15 @@ * @return string The potentially CDNised URL. */ function with_filemtime_cachebuster( $link, $handle = '' ) { - // Only same-host resources, and WordPress.org domains. - if ( - ! str_starts_with( $link, site_url( '/' ) ) || - ! str_contains( $link, 'wordpress.org' ) || - str_contains( $link, 'profiles.wordpress.org' ) - ) { + $hostname = strtolower( wp_parse_url( $link, PHP_URL_HOST ) ); + + // Only WordPress.org domain files + if ( 'wordpress.org' !== $hostname && ! str_ends_with( $hostname, '.wordpress.org' ) ) { + return $link; + } + + // Profiles is hosted on BuddyPress, which is not available via the CDN. + if ( 'profiles.wordpress.org' === $hostname ) { return $link; } @@ -55,8 +58,6 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { return $link; } - $is_production = ( 'production' === wp_get_environment_type() ); - // Set the version to the file modification time, for consistency. $version = false; if ( ! is_timestamp( $url_args['ver'] ) ) { @@ -66,6 +67,8 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { $version = $url_args['ver']; } + $is_production = ( 'production' === wp_get_environment_type() ); + // Chunk the cache buster on a ~2 minute rolling window. // This allows for the production deploy process taking a few minutes, setting different modification times on different servers. if ( $is_production && is_timestamp( $version ) ) { @@ -81,8 +84,14 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { $use_cdn = true; } + // If we're using the CDN, change the hostname. + if ( $use_cdn ) { + $hostname = 's.w.org'; + } + // Generate the new link. - $link = 'https://' . ( $use_cdn ? 's.w.org' : $_SERVER['HTTP_HOST'] ) . '/' . $filepath . '?ver=' . urlencode( $version ); + $version = urlencode( $version ); + $link = "https://{$hostname}/{$filepath}?ver={$version}"; return $link; } From 43f6929969f6d2fb4f3fa44fe44adaa1cd6e89aa Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Thu, 12 May 2022 04:48:47 +0000 Subject: [PATCH 08/18] Switch to stripping the hostname / sub-site off rather than explicit site_url() which won't work for files in /style/ --- mu-plugins/cdn/cdn-assets.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php index feb5c165..ee07e15f 100644 --- a/mu-plugins/cdn/cdn-assets.php +++ b/mu-plugins/cdn/cdn-assets.php @@ -3,19 +3,18 @@ /** * CDNise script/style assets to s.w.org. - * + * * This only applies to assets which are: - * - Loaded from the same host as this site is served on * - Is a *wordpress.org domain. This ensures that Local environments and other W.org hosted domains are not affected. * - Is NOT profiles.wordpress.org. This site does not use the same docroot as the rest of wordpress.org. * - Only applies to URLs which already include ?ver= cache-busters, and do NOT contain other parameters. - * + * * In CDN'ing, there's a few specific changes made: * - ver= is always changed to the filemtime of the asset (if not already), for consistent and easy cache-busting. * - Caches are chunked into two-minute windows, to avoid slight time differences between servers using different cache keys. * - assets are shared between sites, all use s.w.org/* instead of wordpress.org/wp-includes/* or wordpress.org/plugins/wp-includes/*. * - non-production wp_get_envionment_type() skips CDN'isation. - * + * * @param string $link The non-CDNised URL. * @param string $handle The asset handle, used to skip certain assets. * @return string The potentially CDNised URL. @@ -34,7 +33,10 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { } $url_args = []; - $relative_url = str_replace( site_url( '/' ), '', $link ); + // Trim the scheme & hostname off. + $relative_url = preg_replace( '!^(\w+:)?//[^/]+/!', '', $link ); + // Trim any sub-site path off. + $relative_url = preg_replace( '!^[^/]+/(wp-(?:content|includes|admin)/)!', '$1', $relative_url ); if ( str_contains( $relative_url, '?' ) ) { list( $filepath, $url_part_args ) = explode( '?', $relative_url, 2 ); @@ -100,10 +102,10 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { /** * Determine if a string appears to be a timestamp. - * + * * Due to the use-case here, we're assuming that the timestamp will occur * between Y2.01K and now. - * + * * @param string|int $string The string to check. * @return bool Whether the input appears to be a UTC timestamp. */ @@ -113,4 +115,4 @@ function is_timestamp( $string ) { $string >= 1262304000 /* Y2.01K - 2010-01-01 */ && $string <= time() ); -} +} \ No newline at end of file From a1663b762c69a306b2de7da9f7835dc3595287ee Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Thu, 12 May 2022 05:22:12 +0000 Subject: [PATCH 09/18] Fix typo in loader --- mu-plugins/loader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/loader.php b/mu-plugins/loader.php index 21d8fa3f..c4ff6571 100644 --- a/mu-plugins/loader.php +++ b/mu-plugins/loader.php @@ -8,4 +8,4 @@ require_once __DIR__ . '/plugin-tweaks/index.php'; require_once __DIR__ . '/rest-api/index.php'; require_once __DIR__ . '/skip-to/skip-to.php'; -require_once __DIR__ . '/cdn/cdn-assets.php.php'; +require_once __DIR__ . '/cdn/cdn-assets.php'; From 472e76b41081c2b2901fd154a81f72dede2ef754 Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Mon, 21 Aug 2023 14:41:34 +1000 Subject: [PATCH 10/18] Update cdn-assets.php --- mu-plugins/cdn/cdn-assets.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php index ee07e15f..7331ea2c 100644 --- a/mu-plugins/cdn/cdn-assets.php +++ b/mu-plugins/cdn/cdn-assets.php @@ -27,21 +27,26 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { return $link; } - // Profiles is hosted on BuddyPress, which is not available via the CDN. - if ( 'profiles.wordpress.org' === $hostname ) { + // Several sites are hosted on other Multisites, which are not available via this CDN. + $other_networks = [ + 'profiles.wordpress.org', + 'events.wordpress.org', + ]; + if ( in_array( $hostname, $other_networks, true ) { return $link; } $url_args = []; // Trim the scheme & hostname off. $relative_url = preg_replace( '!^(\w+:)?//[^/]+/!', '', $link ); - // Trim any sub-site path off. + + // Trim any sub-site path off - We only use single-depth on WordPress.org at present. $relative_url = preg_replace( '!^[^/]+/(wp-(?:content|includes|admin)/)!', '$1', $relative_url ); if ( str_contains( $relative_url, '?' ) ) { list( $filepath, $url_part_args ) = explode( '?', $relative_url, 2 ); - parse_str( $url_part_args, $url_args ); + wp_parse_str( $url_part_args, $url_args ); } else { $filepath = $relative_url; // No `$url_args` here. @@ -62,7 +67,7 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { // Set the version to the file modification time, for consistency. $version = false; - if ( ! is_timestamp( $url_args['ver'] ) ) { + if ( ! is_timestamp( $url_args['ver'] ) && file_exists( ABSPATH . $filepath ) ) { $version = filemtime( ABSPATH . $filepath ); } if ( ! $version ) { @@ -115,4 +120,4 @@ function is_timestamp( $string ) { $string >= 1262304000 /* Y2.01K - 2010-01-01 */ && $string <= time() ); -} \ No newline at end of file +} From b0e288b8d5b32c13e8ec3d226d3ca2425a48746a Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Mon, 21 Aug 2023 14:45:37 +1000 Subject: [PATCH 11/18] Remove the time chunking, multiple cached variants are not ideal, but they'll not break anything. --- mu-plugins/cdn/cdn-assets.php | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php index 7331ea2c..f67e536d 100644 --- a/mu-plugins/cdn/cdn-assets.php +++ b/mu-plugins/cdn/cdn-assets.php @@ -74,17 +74,8 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { $version = $url_args['ver']; } - $is_production = ( 'production' === wp_get_environment_type() ); - - // Chunk the cache buster on a ~2 minute rolling window. - // This allows for the production deploy process taking a few minutes, setting different modification times on different servers. - if ( $is_production && is_timestamp( $version ) ) { - $window = 2 * MINUTE_IN_SECONDS; - $version = floor( $version / $window ) * $window; - } - // CDN is used in production by default. - $use_cdn = $is_production; + $use_cdn = ( 'production' === wp_get_environment_type() ); // Allow other environments to opt-in via constant. if ( defined( 'USE_WPORG_CDN' ) && USE_WPORG_CDN ) { From 51562a92a0badc9c20d4333bb7b6a3037603aabb Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Mon, 21 Aug 2023 15:05:23 +1000 Subject: [PATCH 12/18] Merge the mid-deploy cachebuster changes into the CDN plugin This also only modifies recent files, such that older files that have not been modified recently retain their previous caches during deploys. --- mu-plugins/cdn/cdn-assets.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php index f67e536d..907e5065 100644 --- a/mu-plugins/cdn/cdn-assets.php +++ b/mu-plugins/cdn/cdn-assets.php @@ -11,9 +11,11 @@ * * In CDN'ing, there's a few specific changes made: * - ver= is always changed to the filemtime of the asset (if not already), for consistent and easy cache-busting. - * - Caches are chunked into two-minute windows, to avoid slight time differences between servers using different cache keys. * - assets are shared between sites, all use s.w.org/* instead of wordpress.org/wp-includes/* or wordpress.org/plugins/wp-includes/*. * - non-production wp_get_envionment_type() skips CDN'isation. + * - During a deploy, any file that has recently been modified temporarily uses a different cache buster until the deploy is finished. + * This avoids scenario's where a web-node references a newer version of the file, but the subsequent request is served by a node + * which hasn't yet got that new version of the file, which would then otherwise be cached by the CDN with the new version identifier. * * @param string $link The non-CDNised URL. * @param string $handle The asset handle, used to skip certain assets. @@ -74,6 +76,19 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { $version = $url_args['ver']; } + // While a deploy is occuring, use a mid-deploy version for recently modified files. + wp_cache_add_global_groups( 'wporg_deploy' ); + $is_mid_deploy = wp_cache_get( 'is_mid_deploy', 'wporg_deploy', false, $found ); + if ( + $found && + $is_mid_deploy && + is_timestamp( $version ) && + // .. and cache buster version is a recent timestamp, older assets can re-use existing caches + $version > ( time() - HOUR_IN_SECONDS ) + ) { + $version .= '-mid'; + } + // CDN is used in production by default. $use_cdn = ( 'production' === wp_get_environment_type() ); From d8f2df96065715f48e672d9451e5c02fc8e1ed23 Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Mon, 21 Aug 2023 15:16:07 +1000 Subject: [PATCH 13/18] Update comment re: events.w.org --- mu-plugins/cdn/cdn-assets.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/cdn-assets.php index 907e5065..c226cf4b 100644 --- a/mu-plugins/cdn/cdn-assets.php +++ b/mu-plugins/cdn/cdn-assets.php @@ -6,7 +6,7 @@ * * This only applies to assets which are: * - Is a *wordpress.org domain. This ensures that Local environments and other W.org hosted domains are not affected. - * - Is NOT profiles.wordpress.org. This site does not use the same docroot as the rest of wordpress.org. + * - Is NOT profiles.wordpress.org, or events.wordpress.org. These sites are not hoted in the same docroot as the rest of wordpress.org. * - Only applies to URLs which already include ?ver= cache-busters, and do NOT contain other parameters. * * In CDN'ing, there's a few specific changes made: From 5c0fc9394133fa071df952c740f5ed1b46ba26ad Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Tue, 22 Aug 2023 01:54:20 +0000 Subject: [PATCH 14/18] Rename the file to reduce duplication. --- mu-plugins/cdn/{cdn-assets.php => assets.php} | 0 mu-plugins/loader.php | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename mu-plugins/cdn/{cdn-assets.php => assets.php} (100%) diff --git a/mu-plugins/cdn/cdn-assets.php b/mu-plugins/cdn/assets.php similarity index 100% rename from mu-plugins/cdn/cdn-assets.php rename to mu-plugins/cdn/assets.php diff --git a/mu-plugins/loader.php b/mu-plugins/loader.php index a017bb4d..18cc147d 100644 --- a/mu-plugins/loader.php +++ b/mu-plugins/loader.php @@ -45,4 +45,4 @@ require_once __DIR__ . '/db-user-sessions/index.php'; require_once __DIR__ . '/encryption/index.php'; require_once __DIR__ . '/admin/index.php'; -require_once __DIR__ . '/cdn/cdn-assets.php'; +require_once __DIR__ . '/cdn/assets.php'; From d47d78125f7a7d4be44dfb3a264fe409f15cf5b4 Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Tue, 22 Aug 2023 01:55:15 +0000 Subject: [PATCH 15/18] Switch to using a file hash for the buster, to avoid multi-server filemtime differences. Cache the file hashes using APCu. Move the mid-deploy cache buster into a separate function. Apply to URLs generated by `plugins_url()`. --- mu-plugins/cdn/assets.php | 115 ++++++++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 28 deletions(-) diff --git a/mu-plugins/cdn/assets.php b/mu-plugins/cdn/assets.php index c226cf4b..da00a455 100644 --- a/mu-plugins/cdn/assets.php +++ b/mu-plugins/cdn/assets.php @@ -10,18 +10,17 @@ * - Only applies to URLs which already include ?ver= cache-busters, and do NOT contain other parameters. * * In CDN'ing, there's a few specific changes made: - * - ver= is always changed to the filemtime of the asset (if not already), for consistent and easy cache-busting. + * - ver= is always changed to a hash of the asset contents, for consistent and easy cache-busting. * - assets are shared between sites, all use s.w.org/* instead of wordpress.org/wp-includes/* or wordpress.org/plugins/wp-includes/*. - * - non-production wp_get_envionment_type() skips CDN'isation. + * - non-production wp_get_envionment_type() skips CDN'isation by default, but can be overridden with a constant. * - During a deploy, any file that has recently been modified temporarily uses a different cache buster until the deploy is finished. * This avoids scenario's where a web-node references a newer version of the file, but the subsequent request is served by a node * which hasn't yet got that new version of the file, which would then otherwise be cached by the CDN with the new version identifier. * * @param string $link The non-CDNised URL. - * @param string $handle The asset handle, used to skip certain assets. * @return string The potentially CDNised URL. */ -function with_filemtime_cachebuster( $link, $handle = '' ) { +function with_filemtime_cachebuster( $link ) { $hostname = strtolower( wp_parse_url( $link, PHP_URL_HOST ) ); // Only WordPress.org domain files @@ -34,7 +33,7 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { 'profiles.wordpress.org', 'events.wordpress.org', ]; - if ( in_array( $hostname, $other_networks, true ) { + if ( in_array( $hostname, $other_networks, true ) ) { return $link; } @@ -67,39 +66,45 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { return $link; } - // Set the version to the file modification time, for consistency. - $version = false; - if ( ! is_timestamp( $url_args['ver'] ) && file_exists( ABSPATH . $filepath ) ) { - $version = filemtime( ABSPATH . $filepath ); - } - if ( ! $version ) { - $version = $url_args['ver']; + // Find the modified time for the file, which may already be the version. + $timestamp = $url_args['ver']; + if ( ! is_timestamp( $timestamp ) ) { + if ( file_exists( ABSPATH . $filepath ) ) { + $timestamp = filemtime( ABSPATH . $filepath ); + } else { + $timestamp = null; + } } - // While a deploy is occuring, use a mid-deploy version for recently modified files. - wp_cache_add_global_groups( 'wporg_deploy' ); - $is_mid_deploy = wp_cache_get( 'is_mid_deploy', 'wporg_deploy', false, $found ); - if ( - $found && - $is_mid_deploy && - is_timestamp( $version ) && - // .. and cache buster version is a recent timestamp, older assets can re-use existing caches - $version > ( time() - HOUR_IN_SECONDS ) - ) { - $version .= '-mid'; - } + /* + * The version is set to the timestamp by default. + * CDN will override this with a content hash. + */ + $version = $timestamp ?: $url_args['ver']; // CDN is used in production by default. $use_cdn = ( 'production' === wp_get_environment_type() ); - // Allow other environments to opt-in via constant. + /* + * Allow other environments to opt-in via constant. + * Note: This is not recommended, except for testing. + */ if ( defined( 'USE_WPORG_CDN' ) && USE_WPORG_CDN ) { $use_cdn = true; } - // If we're using the CDN, change the hostname. + // If we're using the CDN, make the needed changes. if ( $use_cdn ) { $hostname = 's.w.org'; + + /* + * Use a cache-buster that's unique to this file contents. + * This allows a cache to be consistent between servers with different modification times. + */ + $version = get_file_hash( $filepath, $timestamp ) ?: $timestamp; + + // While a deploy is occuring, use a mid-deploy version recently modified files. + $version .= mid_deploy_cachebuster( $filepath, $timestamp ); } // Generate the new link. @@ -108,8 +113,9 @@ function with_filemtime_cachebuster( $link, $handle = '' ) { return $link; } -add_filter( 'style_loader_src', __NAMESPACE__ . '\with_filemtime_cachebuster', 5, 2 ); -add_filter( 'script_loader_src', __NAMESPACE__ . '\with_filemtime_cachebuster', 5, 2 ); +add_filter( 'style_loader_src', __NAMESPACE__ . '\with_filemtime_cachebuster', 5 ); +add_filter( 'script_loader_src', __NAMESPACE__ . '\with_filemtime_cachebuster', 5 ); +add_filter( 'plugins_url', __NAMESPACE__ . '\with_filemtime_cachebuster', 5 ); /** * Determine if a string appears to be a timestamp. @@ -127,3 +133,56 @@ function is_timestamp( $string ) { $string <= time() ); } + +/** + * Fetch the file content cache-buster for a given file. + * + * @param string $file The file to fetch the cache-buster for. + * @param int $time Optional. The file modification time, if already known. + * @return string The cache-buster. First 12 characters of the sha1. + */ +function get_file_hash( $file, $time = null ) { + static $cached = []; + + $file = trailingslashit( ABSPATH ) . $file; + $time ??= filemtime( $file ); + $key = $file . ':' . $time . ':hash'; + + if ( ! isset( $cached[ $key ] ) ) { + $cached[ $key ] = apcu_fetch( $key, $found ); + + if ( ! $found ) { + $cached[ $key ] = substr( sha1_file( $file ), 0, 12 ); + apcu_store( $key, $cached[ $key ], DAY_IN_SECONDS ); + } + } + + return $cached[ $key ]; +} + +/** + * Return a mid-deploy cache buster, during deploys. + * + * @param string $file The file to fetch the cache-buster for. + * @param int $modified_time Optional. The file modification time, if already known. + * @return string A cache buster, if required, an empty string otherwise. + */ +function mid_deploy_cachebuster( $file, $modified_time = false ) { + wp_cache_add_global_groups( 'wporg_deploy' ); + + $is_mid_deploy = wp_cache_get( 'is_mid_deploy', 'wporg_deploy', false, $found ); + + if ( + $found && + $is_mid_deploy && + ( + ! $modified_time || + // .. and cache buster version is a recent timestamp, older assets can re-use existing caches + $modified_time > ( time() - HOUR_IN_SECONDS ) + ) + ) { + return '-mid-deploy'; + } + + return ''; +} \ No newline at end of file From bd97acc60194725e452638f7d2d4ab28cec3321f Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Tue, 22 Aug 2023 12:14:56 +1000 Subject: [PATCH 16/18] Add a new line to end of file. --- mu-plugins/cdn/assets.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/cdn/assets.php b/mu-plugins/cdn/assets.php index da00a455..d4c7e1bd 100644 --- a/mu-plugins/cdn/assets.php +++ b/mu-plugins/cdn/assets.php @@ -185,4 +185,4 @@ function mid_deploy_cachebuster( $file, $modified_time = false ) { } return ''; -} \ No newline at end of file +} From 8ab4044203493541f4befd3ae05b8ebe27e5eedb Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Tue, 22 Aug 2023 16:09:00 +1000 Subject: [PATCH 17/18] Add CDN versioning for fonts (#424) * Pass the font file to plugins_url(). * Add font hashes. * Remove EB Garamond 'arrows' subset, it doesn't exist. * Update font subset script to generate the CDN hashes. --- bin/font-subset.js | 32 ++++-- mu-plugins/global-fonts/index.php | 20 +++- mu-plugins/global-fonts/style.css | 160 ++++++++++++++---------------- 3 files changed, 116 insertions(+), 96 deletions(-) diff --git a/bin/font-subset.js b/bin/font-subset.js index e6d69862..778b3bf7 100755 --- a/bin/font-subset.js +++ b/bin/font-subset.js @@ -15,7 +15,17 @@ */ import { spawn } from 'child_process'; import path from 'path'; -import { renameSync, writeFile } from 'fs'; +import { existsSync, renameSync, readFileSync, writeFile } from 'fs'; +import { createHash } from 'crypto'; + +function generateHash( filename ) { + filename = path.join( __dirname, `output/${ filename }` ) + /* + * Magic Number 12, See get_file_hash() + * https://github.com/WordPress/wporg-mu-plugins/blob/trunk/mu-plugins/cdn/assets.php + */ + return createHash('sha1').update( readFileSync( filename ), 'binary').digest('hex').substring( 0, 12 ); +} const alphabets = [ { @@ -89,17 +99,25 @@ let cssCode = ''; // Create our font face rules // This would need to be modified for other weights and styles alphabets.forEach( ( alphabet ) => { + let filename = `${ fontFileName }-${ alphabet.name }.woff2`; + + if ( ! existsSync( filename ) ) { + return; + } + + let hash = generateHash( filename ); + cssCode += ` /* ${ alphabet.name } */ - @font-face { + @font-face { font-family: ${ fontFamily }; font-weight: ${ fontWeight }; font-style: ${ fontStyle }; - font-display: swap; - src: url(./${ fontFinalDir }/${ fontFileName }-${ alphabet.name }.woff2) format("woff2"); - unicode-range: ${ alphabet.unicodeRange }; - } - `; + font-display: swap; + src: url(./${ fontFinalDir }/${ filename }?ver=${ hash }) format("woff2"); + unicode-range: ${ alphabet.unicodeRange }; + } + `; } ); // Determine where to save our file diff --git a/mu-plugins/global-fonts/index.php b/mu-plugins/global-fonts/index.php index bb934ccf..da639bba 100644 --- a/mu-plugins/global-fonts/index.php +++ b/mu-plugins/global-fonts/index.php @@ -41,9 +41,19 @@ function relative_to_absolute_urls( $editor_settings ) { } foreach ( $editor_settings['styles'] as $i => $style ) { - if ( str_contains( $style['css'], './Inter' ) || str_contains( $style['css'], './EB-Garamond' ) ) { - $url = plugins_url( '', __FILE__ ); - $style['css'] = str_replace( 'url(./', "url($url/", $style['css'] ); + if ( + str_contains( $style['css'], './Inter' ) || + str_contains( $style['css'], './EB-Garamond' ) || + str_contains( $style['css'], './CourierPrime' ) || + str_contains( $style['css'], './IBMPlexMono' ) + ) { + $style['css'] = preg_replace_callback( + '!url\(./(?P[^)]+)\)!i', + function( $m ) { + return "url(" . plugins_url( $m['path'], __FILE__ ) . ")"; + } + ); + $editor_settings['styles'][ $i ] = $style; } } @@ -199,5 +209,7 @@ function get_font_url( $font, $subset ) { return false; } - return plugins_url( $filepath, __FILE__ ); + $font_version = filemtime( __DIR__ . '/' . $filepath ); + + return plugins_url( "{$filepath}?ver={$font_version}", __FILE__ ); } diff --git a/mu-plugins/global-fonts/style.css b/mu-plugins/global-fonts/style.css index a78b16eb..bdbcd501 100644 --- a/mu-plugins/global-fonts/style.css +++ b/mu-plugins/global-fonts/style.css @@ -8,7 +8,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Regular-cyrillic-ext.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Regular-cyrillic-ext.woff2?ver=4ecb2879668a) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -18,7 +18,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Regular-cyrillic.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Regular-cyrillic.woff2?ver=4ecb2879668a) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -28,7 +28,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Regular-greek-ext.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Regular-greek-ext.woff2?ver=4ecb2879668a) format("woff2"); unicode-range: U+1F00-1FFF; } @@ -38,7 +38,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Regular-greek.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Regular-greek.woff2?ver=eba1f8ff4da0) format("woff2"); unicode-range: U+0370-03FF; } @@ -48,7 +48,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Regular-vietnamese.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Regular-vietnamese.woff2?ver=da75b869896c) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -58,7 +58,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Regular-latin-ext.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Regular-latin-ext.woff2?ver=2aad680866fd) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -68,7 +68,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Regular-latin.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Regular-latin.woff2?ver=7b9aa715ce49) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -82,7 +82,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Bold-cyrillic-ext.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Bold-cyrillic-ext.woff2?ver=c11c7999d78e) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -92,7 +92,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Bold-cyrillic.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Bold-cyrillic.woff2?ver=c11c7999d78e) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -102,7 +102,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Bold-greek-ext.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Bold-greek-ext.woff2?ver=c11c7999d78e) format("woff2"); unicode-range: U+1F00-1FFF; } @@ -112,7 +112,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Bold-greek.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Bold-greek.woff2?ver=ba79634e2cd8) format("woff2"); unicode-range: U+0370-03FF; } @@ -122,7 +122,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Bold-vietnamese.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Bold-vietnamese.woff2?ver=180aa42496b5) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -132,7 +132,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Bold-latin-ext.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Bold-latin-ext.woff2?ver=94527d576afd) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -142,7 +142,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./CourierPrime/CourierPrime-Bold-latin.woff2) format("woff2"); + src: url(./CourierPrime/CourierPrime-Bold-latin.woff2?ver=01c037d9e0a1) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -156,7 +156,7 @@ font-weight: 100 900; font-style: normal; font-display: swap; - src: url(./Inter/Inter-cyrillic-ext.woff2) format("woff2"); + src: url(./Inter/Inter-cyrillic-ext.woff2?ver=870d267d091f) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -166,7 +166,7 @@ font-weight: 100 900; font-style: normal; font-display: swap; - src: url(./Inter/Inter-cyrillic.woff2) format("woff2"); + src: url(./Inter/Inter-cyrillic.woff2?ver=2e1f0e6a6eda) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -176,7 +176,7 @@ font-weight: 100 900; font-style: normal; font-display: swap; - src: url(./Inter/Inter-greek-ext.woff2) format("woff2"); + src: url(./Inter/Inter-greek-ext.woff2?ver=f1fb719a6429) format("woff2"); unicode-range: U+1F00-1FFF; } @@ -186,7 +186,7 @@ font-weight: 100 900; font-style: normal; font-display: swap; - src: url(./Inter/Inter-greek.woff2) format("woff2"); + src: url(./Inter/Inter-greek.woff2?ver=8fb4801a481e) format("woff2"); unicode-range: U+0370-03FF; } @@ -196,7 +196,7 @@ font-weight: 100 900; font-style: normal; font-display: swap; - src: url(./Inter/Inter-vietnamese.woff2) format("woff2"); + src: url(./Inter/Inter-vietnamese.woff2?ver=ec198636627a) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -206,7 +206,7 @@ font-weight: 100 900; font-style: normal; font-display: swap; - src: url(./Inter/Inter-latin-ext.woff2) format("woff2"); + src: url(./Inter/Inter-latin-ext.woff2?ver=802f9ad48332) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -216,7 +216,7 @@ font-weight: 100 900; font-style: normal; font-display: swap; - src: url(./Inter/Inter-latin.woff2) format("woff2"); + src: url(./Inter/Inter-latin.woff2?ver=b07a289bdf69) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -226,7 +226,7 @@ font-weight: 100 900; font-style: normal; font-display: swap; - src: url(./Inter/Inter-arrows.woff2) format("woff2"); + src: url(./Inter/Inter-arrows.woff2?ver=63555c379a62) format("woff2"); unicode-range: U+2190-2199; } @@ -241,7 +241,7 @@ font-weight: 400 700; font-style: normal; font-display: swap; - src: url(./EB-Garamond/EBGaramond-cyrillic-ext.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-cyrillic-ext.woff2?ver=8176ef6e06a1) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -251,7 +251,7 @@ font-weight: 400 700; font-style: normal; font-display: swap; - src: url(./EB-Garamond/EBGaramond-cyrillic.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-cyrillic.woff2?ver=1af56bf0af64) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -261,7 +261,7 @@ font-weight: 400 700; font-style: normal; font-display: swap; - src: url(./EB-Garamond/EBGaramond-greek-ext.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-greek-ext.woff2?ver=d3bd499d027a) format("woff2"); unicode-range: U+1F00-1FFF; } @@ -271,7 +271,7 @@ font-weight: 400 700; font-style: normal; font-display: swap; - src: url(./EB-Garamond/EBGaramond-greek.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-greek.woff2?ver=ec834832b30b) format("woff2"); unicode-range: U+0370-03FF; } @@ -281,7 +281,7 @@ font-weight: 400 700; font-style: normal; font-display: swap; - src: url(./EB-Garamond/EBGaramond-vietnamese.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-vietnamese.woff2?ver=30eaef521e8a) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -291,7 +291,7 @@ font-weight: 400 700; font-style: normal; font-display: swap; - src: url(./EB-Garamond/EBGaramond-latin-ext.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-latin-ext.woff2?ver=a08861311328) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -301,7 +301,7 @@ font-weight: 400 700; font-style: normal; font-display: swap; - src: url(./EB-Garamond/EBGaramond-latin.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-latin.woff2?ver=2c7bc866cb03) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -311,7 +311,7 @@ font-weight: 400 700; font-style: normal; font-display: swap; - src: url(./EB-Garamond/EBGaramond-arrows.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-arrows.woff2?ver=943d7defaf99) format("woff2"); unicode-range: U+2190-2199; } @@ -326,7 +326,7 @@ font-weight: 400 700; font-style: italic; font-display: swap; - src: url(./EB-Garamond/EBGaramond-Italic-cyrillic-ext.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-Italic-cyrillic-ext.woff2?ver=7808b24a969c) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -336,7 +336,7 @@ font-weight: 400 700; font-style: italic; font-display: swap; - src: url(./EB-Garamond/EBGaramond-Italic-cyrillic.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-Italic-cyrillic.woff2?ver=766320cf480d) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -346,7 +346,7 @@ font-weight: 400 700; font-style: italic; font-display: swap; - src: url(./EB-Garamond/EBGaramond-Italic-greek-ext.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-Italic-greek-ext.woff2?ver=5c9c07959839) format("woff2"); unicode-range: U+1F00-1FFF; } @@ -356,7 +356,7 @@ font-weight: 400 700; font-style: italic; font-display: swap; - src: url(./EB-Garamond/EBGaramond-Italic-greek.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-Italic-greek.woff2?ver=9cdc7745aab9) format("woff2"); unicode-range: U+0370-03FF; } @@ -366,7 +366,7 @@ font-weight: 400 700; font-style: italic; font-display: swap; - src: url(./EB-Garamond/EBGaramond-Italic-vietnamese.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-Italic-vietnamese.woff2?ver=47ae16ca8ebd) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -376,7 +376,7 @@ font-weight: 400 700; font-style: italic; font-display: swap; - src: url(./EB-Garamond/EBGaramond-Italic-latin-ext.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-Italic-latin-ext.woff2?ver=cdaf0905fb1c) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -386,20 +386,10 @@ font-weight: 400 700; font-style: italic; font-display: swap; - src: url(./EB-Garamond/EBGaramond-Italic-latin.woff2) format("woff2"); + src: url(./EB-Garamond/EBGaramond-Italic-latin.woff2?ver=b6b388074e82) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } -/* arrows */ -@font-face { - font-family: "EB Garamond"; - font-weight: 400 700; - font-style: italic; - font-display: swap; - src: url(./EB-Garamond/EBGaramond-Italic-arrows.woff2) format("woff2"); - unicode-range: U+2190-2199; -} - /*----------------------------* * IBM Plex Mono ExtraLight * @@ -411,7 +401,7 @@ font-weight: 200; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-ExtraLight-cyrillic-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-ExtraLight-cyrillic-ext.woff2?ver=99488ab1f1b4) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -421,7 +411,7 @@ font-weight: 200; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-ExtraLight-cyrillic.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-ExtraLight-cyrillic.woff2?ver=370513b21aa8) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -431,7 +421,7 @@ font-weight: 200; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-ExtraLight-vietnamese.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-ExtraLight-vietnamese.woff2?ver=04a172643c2d) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -441,7 +431,7 @@ font-weight: 200; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-ExtraLight-latin-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-ExtraLight-latin-ext.woff2?ver=1214d6939808) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -451,7 +441,7 @@ font-weight: 200; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-ExtraLight-latin.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-ExtraLight-latin.woff2?ver=075de20a9833) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -466,7 +456,7 @@ font-weight: 200; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-ExtraLightItalic-cyrillic-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-ExtraLightItalic-cyrillic-ext.woff2?ver=f67b80c3648c) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -476,7 +466,7 @@ font-weight: 200; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-ExtraLightItalic-cyrillic.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-ExtraLightItalic-cyrillic.woff2?ver=51c4ca00cdb0) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -486,7 +476,7 @@ font-weight: 200; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-ExtraLightItalic-vietnamese.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-ExtraLightItalic-vietnamese.woff2?ver=632a48e3ba8e) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -496,7 +486,7 @@ font-weight: 200; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-ExtraLightItalic-latin-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-ExtraLightItalic-latin-ext.woff2?ver=454bc3623abc) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -506,7 +496,7 @@ font-weight: 200; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-ExtraLightItalic-latin.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-ExtraLightItalic-latin.woff2?ver=38cfc7b0cee7) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -521,7 +511,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Regular-cyrillic-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Regular-cyrillic-ext.woff2?ver=d5b4785e465e) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -531,7 +521,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Regular-cyrillic.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Regular-cyrillic.woff2?ver=dbae9f565349) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -541,7 +531,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Regular-vietnamese.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Regular-vietnamese.woff2?ver=0aa3dc1ec47b) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -551,7 +541,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Regular-latin-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Regular-latin-ext.woff2?ver=139e6cd03358) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -561,7 +551,7 @@ font-weight: 400; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Regular-latin.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Regular-latin.woff2?ver=8ddc86b0ebf4) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -576,7 +566,7 @@ font-weight: 400; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Italic-cyrillic-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Italic-cyrillic-ext.woff2?ver=c415eab9d09e) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -586,7 +576,7 @@ font-weight: 400; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Italic-cyrillic.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Italic-cyrillic.woff2?ver=c586ce96eb42) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -596,7 +586,7 @@ font-weight: 400; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Italic-vietnamese.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Italic-vietnamese.woff2?ver=0b8d65223f8f) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -606,7 +596,7 @@ font-weight: 400; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Italic-latin-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Italic-latin-ext.woff2?ver=bb87d332affb) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -616,7 +606,7 @@ font-weight: 400; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Italic-latin.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Italic-latin.woff2?ver=b8d4f3563cf8) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -630,7 +620,7 @@ font-weight: 500; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Medium-cyrillic-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Medium-cyrillic-ext.woff2?ver=431d255a3afa) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -640,7 +630,7 @@ font-weight: 500; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Medium-cyrillic.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Medium-cyrillic.woff2?ver=beb561f0d2e7) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -650,7 +640,7 @@ font-weight: 500; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Medium-greek-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Medium-greek-ext.woff2?ver=49bf3255c571) format("woff2"); unicode-range: U+1F00-1FFF; } @@ -660,7 +650,7 @@ font-weight: 500; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Medium-greek.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Medium-greek.woff2?ver=6152b28764d6) format("woff2"); unicode-range: U+0370-03FF; } @@ -670,7 +660,7 @@ font-weight: 500; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Medium-vietnamese.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Medium-vietnamese.woff2?ver=c58ce4527d80) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -680,7 +670,7 @@ font-weight: 500; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Medium-latin-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Medium-latin-ext.woff2?ver=4ace19a3c116) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -690,7 +680,7 @@ font-weight: 500; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Medium-latin.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Medium-latin.woff2?ver=44150b50e9d4) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -700,7 +690,7 @@ font-weight: 500; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Medium-arrows.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Medium-arrows.woff2?ver=e9f571cc6a63) format("woff2"); unicode-range: U+2190-2199; } @@ -714,7 +704,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Bold-cyrillic-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Bold-cyrillic-ext.woff2?ver=d20781be5b07) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -724,7 +714,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Bold-cyrillic.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Bold-cyrillic.woff2?ver=c6178ab7258f) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -734,7 +724,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Bold-vietnamese.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Bold-vietnamese.woff2?ver=5e8388bb91ff) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -744,7 +734,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Bold-latin-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Bold-latin-ext.woff2?ver=ac5ae799cb8f) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -754,7 +744,7 @@ font-weight: 700; font-style: normal; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-Bold-latin.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-Bold-latin.woff2?ver=59cad49c271e) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -769,7 +759,7 @@ font-weight: 700; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-cyrillic-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-cyrillic-ext.woff2?ver=acd7ea8d0d94) format("woff2"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -779,7 +769,7 @@ font-weight: 700; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-cyrillic.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-cyrillic.woff2?ver=20d5b885400b) format("woff2"); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -789,7 +779,7 @@ font-weight: 700; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-vietnamese.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-vietnamese.woff2?ver=a005afe26029) format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -799,7 +789,7 @@ font-weight: 700; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-latin-ext.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-latin-ext.woff2?ver=580700b45e3a) format("woff2"); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -809,6 +799,6 @@ font-weight: 700; font-style: italic; font-display: swap; - src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-latin.woff2) format("woff2"); + src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-latin.woff2?ver=a96c20e7edc2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } From 1c7d2aa591974d10b9cfe0e53c300c597f75a09f Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Wed, 23 Aug 2023 04:53:20 +0000 Subject: [PATCH 18/18] Global Fonts: Fix the inline URLs after #424. --- mu-plugins/global-fonts/index.php | 3 ++- mu-plugins/global-fonts/style.css | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mu-plugins/global-fonts/index.php b/mu-plugins/global-fonts/index.php index da639bba..9789baaf 100644 --- a/mu-plugins/global-fonts/index.php +++ b/mu-plugins/global-fonts/index.php @@ -51,7 +51,8 @@ function relative_to_absolute_urls( $editor_settings ) { '!url\(./(?P[^)]+)\)!i', function( $m ) { return "url(" . plugins_url( $m['path'], __FILE__ ) . ")"; - } + }, + $style['css'] ); $editor_settings['styles'][ $i ] = $style; diff --git a/mu-plugins/global-fonts/style.css b/mu-plugins/global-fonts/style.css index bdbcd501..92216ab7 100644 --- a/mu-plugins/global-fonts/style.css +++ b/mu-plugins/global-fonts/style.css @@ -802,3 +802,4 @@ src: url(./IBMPlexMono/IBMPlexMono-BoldItalic-latin.woff2?ver=a96c20e7edc2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD; } +