psyho_juicer 1.0.0 → 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +11 -0
- data/History.txt +33 -0
- data/Readme.rdoc +16 -4
- data/VERSION +1 -1
- data/lib/juicer/asset/path.rb +6 -10
- data/lib/juicer/cache_buster.rb +53 -13
- data/lib/juicer/command/merge.rb +14 -6
- data/lib/juicer/css_cache_buster.rb +6 -4
- data/lib/juicer/dependency_resolver/css_dependency_resolver.rb +1 -1
- data/lib/juicer/image_embed.rb +18 -20
- data/lib/juicer/install/yui_compressor_installer.rb +2 -1
- data/lib/juicer/merger/stylesheet_merger.rb +5 -5
- data/lib/juicer/minifyer/closure_compiler.rb +1 -1
- data/lib/juicer.rb +1 -1
- data/lib/psyho_juicer.rb +1 -0
- data/test/data/Changelog.txt +10 -0
- data/test/data/a.css +3 -0
- data/test/data/a.js +5 -0
- data/test/data/a1.css +5 -0
- data/test/data/b.css +1 -0
- data/test/data/b.js +5 -0
- data/test/data/b1.css +5 -0
- data/test/data/b2.css +5 -0
- data/test/data/c1.css +3 -0
- data/test/data/css/2.gif +1 -0
- data/test/data/css/test.css +15 -0
- data/test/data/css/test2.css +1 -0
- data/test/data/css/test3.css +12 -0
- data/test/data/d1.css +3 -0
- data/test/data/images/1.png +1 -0
- data/test/data/my_app.js +2 -0
- data/test/data/not-ok.js +2 -0
- data/test/data/ok.js +3 -0
- data/test/data/path_test.css +5 -0
- data/test/data/path_test2.css +14 -0
- data/test/data/pkg/module/moda.js +2 -0
- data/test/data/pkg/module/modb.js +3 -0
- data/test/data/pkg/pkg.js +1 -0
- data/test/fixtures/git-tracked-file.txt +1 -0
- data/test/fixtures/yui-download.html +103 -243
- data/test/test_helper.rb +27 -1
- data/test/unit/juicer/asset/path_test.rb +7 -1
- data/test/unit/juicer/cache_buster_test.rb +95 -5
- data/test/unit/juicer/command/util_test.rb +1 -1
- data/test/unit/juicer/css_cache_buster_test.rb +127 -32
- data/test/unit/juicer/image_embed_test.rb +35 -0
- data/test/unit/juicer/merger/stylesheet_merger_test.rb +175 -109
- data/test/unit/juicer/minifyer/closure_compressor_test.rb +3 -3
- metadata +68 -21
data/Gemfile
ADDED
data/History.txt
CHANGED
@@ -1,3 +1,36 @@
|
|
1
|
+
== 1.0.6 / 2010-06-29
|
2
|
+
* Fix bug where image embedding could not see the document root,
|
3
|
+
resulting in missing images (Jakub Pawlowicz)
|
4
|
+
|
5
|
+
== 1.0.5 / 2010-06-06
|
6
|
+
* No more Regexp warnings on Ruby 1.9.1
|
7
|
+
* Cycle hosts for relative paths
|
8
|
+
* Allow hostnames with no protocol (i.e. //myassets)
|
9
|
+
|
10
|
+
== 1.0.4 / 2010-05-26
|
11
|
+
* Fix issue (GH-22) where Closure Compiler would not work due to wrong
|
12
|
+
command line arguments passed by Juicer
|
13
|
+
* Brought to you by Elliott Wood, two-fish.com:
|
14
|
+
* Added "rails" cache-buster type for cache-buster stamps that are identical
|
15
|
+
to those generated by Rails'
|
16
|
+
* --all-hosts-local is no longer dependent upon command-line positioning.
|
17
|
+
* Ensured that URLs don't receive two cache busters, even when asset
|
18
|
+
host cycling is used.
|
19
|
+
|
20
|
+
== 1.0.3 / 2010-04-15
|
21
|
+
* Update YUI Compressor installer to find the download link in YUI's updated markup
|
22
|
+
Pacthed by Olle Jonsson (http://ollehost.dk/blog/)
|
23
|
+
* Make stylesheet merger properly handle quoted URLs, fixes GH issue 20
|
24
|
+
|
25
|
+
== 1.0.2 / 2010-03-19
|
26
|
+
* Don't add multiple cache busters
|
27
|
+
|
28
|
+
== 1.0.1 / 2010-03-03
|
29
|
+
* Don't crash when trying to cache bust non-existent files, simply
|
30
|
+
skip them
|
31
|
+
* Don't attempt to cache bust data urls (contributed by
|
32
|
+
http://github.com/psyho/juicer)
|
33
|
+
|
1
34
|
== 1.0.0 / 2010-02-24
|
2
35
|
* Make sure @import rules with url is removed when files are merged
|
3
36
|
* Dependency resolver supports depending on directories
|
data/Readme.rdoc
CHANGED
@@ -4,9 +4,12 @@ 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)
|
11
|
+
* Olle Jonsson (http://ollehost.dk/blog/)
|
12
|
+
* Jakub Pawlowicz (http://blog.jakubpawlowicz.com)
|
10
13
|
|
11
14
|
== DESCRIPTION:
|
12
15
|
|
@@ -68,15 +71,19 @@ Juicer supports so-called cache busters. A cache buster is a pattern in a path
|
|
68
71
|
whose only purpose is to "trick" browsers to redownload a file when it has
|
69
72
|
changed in cases where a far future expires header is used.
|
70
73
|
|
71
|
-
There are
|
72
|
-
so: http://assets/images/1.png?
|
73
|
-
|
74
|
+
There are three types of cache busters. Soft cache busters (the default) add a
|
75
|
+
parameter to the URL, like so: http://assets/images/1.png?jcb=1234567890, ie the
|
76
|
+
letters "jcb" (as in Juicer Cache Buster) and then the timestamp of the files mtime.
|
77
|
+
|
78
|
+
Rails cache busters are similar, except they leave out the parameter name. This
|
79
|
+
mimics the behavior of the image_tag helper in the Ruby on Rails framework, so that
|
80
|
+
images called from both CSS and from Rails views will have identical URLs.
|
74
81
|
|
75
82
|
Unfortunately, the popular web proxy Squid shipped for some time with a default
|
76
83
|
configuration which would not treat a URL as a "new" URL if the only thing changed
|
77
84
|
was the GET parameters. For this reason Juicer provides hard cache busters.
|
78
85
|
|
79
|
-
Hard cache busters result in URLs such as: http://assets/images/1-
|
86
|
+
Hard cache busters result in URLs such as: http://assets/images/1-jcb1234567890.png,
|
80
87
|
ie URLs that require either renaming of files, or (more conveniently) a web
|
81
88
|
server configuration that will forward URLs to the right files anyway.
|
82
89
|
|
@@ -286,6 +293,11 @@ Will tell you about other dependencies that might be missing on your system.
|
|
286
293
|
* Aaron Suggs (http://ktheory.com)
|
287
294
|
Added support for depending on directories
|
288
295
|
Fixed installers on 1.0 branch
|
296
|
+
* Elliott Wood (http://two-fish.com)
|
297
|
+
Added "rails" cache buster type
|
298
|
+
Fixed issues with asset host cycling
|
299
|
+
* Jakub Pawlowicz (http://blog.jakubpawlowicz.com)
|
300
|
+
Fixed issue with embedding images that weren't found
|
289
301
|
|
290
302
|
== LICENSE:
|
291
303
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.7
|
data/lib/juicer/asset/path.rb
CHANGED
@@ -63,7 +63,7 @@ module Juicer
|
|
63
63
|
# Directory served as root through a web server, see Juicer::Asset::Path#initialize
|
64
64
|
attr_reader :document_root
|
65
65
|
|
66
|
-
@@scheme_pattern = %r{^[a-zA-Z]{3,5}
|
66
|
+
@@scheme_pattern = %r{^([a-zA-Z]{3,5}:)?//}
|
67
67
|
|
68
68
|
#
|
69
69
|
# Initialize asset at <tt>path</tt>. Accepts an optional hash of options:
|
@@ -244,16 +244,12 @@ module Juicer
|
|
244
244
|
def path_with_cache_buster(path, options = {})
|
245
245
|
return path if !options.key?(:cache_buster) && options[:cache_buster_type].nil?
|
246
246
|
|
247
|
-
buster_path = nil
|
248
247
|
type = options[:cache_buster_type] || :soft
|
249
248
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
# If :cache_buster wasn't specified, rely on default value
|
255
|
-
buster_path = Juicer::CacheBuster.send(type, filename)
|
256
|
-
end
|
249
|
+
buster_options = {:revision_type => options[:cache_buster_format]}
|
250
|
+
buster_options[:parameter] = options[:cache_buster] if options.key?(:cache_buster)
|
251
|
+
|
252
|
+
buster_path = Juicer::CacheBuster.send(type, filename, buster_options)
|
257
253
|
|
258
254
|
path.sub(File.basename(path), File.basename(buster_path))
|
259
255
|
end
|
@@ -265,7 +261,7 @@ module Juicer
|
|
265
261
|
hosts.each do |host|
|
266
262
|
return path if path !~ @@scheme_pattern
|
267
263
|
|
268
|
-
path.sub
|
264
|
+
path = path.sub(%r{^#{host}}, '')
|
269
265
|
end
|
270
266
|
|
271
267
|
return path
|
data/lib/juicer/cache_buster.rb
CHANGED
@@ -78,20 +78,34 @@ module Juicer
|
|
78
78
|
# See <tt>#hard</tt> and <tt>#soft</tt> for explanation of the parameter
|
79
79
|
# argument.
|
80
80
|
#
|
81
|
-
def self.path(file,
|
81
|
+
def self.path(file, opts = {})
|
82
82
|
return file if file =~ /data:.*;base64/
|
83
|
+
|
84
|
+
type = opts[:type]
|
85
|
+
type = [:soft, :hard, :rails].include?(type) ? type : :soft
|
86
|
+
|
87
|
+
parameter = opts.key?(:parameter) ? opts[:parameter] : DEFAULT_PARAMETER
|
88
|
+
parameter = nil if type == :rails
|
89
|
+
|
83
90
|
file = self.clean(file, parameter)
|
84
91
|
filename = file.split("?").first
|
92
|
+
|
93
|
+
revision_type = opts[:revision_type]
|
94
|
+
revision_type = :mtime if type == :rails
|
95
|
+
revision_type = [:git, :mtime].include?(revision_type) ? revision_type : :mtime
|
96
|
+
|
85
97
|
raise ArgumentError.new("#{file} could not be found") unless File.exists?(filename)
|
86
|
-
|
87
|
-
|
98
|
+
|
99
|
+
revision = Revision.send(revision_type, filename)
|
88
100
|
|
89
101
|
if type == :soft
|
90
102
|
parameter = "#{parameter}=".sub(/^=$/, '')
|
91
|
-
return "#{file}#{file.index('?') ? '&' : '?'}#{parameter}#{
|
103
|
+
return "#{file}#{file.index('?') ? '&' : '?'}#{parameter}#{revision}"
|
104
|
+
elsif type == :rails
|
105
|
+
return "#{file}#{file.index('?') ? '' : "?#{revision}"}"
|
92
106
|
end
|
93
107
|
|
94
|
-
file.sub(/(\.[^\.]+$)/, "-#{parameter}#{
|
108
|
+
file.sub(/(\.[^\.]+$)/, "-#{parameter}#{revision}" + '\1')
|
95
109
|
end
|
96
110
|
|
97
111
|
#
|
@@ -101,8 +115,8 @@ module Juicer
|
|
101
115
|
# <tt>images/logo-cb1234567890.png</tt> which is the case for the default
|
102
116
|
# parameter name "cb" (as in *c*ache *b*uster).
|
103
117
|
#
|
104
|
-
def self.hard(file,
|
105
|
-
self.path(file, :hard
|
118
|
+
def self.hard(file, opts = {})
|
119
|
+
self.path(file, opts.merge(:type => :hard))
|
106
120
|
end
|
107
121
|
|
108
122
|
#
|
@@ -112,20 +126,46 @@ module Juicer
|
|
112
126
|
# <tt>images/logo.png?cb=1234567890</tt> which is the case for the default
|
113
127
|
# parameter name "cb" (as in *c*ache *b*uster).
|
114
128
|
#
|
115
|
-
def self.soft(file,
|
116
|
-
self.path(file, :soft
|
129
|
+
def self.soft(file, opts = {})
|
130
|
+
self.path(file, opts.merge(:type => :soft))
|
117
131
|
end
|
118
132
|
|
133
|
+
#
|
134
|
+
# Add a Rails-style cache buster to a filename. Results in filenames of the
|
135
|
+
# form: <tt>file.suffix?[timestamp]</tt>, ie <tt>images/logo.png?1234567890</tt>
|
136
|
+
# which is the format used by Rails' image_tag helper.
|
137
|
+
#
|
138
|
+
def self.rails(file, opts = {})
|
139
|
+
self.path(file, opts.merge(:type => :rails))
|
140
|
+
end
|
141
|
+
|
119
142
|
#
|
120
143
|
# Remove cache buster from a URL for a given parameter name. Parameter name is
|
121
144
|
# "cb" by default.
|
122
145
|
#
|
123
146
|
def self.clean(file, parameter = DEFAULT_PARAMETER)
|
124
|
-
|
125
|
-
|
126
|
-
|
147
|
+
if "#{parameter}".length == 0
|
148
|
+
return file.sub(/\?\d+$/, '')
|
149
|
+
else
|
150
|
+
query_param = "#{parameter}="
|
151
|
+
new_file = file.sub(/#{query_param}\d+&?/, "").sub(/(\?|&)$/, "")
|
152
|
+
return new_file unless new_file == file
|
127
153
|
|
128
|
-
|
154
|
+
file.sub(/-#{parameter}\d+(\.\w+)($|\?)/, '\1\2')
|
155
|
+
end
|
129
156
|
end
|
157
|
+
|
158
|
+
module Revision
|
159
|
+
def self.git(filename)
|
160
|
+
version = %x{git log --pretty=format:%H -1 -- #{filename} 2> /dev/null}
|
161
|
+
version = %x{git log --pretty=format:%H -1 2> /dev/null} if version == '' || version == nil
|
162
|
+
version = 'unknown' if version == '' || version == nil
|
163
|
+
return version
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.mtime(filename)
|
167
|
+
File.mtime(filename).to_i
|
168
|
+
end
|
169
|
+
end
|
130
170
|
end
|
131
171
|
end
|
data/lib/juicer/command/merge.rb
CHANGED
@@ -68,15 +68,20 @@ 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
|
82
|
+
end
|
83
|
+
opt.on("-C", "--cache-buster-format format", "Format of the cache buster. Allowed mtime (timestamp) and git (git commit hash). Default is mtime") do |format|
|
84
|
+
@cache_buster_format = (format.to_sym == :git) ? :git : :mtime
|
80
85
|
end
|
81
86
|
opt.on("-e", "--embed-images type", "none or data_uri. Default is none. Data_uri embeds images using Base64 encoding\n" +
|
82
87
|
(" " * 37) + "None leaves URLs untouched. Candiate images must be flagged with '?embed=true to be considered") do |embed|
|
@@ -93,6 +98,9 @@ the compressor the path should be the path to where the jar file is found.
|
|
93
98
|
raise SystemExit.new("Please provide atleast one input file")
|
94
99
|
end
|
95
100
|
|
101
|
+
# Copy hosts to local_hosts if --all-hosts-local was specified
|
102
|
+
@local_hosts = @hosts if @all_hosts_local
|
103
|
+
|
96
104
|
# Figure out which file to output to
|
97
105
|
output = output(files.first)
|
98
106
|
|
@@ -180,7 +188,7 @@ the compressor the path should be the path to where the jar file is found.
|
|
180
188
|
#
|
181
189
|
def cache_buster(file)
|
182
190
|
return nil if !file || file !~ /\.css$/ || @cache_buster.nil?
|
183
|
-
Juicer::CssCacheBuster.new(:document_root => @document_root, :type => @cache_buster, :hosts => @local_hosts)
|
191
|
+
Juicer::CssCacheBuster.new(:document_root => @document_root, :type => @cache_buster, :hosts => @local_hosts, :format => @cache_buster_format)
|
184
192
|
end
|
185
193
|
|
186
194
|
#
|
@@ -188,7 +196,7 @@ the compressor the path should be the path to where the jar file is found.
|
|
188
196
|
#
|
189
197
|
def image_embed(file)
|
190
198
|
return nil if !file || file !~ /\.css$/ || @image_embed_type.nil?
|
191
|
-
Juicer::ImageEmbed.new( :type => @image_embed_type )
|
199
|
+
Juicer::ImageEmbed.new(:document_root => @document_root, :type => @image_embed_type )
|
192
200
|
end
|
193
201
|
|
194
202
|
#
|
@@ -29,6 +29,7 @@ module Juicer
|
|
29
29
|
@document_root.sub!(%r{/?$}, "") if @document_root
|
30
30
|
@type = options[:type] || :soft
|
31
31
|
@hosts = (options[:hosts] || []).collect { |h| h.sub!(%r{/?$}, "") }
|
32
|
+
@format = options[:format] || :mtime
|
32
33
|
@contents = @base = nil
|
33
34
|
end
|
34
35
|
|
@@ -42,15 +43,16 @@ module Juicer
|
|
42
43
|
|
43
44
|
urls(file).each do |asset|
|
44
45
|
begin
|
45
|
-
next if used.include?(asset.path)
|
46
|
-
@contents.gsub!(asset.path, asset.path(:cache_buster_type => @type))
|
46
|
+
next if used.include?(asset.path)
|
47
|
+
@contents.gsub!(asset.path, asset.path(:cache_buster_type => @type, :cache_buster_format => @format))
|
48
|
+
used.push(asset.path)
|
47
49
|
rescue Errno::ENOENT
|
48
50
|
puts "Unable to locate file #{asset.path}, skipping cache buster"
|
49
51
|
rescue ArgumentError => e
|
50
52
|
if e.message =~ /No document root/
|
51
|
-
|
53
|
+
puts "Unable to resolve path #{asset.path} without :document_root option"
|
52
54
|
else
|
53
|
-
|
55
|
+
puts "Unable to locate #{asset.path}, skipping cache buster"
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
@@ -8,7 +8,7 @@ module Juicer
|
|
8
8
|
class CssDependencyResolver < DependencyResolver
|
9
9
|
# Regexp borrowed from similar project:
|
10
10
|
# http://github.com/cgriego/front-end-blender/tree/master/lib/front_end_architect/blender.rb
|
11
|
-
@@import_pattern = /^\s*@import(?:\surl\(|\s)(['"]?)([^\?'"\)\s]+)(\?(?:[^'"\)]
|
11
|
+
@@import_pattern = /^\s*@import(?:\surl\(|\s)(['"]?)([^\?'"\)\s]+)(\?(?:[^'"\)]*))?\1\)?(?:[^?;]*);?/im
|
12
12
|
|
13
13
|
private
|
14
14
|
def parse(line, imported_file = nil)
|
data/lib/juicer/image_embed.rb
CHANGED
@@ -62,13 +62,13 @@ module Juicer
|
|
62
62
|
begin
|
63
63
|
next if used.include?(asset) || duplicates.include?(asset.path)
|
64
64
|
used << asset
|
65
|
-
|
65
|
+
|
66
66
|
# make sure we do not exceed SIZE_LIMIT
|
67
67
|
new_path = embed_data_uri(asset.filename)
|
68
68
|
|
69
69
|
if new_path.length < SIZE_LIMIT
|
70
70
|
# replace the url in the css file with the data uri
|
71
|
-
@contents.gsub!(asset.path, embed_data_uri(asset.
|
71
|
+
@contents.gsub!(asset.path, embed_data_uri(asset.filename)) if asset.filename.match( /\?embed=true$/ )
|
72
72
|
else
|
73
73
|
Juicer::LOGGER.warn("The final data uri for the image located at #{asset.path.gsub('?embed=true', '')} exceeds #{SIZE_LIMIT} and will not be embedded to maintain compatability.")
|
74
74
|
end
|
@@ -86,25 +86,23 @@ module Juicer
|
|
86
86
|
def embed_data_uri( path )
|
87
87
|
new_path = path
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
|
89
|
+
supported_file_matches = path.match( /(?:\.)(png|gif|jpg|jpeg)(?:\?embed=true)$/i )
|
90
|
+
filetype = supported_file_matches[1] if supported_file_matches
|
91
|
+
|
92
|
+
if ( filetype )
|
93
|
+
filename = path.gsub('?embed=true','')
|
92
94
|
|
93
|
-
if
|
94
|
-
|
95
|
-
|
96
|
-
#
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
new_path = Datafy::make_data_uri( content, content_type )
|
105
|
-
else
|
106
|
-
puts "Unable to locate file #{filename} on local file system, skipping image embedding"
|
107
|
-
end
|
95
|
+
# check if file exists, throw an error if it doesn't exist
|
96
|
+
if File.exist?( filename )
|
97
|
+
|
98
|
+
# read contents of file into memory
|
99
|
+
content = File.read( filename )
|
100
|
+
content_type = "image/#{filetype}"
|
101
|
+
|
102
|
+
# encode the url
|
103
|
+
new_path = Datafy::make_data_uri( content, content_type )
|
104
|
+
else
|
105
|
+
puts "Unable to locate file #{filename} on local file system, skipping image embedding"
|
108
106
|
end
|
109
107
|
end
|
110
108
|
return new_path
|
@@ -60,8 +60,9 @@ module Juicer
|
|
60
60
|
def latest
|
61
61
|
return @latest if @latest
|
62
62
|
webpage = Nokogiri::HTML(open(@website))
|
63
|
-
@latest = (webpage / "
|
63
|
+
@latest = (webpage / "h3#yuicompressor + ul li a:last").text.match(/(\d\.\d\.\d)/)[1]
|
64
64
|
end
|
65
|
+
|
65
66
|
end
|
66
67
|
end
|
67
68
|
end
|
@@ -53,13 +53,13 @@ module Juicer
|
|
53
53
|
# for all absolute URLs regardless of absolute/relative URL strategy.
|
54
54
|
#
|
55
55
|
def merge(file)
|
56
|
-
content = super.gsub(/^\s*@import(?:\surl\(|\s)(['"]?)([^\?'"\)\s]+)(\?(?:[^'"\)]
|
56
|
+
content = super.gsub(/^\s*@import(?:\surl\(|\s)(['"]?)([^\?'"\)\s]+)(\?(?:[^'"\)]*))?\1\)?(?:[^?;]*);?/i, "")
|
57
57
|
dir = File.expand_path(File.dirname(file))
|
58
58
|
|
59
59
|
content.scan(/url\([\s"']*([^\)"'\s]*)[\s"']*\)/m).uniq.collect do |url|
|
60
60
|
url = url.first
|
61
61
|
path = resolve_path(url, dir)
|
62
|
-
content.gsub!(/\(
|
62
|
+
content.gsub!(/\([\s"']*#{url}[\s"']*\)/m, "(#{path})") unless path == url
|
63
63
|
end
|
64
64
|
|
65
65
|
content
|
@@ -79,7 +79,7 @@ module Juicer
|
|
79
79
|
|
80
80
|
# All URLs that don't start with a protocol
|
81
81
|
if url !~ %r{^/} && url !~ %r{^[a-z]+://}
|
82
|
-
if @use_absolute
|
82
|
+
if @use_absolute || @hosts.length > 0
|
83
83
|
raise ArgumentError.new("Unable to handle absolute URLs without :document_root option") if !@document_root
|
84
84
|
path = File.expand_path(File.join(dir, url)).sub(@document_root, "") # Make absolute
|
85
85
|
else
|
@@ -88,8 +88,8 @@ module Juicer
|
|
88
88
|
end
|
89
89
|
|
90
90
|
# Cycle hosts, if any
|
91
|
-
if
|
92
|
-
path = File.join(@hosts[@host_num % @hosts.length],
|
91
|
+
if path =~ %r{^/} && @hosts.length > 0
|
92
|
+
path = File.join(@hosts[@host_num % @hosts.length], path)
|
93
93
|
@host_num += 1
|
94
94
|
end
|
95
95
|
|
@@ -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/lib/juicer.rb
CHANGED
data/lib/psyho_juicer.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path('juicer', File.dirname(__FILE__)) unless defined?(Juicer)
|
data/test/data/a.css
ADDED
data/test/data/a.js
ADDED
data/test/data/a1.css
ADDED
data/test/data/b.css
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
/* Dette er b.css */
|
data/test/data/b.js
ADDED
data/test/data/b1.css
ADDED
data/test/data/b2.css
ADDED
data/test/data/c1.css
ADDED
data/test/data/css/2.gif
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
body { background: url(/images/1.png); }
|
data/test/data/d1.css
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
|
data/test/data/my_app.js
ADDED
data/test/data/not-ok.js
ADDED
data/test/data/ok.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
var pkg = {};
|
@@ -0,0 +1 @@
|
|
1
|
+
DO NOT MODIFY
|