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.
Files changed (49) hide show
  1. data/Gemfile +11 -0
  2. data/History.txt +33 -0
  3. data/Readme.rdoc +16 -4
  4. data/VERSION +1 -1
  5. data/lib/juicer/asset/path.rb +6 -10
  6. data/lib/juicer/cache_buster.rb +53 -13
  7. data/lib/juicer/command/merge.rb +14 -6
  8. data/lib/juicer/css_cache_buster.rb +6 -4
  9. data/lib/juicer/dependency_resolver/css_dependency_resolver.rb +1 -1
  10. data/lib/juicer/image_embed.rb +18 -20
  11. data/lib/juicer/install/yui_compressor_installer.rb +2 -1
  12. data/lib/juicer/merger/stylesheet_merger.rb +5 -5
  13. data/lib/juicer/minifyer/closure_compiler.rb +1 -1
  14. data/lib/juicer.rb +1 -1
  15. data/lib/psyho_juicer.rb +1 -0
  16. data/test/data/Changelog.txt +10 -0
  17. data/test/data/a.css +3 -0
  18. data/test/data/a.js +5 -0
  19. data/test/data/a1.css +5 -0
  20. data/test/data/b.css +1 -0
  21. data/test/data/b.js +5 -0
  22. data/test/data/b1.css +5 -0
  23. data/test/data/b2.css +5 -0
  24. data/test/data/c1.css +3 -0
  25. data/test/data/css/2.gif +1 -0
  26. data/test/data/css/test.css +15 -0
  27. data/test/data/css/test2.css +1 -0
  28. data/test/data/css/test3.css +12 -0
  29. data/test/data/d1.css +3 -0
  30. data/test/data/images/1.png +1 -0
  31. data/test/data/my_app.js +2 -0
  32. data/test/data/not-ok.js +2 -0
  33. data/test/data/ok.js +3 -0
  34. data/test/data/path_test.css +5 -0
  35. data/test/data/path_test2.css +14 -0
  36. data/test/data/pkg/module/moda.js +2 -0
  37. data/test/data/pkg/module/modb.js +3 -0
  38. data/test/data/pkg/pkg.js +1 -0
  39. data/test/fixtures/git-tracked-file.txt +1 -0
  40. data/test/fixtures/yui-download.html +103 -243
  41. data/test/test_helper.rb +27 -1
  42. data/test/unit/juicer/asset/path_test.rb +7 -1
  43. data/test/unit/juicer/cache_buster_test.rb +95 -5
  44. data/test/unit/juicer/command/util_test.rb +1 -1
  45. data/test/unit/juicer/css_cache_buster_test.rb +127 -32
  46. data/test/unit/juicer/image_embed_test.rb +35 -0
  47. data/test/unit/juicer/merger/stylesheet_merger_test.rb +175 -109
  48. data/test/unit/juicer/minifyer/closure_compressor_test.rb +3 -3
  49. metadata +68 -21
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "bundler", "~> 0.9.26"
4
+ gem "shoulda"
5
+ gem "mocha"
6
+ gem "redgreen"
7
+ gem "nokogiri"
8
+ gem "zip"
9
+ gem "cmdparse"
10
+ gem "turn"
11
+ gem "fakefs"
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 two types of cache busters; soft ones add a parameter to the URL, like
72
- so: http://assets/images/1.png?cb1234567890, ie the letters "cb" (as in cache
73
- buster) and then the timestamp of the files mtime.
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-cb1234567890.png,
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.0
1
+ 1.0.7
@@ -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
- if options.key?(:cache_buster)
251
- # Pass :cache_buster even if it's nil
252
- buster_path = Juicer::CacheBuster.send(type, filename, options[:cache_buster])
253
- else
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!(%r{^#{host}}, '')
264
+ path = path.sub(%r{^#{host}}, '')
269
265
  end
270
266
 
271
267
  return path
@@ -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, type = :soft, parameter = DEFAULT_PARAMETER)
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
- mtime = File.mtime(filename).to_i
87
- type = [:soft, :hard].include?(type) ? type : :soft
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}#{mtime}"
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}#{mtime}" + '\1')
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, parameter = DEFAULT_PARAMETER)
105
- self.path(file, :hard, parameter)
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, parameter = DEFAULT_PARAMETER)
116
- self.path(file, :soft, parameter)
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
- query_param = "#{parameter}".length == 0 ? "" : "#{parameter}="
125
- new_file = file.sub(/#{query_param}\d+&?/, "").sub(/(\?|&)$/, "")
126
- return new_file unless new_file == file
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
- file.sub(/-#{parameter}\d+(\.\w+)($|\?)/, '\1\2')
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
@@ -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") { |t| @local_hosts = @hosts }
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 referenced\n" +
78
- (" " * 37) + "URLs as query parameters. None leaves URLs untouched and hard alters file names") do |type|
79
- @cache_buster = [:soft, :hard].include?(type.to_sym) ? type.to_sym : nil
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
- raise FileNotFoundError.new("Unable to resolve path #{asset.path} without :document_root option")
53
+ puts "Unable to resolve path #{asset.path} without :document_root option"
52
54
  else
53
- raise e
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]+)(\?(?:[^'"\)]+)?)?\1\)?(?:[^?;]+)?;?/im
11
+ @@import_pattern = /^\s*@import(?:\surl\(|\s)(['"]?)([^\?'"\)\s]+)(\?(?:[^'"\)]*))?\1\)?(?:[^?;]*);?/im
12
12
 
13
13
  private
14
14
  def parse(line, imported_file = nil)
@@ -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.path))
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
- if path.match( /\?embed=true$/ )
90
- supported_file_matches = path.match( /(?:\.)(png|gif|jpg|jpeg)(?:\?embed=true)$/i )
91
- filetype = supported_file_matches[1] if supported_file_matches
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 ( filetype )
94
- filename = path.gsub('?embed=true','')
95
-
96
- # check if file exists, throw an error if it doesn't exist
97
- if File.exist?( filename )
98
-
99
- # read contents of file into memory
100
- content = File.read( filename )
101
- content_type = "image/#{filetype}"
102
-
103
- # encode the url
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 / "//h2[@id='yuicompressor']/../../../..//a")[0].get_attribute("href").match(/(\d\.\d\.\d)/)[1]
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]+)(\?(?:[^'"\)]+)?)?\1\)?(?:[^?;]+)?;?/i, "")
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!(/\(#{url}\)/m, "(#{path})") unless path == url
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 url =~ %r{^/} && @hosts.length > 0
92
- path = File.join(@hosts[@host_num % @hosts.length], url)
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
- result = execute(%Q{-jar "#{locate_jar}"#{jar_args} -js_output_file "#{output}" -js "#{file}"})
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
@@ -3,7 +3,7 @@ require "logger"
3
3
  module Juicer
4
4
 
5
5
  # :stopdoc:
6
- VERSION = '1.0.0'
6
+ VERSION = '1.0.6'
7
7
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
8
8
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
9
9
  LOGGER = Logger.new(STDOUT)
@@ -0,0 +1 @@
1
+ require File.expand_path('juicer', File.dirname(__FILE__)) unless defined?(Juicer)
@@ -0,0 +1,10 @@
1
+ 2008.02.09 | stb-base 1.29
2
+
3
+ FEATURE: Core | Bla bla bla bla bla
4
+ FEATURE: UI: | Bla bla bla bla bla
5
+
6
+
7
+ 2008.02.09 | stb-base 1.29
8
+
9
+ FEATURE: Core | Bla bla bla bla bla
10
+ FEATURE: UI: | Bla bla bla bla bla
data/test/data/a.css ADDED
@@ -0,0 +1,3 @@
1
+ @import 'b.css';
2
+
3
+ /* Dette er a.css */
data/test/data/a.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @depend b.js
3
+ */
4
+
5
+ /* Dette er a.js */
data/test/data/a1.css ADDED
@@ -0,0 +1,5 @@
1
+ @import 'b1.css';
2
+ @import 'c1.css';
3
+ body {
4
+ width: 800px;
5
+ }
data/test/data/b.css ADDED
@@ -0,0 +1 @@
1
+ /* Dette er b.css */
data/test/data/b.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @depends a.js
3
+ */
4
+
5
+ /* Dette er b.css */
data/test/data/b1.css ADDED
@@ -0,0 +1,5 @@
1
+ @import url('d1.css');
2
+
3
+ html {
4
+ background: red;
5
+ }
data/test/data/b2.css ADDED
@@ -0,0 +1,5 @@
1
+ @import url("d1.css");
2
+
3
+ html {
4
+ background: red;
5
+ }
data/test/data/c1.css ADDED
@@ -0,0 +1,3 @@
1
+ h1 {
2
+ font-size: 12px;
3
+ }
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,15 @@
1
+ body {
2
+ background: url(../images/1.png);
3
+ }
4
+
5
+ h1 {
6
+ background: url('../a1.css') 0 0 no-repeat;
7
+ }
8
+
9
+ h2 {
10
+ background: url("2.gif") no-repeat;
11
+ }
12
+
13
+ p {
14
+ background: url(2.gif) no-repeat;
15
+ }
@@ -0,0 +1 @@
1
+ body { background: url(/images/1.png); }
@@ -0,0 +1,12 @@
1
+ body {
2
+ background: url(http://assets1/images/1.png);
3
+ }
4
+
5
+ h1 {
6
+ background: url(http://assets2/css/2.gif);
7
+ background: url(http://assets3/a1.css) 0 0 no-repeat;
8
+ }
9
+
10
+ h2 {
11
+ background: url(http://assets2/css/2.gif) no-repeat;
12
+ }
data/test/data/d1.css ADDED
@@ -0,0 +1,3 @@
1
+ h2 {
2
+ font-size: 10px;
3
+ }
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,2 @@
1
+ // @depend pkg
2
+ var myApp = pkg.a;
@@ -0,0 +1,2 @@
1
+ var a = 34
2
+ b = 78;
data/test/data/ok.js ADDED
@@ -0,0 +1,3 @@
1
+ function hey() {
2
+ return "Hey";
3
+ }
@@ -0,0 +1,5 @@
1
+ @import 'css/test.css';
2
+
3
+ body {
4
+ background: url(css/2.gif) no-repeat;
5
+ }
@@ -0,0 +1,14 @@
1
+ body {
2
+ background: url(/images/1.png);
3
+ }
4
+
5
+ h1 {
6
+ background: url(/css/2.gif);
7
+ background: url(/a1.css) 0 0 no-repeat;
8
+ }
9
+
10
+ h2 {
11
+ background: url(/css/2.gif) no-repeat;
12
+ }
13
+
14
+ p { background: url(/a2.css); }
@@ -0,0 +1,2 @@
1
+ // @depend ../pkg.js
2
+ pkg.a = '';
@@ -0,0 +1,3 @@
1
+ // @depend ../pkg.js
2
+ // @depend moda.js
3
+ pkg.b = '';
@@ -0,0 +1 @@
1
+ var pkg = {};
@@ -0,0 +1 @@
1
+ DO NOT MODIFY