asset_hat 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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