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

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

Issue 2441163002: DevTools: clean up scripts folder (Closed)
Patch Set: Fix sys.path for chromevox to load rjsmin Created 4 years, 1 month 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 | « third_party/WebKit/Source/devtools/scripts/optimize_png_images.py ('k') | 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
(Empty)
1 #!/usr/bin/env python
2 #
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"""
18 =====================
19 Javascript Minifier
20 =====================
21
22 rJSmin is a javascript minifier written in python.
23
24 The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\.
25
26 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
28 same results as the original ``jsmin.c``. It differs in the following ways:
29
30 - there is no error detection: unterminated string, regex and comment
31 literals are treated as regular javascript code and minified as such.
32 - Control characters inside string and regex literals are left untouched; they
33 are not converted to spaces (nor to \n)
34 - Newline characters are not allowed inside string and regex literals, except
35 for line continuations in string literals (ECMA-5).
36 - "return /regex/" is recognized correctly.
37 - "+ +" and "- -" sequences are not collapsed to '++' or '--'
38 - Newlines before ! operators are removed more sensibly
39 - rJSmin does not handle streams, but only complete strings. (However, the
40 module provides a "streamy" interface).
41
42 Since most parts of the logic are handled by the regex engine it's way
43 faster than the original python port of ``jsmin.c`` by Baruch Even. The speed
44 factor varies between about 6 and 55 depending on input and python version
45 (it gets 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
47 dramatic but still between 1.2 and 7. See the docs/BENCHMARKS file for
48 details.
49
50 rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.
51
52 Both python 2 and python 3 are supported.
53
54 .. _jsmin.c by Douglas Crockford:
55 http://www.crockford.com/javascript/jsmin.c
56 """
57 __author__ = "Andr\xe9 Malo"
58 __author__ = getattr(__author__, 'decode', lambda x: __author__)('latin-1')
59 __docformat__ = "restructuredtext en"
60 __license__ = "Apache License, Version 2.0"
61 __version__ = '1.0.7'
62 __all__ = ['jsmin']
63
64 import re as _re
65
66
67 def _make_jsmin(python_only=False):
68 """
69 Generate JS minifier based on `jsmin.c by Douglas Crockford`_
70
71 .. _jsmin.c by Douglas Crockford:
72 http://www.crockford.com/javascript/jsmin.c
73
74 :Parameters:
75 `python_only` : ``bool``
76 Use only the python variant. If true, the c extension is not even
77 tried to be loaded.
78
79 :Return: Minifier
80 :Rtype: ``callable``
81 """
82 # pylint: disable = R0912, R0914, W0612
83 if not python_only:
84 try:
85 import _rjsmin
86 except ImportError:
87 pass
88 else:
89 return _rjsmin.jsmin
90 try:
91 xrange
92 except NameError:
93 xrange = range # pylint: disable = W0622
94
95 space_chars = r'[\000-\011\013\014\016-\040]'
96
97 line_comment = r'(?://[^\r\n]*)'
98 space_comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
99 string1 = \
100 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]*)*")'
102 string3 = r'(?:`(?:[^`\\]|\\.)*`)'
103 strings = r'(?:%s|%s|%s)' % (string1, string2, string3)
104
105 charclass = r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])'
106 nospecial = r'[^/\\\[\r\n]'
107 regex = r'(?:/(?![\r\n/*])%s*(?:(?:\\[^\r\n]|%s)%s*)*/)' % (
108 nospecial, charclass, nospecial)
109 space = r'(?:%s|%s)' % (space_chars, space_comment)
110 newline = r'(?:%s?[\r\n])' % line_comment
111
112 def fix_charclass(result):
113 """ Fixup string of chars to fit into a regex char class """
114 pos = result.find('-')
115 if pos >= 0:
116 result = r'%s%s-' % (result[:pos], result[pos + 1:])
117
118 def sequentize(string):
119 """
120 Notate consecutive characters as sequence
121
122 (1-4 instead of 1234)
123 """
124 first, last, result = None, None, []
125 for char in map(ord, string):
126 if last is None:
127 first = last = char
128 elif last + 1 == char:
129 last = char
130 else:
131 result.append((first, last))
132 first = last = char
133 if last is not None:
134 result.append((first, last))
135 return ''.join(['%s%s%s' % (
136 chr(first),
137 last > first + 1 and '-' or '',
138 last != first and chr(last) or '') for first, last in result])
139
140 return _re.sub(r'([\000-\040\047])', # for better portability
141 lambda m: '\\%03o' % ord(m.group(1)), (sequentize(result)
142 .replace('\\', '\\\\')
143 .replace('[', '\\[')
144 .replace(']', '\\]')))
145
146 def id_literal_(what):
147 """ Make id_literal like char class """
148 match = _re.compile(what).match
149 result = ''.join([chr(c) for c in xrange(127) if not match(chr(c))])
150 return '[^%s]' % fix_charclass(result)
151
152 def not_id_literal_(keep):
153 """ Make negated id_literal like char class """
154 match = _re.compile(id_literal_(keep)).match
155 result = ''.join([chr(c) for c in xrange(127) if not match(chr(c))])
156 return r'[%s]' % fix_charclass(result)
157
158 not_id_literal = not_id_literal_(r'[a-zA-Z0-9_$]')
159 preregex1 = r'[(,=:\[!&|?{};\r\n]'
160 preregex2 = r'%(not_id_literal)sreturn' % locals()
161
162 id_literal = id_literal_(r'[a-zA-Z0-9_$]')
163 id_literal_open = id_literal_(r'[a-zA-Z0-9_${\[(!+-]')
164 id_literal_close = id_literal_(r'[a-zA-Z0-9_$}\])"\047+-]')
165
166 dull = r'[^\047"`/\000-\040]'
167
168 space_sub = _re.compile((
169 r'(%(dull)s+)'
170 r'|(%(strings)s%(dull)s*)'
171 r'|(?<=%(preregex1)s)'
172 r'%(space)s*(?:%(newline)s%(space)s*)*'
173 r'(%(regex)s%(dull)s*)'
174 r'|(?<=%(preregex2)s)'
175 r'%(space)s*(?:%(newline)s%(space)s)*'
176 r'(%(regex)s%(dull)s*)'
177 r'|(?<=%(id_literal_close)s)'
178 r'%(space)s*(?:(%(newline)s)%(space)s*)+'
179 r'(?=%(id_literal_open)s)'
180 r'|(?<=%(id_literal)s)(%(space)s)+(?=%(id_literal)s)'
181 r'|(?<=\+)(%(space)s)+(?=\+)'
182 r'|(?<=-)(%(space)s)+(?=-)'
183 r'|%(space)s+'
184 r'|(?:%(newline)s%(space)s*)+') % locals()).sub
185 #print space_sub.__self__.pattern
186
187 def space_subber(match):
188 """ Substitution callback """
189 # pylint: disable = C0321, R0911
190 groups = match.groups()
191 if groups[0]:
192 return groups[0]
193 elif groups[1]:
194 return groups[1]
195 elif groups[2]:
196 return groups[2]
197 elif groups[3]:
198 return groups[3]
199 elif groups[4]:
200 return '\n'
201 elif groups[5] or groups[6] or groups[7]:
202 return ' '
203 else:
204 return ''
205
206 def jsmin(script): # pylint: disable = W0621
207 r"""
208 Minify javascript based on `jsmin.c by Douglas Crockford`_\.
209
210 Instead of parsing the stream char by char, it uses a regular
211 expression approach which minifies the whole script with one big
212 substitution regex.
213
214 .. _jsmin.c by Douglas Crockford:
215 http://www.crockford.com/javascript/jsmin.c
216
217 :Parameters:
218 `script` : ``str``
219 Script to minify
220
221 :Return: Minified script
222 :Rtype: ``str``
223 """
224 return space_sub(space_subber, '\n%s\n' % script).strip()
225
226 return jsmin
227
228 jsmin = _make_jsmin()
229
230
231 def jsmin_for_posers(script):
232 r"""
233 Minify javascript based on `jsmin.c by Douglas Crockford`_\.
234
235 Instead of parsing the stream char by char, it uses a regular
236 expression approach which minifies the whole script with one big
237 substitution regex.
238
239 .. _jsmin.c by Douglas Crockford:
240 http://www.crockford.com/javascript/jsmin.c
241
242 :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
244 vanish any time. Use the `jsmin` function instead.
245
246 :Parameters:
247 `script` : ``str``
248 Script to minify
249
250 :Return: Minified script
251 :Rtype: ``str``
252 """
253 def subber(match):
254 """ Substitution callback """
255 groups = match.groups()
256 return (
257 groups[0] or
258 groups[1] or
259 groups[2] or
260 groups[3] or
261 (groups[4] and '\n') or
262 (groups[5] and ' ') or
263 (groups[6] and ' ') or
264 (groups[7] and ' ') or
265 '')
266
267 return _re.sub(
268 r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?'
269 r'\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|'
270 r'\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?{};\r\n])(?'
271 r':[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*'
272 r'(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*'
273 r'[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:('
274 r'?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\['
275 r'\r\n]*)*/)[^\047"/\000-\040]*)|(?<=[\000-#%-,./:-@\[-^`{-~-]return'
276 r')(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/'
277 r'))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:'
278 r'/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?'
279 r':(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/'
280 r'\\\[\r\n]*)*/)[^\047"/\000-\040]*)|(?<=[^\000-!#%&(*,./:-@\[\\^`{|'
281 r'~])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)'
282 r'*/))*(?:((?:(?://[^\r\n]*)?[\r\n]))(?:[\000-\011\013\014\016-\040]'
283 r'|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040"#%-\047)*,./'
284 r':-@\\-^`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\013\01'
285 r'4\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=[^\000-#%-,./:'
286 r'-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*'
287 r'\*+(?:[^/*][^*]*\*+)*/)))+(?=\+)|(?<=-)((?:[\000-\011\013\014\016-'
288 r'\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=-)|(?:[\000-\011\013'
289 r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+|(?:(?:(?://[^'
290 r'\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^'
291 r'/*][^*]*\*+)*/))*)+', subber, '\n%s\n' % script).strip()
292
293
294 if __name__ == '__main__':
295 import sys as _sys
296 _sys.stdout.write(jsmin(_sys.stdin.read()))
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/devtools/scripts/optimize_png_images.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698