Minify all JS and CSS via middleware. This means JS or CSS anywhere in the site is minified, not just in the Sprockets-controlled directories. I've also added inline CSS compression, and handling of several common "guards" that get wrapped around JS. Also, leave alone non-JS script tags (which may contain something like jQuery templates). Sprockets no longer has anything to do with minification after this.
This commit is contained in:
parent
b1ba94cf22
commit
192047d242
|
@ -68,6 +68,10 @@ Then /^I should see '([^\']*)'$/ do |expected|
|
||||||
@browser.last_response.body.should include(expected)
|
@browser.last_response.body.should include(expected)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Then /^I should see:$/ do |expected|
|
||||||
|
@browser.last_response.body.should include(expected)
|
||||||
|
end
|
||||||
|
|
||||||
Then /^I should not see "([^\"]*)"$/ do |expected|
|
Then /^I should not see "([^\"]*)"$/ do |expected|
|
||||||
@browser.last_response.body.should_not include(expected)
|
@browser.last_response.body.should_not include(expected)
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,8 +59,9 @@ module Middleman::Templates
|
||||||
return unless options[:bundler]
|
return unless options[:bundler]
|
||||||
template "shared/Gemfile.tt", File.join(location, "Gemfile")
|
template "shared/Gemfile.tt", File.join(location, "Gemfile")
|
||||||
|
|
||||||
say_status :run, "bundle install"
|
inside(location) do
|
||||||
print `cd #{location} && "#{Gem.ruby}" -rubygems "#{Gem.bin_path('bundler', 'bundle')}" install`
|
run('bundle install', :capture => true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
Feature: Minify CSS
|
Feature: Minify CSS
|
||||||
In order reduce bytes sent to client and appease YSlow
|
In order reduce bytes sent to client and appease YSlow
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given current environment is "build"
|
||||||
|
|
||||||
Scenario: Rendering external css with the feature disabled
|
Scenario: Rendering external css with the feature disabled
|
||||||
Given "minify_css" feature is "disabled"
|
Given "minify_css" feature is "disabled"
|
||||||
And the Server is running at "minify-css-app"
|
And the Server is running at "minify-css-app"
|
||||||
|
@ -14,8 +17,51 @@ Feature: Minify CSS
|
||||||
When I go to "/stylesheets/site.css"
|
When I go to "/stylesheets/site.css"
|
||||||
Then I should see "1" lines
|
Then I should see "1" lines
|
||||||
And I should see "only screen and (device-width"
|
And I should see "only screen and (device-width"
|
||||||
|
When I go to "/more-css/site.css"
|
||||||
|
Then I should see "1" lines
|
||||||
|
|
||||||
Scenario: Rendering external css with passthrough compressor
|
Scenario: Rendering external css with passthrough compressor
|
||||||
Given the Server is running at "passthrough-app"
|
Given the Server is running at "passthrough-app"
|
||||||
When I go to "/stylesheets/site.css"
|
When I go to "/stylesheets/site.css"
|
||||||
Then I should see "55" lines
|
Then I should see "55" lines
|
||||||
|
|
||||||
|
Scenario: Rendering inline css with the feature disabled
|
||||||
|
Given "minify_css" feature is "disabled"
|
||||||
|
And the Server is running at "minify-css-app"
|
||||||
|
When I go to "/inline-css.html"
|
||||||
|
Then I should see:
|
||||||
|
"""
|
||||||
|
<style type='text/css'>
|
||||||
|
/*<![CDATA[*/
|
||||||
|
body {
|
||||||
|
test: style;
|
||||||
|
good: deal;
|
||||||
|
}
|
||||||
|
/*]]>*/
|
||||||
|
</style>
|
||||||
|
"""
|
||||||
|
|
||||||
|
Scenario: Rendering inline css with a passthrough minifier
|
||||||
|
Given the Server is running at "passthrough-app"
|
||||||
|
When I go to "/inline-css.html"
|
||||||
|
Then I should see:
|
||||||
|
"""
|
||||||
|
<style type='text/css'>
|
||||||
|
body {
|
||||||
|
test: style;
|
||||||
|
good: deal; }
|
||||||
|
</style>
|
||||||
|
"""
|
||||||
|
|
||||||
|
Scenario: Rendering inline css with the feature enabled
|
||||||
|
Given "minify_css" feature is "enabled"
|
||||||
|
And the Server is running at "minify-css-app"
|
||||||
|
When I go to "/inline-css.html"
|
||||||
|
Then I should see:
|
||||||
|
"""
|
||||||
|
<style type='text/css'>
|
||||||
|
/*<![CDATA[*/
|
||||||
|
body{test:style;good:deal}
|
||||||
|
/*]]>*/
|
||||||
|
</style>
|
||||||
|
"""
|
|
@ -8,24 +8,106 @@ Feature: Minify Javascript
|
||||||
Given "minify_javascript" feature is "disabled"
|
Given "minify_javascript" feature is "disabled"
|
||||||
And the Server is running at "minify-js-app"
|
And the Server is running at "minify-js-app"
|
||||||
When I go to "/inline-js.html"
|
When I go to "/inline-js.html"
|
||||||
Then I should see "10" lines
|
Then I should see:
|
||||||
|
"""
|
||||||
|
<script type='text/javascript'>
|
||||||
|
//<![CDATA[
|
||||||
|
;(function() {
|
||||||
|
this;
|
||||||
|
should();
|
||||||
|
all.be();
|
||||||
|
on = { one: line };
|
||||||
|
})();
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
;(function() {
|
||||||
|
this;
|
||||||
|
should();
|
||||||
|
too();
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
//<!--
|
||||||
|
;(function() {
|
||||||
|
one;
|
||||||
|
line();
|
||||||
|
here();
|
||||||
|
})();
|
||||||
|
//-->
|
||||||
|
</script>
|
||||||
|
<script type='text/html'>
|
||||||
|
I'm a jQuery {{template}}.
|
||||||
|
</script>
|
||||||
|
"""
|
||||||
|
|
||||||
Scenario: Rendering inline js with a passthrough minifier
|
Scenario: Rendering inline js with a passthrough minifier
|
||||||
Given the Server is running at "passthrough-app"
|
Given the Server is running at "passthrough-app"
|
||||||
When I go to "/inline-js.html"
|
When I go to "/inline-js.html"
|
||||||
Then I should see "11" lines
|
Then I should see:
|
||||||
|
"""
|
||||||
|
<script type='text/javascript'>
|
||||||
|
//<![CDATA[
|
||||||
|
;(function() {
|
||||||
|
this;
|
||||||
|
should();
|
||||||
|
all.be();
|
||||||
|
on = { one: line };
|
||||||
|
})();
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
;(function() {
|
||||||
|
this;
|
||||||
|
should();
|
||||||
|
too();
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
//<!--
|
||||||
|
;(function() {
|
||||||
|
one;
|
||||||
|
line();
|
||||||
|
here();
|
||||||
|
})();
|
||||||
|
//-->
|
||||||
|
</script>
|
||||||
|
<script type='text/html'>
|
||||||
|
I'm a jQuery {{template}}.
|
||||||
|
</script>
|
||||||
|
"""
|
||||||
|
|
||||||
Scenario: Rendering inline js with the feature enabled
|
Scenario: Rendering inline js with the feature enabled
|
||||||
Given "minify_javascript" feature is "enabled"
|
Given "minify_javascript" feature is "enabled"
|
||||||
And the Server is running at "minify-js-app"
|
And the Server is running at "minify-js-app"
|
||||||
When I go to "/inline-js.html"
|
When I go to "/inline-js.html"
|
||||||
Then I should see "5" lines
|
Then I should see:
|
||||||
|
"""
|
||||||
|
<script type='text/javascript'>
|
||||||
|
//<![CDATA[
|
||||||
|
(function(){this,should(),all.be(),on={one:line}})();
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
(function(){this,should(),too()})();
|
||||||
|
</script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
//<!--
|
||||||
|
(function(){one,line(),here()})();
|
||||||
|
//-->
|
||||||
|
</script>
|
||||||
|
<script type='text/html'>
|
||||||
|
I'm a jQuery {{template}}.
|
||||||
|
</script>
|
||||||
|
"""
|
||||||
|
|
||||||
Scenario: Rendering external js with the feature enabled
|
Scenario: Rendering external js with the feature enabled
|
||||||
Given "minify_javascript" feature is "enabled"
|
Given "minify_javascript" feature is "enabled"
|
||||||
And the Server is running at "minify-js-app"
|
And the Server is running at "minify-js-app"
|
||||||
When I go to "/javascripts/js_test.js"
|
When I go to "/javascripts/js_test.js"
|
||||||
Then I should see "1" lines
|
Then I should see "1" lines
|
||||||
|
When I go to "/more-js/other.js"
|
||||||
|
Then I should see "1" lines
|
||||||
|
|
||||||
Scenario: Rendering external js with a passthrough minifier
|
Scenario: Rendering external js with a passthrough minifier
|
||||||
And the Server is running at "passthrough-app"
|
And the Server is running at "passthrough-app"
|
||||||
|
@ -36,7 +118,7 @@ Feature: Minify Javascript
|
||||||
Given "minify_javascript" feature is "enabled"
|
Given "minify_javascript" feature is "enabled"
|
||||||
And the Server is running at "minify-js-app"
|
And the Server is running at "minify-js-app"
|
||||||
When I go to "/inline-coffeescript.html"
|
When I go to "/inline-coffeescript.html"
|
||||||
Then I should see "5" lines
|
Then I should see "6" lines
|
||||||
|
|
||||||
Scenario: Rendering external js (coffeescript) with the feature enabled
|
Scenario: Rendering external js (coffeescript) with the feature enabled
|
||||||
Given "minify_javascript" feature is "enabled"
|
Given "minify_javascript" feature is "enabled"
|
||||||
|
@ -47,9 +129,10 @@ Feature: Minify Javascript
|
||||||
Scenario: Rendering inline js (coffeescript) with a passthrough minifier
|
Scenario: Rendering inline js (coffeescript) with a passthrough minifier
|
||||||
Given the Server is running at "passthrough-app"
|
Given the Server is running at "passthrough-app"
|
||||||
When I go to "/inline-coffeescript.html"
|
When I go to "/inline-coffeescript.html"
|
||||||
Then I should see "17" lines
|
Then I should see "16" lines
|
||||||
|
|
||||||
Scenario: Rendering external js (coffeescript) with a passthrough minifier
|
Scenario: Rendering external js (coffeescript) with a passthrough minifier
|
||||||
And the Server is running at "passthrough-app"
|
And the Server is running at "passthrough-app"
|
||||||
When I go to "/javascripts/coffee_test.js"
|
When I go to "/javascripts/coffee_test.js"
|
||||||
Then I should see "11" lines
|
Then I should see "11" lines
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
:css
|
||||||
|
body {
|
||||||
|
test: style;
|
||||||
|
good: deal;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
body {
|
||||||
|
display: block;
|
||||||
|
}
|
|
@ -5,3 +5,24 @@
|
||||||
all.be();
|
all.be();
|
||||||
on = { one: line };
|
on = { one: line };
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
%script
|
||||||
|
:plain
|
||||||
|
;(function() {
|
||||||
|
this;
|
||||||
|
should();
|
||||||
|
too();
|
||||||
|
})();
|
||||||
|
|
||||||
|
%script(type="text/javascript")
|
||||||
|
:plain
|
||||||
|
//<!--
|
||||||
|
;(function() {
|
||||||
|
one;
|
||||||
|
line();
|
||||||
|
here();
|
||||||
|
})();
|
||||||
|
//-->
|
||||||
|
|
||||||
|
%script(type="text/html")
|
||||||
|
I'm a jQuery {{template}}.
|
|
@ -0,0 +1,8 @@
|
||||||
|
var race;
|
||||||
|
var __slice = Array.prototype.slice;
|
||||||
|
|
||||||
|
race = function() {
|
||||||
|
var runners, winner;
|
||||||
|
winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
||||||
|
return print(winner, runners);
|
||||||
|
};
|
|
@ -4,12 +4,12 @@ module ::PassThrough
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
set :js_compressor, ::PassThrough
|
|
||||||
set :css_compressor, ::PassThrough
|
|
||||||
|
|
||||||
activate :minify_javascript
|
activate :minify_javascript
|
||||||
activate :minify_css
|
activate :minify_css
|
||||||
|
|
||||||
|
set :js_compressor, ::PassThrough
|
||||||
|
set :css_compressor, ::PassThrough
|
||||||
|
|
||||||
with_layout false do
|
with_layout false do
|
||||||
page "/inline-css.html"
|
page "/inline-css.html"
|
||||||
page "/inline-js.html"
|
page "/inline-js.html"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
:sass
|
%style(type="text/css")
|
||||||
body
|
:sass
|
||||||
test: style
|
body
|
||||||
good: deal
|
test: style
|
||||||
|
good: deal
|
|
@ -5,3 +5,24 @@
|
||||||
all.be();
|
all.be();
|
||||||
on = { one: line };
|
on = { one: line };
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
%script
|
||||||
|
:plain
|
||||||
|
;(function() {
|
||||||
|
this;
|
||||||
|
should();
|
||||||
|
too();
|
||||||
|
})();
|
||||||
|
|
||||||
|
%script(type="text/javascript")
|
||||||
|
:plain
|
||||||
|
//<!--
|
||||||
|
;(function() {
|
||||||
|
one;
|
||||||
|
line();
|
||||||
|
here();
|
||||||
|
})();
|
||||||
|
//-->
|
||||||
|
|
||||||
|
%script(type="text/html")
|
||||||
|
I'm a jQuery {{template}}.
|
|
@ -9,10 +9,6 @@ module Middleman::CoreExtensions::Sprockets
|
||||||
|
|
||||||
# Once registered
|
# Once registered
|
||||||
def registered(app)
|
def registered(app)
|
||||||
# Default compression to off
|
|
||||||
app.set :js_compressor, false
|
|
||||||
app.set :css_compressor, false
|
|
||||||
|
|
||||||
# Add class methods to context
|
# Add class methods to context
|
||||||
app.send :include, InstanceMethods
|
app.send :include, InstanceMethods
|
||||||
|
|
||||||
|
@ -70,28 +66,10 @@ module Middleman::CoreExtensions::Sprockets
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Remove old compressors
|
# Remove compressors, we handle these with middleware
|
||||||
unregister_bundle_processor 'application/javascript', :js_compressor
|
unregister_bundle_processor 'application/javascript', :js_compressor
|
||||||
unregister_bundle_processor 'text/css', :css_compressor
|
unregister_bundle_processor 'text/css', :css_compressor
|
||||||
|
|
||||||
# Register compressor from config
|
|
||||||
register_bundle_processor 'application/javascript', :js_compressor do |context, data|
|
|
||||||
if context.pathname.to_s =~ /\.min\./
|
|
||||||
data
|
|
||||||
else
|
|
||||||
app.js_compressor.compress(data)
|
|
||||||
end
|
|
||||||
end if app.js_compressor
|
|
||||||
|
|
||||||
# Register compressor from config
|
|
||||||
register_bundle_processor 'text/css', :css_compressor do |context, data|
|
|
||||||
if context.pathname.to_s =~ /\.min\./
|
|
||||||
data
|
|
||||||
else
|
|
||||||
app.css_compressor.compress(data)
|
|
||||||
end
|
|
||||||
end if app.css_compressor
|
|
||||||
|
|
||||||
# configure search paths
|
# configure search paths
|
||||||
append_path app.js_dir
|
append_path app.js_dir
|
||||||
append_path app.css_dir
|
append_path app.css_dir
|
||||||
|
|
|
@ -53,18 +53,7 @@ module Middleman::Extensions
|
||||||
dirpath = Pathname.new(File.dirname(path))
|
dirpath = Pathname.new(File.dirname(path))
|
||||||
|
|
||||||
if path =~ /(^\/$)|(\.(htm|html|php|css|js)$)/
|
if path =~ /(^\/$)|(\.(htm|html|php|css|js)$)/
|
||||||
body = case(response)
|
body = extract_response_text(response)
|
||||||
when String
|
|
||||||
response
|
|
||||||
when Array
|
|
||||||
response.join
|
|
||||||
when Rack::Response
|
|
||||||
response.body.join
|
|
||||||
when Rack::File
|
|
||||||
File.read(response.path)
|
|
||||||
else
|
|
||||||
response.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
if body
|
if body
|
||||||
# TODO: This regex will change some paths in plan HTML (not in a tag) - is that OK?
|
# TODO: This regex will change some paths in plan HTML (not in a tag) - is that OK?
|
||||||
|
@ -90,6 +79,23 @@ module Middleman::Extensions
|
||||||
end
|
end
|
||||||
[status, headers, response]
|
[status, headers, response]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def extract_response_text(response)
|
||||||
|
case(response)
|
||||||
|
when String
|
||||||
|
response
|
||||||
|
when Array
|
||||||
|
response.join
|
||||||
|
when Rack::Response
|
||||||
|
response.body.join
|
||||||
|
when Rack::File
|
||||||
|
File.read(response.path)
|
||||||
|
else
|
||||||
|
response.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,18 +9,84 @@ module Middleman::Extensions
|
||||||
|
|
||||||
# Once registered
|
# Once registered
|
||||||
def registered(app)
|
def registered(app)
|
||||||
# Tell Sprockets to use the built in CSSMin
|
app.set :css_compressor, false
|
||||||
|
|
||||||
app.after_configuration do
|
app.after_configuration do
|
||||||
if !css_compressor
|
unless respond_to?(:css_compressor) && css_compressor
|
||||||
require "middleman-more/extensions/minify_css/rainpress"
|
require "middleman-more/extensions/minify_css/rainpress"
|
||||||
set :css_compressor, ::Rainpress
|
set :css_compressor, ::Rainpress
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Setup Rack to watch for inline JS
|
||||||
|
use InlineCSSRack, :compressor => css_compressor
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
alias :included :registered
|
alias :included :registered
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Rack middleware to look for JS in HTML and compress it
|
||||||
|
class InlineCSSRack
|
||||||
|
|
||||||
|
# Init
|
||||||
|
# @param [Class] app
|
||||||
|
# @param [Hash] options
|
||||||
|
def initialize(app, options={})
|
||||||
|
@app = app
|
||||||
|
@compressor = options[:compressor]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Rack interface
|
||||||
|
# @param [Rack::Environmemt] env
|
||||||
|
# @return [Array]
|
||||||
|
def call(env)
|
||||||
|
status, headers, response = @app.call(env)
|
||||||
|
|
||||||
|
path = env["PATH_INFO"]
|
||||||
|
|
||||||
|
if path.end_with?('.html') || path.end_with?('.php')
|
||||||
|
uncompressed_source = extract_response_text(response)
|
||||||
|
|
||||||
|
minified = uncompressed_source.gsub(/(<style[^>]*?>\s*(?:\/\*<!\[CDATA\[\*\/\n)?)(.*?)((?:(?:\n\s*)?\/\*\]\]>\*\/)?\s*<\/style>)/m) do |match|
|
||||||
|
first = $1
|
||||||
|
css = $2
|
||||||
|
last = $3
|
||||||
|
|
||||||
|
minified_css = @compressor.compress(css)
|
||||||
|
|
||||||
|
first << minified_css << last
|
||||||
|
end
|
||||||
|
|
||||||
|
headers["Content-Length"] = ::Rack::Utils.bytesize(minified).to_s
|
||||||
|
response = [minified]
|
||||||
|
elsif path.end_with?('.css') && path !~ /\.min\./
|
||||||
|
uncompressed_source = extract_response_text(response)
|
||||||
|
minified_css = @compressor.compress(uncompressed_source)
|
||||||
|
|
||||||
|
headers["Content-Length"] = ::Rack::Utils.bytesize(minified_css).to_s
|
||||||
|
response = [minified_css]
|
||||||
|
end
|
||||||
|
|
||||||
|
[status, headers, response]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def extract_response_text(response)
|
||||||
|
case(response)
|
||||||
|
when String
|
||||||
|
response
|
||||||
|
when Array
|
||||||
|
response.join
|
||||||
|
when Rack::Response
|
||||||
|
response.body.join
|
||||||
|
when Rack::File
|
||||||
|
File.read(response.path)
|
||||||
|
else
|
||||||
|
response.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
# Register extension
|
# Register extension
|
||||||
# register :minify_css, MinifyCss
|
# register :minify_css, MinifyCss
|
||||||
end
|
end
|
|
@ -9,12 +9,11 @@ module Middleman::Extensions
|
||||||
|
|
||||||
# Once registered
|
# Once registered
|
||||||
def registered(app)
|
def registered(app)
|
||||||
|
app.set :js_compressor, false
|
||||||
|
|
||||||
# Once config is parsed
|
# Once config is parsed
|
||||||
app.after_configuration do
|
app.after_configuration do
|
||||||
|
unless respond_to?(:js_compressor) && js_compressor
|
||||||
# Tell sprockets which compressor to use
|
|
||||||
if !js_compressor
|
|
||||||
require 'uglifier'
|
require 'uglifier'
|
||||||
set :js_compressor, ::Uglifier.new
|
set :js_compressor, ::Uglifier.new
|
||||||
end
|
end
|
||||||
|
@ -43,32 +42,57 @@ module Middleman::Extensions
|
||||||
def call(env)
|
def call(env)
|
||||||
status, headers, response = @app.call(env)
|
status, headers, response = @app.call(env)
|
||||||
|
|
||||||
if env["PATH_INFO"].match(/\.html$/)
|
path = env["PATH_INFO"]
|
||||||
uncompressed_source = case(response)
|
|
||||||
when String
|
|
||||||
response
|
|
||||||
when Array
|
|
||||||
response.join
|
|
||||||
when Rack::Response
|
|
||||||
response.body.join
|
|
||||||
when Rack::File
|
|
||||||
File.read(response.path)
|
|
||||||
end
|
|
||||||
|
|
||||||
minified = uncompressed_source.gsub(/(<scri.*?\/\/<!\[CDATA\[\n)(.*?)(\/\/\]\].*?<\/script>)/m) do |m|
|
if path.end_with?('.html') || path.end_with?('.php')
|
||||||
|
uncompressed_source = extract_response_text(response)
|
||||||
|
|
||||||
|
minified = uncompressed_source.gsub(/(<script[^>]*?>\s*(?:\/\/(?:(?:<!--)|(?:<!\[CDATA\[))\n)?)(.*?)((?:(?:\n\s*)?\/\/(?:(?:-->)|(?:\]\]>)))?\s*<\/script>)/m) do |match|
|
||||||
first = $1
|
first = $1
|
||||||
uncompressed_source = $2
|
javascript = $2
|
||||||
last = $3
|
last = $3
|
||||||
minified_js = @compressor.compress(uncompressed_source)
|
|
||||||
|
|
||||||
first << minified_js << "\n" << last
|
# Only compress script tags that contain JavaScript (as opposed
|
||||||
|
# to something like jQuery templates, identified with a "text/html"
|
||||||
|
# type.
|
||||||
|
if first =~ /<script>/ || first.include?('text/javascript')
|
||||||
|
minified_js = @compressor.compress(javascript)
|
||||||
|
|
||||||
|
first << minified_js << last
|
||||||
|
else
|
||||||
|
match
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
headers["Content-Length"] = ::Rack::Utils.bytesize(minified).to_s
|
headers["Content-Length"] = ::Rack::Utils.bytesize(minified).to_s
|
||||||
response = [minified]
|
response = [minified]
|
||||||
|
elsif path.end_with?('.js') && path !~ /\.min\./
|
||||||
|
uncompressed_source = extract_response_text(response)
|
||||||
|
minified_js = @compressor.compress(uncompressed_source)
|
||||||
|
|
||||||
|
headers["Content-Length"] = ::Rack::Utils.bytesize(minified_js).to_s
|
||||||
|
response = [minified_js]
|
||||||
end
|
end
|
||||||
|
|
||||||
[status, headers, response]
|
[status, headers, response]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def extract_response_text(response)
|
||||||
|
case(response)
|
||||||
|
when String
|
||||||
|
response
|
||||||
|
when Array
|
||||||
|
response.join
|
||||||
|
when Rack::Response
|
||||||
|
response.body.join
|
||||||
|
when Rack::File
|
||||||
|
File.read(response.path)
|
||||||
|
else
|
||||||
|
response.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue