html_press 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme.md +44 -19
- data/lib/html_press/html.rb +49 -11
- data/lib/html_press/version.rb +1 -1
- data/spec/html_press_spec.rb +83 -16
- metadata +10 -10
data/Readme.md
CHANGED
@@ -1,23 +1,14 @@
|
|
1
1
|
#html_press
|
2
2
|
|
3
|
-
##
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
- https://github.com/completelynovel/html_compressor
|
8
|
-
- https://github.com/MadRabbit/frontcompiler
|
9
|
-
|
10
|
-
###Other
|
11
|
-
|
12
|
-
- http://code.google.com/p/htmlcompressor/
|
13
|
-
- smarty `strip` tag
|
14
|
-
- W3 total cache (WP plugin from smashingmagazine contains html minifier)
|
3
|
+
## how it works
|
4
|
+
|
5
|
+
Remove all whitespace junk. Leave only HTML
|
15
6
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
7
|
+
```
|
8
|
+
1. ┌――――――――――――――――――╖ 2. ┌――――――――――――――――――╖
|
9
|
+
●――――――――――――――├―╢ <html> ws junk ║ ●――――――――├―――――――――╢ <html> ║
|
10
|
+
└――――――――――――――――――╜ └――――――――――――――――――╜
|
11
|
+
```
|
21
12
|
|
22
13
|
## Usage
|
23
14
|
|
@@ -35,11 +26,23 @@ _plugins/strip_tag.rb
|
|
35
26
|
```ruby
|
36
27
|
module Jekyll
|
37
28
|
class StripTag < Liquid::Block
|
29
|
+
@total_economy = 0
|
30
|
+
class << self
|
31
|
+
attr_accessor :total_economy
|
32
|
+
end
|
33
|
+
|
38
34
|
begin
|
39
35
|
require 'html_press'
|
40
36
|
def render(context)
|
41
37
|
text = super
|
42
|
-
|
38
|
+
before = text.bytesize
|
39
|
+
text = HtmlPress.compress text
|
40
|
+
after = text.bytesize
|
41
|
+
|
42
|
+
self.class.total_economy += before - after
|
43
|
+
economy = (self.class.total_economy.to_f / 1024).round(2)
|
44
|
+
p 'totally saved: ' + economy.to_s + ' Kb'
|
45
|
+
text
|
43
46
|
end
|
44
47
|
rescue LoadError => e
|
45
48
|
p "Unable to load 'html_press'"
|
@@ -62,5 +65,27 @@ Run
|
|
62
65
|
|
63
66
|
```
|
64
67
|
bundle install
|
65
|
-
bundle exec
|
68
|
+
bundle exec jekyll
|
66
69
|
```
|
70
|
+
|
71
|
+
## Alternatives
|
72
|
+
|
73
|
+
###Ruby
|
74
|
+
|
75
|
+
- https://github.com/completelynovel/html_compressor
|
76
|
+
- https://github.com/MadRabbit/frontcompiler
|
77
|
+
|
78
|
+
###Other
|
79
|
+
|
80
|
+
- http://code.google.com/p/htmlcompressor/
|
81
|
+
- smarty `strip` tag
|
82
|
+
- W3 total cache (WP plugin from smashingmagazine contains html minifier)
|
83
|
+
|
84
|
+
## TODO
|
85
|
+
|
86
|
+
- options
|
87
|
+
- bin
|
88
|
+
- Support other minifiers (Closure, YUI compressor)
|
89
|
+
- htmlTydi
|
90
|
+
- add examples of usage with Sinatra and Rails
|
91
|
+
|
data/lib/html_press/html.rb
CHANGED
@@ -138,6 +138,11 @@ module HtmlPress
|
|
138
138
|
attr k, "'", tag
|
139
139
|
end
|
140
140
|
|
141
|
+
if attributes_compressed == " /"
|
142
|
+
attributes_compressed = "/"
|
143
|
+
elsif attributes_compressed == " "
|
144
|
+
attributes_compressed = ""
|
145
|
+
end
|
141
146
|
return m.gsub(attributes, attributes_compressed)
|
142
147
|
end
|
143
148
|
|
@@ -147,37 +152,70 @@ module HtmlPress
|
|
147
152
|
def attr(attribute, delimiter, tag)
|
148
153
|
re = "([a-z\\-_:]+)(=" + delimiter + "[^" + delimiter + "]*" + delimiter + ")?"
|
149
154
|
re = Regexp.new re
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
155
|
+
value_original = attribute.gsub(re, "\\2")
|
156
|
+
value = value_original.downcase
|
157
|
+
name_original = attribute.gsub(re, "\\1")
|
158
|
+
name = name_original.downcase
|
159
|
+
tag_name = tag.downcase
|
160
|
+
|
161
|
+
case tag_name
|
162
|
+
when "script"
|
154
163
|
if name == "type" || name == "language"
|
155
164
|
return ""
|
165
|
+
elsif name == "async" || name == "defer"
|
166
|
+
return name_original
|
167
|
+
end
|
168
|
+
when "form"
|
169
|
+
if name == "method" && (value == "=\"get\"" || value == "='get'")
|
170
|
+
return ""
|
171
|
+
end
|
172
|
+
when /link|style/
|
173
|
+
if name == "type"
|
174
|
+
return ""
|
175
|
+
end
|
176
|
+
when /input|textarea|button|select|option|optgroup/
|
177
|
+
if name == "disabled"
|
178
|
+
return name_original
|
179
|
+
end
|
180
|
+
if (tag_name == "input" || tag_name == "textarea") && name == "readonly"
|
181
|
+
return name_original
|
182
|
+
end
|
183
|
+
if tag_name == "option" && name == "selected"
|
184
|
+
return name_original
|
185
|
+
end
|
186
|
+
if tag_name == "input"
|
187
|
+
if name == "type" && (value == "=\"text\"" || value == "='text'")
|
188
|
+
return ""
|
189
|
+
end
|
190
|
+
if name == "checked"
|
191
|
+
return name_original
|
192
|
+
end
|
193
|
+
# if name == "value" && (value == "=\"\"" || value == "=''")
|
194
|
+
# return ''
|
195
|
+
# end
|
156
196
|
end
|
157
197
|
end
|
158
198
|
|
159
199
|
if value.size != 0
|
160
200
|
|
161
|
-
name = attribute.gsub(re, "\\1")
|
162
|
-
|
163
201
|
re = "^=" + delimiter + "|" + delimiter + "$"
|
164
202
|
re = Regexp.new re
|
165
|
-
|
203
|
+
value_original.gsub!(re, "")
|
166
204
|
|
167
205
|
if name == "style"
|
168
|
-
|
206
|
+
value_original = HtmlPress.css_compressor value_original
|
169
207
|
end
|
170
208
|
|
171
209
|
if name == "class"
|
172
|
-
|
173
|
-
|
210
|
+
value_original.gsub!(/\s+/, " ")
|
211
|
+
value_original.gsub!(/^\s+|\s+$/, "")
|
174
212
|
end
|
175
213
|
|
176
214
|
# if name == "onclick"
|
177
215
|
# value = HtmlPress.js_compressor value
|
178
216
|
# end
|
179
217
|
|
180
|
-
attribute =
|
218
|
+
attribute = name_original + "=" + delimiter + value_original + delimiter
|
181
219
|
end
|
182
220
|
|
183
221
|
attribute
|
data/lib/html_press/version.rb
CHANGED
data/spec/html_press_spec.rb
CHANGED
@@ -62,15 +62,6 @@ describe HtmlPress do
|
|
62
62
|
HtmlPress.compress(text).should eql text
|
63
63
|
end
|
64
64
|
|
65
|
-
it "should remove unnecessary whitespaces between attributes" do
|
66
|
-
HtmlPress.compress("<p class=\"a\" id=\"b\"></p>").should eql "<p class=\"a\" id=\"b\"></p>"
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should leave whitespaces everywhere else" do
|
70
|
-
text = "<a onclick=\"alert(' ')\" unknown_attr=' a a'>a</a>"
|
71
|
-
HtmlPress.compress(text).should eql text
|
72
|
-
end
|
73
|
-
|
74
65
|
it "should work with special utf-8 symbols" do
|
75
66
|
HtmlPress.compress("✪<p></p> <p></p>").should eql "✪<p></p><p></p>"
|
76
67
|
end
|
@@ -98,12 +89,25 @@ describe HtmlPress do
|
|
98
89
|
HtmlPress.compress(text).should eql text2
|
99
90
|
end
|
100
91
|
|
101
|
-
it "should remove unnecessary whitespaces
|
92
|
+
it "should remove unnecessary whitespaces inside tag" do
|
93
|
+
HtmlPress.compress("<p class=\"a\" id=\"b\"></p>").should eql "<p class=\"a\" id=\"b\"></p>"
|
94
|
+
HtmlPress.compress("<p class=\"a\" ></p>").should eql "<p class=\"a\"></p>"
|
95
|
+
HtmlPress.compress("<img src=\"\" />").should eql "<img src=\"\"/>"
|
96
|
+
HtmlPress.compress("<br />").should eql "<br/>"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should work with 'badly' formatted attributes" do
|
100
|
+
HtmlPress.compress("<p class='a' id='b'></p>").should eql "<p class='a' id='b'></p>"
|
101
|
+
# HtmlPress.compress("<p class = 'a'></p>").should eql "<p class='a'></p>"
|
102
|
+
# HtmlPress.compress("<p class = a></p>").should eql "<p class=a></p>"
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should optimize attributes" do
|
102
106
|
HtmlPress.compress("<p class=\"a b\"></p>").should eql "<p class=\"a b\"></p>"
|
103
|
-
|
107
|
+
# http(s):// to //
|
104
108
|
end
|
105
109
|
|
106
|
-
it "should
|
110
|
+
it "should compress css in style attributes" do
|
107
111
|
HtmlPress.compress("<p style=\"display: none;\"></p>").should eql "<p style=\"display:none;\"></p>"
|
108
112
|
end
|
109
113
|
|
@@ -118,16 +122,79 @@ describe HtmlPress do
|
|
118
122
|
HtmlPress.compress(text)
|
119
123
|
text.should eql text1
|
120
124
|
end
|
121
|
-
|
122
|
-
it "should
|
125
|
+
|
126
|
+
it "should leave whitespaces inside other attributes" do
|
127
|
+
text = "<a onclick=\"alert(' ')\" unknown_attr=' a a'>a</a>"
|
128
|
+
HtmlPress.compress(text).should eql text
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should report javascript errors" do
|
123
132
|
script_with_error = "<script>function(){</script>"
|
124
133
|
l = Lg.new
|
125
134
|
l.warns.size.should eql 0
|
126
135
|
HtmlPress.compress(script_with_error, {:logger => l}).should eql script_with_error
|
127
136
|
l.warns.size.should eql 1
|
128
137
|
end
|
129
|
-
|
130
|
-
|
138
|
+
|
139
|
+
# it "should report css errors" do
|
140
|
+
# script_with_error = "<style>.clas{margin:</style>"
|
141
|
+
# l = Lg.new
|
142
|
+
# l.warns.size.should eql 0
|
143
|
+
# HtmlPress.compress(script_with_error, {:logger => l}).should eql script_with_error
|
144
|
+
# l.warns.size.should eql 1
|
145
|
+
# end
|
146
|
+
|
147
|
+
it "should remove values of boolean attributes" do
|
148
|
+
HtmlPress.compress("<option selected=\"selected\">a</option>").should eql "<option selected>a</option>"
|
149
|
+
HtmlPress.compress("<input type=\"checkbox\" checked=\"checked\"/>").should eql "<input type=\"checkbox\" checked/>"
|
150
|
+
HtmlPress.compress("<input type=\"radio\" checked=\"checked\"/>").should eql "<input type=\"radio\" checked/>"
|
151
|
+
# disabled (input, textarea, button, select, option, optgroup)
|
152
|
+
HtmlPress.compress("<input disabled=\"disabled\"/>").should eql "<input disabled/>"
|
153
|
+
# readonly (input type=text/password, textarea)
|
154
|
+
HtmlPress.compress("<input readonly=\"readonly\"/>").should eql "<input readonly/>"
|
155
|
+
# HtmlPress.compress("<script src=\"example.com\" async=\"async\"></script>").should eql "<script src=\"example.com\" async></script>"
|
156
|
+
# HtmlPress.compress("<script src=\"example.com\" defer=\"defer\"></script>").should eql "<script src=\"example.com\" async></script>"
|
157
|
+
# HtmlPress.compress("<select multiple=\"multiple\"/>").should eql "<select multiple/>"
|
158
|
+
# ismap isMap (img, input type=image)
|
159
|
+
# declare (object; never used)
|
160
|
+
# noresize noResize (frame)
|
161
|
+
# nowrap noWrap (td, th; deprecated)
|
162
|
+
# noshade noShade (hr; deprecated)
|
163
|
+
# compact (ul, ol, dl, menu, dir; deprecated)
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should remove attributes with default values" do
|
167
|
+
# HtmlPress.compress("<script type=\"text/javascript\" language=\"JavaScript\">var a;</script>").should eql "<script>var a;</script>"
|
168
|
+
# HtmlPress.compress("<style type=\"text/stylesheet\"></style>").should eql "<style></style>"
|
169
|
+
HtmlPress.compress("<link type=\"text/stylesheet\"/>").should eql "<link/>"
|
170
|
+
HtmlPress.compress("<form method=\"get\"></form>").should eql "<form></form>"
|
171
|
+
HtmlPress.compress("<input type=\"text\"/>").should eql "<input/>"
|
172
|
+
# input value "" ?
|
173
|
+
end
|
174
|
+
|
175
|
+
# it "should compress javascript in event attributes" do
|
176
|
+
# # javascript: - remove
|
177
|
+
# # onfocus
|
178
|
+
# # onblur
|
179
|
+
# # onselect
|
180
|
+
# # onchange
|
181
|
+
# # onclick
|
182
|
+
# # ondblclick
|
183
|
+
# # onmousedown
|
184
|
+
# # onmouseup
|
185
|
+
# # onmouseover
|
186
|
+
# # onmousemove
|
187
|
+
# # onmouseout
|
188
|
+
# # onkeypress
|
189
|
+
# # onkeydown
|
190
|
+
# # onkeyup
|
191
|
+
# end
|
192
|
+
#
|
193
|
+
# it "should remove unnecessary quotes for attributes values" do
|
194
|
+
# end
|
195
|
+
#
|
196
|
+
# it "should convert html entities to utf-8 symbols" do
|
197
|
+
# # except <>&
|
131
198
|
# end
|
132
199
|
|
133
200
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: html_press
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-05 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &26078568 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *26078568
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &26078208 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *26078208
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rainpress
|
38
|
-
requirement: &
|
38
|
+
requirement: &26077776 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *26077776
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: uglifier
|
49
|
-
requirement: &
|
49
|
+
requirement: &26077452 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *26077452
|
58
58
|
description: Ruby gem for compressing html
|
59
59
|
email:
|
60
60
|
- stereobooster@gmail.com
|