html_press 0.6.5 → 0.6.6
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.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
|
+
|