#!/usr/bin/python2.7 # Compresses the Blockscad files into a single javascript file. # ''' Copyright (C) 2014-2015 H3XL, Inc This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ''' import errno, httplib, json, os, re, subprocess, sys, threading, urllib # Define the parameters for the POST request and encode them in # a URL-safe format. HEADER = ('// Do not edit this file; automatically generated by blockscad_build.py.\n' '"use strict";'); class Gen_compressed(threading.Thread): """Generate a JavaScript file that contains all of Blockly's core and all required parts of Closure, compiled together. Uses the Closure Compiler's online API. Runs in a separate thread. """ def __init__(self, search_paths): threading.Thread.__init__(self) self.search_paths = search_paths def run(self): self.gen_blockscad() self.gen_viewer() def gen_blockscad(self): target_filename = 'blockscad_compressed.js' # Define the parameters for the POST request. params = [ ('compilation_level', 'SIMPLE_OPTIMIZATIONS'), ('output_format', 'json'), ('language', 'ECMASCRIPT5'), ('output_info', 'compiled_code'), ('output_info', 'warnings'), ('output_info', 'errors'), ('output_info', 'statistics'), ] # Read in all the source files. filenames = ['bsPage.js','storage.js','utils.js','blockscad.js', 'text.js','lightgl.js','toolbox.js','deflate.js', 'stl.js'] for filename in filenames: f = open(filename) print filename params.append(('js_code', ''.join(f.readlines()))) f.close() self.do_compile(params, target_filename, filenames, '') def gen_viewer(self): target_filename = 'viewer_compressed.js' # Define the parameters for the POST request. params = [ ('compilation_level', 'SIMPLE_OPTIMIZATIONS'), ('output_format', 'json'), ('language', 'ECMASCRIPT5'), ('output_info', 'compiled_code'), ('output_info', 'warnings'), ('output_info', 'errors'), ('output_info', 'statistics'), ] # Read in all the source files. filenames = ['viewer.js', 'csg.js', 'formats.js'] for filename in filenames: f = open(filename) print filename params.append(('js_code', ''.join(f.readlines()))) f.close() self.do_compile(params, target_filename, filenames, '') def do_compile(self, params, target_filename, filenames, remove): # Send the request to Google. headers = {'Content-type': 'application/x-www-form-urlencoded'} conn = httplib.HTTPConnection('closure-compiler.appspot.com') conn.request('POST', '/compile', urllib.urlencode(params), headers) response = conn.getresponse() json_str = response.read() conn.close() # Parse the JSON response. json_data = json.loads(json_str) def file_lookup(name): if not name.startswith('Input_'): return '???' n = int(name[6:]) return filenames[n] if json_data.has_key('serverErrors'): errors = json_data['serverErrors'] for error in errors: print('SERVER ERROR: %s' % target_filename) print(error['error']) elif json_data.has_key('errors'): errors = json_data['errors'] for error in errors: print('FATAL ERROR') print(error['error']) if error['file']: print('%s at line %d:' % ( file_lookup(error['file']), error['lineno'])) print(error['line']) print((' ' * error['charno']) + '^') sys.exit(1) else: if json_data.has_key('warnings'): warnings = json_data['warnings'] for warning in warnings: print('WARNING') print(warning['warning']) if warning['file']: print('%s at line %d:' % ( file_lookup(warning['file']), warning['lineno'])) print(warning['line']) print((' ' * warning['charno']) + '^') print() if not json_data.has_key('compiledCode'): print('FATAL ERROR: Compiler did not return compiledCode.') sys.exit(1) code = HEADER + '\n' + json_data['compiledCode'] # code = code.replace(remove, '') stats = json_data['statistics'] original_b = stats['originalSize'] compressed_b = stats['compressedSize'] if original_b > 0 and compressed_b > 0: f = open(target_filename, 'w') f.write(code) f.close() original_kb = int(original_b / 1024 + 0.5) compressed_kb = int(compressed_b / 1024 + 0.5) ratio = int(float(compressed_b) / float(original_b) * 100 + 0.5) print('SUCCESS: ' + target_filename) print('Size changed from %d KB to %d KB (%d%%).' % ( original_kb, compressed_kb, ratio)) else: print('UNKNOWN ERROR') def file_lookup(name): if not name.startswith('Input_'): return '???' n = int(name[6:]) return filenames[n] if __name__ == '__main__': Gen_compressed('').start()