sass 3.2.0.alpha.63 → 3.2.0.alpha.64
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/REVISION +1 -1
- data/VERSION +1 -1
- data/lib/sass/cache_stores/filesystem.rb +1 -0
- data/lib/sass/script/funcall.rb +2 -2
- data/lib/sass/script/literal.rb +0 -20
- data/lib/sass/script/operation.rb +8 -0
- data/lib/sass/selector.rb +1 -1
- data/lib/sass/selector/sequence.rb +123 -11
- data/lib/sass/tree/visitors/convert.rb +2 -1
- data/lib/sass/tree/visitors/cssize.rb +21 -6
- data/lib/sass/tree/visitors/perform.rb +2 -0
- data/lib/sass/tree/visitors/to_css.rb +11 -3
- data/lib/sass/util.rb +32 -0
- data/test/sass/engine_test.rb +28 -2
- data/test/sass/extend_test.rb +476 -2
- data/test/sass/more_results/more_import.css +2 -2
- data/test/sass/results/import.css +2 -2
- data/test/sass/results/import_charset.css +1 -0
- data/test/sass/results/import_charset_1_8.css +1 -0
- data/test/sass/results/import_charset_ibm866.css +1 -0
- data/test/sass/results/scss_import.css +2 -2
- data/test/sass/script_test.rb +5 -0
- data/test/sass/scss/scss_test.rb +3 -3
- data/test/sass/templates/import_charset.sass +2 -0
- data/test/sass/templates/import_charset_1_8.sass +2 -0
- data/test/sass/templates/import_charset_ibm866.sass +2 -0
- data/test/sass/util_test.rb +6 -0
- metadata +6 -6
data/REVISION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
13aa911b7cb8d035e5a613f7d94d9b08241a46cd
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.0.alpha.
|
1
|
+
3.2.0.alpha.64
|
data/lib/sass/script/funcall.rb
CHANGED
@@ -36,7 +36,7 @@ module Sass
|
|
36
36
|
# @return [String] A string representation of the function call
|
37
37
|
def inspect
|
38
38
|
args = @args.map {|a| a.inspect}.join(', ')
|
39
|
-
keywords = @keywords.
|
39
|
+
keywords = Sass::Util.hash_to_a(@keywords).
|
40
40
|
map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
|
41
41
|
"#{name}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})"
|
42
42
|
end
|
@@ -44,7 +44,7 @@ module Sass
|
|
44
44
|
# @see Node#to_sass
|
45
45
|
def to_sass(opts = {})
|
46
46
|
args = @args.map {|a| a.to_sass(opts)}.join(', ')
|
47
|
-
keywords = @keywords.
|
47
|
+
keywords = Sass::Util.hash_to_a(@keywords).
|
48
48
|
map {|k, v| "$#{dasherize(k, opts)}: #{v.to_sass(opts)}"}.join(', ')
|
49
49
|
"#{dasherize(name, opts)}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})"
|
50
50
|
end
|
data/lib/sass/script/literal.rb
CHANGED
@@ -55,26 +55,6 @@ The #options attribute is not set on this #{self.class}.
|
|
55
55
|
MSG
|
56
56
|
end
|
57
57
|
|
58
|
-
# The SassScript `and` operation.
|
59
|
-
#
|
60
|
-
# @param other [Literal] The right-hand side of the operator
|
61
|
-
# @return [Literal] The result of a logical and:
|
62
|
-
# `other` if this literal isn't a false {Bool},
|
63
|
-
# and this literal otherwise
|
64
|
-
def and(other)
|
65
|
-
to_bool ? other : self
|
66
|
-
end
|
67
|
-
|
68
|
-
# The SassScript `or` operation.
|
69
|
-
#
|
70
|
-
# @param other [Literal] The right-hand side of the operator
|
71
|
-
# @return [Literal] The result of the logical or:
|
72
|
-
# this literal if it isn't a false {Bool},
|
73
|
-
# and `other` otherwise
|
74
|
-
def or(other)
|
75
|
-
to_bool ? self : other
|
76
|
-
end
|
77
|
-
|
78
58
|
# The SassScript `==` operation.
|
79
59
|
# **Note that this returns a {Sass::Script::Bool} object,
|
80
60
|
# not a Ruby boolean**.
|
@@ -72,6 +72,14 @@ module Sass::Script
|
|
72
72
|
# @raise [Sass::SyntaxError] if the operation is undefined for the operands
|
73
73
|
def _perform(environment)
|
74
74
|
literal1 = @operand1.perform(environment)
|
75
|
+
|
76
|
+
# Special-case :and and :or to support short-circuiting.
|
77
|
+
if @operator == :and
|
78
|
+
return literal1.to_bool ? @operand2.perform(environment) : literal1
|
79
|
+
elsif @operator == :or
|
80
|
+
return literal1.to_bool ? literal1 : @operand2.perform(environment)
|
81
|
+
end
|
82
|
+
|
75
83
|
literal2 = @operand2.perform(environment)
|
76
84
|
|
77
85
|
begin
|
data/lib/sass/selector.rb
CHANGED
@@ -379,7 +379,7 @@ module Sass
|
|
379
379
|
attr_reader :selector
|
380
380
|
|
381
381
|
# @param [String] The name of the pseudoclass
|
382
|
-
# @param [Selector::
|
382
|
+
# @param [Selector::CommaSequence] The selector argument
|
383
383
|
def initialize(name, selector)
|
384
384
|
@name = name
|
385
385
|
@selector = selector
|
@@ -124,15 +124,15 @@ module Sass
|
|
124
124
|
# @param path [Array<Array<SimpleSequence or String>>] A list of parenthesized selector groups.
|
125
125
|
# @return [Array<Array<SimpleSequence or String>>] A list of fully-expanded selectors.
|
126
126
|
def weave(path)
|
127
|
+
# This function works by moving through the selector path left-to-right,
|
128
|
+
# building all possible prefixes simultaneously. These prefixes are
|
129
|
+
# `befores`, while the remaining parenthesized suffixes is `afters`.
|
127
130
|
befores = [[]]
|
128
131
|
afters = path.dup
|
129
132
|
|
130
133
|
until afters.empty?
|
131
134
|
current = afters.shift.dup
|
132
135
|
last_current = [current.pop]
|
133
|
-
while !current.empty? && last_current.first.is_a?(String) || current.last.is_a?(String)
|
134
|
-
last_current.unshift(current.pop)
|
135
|
-
end
|
136
136
|
befores = Sass::Util.flatten(befores.map do |before|
|
137
137
|
next [] unless sub = subweave(before, current)
|
138
138
|
sub.map {|seqs| seqs + last_current}
|
@@ -150,6 +150,12 @@ module Sass
|
|
150
150
|
# `.foo .baz .bar .bang`, `.foo .baz .bar.bang`, `.foo .baz .bang .bar`,
|
151
151
|
# and so on until `.baz .bang .foo .bar`.
|
152
152
|
#
|
153
|
+
# Semantically, for selectors A and B, this returns all selectors `AB_i`
|
154
|
+
# such that the union over all i of elements matched by `AB_i X` is
|
155
|
+
# identical to the intersection of all elements matched by `A X` and all
|
156
|
+
# elements matched by `B X`. Some `AB_i` are elided to reduce the size of
|
157
|
+
# the output.
|
158
|
+
#
|
153
159
|
# @param seq1 [Array<SimpleSequence or String>]
|
154
160
|
# @param seq2 [Array<SimpleSequence or String>]
|
155
161
|
# @return [Array<Array<SimpleSequence or String>>]
|
@@ -157,7 +163,9 @@ module Sass
|
|
157
163
|
return [seq2] if seq1.empty?
|
158
164
|
return [seq1] if seq2.empty?
|
159
165
|
|
166
|
+
seq1, seq2 = seq1.dup, seq2.dup
|
160
167
|
return unless init = merge_initial_ops(seq1, seq2)
|
168
|
+
return unless fin = merge_final_ops(seq1, seq2)
|
161
169
|
seq1 = group_selectors(seq1)
|
162
170
|
seq2 = group_selectors(seq2)
|
163
171
|
lcs = Sass::Util.lcs(seq2, seq1) do |s1, s2|
|
@@ -174,14 +182,15 @@ module Sass
|
|
174
182
|
seq2.shift
|
175
183
|
end
|
176
184
|
diff << chunks(seq1, seq2) {|s| s.empty?}
|
185
|
+
diff += fin.map {|sel| sel.is_a?(Array) ? sel : [sel]}
|
177
186
|
diff.reject! {|c| c.empty?}
|
178
187
|
|
179
188
|
Sass::Util.paths(diff).map {|p| p.flatten}
|
180
189
|
end
|
181
190
|
|
182
|
-
# Extracts initial selector
|
191
|
+
# Extracts initial selector combinators (`"+"`, `">"`, `"~"`, and `"\n"`)
|
183
192
|
# from two sequences and merges them together into a single array of
|
184
|
-
# selector
|
193
|
+
# selector combinators.
|
185
194
|
#
|
186
195
|
# @param seq1 [Array<SimpleSequence or String>]
|
187
196
|
# @param seq2 [Array<SimpleSequence or String>]
|
@@ -204,6 +213,100 @@ module Sass
|
|
204
213
|
return (newline ? ["\n"] : []) + (ops1.size > ops2.size ? ops1 : ops2)
|
205
214
|
end
|
206
215
|
|
216
|
+
# Extracts final selector combinators (`"+"`, `">"`, `"~"`) and the
|
217
|
+
# selectors to which they apply from two sequences and merges them
|
218
|
+
# together into a single array.
|
219
|
+
#
|
220
|
+
# @param seq1 [Array<SimpleSequence or String>]
|
221
|
+
# @param seq2 [Array<SimpleSequence or String>]
|
222
|
+
# @return [Array<SimpleSequence or String or
|
223
|
+
# Array<Array<SimpleSequence or String>>]
|
224
|
+
# If there are no trailing combinators to be merged, this will be the
|
225
|
+
# empty array. If the trailing combinators cannot be merged, this will
|
226
|
+
# be nil. Otherwise, this will contained the merged selector. Array
|
227
|
+
# elements are [Sass::Util#paths]-style options; conceptually, an "or"
|
228
|
+
# of multiple selectors.
|
229
|
+
def merge_final_ops(seq1, seq2, res = [])
|
230
|
+
ops1, ops2 = [], []
|
231
|
+
ops1 << seq1.pop while seq1.last.is_a?(String)
|
232
|
+
ops2 << seq2.pop while seq2.last.is_a?(String)
|
233
|
+
|
234
|
+
# Not worth the headache of trying to preserve newlines here. The most
|
235
|
+
# important use of newlines is at the beginning of the selector to wrap
|
236
|
+
# across lines anyway.
|
237
|
+
ops1.reject! {|o| o == "\n"}
|
238
|
+
ops2.reject! {|o| o == "\n"}
|
239
|
+
|
240
|
+
return res if ops1.empty? && ops2.empty?
|
241
|
+
if ops1.size > 1 || ops2.size > 1
|
242
|
+
# If there are multiple operators, something hacky's going on. If one
|
243
|
+
# is a supersequence of the other, use that, otherwise give up.
|
244
|
+
lcs = Sass::Util.lcs(ops1, ops2)
|
245
|
+
return unless lcs == ops1 || lcs == ops2
|
246
|
+
res.unshift *(ops1.size > ops2.size ? ops1 : ops2).reverse
|
247
|
+
return res
|
248
|
+
end
|
249
|
+
|
250
|
+
# This code looks complicated, but it's actually just a bunch of special
|
251
|
+
# cases for interactions between different combinators.
|
252
|
+
op1, op2 = ops1.first, ops2.first
|
253
|
+
if op1 && op2
|
254
|
+
sel1 = seq1.pop
|
255
|
+
sel2 = seq2.pop
|
256
|
+
if op1 == '~' && op2 == '~'
|
257
|
+
if subweave_superselector?([sel1], [sel2])
|
258
|
+
res.unshift sel2, '~'
|
259
|
+
elsif subweave_superselector?([sel2], [sel1])
|
260
|
+
res.unshift sel1, '~'
|
261
|
+
else
|
262
|
+
merged = sel1.unify(sel2.members)
|
263
|
+
res.unshift [
|
264
|
+
[sel1, '~', sel2, '~'],
|
265
|
+
[sel2, '~', sel1, '~'],
|
266
|
+
([merged, '~'] if merged)
|
267
|
+
].compact
|
268
|
+
end
|
269
|
+
elsif (op1 == '~' && op2 == '+') || (op1 == '+' && op2 == '~')
|
270
|
+
if op1 == '~'
|
271
|
+
tilde_sel, plus_sel = sel1, sel2
|
272
|
+
else
|
273
|
+
tilde_sel, plus_sel = sel2, sel1
|
274
|
+
end
|
275
|
+
|
276
|
+
if subweave_superselector?([tilde_sel], [plus_sel])
|
277
|
+
res.unshift plus_sel, '+'
|
278
|
+
else
|
279
|
+
merged = plus_sel.unify(tilde_sel.members)
|
280
|
+
res.unshift [
|
281
|
+
[tilde_sel, '~', plus_sel, '+'],
|
282
|
+
([merged, '+'] if merged)
|
283
|
+
].compact
|
284
|
+
end
|
285
|
+
elsif op1 == '>' && %w[~ +].include?(op2)
|
286
|
+
res.unshift sel2, op2
|
287
|
+
seq1.push sel1, op1
|
288
|
+
elsif op2 == '>' && %w[~ +].include?(op1)
|
289
|
+
res.unshift sel1, op1
|
290
|
+
seq2.push sel2, op2
|
291
|
+
elsif op1 == op2
|
292
|
+
return unless merged = sel1.unify(sel2.members)
|
293
|
+
res.unshift merged, op1
|
294
|
+
else
|
295
|
+
# Unknown selector combinators can't be unified
|
296
|
+
return
|
297
|
+
end
|
298
|
+
return merge_final_ops(seq1, seq2, res)
|
299
|
+
elsif op1
|
300
|
+
seq2.pop if op1 == '>' && seq2.last && subweave_superselector?([seq2.last], [seq1.last])
|
301
|
+
res.unshift seq1.pop, op1
|
302
|
+
return merge_final_ops(seq1, seq2, res)
|
303
|
+
else # op2
|
304
|
+
seq1.pop if op2 == '>' && seq1.last && subweave_superselector?([seq1.last], [seq2.last])
|
305
|
+
res.unshift seq2.pop, op2
|
306
|
+
return merge_final_ops(seq1, seq2, res)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
207
310
|
# Takes initial subsequences of `seq1` and `seq2` and returns all
|
208
311
|
# orderings of those subsequences. The initial subsequences are determined
|
209
312
|
# by a block.
|
@@ -223,6 +326,7 @@ module Sass
|
|
223
326
|
# cutting off some initial subsequence.
|
224
327
|
# @yieldreturn [Boolean] Whether or not to cut off the initial subsequence
|
225
328
|
# here.
|
329
|
+
# @return [Array<Array>] All possible orderings of the initial subsequences.
|
226
330
|
def chunks(seq1, seq2)
|
227
331
|
chunk1 = []
|
228
332
|
chunk1 << seq1.shift until yield seq1
|
@@ -257,24 +361,32 @@ module Sass
|
|
257
361
|
end
|
258
362
|
|
259
363
|
# Given two sequences of simple selectors, returns whether `sseq1` is a
|
260
|
-
# superselector of `sseq2
|
364
|
+
# superselector of `sseq2`; that is, whether `sseq1` matches every element
|
365
|
+
# `sseq2` matches.
|
366
|
+
#
|
367
|
+
# Both `sseq1` and `sseq2` are of the form
|
368
|
+
# `SimpleSelector (String SimpleSelector)* String*`, although selectors
|
369
|
+
# with a trailing operator are considered to be neither superselectors nor
|
370
|
+
# subselectors.
|
261
371
|
#
|
262
|
-
# @param sseq1 [Array<
|
263
|
-
# @param sseq2 [Array<
|
372
|
+
# @param sseq1 [Array<SimpleSequence or String>]
|
373
|
+
# @param sseq2 [Array<SimpleSequence or String>]
|
264
374
|
# @return [Boolean]
|
265
375
|
def subweave_superselector?(sseq1, sseq2)
|
376
|
+
sseq1 = sseq1.reject {|e| e == "\n"}
|
377
|
+
sseq2 = sseq2.reject {|e| e == "\n"}
|
378
|
+
# Selectors with trailing operators are neither superselectors nor
|
379
|
+
# subselectors.
|
380
|
+
return if sseq1.last.is_a?(String) || sseq2.last.is_a?(String)
|
266
381
|
if sseq1.size > 1
|
267
382
|
# More complex selectors are never superselectors of less complex ones
|
268
383
|
return unless sseq2.size > 1
|
269
384
|
# .foo ~ .bar is a superselector of .foo + .bar
|
270
385
|
return unless sseq1[1] == "~" ? sseq2[1] != ">" : sseq2[1] == sseq1[1]
|
271
386
|
return unless sseq1.first.superselector?(sseq2.first)
|
272
|
-
return true if sseq1.size == 2
|
273
|
-
return false if sseq2.size == 2
|
274
387
|
return subweave_superselector?(sseq1[2..-1], sseq2[2..-1])
|
275
388
|
elsif sseq2.size > 1
|
276
389
|
return true if sseq2[1] == ">" && sseq1.first.superselector?(sseq2.first)
|
277
|
-
return false if sseq2.size == 2
|
278
390
|
return subweave_superselector?(sseq1, sseq2[2..-1])
|
279
391
|
else
|
280
392
|
sseq1.first.superselector?(sseq2.first)
|
@@ -168,7 +168,8 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
168
168
|
def visit_mixin(node)
|
169
169
|
unless node.args.empty? && node.keywords.empty?
|
170
170
|
args = node.args.map {|a| a.to_sass(@options)}.join(", ")
|
171
|
-
keywords = node.keywords
|
171
|
+
keywords = Sass::Util.hash_to_a(node.keywords).
|
172
|
+
map {|k, v| "$#{dasherize(k)}: #{v.to_sass(@options)}"}.join(', ')
|
172
173
|
arglist = "(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})"
|
173
174
|
end
|
174
175
|
"#{tab_str}#{@format == :sass ? '+' : '@include '}#{dasherize(node.name)}#{arglist}#{node.has_children ? yield : semi}\n"
|
@@ -52,12 +52,27 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
52
52
|
def visit_root(node)
|
53
53
|
yield
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
55
|
+
if parent.nil?
|
56
|
+
# In Ruby 1.9 we can make all @charset nodes invisible
|
57
|
+
# and infer the final @charset from the encoding of the final string.
|
58
|
+
if Sass::Util.ruby1_8?
|
59
|
+
charset = node.children.find {|c| c.is_a?(Sass::Tree::CharsetNode)}
|
60
|
+
node.children.reject! {|c| c.is_a?(Sass::Tree::CharsetNode)}
|
61
|
+
node.children.unshift charset if charset
|
62
|
+
end
|
63
|
+
|
64
|
+
imports = Sass::Util.extract!(node.children) do |c|
|
65
|
+
c.is_a?(Sass::Tree::DirectiveNode) && !c.is_a?(Sass::Tree::MediaNode) &&
|
66
|
+
c.resolved_value =~ /^@import /i
|
67
|
+
end
|
68
|
+
charset_and_index = Sass::Util.ruby1_8? &&
|
69
|
+
node.children.each_with_index.find {|c, _| c.is_a?(Sass::Tree::CharsetNode)}
|
70
|
+
if charset_and_index
|
71
|
+
index = charset_and_index.last
|
72
|
+
node.children = node.children[0..index] + imports + node.children[index+1..-1]
|
73
|
+
else
|
74
|
+
node.children = imports + node.children
|
75
|
+
end
|
61
76
|
end
|
62
77
|
|
63
78
|
return node, @extends
|
@@ -247,6 +247,8 @@ END
|
|
247
247
|
# Runs SassScript interpolation in the selector,
|
248
248
|
# and then parses the result into a {Sass::Selector::CommaSequence}.
|
249
249
|
def visit_rule(node)
|
250
|
+
rule = node.rule
|
251
|
+
rule = rule.map {|e| e.is_a?(String) && e != ' ' ? e.strip : e} if node.style == :compressed
|
250
252
|
parser = Sass::SCSS::StaticParser.new(run_interp(node.rule), node.filename, node.line)
|
251
253
|
node.parsed_rules ||= parser.parse_selector
|
252
254
|
if node.options[:trace_selectors]
|
@@ -67,8 +67,10 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def visit_directive(node)
|
70
|
+
was_in_directive = @in_directive
|
70
71
|
return node.resolved_value + ";" unless node.has_children
|
71
72
|
return node.resolved_value + " {}" if node.children.empty?
|
73
|
+
@in_directive = @in_directive || !node.is_a?(Sass::Tree::MediaNode)
|
72
74
|
result = if node.style == :compressed
|
73
75
|
"#{node.resolved_value}{"
|
74
76
|
else
|
@@ -101,6 +103,8 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
101
103
|
else
|
102
104
|
(node.style == :expanded ? "\n" : " ") + "}\n"
|
103
105
|
end
|
106
|
+
ensure
|
107
|
+
@in_directive = was_in_directive
|
104
108
|
end
|
105
109
|
|
106
110
|
def visit_media(node)
|
@@ -133,7 +137,11 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
133
137
|
joined_rules = node.resolved_rules.members.map do |seq|
|
134
138
|
next if seq.has_placeholder?
|
135
139
|
rule_part = seq.to_a.join
|
136
|
-
|
140
|
+
if node.style == :compressed
|
141
|
+
rule_part.gsub!(/([^,])\s*\n\s*/m, '\1 ')
|
142
|
+
rule_part.gsub!(/\s*([,+>])\s*/m, '\1')
|
143
|
+
rule_part.strip!
|
144
|
+
end
|
137
145
|
rule_part
|
138
146
|
end.compact.join(rule_separator)
|
139
147
|
|
@@ -145,7 +153,7 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
145
153
|
old_spaces = ' ' * @tabs
|
146
154
|
spaces = ' ' * (@tabs + 1)
|
147
155
|
if node.style != :compressed
|
148
|
-
if node.options[:debug_info]
|
156
|
+
if node.options[:debug_info] && !@in_directive
|
149
157
|
to_return << visit(debug_info_rule(node.debug_info, node.options)) << "\n"
|
150
158
|
elsif node.options[:trace_selectors]
|
151
159
|
to_return << "#{old_spaces}/* "
|
@@ -191,7 +199,7 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
191
199
|
|
192
200
|
def debug_info_rule(debug_info, options)
|
193
201
|
node = Sass::Tree::DirectiveNode.resolved("@media -sass-debug-info")
|
194
|
-
debug_info.map {|k, v| [k.to_s, v.to_s]}.
|
202
|
+
Sass::Util.hash_to_a(debug_info.map {|k, v| [k.to_s, v.to_s]}).each do |k, v|
|
195
203
|
rule = Sass::Tree::RuleNode.new([""])
|
196
204
|
rule.resolved_rules = Sass::Selector::CommaSequence.new(
|
197
205
|
[Sass::Selector::Sequence.new(
|
data/lib/sass/util.rb
CHANGED
@@ -218,6 +218,20 @@ module Sass
|
|
218
218
|
lcs_backtrace(lcs_table(x, y, &block), x, y, x.size-1, y.size-1, &block)
|
219
219
|
end
|
220
220
|
|
221
|
+
# Converts a Hash to an Array. This is usually identical to `Hash#to_a`,
|
222
|
+
# with the following exceptions:
|
223
|
+
#
|
224
|
+
# * In Ruby 1.8, `Hash#to_a` is not deterministically ordered, but this is.
|
225
|
+
# * In Ruby 1.9 when running tests, this is ordered in the same way it would
|
226
|
+
# be under Ruby 1.8 (sorted key order rather than insertion order).
|
227
|
+
#
|
228
|
+
# @param hash [Hash]
|
229
|
+
# @return [Array]
|
230
|
+
def hash_to_a(hash)
|
231
|
+
return hash.to_a unless ruby1_8? || defined?(Test::Unit)
|
232
|
+
return hash.sort_by {|k, v| k}
|
233
|
+
end
|
234
|
+
|
221
235
|
# Returns information about the caller of the previous method.
|
222
236
|
#
|
223
237
|
# @param entry [String] An entry in the `#caller` list, or a similarly formatted string
|
@@ -561,6 +575,24 @@ MSG
|
|
561
575
|
ruby1_8? ? enum.enum_slice(n) : enum.each_slice(n)
|
562
576
|
end
|
563
577
|
|
578
|
+
# Destructively removes all elements from an array that match a block, and
|
579
|
+
# returns the removed elements.
|
580
|
+
#
|
581
|
+
# @param array [Array] The array from which to remove elements.
|
582
|
+
# @yield [el] Called for each element.
|
583
|
+
# @yieldparam el [*] The element to test.
|
584
|
+
# @yieldreturn [Boolean] Whether or not to extract the element.
|
585
|
+
# @return [Array] The extracted elements.
|
586
|
+
def extract!(array)
|
587
|
+
out = []
|
588
|
+
array.reject! do |e|
|
589
|
+
next false unless yield e
|
590
|
+
out << e
|
591
|
+
true
|
592
|
+
end
|
593
|
+
out
|
594
|
+
end
|
595
|
+
|
564
596
|
# Returns the ASCII code of the given character.
|
565
597
|
#
|
566
598
|
# @param c [String] All characters but the first are ignored.
|
data/test/sass/engine_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# -*- coding: utf-8 -*-
|
3
|
-
require 'test_helper'
|
4
|
-
require '
|
3
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
4
|
+
require File.dirname(__FILE__) + '/test_helper'
|
5
5
|
require 'sass/engine'
|
6
6
|
require 'stringio'
|
7
7
|
require 'mock_importer'
|
@@ -1028,6 +1028,23 @@ foo
|
|
1028
1028
|
SASS
|
1029
1029
|
end
|
1030
1030
|
|
1031
|
+
def test_debug_info_in_keyframes
|
1032
|
+
assert_equal(<<CSS, render(<<SASS, :debug_info => true))
|
1033
|
+
@-webkit-keyframes warm {
|
1034
|
+
from {
|
1035
|
+
color: black; }
|
1036
|
+
|
1037
|
+
to {
|
1038
|
+
color: red; } }
|
1039
|
+
CSS
|
1040
|
+
@-webkit-keyframes warm
|
1041
|
+
from
|
1042
|
+
color: black
|
1043
|
+
to
|
1044
|
+
color: red
|
1045
|
+
SASS
|
1046
|
+
end
|
1047
|
+
|
1031
1048
|
def test_empty_first_line
|
1032
1049
|
assert_equal("#a {\n b: c; }\n", render("#a\n\n b: c"))
|
1033
1050
|
end
|
@@ -2562,6 +2579,15 @@ CSS
|
|
2562
2579
|
SASS
|
2563
2580
|
end
|
2564
2581
|
|
2582
|
+
def test_selector_compression
|
2583
|
+
assert_equal <<CSS, render(<<SASS, :style => :compressed)
|
2584
|
+
a>b,c+d,:-moz-any(e,f,g){h:i}
|
2585
|
+
CSS
|
2586
|
+
a > b, c + d, :-moz-any(e, f, g)
|
2587
|
+
h: i
|
2588
|
+
SASS
|
2589
|
+
end
|
2590
|
+
|
2565
2591
|
# Encodings
|
2566
2592
|
|
2567
2593
|
unless Sass::Util.ruby1_8?
|
data/test/sass/extend_test.rb
CHANGED
@@ -1165,6 +1165,70 @@ SCSS
|
|
1165
1165
|
CSS
|
1166
1166
|
.baz.foo {a: b}
|
1167
1167
|
foo > bar {@extend .foo}
|
1168
|
+
SCSS
|
1169
|
+
|
1170
|
+
assert_equal <<CSS, render(<<SCSS)
|
1171
|
+
.baz > .foo, .baz > .bar {
|
1172
|
+
a: b; }
|
1173
|
+
CSS
|
1174
|
+
.baz > {
|
1175
|
+
.foo {a: b}
|
1176
|
+
.bar {@extend .foo}
|
1177
|
+
}
|
1178
|
+
SCSS
|
1179
|
+
|
1180
|
+
assert_equal <<CSS, render(<<SCSS)
|
1181
|
+
.foo .bar, .foo > .baz {
|
1182
|
+
a: b; }
|
1183
|
+
CSS
|
1184
|
+
.foo {
|
1185
|
+
.bar {a: b}
|
1186
|
+
> .baz {@extend .bar}
|
1187
|
+
}
|
1188
|
+
SCSS
|
1189
|
+
|
1190
|
+
assert_equal <<CSS, render(<<SCSS)
|
1191
|
+
.foo .bar, .foo .bip > .baz {
|
1192
|
+
a: b; }
|
1193
|
+
CSS
|
1194
|
+
.foo {
|
1195
|
+
.bar {a: b}
|
1196
|
+
.bip > .baz {@extend .bar}
|
1197
|
+
}
|
1198
|
+
SCSS
|
1199
|
+
|
1200
|
+
assert_equal <<CSS, render(<<SCSS)
|
1201
|
+
.foo .bip .bar, .foo .bip .foo > .baz {
|
1202
|
+
a: b; }
|
1203
|
+
CSS
|
1204
|
+
.foo {
|
1205
|
+
.bip .bar {a: b}
|
1206
|
+
> .baz {@extend .bar}
|
1207
|
+
}
|
1208
|
+
SCSS
|
1209
|
+
|
1210
|
+
assert_equal <<CSS, render(<<SCSS)
|
1211
|
+
.foo > .bar, .foo > .bip + .baz {
|
1212
|
+
a: b; }
|
1213
|
+
CSS
|
1214
|
+
.foo > .bar {a: b}
|
1215
|
+
.bip + .baz {@extend .bar}
|
1216
|
+
SCSS
|
1217
|
+
|
1218
|
+
assert_equal <<CSS, render(<<SCSS)
|
1219
|
+
.foo + .bar, .bip > .foo + .baz {
|
1220
|
+
a: b; }
|
1221
|
+
CSS
|
1222
|
+
.foo + .bar {a: b}
|
1223
|
+
.bip > .baz {@extend .bar}
|
1224
|
+
SCSS
|
1225
|
+
|
1226
|
+
assert_equal <<CSS, render(<<SCSS)
|
1227
|
+
.foo > .bar, .bip.foo > .baz {
|
1228
|
+
a: b; }
|
1229
|
+
CSS
|
1230
|
+
.foo > .bar {a: b}
|
1231
|
+
.bip > .baz {@extend .bar}
|
1168
1232
|
SCSS
|
1169
1233
|
end
|
1170
1234
|
|
@@ -1186,7 +1250,7 @@ SCSS
|
|
1186
1250
|
|
1187
1251
|
def test_nested_extender_with_hacky_selector
|
1188
1252
|
assert_equal <<CSS, render(<<SCSS)
|
1189
|
-
.baz .foo, .baz foo + > > + bar {
|
1253
|
+
.baz .foo, .baz foo + > > + bar, foo .baz + > > + bar {
|
1190
1254
|
a: b; }
|
1191
1255
|
CSS
|
1192
1256
|
.baz .foo {a: b}
|
@@ -1194,7 +1258,7 @@ foo + > > + bar {@extend .foo}
|
|
1194
1258
|
SCSS
|
1195
1259
|
|
1196
1260
|
assert_equal <<CSS, render(<<SCSS)
|
1197
|
-
.baz .foo,
|
1261
|
+
.baz .foo, > > .baz bar {
|
1198
1262
|
a: b; }
|
1199
1263
|
CSS
|
1200
1264
|
.baz .foo {a: b}
|
@@ -1223,6 +1287,402 @@ CSS
|
|
1223
1287
|
SCSS
|
1224
1288
|
end
|
1225
1289
|
|
1290
|
+
# Combinator Unification
|
1291
|
+
|
1292
|
+
def test_combinator_unification_for_hacky_combinators
|
1293
|
+
assert_equal <<CSS, render(<<SCSS)
|
1294
|
+
.a > + x, .a .b > + y, .b .a > + y {
|
1295
|
+
a: b; }
|
1296
|
+
CSS
|
1297
|
+
.a > + x {a: b}
|
1298
|
+
.b y {@extend x}
|
1299
|
+
SCSS
|
1300
|
+
|
1301
|
+
assert_equal <<CSS, render(<<SCSS)
|
1302
|
+
.a x, .a .b > + y, .b .a > + y {
|
1303
|
+
a: b; }
|
1304
|
+
CSS
|
1305
|
+
.a x {a: b}
|
1306
|
+
.b > + y {@extend x}
|
1307
|
+
SCSS
|
1308
|
+
|
1309
|
+
assert_equal <<CSS, render(<<SCSS)
|
1310
|
+
.a > + x, .a .b > + y, .b .a > + y {
|
1311
|
+
a: b; }
|
1312
|
+
CSS
|
1313
|
+
.a > + x {a: b}
|
1314
|
+
.b > + y {@extend x}
|
1315
|
+
SCSS
|
1316
|
+
|
1317
|
+
assert_equal <<CSS, render(<<SCSS)
|
1318
|
+
.a ~ > + x, .a .b ~ > + y, .b .a ~ > + y {
|
1319
|
+
a: b; }
|
1320
|
+
CSS
|
1321
|
+
.a ~ > + x {a: b}
|
1322
|
+
.b > + y {@extend x}
|
1323
|
+
SCSS
|
1324
|
+
|
1325
|
+
assert_equal <<CSS, render(<<SCSS)
|
1326
|
+
.a + > x {
|
1327
|
+
a: b; }
|
1328
|
+
CSS
|
1329
|
+
.a + > x {a: b}
|
1330
|
+
.b > + y {@extend x}
|
1331
|
+
SCSS
|
1332
|
+
|
1333
|
+
assert_equal <<CSS, render(<<SCSS)
|
1334
|
+
.a + > x {
|
1335
|
+
a: b; }
|
1336
|
+
CSS
|
1337
|
+
.a + > x {a: b}
|
1338
|
+
.b > + y {@extend x}
|
1339
|
+
SCSS
|
1340
|
+
|
1341
|
+
assert_equal <<CSS, render(<<SCSS)
|
1342
|
+
.a ~ > + .b > x, .a .c ~ > + .d.b > y, .c .a ~ > + .d.b > y {
|
1343
|
+
a: b; }
|
1344
|
+
CSS
|
1345
|
+
.a ~ > + .b > x {a: b}
|
1346
|
+
.c > + .d > y {@extend x}
|
1347
|
+
SCSS
|
1348
|
+
end
|
1349
|
+
|
1350
|
+
def test_combinator_unification_double_tilde
|
1351
|
+
assert_equal <<CSS, render(<<SCSS)
|
1352
|
+
.a.b ~ x, .a.b ~ y {
|
1353
|
+
a: b; }
|
1354
|
+
CSS
|
1355
|
+
.a.b ~ x {a: b}
|
1356
|
+
.a ~ y {@extend x}
|
1357
|
+
SCSS
|
1358
|
+
|
1359
|
+
assert_equal <<CSS, render(<<SCSS)
|
1360
|
+
.a ~ x, .a.b ~ y {
|
1361
|
+
a: b; }
|
1362
|
+
CSS
|
1363
|
+
.a ~ x {a: b}
|
1364
|
+
.a.b ~ y {@extend x}
|
1365
|
+
SCSS
|
1366
|
+
|
1367
|
+
assert_equal <<CSS, render(<<SCSS)
|
1368
|
+
.a ~ x, .a ~ .b ~ y, .b ~ .a ~ y, .b.a ~ y {
|
1369
|
+
a: b; }
|
1370
|
+
CSS
|
1371
|
+
.a ~ x {a: b}
|
1372
|
+
.b ~ y {@extend x}
|
1373
|
+
SCSS
|
1374
|
+
|
1375
|
+
assert_equal <<CSS, render(<<SCSS)
|
1376
|
+
a.a ~ x, a.a ~ b.b ~ y, b.b ~ a.a ~ y {
|
1377
|
+
a: b; }
|
1378
|
+
CSS
|
1379
|
+
a.a ~ x {a: b}
|
1380
|
+
b.b ~ y {@extend x}
|
1381
|
+
SCSS
|
1382
|
+
end
|
1383
|
+
|
1384
|
+
def test_combinator_unification_tilde_plus
|
1385
|
+
assert_equal <<CSS, render(<<SCSS)
|
1386
|
+
.a.b + x, .a.b + y {
|
1387
|
+
a: b; }
|
1388
|
+
CSS
|
1389
|
+
.a.b + x {a: b}
|
1390
|
+
.a ~ y {@extend x}
|
1391
|
+
SCSS
|
1392
|
+
|
1393
|
+
assert_equal <<CSS, render(<<SCSS)
|
1394
|
+
.a + x, .a.b ~ .a + y, .a.b + y {
|
1395
|
+
a: b; }
|
1396
|
+
CSS
|
1397
|
+
.a + x {a: b}
|
1398
|
+
.a.b ~ y {@extend x}
|
1399
|
+
SCSS
|
1400
|
+
|
1401
|
+
assert_equal <<CSS, render(<<SCSS)
|
1402
|
+
.a + x, .b ~ .a + y, .b.a + y {
|
1403
|
+
a: b; }
|
1404
|
+
CSS
|
1405
|
+
.a + x {a: b}
|
1406
|
+
.b ~ y {@extend x}
|
1407
|
+
SCSS
|
1408
|
+
|
1409
|
+
assert_equal <<CSS, render(<<SCSS)
|
1410
|
+
a.a + x, b.b ~ a.a + y {
|
1411
|
+
a: b; }
|
1412
|
+
CSS
|
1413
|
+
a.a + x {a: b}
|
1414
|
+
b.b ~ y {@extend x}
|
1415
|
+
SCSS
|
1416
|
+
|
1417
|
+
assert_equal <<CSS, render(<<SCSS)
|
1418
|
+
.a.b ~ x, .a.b ~ .a + y, .a.b + y {
|
1419
|
+
a: b; }
|
1420
|
+
CSS
|
1421
|
+
.a.b ~ x {a: b}
|
1422
|
+
.a + y {@extend x}
|
1423
|
+
SCSS
|
1424
|
+
|
1425
|
+
assert_equal <<CSS, render(<<SCSS)
|
1426
|
+
.a ~ x, .a.b + y {
|
1427
|
+
a: b; }
|
1428
|
+
CSS
|
1429
|
+
.a ~ x {a: b}
|
1430
|
+
.a.b + y {@extend x}
|
1431
|
+
SCSS
|
1432
|
+
|
1433
|
+
assert_equal <<CSS, render(<<SCSS)
|
1434
|
+
.a ~ x, .a ~ .b + y, .a.b + y {
|
1435
|
+
a: b; }
|
1436
|
+
CSS
|
1437
|
+
.a ~ x {a: b}
|
1438
|
+
.b + y {@extend x}
|
1439
|
+
SCSS
|
1440
|
+
|
1441
|
+
assert_equal <<CSS, render(<<SCSS)
|
1442
|
+
a.a ~ x, a.a ~ b.b + y {
|
1443
|
+
a: b; }
|
1444
|
+
CSS
|
1445
|
+
a.a ~ x {a: b}
|
1446
|
+
b.b + y {@extend x}
|
1447
|
+
SCSS
|
1448
|
+
end
|
1449
|
+
|
1450
|
+
def test_combinator_unification_angle_sibling
|
1451
|
+
assert_equal <<CSS, render(<<SCSS)
|
1452
|
+
.a > x, .a > .b ~ y {
|
1453
|
+
a: b; }
|
1454
|
+
CSS
|
1455
|
+
.a > x {a: b}
|
1456
|
+
.b ~ y {@extend x}
|
1457
|
+
SCSS
|
1458
|
+
|
1459
|
+
assert_equal <<CSS, render(<<SCSS)
|
1460
|
+
.a > x, .a > .b + y {
|
1461
|
+
a: b; }
|
1462
|
+
CSS
|
1463
|
+
.a > x {a: b}
|
1464
|
+
.b + y {@extend x}
|
1465
|
+
SCSS
|
1466
|
+
|
1467
|
+
assert_equal <<CSS, render(<<SCSS)
|
1468
|
+
.a ~ x, .b > .a ~ y {
|
1469
|
+
a: b; }
|
1470
|
+
CSS
|
1471
|
+
.a ~ x {a: b}
|
1472
|
+
.b > y {@extend x}
|
1473
|
+
SCSS
|
1474
|
+
|
1475
|
+
assert_equal <<CSS, render(<<SCSS)
|
1476
|
+
.a + x, .b > .a + y {
|
1477
|
+
a: b; }
|
1478
|
+
CSS
|
1479
|
+
.a + x {a: b}
|
1480
|
+
.b > y {@extend x}
|
1481
|
+
SCSS
|
1482
|
+
end
|
1483
|
+
|
1484
|
+
def test_combinator_unification_double_angle
|
1485
|
+
assert_equal <<CSS, render(<<SCSS)
|
1486
|
+
.a.b > x, .b.a > y {
|
1487
|
+
a: b; }
|
1488
|
+
CSS
|
1489
|
+
.a.b > x {a: b}
|
1490
|
+
.b > y {@extend x}
|
1491
|
+
SCSS
|
1492
|
+
|
1493
|
+
assert_equal <<CSS, render(<<SCSS)
|
1494
|
+
.a > x, .a.b > y {
|
1495
|
+
a: b; }
|
1496
|
+
CSS
|
1497
|
+
.a > x {a: b}
|
1498
|
+
.a.b > y {@extend x}
|
1499
|
+
SCSS
|
1500
|
+
|
1501
|
+
assert_equal <<CSS, render(<<SCSS)
|
1502
|
+
.a > x, .b.a > y {
|
1503
|
+
a: b; }
|
1504
|
+
CSS
|
1505
|
+
.a > x {a: b}
|
1506
|
+
.b > y {@extend x}
|
1507
|
+
SCSS
|
1508
|
+
|
1509
|
+
assert_equal <<CSS, render(<<SCSS)
|
1510
|
+
a.a > x {
|
1511
|
+
a: b; }
|
1512
|
+
CSS
|
1513
|
+
a.a > x {a: b}
|
1514
|
+
b.b > y {@extend x}
|
1515
|
+
SCSS
|
1516
|
+
end
|
1517
|
+
|
1518
|
+
def test_combinator_unification_double_plus
|
1519
|
+
assert_equal <<CSS, render(<<SCSS)
|
1520
|
+
.a.b + x, .b.a + y {
|
1521
|
+
a: b; }
|
1522
|
+
CSS
|
1523
|
+
.a.b + x {a: b}
|
1524
|
+
.b + y {@extend x}
|
1525
|
+
SCSS
|
1526
|
+
|
1527
|
+
assert_equal <<CSS, render(<<SCSS)
|
1528
|
+
.a + x, .a.b + y {
|
1529
|
+
a: b; }
|
1530
|
+
CSS
|
1531
|
+
.a + x {a: b}
|
1532
|
+
.a.b + y {@extend x}
|
1533
|
+
SCSS
|
1534
|
+
|
1535
|
+
assert_equal <<CSS, render(<<SCSS)
|
1536
|
+
.a + x, .b.a + y {
|
1537
|
+
a: b; }
|
1538
|
+
CSS
|
1539
|
+
.a + x {a: b}
|
1540
|
+
.b + y {@extend x}
|
1541
|
+
SCSS
|
1542
|
+
|
1543
|
+
assert_equal <<CSS, render(<<SCSS)
|
1544
|
+
a.a + x {
|
1545
|
+
a: b; }
|
1546
|
+
CSS
|
1547
|
+
a.a + x {a: b}
|
1548
|
+
b.b + y {@extend x}
|
1549
|
+
SCSS
|
1550
|
+
end
|
1551
|
+
|
1552
|
+
def test_combinator_unification_angle_space
|
1553
|
+
assert_equal <<CSS, render(<<SCSS)
|
1554
|
+
.a.b > x, .a.b > y {
|
1555
|
+
a: b; }
|
1556
|
+
CSS
|
1557
|
+
.a.b > x {a: b}
|
1558
|
+
.a y {@extend x}
|
1559
|
+
SCSS
|
1560
|
+
|
1561
|
+
assert_equal <<CSS, render(<<SCSS)
|
1562
|
+
.a > x, .a.b .a > y {
|
1563
|
+
a: b; }
|
1564
|
+
CSS
|
1565
|
+
.a > x {a: b}
|
1566
|
+
.a.b y {@extend x}
|
1567
|
+
SCSS
|
1568
|
+
|
1569
|
+
assert_equal <<CSS, render(<<SCSS)
|
1570
|
+
.a > x, .b .a > y {
|
1571
|
+
a: b; }
|
1572
|
+
CSS
|
1573
|
+
.a > x {a: b}
|
1574
|
+
.b y {@extend x}
|
1575
|
+
SCSS
|
1576
|
+
|
1577
|
+
assert_equal <<CSS, render(<<SCSS)
|
1578
|
+
.a.b x, .a.b .a > y {
|
1579
|
+
a: b; }
|
1580
|
+
CSS
|
1581
|
+
.a.b x {a: b}
|
1582
|
+
.a > y {@extend x}
|
1583
|
+
SCSS
|
1584
|
+
|
1585
|
+
assert_equal <<CSS, render(<<SCSS)
|
1586
|
+
.a x, .a.b > y {
|
1587
|
+
a: b; }
|
1588
|
+
CSS
|
1589
|
+
.a x {a: b}
|
1590
|
+
.a.b > y {@extend x}
|
1591
|
+
SCSS
|
1592
|
+
|
1593
|
+
assert_equal <<CSS, render(<<SCSS)
|
1594
|
+
.a x, .a .b > y {
|
1595
|
+
a: b; }
|
1596
|
+
CSS
|
1597
|
+
.a x {a: b}
|
1598
|
+
.b > y {@extend x}
|
1599
|
+
SCSS
|
1600
|
+
end
|
1601
|
+
|
1602
|
+
def test_combinator_unification_plus_space
|
1603
|
+
assert_equal <<CSS, render(<<SCSS)
|
1604
|
+
.a.b + x, .a .a.b + y {
|
1605
|
+
a: b; }
|
1606
|
+
CSS
|
1607
|
+
.a.b + x {a: b}
|
1608
|
+
.a y {@extend x}
|
1609
|
+
SCSS
|
1610
|
+
|
1611
|
+
assert_equal <<CSS, render(<<SCSS)
|
1612
|
+
.a + x, .a.b .a + y {
|
1613
|
+
a: b; }
|
1614
|
+
CSS
|
1615
|
+
.a + x {a: b}
|
1616
|
+
.a.b y {@extend x}
|
1617
|
+
SCSS
|
1618
|
+
|
1619
|
+
assert_equal <<CSS, render(<<SCSS)
|
1620
|
+
.a + x, .b .a + y {
|
1621
|
+
a: b; }
|
1622
|
+
CSS
|
1623
|
+
.a + x {a: b}
|
1624
|
+
.b y {@extend x}
|
1625
|
+
SCSS
|
1626
|
+
|
1627
|
+
assert_equal <<CSS, render(<<SCSS)
|
1628
|
+
.a.b x, .a.b .a + y {
|
1629
|
+
a: b; }
|
1630
|
+
CSS
|
1631
|
+
.a.b x {a: b}
|
1632
|
+
.a + y {@extend x}
|
1633
|
+
SCSS
|
1634
|
+
|
1635
|
+
assert_equal <<CSS, render(<<SCSS)
|
1636
|
+
.a x, .a .a.b + y {
|
1637
|
+
a: b; }
|
1638
|
+
CSS
|
1639
|
+
.a x {a: b}
|
1640
|
+
.a.b + y {@extend x}
|
1641
|
+
SCSS
|
1642
|
+
|
1643
|
+
assert_equal <<CSS, render(<<SCSS)
|
1644
|
+
.a x, .a .b + y {
|
1645
|
+
a: b; }
|
1646
|
+
CSS
|
1647
|
+
.a x {a: b}
|
1648
|
+
.b + y {@extend x}
|
1649
|
+
SCSS
|
1650
|
+
end
|
1651
|
+
|
1652
|
+
def test_combinator_unification_nested
|
1653
|
+
assert_equal <<CSS, render(<<SCSS)
|
1654
|
+
.a > .b + x, .c.a > .d.b + y {
|
1655
|
+
a: b; }
|
1656
|
+
CSS
|
1657
|
+
.a > .b + x {a: b}
|
1658
|
+
.c > .d + y {@extend x}
|
1659
|
+
SCSS
|
1660
|
+
|
1661
|
+
assert_equal <<CSS, render(<<SCSS)
|
1662
|
+
.a > .b + x, .c.a > .b + y {
|
1663
|
+
a: b; }
|
1664
|
+
CSS
|
1665
|
+
.a > .b + x {a: b}
|
1666
|
+
.c > y {@extend x}
|
1667
|
+
SCSS
|
1668
|
+
end
|
1669
|
+
|
1670
|
+
def test_combinator_unification_with_newlines
|
1671
|
+
assert_equal <<CSS, render(<<SCSS)
|
1672
|
+
.a >
|
1673
|
+
.b
|
1674
|
+
+ x, .c.a > .d.b + y {
|
1675
|
+
a: b; }
|
1676
|
+
CSS
|
1677
|
+
.a >
|
1678
|
+
.b
|
1679
|
+
+ x {a: b}
|
1680
|
+
.c
|
1681
|
+
> .d +
|
1682
|
+
y {@extend x}
|
1683
|
+
SCSS
|
1684
|
+
end
|
1685
|
+
|
1226
1686
|
# Loops
|
1227
1687
|
|
1228
1688
|
def test_extend_self_loop
|
@@ -1431,6 +1891,20 @@ SCSS
|
|
1431
1891
|
|
1432
1892
|
# Regression Tests
|
1433
1893
|
|
1894
|
+
def test_newline_near_combinator
|
1895
|
+
assert_equal <<CSS, render(<<SCSS)
|
1896
|
+
.a +
|
1897
|
+
.b x, .a +
|
1898
|
+
.b .c y, .c .a +
|
1899
|
+
.b y {
|
1900
|
+
a: b; }
|
1901
|
+
CSS
|
1902
|
+
.a +
|
1903
|
+
.b x {a: b}
|
1904
|
+
.c y {@extend x}
|
1905
|
+
SCSS
|
1906
|
+
end
|
1907
|
+
|
1434
1908
|
def test_duplicated_selector_with_newlines
|
1435
1909
|
assert_equal(<<CSS, render(<<SCSS))
|
1436
1910
|
.example-1-1,
|
@@ -1,3 +1,5 @@
|
|
1
|
+
@import url(basic.css);
|
2
|
+
@import url(../results/complex.css);
|
1
3
|
imported { otherconst: hello; myconst: goodbye; pre-mixin: here; }
|
2
4
|
|
3
5
|
body { font: Arial; background: blue; }
|
@@ -22,8 +24,6 @@ body { font: Arial; background: blue; }
|
|
22
24
|
#content.user.show #container.top #column.right { width: 600px; }
|
23
25
|
#content.user.show #container.bottom { background: brown; }
|
24
26
|
|
25
|
-
@import url(basic.css);
|
26
|
-
@import url(../results/complex.css);
|
27
27
|
#foo { background-color: #bbaaff; }
|
28
28
|
|
29
29
|
nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
|
@@ -1,3 +1,5 @@
|
|
1
|
+
@import url(basic.css);
|
2
|
+
@import url(../results/complex.css);
|
1
3
|
imported { otherconst: hello; myconst: goodbye; pre-mixin: here; }
|
2
4
|
|
3
5
|
body { font: Arial; background: blue; }
|
@@ -24,8 +26,6 @@ body { font: Arial; background: blue; }
|
|
24
26
|
#content.user.show #container.top #column.right { width: 600px; }
|
25
27
|
#content.user.show #container.bottom { background: brown; }
|
26
28
|
|
27
|
-
@import url(basic.css);
|
28
|
-
@import url(../results/complex.css);
|
29
29
|
#foo { background-color: #bbaaff; }
|
30
30
|
|
31
31
|
nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
|
@@ -1,3 +1,5 @@
|
|
1
|
+
@import url(basic.css);
|
2
|
+
@import url(../results/complex.css);
|
1
3
|
imported { otherconst: hello; myconst: goodbye; pre-mixin: here; }
|
2
4
|
|
3
5
|
body { font: Arial; background: blue; }
|
@@ -24,8 +26,6 @@ body { font: Arial; background: blue; }
|
|
24
26
|
#content.user.show #container.top #column.right { width: 600px; }
|
25
27
|
#content.user.show #container.bottom { background: brown; }
|
26
28
|
|
27
|
-
@import url(basic.css);
|
28
|
-
@import url(../results/complex.css);
|
29
29
|
#foo { background-color: #bbaaff; }
|
30
30
|
|
31
31
|
nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
|
data/test/sass/script_test.rb
CHANGED
@@ -432,6 +432,11 @@ SASS
|
|
432
432
|
assert_raise_message(Sass::SyntaxError, "wrong number of arguments (1 for 0) for `arg-error'") {resolve("arg-error(1)")}
|
433
433
|
end
|
434
434
|
|
435
|
+
def test_boolean_ops_short_circuit
|
436
|
+
assert_equal "false", resolve("$ie and $ie <= 7", {}, env('ie' => Sass::Script::Bool.new(false)))
|
437
|
+
assert_equal "true", resolve("$ie or $undef", {}, env('ie' => Sass::Script::Bool.new(true)))
|
438
|
+
end
|
439
|
+
|
435
440
|
# Regression Tests
|
436
441
|
|
437
442
|
def test_funcall_has_higher_precedence_than_color_name
|
data/test/sass/scss/scss_test.rb
CHANGED
@@ -1245,11 +1245,11 @@ SCSS
|
|
1245
1245
|
|
1246
1246
|
|
1247
1247
|
def test_newlines_removed_from_selectors_when_compressed
|
1248
|
-
assert_equal <<CSS, render(<<SCSS, :style
|
1248
|
+
assert_equal <<CSS, render(<<SCSS, :style => :compressed)
|
1249
1249
|
z a,z b{display:block}
|
1250
1250
|
CSS
|
1251
|
-
a
|
1252
|
-
b {
|
1251
|
+
a
|
1252
|
+
, b {
|
1253
1253
|
z & {
|
1254
1254
|
display: block;
|
1255
1255
|
}
|
data/test/sass/util_test.rb
CHANGED
@@ -159,6 +159,12 @@ class UtilTest < Test::Unit::TestCase
|
|
159
159
|
enum_cons(%w[foo bar baz], 2).map {|s1, s2| "#{s1}#{s2}"})
|
160
160
|
end
|
161
161
|
|
162
|
+
def test_extract
|
163
|
+
arr = [1, 2, 3, 4, 5]
|
164
|
+
assert_equal([1, 3, 5], extract!(arr) {|e| e % 2 == 1})
|
165
|
+
assert_equal([2, 4], arr)
|
166
|
+
end
|
167
|
+
|
162
168
|
def test_ord
|
163
169
|
assert_equal(102, ord("f"))
|
164
170
|
assert_equal(98, ord("bar"))
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 592303005
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 2
|
9
9
|
- 0
|
10
10
|
- alpha
|
11
|
-
-
|
12
|
-
version: 3.2.0.alpha.
|
11
|
+
- 64
|
12
|
+
version: 3.2.0.alpha.64
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Nathan Weizenbaum
|
@@ -19,7 +19,7 @@ autorequire:
|
|
19
19
|
bindir: bin
|
20
20
|
cert_chain: []
|
21
21
|
|
22
|
-
date: 2012-
|
22
|
+
date: 2012-02-05 00:00:00 -05:00
|
23
23
|
default_executable:
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|
@@ -86,7 +86,7 @@ files:
|
|
86
86
|
- lib/sass/logger.rb
|
87
87
|
- lib/sass/logger/base.rb
|
88
88
|
- lib/sass/logger/log_level.rb
|
89
|
-
- lib/sass/
|
89
|
+
- lib/sass/util.rb
|
90
90
|
- lib/sass/plugin.rb
|
91
91
|
- lib/sass/plugin/compiler.rb
|
92
92
|
- lib/sass/plugin/configuration.rb
|
@@ -163,7 +163,7 @@ files:
|
|
163
163
|
- lib/sass/tree/visitors/to_css.rb
|
164
164
|
- lib/sass/tree/warn_node.rb
|
165
165
|
- lib/sass/tree/while_node.rb
|
166
|
-
- lib/sass/
|
166
|
+
- lib/sass/media.rb
|
167
167
|
- lib/sass/util/multibyte_string_scanner.rb
|
168
168
|
- lib/sass/util/subset_map.rb
|
169
169
|
- lib/sass/version.rb
|