dynamic_assets 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +6 -6
- data/app/helpers/dynamic_assets_helpers.rb +17 -13
- data/lib/dynamic_assets/cssmin.rb +110 -0
- data/lib/dynamic_assets/reference/stylesheet_reference.rb +1 -10
- data/lib/dynamic_assets.rb +1 -0
- data/spec/helpers/dynamic_assets_helpers_spec.rb +136 -41
- data/spec/lib/dynamic_assets/stylesheet_reference_spec.rb +88 -7
- data/spec/spec_helper.rb +1 -4
- metadata +4 -3
data/README.rdoc
CHANGED
|
@@ -41,14 +41,14 @@ dynamically is useful enough that multiple people have thought of implementing i
|
|
|
41
41
|
<tt>app/assets/javascripts</tt>. Each filename's extension triggers an
|
|
42
42
|
optional pre-processor:
|
|
43
43
|
|
|
44
|
-
.css = raw
|
|
45
|
-
.js = raw
|
|
44
|
+
.css = raw CSS
|
|
45
|
+
.js = raw JS
|
|
46
46
|
.css.erb = process with ERB
|
|
47
47
|
.js.erb = process with ERB
|
|
48
|
-
.
|
|
49
|
-
.
|
|
50
|
-
.
|
|
51
|
-
.
|
|
48
|
+
.sass = process with Sass and assume sass syntax
|
|
49
|
+
.scss = process with Sass and assume scss syntax
|
|
50
|
+
.sass.erb = process with ERB then Sass (sass syntax)
|
|
51
|
+
.scss.erb = process with ERB then Sass (scss syntax)
|
|
52
52
|
|
|
53
53
|
(Note that each file can be processed differently. You could stick one toe
|
|
54
54
|
into the Sass world by renaming one of your .css files to .scss.)
|
|
@@ -3,14 +3,12 @@ module DynamicAssetsHelpers
|
|
|
3
3
|
|
|
4
4
|
def stylesheet_asset_tag(group_key, http_attributes = {})
|
|
5
5
|
DynamicAssets::Manager.asset_references_for_group_key(:stylesheets, group_key).map do |asset_ref|
|
|
6
|
-
path = stylesheet_asset_path asset_ref.name
|
|
7
|
-
path << "?#{asset_ref.mtime.to_i.to_s}" if asset_ref.mtime.present?
|
|
8
6
|
|
|
9
7
|
tag :link, {
|
|
10
8
|
:type => "text/css",
|
|
11
9
|
:rel => "stylesheet",
|
|
12
10
|
:media => "screen",
|
|
13
|
-
:href =>
|
|
11
|
+
:href => asset_url(asset_ref)
|
|
14
12
|
}.merge!(http_attributes)
|
|
15
13
|
|
|
16
14
|
end.join.html_safe
|
|
@@ -18,12 +16,10 @@ module DynamicAssetsHelpers
|
|
|
18
16
|
|
|
19
17
|
def javascript_asset_tag(group_key, http_attributes = {})
|
|
20
18
|
DynamicAssets::Manager.asset_references_for_group_key(:javascripts, group_key).map do |asset_ref|
|
|
21
|
-
path = javascript_asset_path asset_ref.name
|
|
22
|
-
path << "?#{asset_ref.mtime.to_i.to_s}" if asset_ref.mtime.present?
|
|
23
19
|
|
|
24
20
|
content_tag :script, "", {
|
|
25
21
|
:type => "text/javascript",
|
|
26
|
-
:src =>
|
|
22
|
+
:src => asset_url(asset_ref)
|
|
27
23
|
}.merge!(http_attributes)
|
|
28
24
|
|
|
29
25
|
end.join.html_safe
|
|
@@ -32,16 +28,24 @@ module DynamicAssetsHelpers
|
|
|
32
28
|
|
|
33
29
|
protected
|
|
34
30
|
|
|
35
|
-
def
|
|
36
|
-
|
|
31
|
+
def asset_path(asset_ref)
|
|
32
|
+
name = asset_ref.name
|
|
33
|
+
|
|
34
|
+
case asset_ref
|
|
35
|
+
when DynamicAssets::StylesheetReference then stylesheet_asset_path name
|
|
36
|
+
when DynamicAssets::JavascriptReference then javascript_asset_path name
|
|
37
|
+
else raise "Unknown asset type: #{asset_ref}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def asset_url(asset_ref)
|
|
42
|
+
path = asset_path asset_ref
|
|
37
43
|
path = "/" + path unless path[0,1] == "/"
|
|
44
|
+
path << "?#{asset_ref.mtime.to_i.to_s}" if asset_ref.mtime.present?
|
|
45
|
+
|
|
38
46
|
host = compute_asset_host path
|
|
39
47
|
|
|
40
|
-
|
|
41
|
-
"#{host}#{path}"
|
|
42
|
-
else
|
|
43
|
-
path
|
|
44
|
-
end
|
|
48
|
+
host ? "#{host}#{path}" : path
|
|
45
49
|
end
|
|
46
50
|
|
|
47
51
|
# Extracted from Rails' AssetTagHelper, where it's private
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2008 Ryan Grove <ryan@wonko.com>
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
#
|
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
|
7
|
+
#
|
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
|
9
|
+
# this list of conditions and the following disclaimer.
|
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
# and/or other materials provided with the distribution.
|
|
13
|
+
# * Neither the name of this project nor the names of its contributors may be
|
|
14
|
+
# used to endorse or promote products derived from this software without
|
|
15
|
+
# specific prior written permission.
|
|
16
|
+
#
|
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
#++
|
|
28
|
+
|
|
29
|
+
# = CSSMin
|
|
30
|
+
#
|
|
31
|
+
# Minifies CSS using a fast, safe routine adapted from Julien Lecomte's YUI
|
|
32
|
+
# Compressor, which was in turn adapted from Isaac Schlueter's cssmin PHP
|
|
33
|
+
# script.
|
|
34
|
+
#
|
|
35
|
+
# Author:: Ryan Grove (mailto:ryan@wonko.com)
|
|
36
|
+
# Version:: 1.0.2 (2008-08-23)
|
|
37
|
+
# Copyright:: Copyright (c) 2008 Ryan Grove. All rights reserved.
|
|
38
|
+
# License:: New BSD License (http://opensource.org/licenses/bsd-license.php)
|
|
39
|
+
# Website:: http://github.com/rgrove/cssmin/
|
|
40
|
+
#
|
|
41
|
+
# == Example
|
|
42
|
+
#
|
|
43
|
+
# require 'rubygems'
|
|
44
|
+
# require 'cssmin'
|
|
45
|
+
#
|
|
46
|
+
# File.open('example.css', 'r') {|file| puts CSSMin.minify(file) }
|
|
47
|
+
#
|
|
48
|
+
module CSSMin
|
|
49
|
+
|
|
50
|
+
# Reads CSS from +input+ (which can be a String or an IO object) and
|
|
51
|
+
# returns a String containing minified CSS.
|
|
52
|
+
def self.minify(input)
|
|
53
|
+
css = input.is_a?(IO) ? input.read : input.dup.to_s
|
|
54
|
+
|
|
55
|
+
# Remove comments.
|
|
56
|
+
css.gsub!(/\/\*[\s\S]*?\*\//, '')
|
|
57
|
+
|
|
58
|
+
# Compress all runs of whitespace to a single space to make things easier
|
|
59
|
+
# to work with.
|
|
60
|
+
css.gsub!(/\s+/, ' ')
|
|
61
|
+
|
|
62
|
+
# Replace box model hacks with placeholders.
|
|
63
|
+
css.gsub!(/"\\"\}\\""/, '___BMH___')
|
|
64
|
+
|
|
65
|
+
# Remove unnecessary spaces, but be careful not to turn "p :link {...}"
|
|
66
|
+
# into "p:link{...}".
|
|
67
|
+
css.gsub!(/(?:^|\})[^\{:]+\s+:+[^\{]*\{/) do |match|
|
|
68
|
+
match.gsub(':', '___PSEUDOCLASSCOLON___')
|
|
69
|
+
end
|
|
70
|
+
css.gsub!(/\s+([!\{\};:>+\(\)\],])/, '\1')
|
|
71
|
+
css.gsub!('___PSEUDOCLASSCOLON___', ':')
|
|
72
|
+
css.gsub!(/([!\{\}:;>+\(\[,])\s+/, '\1')
|
|
73
|
+
|
|
74
|
+
# Add missing semicolons.
|
|
75
|
+
css.gsub!(/([^;\}])\}/, '\1;}')
|
|
76
|
+
|
|
77
|
+
# Replace 0(%, em, ex, px, in, cm, mm, pt, pc) with just 0.
|
|
78
|
+
css.gsub!(/([\s:])([+-]?0)(?:%|em|ex|px|in|cm|mm|pt|pc)/i, '\1\2')
|
|
79
|
+
|
|
80
|
+
# Replace 0 0 0 0; with 0.
|
|
81
|
+
css.gsub!(/:(?:0 )+0;/, ':0;')
|
|
82
|
+
|
|
83
|
+
# Replace background-position:0; with background-position:0 0;
|
|
84
|
+
css.gsub!('background-position:0;', 'background-position:0 0;')
|
|
85
|
+
|
|
86
|
+
# Replace 0.6 with .6, but only when preceded by : or a space.
|
|
87
|
+
css.gsub!(/(:|\s)0+\.(\d+)/, '\1.\2')
|
|
88
|
+
|
|
89
|
+
# Convert rgb color values to hex values.
|
|
90
|
+
css.gsub!(/rgb\s*\(\s*([0-9,\s]+)\s*\)/) do |match|
|
|
91
|
+
'#' << $1.scan(/\d+/).map{|n| n.to_i.to_s(16).rjust(2, '0') }.join
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Compress color hex values, making sure not to touch values used in IE
|
|
95
|
+
# filters, since they would break.
|
|
96
|
+
css.gsub!(/([^"'=\s])(\s?)\s*#([0-9a-f])\3([0-9a-f])\4([0-9a-f])\5/i, '\1\2#\3\4\5')
|
|
97
|
+
|
|
98
|
+
# Remove empty rules.
|
|
99
|
+
css.gsub!(/[^\}]+\{;\}\n/, '')
|
|
100
|
+
|
|
101
|
+
# Re-insert box model hacks.
|
|
102
|
+
css.gsub!('___BMH___', '"\"}\""')
|
|
103
|
+
|
|
104
|
+
# Prevent redundant semicolons.
|
|
105
|
+
css.gsub!(/;;+/, ';')
|
|
106
|
+
|
|
107
|
+
css.strip
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
end
|
|
@@ -14,6 +14,7 @@ module DynamicAssets
|
|
|
14
14
|
|
|
15
15
|
RELATIVE_URL_ROOT = "/stylesheets"
|
|
16
16
|
|
|
17
|
+
delegate :minify, :to => CSSMin
|
|
17
18
|
|
|
18
19
|
def formats
|
|
19
20
|
%w(sass scss css)
|
|
@@ -23,16 +24,6 @@ module DynamicAssets
|
|
|
23
24
|
:stylesheets
|
|
24
25
|
end
|
|
25
26
|
|
|
26
|
-
def minify(content_string)
|
|
27
|
-
# From asset_packager. PENDING: replace with github.com/rgrove/cssmin ?
|
|
28
|
-
content_string.gsub(/\s+/, " ").# collapse space
|
|
29
|
-
gsub(/\/\*(.*?)\*\//, ""). # remove comments
|
|
30
|
-
gsub(/\} /, "}\n"). # add line breaks
|
|
31
|
-
gsub(/\n$/, ""). # remove last break
|
|
32
|
-
gsub(/ \{ /, " {"). # trim inside brackets
|
|
33
|
-
gsub(/; \}/, "}") # trim inside brackets
|
|
34
|
-
end
|
|
35
|
-
|
|
36
27
|
|
|
37
28
|
protected
|
|
38
29
|
|
data/lib/dynamic_assets.rb
CHANGED
|
@@ -3,67 +3,162 @@ require 'spec_helper'
|
|
|
3
3
|
describe DynamicAssetsHelpers do
|
|
4
4
|
|
|
5
5
|
describe "#stylesheet_asset_tag" do
|
|
6
|
-
subject { helper.stylesheet_asset_tag
|
|
6
|
+
subject { helper.stylesheet_asset_tag *args }
|
|
7
7
|
|
|
8
|
-
context "when
|
|
9
|
-
let(:
|
|
8
|
+
context "when called with no arguments" do
|
|
9
|
+
let(:args) { [] }
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
and_return [
|
|
14
|
-
double(DynamicAssets::Reference, :name => "a", :mtime => 123),
|
|
15
|
-
double(DynamicAssets::Reference, :name => "b", :mtime => 456),
|
|
16
|
-
double(DynamicAssets::Reference, :name => "c", :mtime => 789)
|
|
17
|
-
]
|
|
11
|
+
it "fails with an ArgumentError" do
|
|
12
|
+
expect { subject }.to raise_error ArgumentError
|
|
18
13
|
end
|
|
14
|
+
end
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
context "when called with a group_key" do
|
|
17
|
+
let(:args) { [group_key] }
|
|
18
|
+
let(:group_key) { :base }
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
context "when the DynamicAssets::Manager says the given group key is associated with 3 stylesheets" do
|
|
21
|
+
|
|
22
|
+
before do
|
|
23
|
+
DynamicAssets::Manager.stub(:asset_references_for_group_key).with(:stylesheets, group_key).
|
|
24
|
+
and_return [
|
|
25
|
+
DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "a", :mtime => 123) },
|
|
26
|
+
DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "b", :mtime => 456) },
|
|
27
|
+
DynamicAssets::StylesheetReference.new.tap { |r| r.stub(:name => "c", :mtime => 789) }
|
|
28
|
+
]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "is three link tags" do
|
|
32
|
+
subject.scan('<link ').length.should == 3
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'is three tags with type="text/css"' do
|
|
36
|
+
subject.scan('type="text/css"').length.should == 3
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'is three tags with rel"stylesheet"' do
|
|
40
|
+
subject.scan('rel="stylesheet"').length.should == 3
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'is three tags with media="screen"' do
|
|
44
|
+
subject.scan('media="screen"').length.should == 3
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "when the arguments also include HTML attributes" do
|
|
48
|
+
before { args << { :media => "print", :id => "foo" } }
|
|
49
|
+
|
|
50
|
+
it "is three links, each of which has the given attributes" do
|
|
51
|
+
subject.scan('media="print"').length.should == 3
|
|
52
|
+
subject.scan('id="foo"').length.should == 3
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "when config.asset_host is nil" do
|
|
57
|
+
before { helper.config.asset_host.should be_nil }
|
|
58
|
+
|
|
59
|
+
it "is three tags with hrefs derived from the asset name and mtime" do
|
|
60
|
+
should contain_string 'href="/assets/stylesheets/a.css?123"'
|
|
61
|
+
should contain_string 'href="/assets/stylesheets/b.css?456"'
|
|
62
|
+
should contain_string 'href="/assets/stylesheets/c.css?789"'
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context "when config.asset_host is set to a.example.com" do
|
|
67
|
+
before { helper.config.stub(:asset_host).and_return "http://a.example.com" }
|
|
68
|
+
|
|
69
|
+
it "is three tags with hrefs whose host is a.example.com" do
|
|
70
|
+
should contain_string 'href="http://a.example.com/assets/stylesheets/a.css?123"'
|
|
71
|
+
should contain_string 'href="http://a.example.com/assets/stylesheets/b.css?456"'
|
|
72
|
+
should contain_string 'href="http://a.example.com/assets/stylesheets/c.css?789"'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "when config.asset_host is set to a%d.example.com" do
|
|
77
|
+
before { helper.config.stub(:asset_host).and_return "http://a%d.example.com" }
|
|
27
78
|
|
|
28
|
-
|
|
29
|
-
|
|
79
|
+
it "is three tags with hrefs whose host is a[0-3].example.com" do
|
|
80
|
+
should =~ /href="http:\/\/a[0-3].example.com\/assets\/stylesheets\/a.css\?123"/
|
|
81
|
+
should =~ /href="http:\/\/a[0-3].example.com\/assets\/stylesheets\/b.css\?456"/
|
|
82
|
+
should =~ /href="http:\/\/a[0-3].example.com\/assets\/stylesheets\/c.css\?789"/
|
|
83
|
+
end
|
|
84
|
+
end
|
|
30
85
|
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe "#javascript_asset_tag" do
|
|
90
|
+
subject { helper.javascript_asset_tag *args }
|
|
31
91
|
|
|
32
|
-
|
|
33
|
-
|
|
92
|
+
context "when called with no arguments" do
|
|
93
|
+
let(:args) { [] }
|
|
94
|
+
|
|
95
|
+
it "fails with an ArgumentError" do
|
|
96
|
+
expect { subject }.to raise_error ArgumentError
|
|
34
97
|
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context "when called with a group_key" do
|
|
101
|
+
let(:args) { [group_key] }
|
|
102
|
+
let(:group_key) { :base }
|
|
35
103
|
|
|
36
|
-
context "when
|
|
37
|
-
before { helper.config.asset_host.should be_nil }
|
|
104
|
+
context "when the DynamicAssets::Manager says the given group key is associated with 3 scripts" do
|
|
38
105
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
106
|
+
before do
|
|
107
|
+
DynamicAssets::Manager.stub(:asset_references_for_group_key).with(:javascripts, group_key).
|
|
108
|
+
and_return [
|
|
109
|
+
DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "a", :mtime => 123) },
|
|
110
|
+
DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "b", :mtime => 456) },
|
|
111
|
+
DynamicAssets::JavascriptReference.new.tap { |r| r.stub(:name => "c", :mtime => 789) }
|
|
112
|
+
]
|
|
43
113
|
end
|
|
44
|
-
end
|
|
45
114
|
|
|
46
|
-
|
|
47
|
-
|
|
115
|
+
it "is three script tags" do
|
|
116
|
+
subject.scan('<script ').length.should == 3
|
|
117
|
+
end
|
|
48
118
|
|
|
49
|
-
it
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
119
|
+
it 'is three tags with type="text/javascript"' do
|
|
120
|
+
subject.scan('type="text/javascript"').length.should == 3
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
context "when the arguments also include HTML attributes" do
|
|
124
|
+
before { args << { :id => "foo" } }
|
|
125
|
+
|
|
126
|
+
it "is three links, each of which has the given attributes" do
|
|
127
|
+
subject.scan('id="foo"').length.should == 3
|
|
128
|
+
end
|
|
53
129
|
end
|
|
54
|
-
end
|
|
55
130
|
|
|
56
|
-
|
|
57
|
-
|
|
131
|
+
context "when config.asset_host is nil" do
|
|
132
|
+
before { helper.config.asset_host.should be_nil }
|
|
58
133
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
134
|
+
it "is three tags with srcs derived from the asset name and mtime" do
|
|
135
|
+
should contain_string 'src="/assets/javascripts/a.js?123"'
|
|
136
|
+
should contain_string 'src="/assets/javascripts/b.js?456"'
|
|
137
|
+
should contain_string 'src="/assets/javascripts/c.js?789"'
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context "when config.asset_host is set to a.example.com" do
|
|
142
|
+
before { helper.config.stub(:asset_host).and_return "http://a.example.com" }
|
|
143
|
+
|
|
144
|
+
it "is three tags with srcs whose host is a.example.com" do
|
|
145
|
+
should contain_string 'src="http://a.example.com/assets/javascripts/a.js?123"'
|
|
146
|
+
should contain_string 'src="http://a.example.com/assets/javascripts/b.js?456"'
|
|
147
|
+
should contain_string 'src="http://a.example.com/assets/javascripts/c.js?789"'
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
context "when config.asset_host is set to a%d.example.com" do
|
|
152
|
+
before { helper.config.stub(:asset_host).and_return "http://a%d.example.com" }
|
|
153
|
+
|
|
154
|
+
it "is three tags with srcs whose host is a[0-3].example.com" do
|
|
155
|
+
should =~ /src="http:\/\/a[0-3].example.com\/assets\/javascripts\/a.js\?123"/
|
|
156
|
+
should =~ /src="http:\/\/a[0-3].example.com\/assets\/javascripts\/b.js\?456"/
|
|
157
|
+
should =~ /src="http:\/\/a[0-3].example.com\/assets\/javascripts\/c.js\?789"/
|
|
158
|
+
end
|
|
63
159
|
end
|
|
64
160
|
end
|
|
65
161
|
end
|
|
66
|
-
|
|
67
162
|
end
|
|
68
163
|
|
|
69
164
|
end
|
|
@@ -10,18 +10,44 @@ module DynamicAssets
|
|
|
10
10
|
context "when a css file with the given reference name exists" do
|
|
11
11
|
before do
|
|
12
12
|
reference.stub(:path_for_member_name).with("thing").and_return "/foo/thing.css"
|
|
13
|
-
reference.stub(:raw_content_exists?).and_return false
|
|
14
13
|
reference.stub(:raw_content_exists?).with("/foo/thing.css").and_return true
|
|
15
|
-
reference.stub(:get_raw_content).with("/foo/thing.css").and_return
|
|
14
|
+
reference.stub(:get_raw_content).with("/foo/thing.css").and_return raw_content
|
|
16
15
|
end
|
|
17
16
|
|
|
18
17
|
context "and the file is blank" do
|
|
19
|
-
let(:
|
|
18
|
+
let(:raw_content) { "" }
|
|
20
19
|
it { should be_blank }
|
|
21
20
|
end
|
|
22
21
|
|
|
22
|
+
context "and the file contains styles" do
|
|
23
|
+
let(:raw_content) { "div.foo { color: #FFF }" }
|
|
24
|
+
|
|
25
|
+
context "and the Manager is not configured to minify" do
|
|
26
|
+
before { Manager.stub :minify? => false }
|
|
27
|
+
|
|
28
|
+
it "is the raw content" do
|
|
29
|
+
subject.should == raw_content
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "does not call its own #minify method" do
|
|
33
|
+
reference.should_not_receive :minify
|
|
34
|
+
subject
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "and the Manager is configured to minify" do
|
|
39
|
+
before { Manager.stub :minify? => true }
|
|
40
|
+
|
|
41
|
+
it "is the result of calling its own #minify method" do
|
|
42
|
+
reference.should_receive(:minify).and_return "tiny output"
|
|
43
|
+
subject.should == "tiny output"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
23
49
|
context "and the file contains URLs relative to the stylesheet" do
|
|
24
|
-
let(:
|
|
50
|
+
let(:raw_content) { "body { background: url(background.gif); }" }
|
|
25
51
|
|
|
26
52
|
it "makes the URLs relative to RELATIVE_URL_ROOT and the member name" do
|
|
27
53
|
should contain_string "url(#{StylesheetReference::RELATIVE_URL_ROOT}/thing/background.gif)"
|
|
@@ -29,7 +55,7 @@ module DynamicAssets
|
|
|
29
55
|
end
|
|
30
56
|
|
|
31
57
|
context "and the file contains URLs within directories relative to the stylesheet" do
|
|
32
|
-
let(:
|
|
58
|
+
let(:raw_content) { "body { background: url(a/b/background.gif); }" }
|
|
33
59
|
|
|
34
60
|
it "makes the URLs relative to RELATIVE_URL_ROOT and the member name" do
|
|
35
61
|
should contain_string "url(#{StylesheetReference::RELATIVE_URL_ROOT}/thing/a/b/background.gif)"
|
|
@@ -37,7 +63,7 @@ module DynamicAssets
|
|
|
37
63
|
end
|
|
38
64
|
|
|
39
65
|
context "and the file contains URLs with dots, relative to the stylesheet" do
|
|
40
|
-
let(:
|
|
66
|
+
let(:raw_content) { "body { background: url(../a/b/background.gif); }" }
|
|
41
67
|
|
|
42
68
|
it "makes the URLs relative to RELATIVE_URL_ROOT and the member name, ignoring leading dots" do
|
|
43
69
|
should contain_string "url(#{StylesheetReference::RELATIVE_URL_ROOT}/thing/a/b/background.gif)"
|
|
@@ -45,7 +71,7 @@ module DynamicAssets
|
|
|
45
71
|
end
|
|
46
72
|
|
|
47
73
|
context "and the file contains full URLs with hosts" do
|
|
48
|
-
let(:
|
|
74
|
+
let(:raw_content) { "body { background: url(http://www.example.com/background.gif); }" }
|
|
49
75
|
|
|
50
76
|
it "leaves the URLs unchanged" do
|
|
51
77
|
should contain_string "url(http://www.example.com/background.gif)"
|
|
@@ -54,5 +80,60 @@ module DynamicAssets
|
|
|
54
80
|
end
|
|
55
81
|
end
|
|
56
82
|
|
|
83
|
+
describe "#minify" do
|
|
84
|
+
subject { reference.minify content }
|
|
85
|
+
let(:reference) { StylesheetReference.new :name => "thing" }
|
|
86
|
+
|
|
87
|
+
context "when given content that has whitespace and comments" do
|
|
88
|
+
let(:content) do %Q!
|
|
89
|
+
/*
|
|
90
|
+
* Some sample styles
|
|
91
|
+
*/
|
|
92
|
+
div.foo { color: #FFF; } /* foo style */
|
|
93
|
+
div.bar, span.baz { font-size: 12px; }
|
|
94
|
+
!
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "is the result of calling CSSMin.minify" do
|
|
98
|
+
CSSMin.should_receive(:minify).with(content).and_return "tiny content"
|
|
99
|
+
subject.should == "tiny content"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# We assume CSSMin is fully tested, but as a sanity check we
|
|
103
|
+
# observe the StylesheetReference's behavior with a few examples:
|
|
104
|
+
|
|
105
|
+
it "contains no double spaces" do
|
|
106
|
+
should_not =~ / /
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "contains no newlines" do
|
|
110
|
+
should_not =~ /\n/
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "removes space between selectors" do
|
|
114
|
+
should contain_string "div.bar,span.baz"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "removes space around opening brackets" do
|
|
118
|
+
should contain_string "span.baz{font-size"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "removes space around closing brackets" do
|
|
122
|
+
should contain_string "}div.bar"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "removes space around values" do
|
|
126
|
+
should contain_string "font-size:12px;}"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "removes comments that are on their own lines" do
|
|
130
|
+
should_not contain_string "Some sample styles"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "removes comments that are on the same line as a style" do
|
|
134
|
+
should_not contain_string "Some sample styles"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
57
138
|
end
|
|
58
139
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -6,10 +6,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
|
6
6
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
7
7
|
|
|
8
8
|
require 'rspec/rails'
|
|
9
|
-
|
|
10
|
-
require "capybara/rails"
|
|
11
|
-
Capybara.default_driver = :rack_test
|
|
12
|
-
Capybara.default_selector = :css
|
|
9
|
+
require 'capybara/rspec'
|
|
13
10
|
|
|
14
11
|
require 'dynamic_assets'
|
|
15
12
|
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dynamic_assets
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 19
|
|
5
5
|
prerelease: false
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
|
-
-
|
|
8
|
+
- 3
|
|
9
9
|
- 0
|
|
10
|
-
version: 0.
|
|
10
|
+
version: 0.3.0
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Robert Davis
|
|
@@ -128,6 +128,7 @@ files:
|
|
|
128
128
|
- lib/dynamic_assets/config.rb
|
|
129
129
|
- lib/dynamic_assets/controller.rb
|
|
130
130
|
- lib/dynamic_assets/core_extensions.rb
|
|
131
|
+
- lib/dynamic_assets/cssmin.rb
|
|
131
132
|
- lib/dynamic_assets/engine.rb
|
|
132
133
|
- lib/dynamic_assets/manager.rb
|
|
133
134
|
- lib/dynamic_assets/reference.rb
|