sass 3.2.0.alpha.93 → 3.2.0.alpha.94
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/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
|