-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathminify.py
More file actions
executable file
·111 lines (85 loc) · 3.68 KB
/
minify.py
File metadata and controls
executable file
·111 lines (85 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env python
import argparse
import os
import subprocess
#import rjsmin
#def minify_rjsmin(fp_in, unminified):
# return rjsmin.jsmin(unminified)
def minify_slimit(fp_in, unminified):
return subprocess.check_output(["slimit", "-m", fp_in],
stderr=subprocess.STDOUT
).decode("utf-8")
def minify_yuicompressor(fp_in, unminified):
return subprocess.check_output(["java", "-jar", os.path.expanduser("~/bin/yuicompressor-2.4.8.jar"), fp_in],
stderr=subprocess.STDOUT
).decode("utf-8")
def minify_crimp(fp_in, unminified):
return subprocess.check_output(["crimp", fp_in, "-m"],
stderr=subprocess.STDOUT
).decode("utf-8")
def minify_uglify(fp_in, unminified):
return subprocess.check_output(["uglifyjs", fp_in, "-m", "-c"],
stderr=subprocess.STDOUT
).decode("utf-8")
minifiers = [
# used for static/js/sh
{ "name": "slimit", "func": minify_slimit, "count": 0, "errors": 0 },
# used for static/js
{ "name": "uglify", "func": minify_uglify, "count": 0, "errors": 0 },
# used for static/css
{ "name": "yuicompressor", "func": minify_yuicompressor, "count": 0, "errors": 0 },
# not giving any useful results
#{ "name": "rjsmin", "func": minify_rjsmin, "count": 0, "errors": 0 },
#{ "name": "crimp", "func": minify_crimp, "count": 0, "errors": 0 },
]
saved = 0
def minify_file(fp_in, fp_out):
global saved
with open(fp_in, "r") as f:
unminified = f.read()
minified = ""
unminified_lines = unminified.split("\n")
if unminified_lines[0].startswith("// @license"):
minified += unminified_lines[0] + "\n"
mini = ""
mini_select = None
for i, f in enumerate(minifiers):
try:
m = f["func"](fp_in, unminified)
print(fp_in + " with " + f["name"] + " at " + str(len(m)))
if (len(mini) == 0) or (len(m) < len(mini)):
mini = m
mini_select = i
except Exception as e:
print("could not convert " + fp_in + " with " + f["name"])
#print(e)
f["errors"] += 1
if len(mini) == 0:
print("ERROR: could not convert " + fp_in)
return
minifiers[mini_select]["count"] += 1
print(fp_in + " used " + minifiers[mini_select]["name"] + " at " + str(len(mini)))
minified += mini
if unminified_lines[-2].startswith("// @license"):
minified += "\n" + unminified_lines[-2] + "\n"
minified = "\n".join([line for line in minified.split("\n") if len(line) > 0])
saved += len(unminified) - len(minified)
with open(fp_out, "w") as f:
f.write(minified)
def minify_dir(dirpath, extension):
for filename in os.listdir(dirpath):
if filename.endswith(extension) and not filename.endswith(".min" + extension):
fp_in = os.path.join(dirpath, filename)
fp_out = os.path.splitext(fp_in)[0] + ".min" + extension
print("minify " + fp_in + " to " + fp_out)
minify_file(fp_in, fp_out)
print()
for f in minifiers:
print(f["name"] + " count=" + str(f["count"]) + " errors=" + str(f["errors"]))
print("saved " + str(saved) + " bytes")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--extension", help="file extension (start with .)", default=".js")
parser.add_argument("directory", help="working directory", default=".")
args = parser.parse_args()
minify_dir(args.directory, args.extension)