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 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
+