juicer 1.0.3 → 1.0.4
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/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
|