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.
- 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
@@ -0,0 +1,65 @@
|
|
1
|
+
module AssetHat
|
2
|
+
def self.last_commit_id(*args)
|
3
|
+
# Usage:
|
4
|
+
#
|
5
|
+
# AssetHat.last_commit_id('public/stylesheets/application.css')
|
6
|
+
# AssetHat.last_commit_id('public/stylesheets/ie.css',
|
7
|
+
# 'public/stylesheets/ie7.css',
|
8
|
+
# 'public/stylesheets/ie6.css')
|
9
|
+
#
|
10
|
+
# Returns a string of the commit ID for the file with the most recent
|
11
|
+
# commit. If the file(s) cannot be found, `nil` is returned.
|
12
|
+
|
13
|
+
# Process arguments
|
14
|
+
options = args.extract_options!
|
15
|
+
options = options.symbolize_keys.reverse_merge(:vcs => :git)
|
16
|
+
filepaths = args.join(' ')
|
17
|
+
|
18
|
+
# Validate options
|
19
|
+
if options[:vcs] != :git
|
20
|
+
raise 'Git is currently the only supported VCS.' and return
|
21
|
+
end
|
22
|
+
|
23
|
+
@@last_commit_ids ||= {}
|
24
|
+
if @@last_commit_ids[filepaths].blank?
|
25
|
+
h = `git log -1 --pretty=format:%h #{filepaths} 2>/dev/null`
|
26
|
+
# `h` has either the abbreviated Git commit hash or an empty string
|
27
|
+
@@last_commit_ids[filepaths] = h if h.present?
|
28
|
+
end
|
29
|
+
@@last_commit_ids[filepaths]
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.last_bundle_commit_id(bundle, type)
|
33
|
+
# Usage:
|
34
|
+
#
|
35
|
+
# AssetHat.last_bundle_commit_id('application', :css)
|
36
|
+
#
|
37
|
+
# Returns a string of the latest commit ID for the given bundle, based
|
38
|
+
# on which of its files were most recently modified in the repository. If
|
39
|
+
# no ID can be found, `nil` is returned.
|
40
|
+
|
41
|
+
# Process arguments
|
42
|
+
type = type.to_sym
|
43
|
+
unless TYPES.include?(type)
|
44
|
+
raise "Unknown type \"#{type}\"; should be one of: #{TYPES.join(', ')}."
|
45
|
+
return
|
46
|
+
end
|
47
|
+
|
48
|
+
# Default to `{:css => {}, :js => {}}`
|
49
|
+
@@last_bundle_commit_ids ||=
|
50
|
+
TYPES.inject({}) { |hsh, t| hsh.merge(t => {}) }
|
51
|
+
|
52
|
+
if @@last_bundle_commit_ids[type][bundle].blank?
|
53
|
+
dir = self.assets_dir(type)
|
54
|
+
filepaths = self.bundle_filepaths(bundle, type)
|
55
|
+
if filepaths.present?
|
56
|
+
@@last_bundle_commit_ids[type][bundle] = self.last_commit_id(*filepaths)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
@@last_bundle_commit_ids[type][bundle]
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.last_commit_ids ; @@last_commit_ids ; end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module AssetHat
|
2
|
+
def self.version
|
3
|
+
data_filepath = File.join(File.dirname(__FILE__), %w[.. .. VERSION.yml])
|
4
|
+
data = YAML.load(File.open(data_filepath, 'r'))
|
5
|
+
[:major, :minor, :patch, :build].
|
6
|
+
map { |x| data[x] }.reject(&:blank?).join('.')
|
7
|
+
end
|
8
|
+
|
9
|
+
VERSION = self.version
|
10
|
+
|
11
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
@@ -0,0 +1 @@
|
|
1
|
+
/* [placeholder] */
|
data/rails/init.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
::ActionView::Base.send(:include, AssetHatHelper)
|
2
|
+
|
3
|
+
# Precalculate (and memoize) asset commit IDs
|
4
|
+
AssetHat::TYPES.each do |type|
|
5
|
+
next if AssetHat.config[type.to_s].blank? ||
|
6
|
+
AssetHat.config[type.to_s]['bundles'].blank?
|
7
|
+
|
8
|
+
AssetHat.config[type.to_s]['bundles'].keys.each do |bundle|
|
9
|
+
# Memoize commit ID for this bundle
|
10
|
+
AssetHat.last_bundle_commit_id(bundle, type) if AssetHat.cache?
|
11
|
+
|
12
|
+
# Memoize commit IDs for each file in this bundle
|
13
|
+
AssetHat.bundle_filepaths(bundle, type).each do |filepath|
|
14
|
+
AssetHat.last_commit_id(filepath)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. lib asset_hat tasks])
|
@@ -0,0 +1,237 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AssetHatHelperTest < ActionView::TestCase
|
4
|
+
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
|
5
|
+
|
6
|
+
context 'include_css' do
|
7
|
+
context 'with caching enabled' do
|
8
|
+
context 'with minified versions' do
|
9
|
+
setup do
|
10
|
+
@commit_id = '111'
|
11
|
+
flexmock(AssetHat).should_receive(:last_commit_id => @commit_id)
|
12
|
+
end
|
13
|
+
|
14
|
+
should 'include one file by name, and automatically use minified version' do
|
15
|
+
flexmock(AssetHat).should_receive(:asset_exists?).and_return(true)
|
16
|
+
output = include_css('foo', :cache => true)
|
17
|
+
assert_equal css_tag("foo.min.css?#{@commit_id}"), output
|
18
|
+
end
|
19
|
+
|
20
|
+
should 'include one unminified file by name and extension' do
|
21
|
+
output = include_css('foo.css', :cache => true)
|
22
|
+
assert_equal css_tag("foo.css?#{@commit_id}"), output
|
23
|
+
end
|
24
|
+
|
25
|
+
should 'include one minified file by name and extension' do
|
26
|
+
output = include_css('foo.min.css', :cache => true)
|
27
|
+
assert_equal css_tag("foo.min.css?#{@commit_id}"), output
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'include multiple files by name' do
|
31
|
+
flexmock(AssetHat).should_receive(:asset_exists?).and_return(true)
|
32
|
+
expected = %w[foo bar].map do |source|
|
33
|
+
css_tag("#{source}.min.css?#{@commit_id}")
|
34
|
+
end.join("\n")
|
35
|
+
output = include_css('foo', 'bar', :cache => true)
|
36
|
+
assert_equal expected, output
|
37
|
+
end
|
38
|
+
|
39
|
+
should 'include multiple files as a bundle' do
|
40
|
+
bundle = 'css-bundle-1'
|
41
|
+
output = include_css(:bundle => bundle, :cache => true)
|
42
|
+
assert_equal css_tag("bundles/#{bundle}.min.css?#{@commit_id}"), output
|
43
|
+
end
|
44
|
+
end # context 'with minified versions'
|
45
|
+
|
46
|
+
context 'without minified versions' do
|
47
|
+
should 'include one file by name, and automatically use original version' do
|
48
|
+
output = include_css('foo')
|
49
|
+
assert_equal css_tag('foo.css'), output
|
50
|
+
end
|
51
|
+
end # context 'without minified versions'
|
52
|
+
end # context 'with caching enabled'
|
53
|
+
|
54
|
+
context 'with caching disabled' do
|
55
|
+
should 'include one file by name, and automatically use original version' do
|
56
|
+
output = include_css('foo', :cache => false)
|
57
|
+
assert_equal css_tag('foo.css'), output
|
58
|
+
end
|
59
|
+
|
60
|
+
should 'include one unminified file by name and extension' do
|
61
|
+
output = include_css('foo.css', :cache => false)
|
62
|
+
assert_equal css_tag('foo.css'), output
|
63
|
+
end
|
64
|
+
|
65
|
+
should 'include multiple files by name' do
|
66
|
+
expected = %w[foo bar.min].map { |src| css_tag("#{src}.css") }.join("\n")
|
67
|
+
output = include_css('foo', 'bar.min', :cache => false)
|
68
|
+
assert_equal expected, output
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'with real bundle files' do
|
72
|
+
setup do
|
73
|
+
@asset_id = ENV['RAILS_ASSET_ID'] = '222'
|
74
|
+
@config = AssetHat.config
|
75
|
+
end
|
76
|
+
teardown { ENV['RAILS_ASSET_ID'] = nil }
|
77
|
+
|
78
|
+
should 'include a bundle as separate files' do
|
79
|
+
bundle = 'css-bundle-1'
|
80
|
+
expected = @config['css']['bundles'][bundle].map do |source|
|
81
|
+
css_tag("#{source}.css?#{@asset_id}")
|
82
|
+
end.join("\n")
|
83
|
+
output = include_css(:bundle => bundle, :cache => false)
|
84
|
+
assert_equal expected, output
|
85
|
+
end
|
86
|
+
|
87
|
+
should 'include multiple bundles as separate files' do
|
88
|
+
bundles = [1,2,3].map { |i| "css-bundle-#{i}" }
|
89
|
+
expected = bundles.map do |bundle|
|
90
|
+
sources = @config['css']['bundles'][bundle]
|
91
|
+
sources.map { |src| css_tag("#{src}.css?#{@asset_id}") }
|
92
|
+
end.flatten.uniq.join("\n")
|
93
|
+
output = include_css(:bundles => bundles, :cache => false)
|
94
|
+
assert_equal expected, output
|
95
|
+
end
|
96
|
+
end # context 'with real bundle files'
|
97
|
+
end # context 'with caching disabled'
|
98
|
+
end # context 'include_css'
|
99
|
+
|
100
|
+
context 'include_js' do
|
101
|
+
context 'with caching enabled' do
|
102
|
+
context 'with minified versions' do
|
103
|
+
setup do
|
104
|
+
@commit_id = '111'
|
105
|
+
flexmock(AssetHat).should_receive(
|
106
|
+
:last_commit_id => @commit_id,
|
107
|
+
:last_bundle_commit_id => @commit_id
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
should 'include one file by name, and automatically use minified version' do
|
112
|
+
flexmock(AssetHat).should_receive(:asset_exists?).and_return(true)
|
113
|
+
output = include_js('jquery.some-plugin', :cache => true)
|
114
|
+
assert_equal js_tag("jquery.some-plugin.min.js?#{@commit_id}"), output
|
115
|
+
end
|
116
|
+
|
117
|
+
should 'include one unminified file by name and extension' do
|
118
|
+
output = include_js('jquery.some-plugin.js', :cache => true)
|
119
|
+
assert_equal js_tag("jquery.some-plugin.js?#{@commit_id}"), output
|
120
|
+
end
|
121
|
+
|
122
|
+
should 'include one minified file by name and extension' do
|
123
|
+
output = include_js('jquery.some-plugin.min.js', :cache => true)
|
124
|
+
assert_equal js_tag("jquery.some-plugin.min.js?#{@commit_id}"), output
|
125
|
+
end
|
126
|
+
|
127
|
+
should 'include jQuery' do
|
128
|
+
version = AssetHat::JS::Vendors::JQUERY_DEFAULT_VERSION
|
129
|
+
output = include_js(:jquery, :cache => true)
|
130
|
+
assert_equal(
|
131
|
+
js_tag("jquery-#{version}.min.js?#{@commit_id}"), output)
|
132
|
+
end
|
133
|
+
|
134
|
+
should 'include jQuery by version' do
|
135
|
+
version = '1.3.2'
|
136
|
+
output = include_js(:jquery, :version => version, :cache => true)
|
137
|
+
assert_equal(
|
138
|
+
js_tag("jquery-#{version}.min.js?#{@commit_id}"), output)
|
139
|
+
end
|
140
|
+
|
141
|
+
should 'include multiple files by name' do
|
142
|
+
flexmock(AssetHat).should_receive(:asset_exists?).and_return(true)
|
143
|
+
expected = %w[foo jquery.bar].map do |source|
|
144
|
+
js_tag("#{source}.min.js?#{@commit_id}")
|
145
|
+
end.join("\n")
|
146
|
+
output = include_js('foo', 'jquery.bar', :cache => true)
|
147
|
+
assert_equal expected, output
|
148
|
+
end
|
149
|
+
|
150
|
+
should 'include multiple files as a bundle' do
|
151
|
+
bundle = 'js-bundle-1'
|
152
|
+
output = include_js(:bundle => bundle, :cache => true)
|
153
|
+
assert_equal js_tag("bundles/#{bundle}.min.js?#{@commit_id}"), output
|
154
|
+
end
|
155
|
+
|
156
|
+
should 'include multiple bundles' do
|
157
|
+
flexmock(AssetHat).should_receive(:asset_exists?).and_return(true)
|
158
|
+
expected = %w[foo bar].map do |bundle|
|
159
|
+
js_tag("bundles/#{bundle}.min.js?#{@commit_id}")
|
160
|
+
end.join("\n")
|
161
|
+
output = include_js(:bundles => %w[foo bar], :cache => true)
|
162
|
+
assert_equal expected, output
|
163
|
+
end
|
164
|
+
end # context 'with minified versions'
|
165
|
+
|
166
|
+
context 'without minified versions' do
|
167
|
+
should 'include one file by name, and automatically use original version' do
|
168
|
+
output = include_js('jquery.some-plugin', :cache => true)
|
169
|
+
assert_equal js_tag('jquery.some-plugin.js'), output
|
170
|
+
end
|
171
|
+
end # context 'without minified versions'
|
172
|
+
end # context 'with caching enabled'
|
173
|
+
|
174
|
+
context 'with caching disabled' do
|
175
|
+
should 'include one file by name, and automatically use original version' do
|
176
|
+
output = include_js('foo', :cache => false)
|
177
|
+
assert_equal js_tag('foo.js'), output
|
178
|
+
end
|
179
|
+
|
180
|
+
should 'include one unminified file by name and extension' do
|
181
|
+
output = include_js('foo.js', :cache => false)
|
182
|
+
assert_equal js_tag('foo.js'), output
|
183
|
+
end
|
184
|
+
|
185
|
+
should 'include one minified file by name and extension' do
|
186
|
+
output = include_js('foo.min.js', :cache => false)
|
187
|
+
assert_equal js_tag('foo.min.js'), output
|
188
|
+
end
|
189
|
+
|
190
|
+
should 'include multiple files by name' do
|
191
|
+
expected = %w[foo bar.min].map { |src| js_tag("#{src}.js") }.join("\n")
|
192
|
+
output = include_js('foo', 'bar.min', :cache => false)
|
193
|
+
assert_equal expected, output
|
194
|
+
end
|
195
|
+
|
196
|
+
context 'with real bundle files' do
|
197
|
+
setup do
|
198
|
+
@asset_id = ENV['RAILS_ASSET_ID'] = '222'
|
199
|
+
@config = AssetHat.config
|
200
|
+
end
|
201
|
+
teardown { ENV['RAILS_ASSET_ID'] = nil }
|
202
|
+
|
203
|
+
should 'include a bundle as separate files' do
|
204
|
+
bundle = 'js-bundle-1'
|
205
|
+
sources = @config['js']['bundles'][bundle]
|
206
|
+
expected = sources.map { |src| js_tag("#{src}.js?#{@asset_id}") }.join("\n")
|
207
|
+
output = include_js(:bundle => bundle, :cache => false)
|
208
|
+
assert_equal expected, output
|
209
|
+
end
|
210
|
+
|
211
|
+
should 'include multiple bundles as separate files' do
|
212
|
+
bundles = [1,2,3].map { |i| "js-bundle-#{i}" }
|
213
|
+
expected = bundles.map do |bundle|
|
214
|
+
sources = @config['js']['bundles'][bundle]
|
215
|
+
sources.map { |src| js_tag("#{src}.js?#{@asset_id}") }
|
216
|
+
end.flatten.uniq.join("\n")
|
217
|
+
output = include_js(:bundles => bundles, :cache => false)
|
218
|
+
assert_equal expected, output
|
219
|
+
end
|
220
|
+
end # context 'with real bundle files'
|
221
|
+
end # context 'with caching disabled'
|
222
|
+
|
223
|
+
end # context 'include_js'
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
private
|
228
|
+
|
229
|
+
def css_tag(filename)
|
230
|
+
%Q{<link href="/stylesheets/#{filename}" media="screen,projection" rel="stylesheet" type="text/css" />}
|
231
|
+
end
|
232
|
+
|
233
|
+
def js_tag(filename)
|
234
|
+
%Q{<script src="/javascripts/#{filename}" type="text/javascript"></script>}
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AssetHatTest < ActiveSupport::TestCase
|
4
|
+
context 'AssetHat::CSS' do
|
5
|
+
should 'return path to minified file' do
|
6
|
+
assert_equal 'foo/bar/baz.min.css',
|
7
|
+
AssetHat::CSS.min_filepath('foo/bar/baz.css')
|
8
|
+
end
|
9
|
+
|
10
|
+
should 'add asset commit IDs' do
|
11
|
+
commit_id = 111
|
12
|
+
flexmock(AssetHat).should_receive(:last_commit_id => commit_id)
|
13
|
+
flexmock(Rails).should_receive(:public_path => '')
|
14
|
+
|
15
|
+
assert_equal "p{background:url(/images/foo.png?#{commit_id})}",
|
16
|
+
AssetHat::CSS.add_asset_commit_ids(
|
17
|
+
'p{background:url(/images/foo.png)}')
|
18
|
+
end
|
19
|
+
|
20
|
+
should 'add asset hosts' do
|
21
|
+
asset_host = 'http://media%d.example.com'
|
22
|
+
assert_match(
|
23
|
+
/^p\{background:url\(http:\/\/media[\d]\.example\.com\/images\/foo.png\)\}$/,
|
24
|
+
AssetHat::CSS.add_asset_hosts(
|
25
|
+
'p{background:url(/images/foo.png)}', asset_host)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end # context 'AssetHat::CSS'
|
29
|
+
|
30
|
+
context 'AssetHat::JS' do
|
31
|
+
should 'return path to minified file' do
|
32
|
+
assert_equal 'foo/bar/baz.min.js',
|
33
|
+
AssetHat::JS.min_filepath('foo/bar/baz.js')
|
34
|
+
end
|
35
|
+
end # context 'AssetHat::JS'
|
36
|
+
|
37
|
+
should "return a bundle's filenames" do
|
38
|
+
assert_equal %w[css-file-1-1 css-file-1-2 css-file-1-3],
|
39
|
+
AssetHat.bundle_filenames('css-bundle-1', :css)
|
40
|
+
end
|
41
|
+
|
42
|
+
should "return a bundle's filepaths" do
|
43
|
+
expected = [1,2,3].map { |i| "public/stylesheets/css-file-1-#{i}.css" }
|
44
|
+
assert_equal expected, AssetHat.bundle_filepaths('css-bundle-1', :css)
|
45
|
+
end
|
46
|
+
end
|