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 CHANGED
@@ -1 +1 @@
1
- f19a88c02e1ac7a174ad2ada5cab276a5084fb2e
1
+ 8f4869e608e70d7f468bb463ebfe7a939d834e27
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.0.alpha.93
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
- paths = Sass::Util.paths(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
- Sass::Util.flatten(paths.map {|path| weave(path)}, 1).map {|p| Sequence.new(p)}
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 subweave_superselector?(s1, s2)
175
- next s1 if subweave_superselector?(s2, s1)
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| subweave_superselector?(s.first, lcs.first)} << [lcs.shift]
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 subweave_superselector?([sel1], [sel2])
258
+ if sel1.superselector?(sel2)
258
259
  res.unshift sel2, '~'
259
- elsif subweave_superselector?([sel2], [sel1])
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 subweave_superselector?([tilde_sel], [plus_sel])
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 && subweave_superselector?([seq2.last], [seq1.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 && subweave_superselector?([seq1.last], [seq2.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 of simple selectors, returns whether `sseq1` is a
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.
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 sseq1 [Array<SimpleSequence or String>]
373
- # @param sseq2 [Array<SimpleSequence or String>]
368
+ # @param seq1 [Array<SimpleSequence or String>]
369
+ # @param seq2 [Array<SimpleSequence or String>]
374
370
  # @return [Boolean]
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)
381
- if sseq1.size > 1
382
- # More complex selectors are never superselectors of less complex ones
383
- return unless sseq2.size > 1
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 sseq1[1] == "~" ? sseq2[1] != ">" : sseq2[1] == sseq1[1]
386
- return unless sseq1.first.superselector?(sseq2.first)
387
- return subweave_superselector?(sseq1[2..-1], sseq2[2..-1])
388
- elsif sseq2.size > 1
389
- return true if sseq2[1] == ">" && sseq1.first.superselector?(sseq2.first)
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
- sseq1.first.superselector?(sseq2.first)
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
@@ -1753,7 +1753,7 @@ SCSS
1753
1753
  assert_equal <<CSS, render(<<SCSS)
1754
1754
  .bar, .bar .foo {
1755
1755
  a: b; }
1756
- .bar .foo, .bar .foo .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: 592303015
4
+ hash: 592303009
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 3
8
8
  - 2
9
9
  - 0
10
10
  - alpha
11
- - 93
12
- version: 3.2.0.alpha.93
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-09 00:00:00 -05:00
22
+ date: 2012-03-14 00:00:00 -04:00
23
23
  default_executable:
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency