multi_css 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -2
- data/lib/multi_css.rb +4 -5
- data/lib/multi_css/version.rb +1 -1
- data/multi_css.gemspec +2 -1
- data/spec/multi_css_spec.rb +5 -10
- metadata +17 -116
- data/.gitmodules +0 -3
- data/lib/multi_css/adapters/vendored.rb +0 -9
- data/vendor/cssminify/.gitignore +0 -9
- data/vendor/cssminify/.travis.yml +0 -7
- data/vendor/cssminify/CHANGES.md +0 -12
- data/vendor/cssminify/Gemfile +0 -4
- data/vendor/cssminify/LICENSE.md +0 -22
- data/vendor/cssminify/README.md +0 -64
- data/vendor/cssminify/cssminify.gemspec +0 -30
- data/vendor/cssminify/lib/cssminify.rb +0 -34
- data/vendor/cssminify/lib/cssminify/cssmin.rb +0 -383
- data/vendor/cssminify/lib/cssminify/version.rb +0 -5
- data/vendor/cssminify/spec/cssminify_spec.rb +0 -257
- data/vendor/cssminify/spec/sample.css +0 -100
- data/vendor/cssminify/spec/spec_helper.rb +0 -4
- data/vendor/cssminify/spec/tests/background-position.css +0 -2
- data/vendor/cssminify/spec/tests/background-position.css.min +0 -1
- data/vendor/cssminify/spec/tests/border-none.css +0 -5
- data/vendor/cssminify/spec/tests/border-none.css.min +0 -1
- data/vendor/cssminify/spec/tests/box-model-hack.css +0 -9
- data/vendor/cssminify/spec/tests/box-model-hack.css.min +0 -1
- data/vendor/cssminify/spec/tests/bug2527974.css +0 -10
- data/vendor/cssminify/spec/tests/bug2527974.css.min +0 -1
- data/vendor/cssminify/spec/tests/bug2527991.css +0 -19
- data/vendor/cssminify/spec/tests/bug2527991.css.min +0 -1
- data/vendor/cssminify/spec/tests/bug2527998.css +0 -4
- data/vendor/cssminify/spec/tests/bug2527998.css.min +0 -1
- data/vendor/cssminify/spec/tests/bug2528034.css +0 -5
- data/vendor/cssminify/spec/tests/bug2528034.css.min +0 -1
- data/vendor/cssminify/spec/tests/bug2528093.css +0 -3
- data/vendor/cssminify/spec/tests/bug2528093.css.min +0 -1
- data/vendor/cssminify/spec/tests/charset-media.css +0 -9
- data/vendor/cssminify/spec/tests/charset-media.css.min +0 -1
- data/vendor/cssminify/spec/tests/color-simple.css +0 -8
- data/vendor/cssminify/spec/tests/color-simple.css.min +0 -1
- data/vendor/cssminify/spec/tests/color.css +0 -46
- data/vendor/cssminify/spec/tests/color.css.min +0 -1
- data/vendor/cssminify/spec/tests/comment.css +0 -3
- data/vendor/cssminify/spec/tests/comment.css.min +0 -1
- data/vendor/cssminify/spec/tests/concat-charset.css +0 -15
- data/vendor/cssminify/spec/tests/concat-charset.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-base64-doublequotes.css +0 -23
- data/vendor/cssminify/spec/tests/dataurl-base64-doublequotes.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-base64-eof.css +0 -10
- data/vendor/cssminify/spec/tests/dataurl-base64-eof.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-base64-linebreakindata.css +0 -34
- data/vendor/cssminify/spec/tests/dataurl-base64-linebreakindata.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-base64-noquotes.css +0 -26
- data/vendor/cssminify/spec/tests/dataurl-base64-noquotes.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-base64-singlequotes.css +0 -23
- data/vendor/cssminify/spec/tests/dataurl-base64-singlequotes.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-base64-twourls.css +0 -27
- data/vendor/cssminify/spec/tests/dataurl-base64-twourls.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-dbquote-font.css +0 -30
- data/vendor/cssminify/spec/tests/dataurl-dbquote-font.css.min +0 -5
- data/vendor/cssminify/spec/tests/dataurl-nonbase64-doublequotes.css +0 -13
- data/vendor/cssminify/spec/tests/dataurl-nonbase64-doublequotes.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-nonbase64-noquotes.css +0 -11
- data/vendor/cssminify/spec/tests/dataurl-nonbase64-noquotes.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-nonbase64-singlequotes.css +0 -15
- data/vendor/cssminify/spec/tests/dataurl-nonbase64-singlequotes.css.min +0 -2
- data/vendor/cssminify/spec/tests/dataurl-noquote-multiline-font.css +0 -31
- data/vendor/cssminify/spec/tests/dataurl-noquote-multiline-font.css.min +0 -3
- data/vendor/cssminify/spec/tests/dataurl-realdata-doublequotes.css +0 -90
- data/vendor/cssminify/spec/tests/dataurl-realdata-doublequotes.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-realdata-noquotes.css +0 -90
- data/vendor/cssminify/spec/tests/dataurl-realdata-noquotes.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-realdata-singlequotes.css +0 -90
- data/vendor/cssminify/spec/tests/dataurl-realdata-singlequotes.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-realdata-yuiapp.css +0 -106
- data/vendor/cssminify/spec/tests/dataurl-realdata-yuiapp.css.min +0 -1
- data/vendor/cssminify/spec/tests/dataurl-singlequote-font.css +0 -30
- data/vendor/cssminify/spec/tests/dataurl-singlequote-font.css.min +0 -3
- data/vendor/cssminify/spec/tests/decimals.css +0 -3
- data/vendor/cssminify/spec/tests/decimals.css.min +0 -1
- data/vendor/cssminify/spec/tests/dollar-header.css +0 -7
- data/vendor/cssminify/spec/tests/dollar-header.css.min +0 -3
- data/vendor/cssminify/spec/tests/font-face.css +0 -6
- data/vendor/cssminify/spec/tests/font-face.css.min +0 -1
- data/vendor/cssminify/spec/tests/ie5mac.css +0 -5
- data/vendor/cssminify/spec/tests/ie5mac.css.min +0 -1
- data/vendor/cssminify/spec/tests/media-empty-class.css +0 -16
- data/vendor/cssminify/spec/tests/media-empty-class.css.min +0 -1
- data/vendor/cssminify/spec/tests/media-multi.css +0 -3
- data/vendor/cssminify/spec/tests/media-multi.css.min +0 -1
- data/vendor/cssminify/spec/tests/media-test.css +0 -3
- data/vendor/cssminify/spec/tests/media-test.css.min +0 -1
- data/vendor/cssminify/spec/tests/opacity-filter.css +0 -14
- data/vendor/cssminify/spec/tests/opacity-filter.css.min +0 -1
- data/vendor/cssminify/spec/tests/preserve-case.css +0 -15
- data/vendor/cssminify/spec/tests/preserve-case.css.min +0 -1
- data/vendor/cssminify/spec/tests/preserve-new-line.css +0 -6
- data/vendor/cssminify/spec/tests/preserve-new-line.css.min +0 -3
- data/vendor/cssminify/spec/tests/preserve-strings.css +0 -7
- data/vendor/cssminify/spec/tests/preserve-strings.css.min +0 -1
- data/vendor/cssminify/spec/tests/pseudo-first.css +0 -16
- data/vendor/cssminify/spec/tests/pseudo-first.css.min +0 -1
- data/vendor/cssminify/spec/tests/pseudo.css +0 -4
- data/vendor/cssminify/spec/tests/pseudo.css.min +0 -1
- data/vendor/cssminify/spec/tests/special-comments.css +0 -13
- data/vendor/cssminify/spec/tests/special-comments.css.min +0 -9
- data/vendor/cssminify/spec/tests/star-underscore-hacks.css +0 -5
- data/vendor/cssminify/spec/tests/star-underscore-hacks.css.min +0 -1
- data/vendor/cssminify/spec/tests/string-in-comment.css +0 -8
- data/vendor/cssminify/spec/tests/string-in-comment.css.min +0 -1
- data/vendor/cssminify/spec/tests/webkit-transform.css +0 -2
- data/vendor/cssminify/spec/tests/webkit-transform.css.min +0 -1
- data/vendor/cssminify/spec/tests/zeros.css +0 -12
- data/vendor/cssminify/spec/tests/zeros.css.min +0 -1
@@ -1,34 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require "cssminify/cssmin"
|
4
|
-
require "cssminify/version"
|
5
|
-
|
6
|
-
class CSSminify
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
end
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
# Compress CSS with YUI
|
14
|
-
#
|
15
|
-
# @param [String, #read] CSS String or IO-like object that supports #read
|
16
|
-
# @param [Integer] length Maximum line length
|
17
|
-
# @return [String] Compressed CSS
|
18
|
-
def self.compress(source, length = 5000)
|
19
|
-
self.new.compress(source, length)
|
20
|
-
end
|
21
|
-
|
22
|
-
|
23
|
-
#
|
24
|
-
# Compress CSS with YUI
|
25
|
-
#
|
26
|
-
# @param [String, #read] CSS String or IO-like object that supports #read
|
27
|
-
# @param [Integer] length Maximum line length
|
28
|
-
# @return [String] Compressed CSS
|
29
|
-
def compress(source = '', length = 5000)
|
30
|
-
source = source.respond_to?(:read) ? source.read : source.to_s
|
31
|
-
|
32
|
-
CssCompressor.compress(source, length)
|
33
|
-
end
|
34
|
-
end
|
@@ -1,383 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# cssmin.rb - 1.0.1
|
3
|
-
# Author: Matthias Siegel - https://github.com/matthiassiegel/cssmin
|
4
|
-
# This is a Ruby port of the CSS minification tool
|
5
|
-
# distributed with YUICompressor, based on the original Java
|
6
|
-
# code and the Javascript port by Stoyan Stefanov.
|
7
|
-
# Permission is hereby granted to use the Ruby version under the same
|
8
|
-
# conditions as YUICompressor (original YUICompressor note below).
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# YUI Compressor
|
12
|
-
# http://developer.yahoo.com/yui/compressor/
|
13
|
-
# Author: Julien Lecomte - http://www.julienlecomte.net/
|
14
|
-
# Author: Isaac Schlueter - http://foohack.com/
|
15
|
-
# Author: Stoyan Stefanov - http://phpied.com/
|
16
|
-
# Copyright (c) 2011 Yahoo! Inc. All rights reserved.
|
17
|
-
# The copyrights embodied in the content of this file are licensed
|
18
|
-
# by Yahoo! Inc. under the BSD (revised) open source license.
|
19
|
-
#
|
20
|
-
|
21
|
-
module CssCompressor
|
22
|
-
|
23
|
-
def self.compress(css, linebreakpos = 5000)
|
24
|
-
|
25
|
-
#
|
26
|
-
# Support for various input types
|
27
|
-
#
|
28
|
-
if css.respond_to?(:read)
|
29
|
-
css = css.read
|
30
|
-
elsif css.respond_to?(:path)
|
31
|
-
css = File.read(css.path)
|
32
|
-
end
|
33
|
-
|
34
|
-
@@preservedTokens = []
|
35
|
-
comments = []
|
36
|
-
startIndex = 0
|
37
|
-
|
38
|
-
#
|
39
|
-
# Extract data urls
|
40
|
-
#
|
41
|
-
css = extractDataUrls(css)
|
42
|
-
|
43
|
-
#
|
44
|
-
# Collect all comment blocks...
|
45
|
-
#
|
46
|
-
while (startIndex = css.index(/\/\*/, startIndex)) != nil
|
47
|
-
endIndex = css.index(/\*\//, startIndex + 2)
|
48
|
-
endIndex = css.length if endIndex.nil?
|
49
|
-
|
50
|
-
comments << css[(startIndex + 2)...endIndex]
|
51
|
-
|
52
|
-
css = css[0...(startIndex + 2)] + '___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_' + (comments.length - 1).to_s + '___' + css[endIndex..-1]
|
53
|
-
startIndex += 2
|
54
|
-
end
|
55
|
-
|
56
|
-
#
|
57
|
-
# Preserve strings so their content doesn't get accidentally minified
|
58
|
-
#
|
59
|
-
css = css.gsub(/("([^\\"]|\\.|\\)*")|('([^\\']|\\.|\\)*')/) { |match|
|
60
|
-
quote = match[0, 1]
|
61
|
-
match = match[1...-1]
|
62
|
-
|
63
|
-
#
|
64
|
-
# Maybe the string contains a comment-like substring?
|
65
|
-
# One, maybe more? put'em back then
|
66
|
-
#
|
67
|
-
unless match.index('___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_').nil?
|
68
|
-
comments.each_index { |i| match = match.gsub(/___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_#{i}___/, comments[i]) }
|
69
|
-
end
|
70
|
-
|
71
|
-
#
|
72
|
-
# Minify alpha opacity in filter strings
|
73
|
-
#
|
74
|
-
match = match.gsub(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/i, 'alpha(opacity=')
|
75
|
-
|
76
|
-
@@preservedTokens << match
|
77
|
-
|
78
|
-
quote + "___YUICSSMIN_PRESERVED_TOKEN_" + (@@preservedTokens.length - 1).to_s + "___" + quote
|
79
|
-
}
|
80
|
-
|
81
|
-
#
|
82
|
-
# Strings are safe, now wrestle the comments
|
83
|
-
#
|
84
|
-
for i in 0...comments.length
|
85
|
-
token = comments[i]
|
86
|
-
placeholder = /___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_#{i}___/
|
87
|
-
|
88
|
-
#
|
89
|
-
# ! in the first position of the comment means preserve
|
90
|
-
# so push to the preserved tokens keeping the !
|
91
|
-
#
|
92
|
-
if token[0] === '!'
|
93
|
-
@@preservedTokens << token
|
94
|
-
css = css.gsub(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (@@preservedTokens.length - 1).to_s + "___")
|
95
|
-
next
|
96
|
-
end
|
97
|
-
|
98
|
-
#
|
99
|
-
# \ in the last position looks like hack for Mac/IE5
|
100
|
-
# shorten that to /*\*/ and the next one to /**/
|
101
|
-
#
|
102
|
-
if token[(token.length - 1)..-1] === '\\'
|
103
|
-
@@preservedTokens << '\\'
|
104
|
-
css = css.gsub(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (@@preservedTokens.length - 1).to_s + "___")
|
105
|
-
|
106
|
-
i += 1 # Attn: advancing the loop
|
107
|
-
|
108
|
-
@@preservedTokens << ''
|
109
|
-
css = css.gsub(/___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_#{i}___/, "___YUICSSMIN_PRESERVED_TOKEN_" + (@@preservedTokens.length - 1).to_s + "___")
|
110
|
-
next
|
111
|
-
end
|
112
|
-
|
113
|
-
#
|
114
|
-
# Keep empty comments after child selectors (IE7 hack)
|
115
|
-
# E.g. html >/**/ body
|
116
|
-
#
|
117
|
-
if token.length == 0
|
118
|
-
startIndex = css.index(placeholder)
|
119
|
-
|
120
|
-
if startIndex and startIndex > 2
|
121
|
-
if css[startIndex - 3] === '>'
|
122
|
-
@@preservedTokens << ''
|
123
|
-
css = css.gsub(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (@@preservedTokens.length - 1).to_s + "___")
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
#
|
129
|
-
# In all other cases kill the comment
|
130
|
-
#
|
131
|
-
css = css.gsub(/\/\*___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_#{i}___\*\//, '')
|
132
|
-
end
|
133
|
-
|
134
|
-
#
|
135
|
-
# Shorten all whitespace strings to single spaces
|
136
|
-
#
|
137
|
-
css = css.gsub(/\s+/, ' ')
|
138
|
-
|
139
|
-
#
|
140
|
-
# Remove the spaces before the things that should not have spaces before them.
|
141
|
-
# But, be careful not to turn "p :link {...}" into "p:link{...}"
|
142
|
-
# Swap out any pseudo-class colons with the token, and then swap back.
|
143
|
-
#
|
144
|
-
css = css.gsub(/(^|\})(([^\{:])+:)+([^\{]*\{)/) { |m| m.gsub(/:/, '___YUICSSMIN_PSEUDOCLASSCOLON___') }
|
145
|
-
css = css.gsub(/\s+([!{};:>+\(\)\],])/) { $1.to_s }
|
146
|
-
css = css.gsub(/___YUICSSMIN_PSEUDOCLASSCOLON___/, ':')
|
147
|
-
|
148
|
-
#
|
149
|
-
# Retain space for special IE6 cases
|
150
|
-
#
|
151
|
-
css = css.gsub(/:first-(line|letter)(\{|,)/i) { ":first-#{$1.to_s.downcase} #{$2.to_s}" }
|
152
|
-
|
153
|
-
#
|
154
|
-
# No space after the end of a preserved comment
|
155
|
-
#
|
156
|
-
css = css.gsub(/\*\/\s+/, '*/')
|
157
|
-
|
158
|
-
#
|
159
|
-
# If there is a @charset, then only allow one, and push to the top of the file.
|
160
|
-
#
|
161
|
-
css = css.gsub(/^(.*)(@charset "[^"]*";)/i) { $2.to_s + $1.to_s }
|
162
|
-
css = css.gsub(/^(\s*@charset [^;]+;\s*)+/i) { $1.to_s }
|
163
|
-
|
164
|
-
#
|
165
|
-
# Put the space back in some cases, to support stuff like
|
166
|
-
# @media screen and (-webkit-min-device-pixel-ratio:0){
|
167
|
-
#
|
168
|
-
css = css.gsub(/\band\(/i, 'and (')
|
169
|
-
|
170
|
-
#
|
171
|
-
# Remove the spaces after the things that should not have spaces after them.
|
172
|
-
#
|
173
|
-
css = css.gsub(/([!{}:;>+\(\[,])\s+/) { $1.to_s }
|
174
|
-
|
175
|
-
#
|
176
|
-
# Remove unnecessary semicolons
|
177
|
-
#
|
178
|
-
css = css.gsub(/;+\}/, '}')
|
179
|
-
|
180
|
-
#
|
181
|
-
# Replace 0(px,em,%) with 0
|
182
|
-
#
|
183
|
-
css = css.gsub(/(^|[^0-9])(?:0?\.)?0(?:px|em|%|in|cm|mm|pc|pt|ex|deg|g?rad|m?s|k?hz)/i) { $1.to_s + '0' }
|
184
|
-
|
185
|
-
#
|
186
|
-
# Replace 0 0 0 0; with 0
|
187
|
-
#
|
188
|
-
css = css.gsub(/:0 0 0 0(;|\})/) { ':0' + $1.to_s }
|
189
|
-
css = css.gsub(/:0 0 0(;|\})/) { ':0' + $1.to_s }
|
190
|
-
css = css.gsub(/:0 0(;|\})/) { ':0' + $1.to_s }
|
191
|
-
|
192
|
-
#
|
193
|
-
# Replace background-position:0; with background-position:0 0;
|
194
|
-
# Same for transform-origin
|
195
|
-
#
|
196
|
-
css = css.gsub(/(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|\})/i) { "#{$1.to_s.downcase}:0 0#{$2.to_s}" }
|
197
|
-
|
198
|
-
#
|
199
|
-
# Replace 0.6 to .6, but only when preceded by : or a white-space
|
200
|
-
#
|
201
|
-
css = css.gsub(/(:|\s)0+\.(\d+)/) { "#{$1.to_s}.#{$2.to_s}" }
|
202
|
-
|
203
|
-
#
|
204
|
-
# Shorten colors from rgb(51,102,153) to #336699
|
205
|
-
# This makes it more likely that it'll get further compressed in the next step.
|
206
|
-
#
|
207
|
-
css = css.gsub(/rgb\s*\(\s*([0-9,\s]+)\s*\)(\d+%)?/i) {
|
208
|
-
rgbcolors = $1.to_s.split(',')
|
209
|
-
i = 0
|
210
|
-
|
211
|
-
while i < rgbcolors.length
|
212
|
-
rgbcolors[i] = rgbcolors[i].to_i.to_s(16)
|
213
|
-
|
214
|
-
if rgbcolors[i].length === 1
|
215
|
-
rgbcolors[i] = '0' + rgbcolors[i]
|
216
|
-
end
|
217
|
-
|
218
|
-
i += 1
|
219
|
-
end
|
220
|
-
|
221
|
-
unless $2.to_s.empty?
|
222
|
-
rgbcolors << (' ' + $2.to_s)
|
223
|
-
end
|
224
|
-
|
225
|
-
'#' + rgbcolors.join('')
|
226
|
-
}
|
227
|
-
|
228
|
-
#
|
229
|
-
# Shorten colors from #AABBCC to #ABC. Note that we want to make sure
|
230
|
-
# the color is not preceded by either ", " or =. Indeed, the property
|
231
|
-
# filter: chroma(color="#FFFFFF");
|
232
|
-
# would become
|
233
|
-
# filter: chroma(color="#FFF");
|
234
|
-
# which makes the filter break in IE.
|
235
|
-
# We also want to make sure we're only compressing #AABBCC patterns inside { }, not id selectors ( #FAABAC {} )
|
236
|
-
# We also want to avoid compressing invalid values (e.g. #AABBCCD to #ABCD)
|
237
|
-
#
|
238
|
-
rest = css
|
239
|
-
new_css = ''
|
240
|
-
|
241
|
-
while m = rest.match(/(\=\s*?["']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(:?\}|[^0-9a-f{][^{]*?\})/i) do
|
242
|
-
#
|
243
|
-
# Normal color value
|
244
|
-
#
|
245
|
-
if m[1].nil?
|
246
|
-
#
|
247
|
-
# Color value that can be shortened
|
248
|
-
#
|
249
|
-
if m[2].to_s.downcase == m[3].to_s.downcase && m[4].to_s.downcase == m[5].to_s.downcase && m[6].to_s.downcase == m[7].to_s.downcase
|
250
|
-
color = '#' + m[2].to_s.downcase + m[4].to_s.downcase + m[6].to_s.downcase
|
251
|
-
shift = 7
|
252
|
-
|
253
|
-
#
|
254
|
-
# Color value that can't be shortened
|
255
|
-
#
|
256
|
-
else
|
257
|
-
color = '#' + m[2].to_s.downcase + m[3].to_s.downcase + m[4].to_s.downcase + m[5].to_s.downcase + m[6].to_s.downcase + m[7].to_s.downcase
|
258
|
-
shift = 7
|
259
|
-
end
|
260
|
-
|
261
|
-
#
|
262
|
-
# Filter property that needs to stay the way it is
|
263
|
-
#
|
264
|
-
else
|
265
|
-
color = m[1].to_s + '#' + m[2].to_s + m[3].to_s + m[4].to_s + m[5].to_s + m[6].to_s + m[7].to_s
|
266
|
-
shift = color.length
|
267
|
-
end
|
268
|
-
|
269
|
-
new_css += m.pre_match + color
|
270
|
-
rest.slice!(rest.index(m.pre_match || 0), m.pre_match.length + shift)
|
271
|
-
|
272
|
-
end
|
273
|
-
css = new_css + rest
|
274
|
-
|
275
|
-
#
|
276
|
-
# border: none -> border:0
|
277
|
-
#
|
278
|
-
css = css.gsub(/(border|border-top|border-right|border-bottom|border-left|outline|background):none(;|\})/i) { "#{$1.to_s.downcase}:0#{$2.to_s}" }
|
279
|
-
|
280
|
-
#
|
281
|
-
# Shorter opacity IE filter
|
282
|
-
#
|
283
|
-
css = css.gsub(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/i, 'alpha(opacity=')
|
284
|
-
|
285
|
-
#
|
286
|
-
# Remove empty rules.
|
287
|
-
#
|
288
|
-
css = css.gsub(/[^\};\{\/]+\{\}/, '')
|
289
|
-
|
290
|
-
#
|
291
|
-
# Some source control tools don't like it when files containing lines longer
|
292
|
-
# than, say 8000 characters, are checked in. The linebreak option is used in
|
293
|
-
# that case to split long lines after a specific column.
|
294
|
-
#
|
295
|
-
if linebreakpos
|
296
|
-
startIndex = 0
|
297
|
-
i = 0
|
298
|
-
while i < css.length
|
299
|
-
i = i + 1
|
300
|
-
if css[i - 1] === '}' && i - startIndex > linebreakpos
|
301
|
-
css = css.slice(0, i) + "\n" + css.slice(i, css.length - i)
|
302
|
-
startIndex = i
|
303
|
-
end
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
#
|
308
|
-
# Replace multiple semi-colons in a row by a single one
|
309
|
-
#
|
310
|
-
css = css.gsub(/;;+/, ';')
|
311
|
-
|
312
|
-
#
|
313
|
-
# Restore preserved comments and strings
|
314
|
-
#
|
315
|
-
for i in 0...@@preservedTokens.length do
|
316
|
-
css = css.gsub(/___YUICSSMIN_PRESERVED_TOKEN_#{i}___/) { @@preservedTokens[i] }
|
317
|
-
end
|
318
|
-
|
319
|
-
#
|
320
|
-
# Remove leading and trailing whitespace
|
321
|
-
#
|
322
|
-
css = css.chomp.strip
|
323
|
-
end
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
private
|
329
|
-
|
330
|
-
|
331
|
-
#
|
332
|
-
# Utility method to replace all data urls with tokens before we start
|
333
|
-
# compressing, to avoid performance issues running some of the subsequent
|
334
|
-
# regexes against large strings chunks.
|
335
|
-
#
|
336
|
-
# @param [String] css The input css
|
337
|
-
# @returns [String] The processed css
|
338
|
-
#
|
339
|
-
def self.extractDataUrls(css)
|
340
|
-
new_css = ''
|
341
|
-
|
342
|
-
while m = css.match(/url\(\s*(["']?)data\:/i) do
|
343
|
-
startIndex = m.begin(0) + 4 # "url(".length()
|
344
|
-
terminator = m[1] # ', " or empty (not quoted)
|
345
|
-
terminator = ')' if terminator.empty?
|
346
|
-
foundTerminator = false
|
347
|
-
endIndex = m.end(0) - 1
|
348
|
-
|
349
|
-
while !foundTerminator && endIndex + 1 <= css.length
|
350
|
-
endIndex = css.index(terminator, endIndex + 1)
|
351
|
-
|
352
|
-
#
|
353
|
-
# endIndex == 0 doesn't really apply here
|
354
|
-
#
|
355
|
-
if endIndex > 0 && css[endIndex - 1] != '\\'
|
356
|
-
foundTerminator = true
|
357
|
-
endIndex = css.index(')', endIndex) if terminator != ')'
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
|
-
new_css += css[0...m.begin(0)]
|
362
|
-
|
363
|
-
if foundTerminator
|
364
|
-
token = css[startIndex...endIndex]
|
365
|
-
token = token.gsub(/\s+/, '')
|
366
|
-
@@preservedTokens << token
|
367
|
-
|
368
|
-
new_css += "url(___YUICSSMIN_PRESERVED_TOKEN_" + (@@preservedTokens.length - 1).to_s + "___)"
|
369
|
-
|
370
|
-
#
|
371
|
-
# No end terminator found, re-add the whole match
|
372
|
-
#
|
373
|
-
else
|
374
|
-
new_css += css[m.begin(0)...m.end(0)]
|
375
|
-
end
|
376
|
-
|
377
|
-
css = css[(endIndex + 1)..-1]
|
378
|
-
end
|
379
|
-
|
380
|
-
css = new_css + css
|
381
|
-
end
|
382
|
-
|
383
|
-
end
|
@@ -1,257 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
|
6
|
-
describe "CSSminify" 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 = CSSminify.compress(source)
|
13
|
-
minified.length.should < source.length
|
14
|
-
lambda {
|
15
|
-
CSSminify.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 = CSSminify.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
|
-
CSSminify.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
|
-
CSSminify.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
|
-
CSSminify.compress(File.open(File.expand_path("../sample.css", __FILE__), "r:UTF-8").read).should_not be_empty
|
52
|
-
CSSminify.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
|
-
CSSminify.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
|
-
(CSSminify.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
|
-
CSSminify.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
|
-
CSSminify.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
|
-
CSSminify.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
|
-
CSSminify.compress(source).should eq('a{margin:0;background-position:0 0;padding:0}')
|
130
|
-
end
|
131
|
-
|
132
|
-
it "removes leading zeros from floats" do
|
133
|
-
source = <<-EOS
|
134
|
-
.classname {
|
135
|
-
margin: 0.6px 0.333pt 1.2em 8.8cm;
|
136
|
-
}
|
137
|
-
EOS
|
138
|
-
CSSminify.compress(source).should eq('.classname{margin:.6px .333pt 1.2em 8.8cm}')
|
139
|
-
end
|
140
|
-
|
141
|
-
it "simplifies color values but preserves filter properties, RGBa values and ID strings" do
|
142
|
-
source = <<-EOS
|
143
|
-
.color-me {
|
144
|
-
color: rgb(123, 123, 123);
|
145
|
-
border-color: #ffeedd;
|
146
|
-
background: none repeat scroll 0 0 rgb(255, 0,0);
|
147
|
-
}
|
148
|
-
EOS
|
149
|
-
CSSminify.compress(source).should eq('.color-me{color:#7b7b7b;border-color:#fed;background:none repeat scroll 0 0 #f00}')
|
150
|
-
|
151
|
-
source = <<-EOS
|
152
|
-
#AABBCC {
|
153
|
-
color: rgba(1, 2, 3, 4);
|
154
|
-
filter: chroma(color="#FFFFFF");
|
155
|
-
}
|
156
|
-
EOS
|
157
|
-
CSSminify.compress(source).should eq('#AABBCC{color:rgba(1,2,3,4);filter:chroma(color="#FFFFFF")}')
|
158
|
-
end
|
159
|
-
|
160
|
-
it "only keeps the first charset declaration" do
|
161
|
-
source = <<-EOS
|
162
|
-
@charset "utf-8";
|
163
|
-
#foo {
|
164
|
-
border-width: 1px;
|
165
|
-
}
|
166
|
-
|
167
|
-
/* second css, merged */
|
168
|
-
@charset "another one";
|
169
|
-
#bar {
|
170
|
-
border-width: 10px;
|
171
|
-
}
|
172
|
-
EOS
|
173
|
-
CSSminify.compress(source).should eq('@charset "utf-8";#foo{border-width:1px}#bar{border-width:10px}')
|
174
|
-
end
|
175
|
-
|
176
|
-
it "simplifies the IE opacity filter syntax" do
|
177
|
-
source = <<-EOS
|
178
|
-
.classname {
|
179
|
-
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; /* IE 8 */
|
180
|
-
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); /* IE < 8 */
|
181
|
-
}
|
182
|
-
EOS
|
183
|
-
CSSminify.compress(source).should eq('.classname{-ms-filter:"alpha(opacity=80)";filter:alpha(opacity=80)}')
|
184
|
-
end
|
185
|
-
|
186
|
-
it "replaces 'none' values with 0 where allowed" do
|
187
|
-
source = <<-EOS
|
188
|
-
.classname {
|
189
|
-
border: none;
|
190
|
-
background: none;
|
191
|
-
outline: none;
|
192
|
-
}
|
193
|
-
EOS
|
194
|
-
CSSminify.compress(source).should eq('.classname{border:0;background:0;outline:0}')
|
195
|
-
end
|
196
|
-
|
197
|
-
it "tolerates underscore/star hacks" do
|
198
|
-
source = <<-EOS
|
199
|
-
#element {
|
200
|
-
width: 1px;
|
201
|
-
*width: 2px;
|
202
|
-
_width: 3px;
|
203
|
-
}
|
204
|
-
EOS
|
205
|
-
CSSminify.compress(source).should eq('#element{width:1px;*width:2px;_width:3px}')
|
206
|
-
end
|
207
|
-
|
208
|
-
it "tolerates child selector hacks" do
|
209
|
-
source = <<-EOS
|
210
|
-
html >/**/ body p {
|
211
|
-
color: blue;
|
212
|
-
}
|
213
|
-
EOS
|
214
|
-
CSSminify.compress(source).should eq('html>/**/body p{color:blue}')
|
215
|
-
end
|
216
|
-
|
217
|
-
it "tolerates IE5/Mac hacks" do
|
218
|
-
source = <<-EOS
|
219
|
-
/* Ignore the next rule in IE mac \\*/
|
220
|
-
.selector {
|
221
|
-
color: khaki;
|
222
|
-
}
|
223
|
-
/* Stop ignoring in IE mac */
|
224
|
-
EOS
|
225
|
-
CSSminify.compress(source).should eq('/*\*/.selector{color:khaki}/**/')
|
226
|
-
end
|
227
|
-
|
228
|
-
it "tolerates box model hacks" do
|
229
|
-
source = <<-EOS
|
230
|
-
#elem {
|
231
|
-
width: 100px; /* IE */
|
232
|
-
voice-family: "\\"}\\"";
|
233
|
-
voice-family:inherit;
|
234
|
-
width: 200px; /* others */
|
235
|
-
}
|
236
|
-
html>body #elem {
|
237
|
-
width: 200px; /* others */
|
238
|
-
}
|
239
|
-
EOS
|
240
|
-
CSSminify.compress(source).should eq('#elem{width:100px;voice-family:"\"}\"";voice-family:inherit;width:200px}html>body #elem{width:200px}')
|
241
|
-
end
|
242
|
-
|
243
|
-
it "should pass all the original tests included in the YUI compressor package" do
|
244
|
-
puts "Now running original YUI compressor test files:"
|
245
|
-
|
246
|
-
files = Dir.glob(File.join(File.dirname(__FILE__), 'tests', '*.css'))
|
247
|
-
|
248
|
-
for file in files do
|
249
|
-
print " -- testing #{file} ..."
|
250
|
-
CSSminify.compress(File.read(file)).chomp.strip.should eq(File.read(file + '.min').chomp.strip)
|
251
|
-
print "successful\n"
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
end
|
256
|
-
|
257
|
-
end
|