uglify/squish.uglify.lua

changeset 8
f62f83d9dc43
child 36
bbfbc08d568f
equal deleted inserted replaced
7:0db12f8037f7 8:f62f83d9dc43
1 local llex = require "llex"
2
3 local base_char = 128;
4 local keywords = { "and", "break", "do", "else", "elseif",
5 "end", "false", "for", "function", "if",
6 "in", "local", "nil", "not", "or", "repeat",
7 "return", "then", "true", "until", "while" }
8
9 function uglify_file(infile_fn, outfile_fn)
10 local infile, err = io.open(infile_fn);
11 if not infile then
12 print_err("Can't open input file for reading: "..tostring(err));
13 return;
14 end
15
16 local outfile, err = io.open(outfile_fn..".uglified", "w+");
17 if not outfile then
18 print_err("Can't open output file for writing: "..tostring(err));
19 return;
20 end
21
22 local data = infile:read("*a");
23 infile:close();
24
25 local shebang, newdata = data:match("^(#.-\n)(.+)$");
26 local code = newdata or data;
27 if shebang then
28 outfile:write(shebang)
29 end
30
31
32 while base_char + #keywords < 255 and code:find("["..string.char(base_char).."-"..string.char(base_char+#keywords-1).."]") do
33 base_char = base_char + 1;
34 end
35 if base_char == 255 then
36 -- Sorry, can't uglify this file :(
37 -- We /could/ use a multi-byte marker, but that would complicate
38 -- things and lower the compression ratio (there are quite a few
39 -- 2-letter keywords)
40 outfile:write(code);
41 outfile:close();
42 os.rename(outfile_fn..".uglified", outfile_fn);
43 return;
44 end
45
46 local keyword_map_to_char = {}
47 for i, keyword in ipairs(keywords) do
48 keyword_map_to_char[keyword] = string.char(base_char + i);
49 end
50
51 outfile:write("local base_char,keywords=", tostring(base_char), ",{");
52 for _, keyword in ipairs(keywords) do
53 outfile:write('"', keyword, '",');
54 end
55 outfile:write[[}; function prettify(code) return code:gsub("["..string.char(base_char).."-"..string.char(base_char+#keywords).."]",
56 function (c) return keywords[c:byte()-base_char]; end) end ]]
57
58 -- Write loadstring and open string
59 local maxequals = 0;
60 data:gsub("(=+)", function (equals_string) maxequals = math.max(maxequals, #equals_string); end);
61
62 outfile:write [[assert(loadstring(prettify]]
63 outfile:write("[", string.rep("=", maxequals+1), "[");
64
65 -- Write code, substituting tokens as we go
66 llex.init(code, "@"..infile_fn);
67 llex.llex()
68 local seminfo = llex.seminfo;
69 for k,v in ipairs(llex.tok) do
70 if v == "TK_KEYWORD" then
71 local keyword_char = keyword_map_to_char[seminfo[k]];
72 if keyword_char then
73 outfile:write(keyword_char);
74 else -- Those who think Lua shouldn't have 'continue, fix this please :)
75 outfile:write(seminfo[k]);
76 end
77 else
78 outfile:write(seminfo[k]);
79 end
80 end
81
82 -- Close string/functions
83 outfile:write("]", string.rep("=", maxequals+1), "]");
84 outfile:write("))()");
85 outfile:close();
86 os.rename(outfile_fn..".uglified", outfile_fn);
87 end
88
89 if opts.uglify then
90 print_info("Uglifying "..out_fn.."...");
91 uglify_file(out_fn, out_fn);
92 print_info("OK!");
93 end
94

mercurial