From 50b797e0be8350a4eb359d37d4a91c08e6d5bbea Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Tue, 17 Apr 2012 00:22:08 -0700 Subject: [PATCH] Get asset_hash working after the sitemap refactor. Part of this required changing the behavior of the OnDisk Sitemap extension to rebuild the sitemap every time a file is touched, instead of just when files are added (even if the file being touched is ignored by the sitemap, like a partial!). This is because asset_hash needs to recalculate hashes whenever any file changes, since partials can affect the output of other files. --- .../middleman-core/core_extensions/assets.rb | 2 +- .../sitemap/extensions/on_disk.rb | 32 ++++----- .../middleman-more/extensions/asset_hash.rb | 70 ++++++++++++------- 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/middleman-core/lib/middleman-core/core_extensions/assets.rb b/middleman-core/lib/middleman-core/core_extensions/assets.rb index d2592f7f..ad2f0527 100644 --- a/middleman-core/lib/middleman-core/core_extensions/assets.rb +++ b/middleman-core/lib/middleman-core/core_extensions/assets.rb @@ -29,7 +29,7 @@ module Middleman::CoreExtensions::Assets else # rewrite paths to use their destination path path = File.join(prefix, path) if resource = sitemap.find_resource_by_path(path) - path = resource.path + path = resource.destination_path end File.join(http_prefix, path) diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/on_disk.rb b/middleman-core/lib/middleman-core/sitemap/extensions/on_disk.rb index 05102d1b..d8e89331 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/on_disk.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/on_disk.rb @@ -1,3 +1,5 @@ +require 'set' + module Middleman::Sitemap::Extensions class OnDisk @@ -8,12 +10,8 @@ module Middleman::Sitemap::Extensions @sitemap = sitemap @app = @sitemap.app - @file_paths_on_disk = [] + @file_paths_on_disk = Set.new - # Cleanup paths - # static_path = @app.source_dir.sub(@app.root, "").sub(/^\//, "") - # sitemap_regex = static_path.empty? ? // : (%r{^#{static_path + "/"}}) - scoped_self = self @waiting_for_ready = true @@ -38,26 +36,28 @@ module Middleman::Sitemap::Extensions # @return [Boolean] def touch_file(file, rebuild=true) return false if file == @app.source_dir || File.directory?(file) - + path = file_to_path(file) return false unless path - - return false if @app.ignored_sitemap_matchers.any? do |name, callback| + + ignored = @app.ignored_sitemap_matchers.any? do |name, callback| callback.call(file, path) end - - if !@file_paths_on_disk.include?(file) - @file_paths_on_disk << file - @sitemap.rebuild_resource_list!(:added_file) if rebuild - end + + @file_paths_on_disk << file unless ignored + + # Rebuild the sitemap any time a file is touched + # in case one of the other manipulators + # (like asset_hash) cares about the contents of this file, + # whether or not it belongs in the sitemap (like a partial) + @sitemap.rebuild_resource_list!(:touched_file) if rebuild end # Remove a file from the store # @param [String] file # @return [void] def remove_file(file, rebuild=true) - if @file_paths_on_disk.include?(file) - @file_paths_on_disk.delete(file) + if @file_paths_on_disk.delete?(file) @sitemap.rebuild_resource_list!(:removed_file) if rebuild end end @@ -117,4 +117,4 @@ module Middleman::Sitemap::Extensions path end end -end \ No newline at end of file +end diff --git a/middleman-more/lib/middleman-more/extensions/asset_hash.rb b/middleman-more/lib/middleman-more/extensions/asset_hash.rb index c5c2f18c..e880973c 100755 --- a/middleman-more/lib/middleman-more/extensions/asset_hash.rb +++ b/middleman-more/lib/middleman-more/extensions/asset_hash.rb @@ -5,32 +5,11 @@ module Middleman::Extensions def registered(app, options) exts = options[:exts] || %w(.ico .manifest .jpg .jpeg .png .gif .js .css) - app.after_configuration do - sitemap.reroute do |destination, page| - if exts.include? page.ext - # figure out the path Sprockets would use for this asset - if page.ext == '.js' - sprockets_path = page.path.sub(js_dir,'').sub(/^\//,'') - elsif page.ext == '.css' - sprockets_path = page.path.sub(css_dir,'').sub(/^\//,'') - end - - # See if Sprockets knows about the file - asset = sprockets.find_asset(sprockets_path) if sprockets_path - - if asset # if it's a Sprockets asset, ask sprockets for its digest - digest = asset.digest[0..7] - elsif page.template? # if it's a template, render it out - digest = Digest::SHA1.hexdigest(page.render)[0..7] - else # if it's a static file, just hash it - digest = Digest::SHA1.file(page.source_file).hexdigest[0..7] - end - - destination.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" } - else - destination - end - end + app.ready do + sitemap.register_resource_list_manipulator( + :asset_hash, + AssetHashManager.new(self, exts) + ) use Middleware, :exts => exts, :middleman_app => self end @@ -38,6 +17,43 @@ module Middleman::Extensions alias :included :registered end + class AssetHashManager + def initialize(app, exts) + @app = app + @exts = exts + end + + # Update the main sitemap resource list + # @return [void] + def manipulate_resource_list(resources) + resources.each do |resource| + if @exts.include? resource.ext + # figure out the path Sprockets would use for this asset + if resource.ext == '.js' + sprockets_path = resource.path.sub(@app.js_dir,'').sub(/^\//,'') + elsif resource.ext == '.css' + sprockets_path = resource.path.sub(@app.css_dir,'').sub(/^\//,'') + end + + # See if Sprockets knows about the file + asset = @app.sprockets.find_asset(sprockets_path) if sprockets_path + + if asset # if it's a Sprockets asset, ask sprockets for its digest + digest = asset.digest[0..7] + elsif resource.template? # if it's a template, render it out + digest = Digest::SHA1.hexdigest(resource.render)[0..7] + else # if it's a static file, just hash it + digest = Digest::SHA1.file(resource.source_file).hexdigest[0..7] + end + + resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" } + end + end + end + end + + # The asset hash middleware is responsible for rewriting references to + # assets to include their new, hashed name. class Middleware def initialize(app, options={}) @rack_app = app @@ -63,7 +79,7 @@ module Middleman::Extensions asset_path = dirpath.join(asset_path).to_s if relative_path - if asset_page = @middleman_app.sitemap.find_page_by_path(asset_path) + if asset_page = @middleman_app.sitemap.find_resource_by_path(asset_path) replacement_path = "/#{asset_page.destination_path}" replacement_path = Pathname.new(replacement_path).relative_path_from(dirpath).to_s if relative_path