Exemple #1
0
	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}
Exemple #2
0
    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}
Exemple #3
0
	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)
Exemple #4
0
		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))
Exemple #5
0
        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_)
Exemple #6
0
 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)
Exemple #8
0
        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 }