asset_hat 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. data/.gitignore +1 -0
  2. data/HISTORY +12 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +153 -0
  5. data/Rakefile +22 -0
  6. data/VERSION.yml +5 -0
  7. data/app/helpers/asset_hat_helper.rb +171 -0
  8. data/asset_hat.gemspec +98 -0
  9. data/config/assets.yml +59 -0
  10. data/lib/asset_hat.rb +85 -0
  11. data/lib/asset_hat/css.rb +76 -0
  12. data/lib/asset_hat/js.rb +86 -0
  13. data/lib/asset_hat/tasks.rb +296 -0
  14. data/lib/asset_hat/vcs.rb +65 -0
  15. data/lib/asset_hat/version.rb +11 -0
  16. data/public/javascripts/bundles/js-bundle-1.min.js +6 -0
  17. data/public/javascripts/bundles/js-bundle-2.min.js +6 -0
  18. data/public/javascripts/bundles/js-bundle-3.min.js +6 -0
  19. data/public/javascripts/js-file-1-1.js +1 -0
  20. data/public/javascripts/js-file-1-2.js +1 -0
  21. data/public/javascripts/js-file-1-3.js +1 -0
  22. data/public/javascripts/js-file-2-1.js +1 -0
  23. data/public/javascripts/js-file-2-2.js +1 -0
  24. data/public/javascripts/js-file-2-3.js +1 -0
  25. data/public/javascripts/js-file-3-1.js +1 -0
  26. data/public/javascripts/js-file-3-2.js +1 -0
  27. data/public/javascripts/js-file-3-3.js +1 -0
  28. data/public/stylesheets/bundles/css-bundle-1.min.css +3 -0
  29. data/public/stylesheets/bundles/css-bundle-2.min.css +3 -0
  30. data/public/stylesheets/bundles/css-bundle-3.min.css +3 -0
  31. data/public/stylesheets/css-file-1-1.css +1 -0
  32. data/public/stylesheets/css-file-1-2.css +1 -0
  33. data/public/stylesheets/css-file-1-3.css +1 -0
  34. data/public/stylesheets/css-file-2-1.css +1 -0
  35. data/public/stylesheets/css-file-2-2.css +1 -0
  36. data/public/stylesheets/css-file-2-3.css +1 -0
  37. data/public/stylesheets/css-file-3-1.css +1 -0
  38. data/public/stylesheets/css-file-3-2.css +1 -0
  39. data/public/stylesheets/css-file-3-3.css +1 -0
  40. data/rails/init.rb +17 -0
  41. data/tasks/asset_hat.rake +1 -0
  42. data/test/asset_hat_helper_test.rb +237 -0
  43. data/test/asset_hat_test.rb +46 -0
  44. data/test/test_helper.rb +23 -0
  45. metadata +141 -0
@@ -0,0 +1,59 @@
1
+ # This belongs in your app's `config` directory. Configure your bundles
2
+ # below; no `.css` or `.js` suffixes needed. Example:
3
+ #
4
+ # css:
5
+ # engine: cssmin
6
+ # bundles:
7
+ # application:
8
+ # - reset
9
+ # - application
10
+ # - clearfix
11
+ # admin:
12
+ # - reset
13
+ # - admin
14
+ # - clearfix
15
+ # js:
16
+ # engine: jsmin
17
+ # vendors:
18
+ # jquery:
19
+ # version: 1.4
20
+ # bundles:
21
+ # plugins:
22
+ # - init
23
+ # - third-party-plugin.min
24
+ # # Here, the suffix `.min` indicates that the code has already
25
+ # # been minified, and should not be re-minified.
26
+ # common:
27
+ # - utilities
28
+ # - application
29
+
30
+ css:
31
+ engine: cssmin
32
+ bundles:
33
+ css-bundle-1:
34
+ - css-file-1-1
35
+ - css-file-1-2
36
+ - css-file-1-3
37
+ css-bundle-2:
38
+ - css-file-2-1
39
+ - css-file-2-2
40
+ - css-file-2-3
41
+ css-bundle-3:
42
+ - css-file-3-1
43
+ - css-file-3-2
44
+ - css-file-3-3
45
+ js:
46
+ engine: jsmin
47
+ bundles:
48
+ js-bundle-1:
49
+ - js-file-1-1
50
+ - js-file-1-2
51
+ - js-file-1-3
52
+ js-bundle-2:
53
+ - js-file-2-1
54
+ - js-file-2-2
55
+ - js-file-2-3
56
+ js-bundle-3:
57
+ - js-file-3-1
58
+ - js-file-3-2
59
+ - js-file-3-3
@@ -0,0 +1,85 @@
1
+ %w[css js vcs].each do |x|
2
+ require File.join(File.dirname(__FILE__), 'asset_hat', x)
3
+ end
4
+
5
+ module AssetHat
6
+ RAILS_ROOT = File.join(File.dirname(__FILE__), '..') unless defined?(RAILS_ROOT)
7
+ TYPES = [:css, :js]
8
+ ASSETS_DIR = defined?(Rails.public_path) ? Rails.public_path : 'public'
9
+ JAVASCRIPTS_DIR = "#{ASSETS_DIR}/javascripts"
10
+ STYLESHEETS_DIR = "#{ASSETS_DIR}/stylesheets"
11
+ CONFIG_FILEPATH = File.join(RAILS_ROOT, 'config', 'assets.yml')
12
+
13
+ def self.config
14
+ @@config ||= YAML.load(File.open(CONFIG_FILEPATH, 'r'))
15
+ end
16
+
17
+ def self.assets_dir(type)
18
+ case type.to_sym
19
+ when :css ; STYLESHEETS_DIR
20
+ when :js ; JAVASCRIPTS_DIR
21
+ end
22
+ end
23
+
24
+ def self.asset_exists?(filename, type)
25
+ # Process arguments
26
+ type = type.to_sym
27
+ unless TYPES.include?(type)
28
+ raise "Unknown type \"#{type}\"; should be one of: #{TYPES.join(', ')}."
29
+ return
30
+ end
31
+
32
+ @@asset_exists ||= TYPES.inject({}) do |hsh, known_type|
33
+ hsh.merge!(known_type => {})
34
+ end
35
+ if @@asset_exists[type][filename].nil?
36
+ @@asset_exists[type][filename] =
37
+ File.exist?(File.join(self.assets_dir(type), filename))
38
+ end
39
+ @@asset_exists[type][filename]
40
+ end
41
+
42
+ def self.cache? ; ActionController::Base.perform_caching ; end
43
+
44
+ def self.min_filepath(filepath, extension)
45
+ filepath.sub(/([^\.]*).#{extension}$/, "\\1.min.#{extension}")
46
+ end
47
+
48
+ def self.bundle_filenames(bundle, type)
49
+ # Usage:
50
+ #
51
+ # AssetHat.bundle_filenames('application', :css)
52
+ # # => ['reset', 'application', 'clearfix']
53
+ # AssetHat.bundle_filenames('non-existent-file', :css)
54
+ # # => nil
55
+
56
+ # Process arguments
57
+ unless TYPES.include?(type.to_sym)
58
+ raise "Unknown type \"#{type}\"; should be one of: #{TYPES.join(', ')}."
59
+ return
60
+ end
61
+
62
+ self.config[type.to_s]['bundles'][bundle] rescue nil
63
+ end
64
+
65
+ def self.bundle_filepaths(bundle, type)
66
+ # Usage:
67
+ #
68
+ # AssetHat.bundle_filenames('application', :css)
69
+ # # => ['reset', 'application', 'clearfix']
70
+ # AssetHat.bundle_filenames('non-existent-file', :css)
71
+ # # => nil
72
+
73
+ # Process arguments
74
+ unless TYPES.include?(type.to_sym)
75
+ raise "Unknown type \"#{type}\"; should be one of: #{TYPES.join(', ')}."
76
+ return
77
+ end
78
+
79
+ dir = self.assets_dir(type)
80
+ filenames = self.bundle_filenames(bundle, type)
81
+ filepaths = filenames.present? ?
82
+ filenames.map { |fn| File.join(dir, "#{fn}.#{type}") } : nil
83
+ end
84
+
85
+ end
@@ -0,0 +1,76 @@
1
+ require 'cssmin'
2
+ # - http://github.com/rgrove/cssmin
3
+ # - http://gemcutter.org/gems/cssmin
4
+
5
+ module AssetHat
6
+ module CSS
7
+ ENGINES = [:weak, :cssmin]
8
+
9
+ def self.min_filepath(filepath)
10
+ AssetHat.min_filepath(filepath, 'css')
11
+ end
12
+
13
+ def self.minify(input_string, options={})
14
+ options.reverse_merge!(:engine => :cssmin)
15
+
16
+ options[:engine] = options[:engine].to_sym
17
+ unless ENGINES.include?(options[:engine])
18
+ raise %Q{
19
+ Unknown CSS minification engine '#{options[:engine]}'.
20
+ Allowed: #{ENGINES.map{ |e| "'#{e}'" }.join(', ')}
21
+ }.strip.gsub(/\s+/, ' ') and return
22
+ end
23
+
24
+ AssetHat::CSS::Engines.send(options[:engine], input_string)
25
+ end
26
+
27
+ # def self.add_asset_mtimes(css)
28
+ # css.gsub(/url[\s]*\((\/images\/[^)]+)\)/) do |match|
29
+ # src = $1
30
+ # mtime = File.mtime(File.join(Rails.public_path, src))
31
+ # "url(#{src}?#{mtime.to_i})"
32
+ # end
33
+ # end
34
+
35
+ def self.add_asset_commit_ids(css)
36
+ css.gsub(/url[\s]*\((\/images\/[^)]+)\)/) do |match|
37
+ src = $1
38
+ filepath = File.join(Rails.public_path, src)
39
+ commit_id = AssetHat.last_commit_id(filepath)
40
+ commit_id.present? ? "url(#{src}?#{commit_id})" : "url(#{src})"
41
+ end
42
+ end
43
+
44
+ def self.add_asset_hosts(css, asset_host)
45
+ return if asset_host.blank?
46
+ css.gsub(/url[\s]*\((\/images\/[^)]+)\)/) do |match|
47
+ src = $1
48
+ "url(#{(asset_host =~ /%d/) ? asset_host % (src.hash % 4) : asset_host}#{src})"
49
+ end
50
+ end
51
+
52
+ module Engines
53
+ def self.weak(input_string)
54
+ input = StringIO.new(input_string)
55
+ output = StringIO.new
56
+
57
+ input.each do |line|
58
+ # Remove indentation and trailing whitespace (including line breaks)
59
+ line.strip!
60
+ next if line.blank?
61
+
62
+ output.write line
63
+ end
64
+
65
+ output.rewind
66
+ output.read
67
+ end
68
+
69
+ def self.cssmin(input_string)
70
+ CSSMin.minify(input_string)
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ end
@@ -0,0 +1,86 @@
1
+ require 'jsmin'
2
+ # - http://github.com/rgrove/jsmin
3
+ # - http://gemcutter.org/gems/jsmin
4
+
5
+ module AssetHat
6
+ module JS
7
+ ENGINES = [:weak, :jsmin]
8
+ VENDORS = [:jquery]
9
+ # TODO: Support jQuery UI, Prototype, MooTools, etc.
10
+
11
+ def self.min_filepath(filepath)
12
+ AssetHat.min_filepath(filepath, 'js')
13
+ end
14
+
15
+ def self.minify(input_string, options={})
16
+ options.reverse_merge!(:engine => :jsmin)
17
+
18
+ options[:engine] = options[:engine].to_sym
19
+ unless ENGINES.include?(options[:engine])
20
+ raise %Q{
21
+ Unknown JS minification engine '#{options[:engine]}'.
22
+ Allowed: #{ENGINES.map{ |e| "'#{e}'" }.join(', ')}
23
+ }.strip.gsub(/\s+/, ' ') and return
24
+ end
25
+
26
+ AssetHat::JS::Engines.send(options[:engine], input_string)
27
+ end
28
+
29
+ module Engines
30
+ def self.weak(input_string)
31
+ input = StringIO.new(input_string)
32
+ output = StringIO.new
33
+
34
+ input.each do |line|
35
+ # Remove indentation and trailing whitespace
36
+ line.strip!
37
+ next if line.blank?
38
+
39
+ # Skip single-line comments
40
+ next if !(line =~ /^\/\//).nil?
41
+ # TODO: Also skip single-line comments that began mid-line, but not
42
+ # inside a string or regex
43
+
44
+ # TODO: Skip multi-line comments
45
+ # - Should not strip from within a string or regex
46
+ # - Should not strip comments that begin with `/*!` (e.g., licenses)
47
+
48
+ output.write(line + "\n")
49
+ end
50
+
51
+ output.rewind
52
+ output.read
53
+ end
54
+
55
+ def self.jsmin(input_string)
56
+ JSMin.minify(input_string)
57
+ end
58
+ end # module Engines
59
+
60
+ module Vendors
61
+ JQUERY_DEFAULT_VERSION = '1.4'
62
+
63
+ def self.source_for(vendor, options={})
64
+ version = options[:version]
65
+ if version.blank?
66
+ version = begin
67
+ AssetHat.config['js']['vendors'][vendor.to_s]['version']
68
+ rescue
69
+ AssetHat::JS::Vendors.const_get(
70
+ :"#{vendor.to_s.upcase}_DEFAULT_VERSION")
71
+ end
72
+ end
73
+
74
+ case vendor
75
+ when :jquery
76
+ src = ActionController::Base.consider_all_requests_local ?
77
+ "jquery-#{version}.min.js" :
78
+ "http://ajax.googleapis.com/ajax/libs/jquery/#{version}/jquery.min.js"
79
+ end
80
+ src
81
+ end
82
+ end # module Vendors
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,296 @@
1
+ require 'rake/testtask'
2
+ require 'active_support'
3
+ require 'action_controller'
4
+ require 'action_view'
5
+ require File.join(File.dirname(__FILE__), %w[.. asset_hat])
6
+
7
+
8
+
9
+ unless defined?(RAILS_ROOT)
10
+ RAILS_ROOT = File.join(File.dirname(__FILE__), '..', '..')
11
+ end
12
+
13
+ task :default => :test
14
+
15
+ desc 'Run tests'
16
+ Rake::TestTask.new(:test) do |t|
17
+ t.libs << 'lib' << 'test'
18
+ t.pattern = 'test/**/*_test.rb'
19
+ t.verbose = false
20
+ end
21
+
22
+
23
+
24
+ namespace :asset_hat do
25
+ desc 'Minifies all CSS and JS bundles'
26
+ task :minify do
27
+ Rake::Task['asset_hat:css:minify'].invoke # Generate all CSS bundles
28
+ Rake::Task['asset_hat:js:minify'].invoke # Generate all JS bundles
29
+ end
30
+
31
+ desc 'Prepare configuration file'
32
+ task :config do
33
+ template_filepath =
34
+ File.join(File.dirname(__FILE__), '..', '..', AssetHat::CONFIG_FILEPATH)
35
+ target_filepath = File.join(RAILS_ROOT, AssetHat::CONFIG_FILEPATH)
36
+
37
+ if File.exists?(target_filepath)
38
+ print "Replace #{target_filepath}? (y/n) "
39
+ response = STDIN.gets.chomp
40
+ unless response.downcase == 'y'
41
+ puts 'Aborted.' ; exit
42
+ end
43
+ end
44
+
45
+ FileUtils.cp(template_filepath, target_filepath)
46
+ puts "Wrote to #{target_filepath}"
47
+ end
48
+
49
+ namespace :css do
50
+ # desc 'Adds mtimes to asset URLs in CSS'
51
+ # task :add_asset_mtimes, :filename, :verbose do |t, args|
52
+ # if args.filename.blank?
53
+ # raise 'Usage: rake asset_hat:css:add_asset_mtimes[filename.css]' and return
54
+ # end
55
+ #
56
+ # args.with_defaults :verbose => true
57
+ #
58
+ # css = File.open(args.filename, 'r') { |f| f.read }
59
+ # css = AssetHat::CSS.add_asset_mtimes(css)
60
+ # File.open(args.filename, 'w') { |f| f.write css }
61
+ #
62
+ # puts "- Added asset mtimes to #{args.filename}" if args.verbose
63
+ # end
64
+
65
+ desc 'Adds commit IDs to asset URLs in CSS for cache busting'
66
+ task :add_asset_commit_ids, :filename, :verbose do |t, args|
67
+ if args.filename.blank?
68
+ raise 'Usage: rake asset_hat:css:add_asset_commit_ids[filename.css]' and return
69
+ end
70
+
71
+ args.with_defaults :verbose => true
72
+
73
+ css = File.open(args.filename, 'r') { |f| f.read }
74
+ css = AssetHat::CSS.add_asset_commit_ids(css)
75
+ File.open(args.filename, 'w') { |f| f.write css }
76
+
77
+ puts "- Added asset commit IDs to #{args.filename}" if args.verbose
78
+ end
79
+
80
+ desc 'Adds hosts to asset URLs in CSS'
81
+ task :add_asset_hosts, :filename, :verbose, :needs => :environment do |t, args|
82
+ if args.filename.blank?
83
+ raise 'Usage: rake asset_hat:css:add_asset_hosts[filename.css]' and return
84
+ end
85
+
86
+ args.with_defaults :verbose => true
87
+
88
+ asset_host = ActionController::Base.asset_host
89
+ if asset_host.blank?
90
+ raise "This environment (#{ENV['RAILS_ENV']}) doesn't have an `asset_host` configured."
91
+ return
92
+ end
93
+
94
+ css = File.open(args.filename, 'r') { |f| f.read }
95
+ css = AssetHat::CSS.add_asset_hosts(css, asset_host)
96
+ File.open(args.filename, 'w') { |f| f.write css }
97
+
98
+ puts "- Added asset hosts to #{args.filename}" if args.verbose
99
+ end
100
+
101
+ desc 'Minifies one CSS file'
102
+ task :minify_file, :filepath, :verbose do |t, args|
103
+ if args.filepath.blank?
104
+ raise 'Usage: rake asset_hat:css:minify_file[path/to/filename.css]' and return
105
+ end
106
+
107
+ args.with_defaults :verbose => false
108
+ min_options = {
109
+ :engine => AssetHat.config['css']['engine']
110
+ }.reject { |k,v| v.blank? }
111
+
112
+ input = File.open(args.filepath, 'r').read
113
+ output = AssetHat::CSS.minify(input, min_options)
114
+
115
+ # Write minified content to file
116
+ target_filepath = AssetHat::CSS.min_filepath(args.filepath)
117
+ File.open(target_filepath, 'w') { |f| f.write output }
118
+
119
+ # Print results
120
+ puts "- Minified to #{target_filepath}" if args.verbose
121
+ end
122
+
123
+ desc 'Minifies one CSS bundle'
124
+ task :minify_bundle, :bundle, :needs => :environment do |t, args|
125
+ if args.bundle.blank?
126
+ raise 'Usage: rake asset_hat:css:minify_bundle[application]' and return
127
+ end
128
+
129
+ config = AssetHat.config
130
+ old_bundle_size = 0.0
131
+ new_bundle_size = 0.0
132
+ min_options = {
133
+ :engine => config['css']['engine']
134
+ }.reject { |k,v| v.blank? }
135
+
136
+ # Get bundle filenames
137
+ filenames = config['css']['bundles'][args.bundle]
138
+ if filenames.empty?
139
+ raise "No CSS files are specified for the #{args.bundle} bundle in #{AssetHat::CONFIG_FILEPATH}."
140
+ return
141
+ end
142
+ filepaths = filenames.map do |filename|
143
+ File.join('public', 'stylesheets', "#{filename}.css")
144
+ end
145
+ bundle_filepath = AssetHat::CSS.min_filepath(File.join(
146
+ 'public', 'stylesheets', 'bundles', "#{args.bundle}.css"))
147
+
148
+ # Concatenate and process output
149
+ output = ''
150
+ asset_host = ActionController::Base.asset_host
151
+ filepaths.each do |filepath|
152
+ file_output = File.open(filepath, 'r').read
153
+ old_bundle_size += file_output.size
154
+
155
+ file_output = AssetHat::CSS.minify(file_output, min_options)
156
+ file_output = AssetHat::CSS.add_asset_commit_ids(file_output)
157
+ if asset_host.present?
158
+ file_output = AssetHat::CSS.add_asset_hosts(file_output, asset_host)
159
+ end
160
+
161
+ new_bundle_size += file_output.size
162
+ output << file_output + "\n"
163
+ end
164
+ FileUtils.makedirs(File.dirname(bundle_filepath))
165
+ File.open(bundle_filepath, 'w') { |f| f.write output }
166
+
167
+ # Print results
168
+ percent_saved = 1 - (new_bundle_size / old_bundle_size)
169
+ puts "\nWrote CSS bundle: #{bundle_filepath}"
170
+ filepaths.each do |filepath|
171
+ puts " contains: #{filepath}"
172
+ end
173
+ if old_bundle_size > 0
174
+ engine = "(Engine: #{min_options[:engine]})"
175
+ puts " MINIFIED: #{'%.1f' % (percent_saved * 100)}% #{engine}"
176
+ end
177
+ end
178
+
179
+ desc 'Concatenates and minifies all CSS bundles'
180
+ task :minify do
181
+ # Get input bundles
182
+ config = AssetHat.config
183
+ if config['css'].blank? || config['css']['bundles'].blank?
184
+ puts "You need to set up CSS bundles in #{AssetHat::CONFIG_FILEPATH}."
185
+ exit
186
+ end
187
+ bundles = config['css']['bundles'].keys
188
+
189
+ # Minify bundles
190
+ bundles.each do |bundle|
191
+ Rake::Task['asset_hat:css:minify_bundle'].reenable
192
+ Rake::Task['asset_hat:css:minify_bundle'].invoke(bundle)
193
+ end
194
+ end
195
+
196
+ end # namespace :css
197
+
198
+ namespace :js do
199
+ desc 'Minifies one JS file'
200
+ task :minify_file, :filepath, :verbose do |t, args|
201
+ if args.filepath.blank?
202
+ raise 'Usage: rake asset_hat:js:minify_file[filepath.js]' and return
203
+ end
204
+
205
+ args.with_defaults :verbose => false
206
+ min_options = {
207
+ :engine => AssetHat.config['js']['engine']
208
+ }.reject { |k,v| v.blank? }
209
+
210
+ if args.verbose && args.filepath.match(/\.min\.js$/)
211
+ puts "#{args.filepath} is already minified."
212
+ exit 1
213
+ end
214
+
215
+ input = File.open(args.filepath, 'r').read
216
+ output = AssetHat::JS.minify(input, min_options)
217
+
218
+ # Write minified content to file
219
+ target_filepath = AssetHat::JS.min_filepath(args.filepath)
220
+ File.open(target_filepath, 'w') { |f| f.write output }
221
+
222
+ # Print results
223
+ puts "- Minified to #{target_filepath}" if args.verbose
224
+ end
225
+
226
+ desc 'Minifies one JS bundle'
227
+ task :minify_bundle, :bundle do |t, args|
228
+ if args.bundle.blank?
229
+ raise 'Usage: rake asset_hat:js:minify_bundle[application]' and return
230
+ end
231
+
232
+ config = AssetHat.config
233
+ old_bundle_size = 0.0
234
+ new_bundle_size = 0.0
235
+ min_options = {
236
+ :engine => config['js']['engine']
237
+ }.reject { |k,v| v.blank? }
238
+
239
+ # Get bundle filenames
240
+ filenames = config['js']['bundles'][args.bundle]
241
+ if filenames.empty?
242
+ raise "No JS files are specified for the #{args.bundle} bundle in #{AssetHat::CONFIG_FILEPATH}."
243
+ return
244
+ end
245
+ filepaths = filenames.map do |filename|
246
+ File.join('public', 'javascripts', "#{filename}.js")
247
+ end
248
+ bundle_filepath = AssetHat::JS.min_filepath(File.join(
249
+ 'public', 'javascripts', 'bundles', "#{args.bundle}.js"))
250
+
251
+ # Concatenate and process output
252
+ output = ''
253
+ filepaths.each do |filepath|
254
+ file_output = File.open(filepath, 'r').read
255
+ old_bundle_size += file_output.size
256
+ unless filepath =~ /\.min\.js$/ # Already minified
257
+ file_output = AssetHat::JS.minify(file_output, min_options)
258
+ end
259
+ new_bundle_size += file_output.size
260
+ output << file_output + "\n"
261
+ end
262
+ FileUtils.makedirs(File.dirname(bundle_filepath))
263
+ File.open(bundle_filepath, 'w') { |f| f.write output }
264
+
265
+ # Print results
266
+ percent_saved = 1 - (new_bundle_size / old_bundle_size)
267
+ puts "\n Wrote JS bundle: #{bundle_filepath}"
268
+ filepaths.each do |filepath|
269
+ puts " contains: #{filepath}"
270
+ end
271
+ if old_bundle_size > 0
272
+ engine = "(Engine: #{min_options[:engine]})"
273
+ puts " MINIFIED: #{'%.1f' % (percent_saved * 100)}% #{engine}"
274
+ end
275
+ end
276
+
277
+ desc 'Concatenates and minifies all JS bundles'
278
+ task :minify do
279
+ # Get input bundles
280
+ config = AssetHat.config
281
+ if config['js'].blank? || config['js']['bundles'].blank?
282
+ puts "You need to set up JS bundles in #{AssetHat::CONFIG_FILEPATH}."
283
+ exit
284
+ end
285
+ bundles = config['js']['bundles'].keys
286
+
287
+ # Minify bundles
288
+ bundles.each do |bundle|
289
+ Rake::Task['asset_hat:js:minify_bundle'].reenable
290
+ Rake::Task['asset_hat:js:minify_bundle'].invoke(bundle)
291
+ end
292
+ end
293
+
294
+ end # namespace :js
295
+
296
+ end # namespace :asset_hat