asset_hat 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/HISTORY +12 -0
- data/LICENSE +20 -0
- data/README.markdown +153 -0
- data/Rakefile +22 -0
- data/VERSION.yml +5 -0
- data/app/helpers/asset_hat_helper.rb +171 -0
- data/asset_hat.gemspec +98 -0
- data/config/assets.yml +59 -0
- data/lib/asset_hat.rb +85 -0
- data/lib/asset_hat/css.rb +76 -0
- data/lib/asset_hat/js.rb +86 -0
- data/lib/asset_hat/tasks.rb +296 -0
- data/lib/asset_hat/vcs.rb +65 -0
- data/lib/asset_hat/version.rb +11 -0
- data/public/javascripts/bundles/js-bundle-1.min.js +6 -0
- data/public/javascripts/bundles/js-bundle-2.min.js +6 -0
- data/public/javascripts/bundles/js-bundle-3.min.js +6 -0
- data/public/javascripts/js-file-1-1.js +1 -0
- data/public/javascripts/js-file-1-2.js +1 -0
- data/public/javascripts/js-file-1-3.js +1 -0
- data/public/javascripts/js-file-2-1.js +1 -0
- data/public/javascripts/js-file-2-2.js +1 -0
- data/public/javascripts/js-file-2-3.js +1 -0
- data/public/javascripts/js-file-3-1.js +1 -0
- data/public/javascripts/js-file-3-2.js +1 -0
- data/public/javascripts/js-file-3-3.js +1 -0
- data/public/stylesheets/bundles/css-bundle-1.min.css +3 -0
- data/public/stylesheets/bundles/css-bundle-2.min.css +3 -0
- data/public/stylesheets/bundles/css-bundle-3.min.css +3 -0
- data/public/stylesheets/css-file-1-1.css +1 -0
- data/public/stylesheets/css-file-1-2.css +1 -0
- data/public/stylesheets/css-file-1-3.css +1 -0
- data/public/stylesheets/css-file-2-1.css +1 -0
- data/public/stylesheets/css-file-2-2.css +1 -0
- data/public/stylesheets/css-file-2-3.css +1 -0
- data/public/stylesheets/css-file-3-1.css +1 -0
- data/public/stylesheets/css-file-3-2.css +1 -0
- data/public/stylesheets/css-file-3-3.css +1 -0
- data/rails/init.rb +17 -0
- data/tasks/asset_hat.rake +1 -0
- data/test/asset_hat_helper_test.rb +237 -0
- data/test/asset_hat_test.rb +46 -0
- data/test/test_helper.rb +23 -0
- metadata +141 -0
data/config/assets.yml
ADDED
@@ -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
|
data/lib/asset_hat.rb
ADDED
@@ -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
|
data/lib/asset_hat/js.rb
ADDED
@@ -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
|