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