juicer 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -0
- data/Readme.rdoc +12 -4
- data/VERSION +1 -1
- data/lib/juicer.rb +1 -1
- data/lib/juicer/asset/path.rb +1 -1
- data/lib/juicer/cache_buster.rb +21 -5
- data/lib/juicer/command/merge.rb +9 -4
- data/lib/juicer/merger/stylesheet_merger.rb +0 -1
- data/lib/juicer/minifyer/closure_compiler.rb +1 -1
- data/test/data/css/test3.css +12 -0
- data/test/test_helper.rb +17 -0
- data/test/unit/juicer/cache_buster_test.rb +25 -1
- data/test/unit/juicer/css_cache_buster_test.rb +21 -0
- metadata +4 -3
data/History.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
== 1.0.4 / 2010-05-26
|
2
|
+
* Brought to you by Elliott Wood, two-fish.com
|
3
|
+
* Added "rails" cache-buster type for cache-buster stamps that are identical
|
4
|
+
to those generated by Rails'
|
5
|
+
* --all-hosts-local is no longer dependent upon command-line positioning.
|
6
|
+
* Ensured that URLs don't receive two cache busters, even when asset
|
7
|
+
host cycling is used.
|
8
|
+
|
1
9
|
== 1.0.3 / 2010-04-15
|
2
10
|
* Update YUI Compressor installer to find the download link in YUI's updated markup
|
3
11
|
Pacthed by Olle Jonsson (http://ollehost.dk/blog/)
|
data/Readme.rdoc
CHANGED
@@ -4,6 +4,7 @@ Official URL: http://github.com/cjohansen/juicer/tree/master
|
|
4
4
|
Christian Johansen (http://www.cjohansen.no) and contributors:
|
5
5
|
|
6
6
|
* Morgan Roderick (http://roderick.dk)
|
7
|
+
* Elliott Wood (http://two-fish.com)
|
7
8
|
* Pavel Valodzka (http://github.com/valodzka)
|
8
9
|
* Daniel Stockman (http://evocateur.org/)
|
9
10
|
* Aaron Suggs (http://ktheory.com)
|
@@ -69,15 +70,19 @@ Juicer supports so-called cache busters. A cache buster is a pattern in a path
|
|
69
70
|
whose only purpose is to "trick" browsers to redownload a file when it has
|
70
71
|
changed in cases where a far future expires header is used.
|
71
72
|
|
72
|
-
There are
|
73
|
-
so: http://assets/images/1.png?
|
74
|
-
|
73
|
+
There are three types of cache busters. Soft cache busters (the default) add a
|
74
|
+
parameter to the URL, like so: http://assets/images/1.png?jcb=1234567890, ie the
|
75
|
+
letters "jcb" (as in Juicer Cache Buster) and then the timestamp of the files mtime.
|
76
|
+
|
77
|
+
Rails cache busters are similar, except they leave out the parameter name. This
|
78
|
+
mimics the behavior of the image_tag helper in the Ruby on Rails framework, so that
|
79
|
+
images called from both CSS and from Rails views will have identical URLs.
|
75
80
|
|
76
81
|
Unfortunately, the popular web proxy Squid shipped for some time with a default
|
77
82
|
configuration which would not treat a URL as a "new" URL if the only thing changed
|
78
83
|
was the GET parameters. For this reason Juicer provides hard cache busters.
|
79
84
|
|
80
|
-
Hard cache busters result in URLs such as: http://assets/images/1-
|
85
|
+
Hard cache busters result in URLs such as: http://assets/images/1-jcb1234567890.png,
|
81
86
|
ie URLs that require either renaming of files, or (more conveniently) a web
|
82
87
|
server configuration that will forward URLs to the right files anyway.
|
83
88
|
|
@@ -287,6 +292,9 @@ Will tell you about other dependencies that might be missing on your system.
|
|
287
292
|
* Aaron Suggs (http://ktheory.com)
|
288
293
|
Added support for depending on directories
|
289
294
|
Fixed installers on 1.0 branch
|
295
|
+
* Elliott Wood (http://two-fish.com)
|
296
|
+
Added "rails" cache buster type
|
297
|
+
Fixed issues with asset host cycling
|
290
298
|
|
291
299
|
== LICENSE:
|
292
300
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.4
|
data/lib/juicer.rb
CHANGED
data/lib/juicer/asset/path.rb
CHANGED
data/lib/juicer/cache_buster.rb
CHANGED
@@ -80,15 +80,18 @@ module Juicer
|
|
80
80
|
#
|
81
81
|
def self.path(file, type = :soft, parameter = DEFAULT_PARAMETER)
|
82
82
|
return file if file =~ /data:.*;base64/
|
83
|
+
type = [:soft, :hard, :rails].include?(type) ? type : :soft
|
84
|
+
parameter = nil if type == :rails
|
83
85
|
file = self.clean(file, parameter)
|
84
86
|
filename = file.split("?").first
|
85
87
|
raise ArgumentError.new("#{file} could not be found") unless File.exists?(filename)
|
86
88
|
mtime = File.mtime(filename).to_i
|
87
|
-
type = [:soft, :hard].include?(type) ? type : :soft
|
88
89
|
|
89
90
|
if type == :soft
|
90
91
|
parameter = "#{parameter}=".sub(/^=$/, '')
|
91
92
|
return "#{file}#{file.index('?') ? '&' : '?'}#{parameter}#{mtime}"
|
93
|
+
elsif type == :rails
|
94
|
+
return "#{file}#{file.index('?') ? '' : "?#{mtime}"}"
|
92
95
|
end
|
93
96
|
|
94
97
|
file.sub(/(\.[^\.]+$)/, "-#{parameter}#{mtime}" + '\1')
|
@@ -116,16 +119,29 @@ module Juicer
|
|
116
119
|
self.path(file, :soft, parameter)
|
117
120
|
end
|
118
121
|
|
122
|
+
#
|
123
|
+
# Add a Rails-style cache buster to a filename. Results in filenames of the
|
124
|
+
# form: <tt>file.suffix?[timestamp]</tt>, ie <tt>images/logo.png?1234567890</tt>
|
125
|
+
# which is the format used by Rails' image_tag helper.
|
126
|
+
#
|
127
|
+
def self.rails(file)
|
128
|
+
self.path(file, :rails)
|
129
|
+
end
|
130
|
+
|
119
131
|
#
|
120
132
|
# Remove cache buster from a URL for a given parameter name. Parameter name is
|
121
133
|
# "cb" by default.
|
122
134
|
#
|
123
135
|
def self.clean(file, parameter = DEFAULT_PARAMETER)
|
124
|
-
|
125
|
-
|
126
|
-
|
136
|
+
if "#{parameter}".length == 0
|
137
|
+
return file.sub(/\?\d+$/, '')
|
138
|
+
else
|
139
|
+
query_param = "#{parameter}="
|
140
|
+
new_file = file.sub(/#{query_param}\d+&?/, "").sub(/(\?|&)$/, "")
|
141
|
+
return new_file unless new_file == file
|
127
142
|
|
128
|
-
|
143
|
+
file.sub(/-#{parameter}\d+(\.\w+)($|\?)/, '\1\2')
|
144
|
+
end
|
129
145
|
end
|
130
146
|
end
|
131
147
|
end
|
data/lib/juicer/command/merge.rb
CHANGED
@@ -68,15 +68,17 @@ the compressor the path should be the path to where the jar file is found.
|
|
68
68
|
opt.on("-l", "--local-hosts hosts", "Host names that are served from --document-root (can be given cache busters). Comma separated") do |hosts|
|
69
69
|
@local_hosts = hosts.split(",")
|
70
70
|
end
|
71
|
-
opt.on("", "--all-hosts-local", "Treat all hosts as local (ie served from --document-root") {
|
71
|
+
opt.on("", "--all-hosts-local", "Treat all hosts as local (ie served from --document-root)") { @all_hosts_local = true }
|
72
72
|
opt.on("-r", "--relative-urls", "Convert all referenced URLs to relative URLs. Requires --document-root if\n" +
|
73
73
|
(" " * 37) + "absolute URLs are used. Only valid for CSS files") { |t| @relative_urls = true }
|
74
74
|
opt.on("-b", "--absolute-urls", "Convert all referenced URLs to absolute URLs. Requires --document-root.\n" +
|
75
75
|
(" " * 37) + "Works with cycled asset hosts. Only valid for CSS files") { |t| @absolute_urls = true }
|
76
76
|
opt.on("-d", "--document-root dir", "Path to resolve absolute URLs relative to") { |path| @document_root = path }
|
77
|
-
opt.on("-c", "--cache-buster type", "none, soft or hard. Default is soft, which adds timestamps to
|
78
|
-
(" " * 37) + "URLs as query parameters. None leaves URLs untouched
|
79
|
-
|
77
|
+
opt.on("-c", "--cache-buster type", "none, soft, rails, or hard. Default is soft, which adds timestamps to\n" +
|
78
|
+
(" " * 37) + "reference URLs as query parameters. None leaves URLs untouched, rails adds\n" +
|
79
|
+
(" " * 37) + "timestamps in the same format as Rails' image_tag helper, and hard alters\n" +
|
80
|
+
(" " * 37) + "file names") do |type|
|
81
|
+
@cache_buster = [:soft, :hard, :rails].include?(type.to_sym) ? type.to_sym : nil
|
80
82
|
end
|
81
83
|
opt.on("-e", "--embed-images type", "none or data_uri. Default is none. Data_uri embeds images using Base64 encoding\n" +
|
82
84
|
(" " * 37) + "None leaves URLs untouched. Candiate images must be flagged with '?embed=true to be considered") do |embed|
|
@@ -92,6 +94,9 @@ the compressor the path should be the path to where the jar file is found.
|
|
92
94
|
@log.fatal "Please provide atleast one input file"
|
93
95
|
raise SystemExit.new("Please provide atleast one input file")
|
94
96
|
end
|
97
|
+
|
98
|
+
# Copy hosts to local_hosts if --all-hosts-local was specified
|
99
|
+
@local_hosts = @hosts if @all_hosts_local
|
95
100
|
|
96
101
|
# Figure out which file to output to
|
97
102
|
output = output(files.first)
|
@@ -62,7 +62,7 @@ module Juicer
|
|
62
62
|
|
63
63
|
out_dir = File.dirname(output)
|
64
64
|
FileUtils.mkdir_p(out_dir) unless File.exists?(out_dir)
|
65
|
-
|
65
|
+
execute(%Q{-jar "#{locate_jar}"#{jar_args} --js_output_file "#{output}" --js "#{file}"})
|
66
66
|
|
67
67
|
File.delete(file) if use_tmp
|
68
68
|
end
|
data/test/test_helper.rb
CHANGED
@@ -147,6 +147,23 @@ p { background: url(/a2.css); }
|
|
147
147
|
|
148
148
|
mkfile(@dir, 'path_test2.css', css)
|
149
149
|
|
150
|
+
css = <<-CSS
|
151
|
+
body {
|
152
|
+
background: url(http://assets1/images/1.png);
|
153
|
+
}
|
154
|
+
|
155
|
+
h1 {
|
156
|
+
background: url(http://assets2/css/2.gif);
|
157
|
+
background: url(http://assets3/a1.css) 0 0 no-repeat;
|
158
|
+
}
|
159
|
+
|
160
|
+
h2 {
|
161
|
+
background: url(http://assets2/css/2.gif) no-repeat;
|
162
|
+
}
|
163
|
+
CSS
|
164
|
+
|
165
|
+
mkfile(css_dir, 'test3.css', css)
|
166
|
+
|
150
167
|
mkfile(@dir, 'Changelog.txt', "2008.02.09 | stb-base 1.29\n\nFEATURE: Core | Bla bla bla bla bla\nFEATURE: UI: | Bla bla bla bla bla\n\n\n2008.02.09 | stb-base 1.29\n\nFEATURE: Core | Bla bla bla bla bla\nFEATURE: UI: | Bla bla bla bla bla\n")
|
151
168
|
|
152
169
|
# my_app.js depends on the pkg directory
|
@@ -26,10 +26,17 @@ class CacheBusterTest < Test::Unit::TestCase
|
|
26
26
|
assert_equal @filename, Juicer::CacheBuster.clean("#@filename?1234567890", nil)
|
27
27
|
end
|
28
28
|
|
29
|
+
should "not destroy numeric file names with no cache buster name" do
|
30
|
+
@numeric_filename = "815.gif"
|
31
|
+
File.open(@numeric_filename, "w") { |f| f.puts "Testing" }
|
32
|
+
assert_equal @numeric_filename, Juicer::CacheBuster.clean("#@numeric_filename?1234567890", nil)
|
33
|
+
File.delete(@numeric_filename)
|
34
|
+
end
|
35
|
+
|
29
36
|
should "remove cache buster query parameters with custom name" do
|
30
37
|
assert_equal @filename, Juicer::CacheBuster.clean("#@filename?cb=1234567890", :cb)
|
31
38
|
end
|
32
|
-
|
39
|
+
|
33
40
|
should "remove hard cache buster" do
|
34
41
|
assert_equal @filename, Juicer::CacheBuster.clean(@filename.sub(/(\.txt)/, '-jcb1234567890\1'))
|
35
42
|
end
|
@@ -72,6 +79,23 @@ class CacheBusterTest < Test::Unit::TestCase
|
|
72
79
|
end
|
73
80
|
end
|
74
81
|
|
82
|
+
context "creating rails-style cache busters" do
|
83
|
+
should "clean file before adding new cache buster" do
|
84
|
+
cache_buster = "1234567890"
|
85
|
+
assert_no_match /#{cache_buster}/, Juicer::CacheBuster.rails("#@filename?#{cache_buster}")
|
86
|
+
end
|
87
|
+
|
88
|
+
should "append no cache buster when parameters exist" do
|
89
|
+
parameters = "id=1"
|
90
|
+
assert_match /#{parameters}/, Juicer::CacheBuster.rails("#@filename?#{parameters}")
|
91
|
+
end
|
92
|
+
|
93
|
+
should "include only mtime as query parameter" do
|
94
|
+
mtime = File.mtime(@filename).to_i
|
95
|
+
assert_equal "#@filename?#{mtime}", Juicer::CacheBuster.rails(@filename)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
75
99
|
context "hard cache busters" do
|
76
100
|
setup { @filename.sub!(/\.txt/, '') }
|
77
101
|
teardown { @filename = "#@filename.txt" }
|
@@ -37,6 +37,15 @@ class TestCssCacheBuster < Test::Unit::TestCase
|
|
37
37
|
|
38
38
|
assert_no_match /2\.gif\?jcb=\d+\?jcb=/, File.read(file)
|
39
39
|
end
|
40
|
+
|
41
|
+
should "not add multiple cache busters when asset host cycling is used" do
|
42
|
+
file = path("css/test3.css")
|
43
|
+
buster = Juicer::CssCacheBuster.new( { :hosts => [ 'http://assets1', 'http://assets2', 'http://assets3' ], :document_root => './test/data' } )
|
44
|
+
buster.save file
|
45
|
+
|
46
|
+
assert_no_match /2\.gif\?jcb=\d+\?jcb=/, File.read(file)
|
47
|
+
end
|
48
|
+
|
40
49
|
end
|
41
50
|
|
42
51
|
context "absolute paths" do
|
@@ -75,6 +84,18 @@ class TestCssCacheBuster < Test::Unit::TestCase
|
|
75
84
|
end
|
76
85
|
end
|
77
86
|
|
87
|
+
context "rails cache busters" do
|
88
|
+
should "should append mtime to urls" do
|
89
|
+
File.open(path("a2.css"), "w") { |f| f.puts "" }
|
90
|
+
file = path("path_test2.css")
|
91
|
+
output = path("path_test3.css")
|
92
|
+
buster = Juicer::CssCacheBuster.new :document_root => path(""), :type => :rails
|
93
|
+
buster.save file, output
|
94
|
+
|
95
|
+
buster.urls(output).each { |asset| assert_match /\?\d+$/, asset.path }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
78
99
|
context "hard cache busters" do
|
79
100
|
should "should alter file name" do
|
80
101
|
File.open(path("a2.css"), "w") { |f| f.puts "" }
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 1.0.
|
8
|
+
- 4
|
9
|
+
version: 1.0.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Christian Johansen
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-05-31 00:00:00 +02:00
|
18
18
|
default_executable: juicer
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -178,6 +178,7 @@ files:
|
|
178
178
|
- test/data/css/2.gif
|
179
179
|
- test/data/css/test.css
|
180
180
|
- test/data/css/test2.css
|
181
|
+
- test/data/css/test3.css
|
181
182
|
- test/data/d1.css
|
182
183
|
- test/data/images/1.png
|
183
184
|
- test/data/my_app.js
|