def make_function_from_file(self,path,file): fp = os.path.splitext(path) basename = fp[0].replace(' ','_').replace('/','_').replace('-','_').replace('.','_').replace('+','_') ext = fp[1][1:] filetype = '' contents = '' if ext=='html': filetype = 'page' elif ext=='css': filetype = 'style' elif ext=='js': filetype = 'script' file_contents = open(os.path.expanduser(file)).read() # minimize javascript, css files if ext == 'js': file_contents = jspacker.jsmin(file_contents) self.compile_js(file_contents) elif ext == 'css': packer = CSSPacker(file_contents) file_contents = packer.pack() data = str(file_contents).encode("hex") method = "dataWithHexString(@\"%s\")" % data return {'method':method,'path':path}
def make_function_from_file(self, path, file): fp = os.path.splitext(path) basename = fp[0].replace(" ", "_").replace("/", "_").replace("-", "_").replace(".", "_").replace("+", "_") ext = fp[1][1:] filetype = "" contents = "" if ext == "html": filetype = "page" elif ext == "css": filetype = "style" elif ext == "js": filetype = "script" file_contents = open(os.path.expanduser(file)).read() # minimize javascript, css files if ext == "js": file_contents = jspacker.jsmin(file_contents) self.compile_js(file_contents) elif ext == "css": packer = CSSPacker(file_contents) file_contents = packer.pack() data = str(file_contents).encode("hex") method = 'dataWithHexString(@"%s")' % data return {"method": method, "path": path}
def make_function_from_file(self,file): fp = os.path.splitext(file) ext = fp[1][1:] thefile = os.path.expanduser(file) file_contents = open(thefile).read() save_off = False parse_modules = True # minimize javascript, css files if ext == 'js': file_contents = jspacker.jsmin(file_contents) save_off = True elif ext == 'css': packer = CSSPacker(file_contents) file_contents = packer.pack() save_off = True parse_modules = False if save_off: of = open(thefile,'w') of.write(file_contents) of.close() print "[DEBUG] compressing: %s" % thefile if parse_modules: # determine which modules this file is using self.extract_modules(file_contents)
def add_compiled_resources(source,target): print "[DEBUG] copy resources from %s to %s" % (source,target) compiled_targets = {} for root, dirs, files in os.walk(source): for name in ignoreDirs: if name in dirs: dirs.remove(name) # don't visit ignored directories for file in files: if file in ignoreFiles: continue prefix = root[len(source):] from_ = os.path.join(root, file) to_ = os.path.expanduser(from_.replace(source, target, 1)) to_directory = os.path.expanduser(os.path.split(to_)[0]) if not os.path.exists(to_directory): os.makedirs(to_directory) fp = os.path.splitext(file) ext = fp[1] if ext == '.jss': continue if len(fp)>1 and write_routing and ext in ['.html','.js','.css']: path = prefix + os.sep + file path = path[1:] entry = {'path':path,'from':from_,'to':to_} if compiled_targets.has_key(ext): compiled_targets[ext].append(entry) else: compiled_targets[ext]=[entry] else: # only copy if different filesize or doesn't exist if not os.path.exists(to_) or os.path.getsize(from_)!=os.path.getsize(to_): print "[DEBUG] copying: %s to %s" % (from_,to_) shutil.copyfile(from_, to_) if compiled_targets.has_key('.html'): compiled = self.process_html_files(compiled_targets,source) if len(compiled) > 0: for c in compiled: from_ = c['from'] to_ = c['to'] path = c['path'] print "[DEBUG] copying: %s to %s" % (from_,to_) file_contents = open(from_).read() file_contents = jspacker.jsmin(file_contents) file_contents = file_contents.replace('Titanium.','Ti.') to = open(to_,'w') to.write(file_contents) to.close() for ext in ('.css','.html'): if compiled_targets.has_key(ext): for css_file in compiled_targets[ext]: from_ = css_file['from'] to_ = css_file['to'] print "[DEBUG] copying: %s to %s" % (from_,to_) if path.endswith('.css'): file_contents = open(from_).read() packer = CSSPacker(file_contents) file_contents = packer.pack() to = open(to_,'w') to.write(file_contents) to.close() else: shutil.copyfile(from_, to_) if compiled_targets.has_key('.js'): for js_file in compiled_targets['.js']: path = js_file['path'] from_ = js_file['from'] to_ = js_file['to'] print "[DEBUG] compiling: %s" % from_ metadata = Compiler.make_function_from_file(path,from_,self) method = metadata['method'] eq = path.replace('.','_') impf.write(' [map setObject:%s forKey:@"%s"];\n' % (method,eq))
def add_compiled_resources(source, target): print "[DEBUG] copy resources from %s to %s" % (source, target) compiled_targets = {} for root, dirs, files in os.walk(source, True, None, True): for name in ignoreDirs: if name in dirs: dirs.remove(name) # don't visit ignored directories for file in files: if file in ignoreFiles: continue prefix = root[len(source):] from_ = to_unicode_or_not(os.path.join(root, file)) to_ = os.path.expanduser(from_.replace(source, target, 1)) to_directory = os.path.expanduser(os.path.split(to_)[0]) if not os.path.exists(to_directory): os.makedirs(to_directory) fp = os.path.splitext(file) ext = fp[1] if ext == '.jss': continue if len(fp) > 1 and ext in ['.html', '.js', '.css']: path = prefix + os.sep + file path = path[1:] entry = {'path': path, 'from': from_, 'to': to_} if compiled_targets.has_key(ext): compiled_targets[ext].append(entry) else: compiled_targets[ext] = [entry] if not write_routing: # only copy if different filesize or doesn't exist if not os.path.exists(to_) or os.path.getsize( from_) != os.path.getsize(to_): print "[DEBUG] copying: %s to %s" % (from_, to_) shutil.copyfile(from_, to_) if compiled_targets.has_key('.html'): compiled = self.process_html_files(compiled_targets, source) if len(compiled) > 0: for c in compiled: from_ = c['from'] to_ = c['to'] path = c['path'] print "[DEBUG] copying: %s to %s" % (from_, to_) file_contents = open(from_).read() file_contents = jspacker.jsmin(file_contents) file_contents = file_contents.replace( 'Titanium.', 'Ti.') to = open(to_, 'w') to.write(file_contents) to.close() for ext in ('.css', '.html'): if compiled_targets.has_key(ext): for css_file in compiled_targets[ext]: from_ = css_file['from'] to_ = css_file['to'] print "[DEBUG] copying: %s to %s" % (from_, to_) if path.endswith('.css'): file_contents = open(from_).read() packer = CSSPacker(file_contents) file_contents = packer.pack() to = open(to_, 'w') to.write(file_contents) to.close() else: shutil.copyfile(from_, to_) if compiled_targets.has_key('.js'): for js_file in compiled_targets['.js']: path = js_file['path'] from_ = js_file['from'] compile_js_file(path, from_)
def csspack(c): return CSSPacker(c).pack()
def __init__(self, project_path, deploytype): start_time = time.time() self.minify = deploytype == "production" self.packages = [] self.project_dependencies = [] # modules that the project uses self.modules_map = {} # all modules including deps => individual module deps self.modules_to_cache = [] # all modules to be baked into require.cache() self.modules_to_load = [] # all modules to be required at load time self.tiplus_modules_to_load = [] # all modules to be required at load time # initialize paths self.sdk_path = os.path.abspath(os.path.dirname(sys._getframe(0).f_code.co_filename)) self.sdk_src_path = os.path.join(self.sdk_path, 'src') self.themes_path = os.path.join(self.sdk_path, 'themes') self.ti_package_path = os.path.join(self.sdk_path, 'titanium') self.modules_path = os.path.abspath(os.path.join(self.sdk_path, '..', '..', '..', '..', 'modules')) self.project_path = project_path self.build_path = os.path.join(project_path, 'build', 'mobileweb') self.resources_path = os.path.join(project_path, 'Resources') self.i18n_path = os.path.join(project_path, 'i18n') self.ti_js_file = os.path.join(self.build_path, 'titanium.js') sdk_version = os.path.basename(os.path.abspath(os.path.join(self.sdk_path, '..'))) print '[INFO] Titanium Mobile Web Compiler v%s' % sdk_version if not os.path.exists(self.project_path): print '[ERROR] Invalid project "%s"' % self.project_path sys.exit(1) # read the package.json self.load_package_json() # register the titanium package self.packages.append({ 'name': self.package_json['name'], 'location': './titanium', 'main': self.package_json['main'] }) # read the tiapp.xml tiapp_xml = TiAppXML(os.path.join(self.project_path, 'tiapp.xml'), deploytype) print '[INFO] Compiling Mobile Web project "%s" [%s]' % (tiapp_xml['name'], deploytype) # create the build directory if os.path.exists(self.build_path): shutil.rmtree(self.build_path, True) try: os.makedirs(self.build_path) except: pass # copy all of the project's resources to the build directory self.copy(self.themes_path, os.path.join(self.build_path, 'themes')) self.copy(self.resources_path, self.build_path, ['android', 'iphone']) self.copy(os.path.join(self.resources_path, 'mobileweb'), self.build_path, ['apple_startup_images', 'splash']) self.copy(os.path.join(self.resources_path, 'mobileweb', 'apple_startup_images', 'Default.jpg'), self.build_path) self.copy(os.path.join(self.resources_path, 'mobileweb', 'apple_startup_images', 'Default-Portrait.jpg'), self.build_path) self.copy(os.path.join(self.resources_path, 'mobileweb', 'apple_startup_images', 'Default-Landscape.jpg'), self.build_path) self.copy(self.ti_package_path, os.path.join(self.build_path, 'titanium')) # scan project for dependencies self.find_project_dependencies() # scan all dependencies for distinct list of modules self.find_modules_to_cache() self.modules_to_cache.append('Ti/_/image') self.modules_to_cache.append('Ti/_/include') if len(tiapp_xml['precache']['requires']): for req in tiapp_xml['precache']['requires']: self.modules_to_cache.append('commonjs:' + req) if len(tiapp_xml['precache']['includes']): for inc in tiapp_xml['precache']['includes']: self.modules_to_cache.append('url:' + inc) # find only the top most modules to be required areDeps = {} for module in self.modules_to_cache: # check if module is a dependent of another module for m in self.modules_map: deps = self.modules_map[m] if module in deps: areDeps[module] = 1 for module in self.modules_map: if not module in areDeps: self.modules_to_load.append(module) # determine theme theme = tiapp_xml['mobileweb']['theme'] if not os.path.exists(os.path.join(self.themes_path, theme)): print '[ERROR] Theme "%s" does not exist' % theme sys.exit(1) # check what we need to precache precache_images = [] if 'Ti/UI/TableViewRow' in self.modules_map: precache_images.append('/themes/' + theme + '/UI/TableViewRow/child.png') if len(tiapp_xml['precache']['images']): for img in tiapp_xml['precache']['images']: precache_images.append(img) # detect Ti+ modules if len(tiapp_xml['modules']): print '[INFO] Locating Ti+ modules...' for module in tiapp_xml['modules']: if module['platform'] in ['', 'mobileweb', 'commonjs']: is_commonjs = False if 'version' in module and module['version']: # search <project dir>/modules/mobileweb/<module>/<version>/ module_dir = os.path.join(self.project_path, 'modules', 'mobileweb', module['id'], module['version']) if not os.path.exists(module_dir): # search <project dir>/modules/commonjs/<module>/<version>/ module_dir = os.path.join(self.project_path, 'modules', 'commonjs', module['id'], module['version']) if os.path.exists(module_dir): is_commonjs = True else: # search <global module dir>/<module>/<version>/ module_dir = os.path.join(self.modules_path, 'mobileweb', module['id'], module['version']) if not os.path.exists(module_dir): # search <global commonjs dir>/<module>/<version>/ module_dir = os.path.join(self.modules_path, 'commonjs', module['id'], module['version']) if os.path.exists(module_dir): is_commonjs = True else: print '[ERROR] Unable to find Ti+ module "%s", v%s' % (module['id'], module['version']) sys.exit(1) else: # no version number, gotta do it the hard way # search <project dir>/modules/mobileweb/<module>/ module_dir = self.locate_module(os.path.join(self.project_path, 'modules', 'mobileweb', module['id'])) if module_dir is None: # search <project dir>/modules/commonjs/<module>/<version>/ module_dir = self.locate_module(os.path.join(self.project_path, 'modules', 'commonjs', module['id'])) if module_dir is not None: is_commonjs = True else: # search <global module dir>/<module>/<version>/ module_dir = self.locate_module(os.path.join(self.modules_path, 'mobileweb', module['id'])) if module_dir is None: # search <global commonjs dir>/<module>/<version>/ module_dir = self.locate_module(os.path.join(self.modules_path, 'commonjs', module['id'])) if module_dir is not None: is_commonjs = True else: print '[ERROR] Unable to find Ti+ module "%s"' % module['id'] sys.exit(1) module_package_json_file = os.path.join(module_dir, 'package.json') if not os.path.exists(module_package_json_file): print '[ERROR] Ti+ module "%s" is invalid: missing package.json' % module['id'] sys.exit(1) module_manifest_file = os.path.join(module_dir, 'manifest') if not os.path.exists(module_manifest_file): print '[ERROR] Ti+ module "%s" is invalid: missing manifest' % module['id'] sys.exit(1) manifest = {} for line in open(module_manifest_file).readlines(): line = line.strip() if line[0:1] == '#': continue if line.find(':') < 0: continue key,value = line.split(':') manifest[key.strip()] = value.strip() if 'minsdk' in manifest and compare_versions(manifest['minsdk'], sdk_version) == 1: print '[ERROR] Ti+ module "%s" requires a minimum SDK version of %s: current version %s' % (module['id'], manifest['minsdk'], sdk_version) sys.exit(1) module_package_json = simplejson.load(codecs.open(module_package_json_file, 'r', 'utf-8')) main_file = module_package_json['main'] if main_file.endswith('.js'): main_file = main_file[:-3] lib = '' if 'directories' in module_package_json and 'lib' in module_package_json['directories']: lib = module_package_json['directories']['lib'] if lib.startswith('/'): lib = lib[1:] main_file_path = os.path.join(module_dir, lib, main_file + '.js') if not os.path.exists(main_file_path): print '[ERROR] Ti+ module "%s" is invalid: missing main "%s"' % (module['id'], main_file_path) sys.exit(1) print '[INFO] Bundling Ti+ module "%s"' % module['id'] self.project_dependencies.append(main_file) module_name = module['id'] if module['id'] != main_file: module_name += '/' + main_file if is_commonjs: self.modules_to_cache.append('commonjs:' + module_name) else: self.modules_to_cache.append(module_name) if not is_commonjs: self.tiplus_modules_to_load.append(module['id']) if len(lib): lib = '/' + lib self.packages.append({ 'name': module['id'], 'location': './' + self.compact_path('modules/' + module['id'] + lib), 'main': main_file, 'root': 1 }) # TODO: need to combine ALL Ti+ module .js files into the titanium.js, not just the main file # TODO: need to combine ALL Ti+ module .css files into the titanium.css # copy entire module directory to build directory shutil.copytree(module_dir, os.path.join(self.build_path, 'modules', module['id'])) # detect circular dependencies for module in self.modules_to_cache: if module in self.modules_map: mydeps = self.modules_map[module] for dep in mydeps: if dep in self.modules_map and module in self.modules_map[dep]: print '[WARN] Circular dependency detected: %s dependent on %s' % (module, dep) print '[INFO] Found %s dependenc%s, %s package%s, %s module%s' % ( len(self.project_dependencies), 'y' if len(self.project_dependencies) == 1 else 'ies', len(self.packages), '' if len(self.packages) == 1 else 's', len(self.modules_to_cache), '' if len(self.project_dependencies) == 1 else 's') # TODO: break up the dependencies into layers # TODO: minify the project's code first app_names = {} locales = [] if os.path.exists(self.i18n_path): print '[INFO] Processing i18n strings...' for dir in os.listdir(self.i18n_path): app = self.load_i18n(os.path.join(self.i18n_path, dir, 'app.xml')) if app is not None and 'appname' in app: app_names[dir] = app['appname'] strings = self.load_i18n(os.path.join(self.i18n_path, dir, 'strings.xml')) if strings is not None: locales.append(dir) locale_path = os.path.join(self.build_path, 'titanium', 'Ti', 'Locale', dir) try: os.makedirs(locale_path) except: pass i18n_file = codecs.open(os.path.join(locale_path, 'i18n.js'), 'w', 'utf-8') i18n_file.write('define(%s);' % simplejson.dumps(strings)) i18n_file.close() if dir in tiapp_xml['precache']['locales']: self.modules_to_cache.append('Ti/Locale/%s/i18n' % dir) # build the titanium.js print '[INFO] Assembling titanium.js...' ti_js = codecs.open(self.ti_js_file, 'w', 'utf-8') ti_js.write(HEADER + '\n') # 1) read in the config.js and fill in the template enableInstrumentation = tiapp_xml['mobileweb']['instrumentation'] == 'true' if 'instrumentation' in tiapp_xml['mobileweb'] else False ti_js.write(AppcTemplate(codecs.open(os.path.join(self.sdk_src_path, 'config.js'), 'r', 'utf-8').read(), input_encoding='utf-8', output_encoding='utf-8').render( app_analytics = tiapp_xml['analytics'], app_copyright = tiapp_xml['copyright'], app_description = tiapp_xml['description'], app_guid = tiapp_xml['guid'], app_id = tiapp_xml['id'], app_name = tiapp_xml['name'], app_names = simplejson.dumps(app_names), app_publisher = tiapp_xml['publisher'], app_url = tiapp_xml['url'], app_version = tiapp_xml['version'], deploy_type = deploytype, locales = simplejson.dumps(locales), packages = simplejson.dumps(self.packages, sort_keys=True), project_id = tiapp_xml['id'], project_name = tiapp_xml['name'], ti_fs_registry = tiapp_xml['mobileweb']['filesystem']['registry'], ti_theme = theme, ti_githash = self.package_json['titanium']['githash'], ti_timestamp = self.package_json['titanium']['timestamp'], ti_version = sdk_version, has_analytics_use_xhr = tiapp_xml['mobileweb']['analytics']['use-xhr'], has_show_errors = 'false' if deploytype == 'production' or tiapp_xml['mobileweb']['disable-error-screen'] == 'true' else 'true', has_instrumentation = 'true' if enableInstrumentation else 'false', jsQuoteEscapeFilter = lambda str: str.replace("\\\"","\\\\\\\"") )) # 2) copy in instrumentation if it's enabled if enableInstrumentation: ti_js.write(codecs.open(os.path.join(self.sdk_src_path, 'instrumentation.js'), 'r', 'utf-8').read()) # 3) copy in the loader ti_js.write(codecs.open(os.path.join(self.sdk_src_path, 'loader.js'), 'r', 'utf-8').read() + '\n') # 4) cache the dependencies first = True require_cache_written = False module_counter = 0 # uncomment next line to bypass module caching (which is ill advised): # self.modules_to_cache = {} for x in self.modules_to_cache: is_cjs = False if x.startswith('commonjs:'): is_cjs = True x = x[9:] dep = self.resolve(x, None) if not len(dep): continue if not require_cache_written: ti_js.write('require.cache({\n'); require_cache_written = True; if not first: ti_js.write(',\n') first = False module_counter += 1 filename = dep[1] if not filename.endswith('.js'): filename += '.js' file_path = os.path.join(dep[0], filename) if x.startswith('url:'): source = file_path + '.uncompressed.js' if self.minify: os.rename(file_path, source) print '[INFO] Minifying include %s' % file_path p = subprocess.Popen('java -Xms256m -Xmx256m -jar "%s" --compilation_level SIMPLE_OPTIMIZATIONS --js "%s" --js_output_file "%s"' % (os.path.join(self.sdk_path, 'closureCompiler', 'compiler.jar'), source, file_path), shell=True, stdout = subprocess.PIPE, stderr = subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: print '[ERROR] Failed to minify "%s"' % file_path for line in stderr.split('\n'): if len(line): print '[ERROR] %s' % line print '[WARN] Leaving %s un-minified' % file_path os.remove(file_path) shutil.copy(source, file_path) ti_js.write('"%s":"%s"' % (x, codecs.open(file_path, 'r', 'utf-8').read().strip().replace('\\', '\\\\').replace('\n', '\\n\\\n').replace('\"', '\\\"'))) elif is_cjs: ti_js.write('"%s":function(){\n/* %s */\ndefine(function(require, exports, module){\n%s\n});\n}' % (x, file_path.replace(self.build_path, ''), codecs.open(file_path, 'r', 'utf-8').read())) else: ti_js.write('"%s":function(){\n/* %s */\n\n%s\n}' % (x, file_path.replace(self.build_path, ''), codecs.open(file_path, 'r', 'utf-8').read())) image_mime_types = { '.png': 'image/png', '.gif': 'image/gif', '.jpg': 'image/jpg', '.jpeg': 'image/jpg' } for x in precache_images: x = x.replace('\\', '/') y = x if y.startswith(os.sep): y = '.' + y img = os.path.join(self.resources_path, os.sep.join(y.split('/'))) if os.path.exists(img): fname, ext = os.path.splitext(img.lower()) if ext in image_mime_types: if not require_cache_written: ti_js.write('require.cache({\n'); require_cache_written = True; if not first: ti_js.write(',\n') first = False module_counter += 1 ti_js.write('"url:%s":"data:%s;base64,%s"' % (x, image_mime_types[ext], base64.b64encode(open(img,'rb').read()))) if require_cache_written: ti_js.write('});\n') # 4) write the ti.app.properties def addProp(prop, val): tiapp_xml['properties'][prop] = { 'type': 'string', 'value': val } addProp('ti.fs.backend', tiapp_xml['mobileweb']['filesystem']['backend']) addProp('ti.map.backend', tiapp_xml['mobileweb']['map']['backend']) addProp('ti.map.apikey', tiapp_xml['mobileweb']['map']['apikey']) s = '' for name in tiapp_xml['properties']: prop = tiapp_xml['properties'][name] if prop['type'] == 'bool': s += 'p.setBool("' + name + '",' + prop['value'] + ');\n' elif prop['type'] == 'int': s += 'p.setInt("' + name + '",' + prop['value'] + ');\n' elif prop['type'] == 'double': s += 'p.setDouble("' + name + '",' + prop['value'] + ');\n' else: s += 'p.setString("' + name + '","' + str(prop['value']).replace('"', '\\"') + '");\n' ti_js.write('require("Ti/App/Properties", function(p) {\n%s});\n' % s) # 5) write require() to load all Ti modules self.modules_to_load.sort() self.modules_to_load += self.tiplus_modules_to_load ti_js.write('require(%s);\n' % simplejson.dumps(self.modules_to_load)) # 6) close the titanium.js ti_js.close() # build the splash screen splash_html = '' splash_css = '' if tiapp_xml['mobileweb']['splash']['enabled'] == 'true': print '[INFO] Processing splash screen...' splash_path = os.path.join(self.project_path, 'Resources', 'mobileweb', 'splash') splash_root_path = os.path.join(self.project_path, 'Resources') if not os.path.exists(splash_path): splash_path = os.path.join(self.sdk_path, 'splash') splash_root_path = splash_path splash_html_file = os.path.join(splash_path, 'splash.html') splash_css_file = os.path.join(splash_path, 'splash.css') if os.path.exists(splash_html_file): splash_html = codecs.open(splash_html_file, 'r', 'utf-8').read() if os.path.exists(splash_css_file): splash_css = codecs.open(splash_css_file, 'r', 'utf-8').read() if tiapp_xml['mobileweb']['splash']['inline-css-images'] == 'true': parts = splash_css.split('url(') for i in range(1, len(parts)): j = parts[i].find(')') if j != -1: img = parts[i][:j].replace('"', '').replace('\'', '').strip() if img.find('data:') == -1: if img[1] == '/': img_path = os.path.join(splash_root_path, img[1:]) else: img_path = os.path.join(splash_path, img) if os.path.exists(img_path): fname, ext = os.path.splitext(img_path.lower()) if ext in image_mime_types: parts[i] = 'data:%s;base64,%s%s' % (image_mime_types[ext], base64.b64encode(open(img_path,'rb').read()), parts[i][j:]) splash_css = 'url('.join(parts) # build the titanium.css file print '[INFO] Assembling titanium.css...' ti_css = HEADER + '\n' + splash_css + '\n' + codecs.open(os.path.join(self.themes_path, 'common.css'), 'r', 'utf-8').read() # TODO: need to rewrite absolute paths for urls # TODO: code below does NOT inline imports, nor remove them... do NOT use imports until themes are fleshed out if len(theme): theme_path = os.path.join(self.resources_path, 'themes', theme) if not os.path.exists(theme_path): theme_path = os.path.join(self.resources_path, theme) if not os.path.exists(theme_path): theme_path = os.path.join(self.themes_path, theme) if not os.path.exists(theme_path): print '[ERROR] Unable to locate theme "%s"' % theme else: for dirname, dirnames, filenames in os.walk(theme_path): for filename in filenames: fname, ext = os.path.splitext(filename.lower()) if ext == '.css': ti_css += codecs.open(os.path.join(dirname, filename), 'r', 'utf-8').read() # detect any fonts and add font face rules to the css file fonts = {} for dirname, dirnames, filenames in os.walk(self.resources_path): for filename in filenames: fname, ext = os.path.splitext(filename.lower()) if ext == '.otf' or ext == '.woff': if not fname in fonts: fonts[fname] = [] fonts[fname].append(os.path.join(dirname, filename)[len(self.resources_path):]) for font in fonts: ti_css += '@font-face{font-family:%s;src:url(%s);}\n' % (font, '),url('.join(fonts[font])) # minify the css if self.minify: ti_css = CSSPacker(ti_css).pack() # write the titanium.css ti_css_file = codecs.open(os.path.join(self.build_path, 'titanium.css'), 'w', 'utf-8') ti_css_file.write(ti_css) ti_css_file.close() # minify all javascript, html, and css files if self.minify: # TODO: only minify non-project code (i.e. Titanium and Ti+ modules) subprocess.call('java -Xms256m -Xmx256m -cp "%s%s%s" -Djava.awt.headless=true minify "%s"' % (os.path.join(self.sdk_path, 'minify'), os.pathsep, os.path.join(self.sdk_path, 'closureCompiler', 'compiler.jar'), self.build_path), shell=True) # elif ext == '.json': # TODO: minify json # elif ext == '.css': # TODO: minify css # elif ext == '.html': # TODO: minify html # create the favicon and apple touch icons icon_file = os.path.join(self.resources_path, tiapp_xml['icon']) fname, ext = os.path.splitext(icon_file.lower()) if os.path.exists(icon_file) and (ext == '.png' or ext == '.jpg' or ext == '.gif'): self.build_icons(icon_file) else: icon_file = os.path.join(self.resources_path, 'mobileweb', 'appicon.png') if os.path.exists(icon_file): self.build_icons(icon_file) # create the filesystem registry print '[INFO] Building filesystem registry...' filesystem_registry = 'ts\t' + str(int(os.path.getctime(self.build_path)) * 1000) + '\n' + self.walk_fs(self.build_path, 0) filesystem_registry_file = codecs.open(os.path.join(self.build_path, 'titanium', 'filesystem.registry'), 'w', 'utf-8') filesystem_registry_file.write(filesystem_registry) filesystem_registry_file.close() # if we're preloading the filesystem registry, write it to the require cache if tiapp_xml['mobileweb']['filesystem']['registry'] == 'preload': ti_js = codecs.open(self.ti_js_file, 'a', 'utf-8') ti_js.write('require.cache({"url:/titanium/filesystem.registry":"' + filesystem_registry.strip().replace('\n', '|') + '"});') ti_js.close() # get status bar style status_bar_style = 'default' if 'statusbar-style' in tiapp_xml: status_bar_style = tiapp_xml['statusbar-style'] if status_bar_style == 'opaque_black' or status_bar_style == 'opaque': status_bar_style = 'black' elif status_bar_style == 'translucent_black' or status_bar_style == 'transparent' or status_bar_style == 'translucent': status_bar_style = 'black-translucent' else: status_bar_style = 'default' # populate index.html index_html_file = codecs.open(os.path.join(self.build_path, 'index.html'), 'w', 'utf-8') index_html_file.write(AppcTemplate(codecs.open(os.path.join(self.sdk_src_path, 'index.html'), 'r', 'utf-8').read().strip(), input_encoding='utf-8', output_encoding='utf-8').render( ti_header = HTML_HEADER, project_name = tiapp_xml['name'] or '', app_description = tiapp_xml['description'] or '', app_publisher = tiapp_xml['publisher'] or '', splash_screen = splash_html, ti_generator = 'Appcelerator Titanium Mobile ' + sdk_version, ti_statusbar_style = status_bar_style, ti_css = ti_css, ti_js = codecs.open(self.ti_js_file, 'r', 'utf-8').read() )) index_html_file.close() total_time = round(time.time() - start_time) total_minutes = math.floor(total_time / 60) total_seconds = total_time % 60 if total_minutes > 0: print '[INFO] Finished in %s minutes %s seconds' % (int(total_minutes), int(total_seconds)) else: print '[INFO] Finished in %s seconds' % int(total_time)
def add_compiled_resources(source, target): print "[DEBUG] copy resources from %s to %s" % (source, target) compiled_targets = {} for root, dirs, files in os.walk(source, True, None, True): for name in ignoreDirs: if name in dirs: dirs.remove(name) # don't visit ignored directories for file in files: if file in ignoreFiles: continue prefix = root[len(source) :] from_ = to_unicode_or_not(os.path.join(root, file)) to_ = os.path.expanduser(from_.replace(source, target, 1)) to_directory = os.path.expanduser(os.path.split(to_)[0]) if not os.path.exists(to_directory): os.makedirs(to_directory) fp = os.path.splitext(file) ext = fp[1] if ext == ".jss": continue if len(fp) > 1 and write_routing and ext in [".html", ".js", ".css"]: path = prefix + os.sep + file path = path[1:] entry = {"path": path, "from": from_, "to": to_} if compiled_targets.has_key(ext): compiled_targets[ext].append(entry) else: compiled_targets[ext] = [entry] else: # only copy if different filesize or doesn't exist if not os.path.exists(to_) or os.path.getsize(from_) != os.path.getsize(to_): print "[DEBUG] copying: %s to %s" % (from_, to_) shutil.copyfile(from_, to_) if compiled_targets.has_key(".html"): compiled = self.process_html_files(compiled_targets, source) if len(compiled) > 0: for c in compiled: from_ = c["from"] to_ = c["to"] path = c["path"] print "[DEBUG] copying: %s to %s" % (from_, to_) file_contents = open(from_).read() file_contents = jspacker.jsmin(file_contents) file_contents = file_contents.replace("Titanium.", "Ti.") to = open(to_, "w") to.write(file_contents) to.close() for ext in (".css", ".html"): if compiled_targets.has_key(ext): for css_file in compiled_targets[ext]: from_ = css_file["from"] to_ = css_file["to"] print "[DEBUG] copying: %s to %s" % (from_, to_) if path.endswith(".css"): file_contents = open(from_).read() packer = CSSPacker(file_contents) file_contents = packer.pack() to = open(to_, "w") to.write(file_contents) to.close() else: shutil.copyfile(from_, to_) if compiled_targets.has_key(".js"): for js_file in compiled_targets[".js"]: path = js_file["path"] from_ = js_file["from"] compile_js_file(path, from_)
def make_function_from_file(self,path,file): fp = os.path.splitext(path) basename = fp[0].replace(' ','_').replace('/','_').replace('-','_').replace('.','_').replace('+','_') ext = fp[1][1:] url = 'app://%s/%s' % (self.appid,path) filetype = '' contents = '' if ext=='html': filetype = 'page' elif ext=='css': filetype = 'style' elif ext=='js': filetype = 'script' methodname = "%sNamed%s%s" % (filetype,basename[0:1].upper(),basename[1:]) method_define = "- (NSData*) %s;" % methodname seed = random.randint(1,9) key = "%s%d%s" % (self.appid,seed,methodname) file_contents = open(os.path.expanduser(file)).read() _file_contents = file_contents # minimize javascript, css files if ext == 'js': file_contents = jspacker.jsmin(file_contents) elif ext == 'css': packer = CSSPacker(file_contents) file_contents = packer.pack() # determine which modules this file is using self.extract_modules(file_contents) if self.debug and ext == 'js': file_contents = """ try { %s } catch(__ex__) { if (typeof __ex__ == 'string') { var msg = __ex__ __ex__ = {line:3,sourceURL:'%s',message:msg}; } var _sur = __ex__.sourceURL; if (_sur) { _sur = _sur.substring(%d); } Titanium.API.reportUnhandledException(__ex__.line-3,_sur,__ex__.message); } """ % (_file_contents,url.encode("utf-8"),len('app://%s/'%self.appid)) if self.encrypt: out = subprocess.Popen([self.encryptor,file,key], stderr=subprocess.PIPE, stdout=subprocess.PIPE).communicate()[0] data = str(out).strip() method = """ %s { NSString *k1 = @"%s"; int seed = %d; NSString *k2 = @"%s"; NSData *d = AES128DecryptWithKey(dataWithHexString(@"%s"), [NSString stringWithFormat:@"%%@%%d%%@",k1,seed,k2]); if ([d length] == 0) return nil; return decode64(d); } """ % (method_define,self.appid,seed,methodname,data) else: sys.stdout.flush() data = str(file_contents).encode("hex") method = """ %s { NSData *d = dataWithHexString(@"%s"); if ([d length] == 0) return nil; return d; } """ % (method_define,data) return {'name':methodname,'method':method,'define':method_define,'url':url,'path':path}
def csspack(c): return CSSPacker(c).pack() packers = {'js': jspack, 'css': csspack }