psyho_juicer 1.0.0 → 1.0.7

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.
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