Index: trunk/phase3/includes/libs/ParseMaster.php |
— | — | @@ -1,214 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * ParseMaster, version 1.0.2 (2005-08-19) Copyright 2005, Dean Edwards |
5 | | - * A multi-pattern parser. |
6 | | - * License: http://creativecommons.org/licenses/LGPL/2.1/ |
7 | | - * |
8 | | - * This is the PHP version of the ParseMaster component of Dean Edwards' (http://dean.edwards.name/) |
9 | | - * Packer, which was originally written in JavaScript. It was ported to PHP by Nicolas Martin. |
10 | | - * |
11 | | - * Original Source: http://joliclic.free.fr/php/javascript-packer/en/ |
12 | | - * |
13 | | - * Changes should be pushed back upstream. |
14 | | - */ |
15 | | -class ParseMaster { |
16 | | - public $ignoreCase = false; |
17 | | - public $escapeChar = ''; |
18 | | - |
19 | | - // constants |
20 | | - const EXPRESSION = 0; |
21 | | - const REPLACEMENT = 1; |
22 | | - const LENGTH = 2; |
23 | | - |
24 | | - // used to determine nesting levels |
25 | | - private $GROUPS = '/\\(/';//g |
26 | | - private $SUB_REPLACE = '/\\$\\d/'; |
27 | | - private $INDEXED = '/^\\$\\d+$/'; |
28 | | - private $TRIM = '/([\'"])\\1\\.(.*)\\.\\1\\1$/'; |
29 | | - private $ESCAPE = '/\\\./';//g |
30 | | - private $QUOTE = '/\'/'; |
31 | | - private $DELETED = '/\\x01[^\\x01]*\\x01/';//g |
32 | | - |
33 | | - public function add($expression, $replacement = '') { |
34 | | - // count the number of sub-expressions |
35 | | - // - add one because each pattern is itself a sub-expression |
36 | | - $length = 1 + preg_match_all($this->GROUPS, $this->_internalEscape((string)$expression), $out); |
37 | | - |
38 | | - // treat only strings $replacement |
39 | | - if (is_string($replacement)) { |
40 | | - // does the pattern deal with sub-expressions? |
41 | | - if (preg_match($this->SUB_REPLACE, $replacement)) { |
42 | | - // a simple lookup? (e.g. "$2") |
43 | | - if (preg_match($this->INDEXED, $replacement)) { |
44 | | - // store the index (used for fast retrieval of matched strings) |
45 | | - $replacement = (int)(substr($replacement, 1)) - 1; |
46 | | - } else { // a complicated lookup (e.g. "Hello $2 $1") |
47 | | - // build a function to do the lookup |
48 | | - $quote = preg_match($this->QUOTE, $this->_internalEscape($replacement)) |
49 | | - ? '"' : "'"; |
50 | | - $replacement = array( |
51 | | - 'fn' => '_backReferences', |
52 | | - 'data' => array( |
53 | | - 'replacement' => $replacement, |
54 | | - 'length' => $length, |
55 | | - 'quote' => $quote |
56 | | - ) |
57 | | - ); |
58 | | - } |
59 | | - } |
60 | | - } |
61 | | - // pass the modified arguments |
62 | | - if (!empty($expression)) $this->_add($expression, $replacement, $length); |
63 | | - else $this->_add('/^$/', $replacement, $length); |
64 | | - } |
65 | | - |
66 | | - public function exec($string) { |
67 | | - // execute the global replacement |
68 | | - $this->_escaped = array(); |
69 | | - |
70 | | - // simulate the _patterns.toSTring of Dean |
71 | | - $regexp = '/'; |
72 | | - foreach ($this->_patterns as $reg) { |
73 | | - $regexp .= '(' . substr($reg[self::EXPRESSION], 1, -1) . ')|'; |
74 | | - } |
75 | | - $regexp = substr($regexp, 0, -1) . '/'; |
76 | | - $regexp .= ($this->ignoreCase) ? 'i' : ''; |
77 | | - |
78 | | - $string = $this->_escape($string, $this->escapeChar); |
79 | | - $string = preg_replace_callback( |
80 | | - $regexp, |
81 | | - array( |
82 | | - &$this, |
83 | | - '_replacement' |
84 | | - ), |
85 | | - $string |
86 | | - ); |
87 | | - $string = $this->_unescape($string, $this->escapeChar); |
88 | | - |
89 | | - return preg_replace($this->DELETED, '', $string); |
90 | | - } |
91 | | - |
92 | | - public function reset() { |
93 | | - // clear the patterns collection so that this object may be re-used |
94 | | - $this->_patterns = array(); |
95 | | - } |
96 | | - |
97 | | - // private |
98 | | - private $_escaped = array(); // escaped characters |
99 | | - private $_patterns = array(); // patterns stored by index |
100 | | - |
101 | | - // create and add a new pattern to the patterns collection |
102 | | - private function _add() { |
103 | | - $arguments = func_get_args(); |
104 | | - $this->_patterns[] = $arguments; |
105 | | - } |
106 | | - |
107 | | - // this is the global replace function (it's quite complicated) |
108 | | - private function _replacement($arguments) { |
109 | | - if (empty($arguments)) return ''; |
110 | | - |
111 | | - $i = 1; $j = 0; |
112 | | - // loop through the patterns |
113 | | - while (isset($this->_patterns[$j])) { |
114 | | - $pattern = $this->_patterns[$j++]; |
115 | | - // do we have a result? |
116 | | - if (isset($arguments[$i]) && ($arguments[$i] != '')) { |
117 | | - $replacement = $pattern[self::REPLACEMENT]; |
118 | | - |
119 | | - if (is_array($replacement) && isset($replacement['fn'])) { |
120 | | - |
121 | | - if (isset($replacement['data'])) $this->buffer = $replacement['data']; |
122 | | - return call_user_func(array(&$this, $replacement['fn']), $arguments, $i); |
123 | | - |
124 | | - } elseif (is_int($replacement)) { |
125 | | - return $arguments[$replacement + $i]; |
126 | | - |
127 | | - } |
128 | | - $delete = ($this->escapeChar == '' || |
129 | | - strpos($arguments[$i], $this->escapeChar) === false) |
130 | | - ? '' : "\x01" . $arguments[$i] . "\x01"; |
131 | | - return $delete . $replacement; |
132 | | - |
133 | | - // skip over references to sub-expressions |
134 | | - } else { |
135 | | - $i += $pattern[self::LENGTH]; |
136 | | - } |
137 | | - } |
138 | | - } |
139 | | - |
140 | | - private function _backReferences($match, $offset) { |
141 | | - $replacement = $this->buffer['replacement']; |
142 | | - $quote = $this->buffer['quote']; |
143 | | - $i = $this->buffer['length']; |
144 | | - while ($i) { |
145 | | - $replacement = str_replace('$'.$i--, $match[$offset + $i], $replacement); |
146 | | - } |
147 | | - return $replacement; |
148 | | - } |
149 | | - |
150 | | - private function _replace_name($match, $offset){ |
151 | | - $length = strlen($match[$offset + 2]); |
152 | | - $start = $length - max($length - strlen($match[$offset + 3]), 0); |
153 | | - return substr($match[$offset + 1], $start, $length) . $match[$offset + 4]; |
154 | | - } |
155 | | - |
156 | | - private function _replace_encoded($match, $offset) { |
157 | | - return $this->buffer[$match[$offset]]; |
158 | | - } |
159 | | - |
160 | | - |
161 | | - // php : we cannot pass additional data to preg_replace_callback, |
162 | | - // and we cannot use &$this in create_function, so let's go to lower level |
163 | | - private $buffer; |
164 | | - |
165 | | - // encode escaped characters |
166 | | - private function _escape($string, $escapeChar) { |
167 | | - if ($escapeChar) { |
168 | | - $this->buffer = $escapeChar; |
169 | | - return preg_replace_callback( |
170 | | - '/\\' . $escapeChar . '(.)' .'/', |
171 | | - array(&$this, '_escapeBis'), |
172 | | - $string |
173 | | - ); |
174 | | - |
175 | | - } else { |
176 | | - return $string; |
177 | | - } |
178 | | - } |
179 | | - private function _escapeBis($match) { |
180 | | - $this->_escaped[] = $match[1]; |
181 | | - return $this->buffer; |
182 | | - } |
183 | | - |
184 | | - // decode escaped characters |
185 | | - private function _unescape($string, $escapeChar) { |
186 | | - if ($escapeChar) { |
187 | | - $regexp = '/'.'\\'.$escapeChar.'/'; |
188 | | - $this->buffer = array('escapeChar'=> $escapeChar, 'i' => 0); |
189 | | - return preg_replace_callback |
190 | | - ( |
191 | | - $regexp, |
192 | | - array(&$this, '_unescapeBis'), |
193 | | - $string |
194 | | - ); |
195 | | - |
196 | | - } else { |
197 | | - return $string; |
198 | | - } |
199 | | - } |
200 | | - private function _unescapeBis() { |
201 | | - if (isset($this->_escaped[$this->buffer['i']]) |
202 | | - && $this->_escaped[$this->buffer['i']] != '') |
203 | | - { |
204 | | - $temp = $this->_escaped[$this->buffer['i']]; |
205 | | - } else { |
206 | | - $temp = ''; |
207 | | - } |
208 | | - $this->buffer['i']++; |
209 | | - return $this->buffer['escapeChar'] . $temp; |
210 | | - } |
211 | | - |
212 | | - private function _internalEscape($string) { |
213 | | - return preg_replace($this->ESCAPE, '', $string); |
214 | | - } |
215 | | -} |
Index: trunk/phase3/includes/libs/JavaScriptDistiller.php |
— | — | @@ -16,12 +16,69 @@ |
17 | 17 | * JSMin::minify, this produces < 1% larger output (after gzip) in approx. 25% of the time. |
18 | 18 | * |
19 | 19 | * @param $script String: JavaScript code to minify |
| 20 | + * @param $stripVerticalSpace Boolean: Try to remove as much vertical whitespace as possible |
20 | 21 | */ |
21 | | - public static function stripWhiteSpace( $script, $collapseVertical = false ) { |
22 | | - // This parser is based on regular expressions, which all get or'd together, so rules take |
23 | | - // precedence in the order they are added. We can use it to minify by armoring certain |
24 | | - // regions by matching them and replacing them with the full match, leaving the remaining |
25 | | - // regions around for further matching and replacing. |
| 22 | + public static function stripWhiteSpace( $script, $stripVerticalSpace = false ) { |
| 23 | + $script = self::stripComments( $script ); |
| 24 | + $script = self::stripHorizontalSpace( $script ); |
| 25 | + // If requested, make some vertical whitespace collapsing as well |
| 26 | + if ( $collapseVertical ) { |
| 27 | + $script = self::stripVerticalSpace( $script ); |
| 28 | + } |
| 29 | + // Done |
| 30 | + return $script; |
| 31 | + } |
| 32 | + |
| 33 | + private static function stripComments( $script ) { |
| 34 | + $parser = self::createParser(); |
| 35 | + // Remove comments |
| 36 | + $parser->add( '/\\/\\/[^\\r\\n]*[\\r\\n]/' ); |
| 37 | + $parser->add( '/\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\//' ); |
| 38 | + // Execute and return |
| 39 | + return $parser->exec( $script ); |
| 40 | + } |
| 41 | + |
| 42 | + private static function stripHorizontalSpace( $script ) { |
| 43 | + $parser = self::createParser(); |
| 44 | + // Collapse horizontal whitespaces between variable names into a single space |
| 45 | + $parser->add( '/(\\b|\\$)[ \\t]+(\\b|\\$)/', '$2 $3' ); |
| 46 | + // Collapse horizontal whitespaces between unary operators into a single space |
| 47 | + $parser->add( '/([+\\-])[ \\t]+([+\\-])/', '$2 $3' ); |
| 48 | + // Remove all remaining un-protected horizontal whitespace |
| 49 | + $parser->add( '/[ \\t]+/'); |
| 50 | + // Collapse multiple vertical whitespaces with some horizontal spaces between them |
| 51 | + $parser->add( '/[\\r\\n]+[ \\t]*[\\r\\n]+/', "\n" ); |
| 52 | + // Execute and return |
| 53 | + return $parser->exec($script); |
| 54 | + } |
| 55 | + |
| 56 | + private static function stripVerticalSpace( $script ) { |
| 57 | + $parser = self::createParser(); |
| 58 | + // Collapse whitespaces between and after a ){ pair (function definitions) |
| 59 | + $parser->add( '/\\)\\s+\\{\\s+/', '){' ); |
| 60 | + // Collapse whitespaces between and after a ({ pair (JSON argument) |
| 61 | + $parser->add( '/\\(\\s+\\{\\s+/', '({' ); |
| 62 | + // Collapse whitespaces between a parenthesis and a period (call chaining) |
| 63 | + $parser->add( '/\\)\\s+\\./', ').'); |
| 64 | + // Collapse vertical whitespaces which come directly after a semicolon or a comma |
| 65 | + $parser->add( '/([;,])\\s+/', '$2' ); |
| 66 | + // Collapse whitespaces between multiple parenthesis/brackets of similar direction |
| 67 | + $parser->add( '/([\\)\\}])\\s+([\\)\\}])/', '$2$3' ); |
| 68 | + $parser->add( '/([\\(\\{])\\s+([\\(\\{])/', '$2$3' ); |
| 69 | + return $parser->exec( $script ); |
| 70 | + } |
| 71 | + |
| 72 | + /* |
| 73 | + * Creates an instance of ParseMaster and protects sensitive JavaScript regions. |
| 74 | + * |
| 75 | + * This parser is based on regular expressions, which all get or'd together, so rules take |
| 76 | + * precedence in the order they are added. We can use it to minify by armoring certain regions |
| 77 | + * by matching them and replacing them with the full match, leaving the remaining regions around |
| 78 | + * for further matching and replacing. When creating rules please note that because ParseMaster |
| 79 | + * "or"s all of the rules together in a single pattern, encapsulating them in parenthesis, $1 |
| 80 | + * represents the whole match for a given rule, and $2 is the first submatch. |
| 81 | + */ |
| 82 | + private static function createParser() { |
26 | 83 | $parser = new ParseMaster(); |
27 | 84 | // There is a bug in ParseMaster that causes a backslash at the end of a line to be changed |
28 | 85 | // to \s if we use a backslash as the escape character. We work around this by using an |
— | — | @@ -30,46 +87,225 @@ |
31 | 88 | // Protect strings. The original code had [^\'\\v] here, but that didn't armor multiline |
32 | 89 | // strings correctly. This also armors multiline strings that don't have backslashes at the |
33 | 90 | // end of the line (these are invalid), but that's fine because we're just armoring here. |
34 | | - $parser->add('/\'[^\']*\'/', '$1' ); |
35 | | - $parser->add('/"[^"]*"/', '$1' ); |
36 | | - // Remove comments |
37 | | - $parser->add('/\\/\\/[^\v]*[\v]/', ' '); |
38 | | - $parser->add('/\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\//', ' '); |
| 91 | + $parser->add( '/\'[^\']*\'/', '$1' ); |
| 92 | + $parser->add( '/"[^"]*"/', '$1' ); |
39 | 93 | // Protect regular expressions |
40 | | - $parser->add('/\\h+(\\/[^\\/\\v\\*][^\\/\\v]*\\/g?i?)/', '$2'); // IGNORE |
41 | | - $parser->add('/[^\\w\\x24\\/\'"*)\\?:]\\/[^\\/\\v\\*][^\\/\\v]*\\/g?i?/', '$1'); |
42 | | - // Remove: ;;; doSomething(); |
43 | | - $parser->add('/;;;[^\\v]+[\\v]/'); |
44 | | - // Remove redundant semi-colons |
45 | | - $parser->add('/\\(;;\\)/', '$1'); // protect for (;;) loops |
46 | | - $parser->add('/;+\\h*([};])/', '$2'); |
47 | | - // Apply all rules defined up to this point |
48 | | - $script = $parser->exec($script); |
49 | | - // If requested, make some vertical whitespace collapsing as well |
50 | | - if ( $collapseVertical ) { |
51 | | - // Collapse whitespaces between and after a ){ pair (function definitions) |
52 | | - $parser->add('/\\)\\s+\\{\\s+/', '){'); |
53 | | - // Collapse whitespaces between and after a ({ pair (JSON argument) |
54 | | - $parser->add('/\\(\\s+\\{\\s+/', '({'); |
55 | | - // Collapse whitespaces between a parenthesis and a period (call chaining) |
56 | | - $parser->add('/\\)\\s+\\./', ').'); |
57 | | - // Collapse vertical whitespaces which come directly after a semicolon or a comma |
58 | | - $parser->add('/([;,])\\s+/', '$2'); |
59 | | - // Collapse whitespaces between multiple parenthesis/brackets of similar direction |
60 | | - $parser->add('/([\\)\\}])\\s+([\\)\\}])/', '$2$3'); |
61 | | - $parser->add('/([\\(\\{])\\s+([\\(\\{])/', '$2$3'); |
| 94 | + $parser->add( '/[ \\t]+(\\/[^\\/\\r\\n\\*][^\\/\\r\\n]*\\/g?i?)/', '$2' ); |
| 95 | + $parser->add( '/[^\\w\\$\\/\'"*)\\?:]\\/[^\\/\\r\\n\\*][^\\/\\r\\n]*\\/g?i?/', '$1' ); |
| 96 | + return $parser; |
| 97 | + } |
| 98 | +} |
| 99 | + |
| 100 | +/** |
| 101 | + * ParseMaster, version 1.0.2 (2005-08-19) Copyright 2005, Dean Edwards |
| 102 | + * A multi-pattern parser. |
| 103 | + * License: http://creativecommons.org/licenses/LGPL/2.1/ |
| 104 | + * |
| 105 | + * This is the PHP version of the ParseMaster component of Dean Edwards' (http://dean.edwards.name/) |
| 106 | + * Packer, which was originally written in JavaScript. It was ported to PHP by Nicolas Martin. |
| 107 | + * |
| 108 | + * Original Source: http://joliclic.free.fr/php/javascript-packer/en/ |
| 109 | + * |
| 110 | + * Changes should be pushed back upstream. |
| 111 | + */ |
| 112 | +class ParseMaster { |
| 113 | + public $ignoreCase = false; |
| 114 | + public $escapeChar = ''; |
| 115 | + |
| 116 | + // constants |
| 117 | + const EXPRESSION = 0; |
| 118 | + const REPLACEMENT = 1; |
| 119 | + const LENGTH = 2; |
| 120 | + |
| 121 | + // used to determine nesting levels |
| 122 | + private $GROUPS = '/\\(/';//g |
| 123 | + private $SUB_REPLACE = '/\\$\\d/'; |
| 124 | + private $INDEXED = '/^\\$\\d+$/'; |
| 125 | + private $TRIM = '/([\'"])\\1\\.(.*)\\.\\1\\1$/'; |
| 126 | + private $ESCAPE = '/\\\./';//g |
| 127 | + private $QUOTE = '/\'/'; |
| 128 | + private $DELETED = '/\\x01[^\\x01]*\\x01/';//g |
| 129 | + |
| 130 | + public function add($expression, $replacement = '') { |
| 131 | + // count the number of sub-expressions |
| 132 | + // - add one because each pattern is itself a sub-expression |
| 133 | + $length = 1 + preg_match_all($this->GROUPS, $this->_internalEscape((string)$expression), $out); |
| 134 | + |
| 135 | + // treat only strings $replacement |
| 136 | + if (is_string($replacement)) { |
| 137 | + // does the pattern deal with sub-expressions? |
| 138 | + if (preg_match($this->SUB_REPLACE, $replacement)) { |
| 139 | + // a simple lookup? (e.g. "$2") |
| 140 | + if (preg_match($this->INDEXED, $replacement)) { |
| 141 | + // store the index (used for fast retrieval of matched strings) |
| 142 | + $replacement = (int)(substr($replacement, 1)) - 1; |
| 143 | + } else { // a complicated lookup (e.g. "Hello $2 $1") |
| 144 | + // build a function to do the lookup |
| 145 | + $quote = preg_match($this->QUOTE, $this->_internalEscape($replacement)) |
| 146 | + ? '"' : "'"; |
| 147 | + $replacement = array( |
| 148 | + 'fn' => '_backReferences', |
| 149 | + 'data' => array( |
| 150 | + 'replacement' => $replacement, |
| 151 | + 'length' => $length, |
| 152 | + 'quote' => $quote |
| 153 | + ) |
| 154 | + ); |
| 155 | + } |
| 156 | + } |
62 | 157 | } |
63 | | - // Collapse horizontal whitespaces between variable names into a single space |
64 | | - $parser->add('/(\\b|\\x24)\\h+(\\b|\\x24)/', '$2 $3'); |
65 | | - // Collapse horizontal whitespaces between urinary operators into a single space |
66 | | - $parser->add('/([+\\-])\\h+([+\\-])/', '$2 $3'); |
67 | | - // Collapse all remaining un-protected horizontal whitespace |
68 | | - $parser->add('/\\h+/', ''); |
69 | | - // Collapse multiple vertical whitespaces with some horizontal spaces between them |
70 | | - $parser->add('/\\v+\\h*\\v*/', "\n"); |
| 158 | + // pass the modified arguments |
| 159 | + if (!empty($expression)) $this->_add($expression, $replacement, $length); |
| 160 | + else $this->_add('/^$/', $replacement, $length); |
| 161 | + } |
| 162 | + |
| 163 | + public function exec($string) { |
| 164 | + // execute the global replacement |
| 165 | + $this->_escaped = array(); |
71 | 166 | |
72 | | - // Done |
73 | | - return $parser->exec($script); |
| 167 | + // simulate the _patterns.toSTring of Dean |
| 168 | + $regexp = '/'; |
| 169 | + foreach ($this->_patterns as $reg) { |
| 170 | + $regexp .= '(' . substr($reg[self::EXPRESSION], 1, -1) . ')|'; |
| 171 | + } |
| 172 | + $regexp = substr($regexp, 0, -1) . '/'; |
| 173 | + $regexp .= ($this->ignoreCase) ? 'i' : ''; |
74 | 174 | |
| 175 | + $string = $this->_escape($string, $this->escapeChar); |
| 176 | + $string = preg_replace_callback( |
| 177 | + $regexp, |
| 178 | + array( |
| 179 | + &$this, |
| 180 | + '_replacement' |
| 181 | + ), |
| 182 | + $string |
| 183 | + ); |
| 184 | + $string = $this->_unescape($string, $this->escapeChar); |
| 185 | + |
| 186 | + return preg_replace($this->DELETED, '', $string); |
75 | 187 | } |
| 188 | + |
| 189 | + public function reset() { |
| 190 | + // clear the patterns collection so that this object may be re-used |
| 191 | + $this->_patterns = array(); |
| 192 | + } |
| 193 | + |
| 194 | + // private |
| 195 | + private $_escaped = array(); // escaped characters |
| 196 | + private $_patterns = array(); // patterns stored by index |
| 197 | + |
| 198 | + // create and add a new pattern to the patterns collection |
| 199 | + private function _add() { |
| 200 | + $arguments = func_get_args(); |
| 201 | + $this->_patterns[] = $arguments; |
| 202 | + } |
| 203 | + |
| 204 | + // this is the global replace function (it's quite complicated) |
| 205 | + private function _replacement($arguments) { |
| 206 | + if (empty($arguments)) return ''; |
| 207 | + |
| 208 | + $i = 1; $j = 0; |
| 209 | + // loop through the patterns |
| 210 | + while (isset($this->_patterns[$j])) { |
| 211 | + $pattern = $this->_patterns[$j++]; |
| 212 | + // do we have a result? |
| 213 | + if (isset($arguments[$i]) && ($arguments[$i] != '')) { |
| 214 | + $replacement = $pattern[self::REPLACEMENT]; |
| 215 | + |
| 216 | + if (is_array($replacement) && isset($replacement['fn'])) { |
| 217 | + |
| 218 | + if (isset($replacement['data'])) $this->buffer = $replacement['data']; |
| 219 | + return call_user_func(array(&$this, $replacement['fn']), $arguments, $i); |
| 220 | + |
| 221 | + } elseif (is_int($replacement)) { |
| 222 | + return $arguments[$replacement + $i]; |
| 223 | + |
| 224 | + } |
| 225 | + $delete = ($this->escapeChar == '' || |
| 226 | + strpos($arguments[$i], $this->escapeChar) === false) |
| 227 | + ? '' : "\x01" . $arguments[$i] . "\x01"; |
| 228 | + return $delete . $replacement; |
| 229 | + |
| 230 | + // skip over references to sub-expressions |
| 231 | + } else { |
| 232 | + $i += $pattern[self::LENGTH]; |
| 233 | + } |
| 234 | + } |
| 235 | + } |
| 236 | + |
| 237 | + private function _backReferences($match, $offset) { |
| 238 | + $replacement = $this->buffer['replacement']; |
| 239 | + $quote = $this->buffer['quote']; |
| 240 | + $i = $this->buffer['length']; |
| 241 | + while ($i) { |
| 242 | + $replacement = str_replace('$'.$i--, $match[$offset + $i], $replacement); |
| 243 | + } |
| 244 | + return $replacement; |
| 245 | + } |
| 246 | + |
| 247 | + private function _replace_name($match, $offset){ |
| 248 | + $length = strlen($match[$offset + 2]); |
| 249 | + $start = $length - max($length - strlen($match[$offset + 3]), 0); |
| 250 | + return substr($match[$offset + 1], $start, $length) . $match[$offset + 4]; |
| 251 | + } |
| 252 | + |
| 253 | + private function _replace_encoded($match, $offset) { |
| 254 | + return $this->buffer[$match[$offset]]; |
| 255 | + } |
| 256 | + |
| 257 | + |
| 258 | + // php : we cannot pass additional data to preg_replace_callback, |
| 259 | + // and we cannot use &$this in create_function, so let's go to lower level |
| 260 | + private $buffer; |
| 261 | + |
| 262 | + // encode escaped characters |
| 263 | + private function _escape($string, $escapeChar) { |
| 264 | + if ($escapeChar) { |
| 265 | + $this->buffer = $escapeChar; |
| 266 | + return preg_replace_callback( |
| 267 | + '/\\' . $escapeChar . '(.)' .'/', |
| 268 | + array(&$this, '_escapeBis'), |
| 269 | + $string |
| 270 | + ); |
| 271 | + |
| 272 | + } else { |
| 273 | + return $string; |
| 274 | + } |
| 275 | + } |
| 276 | + private function _escapeBis($match) { |
| 277 | + $this->_escaped[] = $match[1]; |
| 278 | + return $this->buffer; |
| 279 | + } |
| 280 | + |
| 281 | + // decode escaped characters |
| 282 | + private function _unescape($string, $escapeChar) { |
| 283 | + if ($escapeChar) { |
| 284 | + $regexp = '/'.'\\'.$escapeChar.'/'; |
| 285 | + $this->buffer = array('escapeChar'=> $escapeChar, 'i' => 0); |
| 286 | + return preg_replace_callback |
| 287 | + ( |
| 288 | + $regexp, |
| 289 | + array(&$this, '_unescapeBis'), |
| 290 | + $string |
| 291 | + ); |
| 292 | + |
| 293 | + } else { |
| 294 | + return $string; |
| 295 | + } |
| 296 | + } |
| 297 | + private function _unescapeBis() { |
| 298 | + if (isset($this->_escaped[$this->buffer['i']]) |
| 299 | + && $this->_escaped[$this->buffer['i']] != '') |
| 300 | + { |
| 301 | + $temp = $this->_escaped[$this->buffer['i']]; |
| 302 | + } else { |
| 303 | + $temp = ''; |
| 304 | + } |
| 305 | + $this->buffer['i']++; |
| 306 | + return $this->buffer['escapeChar'] . $temp; |
| 307 | + } |
| 308 | + |
| 309 | + private function _internalEscape($string) { |
| 310 | + return preg_replace($this->ESCAPE, '', $string); |
| 311 | + } |
76 | 312 | } |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -2448,6 +2448,10 @@ |
2449 | 2449 | */ |
2450 | 2450 | $wgResourceLoaderUseESI = false; |
2451 | 2451 | |
| 2452 | +/** |
| 2453 | + * Enable removal of some of the vertical whitespace (like \r and \n) from |
| 2454 | + * JavaScript code when minifying. |
| 2455 | + */ |
2452 | 2456 | $wgResourceLoaderMinifyJSVerticalSpace = false; |
2453 | 2457 | |
2454 | 2458 | /** @} */ # End of resource loader settings } |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -180,7 +180,6 @@ |
181 | 181 | 'PageHistory' => 'includes/HistoryPage.php', |
182 | 182 | 'PageHistoryPager' => 'includes/HistoryPage.php', |
183 | 183 | 'Pager' => 'includes/Pager.php', |
184 | | - 'ParseMaster' => 'includes/libs/ParseMaster.php', |
185 | 184 | 'PasswordError' => 'includes/User.php', |
186 | 185 | 'PatrolLog' => 'includes/PatrolLog.php', |
187 | 186 | 'PhpHttpRequest' => 'includes/HttpFunctions.php', |