Dotclear

source: build-tools/jsmin-1.1.1.php @ 3730:5c45a5df9a59

Revision 3730:5c45a5df9a59, 9.2 KB checked in by franck <carnet.franck.paul@…>, 8 years ago (diff)

Code formatting (PSR-2)

Line 
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
48class JSMin
49{
50    const ORD_LF    = 10;
51    const ORD_SPACE = 32;
52
53    protected $a           = '';
54    protected $b           = '';
55    protected $input       = '';
56    protected $inputIndex  = 0;
57    protected $inputLength = 0;
58    protected $lookAhead   = null;
59    protected $output      = '';
60
61    // -- Public Static Methods --------------------------------------------------
62
63    public static function minify($js)
64    {
65        $jsmin = new JSMin($js);
66        return $jsmin->min();
67    }
68
69    // -- Public Instance Methods ------------------------------------------------
70
71    public function __construct($input)
72    {
73        $this->input       = str_replace("\r\n", "\n", $input);
74        $this->inputLength = strlen($this->input);
75    }
76
77    // -- Protected Instance Methods ---------------------------------------------
78
79    protected function action($d)
80    {
81        switch ($d) {
82            case 1:
83                $this->output .= $this->a;
84
85            case 2:
86                $this->a = $this->b;
87
88                if ($this->a === "'" || $this->a === '"') {
89                    for (;;) {
90                        $this->output .= $this->a;
91                        $this->a = $this->get();
92
93                        if ($this->a === $this->b) {
94                            break;
95                        }
96
97                        if (ord($this->a) <= self::ORD_LF) {
98                            throw new JSMinException('Unterminated string literal.');
99                        }
100
101                        if ($this->a === '\\') {
102                            $this->output .= $this->a;
103                            $this->a = $this->get();
104                        }
105                    }
106                }
107
108            case 3:
109                $this->b = $this->next();
110
111                if ($this->b === '/' && (
112                    $this->a === '(' || $this->a === ',' || $this->a === '=' ||
113                    $this->a === ':' || $this->a === '[' || $this->a === '!' ||
114                    $this->a === '&' || $this->a === '|' || $this->a === '?')) {
115
116                    $this->output .= $this->a . $this->b;
117
118                    for (;;) {
119                        $this->a = $this->get();
120
121                        if ($this->a === '/') {
122                            break;
123                        } elseif ($this->a === '\\') {
124                            $this->output .= $this->a;
125                            $this->a = $this->get();
126                        } elseif (ord($this->a) <= self::ORD_LF) {
127                            throw new JSMinException('Unterminated regular expression ' .
128                                'literal.');
129                        }
130
131                        $this->output .= $this->a;
132                    }
133
134                    $this->b = $this->next();
135                }
136        }
137    }
138
139    protected function get()
140    {
141        $c               = $this->lookAhead;
142        $this->lookAhead = null;
143
144        if ($c === null) {
145            if ($this->inputIndex < $this->inputLength) {
146                $c = $this->input[$this->inputIndex];
147                $this->inputIndex += 1;
148            } else {
149                $c = null;
150            }
151        }
152
153        if ($c === "\r") {
154            return "\n";
155        }
156
157        if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
158            return $c;
159        }
160
161        return ' ';
162    }
163
164    protected function isAlphaNum($c)
165    {
166        return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
167    }
168
169    protected function min()
170    {
171        $this->a = "\n";
172        $this->action(3);
173
174        while ($this->a !== null) {
175            switch ($this->a) {
176                case ' ':
177                    if ($this->isAlphaNum($this->b)) {
178                        $this->action(1);
179                    } else {
180                        $this->action(2);
181                    }
182                    break;
183
184                case "\n":
185                    switch ($this->b) {
186                        case '{':
187                        case '[':
188                        case '(':
189                        case '+':
190                        case '-':
191                            $this->action(1);
192                            break;
193
194                        case ' ':
195                            $this->action(3);
196                            break;
197
198                        default:
199                            if ($this->isAlphaNum($this->b)) {
200                                $this->action(1);
201                            } else {
202                                $this->action(2);
203                            }
204                    }
205                    break;
206
207                default:
208                    switch ($this->b) {
209                        case ' ':
210                            if ($this->isAlphaNum($this->a)) {
211                                $this->action(1);
212                                break;
213                            }
214
215                            $this->action(3);
216                            break;
217
218                        case "\n":
219                            switch ($this->a) {
220                                case '}':
221                                case ']':
222                                case ')':
223                                case '+':
224                                case '-':
225                                case '"':
226                                case "'":
227                                    $this->action(1);
228                                    break;
229
230                                default:
231                                    if ($this->isAlphaNum($this->a)) {
232                                        $this->action(1);
233                                    } else {
234                                        $this->action(3);
235                                    }
236                            }
237                            break;
238
239                        default:
240                            $this->action(1);
241                            break;
242                    }
243            }
244        }
245
246        return $this->output;
247    }
248
249    protected function next()
250    {
251        $c = $this->get();
252
253        if ($c === '/') {
254            switch ($this->peek()) {
255                case '/':
256                    for (;;) {
257                        $c = $this->get();
258
259                        if (ord($c) <= self::ORD_LF) {
260                            return $c;
261                        }
262                    }
263
264                case '*':
265                    $this->get();
266
267                    for (;;) {
268                        switch ($this->get()) {
269                            case '*':
270                                if ($this->peek() === '/') {
271                                    $this->get();
272                                    return ' ';
273                                }
274                                break;
275
276                            case null:
277                                throw new JSMinException('Unterminated comment.');
278                        }
279                    }
280
281                default:
282                    return $c;
283            }
284        }
285
286        return $c;
287    }
288
289    protected function peek()
290    {
291        $this->lookAhead = $this->get();
292        return $this->lookAhead;
293    }
294}
295
296// -- Exceptions ---------------------------------------------------------------
297class JSMinException extends Exception
298{}
Note: See TracBrowser for help on using the repository browser.

Sites map