diff --git a/doc-src/content/CHANGELOG-v0-11-beta.markdown b/doc-src/content/CHANGELOG-v0-11-beta.markdown index 127f0f24..17fc5769 100644 --- a/doc-src/content/CHANGELOG-v0-11-beta.markdown +++ b/doc-src/content/CHANGELOG-v0-11-beta.markdown @@ -10,6 +10,7 @@ layout: article * Created an official API to add configuration options to compass. [More information](/help/tutorials/extending/). +* Enhanced cache busting by allowing path manipulation 0.11.beta.7 (04/16/2011) ------------------------ diff --git a/doc-src/content/help/tutorials/configuration-reference.markdown b/doc-src/content/help/tutorials/configuration-reference.markdown index af6d6ea7..3a966856 100644 --- a/doc-src/content/help/tutorials/configuration-reference.markdown +++ b/doc-src/content/help/tutorials/configuration-reference.markdown @@ -308,9 +308,12 @@ the asset host configuration is ignored. --- **`asset_cache_buster`** – Pass this function a block of code that defines the -cache buster strategy to be used. The block must return nil or a string that can -be appended to a url as a query parameter. The returned string must not include -the starting `?`. The block will be passed the root-relative url of the asset. +cache buster strategy to be used. The block must return nil, a string or a hash. +If the returned value is a hash the values of :path and/or :query is used to generate +a cache busted path to the asset. If a string value is returned, it is added as a query string. +The returned values for query strings must not include the starting `?`. + +The block will be passed the root-relative url of the asset. If the block accepts two arguments, it will also be passed a path that points to the asset on disk — which may or may not exist. @@ -324,6 +327,18 @@ that points to the asset on disk — which may or may not exist. end end +Busting the cache via path: + + asset_cache_buster do |path, real_path| + if File.exists?(real_path) + pathname = Pathname.new(path) + modified_time = File.mtime(real_path).strftime("%s") + new_path = "%s/%s-%s%s" % [pathname.dirname, pathname.basename(pathname.extname), modified_time, pathname.extname] + + {:path => new_path, :query => nil} + end + end + To disable the asset cache buster: asset_cache_buster :none diff --git a/lib/compass/configuration/data.rb b/lib/compass/configuration/data.rb index 9cde724d..ddc2de3a 100644 --- a/lib/compass/configuration/data.rb +++ b/lib/compass/configuration/data.rb @@ -71,8 +71,10 @@ module Compass end # When called with a block, defines the cache buster strategy to be used. - # The block must return nil or a string that can be appended to a url as a query parameter. - # The returned string must not include the starting '?'. + # If the block returns nil or a string, then it is appended to the url as a query parameter. + # In this case, the returned string must not include the starting '?'. + # The block may also return a hash with :path and/or :query values and it + # will replace the original path and query string with the busted values returned. # The block will be passed the root-relative url of the asset. # If the block accepts two arguments, it will also be passed a File object # that points to the asset on disk -- which may or may not exist. diff --git a/lib/compass/sass_extensions/functions/urls.rb b/lib/compass/sass_extensions/functions/urls.rb index d140c8a5..50ffab52 100644 --- a/lib/compass/sass_extensions/functions/urls.rb +++ b/lib/compass/sass_extensions/functions/urls.rb @@ -91,9 +91,7 @@ module Compass::SassExtensions::Functions::Urls if cache_buster.is_a?(Sass::Script::String) path += "?#{cache_buster.value}" else - if buster = compute_cache_buster(path, real_path) - path += "?#{buster}" - end + path = cache_busted_path(path, real_path) end end @@ -137,6 +135,23 @@ module Compass::SassExtensions::Functions::Urls end end + def cache_busted_path(path, real_path) + cache_buster = compute_cache_buster(path, real_path) + if cache_buster.nil? + return path + elsif cache_buster.is_a?(String) + cache_buster = {:query => cache_buster} + else + path = cache_buster[:path] if cache_buster[:path] + end + + if cache_buster[:query] + "%s?%s" % [path, cache_buster[:query]] + else + path + end + end + def compute_cache_buster(path, real_path) if Compass.configuration.asset_cache_buster args = [path] diff --git a/test/fixtures/stylesheets/busted_image_urls/config.rb b/test/fixtures/stylesheets/busted_image_urls/config.rb new file mode 100644 index 00000000..13821b8e --- /dev/null +++ b/test/fixtures/stylesheets/busted_image_urls/config.rb @@ -0,0 +1,29 @@ +# Require any additional compass plugins here. +project_type = :stand_alone +css_dir = "tmp" +sass_dir = "sass" +images_dir = "images" +output_style = :compact +# To enable relative image paths using the images_url() function: +# http_images_path = :relative +http_images_path = "/images" +line_comments = false + +asset_cache_buster do |path, file| + pathname = Pathname.new(path) + + case pathname.basename(pathname.extname).to_s + when "grid" + new_path = "%s/%s-BUSTED%s" % [pathname.dirname, pathname.basename(pathname.extname), pathname.extname] + {:path => new_path, :query => nil} + when "feed" + "query_string" + when "dk" + {:query => "query_string"} + end +end + + +asset_host do |path| + "http://assets%d.example.com" % (path.size % 4) +end diff --git a/test/fixtures/stylesheets/busted_image_urls/css/screen.css b/test/fixtures/stylesheets/busted_image_urls/css/screen.css new file mode 100644 index 00000000..ab36dbc7 --- /dev/null +++ b/test/fixtures/stylesheets/busted_image_urls/css/screen.css @@ -0,0 +1,9 @@ +.showgrid { background-image: url('http://assets0.example.com/images/grid-BUSTED.png'); } + +.inlinegrid { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAUEAYAAACv1qP4AAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAZ0lEQVRYw+3QwQ2AIBAFUTEUwI3+uzN7gDscsIgxEuO8An52J11X73OudfxMraXkzHfO3Y98nQEhA0IGhAwIGRAyIGRAyICQASEDQgaEDAgZEDIgZEDIgJABoZzSGK3tPuN9ERFP7Nw4fg+c5g8V1wAAAABJRU5ErkJggg=='); } + +.no-buster { background-image: url('http://assets0.example.com/images/grid.png'); } + +.feed { background-image: url('http://assets0.example.com/images/feed.png?query_string'); } + +.dk { background-image: url('http://assets0.example.com/images/flags/dk.png?query_string'); } diff --git a/test/fixtures/stylesheets/busted_image_urls/images/feed.png b/test/fixtures/stylesheets/busted_image_urls/images/feed.png new file mode 100644 index 00000000..315c4f4f Binary files /dev/null and b/test/fixtures/stylesheets/busted_image_urls/images/feed.png differ diff --git a/test/fixtures/stylesheets/busted_image_urls/images/flags/dk.png b/test/fixtures/stylesheets/busted_image_urls/images/flags/dk.png new file mode 100644 index 00000000..5f660619 Binary files /dev/null and b/test/fixtures/stylesheets/busted_image_urls/images/flags/dk.png differ diff --git a/test/fixtures/stylesheets/busted_image_urls/images/grid.png b/test/fixtures/stylesheets/busted_image_urls/images/grid.png new file mode 100644 index 00000000..76aaa851 Binary files /dev/null and b/test/fixtures/stylesheets/busted_image_urls/images/grid.png differ diff --git a/test/fixtures/stylesheets/busted_image_urls/sass/screen.sass b/test/fixtures/stylesheets/busted_image_urls/sass/screen.sass new file mode 100644 index 00000000..b469b120 --- /dev/null +++ b/test/fixtures/stylesheets/busted_image_urls/sass/screen.sass @@ -0,0 +1,14 @@ +.showgrid + background-image: image-url("grid.png") + +.inlinegrid + background-image: inline-image("grid.png") + +.no-buster + background-image: image-url("grid.png", $only-path: false, $cache-buster: false) + +.feed + background-image: image-url("feed.png") + +.dk + background-image: image-url("flags/dk.png") \ No newline at end of file diff --git a/test/integrations/compass_test.rb b/test/integrations/compass_test.rb index c8f4f5f8..b505debb 100644 --- a/test/integrations/compass_test.rb +++ b/test/integrations/compass_test.rb @@ -73,6 +73,17 @@ class CompassTest < Test::Unit::TestCase end end + def test_busted_image_urls + within_project('busted_image_urls') do |proj| + each_css_file(proj.css_path) do |css_file| + assert_no_errors css_file, 'busted_image_urls' + end + each_sass_file do |sass_file| + assert_renders_correctly sass_file + end + end + end + def test_image_urls within_project('image_urls') do |proj| each_css_file(proj.css_path) do |css_file|