Merge pull request #363 from bhollis/asset_hash

Fix asset hash with new sitemap
This commit is contained in:
Thomas Reynolds 2012-04-17 09:36:37 -07:00
commit c623993cc5
4 changed files with 65 additions and 48 deletions

View file

@ -29,7 +29,7 @@ module Middleman::CoreExtensions::Assets
else # rewrite paths to use their destination path else # rewrite paths to use their destination path
path = File.join(prefix, path) path = File.join(prefix, path)
if resource = sitemap.find_resource_by_path(path) if resource = sitemap.find_resource_by_path(path)
path = resource.path path = resource.destination_path
end end
File.join(http_prefix, path) File.join(http_prefix, path)

View file

@ -1,5 +1,6 @@
require "find" require "find"
require "middleman-core/watcher" require "middleman-core/watcher"
require "set"
# API for watching file change events # API for watching file change events
module Middleman::CoreExtensions::FileWatcher module Middleman::CoreExtensions::FileWatcher
@ -54,7 +55,7 @@ module Middleman::CoreExtensions::FileWatcher
# Initialize api and internal path cache # Initialize api and internal path cache
def initialize def initialize
self.known_paths = [] self.known_paths = Set.new
end end
# Add callback to be run on file change # Add callback to be run on file change
@ -83,7 +84,7 @@ module Middleman::CoreExtensions::FileWatcher
# @return [void] # @return [void]
def did_change(path) def did_change(path)
puts "== File Change: #{path}" if instance.logging? && !::Middleman::Watcher.ignore_list.any? { |r| path.match(r) } puts "== File Change: #{path}" if instance.logging? && !::Middleman::Watcher.ignore_list.any? { |r| path.match(r) }
self.known_paths << path unless self.known_paths.include?(path) self.known_paths << path
self.run_callbacks(path, :changed) self.run_callbacks(path, :changed)
end end
@ -93,7 +94,7 @@ module Middleman::CoreExtensions::FileWatcher
# @return [void] # @return [void]
def did_delete(path) def did_delete(path)
puts "== File Deletion: #{path}" if instance.logging? && !::Middleman::Watcher.ignore_list.any? { |r| path.match(r) } puts "== File Deletion: #{path}" if instance.logging? && !::Middleman::Watcher.ignore_list.any? { |r| path.match(r) }
self.known_paths.delete(path) if self.known_paths.include?(path) self.known_paths.delete(path)
self.run_callbacks(path, :deleted) self.run_callbacks(path, :deleted)
end end

View file

@ -1,3 +1,5 @@
require 'set'
module Middleman::Sitemap::Extensions module Middleman::Sitemap::Extensions
class OnDisk class OnDisk
@ -8,11 +10,7 @@ module Middleman::Sitemap::Extensions
@sitemap = sitemap @sitemap = sitemap
@app = @sitemap.app @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 scoped_self = self
@waiting_for_ready = true @waiting_for_ready = true
@ -42,22 +40,24 @@ module Middleman::Sitemap::Extensions
path = file_to_path(file) path = file_to_path(file)
return false unless path 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) callback.call(file, path)
end end
if !@file_paths_on_disk.include?(file) @file_paths_on_disk << file unless ignored
@file_paths_on_disk << file
@sitemap.rebuild_resource_list!(:added_file) if rebuild # Rebuild the sitemap any time a file is touched
end # 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 end
# Remove a file from the store # Remove a file from the store
# @param [String] file # @param [String] file
# @return [void] # @return [void]
def remove_file(file, rebuild=true) def remove_file(file, rebuild=true)
if @file_paths_on_disk.include?(file) if @file_paths_on_disk.delete?(file)
@file_paths_on_disk.delete(file)
@sitemap.rebuild_resource_list!(:removed_file) if rebuild @sitemap.rebuild_resource_list!(:removed_file) if rebuild
end end
end end

View file

@ -5,32 +5,11 @@ module Middleman::Extensions
def registered(app, options) def registered(app, options)
exts = options[:exts] || %w(.ico .manifest .jpg .jpeg .png .gif .js .css) exts = options[:exts] || %w(.ico .manifest .jpg .jpeg .png .gif .js .css)
app.after_configuration do app.ready do
sitemap.reroute do |destination, page| sitemap.register_resource_list_manipulator(
if exts.include? page.ext :asset_hash,
# figure out the path Sprockets would use for this asset AssetHashManager.new(self, exts)
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
use Middleware, :exts => exts, :middleman_app => self use Middleware, :exts => exts, :middleman_app => self
end end
@ -38,6 +17,43 @@ module Middleman::Extensions
alias :included :registered alias :included :registered
end 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 class Middleware
def initialize(app, options={}) def initialize(app, options={})
@rack_app = app @rack_app = app
@ -63,7 +79,7 @@ module Middleman::Extensions
asset_path = dirpath.join(asset_path).to_s if relative_path 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 = "/#{asset_page.destination_path}"
replacement_path = Pathname.new(replacement_path).relative_path_from(dirpath).to_s if relative_path replacement_path = Pathname.new(replacement_path).relative_path_from(dirpath).to_s if relative_path