mirror of
https://github.com/mrclay/minify.git
synced 2025-08-14 01:54:11 +02:00
CSS/UriRewriter.php : + $debugText static var
Minify/Lines.php : + URI rewriting (w/ debugging) test_Minify_CSS_UriRewriter.php : echos $debugText Minify.php : tiny mod to import warning - MyMin.php : needed fix already merged into JSMin.php
This commit is contained in:
@@ -56,7 +56,7 @@ class Minify {
|
|||||||
*
|
*
|
||||||
* @var string $importWarning
|
* @var string $importWarning
|
||||||
*/
|
*/
|
||||||
public static $importWarning = "/* See http://code.google.com/p/minify/wiki/CommonProblems#@imports_can_appear_in_invalid_locations_in_combined_CSS_files */";
|
public static $importWarning = "/* See http://code.google.com/p/minify/wiki/CommonProblems#@imports_can_appear_in_invalid_locations_in_combined_CSS_files */\n";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a cache object (with identical interface as Minify_Cache_File) or
|
* Specify a cache object (with identical interface as Minify_Cache_File) or
|
||||||
|
@@ -19,6 +19,12 @@ class Minify_CSS_UriRewriter {
|
|||||||
*/
|
*/
|
||||||
protected static $className = 'Minify_CSS_UriRewriter';
|
protected static $className = 'Minify_CSS_UriRewriter';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rewrite() and rewriteRelative() append debugging information here
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $debugText = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rewrite file relative URIs as root relative in CSS files
|
* Rewrite file relative URIs as root relative in CSS files
|
||||||
*
|
*
|
||||||
@@ -58,6 +64,13 @@ class Minify_CSS_UriRewriter {
|
|||||||
self::$_symlinks[$link] = self::_realpath($target);
|
self::$_symlinks[$link] = self::_realpath($target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self::$debugText .= "docRoot : " . self::$_docRoot . "\n"
|
||||||
|
. "currentDir : " . self::$_currentDir . "\n";
|
||||||
|
if (self::$_symlinks) {
|
||||||
|
self::$debugText .= "symlinks : " . var_export(self::$_symlinks, 1) . "\n";
|
||||||
|
}
|
||||||
|
self::$debugText .= "\n";
|
||||||
|
|
||||||
$css = self::_trimUrls($css);
|
$css = self::_trimUrls($css);
|
||||||
|
|
||||||
// rewrite
|
// rewrite
|
||||||
@@ -202,16 +215,26 @@ class Minify_CSS_UriRewriter {
|
|||||||
// prepend path with current dir separator (OS-independent)
|
// prepend path with current dir separator (OS-independent)
|
||||||
$path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR)
|
$path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR)
|
||||||
. DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR);
|
. DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
|
self::$debugText .= "file-relative URI : {$uri}\n"
|
||||||
|
. "path prepended : {$path}\n";
|
||||||
|
|
||||||
// "unresolve" a symlink back to doc root
|
// "unresolve" a symlink back to doc root
|
||||||
foreach ($symlinks as $link => $target) {
|
foreach ($symlinks as $link => $target) {
|
||||||
if (0 === strpos($path, $target)) {
|
if (0 === strpos($path, $target)) {
|
||||||
// replace $target with $link
|
// replace $target with $link
|
||||||
$path = $link . substr($path, strlen($target));
|
$path = $link . substr($path, strlen($target));
|
||||||
|
|
||||||
|
self::$debugText .= "symlink unresolved : {$path}\n";
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// strip doc root
|
// strip doc root
|
||||||
$path = substr($path, strlen($realDocRoot));
|
$path = substr($path, strlen($realDocRoot));
|
||||||
|
|
||||||
|
self::$debugText .= "docroot stripped : {$path}\n";
|
||||||
|
|
||||||
// fix to root-relative URI
|
// fix to root-relative URI
|
||||||
$uri = strtr($path, DIRECTORY_SEPARATOR, '/');
|
$uri = strtr($path, DIRECTORY_SEPARATOR, '/');
|
||||||
// remove /./ and /../ where possible
|
// remove /./ and /../ where possible
|
||||||
@@ -220,9 +243,14 @@ class Minify_CSS_UriRewriter {
|
|||||||
do {
|
do {
|
||||||
$uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, -1, $changed);
|
$uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, -1, $changed);
|
||||||
} while ($changed);
|
} while ($changed);
|
||||||
|
|
||||||
|
self::$debugText .= "traversals removed : {$uri}\n\n";
|
||||||
|
|
||||||
return $uri;
|
return $uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get realpath with any trailing slash removed
|
* Get realpath with any trailing slash removed
|
||||||
*
|
*
|
||||||
|
@@ -18,13 +18,19 @@ class Minify_Lines {
|
|||||||
*
|
*
|
||||||
* This uses a very basic parser easily fooled by comment tokens inside
|
* This uses a very basic parser easily fooled by comment tokens inside
|
||||||
* strings or regexes, but, otherwise, generally clean code will not be
|
* strings or regexes, but, otherwise, generally clean code will not be
|
||||||
* mangled.
|
* mangled. URI rewriting can also be performed.
|
||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
*
|
*
|
||||||
* @param array $options available options:
|
* @param array $options available options:
|
||||||
*
|
*
|
||||||
* 'id': (optional) string to identify file. E.g. file name/path
|
* 'id': (optional) string to identify file. E.g. file name/path
|
||||||
|
*
|
||||||
|
* 'currentDir': (default null) if given, this is assumed to be the
|
||||||
|
* directory of the current CSS file. Using this, minify will rewrite
|
||||||
|
* all relative URIs in import/url declarations to correctly point to
|
||||||
|
* the desired files, and prepend a comment with debugging information about
|
||||||
|
* this process.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@@ -49,7 +55,24 @@ class Minify_Lines {
|
|||||||
$newLines[] = self::_addNote($line, $i, $inComment, $padTo);
|
$newLines[] = self::_addNote($line, $i, $inComment, $padTo);
|
||||||
$inComment = self::_eolInComment($line, $inComment);
|
$inComment = self::_eolInComment($line, $inComment);
|
||||||
}
|
}
|
||||||
return implode("\n", $newLines) . "\n";
|
$content = implode("\n", $newLines) . "\n";
|
||||||
|
|
||||||
|
// check for desired URI rewriting
|
||||||
|
if (isset($options['currentDir'])) {
|
||||||
|
require_once 'Minify/CSS/UriRewriter.php';
|
||||||
|
Minify_CSS_UriRewriter::$debugText = '';
|
||||||
|
$content = Minify_CSS_UriRewriter::rewrite(
|
||||||
|
$content
|
||||||
|
,$options['currentDir']
|
||||||
|
,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
|
||||||
|
,isset($options['symlinks']) ? $options['symlinks'] : array()
|
||||||
|
);
|
||||||
|
$content = "/* Minify_CSS_UriRewriter::\$debugText\n\n"
|
||||||
|
. Minify_CSS_UriRewriter::$debugText . "*/\n"
|
||||||
|
. $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,289 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* MyMin - JSMin like alternative parser for JavaScript
|
|
||||||
*
|
|
||||||
* This class is a jsmin alternative, based on same parser logic but modified
|
|
||||||
* to mantain performances and to parse correctly JavaScript conditional comments too.
|
|
||||||
*
|
|
||||||
* SERVER SIDE
|
|
||||||
* PHP 5 or greater is required.
|
|
||||||
* This code is compatible with every error_reporting level (E_ALL | E_STRICT)
|
|
||||||
* The best practice to use this code is caching results without run-time
|
|
||||||
* evaluation (your server should be stressed too much with big files)
|
|
||||||
*
|
|
||||||
* Permission is hereby granted to use this version of the library under the
|
|
||||||
* same terms as jsmin.php, which has the following license:
|
|
||||||
*
|
|
||||||
* --
|
|
||||||
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
* this software and associated documentation files (the "Software"), to deal in
|
|
||||||
* the Software without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
|
||||||
* so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* The Software shall be used for Good, not Evil.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
* --
|
|
||||||
*
|
|
||||||
* @class MyMin
|
|
||||||
* @author Andrea Giammarchi <http://www.3site.eu>
|
|
||||||
* @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
|
|
||||||
* @copyright 2007 Ryan Grove <ryan@wonko.com> (PHP port)
|
|
||||||
* @copyright 2007 Andrea Giammarchi (improvements + MyMinCompressor + MyMinCSS)
|
|
||||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
|
||||||
* @version 1.0.1 (2007-10-05) - updated 2008-02-17
|
|
||||||
*/
|
|
||||||
|
|
||||||
// -- Class MyMin --------------------------------------------------------------
|
|
||||||
class MyMin {
|
|
||||||
|
|
||||||
const /* char */ LF = "\n",
|
|
||||||
SPACE = ' ',
|
|
||||||
EOS = "\x00";
|
|
||||||
|
|
||||||
protected /* boolean */ $cc_on;
|
|
||||||
|
|
||||||
protected /* char */ $a,
|
|
||||||
$ahead,
|
|
||||||
$b;
|
|
||||||
|
|
||||||
protected /* int */ $index = 0,
|
|
||||||
$length;
|
|
||||||
|
|
||||||
protected /* string */ $input,
|
|
||||||
$output = "";
|
|
||||||
|
|
||||||
// -- Public Static Methods ----------------------------------------------------
|
|
||||||
static public final function /* string */ parse(/* string */ $input, /* boolean */ $cc_on = true){
|
|
||||||
return "".(new MyMin($input, $cc_on));
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Public Instance Methods --------------------------------------------------
|
|
||||||
public final function /* object */ __construct(/* string */ $input, /* boolean */ $cc_on = true){
|
|
||||||
$this->input = preg_replace("/(\r\n|\n\r|\r|\n)+/", self::LF, trim($input));
|
|
||||||
$this->length = strlen($this->input);
|
|
||||||
$this->cc_on = $cc_on;
|
|
||||||
$this->b = $this->ahead = self::SPACE;
|
|
||||||
$this->a = self::LF;
|
|
||||||
$this->action(3);
|
|
||||||
while($this->a !== self::EOS){
|
|
||||||
switch($this->a){
|
|
||||||
case self::SPACE:
|
|
||||||
$this->action($this->isAlNum($this->b) ? 1 : 2);
|
|
||||||
break;
|
|
||||||
case self::LF:
|
|
||||||
switch($this->b){
|
|
||||||
case '{':
|
|
||||||
case '[':
|
|
||||||
case '(':
|
|
||||||
case '+':
|
|
||||||
case '-':
|
|
||||||
$this->action(1);
|
|
||||||
break;
|
|
||||||
case self::SPACE:
|
|
||||||
$this->action(3);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->action($this->isAlNum($this->b) ? 1 : 2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
switch($this->b){
|
|
||||||
case self::SPACE:
|
|
||||||
$this->action($this->isAlNum($this->a) ? 1 : 3);
|
|
||||||
break;
|
|
||||||
case self::LF:
|
|
||||||
switch($this->a){
|
|
||||||
case '}':
|
|
||||||
case ']':
|
|
||||||
case ')':
|
|
||||||
case '+':
|
|
||||||
case '-':
|
|
||||||
case '"':
|
|
||||||
case '\'':
|
|
||||||
$this->action(1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->action($this->isAlNum($this->a) ? 1 : 3);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->action(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final function /* string */ __toString(/* void */){
|
|
||||||
return str_replace("\n\n", "\n", ltrim($this->output));
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Protected Instance Methods -----------------------------------------------
|
|
||||||
protected function /* void */ action(/* int */ $i){
|
|
||||||
switch($i){
|
|
||||||
case 1:
|
|
||||||
$this->output .= $this->a;
|
|
||||||
case 2:
|
|
||||||
$this->a = $this->b;
|
|
||||||
if($this->a === '\'' || $this->a === '"'){
|
|
||||||
while(true){
|
|
||||||
$this->output .= $this->a;
|
|
||||||
if(!$this->nextCharNoSlash($this->b, "Unterminated string literal."))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
$this->b = $this->next();
|
|
||||||
if($this->b === '/'){
|
|
||||||
switch($this->a){
|
|
||||||
case self::LF:
|
|
||||||
case self::SPACE:
|
|
||||||
if(!$this->spaceBeforeRegExp($this->output))
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '{':
|
|
||||||
case ';':
|
|
||||||
|
|
||||||
case '(':
|
|
||||||
case ',':
|
|
||||||
case '=':
|
|
||||||
case ':':
|
|
||||||
case '[':
|
|
||||||
case '!':
|
|
||||||
case '&':
|
|
||||||
case '|':
|
|
||||||
case '?':
|
|
||||||
$this->output .= $this->a.$this->b;
|
|
||||||
while($this->nextCharNoSlash('/', "Unterminated regular expression literal."))
|
|
||||||
$this->output .= $this->a;
|
|
||||||
$this->b = $this->next();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function /* void */ appendComment(/* int */ $pos, /* string */ $open, /* string */ $close) {
|
|
||||||
$this->output .= $this->a.$open.(new MyMin(substr($this->input, $this->index, $pos - $this->index), $this->cc_on)).$close;
|
|
||||||
$this->index = $pos;
|
|
||||||
$this->a = self::LF;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function /* void */ conditionalComment(/* char */ $find) {
|
|
||||||
$single = $find === self::LF;
|
|
||||||
$pos = strpos($this->input, $find, $this->index);
|
|
||||||
if($pos === false){
|
|
||||||
if($single)
|
|
||||||
$pos = $this->length;
|
|
||||||
else
|
|
||||||
throw new MyMinException("Unterminated comment.");
|
|
||||||
}
|
|
||||||
$this->appendComment($pos, $single ? "//" : "/*", $find);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function /* char */ get(/* void */) {
|
|
||||||
$c = $this->ahead;
|
|
||||||
$this->ahead = self::EOS;
|
|
||||||
if($c === self::EOS && $this->index < $this->length)
|
|
||||||
$c = $this->input{$this->index++};
|
|
||||||
return ($c === self::EOS || $c === self::LF || $c >= self::SPACE) ? $c : self::SPACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function /* boolean */ isAlNum(/* char */ $c) {
|
|
||||||
return $c > 126 || $c === '\\' || preg_match('/^(\w|\$)$/', $c);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function /* char */ next(/* void */) {
|
|
||||||
$c = $this->get();
|
|
||||||
$loop = true;
|
|
||||||
if($c === '/'){
|
|
||||||
switch($this->ahead = $this->get()){
|
|
||||||
case '/':
|
|
||||||
if($this->cc_on && $this->input{$this->index} === '@')
|
|
||||||
$this->conditionalComment(self::LF);
|
|
||||||
while($loop){
|
|
||||||
$c = $this->get();
|
|
||||||
if($c <= self::LF)
|
|
||||||
$loop = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '*':
|
|
||||||
$this->get();
|
|
||||||
if($this->cc_on && $this->input{$this->index} === '@')
|
|
||||||
$this->conditionalComment("*/");
|
|
||||||
while($loop){
|
|
||||||
switch($this->get()){
|
|
||||||
case '*':
|
|
||||||
if(($this->ahead = $this->get()) === '/'){
|
|
||||||
$this->get();
|
|
||||||
$c = self::SPACE;
|
|
||||||
$loop = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case self::EOS:
|
|
||||||
throw new MyMinException("Unterminated comment.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $c;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function /* boolean */ nextCharNoSlash(/* char */ $c, /* string */ $message) {
|
|
||||||
$loop = true;
|
|
||||||
$this->a = $this->get();
|
|
||||||
if($this->a === $c)
|
|
||||||
$loop = false;
|
|
||||||
else{
|
|
||||||
if($this->a === '\\'){
|
|
||||||
$this->output .= $this->a;
|
|
||||||
$this->a = $this->get();
|
|
||||||
}
|
|
||||||
if($this->a <= self::LF)
|
|
||||||
throw new MyMinException($message);
|
|
||||||
}
|
|
||||||
return $loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function /* boolean */ spaceBeforeRegExp(/* string */ $output){
|
|
||||||
for(
|
|
||||||
$i = 0,
|
|
||||||
$length = strlen($output),
|
|
||||||
$reserved = array("case", "else", "in", "return", "typeof"),
|
|
||||||
$result = false,
|
|
||||||
$tmp = "";
|
|
||||||
$i < 5 && !$result;
|
|
||||||
$i++
|
|
||||||
){
|
|
||||||
if($length === strlen($reserved[$i]))
|
|
||||||
$result = $reserved[$i] === $output;
|
|
||||||
else if($length > strlen($reserved[$i])){
|
|
||||||
$tmp = substr($output, $length - strlen($reserved[$i]) - 1);
|
|
||||||
$result = substr($tmp, 1) === $reserved[$i] && !$this->isAlNum($tmp{0});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return $length < 2 ? true : $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- MyMin Exceptions ---------------------------------------------------------
|
|
||||||
class MyMinException extends Exception {}
|
|
@@ -11,6 +11,8 @@ function test_Minify_CSS_UriRewriter()
|
|||||||
$in = file_get_contents($thisDir . '/_test_files/css_uriRewriter/in.css');
|
$in = file_get_contents($thisDir . '/_test_files/css_uriRewriter/in.css');
|
||||||
$expected = file_get_contents($thisDir . '/_test_files/css_uriRewriter/exp.css');
|
$expected = file_get_contents($thisDir . '/_test_files/css_uriRewriter/exp.css');
|
||||||
|
|
||||||
|
Minify_CSS_UriRewriter::$debugText = '';
|
||||||
|
|
||||||
$actual = Minify_CSS_UriRewriter::rewrite(
|
$actual = Minify_CSS_UriRewriter::rewrite(
|
||||||
$in
|
$in
|
||||||
,$thisDir . '/_test_files/css_uriRewriter' // currentDir
|
,$thisDir . '/_test_files/css_uriRewriter' // currentDir
|
||||||
@@ -24,6 +26,10 @@ function test_Minify_CSS_UriRewriter()
|
|||||||
if (!$passed) {
|
if (!$passed) {
|
||||||
echo "---Expected: " .strlen($expected). " bytes\n\n{$expected}\n\n\n";
|
echo "---Expected: " .strlen($expected). " bytes\n\n{$expected}\n\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// show debugging only when test run directly
|
||||||
|
echo "--- Minify_CSS_UriRewriter::\$debugText\n\n"
|
||||||
|
, Minify_CSS_UriRewriter::$debugText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user