Index: src/inspector/build/rjsmin.py |
diff --git a/src/inspector/build/rjsmin.py b/src/inspector/build/rjsmin.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..8357a6dcc10e571388e1f579676d8c2dce0e9e04 |
--- /dev/null |
+++ b/src/inspector/build/rjsmin.py |
@@ -0,0 +1,295 @@ |
+#!/usr/bin/env python |
+# |
+# Copyright 2011 - 2013 |
+# Andr\xe9 Malo or his licensors, as applicable |
+# |
+# Licensed under the Apache License, Version 2.0 (the "License"); |
+# you may not use this file except in compliance with the License. |
+# You may obtain a copy of the License at |
+# |
+# http://www.apache.org/licenses/LICENSE-2.0 |
+# |
+# Unless required by applicable law or agreed to in writing, software |
+# distributed under the License is distributed on an "AS IS" BASIS, |
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+# See the License for the specific language governing permissions and |
+# limitations under the License. |
+r""" |
+===================== |
+ Javascript Minifier |
+===================== |
+ |
+rJSmin is a javascript minifier written in python. |
+ |
+The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\. |
+ |
+The module is a re-implementation aiming for speed, so it can be used at |
+runtime (rather than during a preprocessing step). Usually it produces the |
+same results as the original ``jsmin.c``. It differs in the following ways: |
+ |
+- there is no error detection: unterminated string, regex and comment |
+ literals are treated as regular javascript code and minified as such. |
+- Control characters inside string and regex literals are left untouched; they |
+ are not converted to spaces (nor to \n) |
+- Newline characters are not allowed inside string and regex literals, except |
+ for line continuations in string literals (ECMA-5). |
+- "return /regex/" is recognized correctly. |
+- "+ +" and "- -" sequences are not collapsed to '++' or '--' |
+- Newlines before ! operators are removed more sensibly |
+- rJSmin does not handle streams, but only complete strings. (However, the |
+ module provides a "streamy" interface). |
+ |
+Since most parts of the logic are handled by the regex engine it's way |
+faster than the original python port of ``jsmin.c`` by Baruch Even. The speed |
+factor varies between about 6 and 55 depending on input and python version |
+(it gets faster the more compressed the input already is). Compared to the |
+speed-refactored python port by Dave St.Germain the performance gain is less |
+dramatic but still between 1.2 and 7. See the docs/BENCHMARKS file for |
+details. |
+ |
+rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more. |
+ |
+Both python 2 and python 3 are supported. |
+ |
+.. _jsmin.c by Douglas Crockford: |
+ http://www.crockford.com/javascript/jsmin.c |
+""" |
+__author__ = "Andr\xe9 Malo" |
+__author__ = getattr(__author__, 'decode', lambda x: __author__)('latin-1') |
+__docformat__ = "restructuredtext en" |
+__license__ = "Apache License, Version 2.0" |
+__version__ = '1.0.7' |
+__all__ = ['jsmin'] |
+ |
+import re as _re |
+ |
+ |
+def _make_jsmin(python_only=False): |
+ """ |
+ Generate JS minifier based on `jsmin.c by Douglas Crockford`_ |
+ |
+ .. _jsmin.c by Douglas Crockford: |
+ http://www.crockford.com/javascript/jsmin.c |
+ |
+ :Parameters: |
+ `python_only` : ``bool`` |
+ Use only the python variant. If true, the c extension is not even |
+ tried to be loaded. |
+ |
+ :Return: Minifier |
+ :Rtype: ``callable`` |
+ """ |
+ # pylint: disable = R0912, R0914, W0612 |
+ if not python_only: |
+ try: |
+ import _rjsmin |
+ except ImportError: |
+ pass |
+ else: |
+ return _rjsmin.jsmin |
+ try: |
+ xrange |
+ except NameError: |
+ xrange = range # pylint: disable = W0622 |
+ |
+ space_chars = r'[\000-\011\013\014\016-\040]' |
+ |
+ line_comment = r'(?://[^\r\n]*)' |
+ space_comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)' |
+ string1 = \ |
+ r'(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^\047\\\r\n]*)*\047)' |
+ string2 = r'(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^"\\\r\n]*)*")' |
+ strings = r'(?:%s|%s)' % (string1, string2) |
+ |
+ charclass = r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])' |
+ nospecial = r'[^/\\\[\r\n]' |
+ regex = r'(?:/(?![\r\n/*])%s*(?:(?:\\[^\r\n]|%s)%s*)*/)' % ( |
+ nospecial, charclass, nospecial) |
+ space = r'(?:%s|%s)' % (space_chars, space_comment) |
+ newline = r'(?:%s?[\r\n])' % line_comment |
+ |
+ def fix_charclass(result): |
+ """ Fixup string of chars to fit into a regex char class """ |
+ pos = result.find('-') |
+ if pos >= 0: |
+ result = r'%s%s-' % (result[:pos], result[pos + 1:]) |
+ |
+ def sequentize(string): |
+ """ |
+ Notate consecutive characters as sequence |
+ |
+ (1-4 instead of 1234) |
+ """ |
+ first, last, result = None, None, [] |
+ for char in map(ord, string): |
+ if last is None: |
+ first = last = char |
+ elif last + 1 == char: |
+ last = char |
+ else: |
+ result.append((first, last)) |
+ first = last = char |
+ if last is not None: |
+ result.append((first, last)) |
+ return ''.join(['%s%s%s' % ( |
+ chr(first), |
+ last > first + 1 and '-' or '', |
+ last != first and chr(last) or '') for first, last in result]) |
+ |
+ return _re.sub(r'([\000-\040\047])', # for better portability |
+ lambda m: '\\%03o' % ord(m.group(1)), (sequentize(result) |
+ .replace('\\', '\\\\') |
+ .replace('[', '\\[') |
+ .replace(']', '\\]'))) |
+ |
+ def id_literal_(what): |
+ """ Make id_literal like char class """ |
+ match = _re.compile(what).match |
+ result = ''.join([chr(c) for c in xrange(127) if not match(chr(c))]) |
+ return '[^%s]' % fix_charclass(result) |
+ |
+ def not_id_literal_(keep): |
+ """ Make negated id_literal like char class """ |
+ match = _re.compile(id_literal_(keep)).match |
+ result = ''.join([chr(c) for c in xrange(127) if not match(chr(c))]) |
+ return r'[%s]' % fix_charclass(result) |
+ |
+ not_id_literal = not_id_literal_(r'[a-zA-Z0-9_$]') |
+ preregex1 = r'[(,=:\[!&|?{};\r\n]' |
+ preregex2 = r'%(not_id_literal)sreturn' % locals() |
+ |
+ id_literal = id_literal_(r'[a-zA-Z0-9_$]') |
+ id_literal_open = id_literal_(r'[a-zA-Z0-9_${\[(!+-]') |
+ id_literal_close = id_literal_(r'[a-zA-Z0-9_$}\])"\047+-]') |
+ |
+ dull = r'[^\047"/\000-\040]' |
+ |
+ space_sub = _re.compile(( |
+ r'(%(dull)s+)' |
+ r'|(%(strings)s%(dull)s*)' |
+ r'|(?<=%(preregex1)s)' |
+ r'%(space)s*(?:%(newline)s%(space)s*)*' |
+ r'(%(regex)s%(dull)s*)' |
+ r'|(?<=%(preregex2)s)' |
+ r'%(space)s*(?:%(newline)s%(space)s)*' |
+ r'(%(regex)s%(dull)s*)' |
+ r'|(?<=%(id_literal_close)s)' |
+ r'%(space)s*(?:(%(newline)s)%(space)s*)+' |
+ r'(?=%(id_literal_open)s)' |
+ r'|(?<=%(id_literal)s)(%(space)s)+(?=%(id_literal)s)' |
+ r'|(?<=\+)(%(space)s)+(?=\+)' |
+ r'|(?<=-)(%(space)s)+(?=-)' |
+ r'|%(space)s+' |
+ r'|(?:%(newline)s%(space)s*)+') % locals()).sub |
+ #print space_sub.__self__.pattern |
+ |
+ def space_subber(match): |
+ """ Substitution callback """ |
+ # pylint: disable = C0321, R0911 |
+ groups = match.groups() |
+ if groups[0]: |
+ return groups[0] |
+ elif groups[1]: |
+ return groups[1] |
+ elif groups[2]: |
+ return groups[2] |
+ elif groups[3]: |
+ return groups[3] |
+ elif groups[4]: |
+ return '\n' |
+ elif groups[5] or groups[6] or groups[7]: |
+ return ' ' |
+ else: |
+ return '' |
+ |
+ def jsmin(script): # pylint: disable = W0621 |
+ r""" |
+ Minify javascript based on `jsmin.c by Douglas Crockford`_\. |
+ |
+ Instead of parsing the stream char by char, it uses a regular |
+ expression approach which minifies the whole script with one big |
+ substitution regex. |
+ |
+ .. _jsmin.c by Douglas Crockford: |
+ http://www.crockford.com/javascript/jsmin.c |
+ |
+ :Parameters: |
+ `script` : ``str`` |
+ Script to minify |
+ |
+ :Return: Minified script |
+ :Rtype: ``str`` |
+ """ |
+ return space_sub(space_subber, '\n%s\n' % script).strip() |
+ |
+ return jsmin |
+ |
+jsmin = _make_jsmin() |
+ |
+ |
+def jsmin_for_posers(script): |
+ r""" |
+ Minify javascript based on `jsmin.c by Douglas Crockford`_\. |
+ |
+ Instead of parsing the stream char by char, it uses a regular |
+ expression approach which minifies the whole script with one big |
+ substitution regex. |
+ |
+ .. _jsmin.c by Douglas Crockford: |
+ http://www.crockford.com/javascript/jsmin.c |
+ |
+ :Warning: This function is the digest of a _make_jsmin() call. It just |
+ utilizes the resulting regex. It's just for fun here and may |
+ vanish any time. Use the `jsmin` function instead. |
+ |
+ :Parameters: |
+ `script` : ``str`` |
+ Script to minify |
+ |
+ :Return: Minified script |
+ :Rtype: ``str`` |
+ """ |
+ def subber(match): |
+ """ Substitution callback """ |
+ groups = match.groups() |
+ return ( |
+ groups[0] or |
+ groups[1] or |
+ groups[2] or |
+ groups[3] or |
+ (groups[4] and '\n') or |
+ (groups[5] and ' ') or |
+ (groups[6] and ' ') or |
+ (groups[7] and ' ') or |
+ '') |
+ |
+ return _re.sub( |
+ r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?' |
+ r'\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|' |
+ r'\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?{};\r\n])(?' |
+ r':[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*' |
+ r'(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*' |
+ r'[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(' |
+ r'?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[' |
+ r'\r\n]*)*/)[^\047"/\000-\040]*)|(?<=[\000-#%-,./:-@\[-^`{-~-]return' |
+ r')(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/' |
+ r'))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:' |
+ r'/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?' |
+ r':(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/' |
+ r'\\\[\r\n]*)*/)[^\047"/\000-\040]*)|(?<=[^\000-!#%&(*,./:-@\[\\^`{|' |
+ r'~])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)' |
+ r'*/))*(?:((?:(?://[^\r\n]*)?[\r\n]))(?:[\000-\011\013\014\016-\040]' |
+ r'|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040"#%-\047)*,./' |
+ r':-@\\-^`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\013\01' |
+ r'4\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=[^\000-#%-,./:' |
+ r'-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*' |
+ r'\*+(?:[^/*][^*]*\*+)*/)))+(?=\+)|(?<=-)((?:[\000-\011\013\014\016-' |
+ r'\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=-)|(?:[\000-\011\013' |
+ r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+|(?:(?:(?://[^' |
+ r'\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^' |
+ r'/*][^*]*\*+)*/))*)+', subber, '\n%s\n' % script).strip() |
+ |
+ |
+if __name__ == '__main__': |
+ import sys as _sys |
+ _sys.stdout.write(jsmin(_sys.stdin.read())) |