├── README.md
├── composer.json
└── src
└── jsmin-1.1.1.php
/README.md:
--------------------------------------------------------------------------------
1 | # jsmin-php
2 |
3 | Unofficial repo containing a composer enabled jsmin-php
4 |
5 | Please check the composer.json for original authors and credits.
6 |
7 | ## Brought to you by the LinkORB Engineering team
8 |
9 | 
10 | Check out our other projects at [linkorb.com/engineering](http://www.linkorb.com/engineering).
11 |
12 | Btw, we're hiring!
13 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "linkorb/jsmin-php",
3 | "description": "Unofficial package of jsmin-php",
4 | "homepage": "http://www.github.com/linkorb/jsmin-php",
5 | "keywords": ["minify", "jsmin", "javascript"],
6 | "type": "library",
7 | "authors": [
8 | {
9 | "name": "Joost Faassen",
10 | "email": "j.faassen@linkorb.com",
11 | "role": "Packaging for composer"
12 | },
13 | {
14 | "name": "Douglas Crockford",
15 | "email": "douglas@crockford.com",
16 | "role": ""
17 | },
18 | {
19 | "name": "Ryan Grove",
20 | "email": "ryan@wonko.com",
21 | "role": "PHP port"
22 | },
23 | {
24 | "name": "Adam Gofort",
25 | "email": "aag@adamgoforth.com",
26 | "role": "Updates to the PHP port"
27 | }
28 | ],
29 | "require": {
30 | "php": ">=5.0.0"
31 | },
32 | "autoload": {
33 | "classmap": ["src/"]
34 | },
35 | "license": "MIT"
36 | }
37 |
--------------------------------------------------------------------------------
/src/jsmin-1.1.1.php:
--------------------------------------------------------------------------------
1 |
41 | * @copyright 2002 Douglas Crockford (jsmin.c)
42 | * @copyright 2008 Ryan Grove (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 | ?>
--------------------------------------------------------------------------------