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