stylo 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/features/fixtures/child-min.js +2 -0
- data/features/javascripts.feature +7 -0
- data/features/step_definitions/stylo_steps.rb +4 -0
- data/lib/jsmin.rb +209 -0
- data/lib/stylo/config.rb +3 -1
- data/lib/stylo/pipeline_steps/javascript_minifying.rb +11 -0
- data/spec/pipeline_steps/javascript_minifying_spec.rb +47 -0
- data/stylo.gemspec +7 -2
- metadata +9 -4
data/Rakefile
CHANGED
@@ -18,7 +18,7 @@ begin
|
|
18
18
|
gem.add_development_dependency "sinatra", ">= 0"
|
19
19
|
gem.add_development_dependency "rails", ">= 3.0.0"
|
20
20
|
gem.add_runtime_dependency "haml", ">= 3.0.21"
|
21
|
-
gem.version = "0.
|
21
|
+
gem.version = "0.7.0"
|
22
22
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
23
23
|
end
|
24
24
|
Jeweler::GemcutterTasks.new
|
@@ -24,3 +24,10 @@ Feature: Javascript serving
|
|
24
24
|
And "child.js" is located at "javascripts" in the asset location
|
25
25
|
When a request is made for "javascripts/grand_parent.js"
|
26
26
|
Then the response body should look like "grand_parent_with_parent_with_child.js"
|
27
|
+
|
28
|
+
Scenario: Minifying javascript
|
29
|
+
Given javascript compression is enabled
|
30
|
+
And "child.js" is located at "javascripts" in the asset location
|
31
|
+
When a request is made for "javascripts/child.js"
|
32
|
+
Then the response body should look like "child-min.js"
|
33
|
+
|
data/lib/jsmin.rb
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
# jsmin.rb
|
2
|
+
# Author: Mike Wagg
|
3
|
+
# This work is a reworking of the ruby port of jsmin produced by
|
4
|
+
# Uladzislau Latynski which itself was a translation of the original
|
5
|
+
# C version published by Douglas Crockford. Permission is hereby granted to use the Ruby
|
6
|
+
# version under the same conditions as the jsmin.c on which it is
|
7
|
+
# based.
|
8
|
+
#
|
9
|
+
# /* jsmin.c
|
10
|
+
# 2003-04-21
|
11
|
+
#
|
12
|
+
# Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
13
|
+
#
|
14
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
15
|
+
# this software and associated documentation files (the "Software"), to deal in
|
16
|
+
# the Software without restriction, including without limitation the rights to
|
17
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
18
|
+
# of the Software, and to permit persons to whom the Software is furnished to do
|
19
|
+
# so, subject to the following conditions:
|
20
|
+
#
|
21
|
+
# The above copyright notice and this permission notice shall be included in all
|
22
|
+
# copies or substantial portions of the Software.
|
23
|
+
#
|
24
|
+
# The Software shall be used for Good, not Evil.
|
25
|
+
#
|
26
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
27
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
28
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
29
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
30
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
31
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
32
|
+
# SOFTWARE.
|
33
|
+
|
34
|
+
require 'stringio'
|
35
|
+
|
36
|
+
class JSMin
|
37
|
+
EOF = -1
|
38
|
+
|
39
|
+
def initialize(original)
|
40
|
+
@original = original
|
41
|
+
end
|
42
|
+
|
43
|
+
def minify
|
44
|
+
@output = ''
|
45
|
+
|
46
|
+
@in = StringIO.new(@original)
|
47
|
+
@out = StringIO.new(@output)
|
48
|
+
|
49
|
+
@the_a = ""
|
50
|
+
@the_b = ""
|
51
|
+
|
52
|
+
jsmin
|
53
|
+
|
54
|
+
@output
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def is_alpha_numeric(c)
|
60
|
+
return false if !c || c == EOF
|
61
|
+
|
62
|
+
((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
|
63
|
+
(c >= 'A' && c <= 'Z') || c == '_' || c == '$' ||
|
64
|
+
c == '\\' || (c[0].class == String ? c[0].ord : c[0]) > 126)
|
65
|
+
end
|
66
|
+
|
67
|
+
# get -- return the next character from stdin. Watch out for lookahead. If
|
68
|
+
# the character is a control character, translate it to a space or linefeed.
|
69
|
+
def get_next_character()
|
70
|
+
c = @in.getc
|
71
|
+
return EOF if (!c)
|
72
|
+
c = c.chr
|
73
|
+
return c if (c >= " " || c == "\n" || c.unpack("c") == EOF)
|
74
|
+
return "\n" if (c == "\r")
|
75
|
+
|
76
|
+
" "
|
77
|
+
end
|
78
|
+
|
79
|
+
def peek()
|
80
|
+
lookahead_char = @in.getc
|
81
|
+
@in.ungetc(lookahead_char)
|
82
|
+
lookahead_char.chr
|
83
|
+
end
|
84
|
+
|
85
|
+
def my_next()
|
86
|
+
c = get_next_character
|
87
|
+
if (c == "/")
|
88
|
+
if (peek == "/")
|
89
|
+
while (true)
|
90
|
+
c = get_next_character
|
91
|
+
if (c <= "\n")
|
92
|
+
return c
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
if (peek == "*")
|
97
|
+
get_next_character
|
98
|
+
while (true)
|
99
|
+
case get_next_character
|
100
|
+
when "*"
|
101
|
+
if (peek == "/")
|
102
|
+
get_next_character
|
103
|
+
return " "
|
104
|
+
end
|
105
|
+
when EOF
|
106
|
+
raise "Unterminated comment"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
c
|
113
|
+
end
|
114
|
+
|
115
|
+
def action(a)
|
116
|
+
if (a==1)
|
117
|
+
@out.write @the_a
|
118
|
+
end
|
119
|
+
if (a==1 || a==2)
|
120
|
+
@the_a = @the_b
|
121
|
+
if (@the_a == "\'" || @the_a == "\"")
|
122
|
+
while (true)
|
123
|
+
@out.write @the_a
|
124
|
+
@the_a = get_next_character
|
125
|
+
break if (@the_a == @the_b)
|
126
|
+
raise "Unterminated string literal" if (@the_a <= "\n")
|
127
|
+
if (@the_a == "\\")
|
128
|
+
@out.write @the_a
|
129
|
+
@the_a = get_next_character
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
if (a==1 || a==2 || a==3)
|
135
|
+
@the_b = my_next
|
136
|
+
if (@the_b == "/" && (@the_a == "(" || @the_a == "," || @the_a == "=" ||
|
137
|
+
@the_a == ":" || @the_a == "[" || @the_a == "!" ||
|
138
|
+
@the_a == "&" || @the_a == "|" || @the_a == "?" ||
|
139
|
+
@the_a == "{" || @the_a == "}" || @the_a == ";" ||
|
140
|
+
@the_a == "\n"))
|
141
|
+
@out.write @the_a
|
142
|
+
@out.write @the_b
|
143
|
+
while (true)
|
144
|
+
@the_a = get_next_character
|
145
|
+
if (@the_a == "/")
|
146
|
+
break
|
147
|
+
elsif (@the_a == "\\")
|
148
|
+
@out.write @the_a
|
149
|
+
@the_a = get_next_character
|
150
|
+
elsif (@the_a <= "\n")
|
151
|
+
raise "Unterminated RegExp Literal"
|
152
|
+
end
|
153
|
+
@out.write @the_a
|
154
|
+
end
|
155
|
+
@the_b = my_next
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def jsmin
|
161
|
+
@the_a = "\n"
|
162
|
+
action(3)
|
163
|
+
while (@the_a != EOF)
|
164
|
+
case @the_a
|
165
|
+
when " "
|
166
|
+
if (is_alpha_numeric(@the_b))
|
167
|
+
action(1)
|
168
|
+
else
|
169
|
+
action(2)
|
170
|
+
end
|
171
|
+
when "\n"
|
172
|
+
case (@the_b)
|
173
|
+
when "{", "[", "(", "+", "-"
|
174
|
+
action(1)
|
175
|
+
when " "
|
176
|
+
action(3)
|
177
|
+
else
|
178
|
+
if (is_alpha_numeric(@the_b))
|
179
|
+
action(1)
|
180
|
+
else
|
181
|
+
action(2)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
else
|
185
|
+
case (@the_b)
|
186
|
+
when " "
|
187
|
+
if (is_alpha_numeric(@the_a))
|
188
|
+
action(1)
|
189
|
+
else
|
190
|
+
action(3)
|
191
|
+
end
|
192
|
+
when "\n"
|
193
|
+
case (@the_a)
|
194
|
+
when "}", "]", ")", "+", "-", "\"", "\\", "'", '"'
|
195
|
+
action(1)
|
196
|
+
else
|
197
|
+
if (is_alpha_numeric(@the_a))
|
198
|
+
action(1)
|
199
|
+
else
|
200
|
+
action(3)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
else
|
204
|
+
action(1)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
data/lib/stylo/config.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
module Stylo
|
2
2
|
class Config
|
3
3
|
class << self
|
4
|
-
attr_accessor :asset_location, :css_combining_enabled, :javascript_combining_enabled
|
4
|
+
attr_accessor :asset_location, :css_combining_enabled, :javascript_combining_enabled, :javascript_minifying_enabled
|
5
5
|
|
6
6
|
def pipeline
|
7
7
|
[Stylo::PipelineSteps::Stylesheet.new,
|
8
8
|
Stylo::PipelineSteps::Javascript.new,
|
9
9
|
Stylo::PipelineSteps::Sass.new,
|
10
|
+
Stylo::PipelineSteps::JavascriptMinifying.new,
|
10
11
|
Stylo::PipelineSteps::Caching.new]
|
11
12
|
end
|
12
13
|
|
13
14
|
def reset_to_default
|
14
15
|
self.css_combining_enabled = true
|
15
16
|
self.javascript_combining_enabled = true
|
17
|
+
self.javascript_minifying_enabled = false
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Stylo
|
2
|
+
module PipelineSteps
|
3
|
+
class JavascriptMinifying
|
4
|
+
def call(response)
|
5
|
+
if Config.javascript_minifying_enabled and response.extension == '.js' and response.has_content?
|
6
|
+
response.set_body(JSMin.new(response.body).minify, :javascript)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Stylo::PipelineSteps::JavascriptMinifying do
|
4
|
+
before(:each) do
|
5
|
+
Stylo::Config.javascript_minifying_enabled = true
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:step) { Stylo::PipelineSteps::JavascriptMinifying.new }
|
9
|
+
let(:jsmin) { mock(:jsmin) }
|
10
|
+
|
11
|
+
describe "when the response body is not javascript" do
|
12
|
+
it "should not modify the response body" do
|
13
|
+
response = Stylo::Response.new('stylesheets/test.css')
|
14
|
+
original_body = "html{ color:#000; }"
|
15
|
+
response.set_body(original_body, :css)
|
16
|
+
|
17
|
+
step.call(response)
|
18
|
+
|
19
|
+
response.body.should == original_body
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "when the response body is javascript" do
|
24
|
+
let(:response) { Stylo::Response.new('javascrips/test.js') }
|
25
|
+
let(:minified_javascript) { 'I am minified!' }
|
26
|
+
|
27
|
+
before(:each) do
|
28
|
+
response.set_body('some javascript', :javascript)
|
29
|
+
|
30
|
+
JSMin.stub(:new).with(response.body).and_return(jsmin)
|
31
|
+
jsmin.stub(:minify).and_return(minified_javascript)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should ask jsmin to minify the javascript" do
|
35
|
+
JSMin.should_receive(:new).with(response.body).and_return(jsmin)
|
36
|
+
jsmin.should_receive(:minify)
|
37
|
+
|
38
|
+
step.call(response)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should replace the response body with the minified text" do
|
42
|
+
step.call(response)
|
43
|
+
|
44
|
+
response.body.should == minified_javascript
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/stylo.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{stylo}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.7.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["mwagg"]
|
12
|
-
s.date = %q{2010-11-
|
12
|
+
s.date = %q{2010-11-11}
|
13
13
|
s.description = %q{Server side stylesheet combining for readonly hosting environments}
|
14
14
|
s.email = %q{michael@guerillatactics.co.uk}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
"TODO",
|
27
27
|
"cucumber.yml",
|
28
28
|
"features/fixtures.rb",
|
29
|
+
"features/fixtures/child-min.js",
|
29
30
|
"features/fixtures/child.css",
|
30
31
|
"features/fixtures/child.js",
|
31
32
|
"features/fixtures/grand_parent.css",
|
@@ -50,12 +51,14 @@ Gem::Specification.new do |s|
|
|
50
51
|
"features/stylesheets.feature",
|
51
52
|
"features/stylo_cannot_serve_asset.feature",
|
52
53
|
"features/support/env.rb",
|
54
|
+
"lib/jsmin.rb",
|
53
55
|
"lib/stylo.rb",
|
54
56
|
"lib/stylo/asset_loader.rb",
|
55
57
|
"lib/stylo/combiner.rb",
|
56
58
|
"lib/stylo/config.rb",
|
57
59
|
"lib/stylo/pipeline_steps/caching.rb",
|
58
60
|
"lib/stylo/pipeline_steps/javascript.rb",
|
61
|
+
"lib/stylo/pipeline_steps/javascript_minifying.rb",
|
59
62
|
"lib/stylo/pipeline_steps/sass.rb",
|
60
63
|
"lib/stylo/pipeline_steps/stylesheet.rb",
|
61
64
|
"lib/stylo/processor.rb",
|
@@ -65,6 +68,7 @@ Gem::Specification.new do |s|
|
|
65
68
|
"spec/asset_loader_spec.rb",
|
66
69
|
"spec/combiner_spec.rb",
|
67
70
|
"spec/pipeline_steps/caching_spec.rb",
|
71
|
+
"spec/pipeline_steps/javascript_minifying_spec.rb",
|
68
72
|
"spec/pipeline_steps/javascript_spec.rb",
|
69
73
|
"spec/pipeline_steps/sass_spec.rb",
|
70
74
|
"spec/pipeline_steps/stylesheet_spec.rb",
|
@@ -82,6 +86,7 @@ Gem::Specification.new do |s|
|
|
82
86
|
"spec/asset_loader_spec.rb",
|
83
87
|
"spec/combiner_spec.rb",
|
84
88
|
"spec/pipeline_steps/caching_spec.rb",
|
89
|
+
"spec/pipeline_steps/javascript_minifying_spec.rb",
|
85
90
|
"spec/pipeline_steps/javascript_spec.rb",
|
86
91
|
"spec/pipeline_steps/sass_spec.rb",
|
87
92
|
"spec/pipeline_steps/stylesheet_spec.rb",
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stylo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 7
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.7.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- mwagg
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-11 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -125,6 +125,7 @@ files:
|
|
125
125
|
- TODO
|
126
126
|
- cucumber.yml
|
127
127
|
- features/fixtures.rb
|
128
|
+
- features/fixtures/child-min.js
|
128
129
|
- features/fixtures/child.css
|
129
130
|
- features/fixtures/child.js
|
130
131
|
- features/fixtures/grand_parent.css
|
@@ -149,12 +150,14 @@ files:
|
|
149
150
|
- features/stylesheets.feature
|
150
151
|
- features/stylo_cannot_serve_asset.feature
|
151
152
|
- features/support/env.rb
|
153
|
+
- lib/jsmin.rb
|
152
154
|
- lib/stylo.rb
|
153
155
|
- lib/stylo/asset_loader.rb
|
154
156
|
- lib/stylo/combiner.rb
|
155
157
|
- lib/stylo/config.rb
|
156
158
|
- lib/stylo/pipeline_steps/caching.rb
|
157
159
|
- lib/stylo/pipeline_steps/javascript.rb
|
160
|
+
- lib/stylo/pipeline_steps/javascript_minifying.rb
|
158
161
|
- lib/stylo/pipeline_steps/sass.rb
|
159
162
|
- lib/stylo/pipeline_steps/stylesheet.rb
|
160
163
|
- lib/stylo/processor.rb
|
@@ -164,6 +167,7 @@ files:
|
|
164
167
|
- spec/asset_loader_spec.rb
|
165
168
|
- spec/combiner_spec.rb
|
166
169
|
- spec/pipeline_steps/caching_spec.rb
|
170
|
+
- spec/pipeline_steps/javascript_minifying_spec.rb
|
167
171
|
- spec/pipeline_steps/javascript_spec.rb
|
168
172
|
- spec/pipeline_steps/sass_spec.rb
|
169
173
|
- spec/pipeline_steps/stylesheet_spec.rb
|
@@ -209,6 +213,7 @@ test_files:
|
|
209
213
|
- spec/asset_loader_spec.rb
|
210
214
|
- spec/combiner_spec.rb
|
211
215
|
- spec/pipeline_steps/caching_spec.rb
|
216
|
+
- spec/pipeline_steps/javascript_minifying_spec.rb
|
212
217
|
- spec/pipeline_steps/javascript_spec.rb
|
213
218
|
- spec/pipeline_steps/sass_spec.rb
|
214
219
|
- spec/pipeline_steps/stylesheet_spec.rb
|