sass 3.2.0.alpha.93 → 3.2.0.alpha.94
Sign up to get free protection for your applications and to get access to all the features.
- data/REVISION +1 -1
- data/VERSION +1 -1
- data/lib/sass/selector/sequence.rb +100 -42
- data/test/sass/extend_test.rb +35 -1
- metadata +4 -4
data/REVISION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
8f4869e608e70d7f468bb463ebfe7a939d834e27
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.0.alpha.
|
1
|
+
3.2.0.alpha.94
|
@@ -76,14 +76,15 @@ module Sass
|
|
76
76
|
# These correspond to a {CommaSequence}'s {CommaSequence#members members array}.
|
77
77
|
# @see CommaSequence#do_extend
|
78
78
|
def do_extend(extends, seen = Set.new)
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
Sass::Util.
|
79
|
+
extended_not_expanded = members.map do |sseq_or_op|
|
80
|
+
next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
|
81
|
+
extended = sseq_or_op.do_extend(extends, seen)
|
82
|
+
choices = extended.map {|seq| seq.members}
|
83
|
+
choices.unshift([sseq_or_op]) unless extended.any? {|seq| seq.superselector?(sseq_or_op)}
|
84
|
+
choices
|
85
|
+
end
|
86
|
+
weaves = Sass::Util.paths(extended_not_expanded).map {|path| weave(path)}
|
87
|
+
Sass::Util.flatten(trim(weaves), 1).map {|p| Sequence.new(p)}
|
87
88
|
end
|
88
89
|
|
89
90
|
# Returns whether or not this selector matches all elements
|
@@ -171,13 +172,13 @@ module Sass
|
|
171
172
|
lcs = Sass::Util.lcs(seq2, seq1) do |s1, s2|
|
172
173
|
next s1 if s1 == s2
|
173
174
|
next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
|
174
|
-
next s2 if
|
175
|
-
next s1 if
|
175
|
+
next s2 if parent_superselector?(s1, s2)
|
176
|
+
next s1 if parent_superselector?(s2, s1)
|
176
177
|
end
|
177
178
|
|
178
179
|
diff = [[init]]
|
179
180
|
until lcs.empty?
|
180
|
-
diff << chunks(seq1, seq2) {|s|
|
181
|
+
diff << chunks(seq1, seq2) {|s| parent_superselector?(s.first, lcs.first)} << [lcs.shift]
|
181
182
|
seq1.shift
|
182
183
|
seq2.shift
|
183
184
|
end
|
@@ -254,9 +255,9 @@ module Sass
|
|
254
255
|
sel1 = seq1.pop
|
255
256
|
sel2 = seq2.pop
|
256
257
|
if op1 == '~' && op2 == '~'
|
257
|
-
if
|
258
|
+
if sel1.superselector?(sel2)
|
258
259
|
res.unshift sel2, '~'
|
259
|
-
elsif
|
260
|
+
elsif sel2.superselector?(sel1)
|
260
261
|
res.unshift sel1, '~'
|
261
262
|
else
|
262
263
|
merged = sel1.unify(sel2.members)
|
@@ -273,7 +274,7 @@ module Sass
|
|
273
274
|
tilde_sel, plus_sel = sel2, sel1
|
274
275
|
end
|
275
276
|
|
276
|
-
if
|
277
|
+
if tilde_sel.superselector?(plus_sel)
|
277
278
|
res.unshift plus_sel, '+'
|
278
279
|
else
|
279
280
|
merged = plus_sel.unify(tilde_sel.members)
|
@@ -297,11 +298,11 @@ module Sass
|
|
297
298
|
end
|
298
299
|
return merge_final_ops(seq1, seq2, res)
|
299
300
|
elsif op1
|
300
|
-
seq2.pop if op1 == '>' && seq2.last &&
|
301
|
+
seq2.pop if op1 == '>' && seq2.last && seq2.last.superselector?(seq1.last)
|
301
302
|
res.unshift seq1.pop, op1
|
302
303
|
return merge_final_ops(seq1, seq2, res)
|
303
304
|
else # op2
|
304
|
-
seq1.pop if op2 == '>' && seq1.last &&
|
305
|
+
seq1.pop if op2 == '>' && seq1.last && seq1.last.superselector?(seq2.last)
|
305
306
|
res.unshift seq2.pop, op2
|
306
307
|
return merge_final_ops(seq1, seq2, res)
|
307
308
|
end
|
@@ -360,36 +361,80 @@ module Sass
|
|
360
361
|
return newseq
|
361
362
|
end
|
362
363
|
|
363
|
-
# Given two sequences
|
364
|
-
# superselector of `
|
365
|
-
# `
|
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.
|
364
|
+
# Given two selector sequences, returns whether `seq1` is a
|
365
|
+
# superselector of `seq2`; that is, whether `seq1` matches every
|
366
|
+
# element `seq2` matches.
|
371
367
|
#
|
372
|
-
# @param
|
373
|
-
# @param
|
368
|
+
# @param seq1 [Array<SimpleSequence or String>]
|
369
|
+
# @param seq2 [Array<SimpleSequence or String>]
|
374
370
|
# @return [Boolean]
|
375
|
-
def
|
376
|
-
|
377
|
-
|
378
|
-
# Selectors with trailing operators are neither
|
379
|
-
# subselectors.
|
380
|
-
return if
|
381
|
-
|
382
|
-
|
383
|
-
|
371
|
+
def _superselector?(seq1, seq2)
|
372
|
+
seq1 = seq1.reject {|e| e == "\n"}
|
373
|
+
seq2 = seq2.reject {|e| e == "\n"}
|
374
|
+
# Selectors with leading or trailing operators are neither
|
375
|
+
# superselectors nor subselectors.
|
376
|
+
return if seq1.last.is_a?(String) || seq2.last.is_a?(String) ||
|
377
|
+
seq1.first.is_a?(String) || seq2.first.is_a?(String)
|
378
|
+
# More complex selectors are never superselectors of less complex ones
|
379
|
+
return if seq1.size > seq2.size
|
380
|
+
return seq1.first.superselector?(seq2.last) if seq1.size == 1
|
381
|
+
|
382
|
+
_, si = Sass::Util.enum_with_index(seq2).find do |e, i|
|
383
|
+
return if i == seq2.size - 1
|
384
|
+
next if e.is_a?(String)
|
385
|
+
seq1.first.superselector?(e)
|
386
|
+
end
|
387
|
+
return unless si
|
388
|
+
|
389
|
+
if seq1[1].is_a?(String)
|
390
|
+
return unless seq2[si+1].is_a?(String)
|
384
391
|
# .foo ~ .bar is a superselector of .foo + .bar
|
385
|
-
return unless
|
386
|
-
return
|
387
|
-
|
388
|
-
|
389
|
-
return
|
390
|
-
return subweave_superselector?(sseq1, sseq2[2..-1])
|
392
|
+
return unless seq1[1] == "~" ? seq2[si+1] != ">" : seq1[1] == seq2[si+1]
|
393
|
+
return _superselector?(seq1[2..-1], seq2[si+2..-1])
|
394
|
+
elsif seq2[si+1].is_a?(String)
|
395
|
+
return unless seq2[si+1] == ">"
|
396
|
+
return _superselector?(seq1[1..-1], seq2[si+2..-1])
|
391
397
|
else
|
392
|
-
|
398
|
+
return _superselector?(seq1[1..-1], seq2[si+1..-1])
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
# Like \{#_superselector?}, but compares the selectors in the
|
403
|
+
# context of parent selectors, as though they shared an implicit
|
404
|
+
# base simple selector. For example, `B` is not normally a
|
405
|
+
# superselector of `B A`, since it doesn't match `A` elements.
|
406
|
+
# However, it is a parent superselector, since `B X` is a
|
407
|
+
# superselector of `B A X`.
|
408
|
+
#
|
409
|
+
# @param seq1 [Array<SimpleSequence or String>]
|
410
|
+
# @param seq2 [Array<SimpleSequence or String>]
|
411
|
+
# @return [Boolean]
|
412
|
+
def parent_superselector?(seq1, seq2)
|
413
|
+
base = Sass::Selector::SimpleSequence.new([Sass::Selector::Placeholder.new('<temp>')])
|
414
|
+
_superselector?(seq1 + [base], seq2 + [base])
|
415
|
+
end
|
416
|
+
|
417
|
+
# Removes redundant selectors from between multiple lists of
|
418
|
+
# selectors. This takes a list of lists of selector sequences;
|
419
|
+
# each individual list is assumed to have no redundancy within
|
420
|
+
# itself. A selector is only removed if it's redundant with a
|
421
|
+
# selector in another list.
|
422
|
+
#
|
423
|
+
# "Redundant" here means that one selector is a superselector of
|
424
|
+
# the other. The more specific selector is removed.
|
425
|
+
#
|
426
|
+
# @param seqses [Array<Array<Array<SimpleSequence or String>>>]
|
427
|
+
# @return [Array<Array<Array<SimpleSequence or String>>>]
|
428
|
+
def trim(seqses)
|
429
|
+
# This is n^2 on the sequences, but only comparing between
|
430
|
+
# separate sequences should limit the quadratic behavior.
|
431
|
+
seqses.map do |seqs1|
|
432
|
+
seqs1.reject do |seq1|
|
433
|
+
seqses.any? do |seqs2|
|
434
|
+
next if seqs1.object_id == seqs2.object_id
|
435
|
+
seqs2.any? {|seq2| _superselector?(seq2, seq1)}
|
436
|
+
end
|
437
|
+
end
|
393
438
|
end
|
394
439
|
end
|
395
440
|
|
@@ -400,6 +445,19 @@ module Sass
|
|
400
445
|
def _eql?(other)
|
401
446
|
other.members.reject {|m| m == "\n"}.eql?(self.members.reject {|m| m == "\n"})
|
402
447
|
end
|
448
|
+
|
449
|
+
private
|
450
|
+
|
451
|
+
def extended_not_expanded_to_s(extended_not_expanded)
|
452
|
+
extended_not_expanded.map do |choices|
|
453
|
+
choices = choices.map do |sel|
|
454
|
+
next sel.first.to_s if sel.size == 1
|
455
|
+
"#{sel.join ' '}"
|
456
|
+
end
|
457
|
+
next choices.first if choices.size == 1 && !choices.include?(' ')
|
458
|
+
"(#{choices.join ', '})"
|
459
|
+
end.join ' '
|
460
|
+
end
|
403
461
|
end
|
404
462
|
end
|
405
463
|
end
|
data/test/sass/extend_test.rb
CHANGED
@@ -1753,7 +1753,7 @@ SCSS
|
|
1753
1753
|
assert_equal <<CSS, render(<<SCSS)
|
1754
1754
|
.bar, .bar .foo {
|
1755
1755
|
a: b; }
|
1756
|
-
.bar .foo
|
1756
|
+
.bar .foo {
|
1757
1757
|
c: d; }
|
1758
1758
|
CSS
|
1759
1759
|
.bar {
|
@@ -2010,6 +2010,40 @@ flip,
|
|
2010
2010
|
SCSS
|
2011
2011
|
end
|
2012
2012
|
|
2013
|
+
def test_extended_parent_and_child_redundancy_elimination
|
2014
|
+
assert_equal <<CSS, render(<<SCSS)
|
2015
|
+
a b, d b, a c, d c {
|
2016
|
+
a: b; }
|
2017
|
+
CSS
|
2018
|
+
a {
|
2019
|
+
b {a: b}
|
2020
|
+
c {@extend b}
|
2021
|
+
}
|
2022
|
+
d {@extend a}
|
2023
|
+
SCSS
|
2024
|
+
end
|
2025
|
+
|
2026
|
+
def test_extend_cross_branch_redundancy_elimination
|
2027
|
+
assert_equal <<CSS, render(<<SCSS)
|
2028
|
+
a c d, b c a d {
|
2029
|
+
a: b; }
|
2030
|
+
CSS
|
2031
|
+
%x c %y {a: b}
|
2032
|
+
a, b {@extend %x}
|
2033
|
+
a d {@extend %y}
|
2034
|
+
SCSS
|
2035
|
+
|
2036
|
+
assert_equal <<CSS, render(<<SCSS)
|
2037
|
+
e a c d, a c e d, e b c a d, b c a e d {
|
2038
|
+
a: b; }
|
2039
|
+
CSS
|
2040
|
+
e %z {a: b}
|
2041
|
+
%x c %y {@extend %z}
|
2042
|
+
a, b {@extend %x}
|
2043
|
+
a d {@extend %y}
|
2044
|
+
SCSS
|
2045
|
+
end
|
2046
|
+
|
2013
2047
|
private
|
2014
2048
|
|
2015
2049
|
def render(sass, options = {})
|
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: 592303009
|
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
|
+
- 94
|
12
|
+
version: 3.2.0.alpha.94
|
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-03-
|
22
|
+
date: 2012-03-14 00:00:00 -04:00
|
23
23
|
default_executable:
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|