sass 3.2.0.alpha.237 → 3.2.0.alpha.240

Sign up to get free protection for your applications and to get access to all the features.
data/REVISION CHANGED
@@ -1 +1 @@
1
- 167ee67e6a16423e95cf074074aea80ff9c828ca
1
+ e215507545439a84c2b2bc01d454ebab722fe209
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.0.alpha.237
1
+ 3.2.0.alpha.240
@@ -29,6 +29,7 @@ require 'sass/tree/charset_node'
29
29
  require 'sass/tree/visitors/base'
30
30
  require 'sass/tree/visitors/perform'
31
31
  require 'sass/tree/visitors/cssize'
32
+ require 'sass/tree/visitors/extend'
32
33
  require 'sass/tree/visitors/convert'
33
34
  require 'sass/tree/visitors/to_css'
34
35
  require 'sass/tree/visitors/deep_copy'
@@ -452,7 +452,7 @@ MSG
452
452
  def probably_dest_dir?(path)
453
453
  return false unless path
454
454
  return false if colon_path?(path)
455
- return Sass::Util.glob(File.join(path, "*.s[ca]ss")).empty?
455
+ return ::Sass::Util.glob(File.join(path, "*.s[ca]ss")).empty?
456
456
  end
457
457
  end
458
458
 
@@ -595,7 +595,7 @@ END
595
595
  end
596
596
 
597
597
  ext = @options[:from]
598
- Sass::Util.glob("#{@options[:input]}/**/*.#{ext}") do |f|
598
+ ::Sass::Util.glob("#{@options[:input]}/**/*.#{ext}") do |f|
599
599
  output =
600
600
  if @options[:in_place]
601
601
  f
@@ -44,13 +44,16 @@ module Sass
44
44
  # @todo Link this to the reference documentation on `@extend`
45
45
  # when such a thing exists.
46
46
  #
47
- # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
47
+ # @param extends [Sass::Util::SubsetMap{Selector::Simple =>
48
+ # Sass::Tree::Visitors::Cssize::Extend}]
48
49
  # The extensions to perform on this selector
50
+ # @param parent_directives [Array<Sass::Tree::DirectiveNode>]
51
+ # The directives containing this selector.
49
52
  # @return [CommaSequence] A copy of this selector,
50
53
  # with extensions made according to `extends`
51
- def do_extend(extends)
54
+ def do_extend(extends, parent_directives)
52
55
  CommaSequence.new(members.map do |seq|
53
- extended = seq.do_extend(extends)
56
+ extended = seq.do_extend(extends, parent_directives)
54
57
  # First Law of Extend: the result of extending a selector should
55
58
  # always contain the base selector.
56
59
  #
@@ -68,17 +68,20 @@ module Sass
68
68
  # Non-destructively extends this selector with the extensions specified in a hash
69
69
  # (which should come from {Sass::Tree::Visitors::Cssize}).
70
70
  #
71
- # @overload def do_extend(extends)
72
- # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
71
+ # @overload def do_extend(extends, parent_directives)
72
+ # @param extends [Sass::Util::SubsetMap{Selector::Simple =>
73
+ # Sass::Tree::Visitors::Cssize::Extend}]
73
74
  # The extensions to perform on this selector
75
+ # @param parent_directives [Array<Sass::Tree::DirectiveNode>]
76
+ # The directives containing this selector.
74
77
  # @return [Array<Sequence>] A list of selectors generated
75
78
  # by extending this selector with `extends`.
76
79
  # These correspond to a {CommaSequence}'s {CommaSequence#members members array}.
77
80
  # @see CommaSequence#do_extend
78
- def do_extend(extends, seen = Set.new)
81
+ def do_extend(extends, parent_directives, seen = Set.new)
79
82
  extended_not_expanded = members.map do |sseq_or_op|
80
83
  next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
81
- extended = sseq_or_op.do_extend(extends, seen)
84
+ extended = sseq_or_op.do_extend(extends, parent_directives, seen)
82
85
  choices = extended.map {|seq| seq.members}
83
86
  choices.unshift([sseq_or_op]) unless extended.any? {|seq| seq.superselector?(sseq_or_op)}
84
87
  choices
@@ -72,25 +72,29 @@ module Sass
72
72
  # Non-destrucively extends this selector with the extensions specified in a hash
73
73
  # (which should come from {Sass::Tree::Visitors::Cssize}).
74
74
  #
75
- # @overload def do_extend(extends, sources)
76
- # @param extends [{Selector::Simple => Selector::Sequence}]
75
+ # @overload def do_extend(extends, parent_directives)
76
+ # @param extends [{Selector::Simple =>
77
+ # Sass::Tree::Visitors::Cssize::Extend}]
77
78
  # The extensions to perform on this selector
79
+ # @param parent_directives [Array<Sass::Tree::DirectiveNode>]
80
+ # The directives containing this selector.
78
81
  # @return [Array<Sequence>] A list of selectors generated
79
82
  # by extending this selector with `extends`.
80
83
  # @see CommaSequence#do_extend
81
- def do_extend(extends, seen = Set.new)
82
- Sass::Util.group_by_to_a(extends.get(members.to_set)) {|seq, _| seq}.map do |seq, group|
84
+ def do_extend(extends, parent_directives, seen = Set.new)
85
+ Sass::Util.group_by_to_a(extends.get(members.to_set)) {|ex, _| ex.extender}.map do |seq, group|
83
86
  sels = group.map {|_, s| s}.flatten
84
87
  # If A {@extend B} and C {...},
85
88
  # seq is A, sels is B, and self is C
86
89
 
87
90
  self_without_sel = self.members - sels
88
91
  next unless unified = seq.members.last.unify(self_without_sel)
92
+ next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none?
89
93
  new_seq = Sequence.new(seq.members[0...-1] + [unified])
90
94
  new_seq.add_sources!(sources + [seq])
91
95
  [sels, new_seq]
92
96
  end.compact.map do |sels, seq|
93
- seen.include?(sels) ? [] : seq.do_extend(extends, seen + [sels])
97
+ seen.include?(sels) ? [] : seq.do_extend(extends, parent_directives, seen + [sels])
94
98
  end.flatten.uniq
95
99
  end
96
100
 
@@ -154,6 +158,21 @@ module Sass
154
158
 
155
159
  private
156
160
 
161
+ def check_directives_match!(extend, parent_directives)
162
+ dirs1 = extend.directives.map {|d| d.resolved_value}
163
+ dirs2 = parent_directives.map {|d| d.resolved_value}
164
+ return true if Sass::Util.subsequence?(dirs1, dirs2)
165
+
166
+ Sass::Util.sass_warn <<WARNING
167
+ DEPRECATION WARNING on line #{extend.node.line}#{" of #{extend.node.filename}" if extend.node.filename}:
168
+ @extending an outer selector from within #{extend.directives.last.name} is deprecated.
169
+ You may only @extend selectors within the same directive.
170
+ This will be an error in Sass 3.3.
171
+ It can only work once @extend is supported natively in the browser.
172
+ WARNING
173
+ return false
174
+ end
175
+
157
176
  def _hash
158
177
  [base, Sass::Util.set_hash(rest)].hash
159
178
  end
@@ -141,27 +141,6 @@ module Sass
141
141
  "(#{self.class} #{children.map {|c| c.inspect}.join(' ')})"
142
142
  end
143
143
 
144
- # Converts a static CSS tree (e.g. the output of \{Tree::Visitors::Cssize})
145
- # into another static CSS tree,
146
- # with the given extensions applied to all relevant {RuleNode}s.
147
- #
148
- # @todo Link this to the reference documentation on `@extend`
149
- # when such a thing exists.
150
- #
151
- # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
152
- # The extensions to perform on this tree
153
- # @return [Tree::Node] The resulting tree of static CSS nodes.
154
- # @raise [Sass::SyntaxError] Only if there's a programmer error
155
- # and this is not a static CSS tree
156
- def do_extend(extends)
157
- node = dup
158
- node.children = children.map {|c| c.do_extend(extends)}
159
- node
160
- rescue Sass::SyntaxError => e
161
- e.modify_backtrace(:filename => filename, :line => line)
162
- raise e
163
- end
164
-
165
144
  # Iterates through each node in the tree rooted at this node
166
145
  # in a pre-order walk.
167
146
  #
@@ -20,7 +20,7 @@ module Sass
20
20
  result = Visitors::Perform.visit(self)
21
21
  Visitors::CheckNesting.visit(result) # Check again to validate mixins
22
22
  result, extends = Visitors::Cssize.visit(result)
23
- result = result.do_extend(extends) unless extends.empty?
23
+ Visitors::Extend.visit(result, extends)
24
24
  result.to_s
25
25
  end
26
26
  end
@@ -103,15 +103,6 @@ module Sass::Tree
103
103
  last.is_a?(String) && last[-1] == ?,
104
104
  end
105
105
 
106
- # Extends this Rule's selector with the given `extends`.
107
- #
108
- # @see Node#do_extend
109
- def do_extend(extends)
110
- node = dup
111
- node.resolved_rules = resolved_rules.do_extend(extends)
112
- node
113
- end
114
-
115
106
  # A hash that will be associated with this rule in the CSS document
116
107
  # if the {file:SASS_REFERENCE.md#debug_info-option `:debug_info` option} is enabled.
117
108
  # This data is used by e.g. [the FireSass Firebug extension](https://addons.mozilla.org/en-US/firefox/addon/103988).
@@ -71,14 +71,6 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
71
71
  unless is_any_of?(parent, VALID_EXTEND_PARENTS)
72
72
  return "Extend directives may only be used within rules."
73
73
  end
74
-
75
- if directive = @parents.find {|p| p.is_a?(Sass::Tree::DirectiveNode)}
76
- return <<ERR.rstrip
77
- @extend may not be used within directives (e.g. #{directive.name}).
78
-
79
- This will only work once @extend is supported natively in the browser.
80
- ERR
81
- end
82
74
  end
83
75
 
84
76
  def invalid_function_parent?(parent, child)
@@ -81,7 +81,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
81
81
  content.gsub!(/^/, tab_str)
82
82
  content.rstrip + "\n"
83
83
  else
84
- spaces = (' ' * [@tabs - value[/^ */].size, 0].max)
84
+ spaces = (@tab_chars * [@tabs - value[/^ */].size, 0].max)
85
85
  content = if node.type == :silent
86
86
  value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '')
87
87
  else
@@ -12,6 +12,7 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
12
12
  attr_reader :parent
13
13
 
14
14
  def initialize
15
+ @parent_directives = []
15
16
  @extends = Sass::Util::SubsetMap.new
16
17
  end
17
18
 
@@ -38,9 +39,11 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
38
39
  # @yield A block in which the parent is set to `parent`.
39
40
  # @return [Object] The return value of the block.
40
41
  def with_parent(parent)
42
+ @parent_directives.push parent if parent.is_a?(Sass::Tree::DirectiveNode)
41
43
  old_parent, @parent = @parent, parent
42
44
  yield
43
45
  ensure
46
+ @parent_directives.pop if parent.is_a?(Sass::Tree::DirectiveNode)
44
47
  @parent = old_parent
45
48
  end
46
49
 
@@ -81,6 +84,18 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
81
84
  raise e
82
85
  end
83
86
 
87
+ # A simple struct wrapping up information about a single `@extend` instance. A
88
+ # single [ExtendNode] can have multiple Extends if either the parent node or
89
+ # the extended selector is a comma sequence.
90
+ #
91
+ # @attr extender [Array<Sass::Selector::SimpleSequence, String>]
92
+ # The selector of the CSS rule containing the `@extend`.
93
+ # @attr target [Array<Sass::Selector::Simple>] The selector being `@extend`ed.
94
+ # @attr node [Sass::Tree::ExtendNode] The node that produced this extend.
95
+ # @attr directives [Array<Sass::Tree::DirectiveNode>]
96
+ # The directives containing the `@extend`.
97
+ Extend = Struct.new(:extender, :target, :node, :directives)
98
+
84
99
  # Registers an extension in the `@extends` subset map.
85
100
  def visit_extend(node)
86
101
  node.resolved_selector.members.each do |seq|
@@ -101,7 +116,7 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
101
116
  raise Sass::SyntaxError.new("#{seq} can't extend: invalid selector")
102
117
  end
103
118
 
104
- @extends[sel] = seq
119
+ @extends[sel] = Extend.new(seq, sel, node, @parent_directives.dup)
105
120
  end
106
121
  end
107
122
 
@@ -0,0 +1,42 @@
1
+ # A visitor for performing selector inheritance on a static CSS tree.
2
+ #
3
+ # Destructively modifies the tree.
4
+ class Sass::Tree::Visitors::Extend < Sass::Tree::Visitors::Base
5
+ # @param root [Tree::Node] The root node of the tree to visit.
6
+ # @param extends [Sass::Util::SubsetMap{Selector::Simple =>
7
+ # Sass::Tree::Visitors::Cssize::Extend}]
8
+ # The extensions to perform on this tree.
9
+ # @return [Object] The return value of \{#visit} for the root node.
10
+ def self.visit(root, extends)
11
+ return if extends.empty?
12
+ new(extends).send(:visit, root)
13
+ end
14
+
15
+ protected
16
+
17
+ def initialize(extends)
18
+ @parent_directives = []
19
+ @extends = extends
20
+ end
21
+
22
+ # If an exception is raised, this adds proper metadata to the backtrace.
23
+ def visit(node)
24
+ super(node)
25
+ rescue Sass::SyntaxError => e
26
+ e.modify_backtrace(:filename => node.filename, :line => node.line)
27
+ raise e
28
+ end
29
+
30
+ # Keeps track of the current parent directives.
31
+ def visit_children(parent)
32
+ @parent_directives.push parent if parent.is_a?(Sass::Tree::DirectiveNode)
33
+ super
34
+ ensure
35
+ @parent_directives.pop if parent.is_a?(Sass::Tree::DirectiveNode)
36
+ end
37
+
38
+ # Applies the extend to a single rule's selector.
39
+ def visit_rule(node)
40
+ node.resolved_rules = node.resolved_rules.do_extend(@extends, @parent_directives)
41
+ end
42
+ end
@@ -68,13 +68,14 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
68
68
 
69
69
  def visit_directive(node)
70
70
  was_in_directive = @in_directive
71
- return node.resolved_value + ";" unless node.has_children
72
- return node.resolved_value + " {}" if node.children.empty?
71
+ tab_str = ' ' * @tabs
72
+ return tab_str + node.resolved_value + ";" unless node.has_children
73
+ return tab_str + node.resolved_value + " {}" if node.children.empty?
73
74
  @in_directive = @in_directive || !node.is_a?(Sass::Tree::MediaNode)
74
75
  result = if node.style == :compressed
75
76
  "#{node.resolved_value}{"
76
77
  else
77
- "#{' ' * @tabs}#{node.resolved_value} {" + (node.style == :compact ? ' ' : "\n")
78
+ "#{tab_str}#{node.resolved_value} {" + (node.style == :compact ? ' ' : "\n")
78
79
  end
79
80
  was_prop = false
80
81
  first = true
@@ -276,6 +276,23 @@ module Sass
276
276
  "#{name} #{str} must be between #{range.first}#{unit} and #{range.last}#{unit}")
277
277
  end
278
278
 
279
+ # Returns whether or not `seq1` is a subsequence of `seq2`. That is, whether
280
+ # or not `seq2` contains every element in `seq1` in the same order (and
281
+ # possibly more elements besides).
282
+ #
283
+ # @param seq1 [Array]
284
+ # @param seq2 [Array]
285
+ # @return [Boolean]
286
+ def subsequence?(seq1, seq2)
287
+ i = j = 0
288
+ loop do
289
+ return true if i == seq1.size
290
+ return false if j == seq2.size
291
+ i += 1 if seq1[i] == seq2[j]
292
+ j += 1
293
+ end
294
+ end
295
+
279
296
  # Returns information about the caller of the previous method.
280
297
  #
281
298
  # @param entry [String] An entry in the `#caller` list, or a similarly formatted string
@@ -1558,6 +1558,21 @@ SASS
1558
1558
  SCSS
1559
1559
  end
1560
1560
 
1561
+ def test_comment_indentation
1562
+ assert_renders(<<SASS, <<SCSS, :indent => ' ')
1563
+ foo
1564
+ // bar
1565
+ /* baz
1566
+ a: b
1567
+ SASS
1568
+ foo {
1569
+ // bar
1570
+ /* baz */
1571
+ a: b;
1572
+ }
1573
+ SCSS
1574
+ end
1575
+
1561
1576
  private
1562
1577
 
1563
1578
  def assert_sass_to_sass(sass, options = {})
@@ -1580,7 +1595,7 @@ SCSS
1580
1595
  options ||= {}
1581
1596
 
1582
1597
  assert_equal(scss.rstrip, to_scss(in_scss, options.merge(:syntax => :scss)).rstrip,
1583
- "Expected SCSS to transform to #{scss == in_scss ? 'itself' : 'SCSS'}k")
1598
+ "Expected SCSS to transform to #{scss == in_scss ? 'itself' : 'SCSS'}")
1584
1599
  end
1585
1600
 
1586
1601
  def assert_sass_to_scss(scss, sass, options = {})
@@ -146,8 +146,6 @@ MSG
146
146
  "$var: true\n@while $var\n @extend .bar\n $var: false" => ["Extend directives may only be used within rules.", 3],
147
147
  "@for $i from 0 to 1\n @extend .bar" => ["Extend directives may only be used within rules.", 2],
148
148
  "@mixin foo\n @extend .bar\n@include foo" => ["Extend directives may only be used within rules.", 2],
149
- "@media screen\n .bar\n @extend .foo" => "@extend may not be used within directives (e.g. @media).\n\nThis will only work once @extend is supported natively in the browser.",
150
- "@flooblehoof\n .bar\n @extend .foo" => "@extend may not be used within directives (e.g. @flooblehoof).\n\nThis will only work once @extend is supported natively in the browser.",
151
149
  "foo\n &a\n b: c" => ["Invalid CSS after \"&\": expected \"{\", was \"a\"\n\n\"a\" may only be used at the beginning of a selector.", 2],
152
150
  "foo\n &1\n b: c" => ["Invalid CSS after \"&\": expected \"{\", was \"1\"\n\n\"1\" may only be used at the beginning of a selector.", 2],
153
151
  "foo %\n a: b" => ['Invalid CSS after "foo %": expected placeholder name, was ""', 1],
@@ -2724,6 +2722,22 @@ SASS
2724
2722
  SASS
2725
2723
  end
2726
2724
 
2725
+ def test_nested_empty_directive
2726
+ assert_equal <<CSS, render(<<SASS)
2727
+ @media screen {
2728
+ .foo {
2729
+ a: b; }
2730
+
2731
+ @unknown-directive; }
2732
+ CSS
2733
+ @media screen
2734
+ .foo
2735
+ a: b
2736
+
2737
+ @unknown-directive
2738
+ SASS
2739
+ end
2740
+
2727
2741
  # Encodings
2728
2742
 
2729
2743
  unless Sass::Util.ruby1_8?
@@ -795,6 +795,219 @@ CSS
795
795
  SCSS
796
796
  end
797
797
 
798
+ def test_extend_out_of_media
799
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
800
+ DEPRECATION WARNING on line 3 of test_extend_out_of_media_inline.sass:
801
+ @extending an outer selector from within @media is deprecated.
802
+ You may only @extend selectors within the same directive.
803
+ This will be an error in Sass 3.3.
804
+ It can only work once @extend is supported natively in the browser.
805
+ WARN
806
+ .foo {
807
+ a: b; }
808
+ CSS
809
+ .foo {a: b}
810
+ @media screen {
811
+ .bar {@extend .foo}
812
+ }
813
+ SCSS
814
+ end
815
+
816
+ def test_extend_out_of_unknown_directive
817
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
818
+ DEPRECATION WARNING on line 3 of test_extend_out_of_unknown_directive_inline.sass:
819
+ @extending an outer selector from within @flooblehoof is deprecated.
820
+ You may only @extend selectors within the same directive.
821
+ This will be an error in Sass 3.3.
822
+ It can only work once @extend is supported natively in the browser.
823
+ WARN
824
+ .foo {
825
+ a: b; }
826
+
827
+ @flooblehoof {}
828
+ CSS
829
+ .foo {a: b}
830
+ @flooblehoof {
831
+ .bar {@extend .foo}
832
+ }
833
+ SCSS
834
+ end
835
+
836
+ def test_extend_out_of_nested_directives
837
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
838
+ DEPRECATION WARNING on line 4 of test_extend_out_of_nested_directives_inline.sass:
839
+ @extending an outer selector from within @flooblehoof is deprecated.
840
+ You may only @extend selectors within the same directive.
841
+ This will be an error in Sass 3.3.
842
+ It can only work once @extend is supported natively in the browser.
843
+ WARN
844
+ @media screen {
845
+ .foo {
846
+ a: b; }
847
+
848
+ @flooblehoof {} }
849
+ CSS
850
+ @media screen {
851
+ .foo {a: b}
852
+ @flooblehoof {
853
+ .bar {@extend .foo}
854
+ }
855
+ }
856
+ SCSS
857
+ end
858
+
859
+ def test_extend_within_media
860
+ assert_equal(<<CSS, render(<<SCSS))
861
+ @media screen {
862
+ .foo, .bar {
863
+ a: b; } }
864
+ CSS
865
+ @media screen {
866
+ .foo {a: b}
867
+ .bar {@extend .foo}
868
+ }
869
+ SCSS
870
+ end
871
+
872
+ def test_extend_within_unknown_directive
873
+ assert_equal(<<CSS, render(<<SCSS))
874
+ @flooblehoof {
875
+ .foo, .bar {
876
+ a: b; } }
877
+ CSS
878
+ @flooblehoof {
879
+ .foo {a: b}
880
+ .bar {@extend .foo}
881
+ }
882
+ SCSS
883
+ end
884
+
885
+ def test_extend_within_nested_directives
886
+ assert_equal(<<CSS, render(<<SCSS))
887
+ @media screen {
888
+ @flooblehoof {
889
+ .foo, .bar {
890
+ a: b; } } }
891
+ CSS
892
+ @media screen {
893
+ @flooblehoof {
894
+ .foo {a: b}
895
+ .bar {@extend .foo}
896
+ }
897
+ }
898
+ SCSS
899
+ end
900
+
901
+ def test_extend_within_disparate_media
902
+ assert_equal(<<CSS, render(<<SCSS))
903
+ @media screen {
904
+ .foo, .bar {
905
+ a: b; } }
906
+ CSS
907
+ @media screen {.foo {a: b}}
908
+ @media screen {.bar {@extend .foo}}
909
+ SCSS
910
+ end
911
+
912
+ def test_extend_within_disparate_unknown_directive
913
+ assert_equal(<<CSS, render(<<SCSS))
914
+ @flooblehoof {
915
+ .foo, .bar {
916
+ a: b; } }
917
+
918
+ @flooblehoof {}
919
+ CSS
920
+ @flooblehoof {.foo {a: b}}
921
+ @flooblehoof {.bar {@extend .foo}}
922
+ SCSS
923
+ end
924
+
925
+ def test_extend_within_disparate_nested_directives
926
+ assert_equal(<<CSS, render(<<SCSS))
927
+ @media screen {
928
+ @flooblehoof {
929
+ .foo, .bar {
930
+ a: b; } } }
931
+ @media screen {
932
+ @flooblehoof {} }
933
+ CSS
934
+ @media screen {@flooblehoof {.foo {a: b}}}
935
+ @media screen {@flooblehoof {.bar {@extend .foo}}}
936
+ SCSS
937
+ end
938
+
939
+ def test_extend_within_and_without_media
940
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
941
+ DEPRECATION WARNING on line 4 of test_extend_within_and_without_media_inline.sass:
942
+ @extending an outer selector from within @media is deprecated.
943
+ You may only @extend selectors within the same directive.
944
+ This will be an error in Sass 3.3.
945
+ It can only work once @extend is supported natively in the browser.
946
+ WARN
947
+ .foo {
948
+ a: b; }
949
+
950
+ @media screen {
951
+ .foo, .bar {
952
+ c: d; } }
953
+ CSS
954
+ .foo {a: b}
955
+ @media screen {
956
+ .foo {c: d}
957
+ .bar {@extend .foo}
958
+ }
959
+ SCSS
960
+ end
961
+
962
+ def test_extend_within_and_without_unknown_directive
963
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
964
+ DEPRECATION WARNING on line 4 of test_extend_within_and_without_unknown_directive_inline.sass:
965
+ @extending an outer selector from within @flooblehoof is deprecated.
966
+ You may only @extend selectors within the same directive.
967
+ This will be an error in Sass 3.3.
968
+ It can only work once @extend is supported natively in the browser.
969
+ WARN
970
+ .foo {
971
+ a: b; }
972
+
973
+ @flooblehoof {
974
+ .foo, .bar {
975
+ c: d; } }
976
+ CSS
977
+ .foo {a: b}
978
+ @flooblehoof {
979
+ .foo {c: d}
980
+ .bar {@extend .foo}
981
+ }
982
+ SCSS
983
+ end
984
+
985
+ def test_extend_within_and_without_nested_directives
986
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
987
+ DEPRECATION WARNING on line 5 of test_extend_within_and_without_nested_directives_inline.sass:
988
+ @extending an outer selector from within @flooblehoof is deprecated.
989
+ You may only @extend selectors within the same directive.
990
+ This will be an error in Sass 3.3.
991
+ It can only work once @extend is supported natively in the browser.
992
+ WARN
993
+ @media screen {
994
+ .foo {
995
+ a: b; }
996
+
997
+ @flooblehoof {
998
+ .foo, .bar {
999
+ c: d; } } }
1000
+ CSS
1001
+ @media screen {
1002
+ .foo {a: b}
1003
+ @flooblehoof {
1004
+ .foo {c: d}
1005
+ .bar {@extend .foo}
1006
+ }
1007
+ }
1008
+ SCSS
1009
+ end
1010
+
798
1011
  # Regression Tests
799
1012
 
800
1013
  def test_newline_near_combinator
@@ -127,6 +127,16 @@ class UtilTest < Test::Unit::TestCase
127
127
  group_by_to_a(1..12) {|i| i % 3})
128
128
  end
129
129
 
130
+ def test_subsequence
131
+ assert(subsequence?([1, 2, 3], [1, 2, 3]))
132
+ assert(subsequence?([1, 2, 3], [1, :a, 2, :b, 3]))
133
+ assert(subsequence?([1, 2, 3], [:a, 1, :b, :c, 2, :d, 3, :e, :f]))
134
+
135
+ assert(!subsequence?([1, 2, 3], [1, 2]))
136
+ assert(!subsequence?([1, 2, 3], [1, 3, 2]))
137
+ assert(!subsequence?([1, 2, 3], [3, 2, 1]))
138
+ end
139
+
130
140
  def test_silence_warnings
131
141
  old_stderr, $stderr = $stderr, StringIO.new
132
142
  warn "Out"
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: 592302791
4
+ hash: 592302845
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 3
8
8
  - 2
9
9
  - 0
10
10
  - alpha
11
- - 237
12
- version: 3.2.0.alpha.237
11
+ - 240
12
+ version: 3.2.0.alpha.240
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-05-11 00:00:00 -04:00
22
+ date: 2012-05-25 00:00:00 -04:00
23
23
  default_executable:
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency
@@ -162,6 +162,7 @@ files:
162
162
  - lib/sass/tree/visitors/perform.rb
163
163
  - lib/sass/tree/visitors/set_options.rb
164
164
  - lib/sass/tree/visitors/to_css.rb
165
+ - lib/sass/tree/visitors/extend.rb
165
166
  - lib/sass/tree/warn_node.rb
166
167
  - lib/sass/tree/while_node.rb
167
168
  - lib/sass/tree/supports_node.rb