• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

src/H03-May-2022-6,1584,546

CHANGESH A D26-Mar-20133.1 KiB11694

MANIFEST.inH A D07-May-201126 11

PKG-INFOH A D26-Mar-201312 KiB344277

README.rstH A D21-May-20125.9 KiB212169

setup.cfgH A D26-Mar-201359 64

setup.pyH A D03-May-20221.6 KiB5948

README.rst

1::
2
3      _____ _      _____ __  __ _____ _______
4     / ____| |    |_   _|  \/  |_   _|__   __|
5    | (___ | |      | | | \  / | | |    | |
6     \___ \| |      | | | |\/| | | |    | |
7     ____) | |____ _| |_| |  | |_| |_   | |
8    |_____/|______|_____|_|  |_|_____|  |_|
9
10
11Welcome to SlimIt
12==================================
13
14`SlimIt` is a JavaScript minifier written in Python.
15It compiles JavaScript into more compact code so that it downloads
16and runs faster.
17
18`SlimIt` also provides a library that includes a JavaScript parser,
19lexer, pretty printer and a tree visitor.
20
21`http://slimit.readthedocs.org/ <http://slimit.readthedocs.org/>`_
22
23Installation
24------------
25
26::
27
28    $ [sudo] pip install slimit
29
30Or the bleeding edge version from the git master branch:
31
32::
33
34    $ [sudo] pip install git+https://github.com/rspivak/slimit.git#egg=slimit
35
36
37There is also an official DEB package available at
38`http://packages.debian.org/sid/slimit <http://packages.debian.org/sid/slimit>`_
39
40
41Let's minify some code
42----------------------
43
44From the command line:
45
46::
47
48    $ slimit -h
49    Usage: slimit [options] [input file]
50
51    If no input file is provided STDIN is used by default.
52    Minified JavaScript code is printed to STDOUT.
53
54    Options:
55      -h, --help            show this help message and exit
56      -m, --mangle          mangle names
57      -t, --mangle-toplevel
58                            mangle top level scope (defaults to False)
59
60    $ cat test.js
61    var foo = function( obj ) {
62            for ( var name in obj ) {
63                    return false;
64            }
65            return true;
66    };
67    $
68    $ slimit --mangle < test.js
69    var foo=function(a){for(var b in a)return false;return true;};
70
71Or using library API:
72
73>>> from slimit import minify
74>>> text = """
75... var foo = function( obj ) {
76...         for ( var name in obj ) {
77...                 return false;
78...         }
79...         return true;
80... };
81... """
82>>> print minify(text, mangle=True, mangle_toplevel=True)
83var a=function(a){for(var b in a)return false;return true;};
84
85
86Iterate over, modify a JavaScript AST and pretty print it
87---------------------------------------------------------
88
89>>> from slimit.parser import Parser
90>>> from slimit.visitors import nodevisitor
91>>> from slimit import ast
92>>>
93>>> parser = Parser()
94>>> tree = parser.parse('for(var i=0; i<10; i++) {var x=5+i;}')
95>>> for node in nodevisitor.visit(tree):
96...     if isinstance(node, ast.Identifier) and node.value == 'i':
97...         node.value = 'hello'
98...
99>>> print tree.to_ecma() # print awesome javascript :)
100for (var hello = 0; hello < 10; hello++) {
101  var x = 5 + hello;
102}
103>>>
104
105Writing custom node visitor
106---------------------------
107
108>>> from slimit.parser import Parser
109>>> from slimit.visitors.nodevisitor import ASTVisitor
110>>>
111>>> text = """
112... var x = {
113...     "key1": "value1",
114...     "key2": "value2"
115... };
116... """
117>>>
118>>> class MyVisitor(ASTVisitor):
119...     def visit_Object(self, node):
120...         """Visit object literal."""
121...         for prop in node:
122...             left, right = prop.left, prop.right
123...             print 'Property key=%s, value=%s' % (left.value, right.value)
124...             # visit all children in turn
125...             self.visit(prop)
126...
127>>>
128>>> parser = Parser()
129>>> tree = parser.parse(text)
130>>> visitor = MyVisitor()
131>>> visitor.visit(tree)
132Property key="key1", value="value1"
133Property key="key2", value="value2"
134
135Using lexer in your project
136---------------------------
137
138>>> from slimit.lexer import Lexer
139>>> lexer = Lexer()
140>>> lexer.input('a = 1;')
141>>> for token in lexer:
142...     print token
143...
144LexToken(ID,'a',1,0)
145LexToken(EQ,'=',1,2)
146LexToken(NUMBER,'1',1,4)
147LexToken(SEMI,';',1,5)
148
149You can get one token at a time using ``token`` method:
150
151>>> lexer.input('a = 1;')
152>>> while True:
153...     token = lexer.token()
154...     if not token:
155...         break
156...     print token
157...
158LexToken(ID,'a',1,0)
159LexToken(EQ,'=',1,2)
160LexToken(NUMBER,'1',1,4)
161LexToken(SEMI,';',1,5)
162
163`LexToken` instance has different attributes:
164
165>>> lexer.input('a = 1;')
166>>> token = lexer.token()
167>>> token.type, token.value, token.lineno, token.lexpos
168('ID', 'a', 1, 0)
169
170Benchmarks
171----------
172
173**SAM** - JQuery size after minification in bytes (the smaller number the better)
174
175+-------------------------------+------------+------------+------------+
176| Original jQuery 1.6.1 (bytes) | SlimIt SAM | rJSmin SAM | jsmin SAM  |
177+===============================+============+============+============+
178| 234,995                       | 94,290     | 134,215    | 134,819    |
179+-------------------------------+------------+------------+------------+
180
181Roadmap
182-------
183- when doing name mangling handle cases with 'eval' and 'with'
184- foo["bar"] ==> foo.bar
185- consecutive declarations: var a = 10; var b = 20; ==> var a=10,b=20;
186- reduce simple constant expressions if the result takes less space:
187  1 +2 * 3 ==> 7
188- IF statement optimizations
189
190  1. if (foo) bar(); else baz(); ==> foo?bar():baz();
191  2. if (!foo) bar(); else baz(); ==> foo?baz():bar();
192  3. if (foo) bar(); ==> foo&&bar();
193  4. if (!foo) bar(); ==> foo||bar();
194  5. if (foo) return bar(); else return baz(); ==> return foo?bar():baz();
195  6. if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}
196
197- remove unreachable code that follows a return, throw, break or
198  continue statement, except function/variable declarations
199- parsing speed improvements
200
201Acknowledgments
202---------------
203- The lexer and parser are built with `PLY <http://www.dabeaz.com/ply/>`_
204- Several test cases and regexes from `jslex <https://bitbucket.org/ned/jslex>`_
205- Some visitor ideas - `pycparser <http://code.google.com/p/pycparser/>`_
206- Many grammar rules are taken from `rkelly <https://github.com/tenderlove/rkelly>`_
207- Name mangling and different optimization ideas - `UglifyJS <https://github.com/mishoo/UglifyJS>`_
208- ASI implementation was inspired by `pyjsparser <http://bitbucket.org/mvantellingen/pyjsparser>`_
209
210License
211-------
212The MIT License (MIT)