minify/squish.minify.lua

1
local optlex = require "optlex"
2
local optparser = require "optparser"
3
local llex = require "llex"
4
local lparser = require "lparser"
5
 
6
local minify_defaults = {
7
	none = {};
8
	debug = { "whitespace", "locals", "entropy", "comments", "numbers" };
9
	default = { "comments", "whitespace", "emptylines", "numbers", "locals" };
10
	basic = { "comments", "whitespace", "emptylines" };
11
	full = { "comments", "whitespace", "emptylines", "eols", "strings", "numbers", "locals", "entropy" };
12
	}
13
 
14
if opts.minify_level and not minify_defaults[opts.minify_level] then
15
	print_err("Unknown minify level: "..opts.minify_level);
16
	print_err("Available minify levels: none, basic, default, full, debug");
17
end
18
for _, opt in ipairs(minify_defaults[opts.minify_level or "default"] or {}) do
19
	if opts["minify_"..opt] == nil then
20
		opts["minify_"..opt] = true;
21
	end
22
end
23
 
24
local option = {
25
	["opt-locals"] = opts.minify_locals;
26
	["opt-comments"] = opts.minify_comments;
27
	["opt-entropy"] = opts.minify_entropy;
28
	["opt-whitespace"] = opts.minify_whitespace;
29
	["opt-emptylines"] = opts.minify_emptylines;
30
	["opt-eols"] = opts.minify_eols;
31
	["opt-strings"] = opts.minify_strings;
32
	["opt-numbers"] = opts.minify_numbers;
33
	}
34
 
35
local function die(msg)
36
  print_err("minify: "..msg); os.exit(1);
37
end
38
 
39
local function load_file(fname)
40
  local INF = io.open(fname, "rb")
41
  if not INF then die("cannot open \""..fname.."\" for reading") end
42
  local dat = INF:read("*a")
43
  if not dat then die("cannot read from \""..fname.."\"") end
44
  INF:close()
45
  return dat
46
end
47
 
48
local function save_file(fname, dat)
49
  local OUTF = io.open(fname, "wb")
50
  if not OUTF then die("cannot open \""..fname.."\" for writing") end
51
  local status = OUTF:write(dat)
52
  if not status then die("cannot write to \""..fname.."\"") end
53
  OUTF:close()
54
end
55
 
56
 
57
function minify_string(dat)
58
	llex.init(dat)
59
	llex.llex()
60
	local toklist, seminfolist, toklnlist
61
	= llex.tok, llex.seminfo, llex.tokln
62
	if option["opt-locals"] then
63
		optparser.print = print  -- hack
64
		lparser.init(toklist, seminfolist, toklnlist)
65
		local globalinfo, localinfo = lparser.parser()
66
		optparser.optimize(option, toklist, seminfolist, globalinfo, localinfo)
67
	end
68
	optlex.print = print  -- hack
69
	toklist, seminfolist, toklnlist
70
		= optlex.optimize(option, toklist, seminfolist, toklnlist)
71
	local dat = table.concat(seminfolist)
72
	-- depending on options selected, embedded EOLs in long strings and
73
	-- long comments may not have been translated to \n, tack a warning
74
	if string.find(dat, "\r\n", 1, 1) or
75
		string.find(dat, "\n\r", 1, 1) then
76
		optlex.warn.mixedeol = true
77
	end
78
	return dat;
79
end
80
 
81
function minify_file(srcfl, destfl)
82
	local z = load_file(srcfl);
83
	z = minify_string(z);
84
	save_file(destfl, z);
85
end
86
 
87
if opts.minify ~= false then
88
	print_info("Minifying "..out_fn.."...");
89
	minify_file(out_fn, out_fn);
90
	print_info("OK!");
91
end