<?php
/**
* Cruncher class,
* single method class to crunch code [default: JavaScript (ActionScript or ECMAScript) source].
* With a dedicated associative array rules and one regexp should crunch other sources too.
* ____________________________________
* @example
* $cruncher = new Crunch;
* echo $cruncher->crunch($source, 3);
* --------------------------------------------------------------
* @Compatibility PHP >= 4 and 5 (E_ALL | E_STRICT) error free
* @Dependencies SourceMap.class.php
* @Author Andrea Giammarchi
* @Site http://www.devpro.it/
* @Date 2007/01/15
* @LastMod 2007/02/11 [supports JavaScript conditional comments]
* @Version 1.0
*/
require_once 'SourceMap.class.php';
class Cruncher {
/**
* code rules, by default these are JavaScript (ActionScript or ECMAScript) dedicated
* You could change them setting directly this variable
* (i.e. $cruncher->rules = array(....))
*/
/** public */ var $rules = array(
array('name'=>'doublequote', 'start'=>'"', 'end'=>'"', 'noslash'=>true),
array('name'=>'singlequote', 'start'=>"'", 'end'=>"'", 'noslash'=>true),
array('name'=>'conditionalcomment', 'start'=>'/*@', 'end'=>'@*/'),
array('name'=>'singlelinecomment', 'start'=>'//', 'end'=>array("\n", "\r")),
array('name'=>'multilinecomment', 'start'=>'/*', 'end'=>'*/'),
array('name'=>'regexp', 'start'=>'/', 'end'=>'/', 'match'=>'#^/[^\x0a\x0d]+/$#', 'noslash'=>true)
);
/**
* regexp to crunch code, by default these are JavaScript (ActionScript or ECMAScript) dedicated
* These regexp should be compatible with CSS sources too
*/
/** public */ var $re = array(
// find one or more space and return them as value \\1
'space' => '/([[:space:]]+)/',
// trim common JavaScript operators and return them as value \\1
'operator' => '/[[:space:]]?([\.|\(|\)|;|\:|=|\{|\}|\,|\-|\+|\?|>|<|\*|\/|^|\||\!|&|\[|\]|%]+)[[:space:]]?/'
);
// "private" instance of SourceMap
/** private */ var $__sourceMap = null;
/**
* public constructor,
* init a new cruncher setting private __courceMap variable.
*
* new Cruncher(Void)
*/
/** public /**/ function Cruncher(){
$this->__sourceMap = new SourceMap;
}
/**
* public method,
* parse a source code and return them crunched
*
* self->crunch(source:String [, level:UShortRange(1,3)]):String
*
* @param String the source to parse
* @param UShort compression level from 1 to 3, default: 1
* level 1 - removes comments and trim spaces of each block of code
* level 2 - removes comments and duplicated spaces(should be regressive)
* level 3 - removes comments and spaces (can be regressive)
* @return String crunched string
*/
/** public /**/ function crunch($str, $level = 1){
$conditional = create_function('$m', '$tmp=new Cruncher;return $m[1].$tmp->crunch($m[2], '.$level.').$m[3];');
$evalspace = $this->re['space'].'e';
$parsed = array();
$map = $this->__sourceMap->getMap($str, $this->rules);
--$level;
for($i = 0, $j = 0, $k = count($map), $name = ''; $j < $k; $j++) {
$name = &$map[$j]['name'];
switch($name) {
case 'singlelinecomment':
case 'multilinecomment':
if($level < 2 && $i > 0 && !preg_match("/(\r|\n)$/", $parsed[$i-1]))
$parsed[$i++] = "\r\n";
break;
case 'conditionalcomment':
$parsed[$i++] = preg_replace_callback(
'/^(\/\*@)([^\a]*?)(@\*\/)$/',
$conditional,
substr($str, $map[$j]['start'], $map[$j]['end'] - $map[$j]['start'])
);
break;
default:
$parsed[$i] = substr($str, $map[$j]['start'], $map[$j]['end'] - $map[$j]['start']);
if($name === 'code') {
switch($level) {
case 0:
$parsed[$i] = trim($parsed[$i]);
break;
case 1:
$parsed[$i] = $this->__trimAndReplace($evalspace, 'substr("\\1", 0, 1)', $parsed[$i]);
break;
case 2:
$parsed[$i] = $this->__trimOperatorsAndReplace($parsed[$i]);
break;
}
}
++$i;
break;
}
}
return implode('', $parsed);
}
/**
* "private" method,
* replace using a regexp and return trimmed string
*
* (self)->__trimAndReplace(re:String, place:String, *source:String):String
*
* @param String regexp to use
* @param String replacement for used regexp
* @param String string to change
* @param String trim and replaced string
*/
/** private /**/ function __trimAndReplace($re, $place, &$str){
return trim(preg_replace($re, $place, $str));
}
/**
* "private" method,
* replace using a regexp and return trimmed string without spaces between operators (defined in self->re['operator'] string)
*
* (self)->__trimOperatorsAndReplace(*source:String):String
*
* @param String string to change
* @param String trim and replaced string without spaces between operators
*/
/** private /**/ function __trimOperatorsAndReplace(&$str){
return preg_replace($this->re['operator'], '\\1', $this->__trimAndReplace($this->re['space'], ' ', $str));
}
}
?>
|