def minify(filename, filetype, stream): if ".min" in filename or ".pack" in filename: return stream, 'already minified' if filetype == 'application/javascript': # Remove console statements js = re.sub("console.\\w+\\(.*?\\);?", "", stream.read()) js = jsmin(js) stream = BytesIO(js) elif filetype == 'text/css': css = cssmin(stream.read()) stream = BytesIO(css) return stream, 'minified'
def build_assets(): less() coffee() uglify() cssmin()
from cssmin import * # Minify Js using Closure Compiler os.system('java -jar ~/bin/compiler.jar --js js-enhanced/app-enhanced.js --js_output_file js-enhanced/app-enhanced.min.js') os.system('java -jar ~/bin/compiler.jar --js theme/js/app-basic.js --js_output_file theme/js/app-basic.min.js') # Prepend the Geo Js file to the start of the app-basic js file geo = open('theme/js/geo.min.js') geocontent = geo.read() geo.close() js = open('theme/js/app-basic.min.js') jscontent = js.read() js.close() jsw = open('theme/js/app-basic.min.js', 'w') jsw.write(geocontent + '\n' + jscontent) jsw.close() # Minify Css using the Python cssmin egg csstomin = ['theme/css/basic.css', 'theme/css/enhanced-wide.css', 'theme/css/enhanced.css'] for cssfile in csstomin: content = open(cssfile) outs = cssmin(content.read()) content.close() fout = open(cssfile.replace('.css', '.min.css'), 'w') fout.write(outs + '\n') fout.close()
def main(): parser = OptionParser( usage='usage: %prog [options] src_folder destination_bucket_name prefix' ) (options, args) = parser.parse_args() if len(args) != 3: parser.error("incorrect number of arguments") src_folder = os.path.normpath(args[0]) bucket_name = args[1] prefix = args[2] conn = boto.connect_s3() bucket = conn.get_bucket(bucket_name) DEPLOY_VERSION_FILE = src_folder + '/s3deploy.txt' S3_VERSION_FILE = prefix + '.s3deploy.txt' if bucket.get_key(S3_VERSION_FILE): print 'Deploy version exists' key = bucket.new_key(S3_VERSION_FILE) previous_version = int(key.get_contents_as_string()) version = previous_version + 1 file = open(DEPLOY_VERSION_FILE, 'w') file.write(str(version)) file.close() else: print 'Deploy version doesn\'t exist' file = open(DEPLOY_VERSION_FILE, 'r') version = file.read() key = bucket.new_key(S3_VERSION_FILE) headers = {'Content-Type': 'text/plain', 'x-amz-acl': 'public-read'} content = open(DEPLOY_VERSION_FILE) key.set_contents_from_file(content, headers) namelist = [] for root, dirs, files in os.walk(src_folder): if files and not '.webassets' in root: path = os.path.relpath(root, src_folder) namelist += [ os.path.normpath(os.path.join(path, f)) for f in files ] print 'Uploading %d files to bucket %s' % (len(namelist), bucket.name) replace = {} for name in namelist: type, encoding = mimetypes.guess_type(name) type = type or 'application/octet-stream' if 'image' in type: root = '/' + STATIC_NAME + '/' + name if '@' in name and 'x.' in name: retina = name.split('@')[1].split('x')[0] clean_name = name.replace('@' + retina + 'x', '') key = hashlib.md5(prefix + str(version) + clean_name).hexdigest( ) + '@' + retina + 'x.' + name.split('.')[-1] else: key = hashlib.md5(prefix + str(version) + name).hexdigest() + '.' + name.split('.')[-1] replace[root] = key keys = {'old': [], 'new': []} for name in namelist: if '.DS_Store' not in name and '.scss' not in name: if 'image' in type and '@' in name and 'x.' in name: retina = name.split('@')[1].split('x')[0] clean_name = name.replace('@' + retina + 'x', '') key = hashlib.md5(prefix + str(version) + clean_name).hexdigest( ) + '@' + retina + 'x.' + name.split('.')[-1] else: key = hashlib.md5(prefix + str(version) + name).hexdigest() + '.' + name.split('.')[-1] old_key = hashlib.md5(prefix + str((int(version) - 1)) + name).hexdigest() + '.' + name.split('.')[-1] keys['old'].append(old_key) keys['new'].append(key) content = open(os.path.join(src_folder, name)) key = bucket.new_key(key) expires = datetime.utcnow() + timedelta(days=(25 * 365)) expires = expires.strftime("%a, %d %b %Y %H:%M:%S GMT") type, encoding = mimetypes.guess_type(name) type = type or 'application/octet-stream' headers = { 'Content-Type': type, 'Expires': expires, 'x-amz-acl': 'public-read', 'Cache-Control': 'public, max-age=365000000, immutable' } states = [type] if type == 'application/javascript': outs = StringIO() JavascriptMinify().minify(content, outs) content.close() content = outs.getvalue() if len(content) > 0 and content[0] == '\n': content = content[1:] content = BytesIO(content) states.append('minified') if type == 'text/css': outs = cssmin(content.read()) for k, v in replace.iteritems(): v = CDN_ROOT + v outs = outs.replace(k, v) content.close() content = outs if len(content) > 0 and content[0] == '\n': content = content[1:] content = BytesIO(content) states.append('minified') if type in COMPRESSIBLE: headers['Content-Encoding'] = 'gzip' compressed = StringIO() gz = gzip.GzipFile(filename=name, fileobj=compressed, mode='w') gz.writelines(content) gz.close() content.close content = BytesIO(compressed.getvalue()) states.append('gzipped') states = ', '.join(states) print '- %s => %s (%s)' % (name, key.name, states) key.set_contents_from_file(content, headers) content.close()
) os.system( 'java -jar ~/bin/compiler.jar --js theme/js/app-basic.js --js_output_file theme/js/app-basic.min.js' ) # Prepend the Geo Js file to the start of the app-basic js file geo = open('theme/js/geo.min.js') geocontent = geo.read() geo.close() js = open('theme/js/app-basic.min.js') jscontent = js.read() js.close() jsw = open('theme/js/app-basic.min.js', 'w') jsw.write(geocontent + '\n' + jscontent) jsw.close() # Minify Css using the Python cssmin egg csstomin = [ 'theme/css/basic.css', 'theme/css/enhanced-wide.css', 'theme/css/enhanced.css' ] for cssfile in csstomin: content = open(cssfile) outs = cssmin(content.read()) content.close() fout = open(cssfile.replace('.css', '.min.css'), 'w') fout.write(outs + '\n') fout.close()
def main(): parser = OptionParser(usage='usage: %prog [options] src_folder destination_bucket_name prefix') parser.add_option('-x', '--expires', action='store_true', help='set far future expiry for all files') parser.add_option('-m', '--minify', action='store_true', help='minify javascript files') (options, args) = parser.parse_args() if len(args) != 3: parser.error("incorrect number of arguments") src_folder = os.path.normpath(args[0]) bucket_name = args[1] prefix = args[2] conn = boto.connect_s3() bucket = conn.get_bucket(bucket_name) namelist = [] for root, dirs, files in os.walk(src_folder): if files and not '.svn' in root: path = os.path.relpath(root, src_folder) namelist += [os.path.normpath(os.path.join(path, f)) for f in files] print 'Uploading %d files to bucket %s' % (len(namelist), bucket.name) for name in namelist: content = open(os.path.join(src_folder, name)) key = bucket.new_key(os.path.join(prefix, name)) type, encoding = mimetypes.guess_type(name) type = type or 'application/octet-stream' headers = { 'Content-Type': type, 'x-amz-acl': 'public-read' } states = [type] if options.expires: # We only use HTTP 1.1 headers because they are relative to the time of download # instead of being hardcoded. headers['Cache-Control'] = 'max-age %d' % (3600 * 24 * 365) if options.minify and type == 'application/javascript': outs = StringIO() JavascriptMinify().minify(content, outs) content.close() content = outs.getvalue() if len(content) > 0 and content[0] == '\n': content = content[1:] content = BytesIO(content) states.append('minified') if options.minify and type == 'text/css': outs = cssmin(content.read()) content.close() content = outs if len(content) > 0 and content[0] == '\n': content = content[1:] content = BytesIO(content) states.append('minified') if type in COMPRESSIBLE: headers['Content-Encoding'] = 'gzip' compressed = StringIO() gz = gzip.GzipFile(filename=name, fileobj=compressed, mode='w') gz.writelines(content) gz.close() content.close content = BytesIO(compressed.getvalue()) states.append('gzipped') states = ', '.join(states) print '- %s => %s (%s)' % (name, key.name, states) key.set_contents_from_file(content, headers) content.close();