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.

This commit is contained in:
Ben Hollis 2012-04-17 00:22:08 -07:00
parent dc784edc66
commit 50b797e0be
3 changed files with 60 additions and 44 deletions

View file

@ -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)

View file

@ -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
end

View file

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