seitime-frappe/py/build/bundle.py
Rushabh Mehta 0abfaf1180 version 2
2011-09-07 17:27:20 +05:30

142 lines
3.3 KiB
Python

from minify import JavascriptMinify
class Bundle:
"""
Concatenate, compress and mix (if required) js+css files from build.json
"""
def concat(self, filelist, outfile=None, is_js=False):
"""
Concat css and js files into a bundle
"""
import os
from cStringIO import StringIO
from build import verbose
out_type = outfile and outfile.split('.')[-1] or 'js'
temp = StringIO()
for f in filelist:
if verbose:
print f + ' | ' + str(int(os.path.getsize(f)/1024)) + 'k'
fh = open(f)
# get file type
ftype = f.split('.')[-1]
# special concat (css inside js)
if is_js and ftype =='css':
css = fh.read()
data = "\nwn.assets.handler.css('%s');\n" % css.replace("'", "\\'").replace('\n', '\\\n')
# plain concat
else:
data = fh.read() + '\n'
fh.close()
temp.write(data)
if outfile:
f = open(outfile, 'w')
f.write(temp.getvalue())
f.close()
self.timestamps.update(outfile)
if verbose: print 'Wrote %s' % outfile
return temp
def changed(self, files):
"""
Returns true if the files are changed since last build
"""
import os
from build import force_rebuild
if force_rebuild:
return True
for f in files:
if f in self.timestamps.dirty:
return True
return False
def minify(self, in_files, outfile, concat=False):
"""
Compress in_files into outfile,
give some stats
"""
from build import verbose
import os
# concat everything into temp
outtype = outfile.split('.')[-1]
temp = self.concat(in_files, is_js=True)
out = open(outfile, 'w')
org_size = len(temp.getvalue())
temp.seek(0)
# minify
jsm = JavascriptMinify()
jsm.minify(temp, out)
out.close()
self.timestamps.update(outfile)
new_size = os.path.getsize(outfile)
if verbose:
print '=> %s' % outfile
print 'Original: %.2f kB' % (org_size / 1024.0)
print 'Compressed: %.2f kB' % (new_size / 1024.0)
print 'Reduction: %.1f%%' % (float(org_size - new_size) / org_size * 100)
def make(self, path):
"""
Build (stitch + compress) the file defined in build.json
"""
import os, sys, json
from build import no_minify
# open the build.json file and read
# the dict
bfile = open(os.path.join(path, 'build.json'), 'r')
bdata = json.loads(bfile.read())
bfile.close()
for outfile in bdata:
prefix, fname = False, outfile
# check if there is a prefix
if ':' in outfile:
prefix, fname = outfile.split(':')
# build the file list relative to the main folder
fl = [os.path.relpath(os.path.join(path, f), os.curdir) for f in bdata[outfile]]
self.timestamps.bundled += fl
if self.changed(fl):
# js files are minified by default unless explicitly
# mentioned in the prefix.
# some files may not work if minified (known jsmin bug)
if fname.split('.')[-1]=='js' and prefix!='concat' and not no_minify:
self.minify(fl, os.path.relpath(os.path.join(path, fname), os.curdir))
else:
self.concat(fl, os.path.relpath(os.path.join(path, fname), os.curdir))
def bundle(self, timestamps):
"""
Build js files from "build.json"
"""
import os
self.timestamps = timestamps
# walk the parent folder and build all files as defined in the build.json files
for wt in os.walk('.', followlinks=True):
if 'build.json' in wt[2]:
# found build file
self.make(os.path.abspath(wt[0]))