uglify/squish.uglify.lua

Wed, 10 Feb 2016 12:33:42 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Wed, 10 Feb 2016 12:33:42 +0000
changeset 92
55e927a6c228
parent 72
00d72b0f2e7c
child 96
7d6070e5a096
permissions
-rw-r--r--

uglify: Ensure prettified code inherits the current environment, instead of the default global environment

8
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 local llex = require "llex"
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 local base_char = 128;
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 local keywords = { "and", "break", "do", "else", "elseif",
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 "end", "false", "for", "function", "if",
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 "in", "local", "nil", "not", "or", "repeat",
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 "return", "then", "true", "until", "while" }
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 function uglify_file(infile_fn, outfile_fn)
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 local infile, err = io.open(infile_fn);
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 if not infile then
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 print_err("Can't open input file for reading: "..tostring(err));
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 return;
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 end
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15
72
00d72b0f2e7c squish.uglify.lua: Open output file in binary mode
Matthew Wild <mwild1@gmail.com>
parents: 63
diff changeset
16 local outfile, err = io.open(outfile_fn..".uglified", "wb+");
8
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 if not outfile then
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 print_err("Can't open output file for writing: "..tostring(err));
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 return;
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 end
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22 local data = infile:read("*a");
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 infile:close();
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 local shebang, newdata = data:match("^(#.-\n)(.+)$");
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 local code = newdata or data;
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 if shebang then
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 outfile:write(shebang)
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 end
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31
63
f42b3815ce77 uglify: Fix logic that determines whether we can uglify a file
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
32 while base_char + #keywords <= 255 and code:find("["..string.char(base_char).."-"..string.char(base_char+#keywords-1).."]") do
8
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 base_char = base_char + 1;
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34 end
63
f42b3815ce77 uglify: Fix logic that determines whether we can uglify a file
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
35 if base_char + #keywords > 255 then
8
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 -- Sorry, can't uglify this file :(
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 -- We /could/ use a multi-byte marker, but that would complicate
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38 -- things and lower the compression ratio (there are quite a few
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 -- 2-letter keywords)
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 outfile:write(code);
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 outfile:close();
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 os.rename(outfile_fn..".uglified", outfile_fn);
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 return;
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 end
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 local keyword_map_to_char = {}
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 for i, keyword in ipairs(keywords) do
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 keyword_map_to_char[keyword] = string.char(base_char + i);
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 end
62
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
50
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
51 -- Write loadstring and open string
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
52 local maxequals = 0;
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
53 data:gsub("(=+)", function (equals_string) maxequals = math.max(maxequals, #equals_string); end);
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
54
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
55 -- Go lexer!
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
56 llex.init(code, "@"..infile_fn);
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
57 llex.llex()
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
58 local seminfo = llex.seminfo;
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
59
63
f42b3815ce77 uglify: Fix logic that determines whether we can uglify a file
Matthew Wild <mwild1@gmail.com>
parents: 62
diff changeset
60 if opts.uglify_level == "full" and base_char+#keywords < 255 then
62
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
61 -- Find longest TK_NAME and TK_STRING tokens
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
62 local scores = {};
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
63 for k,v in ipairs(llex.tok) do
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
64 if v == "TK_NAME" or v == "TK_STRING" then
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
65 local key = string.format("%q,%q", v, seminfo[k]);
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
66 if not scores[key] then
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
67 scores[key] = { type = v, value = seminfo[k], count = 0 };
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
68 scores[#scores+1] = scores[key];
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
69 end
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
70 scores[key].count = scores[key].count + 1;
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
71 end
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
72 end
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
73 for i=1,#scores do
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
74 local v = scores[i];
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
75 v.score = (v.count)*(#v.value-1)- #string.format("%q", v.value) - 1;
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
76 end
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
77 table.sort(scores, function (a, b) return a.score > b.score; end);
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
78 local free_space = 255-(base_char+#keywords);
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
79 for i=free_space+1,#scores do
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
80 scores[i] = nil; -- Drop any over the limit
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
81 end
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
82
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
83 local base_keywords_len = #keywords;
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
84 for k,v in ipairs(scores) do
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
85 if v.score > 0 then
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
86 table.insert(keywords, v.value);
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
87 keyword_map_to_char[v.value] = string.char(base_char+base_keywords_len+k);
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
88 end
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
89 end
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
90 end
8
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92 outfile:write("local base_char,keywords=", tostring(base_char), ",{");
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
93 for _, keyword in ipairs(keywords) do
62
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
94 outfile:write(string.format("%q", keyword), ',');
8
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
95 end
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
96 outfile:write[[}; function prettify(code) return code:gsub("["..string.char(base_char).."-"..string.char(base_char+#keywords).."]",
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
97 function (c) return keywords[c:byte()-base_char]; end) end ]]
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
98
92
55e927a6c228 uglify: Ensure prettified code inherits the current environment, instead of the default global environment
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
99 outfile:write [[return setfenv(assert(loadstring(prettify]]
8
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
100 outfile:write("[", string.rep("=", maxequals+1), "[");
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
101
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
102 -- Write code, substituting tokens as we go
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
103 for k,v in ipairs(llex.tok) do
62
15c48274ee1f uglify: Support for uglifying identifiers and string literals too (--uglify-level=full)
Matthew Wild <mwild1@gmail.com>
parents: 56
diff changeset
104 if v == "TK_KEYWORD" or v == "TK_NAME" or v == "TK_STRING" then
8
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
105 local keyword_char = keyword_map_to_char[seminfo[k]];
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106 if keyword_char then
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
107 outfile:write(keyword_char);
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
108 else -- Those who think Lua shouldn't have 'continue, fix this please :)
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
109 outfile:write(seminfo[k]);
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
110 end
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
111 else
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
112 outfile:write(seminfo[k]);
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
113 end
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
114 end
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
115
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
116 -- Close string/functions
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
117 outfile:write("]", string.rep("=", maxequals+1), "]");
92
55e927a6c228 uglify: Ensure prettified code inherits the current environment, instead of the default global environment
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
118 outfile:write(", '@", outfile_fn,"')), getfenv())()");
8
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
119 outfile:close();
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
120 os.rename(outfile_fn..".uglified", outfile_fn);
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
121 end
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
122
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
123 if opts.uglify then
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
124 print_info("Uglifying "..out_fn.."...");
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
125 uglify_file(out_fn, out_fn);
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
126 print_info("OK!");
f62f83d9dc43 uglify: New specialised Lua 'compression' filter
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
127 end

mercurial