diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/Scripts/jsmin.py | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz |
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/Scripts/jsmin.py')
-rw-r--r-- | Source/JavaScriptCore/Scripts/jsmin.py | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/Scripts/jsmin.py b/Source/JavaScriptCore/Scripts/jsmin.py new file mode 100644 index 000000000..372418b4d --- /dev/null +++ b/Source/JavaScriptCore/Scripts/jsmin.py @@ -0,0 +1,238 @@ +# This code is original from jsmin by Douglas Crockford, it was translated to +# Python by Baruch Even. It was rewritten by Dave St.Germain for speed. +# +# The MIT License (MIT) +# +# Copyright (c) 2013 Dave St.Germain +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +import sys +is_3 = sys.version_info >= (3, 0) +if is_3: + import io +else: + import StringIO + try: + import cStringIO + except ImportError: + cStringIO = None + + +__all__ = ['jsmin', 'JavascriptMinify'] +__version__ = '2.0.9' + + +def jsmin(js): + """ + returns a minified version of the javascript string + """ + if not is_3: + if cStringIO and not isinstance(js, unicode): + # strings can use cStringIO for a 3x performance + # improvement, but unicode (in python2) cannot + klass = cStringIO.StringIO + else: + klass = StringIO.StringIO + else: + klass = io.StringIO + ins = klass(js) + outs = klass() + JavascriptMinify(ins, outs).minify() + return outs.getvalue() + + +class JavascriptMinify(object): + """ + Minify an input stream of javascript, writing + to an output stream + """ + + def __init__(self, instream=None, outstream=None): + self.ins = instream + self.outs = outstream + + def minify(self, instream=None, outstream=None): + if instream and outstream: + self.ins, self.outs = instream, outstream + + self.is_return = False + self.return_buf = '' + + def write(char): + # all of this is to support literal regular expressions. + # sigh + if char in 'return': + self.return_buf += char + self.is_return = self.return_buf == 'return' + self.outs.write(char) + if self.is_return: + self.return_buf = '' + + read = self.ins.read + + space_strings = "abcdefghijklmnopqrstuvwxyz"\ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$\\" + starters, enders = '{[(+-', '}])+-"\'' + newlinestart_strings = starters + space_strings + newlineend_strings = enders + space_strings + do_newline = False + do_space = False + escape_slash_count = 0 + doing_single_comment = False + previous_before_comment = '' + doing_multi_comment = False + in_re = False + in_quote = '' + quote_buf = [] + + previous = read(1) + if previous == '\\': + escape_slash_count += 1 + next1 = read(1) + if previous == '/': + if next1 == '/': + doing_single_comment = True + elif next1 == '*': + doing_multi_comment = True + previous = next1 + next1 = read(1) + else: + write(previous) + elif not previous: + return + elif previous >= '!': + if previous in "'\"": + in_quote = previous + write(previous) + previous_non_space = previous + else: + previous_non_space = ' ' + if not next1: + return + + while 1: + next2 = read(1) + if not next2: + last = next1.strip() + if not (doing_single_comment or doing_multi_comment)\ + and last not in ('', '/'): + if in_quote: + write(''.join(quote_buf)) + write(last) + break + if doing_multi_comment: + if next1 == '*' and next2 == '/': + doing_multi_comment = False + next2 = read(1) + elif doing_single_comment: + if next1 in '\r\n': + doing_single_comment = False + while next2 in '\r\n': + next2 = read(1) + if not next2: + break + if previous_before_comment in ')}]': + do_newline = True + elif previous_before_comment in space_strings: + write('\n') + elif in_quote: + quote_buf.append(next1) + + if next1 == in_quote: + numslashes = 0 + for c in reversed(quote_buf[:-1]): + if c != '\\': + break + else: + numslashes += 1 + if numslashes % 2 == 0: + in_quote = '' + write(''.join(quote_buf)) + elif next1 in '\r\n': + if previous_non_space in newlineend_strings \ + or previous_non_space > '~': + while 1: + if next2 < '!': + next2 = read(1) + if not next2: + break + else: + if next2 in newlinestart_strings \ + or next2 > '~' or next2 == '/': + do_newline = True + break + elif next1 < '!' and not in_re: + if (previous_non_space in space_strings \ + or previous_non_space > '~') \ + and (next2 in space_strings or next2 > '~'): + do_space = True + elif previous_non_space in '-+' and next2 == previous_non_space: + # protect against + ++ or - -- sequences + do_space = True + elif self.is_return and next2 == '/': + # returning a regex... + write(' ') + elif next1 == '/': + if do_space: + write(' ') + if in_re: + if previous != '\\' or (not escape_slash_count % 2) or next2 in 'gimy': + in_re = False + write('/') + elif next2 == '/': + doing_single_comment = True + previous_before_comment = previous_non_space + elif next2 == '*': + doing_multi_comment = True + previous = next1 + next1 = next2 + next2 = read(1) + else: + in_re = previous_non_space in '(,=:[?!&|' or self.is_return # literal regular expression + write('/') + else: + if do_space: + do_space = False + write(' ') + if do_newline: + write('\n') + do_newline = False + + write(next1) + if not in_re and next1 in "'\"`": + in_quote = next1 + quote_buf = [] + + previous = next1 + next1 = next2 + + if previous >= '!': + previous_non_space = previous + + if previous == '\\': + escape_slash_count += 1 + else: + escape_slash_count = 0 + +if __name__ == '__main__': + minifier = JavascriptMinify(sys.stdin, sys.stdout) + minifier.minify() + sys.stdout.write('\n') |