html_press 0.6.5 → 0.6.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme.md +19 -19
- data/html_press.gemspec +1 -1
- data/lib/html_press/css_press.rb +1 -1
- data/lib/html_press/html.rb +50 -21
- data/lib/html_press/version.rb +1 -1
- data/spec/html_press_spec.rb +219 -217
- metadata +98 -66
data/Readme.md
CHANGED
@@ -70,34 +70,34 @@ bundle install
|
|
70
70
|
bundle exec jekyll
|
71
71
|
```
|
72
72
|
|
73
|
-
## Additional tools
|
74
|
-
|
75
|
-
- https://github.com/aberant/css-spriter
|
76
|
-
- https://github.com/sstephenson/sprockets
|
77
|
-
- https://github.com/documentcloud/jammit
|
78
|
-
- https://github.com/cjohansen/juicer
|
79
|
-
- https://github.com/alexdunae/w3c_validators
|
80
|
-
|
81
73
|
## TODO
|
82
74
|
|
75
|
+
- use parser ([鋸](https://github.com/tenderlove/nokogiri)) instead of regexp's
|
83
76
|
- check if all utf-8 symbols, are smaller than html entities
|
84
77
|
- ambigious ampersands
|
85
|
-
-
|
86
|
-
- Support other minifiers (Closure, YUI compressor)
|
78
|
+
- cli
|
79
|
+
- Support other js/css minifiers (Closure, YUI compressor)
|
87
80
|
- htmlTydi
|
88
81
|
- add examples of usage with Sinatra and Rails
|
89
|
-
- https://github.com/gfranco/jeanny
|
90
|
-
- https://github.com/aanand/deadweight
|
91
82
|
|
92
83
|
## Alternatives
|
93
84
|
|
94
|
-
|
85
|
+
- [html-minifier](https://github.com/kangax/html-minifier) (js), [test suite](https://github.com/kangax/html-minifier/blob/gh-pages/tests/index.html), [ruby wrapper - html_minifier](https://github.com/stereobooster/html_minifier)
|
86
|
+
- [htmlcompressor](http://code.google.com/p/htmlcompressor/) (java), [test suite](http://code.google.com/p/htmlcompressor/source/browse/#svn%2Ftrunk%2Fsrc%2Ftest%2Fresources%2Fhtml%253Fstate%253Dclosed)
|
87
|
+
- PHPTal compress (php), [test suite](https://svn.motion-twin.com/phptal/trunk/tests/CompressTest.php)
|
88
|
+
- [W3 total cache](http://wordpress.org/extend/plugins/w3-total-cache/) - WP plugin from smashingmagazine contains html minifier (php)
|
95
89
|
|
96
|
-
|
97
|
-
- https://github.com/MadRabbit/frontcompiler
|
90
|
+
## Additional tools
|
98
91
|
|
99
|
-
|
92
|
+
- https://github.com/gfranco/jeanny
|
93
|
+
- https://github.com/aanand/deadweight
|
94
|
+
- https://github.com/aberant/css-spriter
|
95
|
+
- https://github.com/sstephenson/sprockets
|
96
|
+
- https://github.com/documentcloud/jammit
|
97
|
+
- https://github.com/cjohansen/juicer
|
98
|
+
- https://github.com/alexdunae/w3c_validators
|
100
99
|
|
101
|
-
|
102
|
-
-
|
103
|
-
-
|
100
|
+
## Resources
|
101
|
+
- http://perfectionkills.com/experimenting-with-html-minifier
|
102
|
+
- http://perfectionkills.com/optimizing-html
|
103
|
+
- https://developers.google.com/speed/articles/optimizing-html
|
data/html_press.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_development_dependency "rspec"
|
24
24
|
s.add_development_dependency "rake"
|
25
25
|
|
26
|
-
s.add_runtime_dependency "css_press", ">=0.3.
|
26
|
+
s.add_runtime_dependency "css_press", ">=0.3.2"
|
27
27
|
s.add_runtime_dependency "uglifier"
|
28
28
|
s.add_runtime_dependency "htmlentities"
|
29
29
|
end
|
data/lib/html_press/css_press.rb
CHANGED
data/lib/html_press/html.rb
CHANGED
@@ -4,11 +4,15 @@ module HtmlPress
|
|
4
4
|
DEFAULTS = {
|
5
5
|
:logger => false,
|
6
6
|
:unquoted_attributes => false,
|
7
|
-
:
|
7
|
+
:drop_empty_values => false
|
8
8
|
}
|
9
9
|
|
10
10
|
def initialize (options = {})
|
11
11
|
@options = DEFAULTS.merge(options)
|
12
|
+
if @options.keys.include? :dump_empty_values
|
13
|
+
@options[:drop_empty_values] = @options.delete(:dump_empty_values)
|
14
|
+
warn "dump_empty_values deprecated use drop_empty_values"
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
def log (text)
|
@@ -37,7 +41,10 @@ module HtmlPress
|
|
37
41
|
# replace SCRIPTs (and minify) with placeholders
|
38
42
|
out.gsub! /\s*(<script\b[^>]*?>[\s\S]*?<\/script>)\s*/i do |m|
|
39
43
|
m.gsub!(/^\s+|\s+$/, '')
|
40
|
-
|
44
|
+
m = m.gsub /^<script\s([^>]+)>/i do |m|
|
45
|
+
attrs(m, 'script', true)
|
46
|
+
end
|
47
|
+
js = m.gsub(/^<script\b[^>]*?>([\s\S]*?)<\/script>/i , "\\1")
|
41
48
|
begin
|
42
49
|
js_compressed = HtmlPress.js_compressor js
|
43
50
|
m.gsub!(js, js_compressed)
|
@@ -50,7 +57,10 @@ module HtmlPress
|
|
50
57
|
# replace STYLEs (and minify) with placeholders
|
51
58
|
out.gsub! /\s*(<style\b[^>]*?>[\s\S]*?<\/style>)\s*/i do |m|
|
52
59
|
m.gsub!(/^\s+|\s+$/, '')
|
53
|
-
|
60
|
+
m = m.gsub /^<style\s([^>]+)>/i do |m|
|
61
|
+
attrs(m, 'style', true)
|
62
|
+
end
|
63
|
+
css = m.gsub(/^<style\b[^>]*?>([\s\S]*?)<\/style>/i, "\\1")
|
54
64
|
begin
|
55
65
|
css_compressed = HtmlPress.style_compressor css
|
56
66
|
m.gsub!(css, css_compressed)
|
@@ -150,15 +160,17 @@ module HtmlPress
|
|
150
160
|
attr k, "'", tag
|
151
161
|
end
|
152
162
|
|
163
|
+
attributes_compressed = " " + attributes_compressed.strip
|
164
|
+
|
153
165
|
if attributes_compressed == " /"
|
154
166
|
attributes_compressed = "/"
|
155
167
|
elsif attributes_compressed == " "
|
156
168
|
attributes_compressed = ""
|
157
169
|
end
|
158
|
-
|
170
|
+
m.gsub(attributes, attributes_compressed)
|
171
|
+
else
|
172
|
+
m
|
159
173
|
end
|
160
|
-
|
161
|
-
return m
|
162
174
|
end
|
163
175
|
|
164
176
|
def attr(attribute, delimiter, tag)
|
@@ -170,19 +182,25 @@ module HtmlPress
|
|
170
182
|
name = name_original.downcase
|
171
183
|
tag_name = tag.downcase
|
172
184
|
|
185
|
+
if value.size > 0
|
186
|
+
re = "^=" + delimiter + "|" + delimiter + "$"
|
187
|
+
re = Regexp.new re
|
188
|
+
value_original.gsub!(re, "")
|
189
|
+
end
|
190
|
+
|
173
191
|
case tag_name
|
174
192
|
when "script"
|
175
|
-
if name == "type" || name == "language"
|
193
|
+
if (name == "type" && value_original == "text/javascript") || (name == "language" && value_original == "JavaScript")
|
176
194
|
return ""
|
177
195
|
elsif name == "async" || name == "defer"
|
178
196
|
return name_original
|
179
197
|
end
|
180
198
|
when "form"
|
181
|
-
if name == "method" &&
|
199
|
+
if name == "method" && value_original == "get"
|
182
200
|
return ""
|
183
201
|
end
|
184
202
|
when /link|style/
|
185
|
-
if name == "type"
|
203
|
+
if name == "type" && value_original == "text/stylesheet"
|
186
204
|
return ""
|
187
205
|
end
|
188
206
|
when /input|textarea|button|select|option|optgroup/
|
@@ -196,7 +214,7 @@ module HtmlPress
|
|
196
214
|
return name_original
|
197
215
|
end
|
198
216
|
if tag_name == "input"
|
199
|
-
if name == "type" &&
|
217
|
+
if name == "type" && value_original == "text"
|
200
218
|
return ""
|
201
219
|
end
|
202
220
|
if name == "checked"
|
@@ -208,14 +226,20 @@ module HtmlPress
|
|
208
226
|
end
|
209
227
|
end
|
210
228
|
|
211
|
-
if value.size
|
212
|
-
|
213
|
-
re = "^=" + delimiter + "|" + delimiter + "$"
|
214
|
-
re = Regexp.new re
|
215
|
-
value_original.gsub!(re, "")
|
229
|
+
if value.size > 0
|
216
230
|
|
217
231
|
if name == "style"
|
218
|
-
|
232
|
+
begin
|
233
|
+
value_original = HtmlPress.css_compressor value_original
|
234
|
+
# TODO what about escaped attribute values?
|
235
|
+
if delimiter == "\""
|
236
|
+
value_original.gsub!("\"", "'")
|
237
|
+
else
|
238
|
+
value_original.gsub!("'", "\"")
|
239
|
+
end
|
240
|
+
rescue Exception => e
|
241
|
+
log e.message
|
242
|
+
end
|
219
243
|
end
|
220
244
|
|
221
245
|
if name == "class"
|
@@ -228,16 +252,21 @@ module HtmlPress
|
|
228
252
|
onmouseout onkeypress onkeydown onkeyup]
|
229
253
|
|
230
254
|
if events.include? name
|
231
|
-
value_original.gsub! /^javascript:\s
|
232
|
-
|
233
|
-
|
234
|
-
|
255
|
+
value_original.gsub! /^javascript:\s+|;$/, ''
|
256
|
+
begin
|
257
|
+
value_original = HtmlPress.js_compressor value_original
|
258
|
+
# TODO what about escaped attribute values?
|
259
|
+
if delimiter == "\""
|
260
|
+
value_original.gsub! "\"", "'"
|
261
|
+
end
|
262
|
+
rescue Exception => e
|
263
|
+
log e.message
|
235
264
|
end
|
236
265
|
end
|
237
266
|
|
238
267
|
if value_original.size == 0
|
239
268
|
#attribute without value may be dropped by IE7
|
240
|
-
if @options[:
|
269
|
+
if @options[:drop_empty_values]
|
241
270
|
attribute = name_original
|
242
271
|
else
|
243
272
|
attribute = name_original + "=" + delimiter + delimiter
|
data/lib/html_press/version.rb
CHANGED
data/spec/html_press_spec.rb
CHANGED
@@ -1,218 +1,220 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require File.expand_path("../lib/html_press", File.dirname(__FILE__))
|
4
|
-
|
5
|
-
class Lg
|
6
|
-
class << self
|
7
|
-
@warns = []
|
8
|
-
attr_accessor :warns
|
9
|
-
def log text
|
10
|
-
Lg.warns.push text
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
describe HtmlPress do
|
16
|
-
before :each do
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should leave only one whitespace between inline tags" do
|
20
|
-
HtmlPress.press("<p>lorem <b>ipsum</b> <i>dolor</i> </p>").should eql "<p>lorem <b>ipsum</b> <i>dolor</i></p>"
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should leave no whitespaces between block tags" do
|
24
|
-
HtmlPress.press("<div></div> \t\r\n <div></div>").should eql "<div></div><div></div>"
|
25
|
-
HtmlPress.press("<div> <div> \t\r\n </div> </div>").should eql "<div><div></div></div>"
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should leave only one whitespace in text" do
|
29
|
-
HtmlPress.press("<p>a a</p>").should eql "<p>a a</p>"
|
30
|
-
end
|
31
|
-
|
32
|
-
it "should leave newlines in pre tags and remove trailing spaces" do
|
33
|
-
HtmlPress.press("<pre>a \t </pre>").should eql "<pre>a</pre>"
|
34
|
-
HtmlPress.press("<pre>qwe \nasd </pre>").should eql "<pre>qwe\nasd</pre>"
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should leave textareas as is" do
|
38
|
-
text = "<textarea> \t </textarea>"
|
39
|
-
HtmlPress.press(text).should eql text
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should compress js in script tags" do
|
43
|
-
script = " (function(undefined){ \t\n var long_name = ' '; }()) \n \r"
|
44
|
-
pressed_script = "<script>" + HtmlPress.js_compressor(script) + "</script>"
|
45
|
-
script = " <script>" + script + "</script> "
|
46
|
-
HtmlPress.press(script).should eql pressed_script
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should compress css in style tags" do
|
50
|
-
style = " div { margin: 0px 0px; \n} "
|
51
|
-
pressed_style = "<style>" + HtmlPress.style_compressor(style) + "</style>"
|
52
|
-
style = " <style>" + style + "</style> "
|
53
|
-
HtmlPress.press(style).should eql pressed_style
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should remove html comments" do
|
57
|
-
HtmlPress.press("<p></p><!-- comment --><p></p>").should eql "<p></p><p></p>"
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should leave IE conditional comments" do
|
61
|
-
text = "<!--[if IE]><html class=\"ie\"><![endif]--><div></div>"
|
62
|
-
HtmlPress.press(text).should eql text
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should work with special utf-8 symbols" do
|
66
|
-
HtmlPress.press("✪<p></p> <p></p>").should eql "✪<p></p><p></p>"
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should work with tags in upper case" do
|
70
|
-
HtmlPress.press("<P> </p>").should eql "<P></p>"
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should remove whitespaces between IE conditional comments" do
|
74
|
-
text = "<p></p> <!--[if IE]><html class=\"ie\"> <![endif]--> <!--[if IE]><html class=\"ie1\"><![endif]-->"
|
75
|
-
text2 = "<p></p><!--[if IE]><html class=\"ie\"><![endif]--><!--[if IE]><html class=\"ie1\"><![endif]-->"
|
76
|
-
HtmlPress.press(text).should eql text2
|
77
|
-
end
|
78
|
-
|
79
|
-
it "should treat text inside IE conditional comments as it was without comments" do
|
80
|
-
text = "<div class=\"a\" id=\"b\"> </div> <p></p>"
|
81
|
-
text2 = HtmlPress.press(text)
|
82
|
-
text = "<!--[if IE]>" + text + "<![endif]-->"
|
83
|
-
text2 = "<!--[if IE]>" + text2 + "<![endif]-->"
|
84
|
-
HtmlPress.press(text).should eql text2
|
85
|
-
text = "<script> (function(undefined){ var a;}()) </script>"
|
86
|
-
text2 = HtmlPress.press(text)
|
87
|
-
text = "<!--[if IE]>" + text + "<![endif]-->"
|
88
|
-
text2 = "<!--[if IE]>" + text2 + "<![endif]-->"
|
89
|
-
HtmlPress.press(text).should eql text2
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should remove unnecessary whitespaces inside tag" do
|
93
|
-
HtmlPress.press("<p class=\"a\" id=\"b\"></p>").should eql "<p class=\"a\" id=\"b\"></p>"
|
94
|
-
HtmlPress.press("<p class=\"a\" ></p>").should eql "<p class=\"a\"></p>"
|
95
|
-
HtmlPress.press("<img src=\"\" />").should eql "<img src=\"\"/>"
|
96
|
-
HtmlPress.press("<br />").should eql "<br/>"
|
97
|
-
end
|
98
|
-
|
99
|
-
it "should work with 'badly' formatted attributes" do
|
100
|
-
HtmlPress.press("<p class='a' id='b'></p>").should eql "<p class='a' id='b'></p>"
|
101
|
-
# HtmlPress.press("<p class = 'a'></p>").should eql "<p class='a'></p>"
|
102
|
-
# HtmlPress.press("<p class = a></p>").should eql "<p class=a></p>"
|
103
|
-
end
|
104
|
-
|
105
|
-
it "should optimize attributes" do
|
106
|
-
HtmlPress.press("<p class=\"a b\"></p>").should eql "<p class=\"a b\"></p>"
|
107
|
-
# http(s):// to //
|
108
|
-
end
|
109
|
-
|
110
|
-
it "should compress css in style attributes" do
|
111
|
-
HtmlPress.press("<p style=\"display: none;\"></p>").should eql "<p style=\"display:none\"></p>"
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
text
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
text
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
HtmlPress.press("<input
|
154
|
-
|
155
|
-
#
|
156
|
-
|
157
|
-
#
|
158
|
-
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
#
|
167
|
-
#
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
HtmlPress.press("
|
176
|
-
HtmlPress.press("
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
HtmlPress.press("
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
HtmlPress.press(
|
188
|
-
text = "<p id=\"a
|
189
|
-
HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
|
190
|
-
text = "<p id
|
191
|
-
HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
|
192
|
-
text = "<p id=\"a\
|
193
|
-
HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
HtmlPress.press(
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("../lib/html_press", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class Lg
|
6
|
+
class << self
|
7
|
+
@warns = []
|
8
|
+
attr_accessor :warns
|
9
|
+
def log text
|
10
|
+
Lg.warns.push text
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe HtmlPress do
|
16
|
+
before :each do
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should leave only one whitespace between inline tags" do
|
20
|
+
HtmlPress.press("<p>lorem <b>ipsum</b> <i>dolor</i> </p>").should eql "<p>lorem <b>ipsum</b> <i>dolor</i></p>"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should leave no whitespaces between block tags" do
|
24
|
+
HtmlPress.press("<div></div> \t\r\n <div></div>").should eql "<div></div><div></div>"
|
25
|
+
HtmlPress.press("<div> <div> \t\r\n </div> </div>").should eql "<div><div></div></div>"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should leave only one whitespace in text" do
|
29
|
+
HtmlPress.press("<p>a a</p>").should eql "<p>a a</p>"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should leave newlines in pre tags and remove trailing spaces" do
|
33
|
+
HtmlPress.press("<pre>a \t </pre>").should eql "<pre>a</pre>"
|
34
|
+
HtmlPress.press("<pre>qwe \nasd </pre>").should eql "<pre>qwe\nasd</pre>"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should leave textareas as is" do
|
38
|
+
text = "<textarea> \t </textarea>"
|
39
|
+
HtmlPress.press(text).should eql text
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should compress js in script tags" do
|
43
|
+
script = " (function(undefined){ \t\n var long_name = ' '; }()) \n \r"
|
44
|
+
pressed_script = "<script>" + HtmlPress.js_compressor(script) + "</script>"
|
45
|
+
script = " <script>" + script + "</script> "
|
46
|
+
HtmlPress.press(script).should eql pressed_script
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should compress css in style tags" do
|
50
|
+
style = " div { margin: 0px 0px; \n} "
|
51
|
+
pressed_style = "<style>" + HtmlPress.style_compressor(style) + "</style>"
|
52
|
+
style = " <style>" + style + "</style> "
|
53
|
+
HtmlPress.press(style).should eql pressed_style
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should remove html comments" do
|
57
|
+
HtmlPress.press("<p></p><!-- comment --><p></p>").should eql "<p></p><p></p>"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should leave IE conditional comments" do
|
61
|
+
text = "<!--[if IE]><html class=\"ie\"><![endif]--><div></div>"
|
62
|
+
HtmlPress.press(text).should eql text
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should work with special utf-8 symbols" do
|
66
|
+
HtmlPress.press("✪<p></p> <p></p>").should eql "✪<p></p><p></p>"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should work with tags in upper case" do
|
70
|
+
HtmlPress.press("<P> </p>").should eql "<P></p>"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should remove whitespaces between IE conditional comments" do
|
74
|
+
text = "<p></p> <!--[if IE]><html class=\"ie\"> <![endif]--> <!--[if IE]><html class=\"ie1\"><![endif]-->"
|
75
|
+
text2 = "<p></p><!--[if IE]><html class=\"ie\"><![endif]--><!--[if IE]><html class=\"ie1\"><![endif]-->"
|
76
|
+
HtmlPress.press(text).should eql text2
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should treat text inside IE conditional comments as it was without comments" do
|
80
|
+
text = "<div class=\"a\" id=\"b\"> </div> <p></p>"
|
81
|
+
text2 = HtmlPress.press(text)
|
82
|
+
text = "<!--[if IE]>" + text + "<![endif]-->"
|
83
|
+
text2 = "<!--[if IE]>" + text2 + "<![endif]-->"
|
84
|
+
HtmlPress.press(text).should eql text2
|
85
|
+
text = "<script> (function(undefined){ var a;}()) </script>"
|
86
|
+
text2 = HtmlPress.press(text)
|
87
|
+
text = "<!--[if IE]>" + text + "<![endif]-->"
|
88
|
+
text2 = "<!--[if IE]>" + text2 + "<![endif]-->"
|
89
|
+
HtmlPress.press(text).should eql text2
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should remove unnecessary whitespaces inside tag" do
|
93
|
+
HtmlPress.press("<p class=\"a\" id=\"b\"></p>").should eql "<p class=\"a\" id=\"b\"></p>"
|
94
|
+
HtmlPress.press("<p class=\"a\" ></p>").should eql "<p class=\"a\"></p>"
|
95
|
+
HtmlPress.press("<img src=\"\" />").should eql "<img src=\"\"/>"
|
96
|
+
HtmlPress.press("<br />").should eql "<br/>"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should work with 'badly' formatted attributes" do
|
100
|
+
HtmlPress.press("<p class='a' id='b'></p>").should eql "<p class='a' id='b'></p>"
|
101
|
+
# HtmlPress.press("<p class = 'a'></p>").should eql "<p class='a'></p>"
|
102
|
+
# HtmlPress.press("<p class = a></p>").should eql "<p class=a></p>"
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should optimize attributes" do
|
106
|
+
HtmlPress.press("<p class=\"a b\"></p>").should eql "<p class=\"a b\"></p>"
|
107
|
+
# http(s):// to //
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should compress css in style attributes" do
|
111
|
+
HtmlPress.press("<p style=\"display: none;\"></p>").should eql "<p style=\"display:none\"></p>"
|
112
|
+
HtmlPress.press("<p style=\"\"></p>").should eql "<p style=\"\"></p>"
|
113
|
+
#FIX those tests can be broken if algorithm of css_press will be changed
|
114
|
+
HtmlPress.press("<p style=\"font-family:Arial ,'Helvetica Neue'\"></p>").should eql "<p style=\"font-family:Arial ,'Helvetica Neue'\"></p>"
|
115
|
+
HtmlPress.press("<p style='font-family:Arial ,\"Helvetica Neue\"'></p>").should eql "<p style='font-family:Arial ,\"Helvetica Neue\"'></p>"
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should work with namespaces" do
|
119
|
+
text = "<html xmlns:og=\"http://ogp.me/ns#\" class=\"a b\"><og:like>like</og:like></html>"
|
120
|
+
HtmlPress.press(text).should eql text
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should not modify input value" do
|
124
|
+
text = "<div> </div>"
|
125
|
+
text1 = text.dup
|
126
|
+
HtmlPress.press(text).should_not eql text
|
127
|
+
text.should eql text1
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should leave whitespaces inside other attributes" do
|
131
|
+
text = "<a onclick=\"alert(' ')\" unknown_attr=' a a'>a</a>"
|
132
|
+
HtmlPress.press(text).should eql text
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should report javascript errors" do
|
136
|
+
["<script>function(){</script>", "<a onclick=\"return false\"></a>"].each do |script_with_error|
|
137
|
+
Lg.warns = []
|
138
|
+
HtmlPress.press(script_with_error, {:logger => Lg.method(:log)}).should eql script_with_error
|
139
|
+
Lg.warns.size.should eql 1
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should report css errors" do
|
144
|
+
["<style>.clas{margin:</style>", "<a style=\"#asd\">link</a>"].each do |style_with_error|
|
145
|
+
Lg.warns = []
|
146
|
+
HtmlPress.press(style_with_error, {:logger => Lg.method(:log)}).should eql style_with_error
|
147
|
+
Lg.warns.size.should eql 1
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should remove values of boolean attributes" do
|
152
|
+
HtmlPress.press("<option selected=\"selected\">a</option>").should eql "<option selected>a</option>"
|
153
|
+
HtmlPress.press("<input type=\"checkbox\" checked=\"checked\"/>").should eql "<input type=\"checkbox\" checked/>"
|
154
|
+
HtmlPress.press("<input type=\"radio\" checked=\"checked\"/>").should eql "<input type=\"radio\" checked/>"
|
155
|
+
# disabled (input, textarea, button, select, option, optgroup)
|
156
|
+
HtmlPress.press("<input disabled=\"disabled\"/>").should eql "<input disabled/>"
|
157
|
+
# readonly (input type=text/password, textarea)
|
158
|
+
HtmlPress.press("<input readonly=\"readonly\"/>").should eql "<input readonly/>"
|
159
|
+
# HtmlPress.press("<script src=\"example.com\" async=\"async\"></script>").should eql "<script src=\"example.com\" async></script>"
|
160
|
+
# HtmlPress.press("<script src=\"example.com\" defer=\"defer\"></script>").should eql "<script src=\"example.com\" async></script>"
|
161
|
+
# HtmlPress.press("<select multiple=\"multiple\"/>").should eql "<select multiple/>"
|
162
|
+
# ismap isMap (img, input type=image)
|
163
|
+
# declare (object; never used)
|
164
|
+
# noresize noResize (frame)
|
165
|
+
# nowrap noWrap (td, th; deprecated)
|
166
|
+
# noshade noShade (hr; deprecated)
|
167
|
+
# compact (ul, ol, dl, menu, dir; deprecated)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should remove attributes with default values" do
|
171
|
+
HtmlPress.press("<script type=\"text/javascript\" language=\"JavaScript\">var a</script>").should eql "<script>var a</script>"
|
172
|
+
HtmlPress.press("<style type=\"text/stylesheet\"></style>").should eql "<style></style>"
|
173
|
+
HtmlPress.press("<link type=\"text/stylesheet\"/>").should eql "<link/>"
|
174
|
+
HtmlPress.press("<link rel=\"alternate\" type=\"application/rss+xml\"/>").should eql "<link rel=\"alternate\" type=\"application/rss+xml\"/>"
|
175
|
+
HtmlPress.press("<form method=\"get\"></form>").should eql "<form></form>"
|
176
|
+
HtmlPress.press("<input type=\"text\"/>").should eql "<input/>"
|
177
|
+
# input value "" ?
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should convert html entities to utf-8 symbols" do
|
181
|
+
HtmlPress.press("< < > > & &").should eql "< < > > & &"
|
182
|
+
HtmlPress.press("élan").should eql "élan"
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should remove unnecessary quotes for attribute values" do
|
186
|
+
HtmlPress.press("<img src=\"\">", {:unquoted_attributes => true}).should eql "<img src=\"\">"
|
187
|
+
HtmlPress.press("<p id=\"a\"></p>", {:unquoted_attributes => true}).should eql "<p id=a></p>"
|
188
|
+
text = "<p id=\"a b\"></p>"
|
189
|
+
HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
|
190
|
+
text = "<p id=\"a=\"></p>"
|
191
|
+
HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
|
192
|
+
text = "<p id=\"a'\"></p>"
|
193
|
+
HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
|
194
|
+
text = "<p id=\"a`\"></p>"
|
195
|
+
HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
|
196
|
+
text = "<p id='a\"'></p>"
|
197
|
+
HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
|
198
|
+
text = "<p id=\"a\t\"></p>"
|
199
|
+
HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should remove empty attribute values" do
|
203
|
+
HtmlPress.press("<img src=\"\">", {:drop_empty_values => true}).should eql "<img src>"
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should compress javascript in event attributes" do
|
207
|
+
%w[onfocus onblur onselect onchange onclick
|
208
|
+
ondblclick onmousedown onmouseup onmouseover onmousemove
|
209
|
+
onmouseout onkeypress onkeydown onkeyup
|
210
|
+
].each do |evt|
|
211
|
+
HtmlPress.press("<a #{evt}=\"javacript: alert(' ');\"></a>").should eql "<a #{evt}=\"alert(' ')\"></a>"
|
212
|
+
HtmlPress.press("<a #{evt}=\"\"></a>").should eql "<a #{evt}=\"\"></a>"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# it "should concatenate adjecent script and style tags" do
|
217
|
+
# all stylle tags can be collected, concatneated and placed in header
|
218
|
+
# end
|
219
|
+
|
218
220
|
end
|
metadata
CHANGED
@@ -1,78 +1,105 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: html_press
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 6
|
9
|
+
- 6
|
10
|
+
version: 0.6.6
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- stereobooster
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
+
|
18
|
+
date: 2012-08-07 00:00:00 +03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
type: :development
|
23
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
requirement: *id001
|
33
|
+
prerelease: false
|
34
|
+
name: rspec
|
35
|
+
- !ruby/object:Gem::Dependency
|
22
36
|
type: :development
|
37
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
requirement: *id002
|
23
47
|
prerelease: false
|
24
|
-
version_requirements: *28618932
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
48
|
name: rake
|
27
|
-
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
28
52
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
33
|
-
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 23
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
- 3
|
60
|
+
- 2
|
61
|
+
version: 0.3.2
|
62
|
+
requirement: *id003
|
34
63
|
prerelease: false
|
35
|
-
version_requirements: *28618680
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
64
|
name: css_press
|
38
|
-
|
39
|
-
none: false
|
40
|
-
requirements:
|
41
|
-
- - ! '>='
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: 0.3.1
|
65
|
+
- !ruby/object:Gem::Dependency
|
44
66
|
type: :runtime
|
67
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
requirement: *id004
|
45
77
|
prerelease: false
|
46
|
-
version_requirements: *28618380
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
78
|
name: uglifier
|
49
|
-
|
50
|
-
none: false
|
51
|
-
requirements:
|
52
|
-
- - ! '>='
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
79
|
+
- !ruby/object:Gem::Dependency
|
55
80
|
type: :runtime
|
56
|
-
|
57
|
-
version_requirements: *28618128
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: htmlentities
|
60
|
-
requirement: &28617852 !ruby/object:Gem::Requirement
|
81
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
61
82
|
none: false
|
62
|
-
requirements:
|
63
|
-
- -
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
|
66
|
-
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
hash: 3
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
requirement: *id005
|
67
91
|
prerelease: false
|
68
|
-
|
92
|
+
name: htmlentities
|
69
93
|
description: Ruby gem for compressing html
|
70
|
-
email:
|
94
|
+
email:
|
71
95
|
- stereobooster@gmail.com
|
72
96
|
executables: []
|
97
|
+
|
73
98
|
extensions: []
|
99
|
+
|
74
100
|
extra_rdoc_files: []
|
75
|
-
|
101
|
+
|
102
|
+
files:
|
76
103
|
- .gitignore
|
77
104
|
- .travis.yml
|
78
105
|
- Gemfile
|
@@ -86,34 +113,39 @@ files:
|
|
86
113
|
- lib/html_press/uglifier.rb
|
87
114
|
- lib/html_press/version.rb
|
88
115
|
- spec/html_press_spec.rb
|
116
|
+
has_rdoc: true
|
89
117
|
homepage: https://github.com/stereobooster/html_press
|
90
118
|
licenses: []
|
119
|
+
|
91
120
|
post_install_message:
|
92
121
|
rdoc_options: []
|
93
|
-
|
122
|
+
|
123
|
+
require_paths:
|
94
124
|
- lib
|
95
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
126
|
none: false
|
97
|
-
requirements:
|
98
|
-
- -
|
99
|
-
- !ruby/object:Gem::Version
|
100
|
-
|
101
|
-
segments:
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
hash: 3
|
131
|
+
segments:
|
102
132
|
- 0
|
103
|
-
|
104
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
version: "0"
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
135
|
none: false
|
106
|
-
requirements:
|
107
|
-
- -
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
|
110
|
-
segments:
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
hash: 3
|
140
|
+
segments:
|
111
141
|
- 0
|
112
|
-
|
142
|
+
version: "0"
|
113
143
|
requirements: []
|
144
|
+
|
114
145
|
rubyforge_project: html_press
|
115
|
-
rubygems_version: 1.
|
146
|
+
rubygems_version: 1.5.2
|
116
147
|
signing_key:
|
117
148
|
specification_version: 3
|
118
149
|
summary: Compress html
|
119
150
|
test_files: []
|
151
|
+
|