content ); if ( $noptimize_css ) { return false; } $allowlist_css = apply_filters( 'autoptimize_filter_css_allowlist', '', $this->content ); $allowlist_css = apply_filters( 'autoptimize_filter_css_whitelist', $allowlist_css, $this->content ); // fixme: to be removed in next version. if ( ! empty( $allowlist_css ) ) { $this->allowlist = array_filter( array_map( 'trim', explode( ',', $allowlist_css ) ) ); } $removable_css = apply_filters( 'autoptimize_filter_css_removables', '' ); if ( ! empty( $removable_css ) ) { $this->cssremovables = array_filter( array_map( 'trim', explode( ',', $removable_css ) ) ); } $this->cssinlinesize = apply_filters( 'autoptimize_filter_css_inlinesize', 256 ); // filter to "late inject minified CSS", default to true for now (it is faster). $this->inject_min_late = apply_filters( 'autoptimize_filter_css_inject_min_late', true ); // Remove everything that's not the header. if ( apply_filters( 'autoptimize_filter_css_justhead', $options['justhead'] ) ) { $content = explode( '', $this->content, 2 ); $this->content = $content[0] . ''; $this->restofcontent = $content[1]; } // Determine whether we're doing CSS-files aggregation or not. if ( isset( $options['aggregate'] ) && ! $options['aggregate'] ) { $this->aggregate = false; } // Returning true for "dontaggregate" turns off aggregation. if ( $this->aggregate && apply_filters( 'autoptimize_filter_css_dontaggregate', false ) ) { $this->aggregate = false; } // include inline? if ( apply_filters( 'autoptimize_css_include_inline', $options['include_inline'] ) ) { $this->include_inline = true; } // List of CSS strings which are excluded from autoptimization. $exclude_css = apply_filters( 'autoptimize_filter_css_exclude', $options['css_exclude'], $this->content ); if ( '' !== $exclude_css ) { $this->dontmove = array_filter( array_map( 'trim', explode( ',', $exclude_css ) ) ); } else { $this->dontmove = array(); } // forcefully exclude CSS with data-noptimize attrib. $this->dontmove[] = 'data-noptimize'; // Should we defer css? // value: true / false. $this->defer = $options['defer']; $this->defer = apply_filters( 'autoptimize_filter_css_defer', $this->defer, $this->content ); // Should we inline while deferring? // value: inlined CSS. $this->defer_inline = apply_filters( 'autoptimize_filter_css_defer_inline', $options['defer_inline'], $this->content ); // Should we inline? // value: true / false. $this->inline = $options['inline']; $this->inline = apply_filters( 'autoptimize_filter_css_inline', $this->inline, $this->content ); // Store cdn url. $this->cdn_url = $options['cdn_url']; // Store data: URIs setting for later use. $this->datauris = $options['datauris']; // Determine whether excluded files should be minified if not yet so. if ( ! $options['minify_excluded'] && $options['aggregate'] ) { $this->minify_excluded = false; } $this->minify_excluded = apply_filters( 'autoptimize_filter_css_minify_excluded', $this->minify_excluded, '' ); // should we force all media-attributes to all? $this->media_force_all = apply_filters( 'autoptimize_filter_css_tagmedia_forceall', false ); // noptimize me. $this->content = $this->hide_noptimize( $this->content ); // Exclude (no)script, as those may contain CSS which should be left as is. $this->content = $this->replace_contents_with_marker_if_exists( 'SCRIPT', '#is', $this->content ); // Save IE hacks. $this->content = $this->hide_iehacks( $this->content ); // Hide HTML comments. $this->content = $this->hide_comments( $this->content ); // Get )|(]*stylesheet[^>]*>)#Usmi', $this->content, $matches ) ) { foreach ( $matches[0] as $tag ) { if ( $this->isremovable( $tag, $this->cssremovables ) ) { $this->content = str_replace( $tag, '', $this->content ); } elseif ( $this->ismovable( $tag ) ) { // Get the media. if ( false !== strpos( $tag, 'media=' ) ) { preg_match( '#media=(?:"|\')([^>]*)(?:"|\')#Ui', $tag, $medias ); $medias = explode( ',', $medias[1] ); $media = array(); foreach ( $medias as $elem ) { if ( empty( $elem ) ) { $elem = 'all'; } $media[] = $elem; } } else { // No media specified - applies to all. $media = array( 'all' ); } // forcing media attribute to all to merge all in one file. if ( $this->media_force_all ) { $media = array( 'all' ); } $media = apply_filters( 'autoptimize_filter_css_tagmedia', $media, $tag ); if ( preg_match( '#. $url = current( explode( '?', $source[2], 2 ) ); $path = $this->getpath( $url ); if ( false !== $path && preg_match( '#\.css$#', $path ) ) { // Good link. $this->css[] = array( $media, $path ); } else { // Link is dynamic (.php etc). $new_tag = $this->optionally_defer_excluded( $tag, 'none' ); if ( '' !== $new_tag && $new_tag !== $tag ) { $this->content = str_replace( $tag, $new_tag, $this->content ); } $tag = ''; } } else { // Inline css in style tags can be wrapped in comment tags, so restore comments. $tag = $this->restore_comments( $tag ); preg_match( '#(.*)#Usmi', $tag, $code ); // And re-hide them to be able to to the removal based on tag. $tag = $this->hide_comments( $tag ); if ( $this->include_inline ) { $code = preg_replace( '#^.*.*$#sm', '$1', $code[1] ); $this->css[] = array( $media, 'INLINE;' . $code ); } else { $tag = ''; } } // Remove the original style tag. $this->content = str_replace( $tag, '', $this->content ); } else { if ( preg_match( '#getpath( $url ); $new_tag = $tag; // Excluded CSS, minify that file: // -> if aggregate is on and exclude minify is on // -> if aggregate is off and the file is not in dontmove. if ( $path && $this->minify_excluded ) { $consider_minified_array = apply_filters( 'autoptimize_filter_css_consider_minified', false ); if ( ( false === $this->aggregate && str_replace( $this->dontmove, '', $path ) === $path ) || ( true === $this->aggregate && ( false === $consider_minified_array || str_replace( $consider_minified_array, '', $path ) === $path ) ) ) { $minified_url = $this->minify_single( $path ); if ( ! empty( $minified_url ) ) { // Replace orig URL with cached minified URL. $new_tag = str_replace( $url, $minified_url, $tag ); } elseif ( apply_filters( 'autoptimize_filter_ccsjs_remove_empty_minified_url', false ) ) { // Remove the original style tag, because cache content is empty but only if // filter is true-ed because $minified_url is also false if file is minified already. $new_tag = ''; } } } if ( '' !== $new_tag ) { // Optionally defer (preload) non-aggregated CSS. $new_tag = $this->optionally_defer_excluded( $new_tag, $url ); } // And replace! if ( ( '' !== $new_tag && $new_tag !== $tag ) || ( '' === $new_tag && apply_filters( 'autoptimize_filter_css_remove_empty_files', false ) ) ) { $this->content = str_replace( $tag, $new_tag, $this->content ); } } } } return true; } // Really, no styles? return false; } /** * Checks if non-optimized CSS is to be preloaded and if so return * the tag with preload code. * * @param string $tag (required). * @param string $url (optional). * * @return string $new_tag */ private function optionally_defer_excluded( $tag, $url = '' ) { // Defer single CSS if "inline & defer" is ON and there is inline CSS. if ( ! empty( $tag ) && false === strpos( $tag, ' onload=' ) && $this->defer && ! empty( $this->defer_inline ) && apply_filters( 'autoptimize_filter_css_defer_excluded', true, $tag ) ) { // get media attribute and based on that create onload JS attribute value. if ( false === strpos( $tag, 'media=' ) ) { $tag = str_replace( ']*)(?:"|\')#Ui', $tag, $_medias ); $_media = $_medias[1]; $_preload_onload = autoptimizeConfig::get_ao_css_preload_onload( $_media ); if ( 'print' !== $_media ) { // If not media=print, adapt original element for CSS to be preloaded and add