mirror of
https://github.com/mrclay/minify.git
synced 2025-08-12 17:14:24 +02:00
Minify_CSS : remove charset at-rules by default & options cleanup
Minify_HTML : speed patch (Issue 192) Minify_Controller_MinApp : better error logging (Issue 193) index.php : allow easier custom controller hacking
This commit is contained in:
@@ -14,14 +14,12 @@
|
|||||||
*
|
*
|
||||||
* If you want to use a custom error logger, set this to your logger
|
* If you want to use a custom error logger, set this to your logger
|
||||||
* instance. Your object should have a method log(string $message).
|
* instance. Your object should have a method log(string $message).
|
||||||
*
|
|
||||||
* @todo cache system does not have error logging yet.
|
|
||||||
*/
|
*/
|
||||||
$min_errorLogger = false;
|
$min_errorLogger = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To allow debugging, you must set this option to true.
|
* To allow debug mode output, you must set this option to true.
|
||||||
*
|
*
|
||||||
* Once true, you can send the cookie minDebug to request debug mode output. The
|
* Once true, you can send the cookie minDebug to request debug mode output. The
|
||||||
* cookie value should match the URIs you'd like to debug. E.g. to debug
|
* cookie value should match the URIs you'd like to debug. E.g. to debug
|
||||||
|
@@ -54,10 +54,9 @@ if ($min_errorLogger) {
|
|||||||
require_once 'Minify/Logger.php';
|
require_once 'Minify/Logger.php';
|
||||||
if (true === $min_errorLogger) {
|
if (true === $min_errorLogger) {
|
||||||
require_once 'FirePHP.php';
|
require_once 'FirePHP.php';
|
||||||
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
$min_errorLogger = FirePHP::getInstance(true);
|
||||||
} else {
|
|
||||||
Minify_Logger::setLogger($min_errorLogger);
|
|
||||||
}
|
}
|
||||||
|
Minify_Logger::setLogger($min_errorLogger);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for URI versioning
|
// check for URI versioning
|
||||||
@@ -70,7 +69,12 @@ if (isset($_GET['g'])) {
|
|||||||
}
|
}
|
||||||
if (isset($_GET['f']) || isset($_GET['g'])) {
|
if (isset($_GET['f']) || isset($_GET['g'])) {
|
||||||
// serve!
|
// serve!
|
||||||
Minify::serve('MinApp', $min_serveOptions);
|
|
||||||
|
if (! isset($min_serveController)) {
|
||||||
|
require 'Minify/Controller/MinApp.php';
|
||||||
|
$min_serveController = new Minify_Controller_MinApp();
|
||||||
|
}
|
||||||
|
Minify::serve($min_serveController, $min_serveOptions);
|
||||||
|
|
||||||
} elseif ($min_enableBuilder) {
|
} elseif ($min_enableBuilder) {
|
||||||
header('Location: builder/');
|
header('Location: builder/');
|
||||||
|
@@ -26,6 +26,8 @@ class Minify_CSS {
|
|||||||
* 'preserveComments': (default true) multi-line comments that begin
|
* 'preserveComments': (default true) multi-line comments that begin
|
||||||
* with "/*!" will be preserved with newlines before and after to
|
* with "/*!" will be preserved with newlines before and after to
|
||||||
* enhance readability.
|
* enhance readability.
|
||||||
|
*
|
||||||
|
* 'removeCharsets': (default true) remove all @charset at-rules
|
||||||
*
|
*
|
||||||
* 'prependRelativePath': (default null) if given, this string will be
|
* 'prependRelativePath': (default null) if given, this string will be
|
||||||
* prepended to all relative URIs in import/url declarations
|
* prepended to all relative URIs in import/url declarations
|
||||||
@@ -36,23 +38,37 @@ class Minify_CSS {
|
|||||||
* the desired files. For this to work, the files *must* exist and be
|
* the desired files. For this to work, the files *must* exist and be
|
||||||
* visible by the PHP process.
|
* visible by the PHP process.
|
||||||
*
|
*
|
||||||
* 'symlinks': (default = array()) If the CSS file is stored in
|
* 'symlinks': (default = array()) If the CSS file is stored in
|
||||||
* a symlink-ed directory, provide an array of link paths to
|
* a symlink-ed directory, provide an array of link paths to
|
||||||
* target paths, where the link paths are within the document root. Because
|
* target paths, where the link paths are within the document root. Because
|
||||||
* paths need to be normalized for this to work, use "//" to substitute
|
* paths need to be normalized for this to work, use "//" to substitute
|
||||||
* the doc root in the link paths (the array keys). E.g.:
|
* the doc root in the link paths (the array keys). E.g.:
|
||||||
* <code>
|
* <code>
|
||||||
* array('//symlink' => '/real/target/path') // unix
|
* array('//symlink' => '/real/target/path') // unix
|
||||||
* array('//static' => 'D:\\staticStorage') // Windows
|
* array('//static' => 'D:\\staticStorage') // Windows
|
||||||
* </code>
|
* </code>
|
||||||
|
*
|
||||||
|
* 'docRoot': (default = $_SERVER['DOCUMENT_ROOT'])
|
||||||
|
* see Minify_CSS_UriRewriter::rewrite
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function minify($css, $options = array())
|
public static function minify($css, $options = array())
|
||||||
{
|
{
|
||||||
|
$options = array_merge(array(
|
||||||
|
'removeCharsets' => true,
|
||||||
|
'preserveComments' => true,
|
||||||
|
'currentDir' => null,
|
||||||
|
'docRoot' => $_SERVER['DOCUMENT_ROOT'],
|
||||||
|
'prependRelativePath' => null,
|
||||||
|
'symlinks' => array(),
|
||||||
|
), $options);
|
||||||
|
|
||||||
|
if ($options['removeCharsets']) {
|
||||||
|
$css = preg_replace('/@charset[^;]+;\\s*/', '', $css);
|
||||||
|
}
|
||||||
require_once 'Minify/CSS/Compressor.php';
|
require_once 'Minify/CSS/Compressor.php';
|
||||||
if (isset($options['preserveComments'])
|
if (! $options['preserveComments']) {
|
||||||
&& !$options['preserveComments']) {
|
|
||||||
$css = Minify_CSS_Compressor::process($css, $options);
|
$css = Minify_CSS_Compressor::process($css, $options);
|
||||||
} else {
|
} else {
|
||||||
require_once 'Minify/CommentPreserver.php';
|
require_once 'Minify/CommentPreserver.php';
|
||||||
@@ -62,16 +78,16 @@ class Minify_CSS {
|
|||||||
,array($options)
|
,array($options)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (! isset($options['currentDir']) && ! isset($options['prependRelativePath'])) {
|
if (! $options['currentDir'] && ! $options['prependRelativePath']) {
|
||||||
return $css;
|
return $css;
|
||||||
}
|
}
|
||||||
require_once 'Minify/CSS/UriRewriter.php';
|
require_once 'Minify/CSS/UriRewriter.php';
|
||||||
if (isset($options['currentDir'])) {
|
if ($options['currentDir']) {
|
||||||
return Minify_CSS_UriRewriter::rewrite(
|
return Minify_CSS_UriRewriter::rewrite(
|
||||||
$css
|
$css
|
||||||
,$options['currentDir']
|
,$options['currentDir']
|
||||||
,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
|
,$options['docRoot']
|
||||||
,isset($options['symlinks']) ? $options['symlinks'] : array()
|
,$options['symlinks']
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Minify_CSS_UriRewriter::prepend(
|
return Minify_CSS_UriRewriter::prepend(
|
||||||
|
@@ -65,11 +65,11 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
|
|||||||
if (0 === strpos($file, '//')) {
|
if (0 === strpos($file, '//')) {
|
||||||
$file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1);
|
$file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1);
|
||||||
}
|
}
|
||||||
$file = realpath($file);
|
$realpath = realpath($file);
|
||||||
if ($file && is_file($file)) {
|
if ($realpath && is_file($realpath)) {
|
||||||
$sources[] = $this->_getFileSource($file, $cOptions);
|
$sources[] = $this->_getFileSource($realpath, $cOptions);
|
||||||
} else {
|
} else {
|
||||||
$this->log("The path \"{$file}\" could not be found (or was not a file)");
|
$this->log("The path \"{$file}\" (realpath \"{$realpath}\") could not be found (or was not a file)");
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
|
|||||||
// no "./"
|
// no "./"
|
||||||
|| preg_match('/(?:^|[^\\.])\\.\\//', $_GET['f'])
|
|| preg_match('/(?:^|[^\\.])\\.\\//', $_GET['f'])
|
||||||
) {
|
) {
|
||||||
$this->log("GET param 'f' invalid (see MinApp.php line 63)");
|
$this->log("GET param 'f' was invalid");
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
$ext = ".{$m[1]}";
|
$ext = ".{$m[1]}";
|
||||||
@@ -109,7 +109,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
|
|||||||
}
|
}
|
||||||
$files = explode(',', $_GET['f']);
|
$files = explode(',', $_GET['f']);
|
||||||
if ($files != array_unique($files)) {
|
if ($files != array_unique($files)) {
|
||||||
$this->log("Duplicate files specified");
|
$this->log("Duplicate files were specified");
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
if (isset($_GET['b'])) {
|
if (isset($_GET['b'])) {
|
||||||
@@ -120,7 +120,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
|
|||||||
// valid base
|
// valid base
|
||||||
$base = "/{$_GET['b']}/";
|
$base = "/{$_GET['b']}/";
|
||||||
} else {
|
} else {
|
||||||
$this->log("GET param 'b' invalid (see MinApp.php line 84)");
|
$this->log("GET param 'b' was invalid");
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -134,25 +134,26 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
|
|||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
$uri = $base . $file;
|
$uri = $base . $file;
|
||||||
$path = $_SERVER['DOCUMENT_ROOT'] . $uri;
|
$path = $_SERVER['DOCUMENT_ROOT'] . $uri;
|
||||||
$file = realpath($path);
|
$realpath = realpath($path);
|
||||||
if (false === $file || ! is_file($file)) {
|
if (false === $realpath || ! is_file($realpath)) {
|
||||||
|
$this->log("The path \"{$path}\" (realpath \"{$realpath}\") could not be found (or was not a file)");
|
||||||
if (! $missingUri) {
|
if (! $missingUri) {
|
||||||
$missingUri = $uri;
|
$missingUri = $uri;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
$this->log("At least two files missing: '$missingUri', '$uri'");
|
$this->log("More than one file was missing: '$missingUri', '$uri'");
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
parent::checkNotHidden($file);
|
parent::checkNotHidden($realpath);
|
||||||
parent::checkAllowDirs($file, $allowDirs, $uri);
|
parent::checkAllowDirs($realpath, $allowDirs, $uri);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->log($e->getMessage());
|
$this->log($e->getMessage());
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
$sources[] = $this->_getFileSource($file, $cOptions);
|
$sources[] = $this->_getFileSource($realpath, $cOptions);
|
||||||
$basenames[] = basename($file, $ext);
|
$basenames[] = basename($realpath, $ext);
|
||||||
}
|
}
|
||||||
if ($this->selectionId) {
|
if ($this->selectionId) {
|
||||||
$this->selectionId .= '_f=';
|
$this->selectionId .= '_f=';
|
||||||
|
@@ -1,245 +1,240 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Class Minify_HTML
|
* Class Minify_HTML
|
||||||
* @package Minify
|
* @package Minify
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compress HTML
|
* Compress HTML
|
||||||
*
|
*
|
||||||
* This is a heavy regex-based removal of whitespace, unnecessary comments and
|
* This is a heavy regex-based removal of whitespace, unnecessary comments and
|
||||||
* tokens. IE conditional comments are preserved. There are also options to have
|
* tokens. IE conditional comments are preserved. There are also options to have
|
||||||
* STYLE and SCRIPT blocks compressed by callback functions.
|
* STYLE and SCRIPT blocks compressed by callback functions.
|
||||||
*
|
*
|
||||||
* A test suite is available.
|
* A test suite is available.
|
||||||
*
|
*
|
||||||
* @package Minify
|
* @package Minify
|
||||||
* @author Stephen Clay <steve@mrclay.org>
|
* @author Stephen Clay <steve@mrclay.org>
|
||||||
*/
|
*/
|
||||||
class Minify_HTML {
|
class Minify_HTML {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Minify" an HTML page
|
* "Minify" an HTML page
|
||||||
*
|
*
|
||||||
* @param string $html
|
* @param string $html
|
||||||
*
|
*
|
||||||
* @param array $options
|
* @param array $options
|
||||||
*
|
*
|
||||||
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
||||||
* elements.
|
* elements.
|
||||||
*
|
*
|
||||||
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
||||||
* elements. Note: the type attribute is ignored.
|
* elements. Note: the type attribute is ignored.
|
||||||
*
|
*
|
||||||
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
||||||
* unset, minify will sniff for an XHTML doctype.
|
* unset, minify will sniff for an XHTML doctype.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function minify($html, $options = array()) {
|
public static function minify($html, $options = array()) {
|
||||||
$min = new Minify_HTML($html, $options);
|
$min = new Minify_HTML($html, $options);
|
||||||
return $min->process();
|
return $min->process();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a minifier object
|
* Create a minifier object
|
||||||
*
|
*
|
||||||
* @param string $html
|
* @param string $html
|
||||||
*
|
*
|
||||||
* @param array $options
|
* @param array $options
|
||||||
*
|
*
|
||||||
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
||||||
* elements.
|
* elements.
|
||||||
*
|
*
|
||||||
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
||||||
* elements. Note: the type attribute is ignored.
|
* elements. Note: the type attribute is ignored.
|
||||||
*
|
*
|
||||||
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
||||||
* unset, minify will sniff for an XHTML doctype.
|
* unset, minify will sniff for an XHTML doctype.
|
||||||
*
|
*
|
||||||
* @return null
|
* @return null
|
||||||
*/
|
*/
|
||||||
public function __construct($html, $options = array())
|
public function __construct($html, $options = array())
|
||||||
{
|
{
|
||||||
$this->_html = str_replace("\r\n", "\n", trim($html));
|
$this->_html = str_replace("\r\n", "\n", trim($html));
|
||||||
if (isset($options['xhtml'])) {
|
if (isset($options['xhtml'])) {
|
||||||
$this->_isXhtml = (bool)$options['xhtml'];
|
$this->_isXhtml = (bool)$options['xhtml'];
|
||||||
}
|
}
|
||||||
if (isset($options['cssMinifier'])) {
|
if (isset($options['cssMinifier'])) {
|
||||||
$this->_cssMinifier = $options['cssMinifier'];
|
$this->_cssMinifier = $options['cssMinifier'];
|
||||||
}
|
}
|
||||||
if (isset($options['jsMinifier'])) {
|
if (isset($options['jsMinifier'])) {
|
||||||
$this->_jsMinifier = $options['jsMinifier'];
|
$this->_jsMinifier = $options['jsMinifier'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minify the markeup given in the constructor
|
* Minify the markeup given in the constructor
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function process()
|
public function process()
|
||||||
{
|
{
|
||||||
if ($this->_isXhtml === null) {
|
if ($this->_isXhtml === null) {
|
||||||
$this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
|
$this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
|
$this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
|
||||||
$this->_placeholders = array();
|
$this->_placeholders = array();
|
||||||
|
|
||||||
// replace SCRIPTs (and minify) with placeholders
|
// replace SCRIPTs (and minify) with placeholders
|
||||||
$this->_html = preg_replace_callback(
|
$this->_html = preg_replace_callback(
|
||||||
'/(\\s*)(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
|
'/(\\s*)<script(\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
|
||||||
,array($this, '_removeScriptCB')
|
,array($this, '_removeScriptCB')
|
||||||
,$this->_html);
|
,$this->_html);
|
||||||
|
|
||||||
// replace STYLEs (and minify) with placeholders
|
// replace STYLEs (and minify) with placeholders
|
||||||
$this->_html = preg_replace_callback(
|
$this->_html = preg_replace_callback(
|
||||||
'/\\s*(<style\\b[^>]*?>)([\\s\\S]*?)<\\/style>\\s*/i'
|
'/\\s*<style(\\b[^>]*>)([\\s\\S]*?)<\\/style>\\s*/i'
|
||||||
,array($this, '_removeStyleCB')
|
,array($this, '_removeStyleCB')
|
||||||
,$this->_html);
|
,$this->_html);
|
||||||
|
|
||||||
// remove HTML comments (not containing IE conditional comments).
|
// remove HTML comments (not containing IE conditional comments).
|
||||||
$this->_html = preg_replace_callback(
|
$this->_html = preg_replace_callback(
|
||||||
'/<!--([\\s\\S]*?)-->/'
|
'/<!--([\\s\\S]*?)-->/'
|
||||||
,array($this, '_commentCB')
|
,array($this, '_commentCB')
|
||||||
,$this->_html);
|
,$this->_html);
|
||||||
|
|
||||||
// replace PREs with placeholders
|
// replace PREs with placeholders
|
||||||
$this->_html = preg_replace_callback('/\\s*(<pre\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
|
$this->_html = preg_replace_callback('/\\s*<pre(\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
|
||||||
,array($this, '_removePreCB')
|
,array($this, '_removePreCB')
|
||||||
,$this->_html);
|
,$this->_html);
|
||||||
|
|
||||||
// replace TEXTAREAs with placeholders
|
// replace TEXTAREAs with placeholders
|
||||||
$this->_html = preg_replace_callback(
|
$this->_html = preg_replace_callback(
|
||||||
'/\\s*(<textarea\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
|
'/\\s*<textarea(\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
|
||||||
,array($this, '_removeTextareaCB')
|
,array($this, '_removeTextareaCB')
|
||||||
,$this->_html);
|
,$this->_html);
|
||||||
|
|
||||||
// trim each line.
|
// trim each line.
|
||||||
// @todo take into account attribute values that span multiple lines.
|
// @todo take into account attribute values that span multiple lines.
|
||||||
$this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
|
$this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
|
||||||
|
|
||||||
// remove ws around block/undisplayed elements
|
// remove ws around block/undisplayed elements
|
||||||
$this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
|
$this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
|
||||||
.'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
|
.'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
|
||||||
.'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
|
.'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
|
||||||
.'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
|
.'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
|
||||||
.'|ul)\\b[^>]*>)/i', '$1', $this->_html);
|
.'|ul)\\b[^>]*>)/i', '$1', $this->_html);
|
||||||
|
|
||||||
// remove ws outside of all elements
|
// remove ws outside of all elements
|
||||||
$this->_html = preg_replace_callback(
|
$this->_html = preg_replace(
|
||||||
'/>([^<]+)</'
|
'/>(\\s(?:\\s*))?([^<]+)(\\s(?:\s*))?</'
|
||||||
,array($this, '_outsideTagCB')
|
,'>$1$2$3<'
|
||||||
,$this->_html);
|
,$this->_html);
|
||||||
|
|
||||||
// use newlines before 1st attribute in open tags (to limit line lengths)
|
// use newlines before 1st attribute in open tags (to limit line lengths)
|
||||||
$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
|
$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
|
||||||
|
|
||||||
// fill placeholders
|
// fill placeholders
|
||||||
$this->_html = str_replace(
|
$this->_html = str_replace(
|
||||||
array_keys($this->_placeholders)
|
array_keys($this->_placeholders)
|
||||||
,array_values($this->_placeholders)
|
,array_values($this->_placeholders)
|
||||||
,$this->_html
|
,$this->_html
|
||||||
);
|
);
|
||||||
return $this->_html;
|
return $this->_html;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function _commentCB($m)
|
protected function _commentCB($m)
|
||||||
{
|
{
|
||||||
return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<!['))
|
return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<!['))
|
||||||
? $m[0]
|
? $m[0]
|
||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function _reservePlace($content)
|
protected function _reservePlace($content)
|
||||||
{
|
{
|
||||||
$placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
|
$placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
|
||||||
$this->_placeholders[$placeholder] = $content;
|
$this->_placeholders[$placeholder] = $content;
|
||||||
return $placeholder;
|
return $placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected $_isXhtml = null;
|
protected $_isXhtml = null;
|
||||||
protected $_replacementHash = null;
|
protected $_replacementHash = null;
|
||||||
protected $_placeholders = array();
|
protected $_placeholders = array();
|
||||||
protected $_cssMinifier = null;
|
protected $_cssMinifier = null;
|
||||||
protected $_jsMinifier = null;
|
protected $_jsMinifier = null;
|
||||||
|
|
||||||
protected function _outsideTagCB($m)
|
protected function _removePreCB($m)
|
||||||
{
|
{
|
||||||
return '>' . preg_replace('/^\\s+|\\s+$/', ' ', $m[1]) . '<';
|
return $this->_reservePlace("<pre{$m[1]}");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function _removePreCB($m)
|
protected function _removeTextareaCB($m)
|
||||||
{
|
{
|
||||||
return $this->_reservePlace($m[1]);
|
return $this->_reservePlace("<textarea{$m[1]}");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function _removeTextareaCB($m)
|
protected function _removeStyleCB($m)
|
||||||
{
|
{
|
||||||
return $this->_reservePlace($m[1]);
|
$openStyle = "<style{$m[1]}";
|
||||||
}
|
$css = $m[2];
|
||||||
|
// remove HTML comments
|
||||||
protected function _removeStyleCB($m)
|
$css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
|
||||||
{
|
|
||||||
$openStyle = $m[1];
|
// remove CDATA section markers
|
||||||
$css = $m[2];
|
$css = $this->_removeCdata($css);
|
||||||
// remove HTML comments
|
|
||||||
$css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
|
// minify
|
||||||
|
$minifier = $this->_cssMinifier
|
||||||
// remove CDATA section markers
|
? $this->_cssMinifier
|
||||||
$css = $this->_removeCdata($css);
|
: 'trim';
|
||||||
|
$css = call_user_func($minifier, $css);
|
||||||
// minify
|
|
||||||
$minifier = $this->_cssMinifier
|
return $this->_reservePlace($this->_needsCdata($css)
|
||||||
? $this->_cssMinifier
|
? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
|
||||||
: 'trim';
|
: "{$openStyle}{$css}</style>"
|
||||||
$css = call_user_func($minifier, $css);
|
);
|
||||||
|
}
|
||||||
return $this->_reservePlace($this->_needsCdata($css)
|
|
||||||
? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
|
protected function _removeScriptCB($m)
|
||||||
: "{$openStyle}{$css}</style>"
|
{
|
||||||
);
|
$openScript = "<script{$m[2]}";
|
||||||
}
|
$js = $m[3];
|
||||||
|
|
||||||
protected function _removeScriptCB($m)
|
// whitespace surrounding? preserve at least one space
|
||||||
{
|
$ws1 = ($m[1] === '') ? '' : ' ';
|
||||||
$openScript = $m[2];
|
$ws2 = ($m[4] === '') ? '' : ' ';
|
||||||
$js = $m[3];
|
|
||||||
|
// remove HTML comments (and ending "//" if present)
|
||||||
// whitespace surrounding? preserve at least one space
|
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
|
||||||
$ws1 = ($m[1] === '') ? '' : ' ';
|
|
||||||
$ws2 = ($m[4] === '') ? '' : ' ';
|
// remove CDATA section markers
|
||||||
|
$js = $this->_removeCdata($js);
|
||||||
// remove HTML comments (and ending "//" if present)
|
|
||||||
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
|
// minify
|
||||||
|
$minifier = $this->_jsMinifier
|
||||||
// remove CDATA section markers
|
? $this->_jsMinifier
|
||||||
$js = $this->_removeCdata($js);
|
: 'trim';
|
||||||
|
$js = call_user_func($minifier, $js);
|
||||||
// minify
|
|
||||||
$minifier = $this->_jsMinifier
|
return $this->_reservePlace($this->_needsCdata($js)
|
||||||
? $this->_jsMinifier
|
? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
|
||||||
: 'trim';
|
: "{$ws1}{$openScript}{$js}</script>{$ws2}"
|
||||||
$js = call_user_func($minifier, $js);
|
);
|
||||||
|
}
|
||||||
return $this->_reservePlace($this->_needsCdata($js)
|
|
||||||
? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
|
protected function _removeCdata($str)
|
||||||
: "{$ws1}{$openScript}{$js}</script>{$ws2}"
|
{
|
||||||
);
|
return (false !== strpos($str, '<![CDATA['))
|
||||||
}
|
? str_replace(array('<![CDATA[', ']]>'), '', $str)
|
||||||
|
: $str;
|
||||||
protected function _removeCdata($str)
|
}
|
||||||
{
|
|
||||||
return (false !== strpos($str, '<![CDATA['))
|
protected function _needsCdata($str)
|
||||||
? str_replace(array('<![CDATA[', ']]>'), '', $str)
|
{
|
||||||
: $str;
|
return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
protected function _needsCdata($str)
|
|
||||||
{
|
|
||||||
return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
@charset "utf-8";
|
||||||
|
|
||||||
/* some CSS to try to exercise things in general */
|
/* some CSS to try to exercise things in general */
|
||||||
|
|
||||||
@import url( /more.css );
|
@import url( /more.css );
|
||||||
|
@@ -20,10 +20,12 @@ rel="alternate"
|
|||||||
type="application/rss+xml"
|
type="application/rss+xml"
|
||||||
title="RSS"
|
title="RSS"
|
||||||
href="http://www.csszengarden.com/zengarden.xml" /></head><body
|
href="http://www.csszengarden.com/zengarden.xml" /></head><body
|
||||||
id="css-zen-garden"> <!--[if !IE]>--><p>Browser != IE</p><!--<![endif]--><div
|
id="css-zen-garden">
|
||||||
|
<!--[if !IE]>--><p>Browser != IE</p><!--<![endif]--><div
|
||||||
id="container"><div
|
id="container"><div
|
||||||
id="pageHeader"><h1><span>css Zen Garden</span></h1><h2><span>The Beauty of <acronym
|
id="pageHeader"><h1><span>css Zen Garden</span></h1><h2><span>The Beauty of <acronym
|
||||||
title="Cascading Style Sheets">CSS</acronym> Design</span></h2></div><pre>
|
title="Cascading Style Sheets">CSS</acronym>
|
||||||
|
Design</span></h2></div><pre>
|
||||||
White space is important here!
|
White space is important here!
|
||||||
</pre><div
|
</pre><div
|
||||||
id="quickSummary"><p
|
id="quickSummary"><p
|
||||||
|
@@ -20,10 +20,12 @@ rel="alternate"
|
|||||||
type="application/rss+xml"
|
type="application/rss+xml"
|
||||||
title="RSS"
|
title="RSS"
|
||||||
href="http://www.csszengarden.com/zengarden.xml"></head><body
|
href="http://www.csszengarden.com/zengarden.xml"></head><body
|
||||||
id="css-zen-garden"> <!--[if !IE]>--><p>Browser != IE</p><!--<![endif]--><div
|
id="css-zen-garden">
|
||||||
|
<!--[if !IE]>--><p>Browser != IE</p><!--<![endif]--><div
|
||||||
id="container"><div
|
id="container"><div
|
||||||
id="pageHeader"><h1><span>css Zen Garden</span></h1><h2><span>The Beauty of <acronym
|
id="pageHeader"><h1><span>css Zen Garden</span></h1><h2><span>The Beauty of <acronym
|
||||||
title="Cascading Style Sheets">CSS</acronym> Design</span></h2></div><pre>
|
title="Cascading Style Sheets">CSS</acronym>
|
||||||
|
Design</span></h2></div><pre>
|
||||||
White space is important here!
|
White space is important here!
|
||||||
</pre><div
|
</pre><div
|
||||||
id="quickSummary"><p
|
id="quickSummary"><p
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
@media screen {
|
@media screen {
|
||||||
|
@charset "utf-8";
|
||||||
|
|
||||||
/* some CSS to try to exercise things in general */
|
/* some CSS to try to exercise things in general */
|
||||||
|
|
||||||
@import url(/more.css);
|
@import url(/more.css);
|
||||||
|
Reference in New Issue
Block a user