Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: third_party/WebKit/Source/devtools/scripts/build/rjsmin.py

Issue 2553843002: [Devtools] Update RJSMin (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 # -*- coding: ascii -*-
3 # Copyright 2011 - 2013
4 # Andr\xe9 Malo or his licensors, as applicable
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 r""" 3 r"""
18 ===================== 4 =====================
19 Javascript Minifier 5 Javascript Minifier
20 ===================== 6 =====================
21 7
22 rJSmin is a javascript minifier written in python. 8 rJSmin is a javascript minifier written in python.
23 9
24 The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\. 10 The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\\.
11
12 :Copyright:
13
14 Copyright 2011 - 2015
15 Andr\xe9 Malo or his licensors, as applicable
16
17 :License:
18
19 Licensed under the Apache License, Version 2.0 (the "License");
20 you may not use this file except in compliance with the License.
21 You may obtain a copy of the License at
22
23 http://www.apache.org/licenses/LICENSE-2.0
24
25 Unless required by applicable law or agreed to in writing, software
26 distributed under the License is distributed on an "AS IS" BASIS,
27 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28 See the License for the specific language governing permissions and
29 limitations under the License.
25 30
26 The module is a re-implementation aiming for speed, so it can be used at 31 The module is a re-implementation aiming for speed, so it can be used at
27 runtime (rather than during a preprocessing step). Usually it produces the 32 runtime (rather than during a preprocessing step). Usually it produces the
28 same results as the original ``jsmin.c``. It differs in the following ways: 33 same results as the original ``jsmin.c``. It differs in the following ways:
29 34
30 - there is no error detection: unterminated string, regex and comment 35 - there is no error detection: unterminated string, regex and comment
31 literals are treated as regular javascript code and minified as such. 36 literals are treated as regular javascript code and minified as such.
32 - Control characters inside string and regex literals are left untouched; they 37 - Control characters inside string and regex literals are left untouched; they
33 are not converted to spaces (nor to \n) 38 are not converted to spaces (nor to \\n)
34 - Newline characters are not allowed inside string and regex literals, except 39 - Newline characters are not allowed inside string and regex literals, except
35 for line continuations in string literals (ECMA-5). 40 for line continuations in string literals (ECMA-5).
36 - "return /regex/" is recognized correctly. 41 - "return /regex/" is recognized correctly.
42 - Line terminators after regex literals are handled more sensibly
37 - "+ +" and "- -" sequences are not collapsed to '++' or '--' 43 - "+ +" and "- -" sequences are not collapsed to '++' or '--'
38 - Newlines before ! operators are removed more sensibly 44 - Newlines before ! operators are removed more sensibly
45 - Comments starting with an exclamation mark (``!``) can be kept optionally
39 - rJSmin does not handle streams, but only complete strings. (However, the 46 - rJSmin does not handle streams, but only complete strings. (However, the
40 module provides a "streamy" interface). 47 module provides a "streamy" interface).
41 48
42 Since most parts of the logic are handled by the regex engine it's way 49 Since most parts of the logic are handled by the regex engine it's way faster
43 faster than the original python port of ``jsmin.c`` by Baruch Even. The speed 50 than the original python port of ``jsmin.c`` by Baruch Even. The speed factor
44 factor varies between about 6 and 55 depending on input and python version 51 varies between about 6 and 55 depending on input and python version (it gets
45 (it gets faster the more compressed the input already is). Compared to the 52 faster the more compressed the input already is). Compared to the
46 speed-refactored python port by Dave St.Germain the performance gain is less 53 speed-refactored python port by Dave St.Germain the performance gain is less
47 dramatic but still between 1.2 and 7. See the docs/BENCHMARKS file for 54 dramatic but still between 3 and 50 (for huge inputs). See the docs/BENCHMARKS
48 details. 55 file for details.
49 56
50 rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more. 57 rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.
51 58
52 Both python 2 and python 3 are supported. 59 Both python 2 and python 3 are supported.
53 60
54 .. _jsmin.c by Douglas Crockford: 61 .. _jsmin.c by Douglas Crockford:
55 http://www.crockford.com/javascript/jsmin.c 62 http://www.crockford.com/javascript/jsmin.c
56 """ 63 """
57 __author__ = "Andr\xe9 Malo" 64 if __doc__:
58 __author__ = getattr(__author__, 'decode', lambda x: __author__)('latin-1') 65 # pylint: disable = redefined-builtin
66 __doc__ = __doc__.encode('ascii').decode('unicode_escape')
67 __author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape')
59 __docformat__ = "restructuredtext en" 68 __docformat__ = "restructuredtext en"
60 __license__ = "Apache License, Version 2.0" 69 __license__ = "Apache License, Version 2.0"
61 __version__ = '1.0.7' 70 __version__ = '1.0.12'
62 __all__ = ['jsmin'] 71 __all__ = ['jsmin']
63 72
64 import re as _re 73 import re as _re
65 74
66 75
67 def _make_jsmin(python_only=False): 76 def _make_jsmin(python_only=False):
68 """ 77 """
69 Generate JS minifier based on `jsmin.c by Douglas Crockford`_ 78 Generate JS minifier based on `jsmin.c by Douglas Crockford`_
70 79
71 .. _jsmin.c by Douglas Crockford: 80 .. _jsmin.c by Douglas Crockford:
72 http://www.crockford.com/javascript/jsmin.c 81 http://www.crockford.com/javascript/jsmin.c
73 82
74 :Parameters: 83 :Parameters:
75 `python_only` : ``bool`` 84 `python_only` : ``bool``
76 Use only the python variant. If true, the c extension is not even 85 Use only the python variant. If true, the c extension is not even
77 tried to be loaded. 86 tried to be loaded.
78 87
79 :Return: Minifier 88 :Return: Minifier
80 :Rtype: ``callable`` 89 :Rtype: ``callable``
81 """ 90 """
82 # pylint: disable = R0912, R0914, W0612 91 # pylint: disable = unused-variable
92 # pylint: disable = too-many-locals
93
83 if not python_only: 94 if not python_only:
84 try: 95 try:
85 import _rjsmin 96 import _rjsmin
86 except ImportError: 97 except ImportError:
87 pass 98 pass
88 else: 99 else:
89 return _rjsmin.jsmin 100 return _rjsmin.jsmin
90 try: 101 try:
91 xrange 102 xrange
92 except NameError: 103 except NameError:
93 xrange = range # pylint: disable = W0622 104 xrange = range # pylint: disable = redefined-builtin
94 105
95 space_chars = r'[\000-\011\013\014\016-\040]' 106 space_chars = r'[\000-\011\013\014\016-\040]'
96 107
97 line_comment = r'(?://[^\r\n]*)' 108 line_comment = r'(?://[^\r\n]*)'
98 space_comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)' 109 space_comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
110 space_comment_nobang = r'(?:/\*(?!!)[^*]*\*+(?:[^/*][^*]*\*+)*/)'
111 bang_comment = r'(?:/\*![^*]*\*+(?:[^/*][^*]*\*+)*/)'
112
99 string1 = \ 113 string1 = \
100 r'(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^\047\\\r\n]*)*\047)' 114 r'(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^\047\\\r\n]*)*\047)'
101 string2 = r'(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^"\\\r\n]*)*")' 115 string2 = r'(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^"\\\r\n]*)*")'
102 string3 = r'(?:`(?:[^`\\]|\\.)*`)' 116 string3 = r'(?:`(?:[^`\\]|\\.)*`)'
103 strings = r'(?:%s|%s|%s)' % (string1, string2, string3) 117 strings = r'(?:%s|%s|%s)' % (string1, string2, string3)
104 118
105 charclass = r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])' 119 charclass = r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])'
106 nospecial = r'[^/\\\[\r\n]' 120 nospecial = r'[^/\\\[\r\n]'
107 regex = r'(?:/(?![\r\n/*])%s*(?:(?:\\[^\r\n]|%s)%s*)*/)' % ( 121 regex = r'(?:/(?![\r\n/*])%s*(?:(?:\\[^\r\n]|%s)%s*)*/)' % (
108 nospecial, charclass, nospecial) 122 nospecial, charclass, nospecial
123 )
109 space = r'(?:%s|%s)' % (space_chars, space_comment) 124 space = r'(?:%s|%s)' % (space_chars, space_comment)
110 newline = r'(?:%s?[\r\n])' % line_comment 125 newline = r'(?:%s?[\r\n])' % line_comment
111 126
112 def fix_charclass(result): 127 def fix_charclass(result):
113 """ Fixup string of chars to fit into a regex char class """ 128 """ Fixup string of chars to fit into a regex char class """
114 pos = result.find('-') 129 pos = result.find('-')
115 if pos >= 0: 130 if pos >= 0:
116 result = r'%s%s-' % (result[:pos], result[pos + 1:]) 131 result = r'%s%s-' % (result[:pos], result[pos + 1:])
117 132
118 def sequentize(string): 133 def sequentize(string):
119 """ 134 """
120 Notate consecutive characters as sequence 135 Notate consecutive characters as sequence
121 136
122 (1-4 instead of 1234) 137 (1-4 instead of 1234)
123 """ 138 """
124 first, last, result = None, None, [] 139 first, last, result = None, None, []
125 for char in map(ord, string): 140 for char in map(ord, string):
126 if last is None: 141 if last is None:
127 first = last = char 142 first = last = char
128 elif last + 1 == char: 143 elif last + 1 == char:
129 last = char 144 last = char
130 else: 145 else:
131 result.append((first, last)) 146 result.append((first, last))
132 first = last = char 147 first = last = char
133 if last is not None: 148 if last is not None:
134 result.append((first, last)) 149 result.append((first, last))
135 return ''.join(['%s%s%s' % ( 150 return ''.join(['%s%s%s' % (
136 chr(first), 151 chr(first),
137 last > first + 1 and '-' or '', 152 last > first + 1 and '-' or '',
138 last != first and chr(last) or '') for first, last in result]) 153 last != first and chr(last) or ''
154 ) for first, last in result]) # noqa
139 155
140 return _re.sub(r'([\000-\040\047])', # for better portability 156 return _re.sub(
141 lambda m: '\\%03o' % ord(m.group(1)), (sequentize(result) 157 r'([\000-\040\047])', # \047 for better portability
158 lambda m: '\\%03o' % ord(m.group(1)), (
159 sequentize(result)
142 .replace('\\', '\\\\') 160 .replace('\\', '\\\\')
143 .replace('[', '\\[') 161 .replace('[', '\\[')
144 .replace(']', '\\]'))) 162 .replace(']', '\\]')
163 )
164 )
145 165
146 def id_literal_(what): 166 def id_literal_(what):
147 """ Make id_literal like char class """ 167 """ Make id_literal like char class """
148 match = _re.compile(what).match 168 match = _re.compile(what).match
149 result = ''.join([chr(c) for c in xrange(127) if not match(chr(c))]) 169 result = ''.join([
170 chr(c) for c in xrange(127) if not match(chr(c))
171 ])
150 return '[^%s]' % fix_charclass(result) 172 return '[^%s]' % fix_charclass(result)
151 173
152 def not_id_literal_(keep): 174 def not_id_literal_(keep):
153 """ Make negated id_literal like char class """ 175 """ Make negated id_literal like char class """
154 match = _re.compile(id_literal_(keep)).match 176 match = _re.compile(id_literal_(keep)).match
155 result = ''.join([chr(c) for c in xrange(127) if not match(chr(c))]) 177 result = ''.join([
178 chr(c) for c in xrange(127) if not match(chr(c))
179 ])
156 return r'[%s]' % fix_charclass(result) 180 return r'[%s]' % fix_charclass(result)
157 181
158 not_id_literal = not_id_literal_(r'[a-zA-Z0-9_$]') 182 not_id_literal = not_id_literal_(r'[a-zA-Z0-9_$]')
159 preregex1 = r'[(,=:\[!&|?{};\r\n]' 183 preregex1 = r'[(,=:\[!&|?{};\r\n]'
160 preregex2 = r'%(not_id_literal)sreturn' % locals() 184 preregex2 = r'%(not_id_literal)sreturn' % locals()
161 185
162 id_literal = id_literal_(r'[a-zA-Z0-9_$]') 186 id_literal = id_literal_(r'[a-zA-Z0-9_$]')
163 id_literal_open = id_literal_(r'[a-zA-Z0-9_${\[(!+-]') 187 id_literal_open = id_literal_(r'[a-zA-Z0-9_${\[(!+-]')
164 id_literal_close = id_literal_(r'[a-zA-Z0-9_$}\])"\047+-]') 188 id_literal_close = id_literal_(r'[a-zA-Z0-9_$}\])"\047+-]')
189 post_regex_off = id_literal_(r'[^\000-\040}\])?:|,;.&=+-]')
165 190
166 dull = r'[^\047"`/\000-\040]' 191 dull = r'[^\047"`/\000-\040]'
167 192
168 space_sub = _re.compile(( 193 space_sub_simple = _re.compile((
169 r'(%(dull)s+)' 194 # noqa pylint: disable = bad-continuation
170 r'|(%(strings)s%(dull)s*)' 195
196 r'(%(dull)s+)' # 0
197 r'|(%(strings)s%(dull)s*)' # 1
171 r'|(?<=%(preregex1)s)' 198 r'|(?<=%(preregex1)s)'
172 r'%(space)s*(?:%(newline)s%(space)s*)*' 199 r'%(space)s*(?:%(newline)s%(space)s*)*'
173 r'(%(regex)s%(dull)s*)' 200 r'(%(regex)s)' # 2
201 r'(%(space)s*(?:%(newline)s%(space)s*)+' # 3
202 r'(?=%(post_regex_off)s))?'
174 r'|(?<=%(preregex2)s)' 203 r'|(?<=%(preregex2)s)'
175 r'%(space)s*(?:%(newline)s%(space)s)*' 204 r'%(space)s*(?:(%(newline)s)%(space)s*)*' # 4
176 r'(%(regex)s%(dull)s*)' 205 r'(%(regex)s)' # 5
206 r'(%(space)s*(?:%(newline)s%(space)s*)+' # 6
207 r'(?=%(post_regex_off)s))?'
177 r'|(?<=%(id_literal_close)s)' 208 r'|(?<=%(id_literal_close)s)'
178 r'%(space)s*(?:(%(newline)s)%(space)s*)+' 209 r'%(space)s*(?:(%(newline)s)%(space)s*)+' # 7
179 r'(?=%(id_literal_open)s)' 210 r'(?=%(id_literal_open)s)'
180 r'|(?<=%(id_literal)s)(%(space)s)+(?=%(id_literal)s)' 211 r'|(?<=%(id_literal)s)(%(space)s)+(?=%(id_literal)s)' # 8
181 r'|(?<=\+)(%(space)s)+(?=\+)' 212 r'|(?<=\+)(%(space)s)+(?=\+)' # 9
182 r'|(?<=-)(%(space)s)+(?=-)' 213 r'|(?<=-)(%(space)s)+(?=-)' # 10
183 r'|%(space)s+' 214 r'|%(space)s+'
184 r'|(?:%(newline)s%(space)s*)+') % locals()).sub 215 r'|(?:%(newline)s%(space)s*)+'
185 #print space_sub.__self__.pattern 216 ) % locals()).sub
186 217
187 def space_subber(match): 218 # print space_sub_simple.__self__.pattern
219
220 def space_subber_simple(match):
188 """ Substitution callback """ 221 """ Substitution callback """
189 # pylint: disable = C0321, R0911 222 # pylint: disable = too-many-return-statements
223
190 groups = match.groups() 224 groups = match.groups()
191 if groups[0]: 225 if groups[0]:
192 return groups[0] 226 return groups[0]
193 elif groups[1]: 227 elif groups[1]:
194 return groups[1] 228 return groups[1]
195 elif groups[2]: 229 elif groups[2]:
230 if groups[3]:
231 return groups[2] + '\n'
196 return groups[2] 232 return groups[2]
197 elif groups[3]: 233 elif groups[5]:
198 return groups[3] 234 return "%s%s%s" % (
199 elif groups[4]: 235 groups[4] and '\n' or '',
236 groups[5],
237 groups[6] and '\n' or '',
238 )
239 elif groups[7]:
200 return '\n' 240 return '\n'
201 elif groups[5] or groups[6] or groups[7]: 241 elif groups[8] or groups[9] or groups[10]:
202 return ' ' 242 return ' '
203 else: 243 else:
204 return '' 244 return ''
205 245
206 def jsmin(script): # pylint: disable = W0621 246 space_sub_banged = _re.compile((
247 # noqa pylint: disable = bad-continuation
248
249 r'(%(dull)s+)' # 0
250 r'|(%(strings)s%(dull)s*)' # 1
251 r'|(?<=%(preregex1)s)'
252 r'(%(space)s*(?:%(newline)s%(space)s*)*)' # 2
253 r'(%(regex)s)' # 3
254 r'(%(space)s*(?:%(newline)s%(space)s*)+' # 4
255 r'(?=%(post_regex_off)s))?'
256 r'|(?<=%(preregex2)s)'
257 r'(%(space)s*(?:(%(newline)s)%(space)s*)*)' # 5, 6
258 r'(%(regex)s)' # 7
259 r'(%(space)s*(?:%(newline)s%(space)s*)+' # 8
260 r'(?=%(post_regex_off)s))?'
261 r'|(?<=%(id_literal_close)s)'
262 r'(%(space)s*(?:%(newline)s%(space)s*)+)' # 9
263 r'(?=%(id_literal_open)s)'
264 r'|(?<=%(id_literal)s)(%(space)s+)(?=%(id_literal)s)' # 10
265 r'|(?<=\+)(%(space)s+)(?=\+)' # 11
266 r'|(?<=-)(%(space)s+)(?=-)' # 12
267 r'|(%(space)s+)' # 13
268 r'|((?:%(newline)s%(space)s*)+)' # 14
269 ) % locals()).sub
270
271 # print space_sub_banged.__self__.pattern
272
273 keep = _re.compile((
274 r'%(space_chars)s+|%(space_comment_nobang)s+|%(newline)s+'
275 r'|(%(bang_comment)s+)'
276 ) % locals()).sub
277 keeper = lambda m: m.groups()[0] or ''
278
279 # print keep.__self__.pattern
280
281 def space_subber_banged(match):
282 """ Substitution callback """
283 # pylint: disable = too-many-return-statements
284
285 groups = match.groups()
286 if groups[0]:
287 return groups[0]
288 elif groups[1]:
289 return groups[1]
290 elif groups[3]:
291 return "%s%s%s%s" % (
292 keep(keeper, groups[2]),
293 groups[3],
294 keep(keeper, groups[4] or ''),
295 groups[4] and '\n' or '',
296 )
297 elif groups[7]:
298 return "%s%s%s%s%s" % (
299 keep(keeper, groups[5]),
300 groups[6] and '\n' or '',
301 groups[7],
302 keep(keeper, groups[8] or ''),
303 groups[8] and '\n' or '',
304 )
305 elif groups[9]:
306 return keep(keeper, groups[9]) + '\n'
307 elif groups[10] or groups[11] or groups[12]:
308 return keep(keeper, groups[10] or groups[11] or groups[12]) or ' '
309 else:
310 return keep(keeper, groups[13] or groups[14])
311
312 def jsmin(script, keep_bang_comments=False):
207 r""" 313 r"""
208 Minify javascript based on `jsmin.c by Douglas Crockford`_\. 314 Minify javascript based on `jsmin.c by Douglas Crockford`_\.
209 315
210 Instead of parsing the stream char by char, it uses a regular 316 Instead of parsing the stream char by char, it uses a regular
211 expression approach which minifies the whole script with one big 317 expression approach which minifies the whole script with one big
212 substitution regex. 318 substitution regex.
213 319
214 .. _jsmin.c by Douglas Crockford: 320 .. _jsmin.c by Douglas Crockford:
215 http://www.crockford.com/javascript/jsmin.c 321 http://www.crockford.com/javascript/jsmin.c
216 322
217 :Parameters: 323 :Parameters:
218 `script` : ``str`` 324 `script` : ``str``
219 Script to minify 325 Script to minify
220 326
327 `keep_bang_comments` : ``bool``
328 Keep comments starting with an exclamation mark? (``/*!...*/``)
329
221 :Return: Minified script 330 :Return: Minified script
222 :Rtype: ``str`` 331 :Rtype: ``str``
223 """ 332 """
224 return space_sub(space_subber, '\n%s\n' % script).strip() 333 # pylint: disable = redefined-outer-name
334
335 if keep_bang_comments:
336 return space_sub_banged(
337 space_subber_banged, '\n%s\n' % script
338 ).strip()
339 else:
340 return space_sub_simple(
341 space_subber_simple, '\n%s\n' % script
342 ).strip()
225 343
226 return jsmin 344 return jsmin
227 345
228 jsmin = _make_jsmin() 346 jsmin = _make_jsmin()
229 347
230 348
231 def jsmin_for_posers(script): 349 def jsmin_for_posers(script, keep_bang_comments=False):
232 r""" 350 r"""
233 Minify javascript based on `jsmin.c by Douglas Crockford`_\. 351 Minify javascript based on `jsmin.c by Douglas Crockford`_\.
234 352
235 Instead of parsing the stream char by char, it uses a regular 353 Instead of parsing the stream char by char, it uses a regular
236 expression approach which minifies the whole script with one big 354 expression approach which minifies the whole script with one big
237 substitution regex. 355 substitution regex.
238 356
239 .. _jsmin.c by Douglas Crockford: 357 .. _jsmin.c by Douglas Crockford:
240 http://www.crockford.com/javascript/jsmin.c 358 http://www.crockford.com/javascript/jsmin.c
241 359
242 :Warning: This function is the digest of a _make_jsmin() call. It just 360 :Warning: This function is the digest of a _make_jsmin() call. It just
243 utilizes the resulting regex. It's just for fun here and may 361 utilizes the resulting regexes. It's here for fun and may
244 vanish any time. Use the `jsmin` function instead. 362 vanish any time. Use the `jsmin` function instead.
245 363
246 :Parameters: 364 :Parameters:
247 `script` : ``str`` 365 `script` : ``str``
248 Script to minify 366 Script to minify
249 367
368 `keep_bang_comments` : ``bool``
369 Keep comments starting with an exclamation mark? (``/*!...*/``)
370
250 :Return: Minified script 371 :Return: Minified script
251 :Rtype: ``str`` 372 :Rtype: ``str``
252 """ 373 """
253 def subber(match): 374 if not keep_bang_comments:
254 """ Substitution callback """ 375 rex = (
255 groups = match.groups() 376 r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]'
256 return ( 377 r'|\r?\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]'
257 groups[0] or 378 r'|\r?\n|\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?'
258 groups[1] or 379 r'{};\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*'
259 groups[2] or 380 r'][^*]*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\0'
260 groups[3] or 381 r'14\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*((?:/(?![\r'
261 (groups[4] and '\n') or 382 r'\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r'
262 (groups[5] and ' ') or 383 r'\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))((?:[\000-\011\013\014'
263 (groups[6] and ' ') or 384 r'\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:(?:(?://[^\r'
264 (groups[7] and ' ') or 385 r'\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:'
265 '') 386 r'[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)+,.:;=?\]|}-]))?|(?<=[\00'
387 r'0-#%-,./:-@\[-^`{-~-]return)(?:[\000-\011\013\014\016-\040]|(?'
388 r':/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?://[^\r\n]*)?[\r\n]'
389 r'))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*'
390 r'\*+)*/))*)*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\['
391 r'[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))(('
392 r'?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)'
393 r'*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\04'
394 r'0]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)+,.:;'
395 r'=?\]|}-]))?|(?<=[^\000-!#%&(*,./:-@\[\\^`{|~])(?:[\000-\011\01'
396 r'3\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?:'
397 r'//[^\r\n]*)?[\r\n]))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]'
398 r'*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040"#%-\047)*,./:-@\\-^'
399 r'`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\013\014\0'
400 r'16-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=[^\000-#%-,./'
401 r':-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|(?:/\*['
402 r'^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=\+)|(?<=-)((?:[\000-\011\013'
403 r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=-)|(?:['
404 r'\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
405 r')+|(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]'
406 r'|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+'
407 )
266 408
267 return _re.sub( 409 def subber(match):
268 r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?' 410 """ Substitution callback """
269 r'\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|' 411 groups = match.groups()
270 r'\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?{};\r\n])(?' 412 return (
271 r':[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*' 413 groups[0] or
272 r'(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*' 414 groups[1] or
273 r'[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(' 415 (groups[3] and (groups[2] + '\n')) or
274 r'?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[' 416 groups[2] or
275 r'\r\n]*)*/)[^\047"/\000-\040]*)|(?<=[\000-#%-,./:-@\[-^`{-~-]return' 417 (groups[5] and "%s%s%s" % (
276 r')(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/' 418 groups[4] and '\n' or '',
277 r'))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:' 419 groups[5],
278 r'/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?' 420 groups[6] and '\n' or '',
279 r':(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/' 421 )) or
280 r'\\\[\r\n]*)*/)[^\047"/\000-\040]*)|(?<=[^\000-!#%&(*,./:-@\[\\^`{|' 422 (groups[7] and '\n') or
281 r'~])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)' 423 (groups[8] and ' ') or
282 r'*/))*(?:((?:(?://[^\r\n]*)?[\r\n]))(?:[\000-\011\013\014\016-\040]' 424 (groups[9] and ' ') or
283 r'|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040"#%-\047)*,./' 425 (groups[10] and ' ') or
284 r':-@\\-^`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\013\01' 426 ''
285 r'4\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=[^\000-#%-,./:' 427 )
286 r'-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*' 428 else:
287 r'\*+(?:[^/*][^*]*\*+)*/)))+(?=\+)|(?<=-)((?:[\000-\011\013\014\016-' 429 rex = (
288 r'\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=-)|(?:[\000-\011\013' 430 r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]'
289 r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+|(?:(?:(?://[^' 431 r'|\r?\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]'
290 r'\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^' 432 r'|\r?\n|\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?'
291 r'/*][^*]*\*+)*/))*)+', subber, '\n%s\n' % script).strip() 433 r'{};\r\n])((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/'
434 r'*][^*]*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013'
435 r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*)((?:/(?!'
436 r'[\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^'
437 r'\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))((?:[\000-\011\013\01'
438 r'4\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:(?:(?://[^'
439 r'\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+('
440 r'?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)+,.:;=?\]|}-]))?|(?<=['
441 r'\000-#%-,./:-@\[-^`{-~-]return)((?:[\000-\011\013\014\016-\040'
442 r']|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?://[^\r\n]*)?['
443 r'\r\n]))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*]['
444 r'^*]*\*+)*/))*)*)((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|'
445 r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*'
446 r'/))((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]'
447 r'*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\01'
448 r'6-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)'
449 r'+,.:;=?\]|}-]))?|(?<=[^\000-!#%&(*,./:-@\[\\^`{|~])((?:[\000-'
450 r'\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:'
451 r'(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/'
452 r'\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+)(?=[^\000-\040"#%-\047)*,./'
453 r':-@\\-^`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\01'
454 r'3\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=[^\000'
455 r'-#%-,./:-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|'
456 r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=\+)|(?<=-)((?:[\000-\0'
457 r'11\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=-'
458 r')|((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*'
459 r'\*+)*/))+)|((?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014'
460 r'\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+)'
461 )
462
463 keep = _re.compile((
464 r'[\000-\011\013\014\016-\040]+|(?:/\*(?!!)[^*]*\*+(?:[^/*][^*]*'
465 r'\*+)*/)+|(?:(?://[^\r\n]*)?[\r\n])+|((?:/\*![^*]*\*+(?:[^/*][^'
466 r'*]*\*+)*/)+)'
467 ) % locals()).sub
468 keeper = lambda m: m.groups()[0] or ''
469
470 def subber(match):
471 """ Substitution callback """
472 groups = match.groups()
473 return (
474 groups[0] or
475 groups[1] or
476 (groups[3] and "%s%s%s%s" % (
477 keep(keeper, groups[2]),
478 groups[3],
479 keep(keeper, groups[4] or ''),
480 groups[4] and '\n' or '',
481 )) or
482 (groups[7] and "%s%s%s%s%s" % (
483 keep(keeper, groups[5]),
484 groups[6] and '\n' or '',
485 groups[7],
486 keep(keeper, groups[8] or ''),
487 groups[8] and '\n' or '',
488 )) or
489 (groups[9] and keep(keeper, groups[9] + '\n')) or
490 (groups[10] and keep(keeper, groups[10]) or ' ') or
491 (groups[11] and keep(keeper, groups[11]) or ' ') or
492 (groups[12] and keep(keeper, groups[12]) or ' ') or
493 keep(keeper, groups[13] or groups[14])
494 )
495
496 return _re.sub(rex, subber, '\n%s\n' % script).strip()
292 497
293 498
294 if __name__ == '__main__': 499 if __name__ == '__main__':
295 import sys as _sys 500 def main():
296 _sys.stdout.write(jsmin(_sys.stdin.read())) 501 """ Main """
502 import sys as _sys
503
504 argv = _sys.argv[1:]
505 keep_bang_comments = '-b' in argv or '-bp' in argv or '-pb' in argv
506 if '-p' in argv or '-bp' in argv or '-pb' in argv:
507 xjsmin = _make_jsmin(python_only=True)
508 else:
509 xjsmin = jsmin
510
511 _sys.stdout.write(xjsmin(
512 _sys.stdin.read(), keep_bang_comments=keep_bang_comments
513 ))
514
515 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698