Index: trunk/phase3/tests/phpunit/includes/libs/JavaScriptDistillerTest.php |
— | — | @@ -1,18 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * @group Distiller |
5 | | - */ |
6 | | -class JavaScriptDistillerTest extends PHPUnit_Framework_TestCase { |
7 | | - public function testDistiller() { |
8 | | - $in = self::read( 'distiller-in.js' ); |
9 | | - $out = self::read( 'distiller-out.js' ); |
10 | | - $outFull = self::read( 'distiller-out-full.js' ); |
11 | | - $this->assertEquals( $out, JavaScriptDistiller::stripWhiteSpace( $in ) ); |
12 | | - $this->assertEquals( $outFull, JavaScriptDistiller::stripWhiteSpace( $in, true ) ); |
13 | | - } |
14 | | - |
15 | | - private static function read( $file ) { |
16 | | - $text = file_get_contents( dirname( __FILE__ ) . "/$file" ); |
17 | | - return str_replace( "\r\n", "\n", $text ); |
18 | | - } |
19 | | -} |
\ No newline at end of file |
Index: trunk/phase3/tests/phpunit/includes/libs/distiller-in.js |
— | — | @@ -1,15 +0,0 @@ |
2 | | -/* this is a comment */ |
3 | | -/* a multi- |
4 | | - line comment */ |
5 | | -/* a /* weird comment */ |
6 | | -// one-line comment |
7 | | -var string = /* comment */'/* comment in string */'; |
8 | | - |
9 | | -move_to_the_same_line() |
10 | | - |
11 | | - dont_move(); |
12 | | - |
13 | | -if ( / a + bfoo.* /i.test( bar ) && ( a / b ) * c + d - e) { /* blah */ |
14 | | - statement(); |
15 | | - statement() |
16 | | -} |
\ No newline at end of file |
Index: trunk/phase3/tests/phpunit/includes/libs/distiller-out-full.js |
— | — | @@ -1,7 +0,0 @@ |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | -var string='/* comment in string */';move_to_the_same_line() |
7 | | -dont_move();if(/ a + bfoo.* /i.test(bar)&&(a/ b ) * c + d - e){ |
8 | | -statement();statement()} |
\ No newline at end of file |
Index: trunk/phase3/tests/phpunit/includes/libs/distiller-out.js |
— | — | @@ -1,11 +0,0 @@ |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | -var string='/* comment in string */'; |
7 | | -move_to_the_same_line() |
8 | | -dont_move(); |
9 | | -if(/ a + bfoo.* /i.test(bar)&&(a/ b ) * c + d - e) { /*blah*/ |
10 | | -statement(); |
11 | | -statement() |
12 | | -} |
\ No newline at end of file |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -494,7 +494,6 @@ |
495 | 495 | 'CSSJanus' => 'includes/libs/CSSJanus.php', |
496 | 496 | 'CSSMin' => 'includes/libs/CSSMin.php', |
497 | 497 | 'IEContentAnalyzer' => 'includes/libs/IEContentAnalyzer.php', |
498 | | - 'JavaScriptDistiller' => 'includes/libs/JavaScriptDistiller.php', |
499 | 498 | 'JavaScriptMinifier' => 'includes/libs/JavaScriptMinifier.php', |
500 | 499 | 'Spyc' => 'includes/libs/spyc.php', |
501 | 500 | |
Index: trunk/phase3/includes/libs/JavaScriptDistiller.php |
— | — | @@ -1,337 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * JavaScript Distiller |
5 | | - * |
6 | | - * Author: Dean Edwards, Nicholas Martin, Trevor Parscal |
7 | | - * License: LGPL |
8 | | - */ |
9 | | -class JavaScriptDistiller { |
10 | | - |
11 | | - /* Static Methods */ |
12 | | - |
13 | | - /** |
14 | | - * Removes most of the white-space from JavaScript code. |
15 | | - * |
16 | | - * This code came from the first pass of Dean Edwards' JavaScript Packer. Compared to using |
17 | | - * JSMin::minify, this produces < 1% larger output (after gzip) in approx. 25% of the time. |
18 | | - * |
19 | | - * @param $script String: JavaScript code to minify |
20 | | - * @param $stripVerticalSpace Boolean: Try to remove as much vertical whitespace as possible |
21 | | - */ |
22 | | - public static function stripWhiteSpace( $script, $stripVerticalSpace = false ) { |
23 | | - // Try to avoid segfaulting |
24 | | - // I saw segfaults with a limit of 10000, 1000 seems to work |
25 | | - $oldLimit = ini_get( 'pcre.recursion_limit' ); |
26 | | - if ( intval( $oldLimit ) > 1000 ) { |
27 | | - ini_set( 'pcre.recursion_limit', '1000' ); |
28 | | - } |
29 | | - |
30 | | - $script = self::stripHorizontalSpace( $script ); |
31 | | - // If requested, make some vertical whitespace collapsing as well |
32 | | - if ( $stripVerticalSpace ) { |
33 | | - $script = self::stripVerticalSpace( $script ); |
34 | | - } |
35 | | - // Done |
36 | | - ini_set( 'pcre.recursion_limit', $oldLimit ); |
37 | | - return $script; |
38 | | - } |
39 | | - |
40 | | - public static function stripHorizontalSpace( $script ) { |
41 | | - $parser = self::createParser(); |
42 | | - // Collapse horizontal whitespaces between variable names into a single space |
43 | | - $parser->add( '(\b|\$) [ \t]+ (\b|\$)', '$2 $3' ); |
44 | | - // Collapse horizontal whitespaces between unary operators into a single space |
45 | | - $parser->add( '([+\-]) [ \t]+ ([+\-])', '$2 $3' ); |
46 | | - // Remove all remaining un-protected horizontal whitespace |
47 | | - $parser->add( '[ \t]+'); |
48 | | - // Collapse multiple vertical whitespaces with some horizontal spaces between them |
49 | | - $parser->add( '[\r\n]+ [ \t]* [\r\n]+', "\n" ); |
50 | | - // Execute and return |
51 | | - return $parser->exec($script); |
52 | | - } |
53 | | - |
54 | | - public static function stripVerticalSpace( $script ) { |
55 | | - $parser = self::createParser(); |
56 | | - // Collapse whitespaces between and after a ){ pair (function definitions) |
57 | | - $parser->add( '\) \s+ \{ \s+', '){' ); |
58 | | - // Collapse whitespaces between and after a ({ pair (JSON argument) |
59 | | - $parser->add( '\( \s+ \{ \s+', '({' ); |
60 | | - // Collapse whitespaces between a parenthesis and a period (call chaining) |
61 | | - $parser->add( '\) \s+ \.', ').'); |
62 | | - // Collapse vertical whitespaces which come directly after a semicolon or a comma |
63 | | - $parser->add( '( [;,] ) \s+', '$2' ); |
64 | | - // Collapse whitespaces between multiple parenthesis/brackets of similar direction |
65 | | - $parser->add( '( [\)\}] ) \s+ ( [\)\}] )', '$2$3' ); |
66 | | - $parser->add( '( [\(\{] ) \s+ ( [\(\{] )', '$2$3' ); |
67 | | - return $parser->exec( $script ); |
68 | | - } |
69 | | - |
70 | | - /* |
71 | | - * Creates an instance of ParseMaster and protects sensitive JavaScript regions. |
72 | | - * |
73 | | - * This parser is based on regular expressions, which all get or'd together, so rules take |
74 | | - * precedence in the order they are added. We can use it to minify by armoring certain regions |
75 | | - * by matching them and replacing them with the full match, leaving the remaining regions around |
76 | | - * for further matching and replacing. When creating rules please note that because ParseMaster |
77 | | - * "or"s all of the rules together in a single pattern, encapsulating them in parenthesis, $1 |
78 | | - * represents the whole match for a given rule, and $2 is the first submatch. |
79 | | - */ |
80 | | - private static function createParser() { |
81 | | - $parser = new ParseMaster(); |
82 | | - // There is a bug in ParseMaster that causes a backslash at the end of a line to be changed |
83 | | - // to \s if we use a backslash as the escape character. We work around this by using an |
84 | | - // obscure escape character that we hope will never appear at the end of a line. |
85 | | - $parser->escapeChar = chr( 1 ); |
86 | | - |
87 | | - // C-style comment: use non-greedy repetition to find the end |
88 | | - $parser->add( '\/ \* .*? \* \/' ); |
89 | | - |
90 | | - // Preserve the newline after a C++-style comment -- bug 27046 |
91 | | - $parser->add( '\/ \/ [^\r\n]* ( [\r\n] )', '$2' ); |
92 | | - |
93 | | - // Protect strings. The original code had [^\'\\v] here, but that didn't armor multiline |
94 | | - // strings correctly. This also armors multiline strings that don't have backslashes at the |
95 | | - // end of the line (these are invalid), but that's fine because we're just armoring here. |
96 | | - |
97 | | - // Single quotes |
98 | | - $parser->add( |
99 | | - '\'' . // start quote |
100 | | - '[^\'\\\\]*' . // a run of non-special characters |
101 | | - '(?:' . |
102 | | - '\\\\ .' . // a backslash followed by any character |
103 | | - '[^\'\\\\]*' . // a run of non-special characters |
104 | | - ')*' . // any number of the above |
105 | | - '\'', // end quote |
106 | | - '$1' ); |
107 | | - |
108 | | - // Double quotes: same as above |
109 | | - $parser->add( '" [^"\\\\]* (?: \\\\ . [^"\\\\]* )* "', '$1' ); |
110 | | - |
111 | | - // Protect regular expressions |
112 | | - $parser->add( |
113 | | - '(?<= [ \t] | [^\w\$\/\'"*)\?:] )' . // assert that whitespace or punctuation precedes |
114 | | - '\/' . // start slash |
115 | | - '[^\r\n\*]' . // not a comment-start or line ending |
116 | | - '[^\/\r\n\\\\]*' . // a sequence of non-special characters |
117 | | - '(?:' . |
118 | | - '\\\\ .' . // a backslash followed by any character |
119 | | - '[^\/\r\n\\\\]*' . // a sequence of non-special characters |
120 | | - ')*' . // any number of the above |
121 | | - '\/[ig]*' , // pattern end, optional modifier |
122 | | - '$1' ); |
123 | | - return $parser; |
124 | | - } |
125 | | -} |
126 | | - |
127 | | -/** |
128 | | - * ParseMaster, version 1.0.2 (2005-08-19) Copyright 2005, Dean Edwards |
129 | | - * A multi-pattern parser. |
130 | | - * License: http://creativecommons.org/licenses/LGPL/2.1/ |
131 | | - * |
132 | | - * This is the PHP version of the ParseMaster component of Dean Edwards' (http://dean.edwards.name/) |
133 | | - * Packer, which was originally written in JavaScript. It was ported to PHP by Nicolas Martin. |
134 | | - * |
135 | | - * Original Source: http://joliclic.free.fr/php/javascript-packer/en/ |
136 | | - * |
137 | | - * Changes should be pushed back upstream. |
138 | | - */ |
139 | | -class ParseMaster { |
140 | | - public $ignoreCase = false; |
141 | | - public $escapeChar = ''; |
142 | | - |
143 | | - // constants |
144 | | - const EXPRESSION = 0; |
145 | | - const REPLACEMENT = 1; |
146 | | - const LENGTH = 2; |
147 | | - |
148 | | - // used to determine nesting levels |
149 | | - private $GROUPS = '/\( (?! \? ) /x';//g |
150 | | - private $SUB_REPLACE = '/\$\d/'; |
151 | | - private $INDEXED = '/^\$\d+$/'; |
152 | | - private $ESCAPE = '/\\\./';//g |
153 | | - private $QUOTE = '/\'/'; |
154 | | - private $DELETED = '/\x01[^\x01]*\x01/';//g |
155 | | - |
156 | | - public function add($expression, $replacement = '') { |
157 | | - // count the number of sub-expressions |
158 | | - // - add one because each pattern is itself a sub-expression |
159 | | - $length = 1 + preg_match_all($this->GROUPS, $this->_internalEscape((string)$expression), $out); |
160 | | - |
161 | | - // treat only strings $replacement |
162 | | - if (is_string($replacement)) { |
163 | | - // does the pattern deal with sub-expressions? |
164 | | - if (preg_match($this->SUB_REPLACE, $replacement)) { |
165 | | - // a simple lookup? (e.g. "$2") |
166 | | - if (preg_match($this->INDEXED, $replacement)) { |
167 | | - // store the index (used for fast retrieval of matched strings) |
168 | | - $replacement = (int)(substr($replacement, 1)) - 1; |
169 | | - } else { // a complicated lookup (e.g. "Hello $2 $1") |
170 | | - // build a function to do the lookup |
171 | | - $quote = preg_match($this->QUOTE, $this->_internalEscape($replacement)) |
172 | | - ? '"' : "'"; |
173 | | - $replacement = array( |
174 | | - 'fn' => '_backReferences', |
175 | | - 'data' => array( |
176 | | - 'replacement' => $replacement, |
177 | | - 'length' => $length, |
178 | | - 'quote' => $quote |
179 | | - ) |
180 | | - ); |
181 | | - } |
182 | | - } |
183 | | - } |
184 | | - // pass the modified arguments |
185 | | - if (!empty($expression)) $this->_add($expression, $replacement, $length); |
186 | | - else $this->_add('/^$/', $replacement, $length); |
187 | | - } |
188 | | - |
189 | | - public function exec($string) { |
190 | | - // execute the global replacement |
191 | | - $this->_escaped = array(); |
192 | | - |
193 | | - // simulate the _patterns.toSTring of Dean |
194 | | - $regexp = '/'; |
195 | | - foreach ($this->_patterns as $reg) { |
196 | | - $regexp .= '(' . $reg[self::EXPRESSION] . ")|\n"; |
197 | | - } |
198 | | - $regexp = substr($regexp, 0, -2) . '/Sxs'; |
199 | | - $regexp .= ($this->ignoreCase) ? 'i' : ''; |
200 | | - |
201 | | - $string = $this->_escape($string, $this->escapeChar); |
202 | | - $string = preg_replace_callback( |
203 | | - $regexp, |
204 | | - array( |
205 | | - &$this, |
206 | | - '_replacement' |
207 | | - ), |
208 | | - $string |
209 | | - ); |
210 | | - $string = $this->_unescape($string, $this->escapeChar); |
211 | | - |
212 | | - return preg_replace($this->DELETED, '', $string); |
213 | | - } |
214 | | - |
215 | | - public function reset() { |
216 | | - // clear the patterns collection so that this object may be re-used |
217 | | - $this->_patterns = array(); |
218 | | - } |
219 | | - |
220 | | - // private |
221 | | - private $_escaped = array(); // escaped characters |
222 | | - private $_patterns = array(); // patterns stored by index |
223 | | - |
224 | | - // create and add a new pattern to the patterns collection |
225 | | - private function _add() { |
226 | | - $arguments = func_get_args(); |
227 | | - $this->_patterns[] = $arguments; |
228 | | - } |
229 | | - |
230 | | - // this is the global replace function (it's quite complicated) |
231 | | - private function _replacement($arguments) { |
232 | | - if (empty($arguments)) return ''; |
233 | | - |
234 | | - $i = 1; $j = 0; |
235 | | - // loop through the patterns |
236 | | - while (isset($this->_patterns[$j])) { |
237 | | - $pattern = $this->_patterns[$j++]; |
238 | | - // do we have a result? |
239 | | - if (isset($arguments[$i]) && ($arguments[$i] != '')) { |
240 | | - $replacement = $pattern[self::REPLACEMENT]; |
241 | | - |
242 | | - if (is_array($replacement) && isset($replacement['fn'])) { |
243 | | - |
244 | | - if (isset($replacement['data'])) $this->buffer = $replacement['data']; |
245 | | - return call_user_func(array(&$this, $replacement['fn']), $arguments, $i); |
246 | | - |
247 | | - } elseif (is_int($replacement)) { |
248 | | - return $arguments[$replacement + $i]; |
249 | | - |
250 | | - } |
251 | | - $delete = ($this->escapeChar == '' || |
252 | | - strpos($arguments[$i], $this->escapeChar) === false) |
253 | | - ? '' : "\x01" . $arguments[$i] . "\x01"; |
254 | | - return $delete . $replacement; |
255 | | - |
256 | | - // skip over references to sub-expressions |
257 | | - } else { |
258 | | - $i += $pattern[self::LENGTH]; |
259 | | - } |
260 | | - } |
261 | | - } |
262 | | - |
263 | | - private function _backReferences($match, $offset) { |
264 | | - $replacement = $this->buffer['replacement']; |
265 | | - //$quote = $this->buffer['quote']; |
266 | | - $i = $this->buffer['length']; |
267 | | - while ($i) { |
268 | | - $replacement = str_replace('$'.$i--, $match[$offset + $i], $replacement); |
269 | | - } |
270 | | - return $replacement; |
271 | | - } |
272 | | - |
273 | | - private function _replace_name($match, $offset){ |
274 | | - $length = strlen($match[$offset + 2]); |
275 | | - $start = $length - max($length - strlen($match[$offset + 3]), 0); |
276 | | - return substr($match[$offset + 1], $start, $length) . $match[$offset + 4]; |
277 | | - } |
278 | | - |
279 | | - private function _replace_encoded($match, $offset) { |
280 | | - return $this->buffer[$match[$offset]]; |
281 | | - } |
282 | | - |
283 | | - |
284 | | - // php : we cannot pass additional data to preg_replace_callback, |
285 | | - // and we cannot use &$this in create_function, so let's go to lower level |
286 | | - private $buffer; |
287 | | - |
288 | | - // encode escaped characters |
289 | | - private function _escape($string, $escapeChar) { |
290 | | - if ($escapeChar) { |
291 | | - $this->buffer = $escapeChar; |
292 | | - return preg_replace_callback( |
293 | | - '/\\' . $escapeChar . '(.)' .'/', |
294 | | - array(&$this, '_escapeBis'), |
295 | | - $string |
296 | | - ); |
297 | | - |
298 | | - } else { |
299 | | - return $string; |
300 | | - } |
301 | | - } |
302 | | - private function _escapeBis($match) { |
303 | | - $this->_escaped[] = $match[1]; |
304 | | - return $this->buffer; |
305 | | - } |
306 | | - |
307 | | - // decode escaped characters |
308 | | - private function _unescape($string, $escapeChar) { |
309 | | - if ($escapeChar) { |
310 | | - $regexp = '/'.'\\'.$escapeChar.'/'; |
311 | | - $this->buffer = array('escapeChar'=> $escapeChar, 'i' => 0); |
312 | | - return preg_replace_callback |
313 | | - ( |
314 | | - $regexp, |
315 | | - array(&$this, '_unescapeBis'), |
316 | | - $string |
317 | | - ); |
318 | | - |
319 | | - } else { |
320 | | - return $string; |
321 | | - } |
322 | | - } |
323 | | - private function _unescapeBis() { |
324 | | - if (isset($this->_escaped[$this->buffer['i']]) |
325 | | - && $this->_escaped[$this->buffer['i']] != '') |
326 | | - { |
327 | | - $temp = $this->_escaped[$this->buffer['i']]; |
328 | | - } else { |
329 | | - $temp = ''; |
330 | | - } |
331 | | - $this->buffer['i']++; |
332 | | - return $this->buffer['escapeChar'] . $temp; |
333 | | - } |
334 | | - |
335 | | - private function _internalEscape($string) { |
336 | | - return preg_replace($this->ESCAPE, '', $string); |
337 | | - } |
338 | | -} |