Fix relative URLs in inlined block styles that involve external assets

When styles got inlined, relative URLs break. The problem was that URLs inside CSS files are relative to the stylesheet's path, and when styles get inlined that relation is lost. This patch fixes the issue by finding relative URLs which then get modified to be relative to the site's root.

Fixes #54243.
Props aristath, cdyerkes, hellofromtonya.


Built from https://develop.svn.wordpress.org/trunk@52036


git-svn-id: http://core.svn.wordpress.org/trunk@51628 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
gziolo 2021-11-08 13:24:58 +00:00
parent 2a3ad7c430
commit b519028ab2
2 changed files with 45 additions and 1 deletions

View File

@ -2701,6 +2701,7 @@ function wp_maybe_inline_styles() {
if ( wp_styles()->get_data( $handle, 'path' ) && file_exists( $wp_styles->registered[ $handle ]->extra['path'] ) ) {
$styles[] = array(
'handle' => $handle,
'src' => $wp_styles->registered[ $handle ]->src,
'path' => $wp_styles->registered[ $handle ]->extra['path'],
'size' => filesize( $wp_styles->registered[ $handle ]->extra['path'] ),
);
@ -2735,6 +2736,10 @@ function wp_maybe_inline_styles() {
// Get the styles if we don't already have them.
$style['css'] = file_get_contents( $style['path'] );
// Check if the style contains relative URLs that need to be modified.
// URLs relative to the stylesheet's path should be converted to relative to the site's root.
$style['css'] = _wp_normalize_relative_css_links( $style['css'], $style['src'] );
// Set `src` to `false` and add styles inline.
$wp_styles->registered[ $style['handle'] ]->src = false;
if ( empty( $wp_styles->registered[ $style['handle'] ]->extra['after'] ) ) {
@ -2748,6 +2753,45 @@ function wp_maybe_inline_styles() {
}
}
/**
* Make URLs relative to the WordPress installation.
*
* @since 5.9.0
* @access private
*
* @param string $css The CSS to make URLs relative to the WordPress installation.
* @param string $stylesheet_url The URL to the stylesheet.
*
* @return string The CSS with URLs made relative to the WordPress installation.
*/
function _wp_normalize_relative_css_links( $css, $stylesheet_url ) {
$has_src_results = preg_match_all( '#url\s*\(\s*[\'"]?\s*([^\'"\)]+)#', $css, $src_results );
if ( $has_src_results ) {
// Loop through the URLs to find relative ones.
foreach ( $src_results[1] as $src_index => $src_result ) {
// Skip if this is an absolute URL.
if ( 0 === strpos( $src_result, 'http' ) || 0 === strpos( $src_result, '//' ) ) {
continue;
}
// Build the absolute URL.
$absolute_url = dirname( $stylesheet_url ) . '/' . $src_result;
$absolute_url = str_replace( '/./', '/', $absolute_url );
// Convert to URL related to the site root.
$relative_url = wp_make_link_relative( $absolute_url );
// Replace the URL in the CSS.
$css = str_replace(
$src_results[0][ $src_index ],
str_replace( $src_result, $relative_url, $src_results[0][ $src_index ] ),
$css
);
}
}
return $css;
}
/**
* Inject the block editor assets that need to be loaded into the editor's iframe as an inline script.
*

View File

@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
$wp_version = '5.9-alpha-52035';
$wp_version = '5.9-alpha-52036';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.