| 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 |