PluginProbe
Autoptimize / 2.3.0
Autoptimize v2.3.0
2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 All 107 releases
autoptimize / classes / external / php / jsmin-1.1.1.php

jsmin-1.1.1.php in Autoptimize 2.3.0, at classes/external/php/jsmin-1.1.1.php

292 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * jsmin.php - PHP implementation of Douglas Crockford's JSMin.
4 *
5 * This is pretty much a direct port of jsmin.c to PHP with just a few
6 * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
7 * outputs to stdout, this library accepts a string as input and returns another
8 * string as output.
9 *
10 * PHP 5 or higher is required.
11 *
12 * Permission is hereby granted to use this version of the library under the
13 * same terms as jsmin.c, which has the following license:
14 *
15 * --
16 * Copyright (c) 2002 Douglas Crockford (www.crockford.com)
17 *
18 * Permission is hereby granted, free of charge, to any person obtaining a copy of
19 * this software and associated documentation files (the "Software"), to deal in
20 * the Software without restriction, including without limitation the rights to
21 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
22 * of the Software, and to permit persons to whom the Software is furnished to do
23 * so, subject to the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be included in all
26 * copies or substantial portions of the Software.
27 *
28 * The Software shall be used for Good, not Evil.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 * SOFTWARE.
37 * --
38 *
39 * @package JSMin
40 * @author Ryan Grove <ryan@wonko.com>
41 * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
42 * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
43 * @license http://opensource.org/licenses/mit-license.php MIT License
44 * @version 1.1.1 (2008-03-02)
45 * @link http://code.google.com/p/jsmin-php/
46 */
47
48 class JSMin {
49 const ORD_LF = 10;
50 const ORD_SPACE = 32;
51
52 protected $a = '';
53 protected $b = '';
54 protected $input = '';
55 protected $inputIndex = 0;
56 protected $inputLength = 0;
57 protected $lookAhead = null;
58 protected $output = '';
59
60 // -- Public Static Methods --------------------------------------------------
61
62 public static function minify($js) {
63 $jsmin = new JSMin($js);
64 return $jsmin->min();
65 }
66
67 // -- Public Instance Methods ------------------------------------------------
68
69 public function __construct($input) {
70 $this->input = str_replace("\r\n", "\n", $input);
71 $this->inputLength = strlen($this->input);
72 }
73
74 // -- Protected Instance Methods ---------------------------------------------
75
76 protected function action($d) {
77 switch($d) {
78 case 1:
79 $this->output .= $this->a;
80
81 case 2:
82 $this->a = $this->b;
83
84 if ($this->a === "'" || $this->a === '"') {
85 for (;;) {
86 $this->output .= $this->a;
87 $this->a = $this->get();
88
89 if ($this->a === $this->b) {
90 break;
91 }
92
93 if (ord($this->a) <= self::ORD_LF) {
94 throw new JSMinException('Unterminated string literal.');
95 }
96
97 if ($this->a === '\\') {
98 $this->output .= $this->a;
99 $this->a = $this->get();
100 }
101 }
102 }
103
104 case 3:
105 $this->b = $this->next();
106
107 if ($this->b === '/' && (
108 $this->a === '(' || $this->a === ',' || $this->a === '=' ||
109 $this->a === ':' || $this->a === '[' || $this->a === '!' ||
110 $this->a === '&' || $this->a === '|' || $this->a === '?')) {
111
112 $this->output .= $this->a . $this->b;
113
114 for (;;) {
115 $this->a = $this->get();
116
117 if ($this->a === '/') {
118 break;
119 } elseif ($this->a === '\\') {
120 $this->output .= $this->a;
121 $this->a = $this->get();
122 } elseif (ord($this->a) <= self::ORD_LF) {
123 throw new JSMinException('Unterminated regular expression '.
124 'literal.');
125 }
126
127 $this->output .= $this->a;
128 }
129
130 $this->b = $this->next();
131 }
132 }
133 }
134
135 protected function get() {
136 $c = $this->lookAhead;
137 $this->lookAhead = null;
138
139 if ($c === null) {
140 if ($this->inputIndex < $this->inputLength) {
141 $c = $this->input[$this->inputIndex];
142 $this->inputIndex += 1;
143 } else {
144 $c = null;
145 }
146 }
147
148 if ($c === "\r") {
149 return "\n";
150 }
151
152 if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
153 return $c;
154 }
155
156 return ' ';
157 }
158
159 protected function isAlphaNum($c) {
160 return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
161 }
162
163 protected function min() {
164 $this->a = "\n";
165 $this->action(3);
166
167 while ($this->a !== null) {
168 switch ($this->a) {
169 case ' ':
170 if ($this->isAlphaNum($this->b)) {
171 $this->action(1);
172 } else {
173 $this->action(2);
174 }
175 break;
176
177 case "\n":
178 switch ($this->b) {
179 case '{':
180 case '[':
181 case '(':
182 case '+':
183 case '-':
184 $this->action(1);
185 break;
186
187 case ' ':
188 $this->action(3);
189 break;
190
191 default:
192 if ($this->isAlphaNum($this->b)) {
193 $this->action(1);
194 }
195 else {
196 $this->action(2);
197 }
198 }
199 break;
200
201 default:
202 switch ($this->b) {
203 case ' ':
204 if ($this->isAlphaNum($this->a)) {
205 $this->action(1);
206 break;
207 }
208
209 $this->action(3);
210 break;
211
212 case "\n":
213 switch ($this->a) {
214 case '}':
215 case ']':
216 case ')':
217 case '+':
218 case '-':
219 case '"':
220 case "'":
221 $this->action(1);
222 break;
223
224 default:
225 if ($this->isAlphaNum($this->a)) {
226 $this->action(1);
227 }
228 else {
229 $this->action(3);
230 }
231 }
232 break;
233
234 default:
235 $this->action(1);
236 break;
237 }
238 }
239 }
240
241 return $this->output;
242 }
243
244 protected function next() {
245 $c = $this->get();
246
247 if ($c === '/') {
248 switch($this->peek()) {
249 case '/':
250 for (;;) {
251 $c = $this->get();
252
253 if (ord($c) <= self::ORD_LF) {
254 return $c;
255 }
256 }
257
258 case '*':
259 $this->get();
260
261 for (;;) {
262 switch($this->get()) {
263 case '*':
264 if ($this->peek() === '/') {
265 $this->get();
266 return ' ';
267 }
268 break;
269
270 case null:
271 throw new JSMinException('Unterminated comment.');
272 }
273 }
274
275 default:
276 return $c;
277 }
278 }
279
280 return $c;
281 }
282
283 protected function peek() {
284 $this->lookAhead = $this->get();
285 return $this->lookAhead;
286 }
287 }
288
289 // -- Exceptions ---------------------------------------------------------------
290 class JSMinException extends Exception {}
291 ?>
292