Class: Build

Inherits:
Path show all
Defined in:
lib/mako/build.rb

Instance Attribute Summary

Attributes inherited from Path

#args, #default, #settings

Instance Method Summary collapse

Methods inherited from Path

#aboslute_paths, #absolute_path, #initalize, #prepare_output_path, #prioritize

Constructor Details

#initialize(settings, default, args) ⇒ Build

Returns a new instance of Build.



34
35
36
37
38
# File 'lib/mako/build.rb', line 34

def initialize settings, default, args
	@settings = settings
	@default = default
	@args = args
end

Instance Method Details

#build_staging_area(source, output_dir) ⇒ Object



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/mako/build.rb', line 292

def build_staging_area source, output_dir
	FileUtils.rm_r output_dir, :force=>true

	Dir::mkdir output_dir
	Dir::mkdir output_dir+'/swf'
	Dir::mkdir output_dir+'/img'
	Dir::mkdir output_dir+'/img/screen-shots'
	Dir::mkdir output_dir+'/_score-modules'
	Dir::mkdir output_dir+'/_assets'

	# copy everything to where it needs to be
	FileUtils.cp_r Dir[source+'swf/*'], output_dir+'/swf'
	FileUtils.cp_r Dir[source+'img/*'], output_dir+'/img'
	FileUtils.cp_r Dir[source+'_icons/*'], output_dir+'/img'
	FileUtils.cp_r Dir[source+'_screen-shots/*'], output_dir+'/img/screen-shots'
	FileUtils.cp_r Dir[source+'_assets/*'], output_dir+'/_assets'
	FileUtils.cp   source+'install.yaml', output_dir+'/install.yaml'
	FileUtils.cp   source+'demo.yaml', output_dir+'/demo.yaml'

	if File::exists? source+'_score/score_module.php'
		FileUtils.cp source+'_score/score_module.php', output_dir+'/_score-modules/score_module.php'
		FileUtils.cp source+'_score/test_score_module.php', output_dir+'/_score-modules/test_score_module.php'
	end

	output_dir
end

#compile(configs, current_path = Dir.pwd, output = nil) ⇒ Object

process_configs output, prioritize(:configs, args, default), default, settings, args



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/mako/build.rb', line 41

def compile configs, current_path=Dir.pwd, output = nil
	output = output.nil? ? prepare_output_path(@args, @default) : output
	configs.each do |config|
		source = File.dirname absolute_path(config, current_path)
		cfg = load_symbolized_yaml absolute_path(config, current_path)

		if cfg == false
			abort
		end

		# build.yaml describes a single creator or engine that needs to be compiled?
		if cfg.compiles_widget?
			if cfg[:type] == 'compile_swf'
				compile_swc output, source, cfg
			end
			if cfg[:type] == 'compile_html'
				compile_html output, source, cfg
			end

		# build.yaml describes a single creator or engine that doesnt need compiling
		elsif cfg.is_copy_type?
			copy_to_output output, source, cfg

		# build.yaml describes a list of configs to run compile on
		elsif cfg.contains_configs?
			# for configs that only contain other configs but arent packages
			compile output, cfg[:configs], source

		# build.yaml describes a widget package (creator and engine)
		elsif cfg.is_package?
			if @args[:skip_package]
				compile_package source, output, cfg
			else
				staging_area = Dir.mktmpdir '-mako'
				compile_package source, staging_area, cfg
				zip_package staging_area, output, cfg
				FileUtils.rm_r staging_area, :force => true
			end
		else
			puts "#{config} unknown config type".red
		end
	end
end

#compile_html(output_dir, base_dir, config) ⇒ Object

copy and compile any html, js, coffeescript, saas, css, or images given the settings



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/mako/build.rb', line 159

def compile_html output_dir, base_dir, config

	copy_to_output output_dir, base_dir, config

	coffee = Dir[output_dir+'/**/*.coffee']
	if coffee.any?
		require 'coffee-script'
		coffee.each do |source|
			process_coffee source, output_dir, output_dir, !@args[:skip_optimize]
			File.delete source
		end
	end

	less = Dir[output_dir+'/**/*.{less}']
	if less.any?
		require 'less'
		less.each do |source|
			process_less source, output_dir, output_dir, !@args[:skip_optimize]
			File.delete source
		end
	end

	sass = Dir[output_dir+'/**/*.{scss,sass}']
	if sass.any?
		require 'sass'
		sass.each do |source|
			process_sass source, output_dir, output_dir, !@args[:skip_optimize]
			File.delete source
		end
	end

	remove_html_dev_helpers output_dir
end

#compile_package(source, output_dir, cfg) ⇒ Object



319
320
321
322
323
324
325
326
# File 'lib/mako/build.rb', line 319

def compile_package source, output_dir, cfg
	source << '/' unless source.end_with? '/'

	stage = build_staging_area source, output_dir

	compile [cfg[:engine], cfg[:creator]], Dir.pwd, stage
	optimize_staged_files(output_dir) unless @args[:skip_optimize]
end

#compile_swc(output_dir, base_dir, config) ⇒ Object

execute the mxmlc compiler on the given settings



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/mako/build.rb', line 110

def compile_swc output_dir, base_dir, config

	# combine and prioritize the options
	run = {}
	run[:dev_kit]      = prioritize :dev_kit, @args, @settings, @default
	run[:sdk]          = prioritize :sdk, @args, @settings, @default
	run[:target]       = prioritize :target, @args, config, @default
	run[:app_class]    = absolute_path(prioritize(:app_class, config, @default), base_dir)
	run[:stop_on_fail] = prioritize :stop_on_fail, @args, @settings, @default
	run[:libs]         = aboslute_paths config[:libs], base_dir
	run[:sources]      = aboslute_paths config[:sources], base_dir

	# Make sure the SDK exists
	if run[:sdk].empty?
		puts "Mako can't find your Flex SDK".red
		puts "Please set MAKO_FLEX_SDK environment variable or the --sdk option"
		abort
	end

	# Check for the DevKit
	if prioritize(:dev_kit, @args, @settings, @default).empty?
		puts "Mako can't find your Materia Dev Kit".red
		puts "Please set MAKO_DEV_KIT environment variable or the --dev-kit option"
		abort
	end

	# Add in Materia and Flex Resources
	run[:sources].push run[:sdk]+'frameworks/' # flex sdk framework directory
	run[:sources].push run[:dev_kit]+'flash_widget_dev_core/src/' # Materia widget dev kit source
	run[:libs].push run[:sdk]+'frameworks/libs/' # Flex framework libs
	run[:libs].push run[:sdk]+'frameworks/locale/en_US/' # Flex local files

	# Setup the strings for the command
	mxmlc      = run[:sdk] + 'bin/mxmlc'
	sources    = ' -source-path '+run[:sources].join(' ')
	output_dir = ' -output '+output_dir+'/'+run[:target]
	extras     = ' -load-config '+run[:sdk]+'frameworks/flex-config.xml'+' -target-player 10.2.0 -debug=' +@args[:skip_optimize].to_s
	libs       = ' -library-path '+run[:libs].join(' ')

	# Execute
	puts "[Compiling] #{run[:target]}".white
	unless system(mxmlc+" "+run[:app_class]+sources+output_dir+libs+extras)
		puts "[Compile Failed]".red
		puts mxmlc+" "+run[:app_class]+sources+output_dir+libs+extras
		abort unless run[:stop_on_fail]
	end
end

#copy_to_output(output, base_dir, config) ⇒ Object



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/mako/build.rb', line 193

def copy_to_output output, base_dir, config

	base_dir << '/' unless base_dir.end_with? '/'
	output_dir = output.dup
	output_dir << '/' unless output_dir.end_with? '/'

	# FileUtils.rm_r output_dir, :force=>true
	Dir::mkdir output_dir unless File::exists? output_dir

	# copy any included directories
	if config[:include]
		config[:include].each do |item|
			item << '/' unless item.end_with? '/'
			Dir::mkdir output_dir+item unless File::exists? output_dir+item
			FileUtils.cp_r Dir[base_dir+item+'*'], output_dir+item
		end
	end

	#copy the target file incase its not in the included directories
	if config[:target]
		dir = File::dirname(output_dir+config[:target])
		FileUtils.mkpath dir unless File::exists? dir
		FileUtils.cp_r base_dir+config[:target], output_dir+config[:target]
	end
end

#load_symbolized_yaml(yaml) ⇒ Object



92
93
94
95
96
97
98
99
# File 'lib/mako/build.rb', line 92

def load_symbolized_yaml yaml
	contents = load_yaml yaml
	if contents
		return string_keys_to_symbols contents
	end
	puts "Yaml file not valid #{yaml}".red
	false
end

#load_yaml(yaml) ⇒ Object



85
86
87
88
89
90
# File 'lib/mako/build.rb', line 85

def load_yaml yaml
	if File::exists?(yaml) and contents = YAML::load_file(yaml)
		return contents
	end
	false
end

#optimize_staged_files(path) ⇒ Object



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
# File 'lib/mako/build.rb', line 349

def optimize_staged_files path
	css = Dir[path+'/**/*.css']
	if css.any?
		require "yui/compressor"
		css.each do |source|
			process_css source
		end
	end

	js = Dir[path+'/**/*.js']
	if js.any?
		require "yui/compressor"
		js.each do |source|
			process_js source
		end
	end
end

#process_coffee(file, output_dir, base_dir, optimize) ⇒ Object



246
247
248
249
250
251
252
253
254
255
256
# File 'lib/mako/build.rb', line 246

def process_coffee file, output_dir, base_dir, optimize
	puts "Compiling CoffeeScript:".green + "#{file}".white
	# output to a css file of the same name, in the same reletive structure in the output directory
	output_file = (file.chomp(File.extname(file)) + '.js').sub(base_dir, output_dir)
	output_dir = File.dirname(output_file)
	# makes the directory structure if it doesnt exist
	FileUtils.mkdir_p output_dir unless File.directory? output_dir
	# process sass file and write output
	output = CoffeeScript.compile File.read(file)
	File.open(output_file, 'w') { |file_out| file_out.write(output) }
end

#process_css(file) ⇒ Object



265
266
267
268
269
270
# File 'lib/mako/build.rb', line 265

def process_css file
	puts "Compressing CSS:".blue + "#{file}".white
	compressor = YUI::CssCompressor.new
	compressed = compressor.compress File.read(file)
	File.open(file, 'w') { |file_out| file_out.write(compressed) }
end

#process_js(file) ⇒ Object



258
259
260
261
262
263
# File 'lib/mako/build.rb', line 258

def process_js file
	puts "Compressing JavaScript:".blue + "#{file}".white
	compressor = YUI::JavaScriptCompressor.new :munge => true
	compressed = compressor.compress File.read(file)
	File.open(file, 'w') { |file_out| file_out.write(compressed) }
end

#process_less(file, output_dir, base_dir, optimize) ⇒ Object

requires gem therubyracer



233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/mako/build.rb', line 233

def process_less file, output_dir, base_dir, optimize
	puts "Compiling LESS:".green + "#{file}".white

	output_file = (file.chomp(File.extname(file)) + '.css').sub(base_dir, output_dir)
	output_dir = File.dirname(output_file)
	# makes the directory structure if it doesnt exist
	FileUtils.mkdir_p output_dir unless File.directory? output_dir
	# process sass file and write output
	tree = Less::Parser.new().parse File.read(file)
	output = tree.to_css()
	File.open(output_file, 'w') { |file_out| file_out.write(output) }
end

#process_sass(file, output_dir, base_dir, optimize) ⇒ Object



219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/mako/build.rb', line 219

def process_sass file, output_dir, base_dir, optimize
	puts "Compiling SASS:".green + "#{file}".white
	# output to a css file of the same name, in the same reletive structure in the output directory
	output_file = (file.chomp(File.extname(file)) + '.css').sub(base_dir, output_dir)
	output_dir = File.dirname(output_file)
	# makes the directory structure if it doesnt exist
	FileUtils.mkdir_p output_dir unless File.directory? output_dir
	# process sass file and write output
	sass_engine = Sass::Engine.for_file(file, {:style => :nested})
	output = sass_engine.render
	File.open(output_file, 'w') { |file_out| file_out.write(output) }
end

#remove_html_dev_helpers(output_path) ⇒ Object



272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/mako/build.rb', line 272

def remove_html_dev_helpers output_path
	# For development, html widgets support loading coffeescript via require.js
	# to do so, authors will add 'cs!' before the coffeescript file they are loading
	# dev: [ ...scripts..., 'cs!js/widget'] will load js/widget.coffee
	# packaged: [ ...scripts..., 'js/widget'] will load js/widget.js
	# Now we will pull out cs! because we pre-compile coffeescript
	# ALSO if LESS is used, we will be including  'less' in the require - we'll get rid of this too
	Dir[output_path+'/**/*.{html,htm}'].each do |file|
		text = File.read(file)
		# remove coffeescript helpers
		text = text.gsub(/['"]cs!/, "'")
		# remove less in require
		text = text.gsub(/(require\(\[[^\]]+?)['"]less['"]\s?,/, '\1')
		# remove less in includes
		text = text.gsub(/rel="stylesheet\/less"/, 'rel="stylesheet"')
		text = text.gsub(/href="(.+?)\.less"/, 'href="\1.css"')
		File.open(file, 'w') { |fpath| fpath.puts(text) }
	end
end

#string_keys_to_symbols(hash) ⇒ Object

Convert an array that uses string keys to symbol keys… cuz they look cooler



102
103
104
105
106
107
# File 'lib/mako/build.rb', line 102

def string_keys_to_symbols hash
	hash.keys.each do |key|
		hash[(key.to_sym rescue key) || key] = hash.delete(key)
	end
	hash
end

#zip_package(source, output_dir, cfg) ⇒ Object



329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/mako/build.rb', line 329

def zip_package source, output_dir, cfg
	# setup all the directories
	output_dir = output_dir.dup # output_dir is frozen typically and I don't know ruby enough to understand why
	output_dir << '/' unless output_dir.end_with? '/'
	source << '/' unless source.end_with? '/'
	name = load_yaml(source+'install.yaml')['general']['name'].pretty

	# zip it
	zip_file = "#{output_dir}#{name}.wigt"
	FileUtils.rm zip_file, :force=>true
	Zip::ZipFile.open(zip_file, Zip::ZipFile::CREATE) do |zip|
		Dir[source+'**/**'].each do |file|
			zip.add file.sub(source, ''), file
		end
	end

	# done, cleanup
	puts "[Package Finished] #{name} #{zip_file}".green
end