cssminify2 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGES.md +17 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.md +23 -0
  7. data/README.md +71 -0
  8. data/cssminify2.gemspec +31 -0
  9. data/lib/cssminify2.rb +34 -0
  10. data/lib/cssminify2/cssmin.rb +394 -0
  11. data/lib/cssminify2/version.rb +5 -0
  12. data/spec/cssminify_spec.rb +321 -0
  13. data/spec/sample.css +141 -0
  14. data/spec/spec_helper.rb +4 -0
  15. data/spec/tests/background-position.css +2 -0
  16. data/spec/tests/background-position.css.min +1 -0
  17. data/spec/tests/border-none.css +5 -0
  18. data/spec/tests/border-none.css.min +1 -0
  19. data/spec/tests/box-model-hack.css +9 -0
  20. data/spec/tests/box-model-hack.css.min +1 -0
  21. data/spec/tests/bug2527974.css +10 -0
  22. data/spec/tests/bug2527974.css.min +1 -0
  23. data/spec/tests/bug2527991.css +19 -0
  24. data/spec/tests/bug2527991.css.min +1 -0
  25. data/spec/tests/bug2527998.css +4 -0
  26. data/spec/tests/bug2527998.css.min +1 -0
  27. data/spec/tests/bug2528034.css +5 -0
  28. data/spec/tests/bug2528034.css.min +1 -0
  29. data/spec/tests/bug2528093.css +3 -0
  30. data/spec/tests/bug2528093.css.min +1 -0
  31. data/spec/tests/charset-media.css +9 -0
  32. data/spec/tests/charset-media.css.min +1 -0
  33. data/spec/tests/color-simple.css +8 -0
  34. data/spec/tests/color-simple.css.min +1 -0
  35. data/spec/tests/color.css +46 -0
  36. data/spec/tests/color.css.min +1 -0
  37. data/spec/tests/comment.css +3 -0
  38. data/spec/tests/comment.css.min +1 -0
  39. data/spec/tests/concat-charset.css +15 -0
  40. data/spec/tests/concat-charset.css.min +1 -0
  41. data/spec/tests/dataurl-base64-doublequotes.css +23 -0
  42. data/spec/tests/dataurl-base64-doublequotes.css.min +1 -0
  43. data/spec/tests/dataurl-base64-eof.css +10 -0
  44. data/spec/tests/dataurl-base64-eof.css.min +1 -0
  45. data/spec/tests/dataurl-base64-linebreakindata.css +34 -0
  46. data/spec/tests/dataurl-base64-linebreakindata.css.min +1 -0
  47. data/spec/tests/dataurl-base64-noquotes.css +26 -0
  48. data/spec/tests/dataurl-base64-noquotes.css.min +1 -0
  49. data/spec/tests/dataurl-base64-singlequotes.css +23 -0
  50. data/spec/tests/dataurl-base64-singlequotes.css.min +1 -0
  51. data/spec/tests/dataurl-base64-twourls.css +27 -0
  52. data/spec/tests/dataurl-base64-twourls.css.min +1 -0
  53. data/spec/tests/dataurl-dbquote-font.css +30 -0
  54. data/spec/tests/dataurl-dbquote-font.css.min +5 -0
  55. data/spec/tests/dataurl-nonbase64-doublequotes.css +13 -0
  56. data/spec/tests/dataurl-nonbase64-doublequotes.css.min +1 -0
  57. data/spec/tests/dataurl-nonbase64-noquotes.css +11 -0
  58. data/spec/tests/dataurl-nonbase64-noquotes.css.min +1 -0
  59. data/spec/tests/dataurl-nonbase64-singlequotes.css +15 -0
  60. data/spec/tests/dataurl-nonbase64-singlequotes.css.min +2 -0
  61. data/spec/tests/dataurl-noquote-multiline-font.css +31 -0
  62. data/spec/tests/dataurl-noquote-multiline-font.css.min +3 -0
  63. data/spec/tests/dataurl-realdata-doublequotes.css +90 -0
  64. data/spec/tests/dataurl-realdata-doublequotes.css.min +1 -0
  65. data/spec/tests/dataurl-realdata-noquotes.css +90 -0
  66. data/spec/tests/dataurl-realdata-noquotes.css.min +1 -0
  67. data/spec/tests/dataurl-realdata-singlequotes.css +90 -0
  68. data/spec/tests/dataurl-realdata-singlequotes.css.min +1 -0
  69. data/spec/tests/dataurl-realdata-yuiapp.css +106 -0
  70. data/spec/tests/dataurl-realdata-yuiapp.css.min +1 -0
  71. data/spec/tests/dataurl-singlequote-font.css +30 -0
  72. data/spec/tests/dataurl-singlequote-font.css.min +3 -0
  73. data/spec/tests/decimals.css +3 -0
  74. data/spec/tests/decimals.css.min +1 -0
  75. data/spec/tests/dollar-header.css +7 -0
  76. data/spec/tests/dollar-header.css.min +3 -0
  77. data/spec/tests/font-face.css +6 -0
  78. data/spec/tests/font-face.css.min +1 -0
  79. data/spec/tests/ie5mac.css +5 -0
  80. data/spec/tests/ie5mac.css.min +1 -0
  81. data/spec/tests/issue221.css +7 -0
  82. data/spec/tests/issue221.css.min +1 -0
  83. data/spec/tests/issue222.css +3 -0
  84. data/spec/tests/issue222.css.min +1 -0
  85. data/spec/tests/keyframe.css +4 -0
  86. data/spec/tests/keyframe.css.min +1 -0
  87. data/spec/tests/media-empty-class.css +16 -0
  88. data/spec/tests/media-empty-class.css.min +1 -0
  89. data/spec/tests/media-multi.css +3 -0
  90. data/spec/tests/media-multi.css.min +1 -0
  91. data/spec/tests/media-test.css +3 -0
  92. data/spec/tests/media-test.css.min +1 -0
  93. data/spec/tests/opacity-filter.css +14 -0
  94. data/spec/tests/opacity-filter.css.min +1 -0
  95. data/spec/tests/preserve-case.css +15 -0
  96. data/spec/tests/preserve-case.css.min +1 -0
  97. data/spec/tests/preserve-new-line.css +6 -0
  98. data/spec/tests/preserve-new-line.css.min +3 -0
  99. data/spec/tests/preserve-strings.css +7 -0
  100. data/spec/tests/preserve-strings.css.min +1 -0
  101. data/spec/tests/pseudo-first.css +16 -0
  102. data/spec/tests/pseudo-first.css.min +1 -0
  103. data/spec/tests/pseudo.css +4 -0
  104. data/spec/tests/pseudo.css.min +1 -0
  105. data/spec/tests/special-comments.css +13 -0
  106. data/spec/tests/special-comments.css.min +9 -0
  107. data/spec/tests/star-underscore-hacks.css +5 -0
  108. data/spec/tests/star-underscore-hacks.css.min +1 -0
  109. data/spec/tests/string-in-comment.css +8 -0
  110. data/spec/tests/string-in-comment.css.min +1 -0
  111. data/spec/tests/webkit-transform.css +2 -0
  112. data/spec/tests/webkit-transform.css.min +1 -0
  113. data/spec/tests/zeros.css +12 -0
  114. data/spec/tests/zeros.css.min +1 -0
  115. metadata +278 -0
@@ -0,0 +1,5 @@
1
+ # coding: utf-8
2
+
3
+ class CSSminify2
4
+ VERSION = "2.0.0"
5
+ end
@@ -0,0 +1,321 @@
1
+ # coding: utf-8
2
+
3
+ require "spec_helper"
4
+
5
+
6
+ describe "CSSminify2" do
7
+
8
+ context "application" do
9
+
10
+ it "minifies CSS" do
11
+ source = File.open(File.expand_path("../sample.css", __FILE__), "r:UTF-8").read
12
+ minified = CSSminify2.compress(source)
13
+ minified.length.should < source.length
14
+ lambda {
15
+ CSSminify2.compress(minified)
16
+ }.should_not raise_error
17
+ end
18
+
19
+ it "honors the specified maximum line length" do
20
+ source = <<-EOS
21
+ .classname1 {
22
+ border: none;
23
+ background: none;
24
+ outline: none;
25
+ }
26
+ .classname2 {
27
+ border: none;
28
+ background: none;
29
+ outline: none;
30
+ }
31
+ EOS
32
+ minified = CSSminify2.compress(source, 30)
33
+ minified.split("\n").length.should eq(2)
34
+ minified.should eq(".classname1{border:0;background:0;outline:0}\n.classname2{border:0;background:0;outline:0}")
35
+ end
36
+
37
+ it "handles strings as input format" do
38
+ lambda {
39
+ CSSminify2.compress(File.open(File.expand_path("../sample.css", __FILE__), "r:UTF-8").read).should_not be_empty
40
+ }.should_not raise_error
41
+ end
42
+
43
+ it "handles files as input format" do
44
+ lambda {
45
+ CSSminify2.compress(File.open(File.expand_path("../sample.css", __FILE__), "r:UTF-8")).should_not be_empty
46
+ }.should_not raise_error
47
+ end
48
+
49
+ it "works as both class and class instance" do
50
+ lambda {
51
+ CSSminify2.compress(File.open(File.expand_path("../sample.css", __FILE__), "r:UTF-8").read).should_not be_empty
52
+ CSSminify2.new.compress(File.open(File.expand_path("../sample.css", __FILE__), "r:UTF-8").read).should_not be_empty
53
+ }.should_not raise_error
54
+ end
55
+
56
+ end
57
+
58
+
59
+ context "compression" do
60
+
61
+ it "removes comments and white space" do
62
+ source = <<-EOS
63
+ /*****
64
+ Multi-line comment
65
+ before a new class name
66
+ *****/
67
+ .classname {
68
+ /* comment in declaration block */
69
+ font-weight: normal;
70
+ }
71
+ EOS
72
+ CSSminify2.compress(source).should eq('.classname{font-weight:normal}')
73
+ end
74
+
75
+ it "preserves special comments" do
76
+ source = <<-EOS
77
+ /*!
78
+ (c) Very Important Comment
79
+ */
80
+ .classname {
81
+ /* comment in declaration block */
82
+ font-weight: normal;
83
+ }
84
+ EOS
85
+ result = <<-EOS
86
+ /*!
87
+ (c) Very Important Comment
88
+ */.classname{font-weight:normal}
89
+ EOS
90
+ (CSSminify2.compress(source) + "\n").should eq(result)
91
+ end
92
+
93
+ it "removes last semi-colon in a block" do
94
+ source = <<-EOS
95
+ .classname {
96
+ border-top: 1px;
97
+ border-bottom: 2px;
98
+ }
99
+ EOS
100
+ CSSminify2.compress(source).should eq('.classname{border-top:1px;border-bottom:2px}')
101
+ end
102
+
103
+ it "removes extra semi-colons" do
104
+ source = <<-EOS
105
+ .classname {
106
+ border-top: 1px; ;
107
+ border-bottom: 2px;;;
108
+ }
109
+ EOS
110
+ CSSminify2.compress(source).should eq('.classname{border-top:1px;border-bottom:2px}')
111
+ end
112
+
113
+ it "removes empty declarations" do
114
+ source = <<-EOS
115
+ .empty { ;}
116
+ .nonempty {border: 0;}
117
+ EOS
118
+ CSSminify2.compress(source).should eq('.nonempty{border:0}')
119
+ end
120
+
121
+ it "simplifies zero values" do
122
+ source = <<-EOS
123
+ a {
124
+ margin: 0px 0pt 0em 0%;
125
+ background-position: 0 0ex;
126
+ padding: 0in 0cm 0mm 0pc
127
+ }
128
+ EOS
129
+ CSSminify2.compress(source).should eq('a{margin:0;background-position:0 0;padding:0}')
130
+ end
131
+
132
+ it "simplifies zero values preserving unit when necessary" do
133
+ source = <<-EOS
134
+ @-webkit-keyframes anim {
135
+ 0% {
136
+ left: 0;
137
+ }
138
+ 100% {
139
+ left: -100%;
140
+ }
141
+ }
142
+ @-moz-keyframes anim {
143
+ 0% {
144
+ left: 0;
145
+ }
146
+ 100% {
147
+ left: -100%;
148
+ }
149
+ }
150
+ @-ms-keyframes anim {
151
+ 0% {
152
+ left: 0;
153
+ }
154
+ 100% {
155
+ left: -100%;
156
+ }
157
+ }
158
+ @-o-keyframes anim {
159
+ 0% {
160
+ left: 0;
161
+ }
162
+ 100% {
163
+ left: -100%;
164
+ }
165
+ }
166
+ @keyframes anim {
167
+ 0% {
168
+ left: 0;
169
+ }
170
+ 100% {
171
+ left: -100%;
172
+ }
173
+ }
174
+ EOS
175
+ CSSminify2.compress(source).should eq('@-webkit-keyframes anim{0%{left:0}100%{left:-100%}}@-moz-keyframes anim{0%{left:0}100%{left:-100%}}@-ms-keyframes anim{0%{left:0}100%{left:-100%}}@-o-keyframes anim{0%{left:0}100%{left:-100%}}@keyframes anim{0%{left:0}100%{left:-100%}}')
176
+ end
177
+
178
+ it "removes leading zeros from floats" do
179
+ source = <<-EOS
180
+ .classname {
181
+ margin: 0.6px 0.333pt 1.2em 8.8cm;
182
+ }
183
+ EOS
184
+ CSSminify2.compress(source).should eq('.classname{margin:.6px .333pt 1.2em 8.8cm}')
185
+ end
186
+
187
+ it "removes leading zeros from groups" do
188
+ source = <<-EOS
189
+ a {
190
+ margin: 0px 0pt 0em 0%;
191
+ _padding-top: 0ex;
192
+ background-position: 0 0;
193
+ padding: 0in 0cm 0mm 0pc;
194
+ transition: opacity .0s;
195
+ transition-delay: 0.0ms;
196
+ transform: rotate3d(0grad, 0rad, 0deg);
197
+ pitch: 0khz;
198
+ pitch:
199
+ 0hz /* intentionally on next line */;
200
+ }
201
+ EOS
202
+ CSSminify2.compress(source).should eq('a{margin:0;_padding-top:0;background-position:0 0;padding:0;transition:opacity 0;transition-delay:0;transform:rotate3d(0,0,0);pitch:0;pitch:0}')
203
+ end
204
+
205
+ it "simplifies color values but preserves filter properties, RGBa values and ID strings" do
206
+ source = <<-EOS
207
+ .color-me {
208
+ color: rgb(123, 123, 123);
209
+ border-color: #ffeedd;
210
+ background: none repeat scroll 0 0 rgb(255, 0,0);
211
+ }
212
+ EOS
213
+ CSSminify2.compress(source).should eq('.color-me{color:#7b7b7b;border-color:#fed;background:none repeat scroll 0 0 #f00}')
214
+
215
+ source = <<-EOS
216
+ #AABBCC {
217
+ color: rgba(1, 2, 3, 4);
218
+ filter: chroma(color="#FFFFFF");
219
+ }
220
+ EOS
221
+ CSSminify2.compress(source).should eq('#AABBCC{color:rgba(1,2,3,4);filter:chroma(color="#FFFFFF")}')
222
+ end
223
+
224
+ it "only keeps the first charset declaration" do
225
+ source = <<-EOS
226
+ @charset "utf-8";
227
+ #foo {
228
+ border-width: 1px;
229
+ }
230
+
231
+ /* second css, merged */
232
+ @charset "another one";
233
+ #bar {
234
+ border-width: 10px;
235
+ }
236
+ EOS
237
+ CSSminify2.compress(source).should eq('@charset "utf-8";#foo{border-width:1px}#bar{border-width:10px}')
238
+ end
239
+
240
+ it "simplifies the IE opacity filter syntax" do
241
+ source = <<-EOS
242
+ .classname {
243
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; /* IE 8 */
244
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); /* IE < 8 */
245
+ }
246
+ EOS
247
+ CSSminify2.compress(source).should eq('.classname{-ms-filter:"alpha(opacity=80)";filter:alpha(opacity=80)}')
248
+ end
249
+
250
+ it "replaces 'none' values with 0 where allowed" do
251
+ source = <<-EOS
252
+ .classname {
253
+ border: none;
254
+ background: none;
255
+ outline: none;
256
+ }
257
+ EOS
258
+ CSSminify2.compress(source).should eq('.classname{border:0;background:0;outline:0}')
259
+ end
260
+
261
+ it "tolerates underscore/star hacks" do
262
+ source = <<-EOS
263
+ #element {
264
+ width: 1px;
265
+ *width: 2px;
266
+ _width: 3px;
267
+ }
268
+ EOS
269
+ CSSminify2.compress(source).should eq('#element{width:1px;*width:2px;_width:3px}')
270
+ end
271
+
272
+ it "tolerates child selector hacks" do
273
+ source = <<-EOS
274
+ html >/**/ body p {
275
+ color: blue;
276
+ }
277
+ EOS
278
+ CSSminify2.compress(source).should eq('html>/**/body p{color:blue}')
279
+ end
280
+
281
+ it "tolerates IE5/Mac hacks" do
282
+ source = <<-EOS
283
+ /* Ignore the next rule in IE mac \\*/
284
+ .selector {
285
+ color: khaki;
286
+ }
287
+ /* Stop ignoring in IE mac */
288
+ EOS
289
+ CSSminify2.compress(source).should eq('/*\*/.selector{color:khaki}/**/')
290
+ end
291
+
292
+ it "tolerates box model hacks" do
293
+ source = <<-EOS
294
+ #elem {
295
+ width: 100px; /* IE */
296
+ voice-family: "\\"}\\"";
297
+ voice-family:inherit;
298
+ width: 200px; /* others */
299
+ }
300
+ html>body #elem {
301
+ width: 200px; /* others */
302
+ }
303
+ EOS
304
+ CSSminify2.compress(source).should eq('#elem{width:100px;voice-family:"\"}\"";voice-family:inherit;width:200px}html>body #elem{width:200px}')
305
+ end
306
+
307
+ it "should pass all the original tests included in the YUI compressor package" do
308
+ puts "Now running original YUI compressor test files:"
309
+
310
+ files = Dir.glob(File.join(File.dirname(__FILE__), 'tests', '*.css'))
311
+
312
+ for file in files do
313
+ print " -- testing #{file} ..."
314
+ CSSminify2.compress(File.read(file)).chomp.strip.should eq(File.read(file + '.min').chomp.strip)
315
+ print "successful\n"
316
+ end
317
+ end
318
+
319
+ end
320
+
321
+ end
data/spec/sample.css ADDED
@@ -0,0 +1,141 @@
1
+ /* Source http://developer.yahoo.com/yui/compressor/css.html */
2
+
3
+ /*****
4
+ Multi-line comment
5
+ before a new class name
6
+ *****/
7
+ .classname {
8
+ /* comment in declaration block */
9
+ font-weight: normal;
10
+ }
11
+
12
+ /*!
13
+ (c) Very Important Comment
14
+ */
15
+ .classname {
16
+ /* comment in declaration block */
17
+ font-weight: normal;
18
+ }
19
+
20
+ .classname {
21
+ border-top: 1px;
22
+ border-bottom: 2px;
23
+ }
24
+
25
+ .classname {
26
+ border-top: 1px; ;
27
+ border-bottom: 2px;;;
28
+ }
29
+
30
+ .empty { ;}
31
+ .nonempty {border: 0;}
32
+
33
+ a {
34
+ margin: 0px 0pt 0em 0%;
35
+ background-position: 0 0ex;
36
+ padding: 0in 0cm 0mm 0pc
37
+ }
38
+
39
+ @-webkit-keyframes marquee {
40
+ 0% {
41
+ left: 0;
42
+ }
43
+ 100% {
44
+ left: -100%;
45
+ }
46
+ }
47
+ @-moz-keyframes marquee {
48
+ 0% {
49
+ left: 0;
50
+ }
51
+ 100% {
52
+ left: -100%;
53
+ }
54
+ }
55
+ @-ms-keyframes marquee {
56
+ 0% {
57
+ left: 0;
58
+ }
59
+ 100% {
60
+ left: -100%;
61
+ }
62
+ }
63
+ @-o-keyframes marquee {
64
+ 0% {
65
+ left: 0;
66
+ }
67
+ 100% {
68
+ left: -100%;
69
+ }
70
+ }
71
+ @keyframes marquee {
72
+ 0% {
73
+ left: 0;
74
+ }
75
+ 100% {
76
+ left: -100%;
77
+ }
78
+ }
79
+
80
+ .classname {
81
+ margin: 0.6px 0.333pt 1.2em 8.8cm;
82
+ }
83
+
84
+ .color-me {
85
+ color: rgb(123, 123, 123);
86
+ border-color: #ffeedd;
87
+ background: none repeat scroll 0 0 rgb(255, 0,0);
88
+ }
89
+
90
+ .cantouch {
91
+ color: rgba(1, 2, 3, 4);
92
+ filter: chroma(color="#FFFFFF");
93
+ }
94
+
95
+ @charset "utf-8";
96
+ #foo {
97
+ border-width: 1px;
98
+ }
99
+
100
+ /* second css, merged */
101
+ @charset "another one";
102
+ #bar {
103
+ border-width: 10px;
104
+ }
105
+
106
+ .classname {
107
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; /* IE 8 */
108
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); /* IE < 8 */
109
+ }
110
+
111
+ .classname {
112
+ border: none;
113
+ background: none;
114
+ outline: none;
115
+ }
116
+
117
+ #element {
118
+ width: 1px;
119
+ *width: 2px;
120
+ _width: 3px;
121
+ }
122
+
123
+ html >/**/ body p {
124
+ color: blue;
125
+ }
126
+
127
+ /* Ignore the next rule in IE mac \*/
128
+ .selector {
129
+ color: khaki;
130
+ }
131
+ /* Stop ignoring in IE mac */
132
+
133
+ #elem {
134
+ width: 100px; /* IE */
135
+ voice-family: "\"}\"";
136
+ voice-family:inherit;
137
+ width: 200px; /* others */
138
+ }
139
+ html>body #elem {
140
+ width: 200px; /* others */
141
+ }