lib/juicer/css_cache_buster.rb in juicer-0.2.6 vs lib/juicer/css_cache_buster.rb in juicer-1.0.0
- old
+ new
@@ -1,7 +1,8 @@
-require File.expand_path(File.join(File.dirname(__FILE__), "chainable"))
-require File.expand_path(File.join(File.dirname(__FILE__), "cache_buster"))
+require "juicer/chainable"
+require "juicer/cache_buster"
+require "juicer/asset/path_resolver"
module Juicer
#
# The CssCacheBuster is a tool that can parse a CSS file and substitute all
# referenced URLs by a URL appended with a timestamp denoting it's last change.
@@ -10,48 +11,49 @@
#
# See Juicer::CacheBuster for more information on how the cache buster URLs
# work.
#
# When dealing with CSS files that reference absolute URLs like /images/1.png
- # you must specify the :web_root option that these URLs should be resolved
+ # you must specify the :document_root option that these URLs should be resolved
# against.
#
# When dealing with full URLs (ie including hosts) you can optionally specify
# an array of hosts to recognize as "local", meaning they serve assets from
- # the :web_root directory. This way even asset host cycling can benefit from
+ # the :document_root directory. This way even asset host cycling can benefit from
# cache busters.
#
class CssCacheBuster
include Juicer::Chainable
def initialize(options = {})
- @web_root = options[:web_root]
- @web_root.sub!(%r{/?$}, "") if @web_root # Remove trailing slash
+ @document_root = options[:document_root]
+ @document_root.sub!(%r{/?$}, "") if @document_root
@type = options[:type] || :soft
- @hosts = (options[:hosts] || []).collect { |h| h.sub!(%r{/?$}, "") } # Remove trailing slashes
- @contents = nil
+ @hosts = (options[:hosts] || []).collect { |h| h.sub!(%r{/?$}, "") }
+ @contents = @base = nil
end
#
# Update file. If no +output+ is provided, the input file is overwritten
#
def save(file, output = nil)
@contents = File.read(file)
+ self.base = File.dirname(file)
used = []
- urls(file).each do |url|
+ urls(file).each do |asset|
begin
- path = resolve(url, file)
- next if used.include?(path)
-
- if path != url
- used << path
- basename = File.basename(Juicer::CacheBuster.path(path, @type))
- @contents.gsub!(url, File.join(File.dirname(url), basename))
- end
+ next if used.include?(asset.path)
+ @contents.gsub!(asset.path, asset.path(:cache_buster_type => @type))
rescue Errno::ENOENT
- puts "Unable to locate file #{path || url}, skipping cache buster"
+ puts "Unable to locate file #{asset.path}, skipping cache buster"
+ rescue ArgumentError => e
+ if e.message =~ /No document root/
+ raise FileNotFoundError.new("Unable to resolve path #{asset.path} without :document_root option")
+ else
+ raise e
+ end
end
end
File.open(output || file, "w") { |f| f.puts @contents }
@contents = nil
@@ -65,42 +67,24 @@
#
def urls(file)
@contents = File.read(file) unless @contents
@contents.scan(/url\([\s"']*([^\)"'\s]*)[\s"']*\)/m).collect do |match|
- match.first
+ path_resolver.resolve(match.first)
end
end
- #
- # Resolve full path from URL
- #
- def resolve(target, from)
- # If URL is external, check known hosts to see if URL can be treated
- # like a local one (ie so we can add cache buster)
- catch(:continue) do
- if target =~ %r{^[a-z]+\://}
- # This could've been a one-liner, but I prefer to be
- # able to read my own code ;)
- @hosts.each do |host|
- if target =~ /^#{host}/
- target.sub!(/^#{host}/, "")
- throw :continue
- end
- end
+ protected
+ def base=(base)
+ @prev_base = @base
+ @base = base
+ end
- # No known hosts matched, return
- return target
- end
- end
+ def path_resolver
+ return @path_resolver if @path_resolver && @base == @prev_base
- # Simply add web root to absolute URLs
- if target =~ %r{^/}
- raise FileNotFoundError.new("Unable to resolve absolute path #{target} without :web_root option") unless @web_root
- return File.expand_path(File.join(@web_root, target))
- end
-
- # Resolve relative URLs to full paths
- File.expand_path(File.join(File.dirname(File.expand_path(from)), target))
+ @path_resolver = Juicer::Asset::PathResolver.new(:document_root => @document_root,
+ :hosts => @hosts,
+ :base => @base)
end
end
end