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 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
- - bin
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
- ###Ruby
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
- - https://github.com/completelynovel/html_compressor
97
- - https://github.com/MadRabbit/frontcompiler
90
+ ## Additional tools
98
91
 
99
- ###Other
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
- - http://code.google.com/p/htmlcompressor/
102
- - smarty `strip` tag
103
- - W3 total cache (WP plugin from smashingmagazine contains html minifier)
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.1"
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
@@ -4,7 +4,7 @@ module HtmlPress
4
4
  def self.css_compressor (text)
5
5
  text = "a{#{text}}"
6
6
  text = CssPress.press text
7
- text.gsub(/^a\{/, '').gsub!(/\}$/, '')
7
+ text.gsub(/^a\{/, '').gsub(/\}$/, '')
8
8
  end
9
9
  def self.style_compressor (text)
10
10
  CssPress.press text
@@ -4,11 +4,15 @@ module HtmlPress
4
4
  DEFAULTS = {
5
5
  :logger => false,
6
6
  :unquoted_attributes => false,
7
- :dump_empty_values => false
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
- js = m.gsub(/\s*<script\b[^>]*?>([\s\S]*?)<\/script>\s*/i , "\\1")
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
- css = m.gsub(/\s*<style\b[^>]*?>([\s\S]*?)<\/style>\s*/i, "\\1")
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
- return m.gsub(attributes, attributes_compressed)
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" && (value == "=\"get\"" || value == "='get'")
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" && (value == "=\"text\"" || value == "='text'")
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 != 0
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
- value_original = HtmlPress.css_compressor value_original
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
- value_original = HtmlPress.js_compressor value_original
233
- if delimiter == "\""
234
- value_original.gsub! "\"", "'"
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[:dump_empty_values]
269
+ if @options[:drop_empty_values]
241
270
  attribute = name_original
242
271
  else
243
272
  attribute = name_original + "=" + delimiter + delimiter
@@ -1,3 +1,3 @@
1
1
  module HtmlPress
2
- VERSION = "0.6.5"
2
+ VERSION = "0.6.6"
3
3
  end
@@ -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
- end
113
-
114
- it "should work with namespaces" do
115
- text = "<html xmlns:og=\"http://ogp.me/ns#\" class=\"a b\"><og:like>like</og:like></html>"
116
- HtmlPress.press(text).should eql text
117
- end
118
-
119
- it "should not modify input value" do
120
- text = "<div> </div>"
121
- text1 = text.dup
122
- HtmlPress.press(text).should_not eql text
123
- text.should eql text1
124
- end
125
-
126
- it "should leave whitespaces inside other attributes" do
127
- text = "<a onclick=\"alert(' ')\" unknown_attr=' a a'>a</a>"
128
- HtmlPress.press(text).should eql text
129
- end
130
-
131
- it "should report javascript errors" do
132
- script_with_error = "<script>function(){</script>"
133
- Lg.warns = []
134
- HtmlPress.press(script_with_error, {:logger => Lg.method(:log)}).should eql script_with_error
135
- Lg.warns.size.should eql 1
136
- end
137
-
138
- # it "should report css errors" do
139
- # script_with_error = "<style>.clas{margin:</style>"
140
- # l = Lg.new
141
- # l.warns.size.should eql 0
142
- # HtmlPress.press(script_with_error, {:logger => l}).should eql script_with_error
143
- # l.warns.size.should eql 1
144
- # end
145
-
146
- it "should remove values of boolean attributes" do
147
- HtmlPress.press("<option selected=\"selected\">a</option>").should eql "<option selected>a</option>"
148
- HtmlPress.press("<input type=\"checkbox\" checked=\"checked\"/>").should eql "<input type=\"checkbox\" checked/>"
149
- HtmlPress.press("<input type=\"radio\" checked=\"checked\"/>").should eql "<input type=\"radio\" checked/>"
150
- # disabled (input, textarea, button, select, option, optgroup)
151
- HtmlPress.press("<input disabled=\"disabled\"/>").should eql "<input disabled/>"
152
- # readonly (input type=text/password, textarea)
153
- HtmlPress.press("<input readonly=\"readonly\"/>").should eql "<input readonly/>"
154
- # HtmlPress.press("<script src=\"example.com\" async=\"async\"></script>").should eql "<script src=\"example.com\" async></script>"
155
- # HtmlPress.press("<script src=\"example.com\" defer=\"defer\"></script>").should eql "<script src=\"example.com\" async></script>"
156
- # HtmlPress.press("<select multiple=\"multiple\"/>").should eql "<select multiple/>"
157
- # ismap isMap (img, input type=image)
158
- # declare (object; never used)
159
- # noresize noResize (frame)
160
- # nowrap noWrap (td, th; deprecated)
161
- # noshade noShade (hr; deprecated)
162
- # compact (ul, ol, dl, menu, dir; deprecated)
163
- end
164
-
165
- it "should remove attributes with default values" do
166
- # HtmlPress.press("<script type=\"text/javascript\" language=\"JavaScript\">var a;</script>").should eql "<script>var a;</script>"
167
- # HtmlPress.press("<style type=\"text/stylesheet\"></style>").should eql "<style></style>"
168
- HtmlPress.press("<link type=\"text/stylesheet\"/>").should eql "<link/>"
169
- HtmlPress.press("<form method=\"get\"></form>").should eql "<form></form>"
170
- HtmlPress.press("<input type=\"text\"/>").should eql "<input/>"
171
- # input value "" ?
172
- end
173
-
174
- it "should convert html entities to utf-8 symbols" do
175
- HtmlPress.press("&lt; &#60; &gt; &#62; &amp; &#38;").should eql "&lt; &#60; &gt; &#62; &amp; &#38;"
176
- HtmlPress.press("&eacute;lan").should eql "élan"
177
- end
178
-
179
- it "should remove unnecessary quotes for attribute values" do
180
- HtmlPress.press("<img src=\"\">", {:unquoted_attributes => true}).should eql "<img src=\"\">"
181
- HtmlPress.press("<p id=\"a\"></p>", {:unquoted_attributes => true}).should eql "<p id=a></p>"
182
- text = "<p id=\"a b\"></p>"
183
- HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
184
- text = "<p id=\"a=\"></p>"
185
- HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
186
- text = "<p id=\"a'\"></p>"
187
- HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
188
- text = "<p id=\"a`\"></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\t\"></p>"
193
- HtmlPress.press(text, {:unquoted_attributes => true}).should eql text
194
- end
195
-
196
- it "should remove empty attribute values" do
197
- HtmlPress.press("<img src=\"\">", {:dump_empty_values => true}).should eql "<img src>"
198
- end
199
-
200
- it "should compress javascript in event attributes" do
201
- HtmlPress.press("<a onclick=\"javacript: alert(' ');\"></a>").should eql "<a onclick=\"alert(' ')\"></a>"
202
- # onfocus
203
- # onblur
204
- # onselect
205
- # onchange
206
- # onclick
207
- # ondblclick
208
- # onmousedown
209
- # onmouseup
210
- # onmouseover
211
- # onmousemove
212
- # onmouseout
213
- # onkeypress
214
- # onkeydown
215
- # onkeyup
216
- end
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("&lt; &#60; &gt; &#62; &amp; &#38;").should eql "&lt; &#60; &gt; &#62; &amp; &#38;"
182
+ HtmlPress.press("&eacute;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
- version: 0.6.5
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
- date: 2012-04-28 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: rspec
16
- requirement: &28618932 !ruby/object:Gem::Requirement
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
- version: '0'
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
- requirement: &28618680 !ruby/object:Gem::Requirement
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
- version: '0'
33
- type: :development
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
- requirement: &28618380 !ruby/object:Gem::Requirement
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
- requirement: &28618128 !ruby/object:Gem::Requirement
50
- none: false
51
- requirements:
52
- - - ! '>='
53
- - !ruby/object:Gem::Version
54
- version: '0'
79
+ - !ruby/object:Gem::Dependency
55
80
  type: :runtime
56
- prerelease: false
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
- version: '0'
66
- type: :runtime
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
- version_requirements: *28617852
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
- files:
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
- require_paths:
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
- version: '0'
101
- segments:
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ hash: 3
131
+ segments:
102
132
  - 0
103
- hash: -910783917
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
- version: '0'
110
- segments:
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ hash: 3
140
+ segments:
111
141
  - 0
112
- hash: -910783917
142
+ version: "0"
113
143
  requirements: []
144
+
114
145
  rubyforge_project: html_press
115
- rubygems_version: 1.8.15
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
+