1b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang#!/usr/bin/env python 2b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 3b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# This code is original from jsmin by Douglas Crockford, it was translated to 4b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# Python by Baruch Even. The original code had the following copyright and 5b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# license. 6b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# 7b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# /* jsmin.c 8b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# 2007-05-22 9b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# 10b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# Copyright (c) 2002 Douglas Crockford (www.crockford.com) 11b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# 12b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# Permission is hereby granted, free of charge, to any person obtaining a copy of 13b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# this software and associated documentation files (the "Software"), to deal in 14b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# the Software without restriction, including without limitation the rights to 15b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 16b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# of the Software, and to permit persons to whom the Software is furnished to do 17b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# so, subject to the following conditions: 18b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# 19b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# The above copyright notice and this permission notice shall be included in all 20b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# copies or substantial portions of the Software. 21b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# 22b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# The Software shall be used for Good, not Evil. 23b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# 24b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# SOFTWARE. 31b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# */ 32b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 33b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang# imports adjusted for speed (cStringIO) and python 3 (io) -- nd 34b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wangtry: 35b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang from cStringIO import StringIO 36b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wangexcept ImportError: 37b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang try: 38b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang from StringIO import StringIO 39b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang except ImportError: 40b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang from io import StringIO 41b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 42b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 43b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wangdef jsmin(js): 44b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang ins = StringIO(js) 45b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang outs = StringIO() 46b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang JavascriptMinify().minify(ins, outs) 47b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang str = outs.getvalue() 48b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if len(str) > 0 and str[0] == '\n': 49b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang str = str[1:] 50b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang return str 51b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 52b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wangdef isAlphanum(c): 53b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang """return true if the character is a letter, digit, underscore, 54b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang dollar sign, or non-ASCII character. 55b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang """ 56b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang return ((c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or 57b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang (c >= 'A' and c <= 'Z') or c == '_' or c == '$' or c == '\\' or (c is not None and ord(c) > 126)); 58b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 59b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wangclass UnterminatedComment(Exception): 60b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang pass 61b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 62b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wangclass UnterminatedStringLiteral(Exception): 63b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang pass 64b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 65b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wangclass UnterminatedRegularExpression(Exception): 66b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang pass 67b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 68b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wangclass JavascriptMinify(object): 69b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 70b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang def _outA(self): 71b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.outstream.write(self.theA) 72b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang def _outB(self): 73b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.outstream.write(self.theB) 74b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 75b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang def _get(self): 76b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang """return the next character from stdin. Watch out for lookahead. If 77b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang the character is a control character, translate it to a space or 78b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang linefeed. 79b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang """ 80b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang c = self.theLookahead 81b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theLookahead = None 82b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if c == None: 83b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang c = self.instream.read(1) 84b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if c >= ' ' or c == '\n': 85b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang return c 86b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if c == '': # EOF 87b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang return '\000' 88b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if c == '\r': 89b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang return '\n' 90b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang return ' ' 91b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 92b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang def _peek(self): 93b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theLookahead = self._get() 94b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang return self.theLookahead 95b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 96b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang def _next(self): 97b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang """get the next character, excluding comments. peek() is used to see 98b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if an unescaped '/' is followed by a '/' or '*'. 99b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang """ 100b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang c = self._get() 101b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if c == '/' and self.theA != '\\': 102b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang p = self._peek() 103b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if p == '/': 104b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang c = self._get() 105b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang while c > '\n': 106b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang c = self._get() 107b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang return c 108b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if p == '*': 109b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang c = self._get() 110b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang while 1: 111b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang c = self._get() 112b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if c == '*': 113b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self._peek() == '/': 114b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._get() 115b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang return ' ' 116b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if c == '\000': 117b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang raise UnterminatedComment() 118b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 119b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang return c 120b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 121b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang def _action(self, action): 122b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang """do something! What you do is determined by the argument: 123b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 1 Output A. Copy B to A. Get the next B. 124b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 2 Copy B to A. Get the next B. (Delete A). 125b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 3 Get the next B. (Delete B). 126b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang action treats a string as a single character. Wow! 127b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang action recognizes a regular expression if it is preceded by ( or , or =. 128b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang """ 129b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if action <= 1: 130b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._outA() 131b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 132b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if action <= 2: 133b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA = self.theB 134b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self.theA == "'" or self.theA == '"': 135b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang while 1: 136b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._outA() 137b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA = self._get() 138b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self.theA == self.theB: 139b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang break 140b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self.theA <= '\n': 141b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang raise UnterminatedStringLiteral() 142b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self.theA == '\\': 143b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._outA() 144b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA = self._get() 145b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 146b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 147b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if action <= 3: 148b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theB = self._next() 149b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self.theB == '/' and (self.theA == '(' or self.theA == ',' or 150b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA == '=' or self.theA == ':' or 151b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA == '[' or self.theA == '?' or 152b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA == '!' or self.theA == '&' or 153b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA == '|' or self.theA == ';' or 154b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA == '{' or self.theA == '}' or 155b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA == '\n'): 156b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._outA() 157b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._outB() 158b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang while 1: 159b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA = self._get() 160b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self.theA == '/': 161b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang break 162b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang elif self.theA == '\\': 163b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._outA() 164b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA = self._get() 165b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang elif self.theA <= '\n': 166b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang raise UnterminatedRegularExpression() 167b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._outA() 168b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theB = self._next() 169b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 170b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 171b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang def _jsmin(self): 172b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang """Copy the input to the output, deleting the characters which are 173b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang insignificant to JavaScript. Comments will be removed. Tabs will be 174b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang replaced with spaces. Carriage returns will be replaced with linefeeds. 175b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang Most spaces and linefeeds will be removed. 176b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang """ 177b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA = '\n' 178b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(3) 179b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 180b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang while self.theA != '\000': 181b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self.theA == ' ': 182b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if isAlphanum(self.theB): 183b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(1) 184b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang else: 185b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(2) 186b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang elif self.theA == '\n': 187b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self.theB in ['{', '[', '(', '+', '-']: 188b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(1) 189b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang elif self.theB == ' ': 190b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(3) 191b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang else: 192b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if isAlphanum(self.theB): 193b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(1) 194b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang else: 195b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(2) 196b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang else: 197b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self.theB == ' ': 198b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if isAlphanum(self.theA): 199b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(1) 200b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang else: 201b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(3) 202b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang elif self.theB == '\n': 203b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if self.theA in ['}', ']', ')', '+', '-', '"', '\'']: 204b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(1) 205b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang else: 206b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang if isAlphanum(self.theA): 207b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(1) 208b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang else: 209b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(3) 210b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang else: 211b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._action(1) 212b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 213b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang def minify(self, instream, outstream): 214b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.instream = instream 215b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.outstream = outstream 216b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theA = '\n' 217b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theB = None 218b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.theLookahead = None 219b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 220b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self._jsmin() 221b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang self.instream.close() 222b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang 223b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wangif __name__ == '__main__': 224b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang import sys 225b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang jsm = JavascriptMinify() 226b2cf025c7d5cebd43084f38c6c7ff9cc17da428aWei Wang jsm.minify(sys.stdin, sys.stdout) 227