From 809d3ba53bea8b34155cb8d009d7fa4b8a7bbdaf Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 17 Jun 2011 00:20:48 +0200 Subject: [PATCH 1/2] Use data uris for small image files in CSS This patch adds a new config option 'cssdatauri'. When enabled, the CSS patcher will automatically convert all occurances of small (<600 byte) PNG and GIF images in the CSS to embedded, base64 encoded data uris. This reduces the number of needed HTTP requests and avoids the HTTP header overhead. --- conf/dokuwiki.php | 1 + lib/exe/css.php | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/conf/dokuwiki.php b/conf/dokuwiki.php index e90e4fc23f..67edc46a68 100644 --- a/conf/dokuwiki.php +++ b/conf/dokuwiki.php @@ -108,6 +108,7 @@ $conf['subscribe_time'] = 24*60*60; //Time after which digests / lists are sent (in sec, default 1 day) //Should be smaller than the time specified in recent_days $conf['compress'] = 1; //Strip whitespaces and comments from Styles and JavaScript? 1|0 +$conf['cssdatauri'] = 1; //Embed small images into CSS, won't work on IE<8 1|0 $conf['hidepages'] = ''; //Regexp for pages to be skipped from RSS, Search and Recent Changes $conf['send404'] = 0; //Send a HTTP 404 status for non existing pages? $conf['sitemap'] = 0; //Create a google sitemap? How often? In days. diff --git a/lib/exe/css.php b/lib/exe/css.php index e4105b427f..02ed169c49 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -135,6 +135,12 @@ function css_out(){ $css = css_compress($css); } + // embed small images right into the stylesheet + if($conf['cssdatauri']){ + $base = preg_quote(DOKU_BASE,'#'); + $css = preg_replace_callback('#(url\([ \'"]*)('.$base.')(.*?(?:\.(png|gif)))#i','css_datauri',$css); + } + // save cache file io_saveFile($cache,$css); if(function_exists('gzopen')) io_saveFile("$cache.gz",$css); @@ -271,11 +277,36 @@ function css_loadfile($file,$location=''){ $css = io_readFile($file); if(!$location) return $css; - $css = preg_replace('#(url\([ \'"]*)(?!/|http://|https://| |\'|")#','\\1'.$location,$css); - $css = preg_replace('#(@import\s+[\'"])(?!/|http://|https://)#', '\\1'.$location, $css); + $css = preg_replace('#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#','\\1'.$location,$css); + $css = preg_replace('#(@import\s+[\'"])(?!/|data:|http://|https://)#', '\\1'.$location, $css); + return $css; } +/** + * Converte local image URLs to data URLs if the filesize is small + * + * Callback for preg_replace_callback + */ +function css_datauri($match){ + $pre = unslash($match[1]); + $base = unslash($match[2]); + $url = unslash($match[3]); + $ext = unslash($match[4]); + + $local = DOKU_INC.$url; + $size = @filesize($local); + if($size && $size < 600){ + $data = base64_encode(file_get_contents($local)); + } + if($data){ + $url = 'data:image/'.$ext.';base64,'.$data; + }else{ + $url = $base.$url; + } + return $pre.$url; +} + /** * Returns a list of possible Plugin Styles (no existance check here) From 28f4004c937cfc11f16e6cc7c0eb7da1a61dfcbe Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 18 Jun 2011 10:16:47 +0200 Subject: [PATCH 2/2] Made the maximum embed size for datauris configurable The feature is now disabled by default. Metadata for config manager was added. --- conf/dokuwiki.php | 2 +- lib/exe/css.php | 4 +++- lib/plugins/config/lang/en/lang.php | 1 + lib/plugins/config/settings/config.metadata.php | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/conf/dokuwiki.php b/conf/dokuwiki.php index 67edc46a68..5e185e9c21 100644 --- a/conf/dokuwiki.php +++ b/conf/dokuwiki.php @@ -108,7 +108,7 @@ $conf['subscribe_time'] = 24*60*60; //Time after which digests / lists are sent (in sec, default 1 day) //Should be smaller than the time specified in recent_days $conf['compress'] = 1; //Strip whitespaces and comments from Styles and JavaScript? 1|0 -$conf['cssdatauri'] = 1; //Embed small images into CSS, won't work on IE<8 1|0 +$conf['cssdatauri'] = 0; //Maximum byte size of small images to embed into CSS, won't work on IE<8 $conf['hidepages'] = ''; //Regexp for pages to be skipped from RSS, Search and Recent Changes $conf['send404'] = 0; //Send a HTTP 404 status for non existing pages? $conf['sitemap'] = 0; //Create a google sitemap? How often? In days. diff --git a/lib/exe/css.php b/lib/exe/css.php index 02ed169c49..92d198e198 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -289,6 +289,8 @@ function css_loadfile($file,$location=''){ * Callback for preg_replace_callback */ function css_datauri($match){ + global $conf; + $pre = unslash($match[1]); $base = unslash($match[2]); $url = unslash($match[3]); @@ -296,7 +298,7 @@ function css_datauri($match){ $local = DOKU_INC.$url; $size = @filesize($local); - if($size && $size < 600){ + if($size && $size < $conf['cssdatauri']){ $data = base64_encode(file_get_contents($local)); } if($data){ diff --git a/lib/plugins/config/lang/en/lang.php b/lib/plugins/config/lang/en/lang.php index 9b7c643bfb..e5dd4707a5 100644 --- a/lib/plugins/config/lang/en/lang.php +++ b/lib/plugins/config/lang/en/lang.php @@ -133,6 +133,7 @@ $lang['subscribers'] = 'Enable page subscription support'; $lang['subscribe_time'] = 'Time after which subscription lists and digests are sent (sec); This should be smaller than the time specified in recent_days.'; $lang['compress'] = 'Compact CSS and javascript output'; +$lang['cssdatauri'] = 'Size in bytes up to which images referenced in CSS files should be embedded right into the stylesheet to reduce HTTP request header overhead. This technique won\'t work in IE < 8! 400 to 600 bytes is a good value. Set 0 to disable.'; $lang['hidepages'] = 'Hide matching pages (regular expressions)'; $lang['send404'] = 'Send "HTTP 404/Page Not Found" for non existing pages'; $lang['sitemap'] = 'Generate Google sitemap (days)'; diff --git a/lib/plugins/config/settings/config.metadata.php b/lib/plugins/config/settings/config.metadata.php index af7e63a618..abea1be1cd 100644 --- a/lib/plugins/config/settings/config.metadata.php +++ b/lib/plugins/config/settings/config.metadata.php @@ -179,6 +179,7 @@ $meta['mailfrom'] = array('richemail'); $meta['mailprefix'] = array('string'); $meta['compress'] = array('onoff'); +$meta['cssdatauri'] = array('numeric','_pattern' => '/^\d+$/'); $meta['gzip_output'] = array('onoff'); $meta['hidepages'] = array('string'); $meta['send404'] = array('onoff');