Rewrite gzip_assets to work as a post-build step and to leave uncompressed versions around.

This commit is contained in:
Ben Hollis 2012-03-04 16:42:14 -08:00
parent cf9e59db83
commit af605a909b
2 changed files with 25 additions and 52 deletions

View file

@ -5,6 +5,9 @@ Feature: GZIP assets during build
Then the following files should exist: Then the following files should exist:
| build/javascripts/test.js.gz | | build/javascripts/test.js.gz |
| build/stylesheets/test.css.gz | | build/stylesheets/test.css.gz |
| build/index.html.gz |
| build/javascripts/test.js |
| build/stylesheets/test.css |
| build/index.html | | build/index.html |
When I run `file build/javascripts/test.js.gz` When I run `file build/javascripts/test.js.gz`
Then the output should contain "gzip" Then the output should contain "gzip"

View file

@ -1,5 +1,6 @@
require 'zlib' require 'zlib'
require 'stringio' require 'stringio'
require 'find'
module Middleman::Extensions module Middleman::Extensions
@ -12,73 +13,42 @@ module Middleman::Extensions
# to serve your Gzipped files whenever the normal (non-.gz) filename is requested. # to serve your Gzipped files whenever the normal (non-.gz) filename is requested.
# #
# Pass the :exts options to customize which file extensions get zipped (defaults # Pass the :exts options to customize which file extensions get zipped (defaults
# to .js and .css. # to .html, .htm, .js and .css.
# #
module GzipAssets module GzipAssets
class << self class << self
def registered(app, options={}) def registered(app, options={})
exts = options[:exts] || %w(.js .css) exts = options[:exts] || %w(.js .css .html .htm)
return unless app.inst.build? app.send :include, InstanceMethods
app.after_configuration do app.after_build do |builder|
# Register a reroute transform that adds .gz to asset paths Find.find(self.class.inst.build_dir) do |path|
sitemap.reroute do |destination, page| next if File.directory? path
if exts.include? page.ext if exts.include? File.extname(path)
destination + '.gz' new_size = gzip_file(path, builder)
else end
destination end
end end
end end
use GzipRack, :exts => exts
end
end
alias :included :registered alias :included :registered
end end
# Rack middleware to GZip asset files module InstanceMethods
class GzipRack def gzip_file(path, builder)
input_file = File.open(path, 'r').read
# Init output_filename = path + '.gz'
# @param [Class] app File.open(output_filename, 'w') do |f|
# @param [Hash] options gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
def initialize(app, options={}) gz.write input_file
@app = app
@exts = options[:exts]
@exts_regex = @exts.map {|e| Regexp.escape(e) }.join('|')
end
# Rack interface
# @param [Rack::Environmemt] env
# @return [Array]
def call(env)
status, headers, response = @app.call(env)
if env["PATH_INFO"].match(/(#{@exts_regex}).gz$/)
contents = case(response)
when String
response
when Array
response.join
when Rack::Response
response.body.join
when Rack::File
File.read(response.path)
end
gzipped = ""
StringIO.open(gzipped) do |s|
gz = Zlib::GzipWriter.new(s, Zlib::BEST_COMPRESSION)
gz.write contents
gz.close gz.close
end end
headers["Content-Length"] = ::Rack::Utils.bytesize(gzipped).to_s old_size = File.size(path)
response = [gzipped] new_size = File.size(output_filename)
end
[status, headers, response] builder.say_status :gzip, "#{output_filename} (#{old_size - new_size} bytes smaller)"
end end
end end
end end