sass 3.2.0.alpha.261 → 3.2.0.alpha.268
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/engine.rb +2 -1
- data/lib/sass/less.rb +2 -2
- data/lib/sass/scss/parser.rb +4 -1
- data/lib/sass/scss/rx.rb +1 -0
- data/lib/sass/selector/simple_sequence.rb +2 -0
- data/lib/sass/tree/extend_node.rb +8 -1
- data/lib/sass/tree/visitors/convert.rb +1 -1
- data/lib/sass/tree/visitors/cssize.rb +7 -3
- data/lib/sass/tree/visitors/extend.rb +25 -0
- data/lib/sass/util/subset_map.rb +8 -0
- data/test/sass/conversion_test.rb +11 -0
- data/test/sass/extend_test.rb +145 -20
- data/test/test_helper.rb +9 -0
- metadata +4 -4
data/REVISION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
bdee97a283eb9a69301f0bd60e8dc28db78517c3
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.0.alpha.
|
1
|
+
3.2.0.alpha.268
|
data/lib/sass/engine.rb
CHANGED
@@ -683,8 +683,9 @@ WARNING
|
|
683
683
|
raise SyntaxError.new("Invalid extend directive '@extend': expected expression.") unless value
|
684
684
|
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath extend directives.",
|
685
685
|
:line => @line + 1) unless line.children.empty?
|
686
|
+
optional = !!value.gsub!(/\s+#{Sass::SCSS::RX::OPTIONAL}$/, '')
|
686
687
|
offset = line.offset + line.text.index(value).to_i
|
687
|
-
Tree::ExtendNode.new(parse_interp(value, offset))
|
688
|
+
Tree::ExtendNode.new(parse_interp(value, offset), optional)
|
688
689
|
when 'warn'
|
689
690
|
raise SyntaxError.new("Invalid warn directive '@warn': expected expression.") unless value
|
690
691
|
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath warn directives.",
|
data/lib/sass/less.rb
CHANGED
@@ -25,14 +25,14 @@ module Less
|
|
25
25
|
sel = selector_str(path)
|
26
26
|
base = selector_str(selector_base(path))
|
27
27
|
if base == sel
|
28
|
-
env << Node::SassNode.new(Sass::Tree::ExtendNode.new([sel]))
|
28
|
+
env << Node::SassNode.new(Sass::Tree::ExtendNode.new([sel], false))
|
29
29
|
else
|
30
30
|
Sass::Util.sass_warn <<WARNING
|
31
31
|
WARNING: Sass doesn't support mixing in selector sequences.
|
32
32
|
Replacing "#{sel}" with "@extend #{base}"
|
33
33
|
WARNING
|
34
34
|
env << Node::SassNode.new(Sass::Tree::CommentNode.new(["// #{sel};"], :silent))
|
35
|
-
env << Node::SassNode.new(Sass::Tree::ExtendNode.new([base]))
|
35
|
+
env << Node::SassNode.new(Sass::Tree::ExtendNode.new([base], false))
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
data/lib/sass/scss/parser.rb
CHANGED
@@ -289,7 +289,10 @@ module Sass
|
|
289
289
|
end
|
290
290
|
|
291
291
|
def extend_directive
|
292
|
-
|
292
|
+
selector = expr!(:selector_sequence)
|
293
|
+
optional = tok(OPTIONAL)
|
294
|
+
ss
|
295
|
+
node(Sass::Tree::ExtendNode.new(selector, !!optional))
|
293
296
|
end
|
294
297
|
|
295
298
|
def import_directive
|
data/lib/sass/scss/rx.rb
CHANGED
@@ -102,7 +102,9 @@ module Sass
|
|
102
102
|
# seq is A, sels is B, and self is C
|
103
103
|
|
104
104
|
self_without_sel = self.members - sels
|
105
|
+
group.each {|e, _| e.result = :failed_to_unify}
|
105
106
|
next unless unified = seq.members.last.unify(self_without_sel, subject?)
|
107
|
+
group.each {|e, _| e.result = :succeeded}
|
106
108
|
next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none?
|
107
109
|
new_seq = Sequence.new(seq.members[0...-1] + [unified])
|
108
110
|
new_seq.add_sources!(sources + [seq])
|
@@ -17,12 +17,19 @@ module Sass::Tree
|
|
17
17
|
# @return [Array<String, Sass::Script::Node>]
|
18
18
|
attr_accessor :selector
|
19
19
|
|
20
|
+
# Whether the `@extend` is allowed to match no selectors or not.
|
21
|
+
#
|
22
|
+
# @return [Boolean]
|
23
|
+
def optional?; @optional; end
|
24
|
+
|
20
25
|
# @param selector [Array<String, Sass::Script::Node>]
|
21
26
|
# The CSS selector to extend,
|
22
27
|
# interspersed with {Sass::Script::Node}s
|
23
28
|
# representing `#{}`-interpolation.
|
24
|
-
|
29
|
+
# @param optional [Boolean] See \{#optional}
|
30
|
+
def initialize(selector, optional)
|
25
31
|
@selector = selector
|
32
|
+
@optional = optional
|
26
33
|
super()
|
27
34
|
end
|
28
35
|
end
|
@@ -109,7 +109,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
109
109
|
end
|
110
110
|
|
111
111
|
def visit_extend(node)
|
112
|
-
"#{tab_str}@extend #{selector_to_src(node.selector).lstrip}#{semi}\n"
|
112
|
+
"#{tab_str}@extend #{selector_to_src(node.selector).lstrip}#{semi}#{" !optional" if node.optional?}\n"
|
113
113
|
end
|
114
114
|
|
115
115
|
def visit_for(node)
|
@@ -88,13 +88,17 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
88
88
|
# single [ExtendNode] can have multiple Extends if either the parent node or
|
89
89
|
# the extended selector is a comma sequence.
|
90
90
|
#
|
91
|
-
# @attr extender [
|
91
|
+
# @attr extender [Sass::Selector::Sequence]
|
92
92
|
# The selector of the CSS rule containing the `@extend`.
|
93
93
|
# @attr target [Array<Sass::Selector::Simple>] The selector being `@extend`ed.
|
94
94
|
# @attr node [Sass::Tree::ExtendNode] The node that produced this extend.
|
95
95
|
# @attr directives [Array<Sass::Tree::DirectiveNode>]
|
96
96
|
# The directives containing the `@extend`.
|
97
|
-
|
97
|
+
# @attr result [Symbol]
|
98
|
+
# The result of this extend. One of `:not_found` (the target doesn't exist
|
99
|
+
# in the document), `:failed_to_unify` (the target exists but cannot be
|
100
|
+
# unified with the extender), or `:succeeded`.
|
101
|
+
Extend = Struct.new(:extender, :target, :node, :directives, :result)
|
98
102
|
|
99
103
|
# Registers an extension in the `@extends` subset map.
|
100
104
|
def visit_extend(node)
|
@@ -116,7 +120,7 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
116
120
|
raise Sass::SyntaxError.new("#{seq} can't extend: invalid selector")
|
117
121
|
end
|
118
122
|
|
119
|
-
@extends[sel] = Extend.new(seq, sel, node, @parent_directives.dup)
|
123
|
+
@extends[sel] = Extend.new(seq, sel, node, @parent_directives.dup, :not_found)
|
120
124
|
end
|
121
125
|
end
|
122
126
|
|
@@ -2,6 +2,9 @@
|
|
2
2
|
#
|
3
3
|
# Destructively modifies the tree.
|
4
4
|
class Sass::Tree::Visitors::Extend < Sass::Tree::Visitors::Base
|
5
|
+
# Performs the given extensions on the static CSS tree based in `root`, then
|
6
|
+
# validates that all extends matched some selector.
|
7
|
+
#
|
5
8
|
# @param root [Tree::Node] The root node of the tree to visit.
|
6
9
|
# @param extends [Sass::Util::SubsetMap{Selector::Simple =>
|
7
10
|
# Sass::Tree::Visitors::Cssize::Extend}]
|
@@ -10,6 +13,7 @@ class Sass::Tree::Visitors::Extend < Sass::Tree::Visitors::Base
|
|
10
13
|
def self.visit(root, extends)
|
11
14
|
return if extends.empty?
|
12
15
|
new(extends).send(:visit, root)
|
16
|
+
check_extends_fired! extends
|
13
17
|
end
|
14
18
|
|
15
19
|
protected
|
@@ -39,4 +43,25 @@ class Sass::Tree::Visitors::Extend < Sass::Tree::Visitors::Base
|
|
39
43
|
def visit_rule(node)
|
40
44
|
node.resolved_rules = node.resolved_rules.do_extend(@extends, @parent_directives)
|
41
45
|
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def self.check_extends_fired!(extends)
|
50
|
+
extends.each_value do |ex|
|
51
|
+
next if ex.result == :succeeded || ex.node.optional?
|
52
|
+
warn = "\"#{ex.extender}\" failed to @extend \"#{ex.target}\"."
|
53
|
+
reason =
|
54
|
+
if ex.result == :not_found
|
55
|
+
"The selector \"#{ex.target}\" was not found."
|
56
|
+
else
|
57
|
+
"No selectors matching \"#{ex.target}\" could be unified with \"#{ex.extender}\"."
|
58
|
+
end
|
59
|
+
|
60
|
+
Sass::Util.sass_warn <<WARN
|
61
|
+
WARNING on line #{ex.node.line}#{" of #{ex.node.filename}" if ex.node.filename}: #{warn}
|
62
|
+
#{reason}
|
63
|
+
This will be an error in future releases of Sass.
|
64
|
+
WARN
|
65
|
+
end
|
66
|
+
end
|
42
67
|
end
|
data/lib/sass/util/subset_map.rb
CHANGED
@@ -96,6 +96,14 @@ module Sass
|
|
96
96
|
def [](set)
|
97
97
|
get(set).map {|v, _| v}
|
98
98
|
end
|
99
|
+
|
100
|
+
# Iterates over each value in the subset map. Ignores keys completely. If
|
101
|
+
# multiple keys have the same value, this will return them multiple times.
|
102
|
+
#
|
103
|
+
# @yield [Object] Each value in the map.
|
104
|
+
def each_value
|
105
|
+
@vals.each {|v| yield v}
|
106
|
+
end
|
99
107
|
end
|
100
108
|
end
|
101
109
|
end
|
@@ -1552,6 +1552,17 @@ foo bar {
|
|
1552
1552
|
SCSS
|
1553
1553
|
end
|
1554
1554
|
|
1555
|
+
def test_extend_with_optional
|
1556
|
+
assert_scss_to_sass <<SASS, <<SCSS
|
1557
|
+
foo
|
1558
|
+
@extend .bar !optional
|
1559
|
+
SASS
|
1560
|
+
foo {
|
1561
|
+
@extend .bar !optional;
|
1562
|
+
}
|
1563
|
+
SCSS
|
1564
|
+
end
|
1565
|
+
|
1555
1566
|
## Regression Tests
|
1556
1567
|
|
1557
1568
|
def test_empty_lists
|
data/test/sass/extend_test.rb
CHANGED
@@ -152,7 +152,10 @@ SCSS
|
|
152
152
|
def test_id_unification
|
153
153
|
assert_unification '.foo.bar', '#baz {@extend .foo}', '.foo.bar, .bar#baz'
|
154
154
|
assert_unification '.foo#baz', '#baz {@extend .foo}', '#baz'
|
155
|
-
|
155
|
+
|
156
|
+
assert_extend_doesnt_match('#bar', '.foo', :failed_to_unify, 2) do
|
157
|
+
assert_unification '.foo#baz', '#bar {@extend .foo}', '.foo#baz'
|
158
|
+
end
|
156
159
|
end
|
157
160
|
|
158
161
|
def test_universal_unification_with_simple_target
|
@@ -175,7 +178,11 @@ SCSS
|
|
175
178
|
def test_universal_unification_with_namespaced_universal_target
|
176
179
|
assert_unification 'ns|*.foo', '* {@extend .foo}', 'ns|*'
|
177
180
|
assert_unification 'ns|*.foo', '*|* {@extend .foo}', 'ns|*'
|
178
|
-
|
181
|
+
|
182
|
+
assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
|
183
|
+
assert_unification 'ns1|*.foo', 'ns2|* {@extend .foo}', 'ns1|*.foo'
|
184
|
+
end
|
185
|
+
|
179
186
|
assert_unification 'ns|*.foo', 'ns|* {@extend .foo}', 'ns|*'
|
180
187
|
end
|
181
188
|
|
@@ -191,7 +198,11 @@ SCSS
|
|
191
198
|
def test_universal_unification_with_namespaced_element_target
|
192
199
|
assert_unification 'ns|a.foo', '* {@extend .foo}', 'ns|a'
|
193
200
|
assert_unification 'ns|a.foo', '*|* {@extend .foo}', 'ns|a'
|
194
|
-
|
201
|
+
|
202
|
+
assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
|
203
|
+
assert_unification 'ns1|a.foo', 'ns2|* {@extend .foo}', 'ns1|a.foo'
|
204
|
+
end
|
205
|
+
|
195
206
|
assert_unification 'ns|a.foo', 'ns|* {@extend .foo}', 'ns|a'
|
196
207
|
end
|
197
208
|
|
@@ -214,7 +225,11 @@ SCSS
|
|
214
225
|
def test_element_unification_with_namespaced_universal_target
|
215
226
|
assert_unification 'ns|*.foo', 'a {@extend .foo}', 'ns|*.foo, ns|a'
|
216
227
|
assert_unification 'ns|*.foo', '*|a {@extend .foo}', 'ns|*.foo, ns|a'
|
217
|
-
|
228
|
+
|
229
|
+
assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
|
230
|
+
assert_unification 'ns1|*.foo', 'ns2|a {@extend .foo}', 'ns1|*.foo'
|
231
|
+
end
|
232
|
+
|
218
233
|
assert_unification 'ns|*.foo', 'ns|a {@extend .foo}', 'ns|*.foo, ns|a'
|
219
234
|
end
|
220
235
|
|
@@ -225,13 +240,20 @@ SCSS
|
|
225
240
|
assert_unification '*|a.foo', '*|a {@extend .foo}', '*|a'
|
226
241
|
assert_unification 'a.foo', 'ns|a {@extend .foo}', 'a.foo, ns|a'
|
227
242
|
assert_unification '*|a.foo', 'ns|a {@extend .foo}', '*|a.foo, ns|a'
|
228
|
-
|
243
|
+
|
244
|
+
assert_extend_doesnt_match('h1', '.foo', :failed_to_unify, 2) do
|
245
|
+
assert_unification 'a.foo', 'h1 {@extend .foo}', 'a.foo'
|
246
|
+
end
|
229
247
|
end
|
230
248
|
|
231
249
|
def test_element_unification_with_namespaced_element_target
|
232
250
|
assert_unification 'ns|a.foo', 'a {@extend .foo}', 'ns|a'
|
233
251
|
assert_unification 'ns|a.foo', '*|a {@extend .foo}', 'ns|a'
|
234
|
-
|
252
|
+
|
253
|
+
assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
|
254
|
+
assert_unification 'ns1|a.foo', 'ns2|a {@extend .foo}', 'ns1|a.foo'
|
255
|
+
end
|
256
|
+
|
235
257
|
assert_unification 'ns|a.foo', 'ns|a {@extend .foo}', 'ns|a'
|
236
258
|
end
|
237
259
|
|
@@ -246,8 +268,15 @@ SCSS
|
|
246
268
|
def test_pseudo_unification
|
247
269
|
assert_unification ':foo.baz', ':foo(2n+1) {@extend .baz}', ':foo.baz, :foo:foo(2n+1)'
|
248
270
|
assert_unification ':foo.baz', '::foo {@extend .baz}', ':foo.baz, :foo::foo'
|
249
|
-
|
250
|
-
|
271
|
+
|
272
|
+
assert_extend_doesnt_match('::bar', '.baz', :failed_to_unify, 2) do
|
273
|
+
assert_unification '::foo.baz', '::bar {@extend .baz}', '::foo.baz'
|
274
|
+
end
|
275
|
+
|
276
|
+
assert_extend_doesnt_match('::foo(2n+1)', '.baz', :failed_to_unify, 2) do
|
277
|
+
assert_unification '::foo.baz', '::foo(2n+1) {@extend .baz}', '::foo.baz'
|
278
|
+
end
|
279
|
+
|
251
280
|
assert_unification '::foo.baz', '::foo {@extend .baz}', '::foo'
|
252
281
|
assert_unification '::foo(2n+1).baz', '::foo(2n+1) {@extend .baz}', '::foo(2n+1)'
|
253
282
|
assert_unification ':foo.baz', ':bar {@extend .baz}', ':foo.baz, :foo:bar'
|
@@ -318,7 +347,9 @@ SCSS
|
|
318
347
|
end
|
319
348
|
|
320
349
|
def test_long_extendee_requires_all_selectors
|
321
|
-
|
350
|
+
assert_extend_doesnt_match('.baz', '.foo.bar', :not_found, 2) do
|
351
|
+
assert_extends '.foo', '.baz {@extend .foo.bar}', '.foo'
|
352
|
+
end
|
322
353
|
end
|
323
354
|
|
324
355
|
def test_long_extendee_matches_supersets
|
@@ -340,8 +371,13 @@ SCSS
|
|
340
371
|
end
|
341
372
|
|
342
373
|
def test_long_extender_aborts_unification
|
343
|
-
|
344
|
-
|
374
|
+
assert_extend_doesnt_match('h1.baz', '.foo', :failed_to_unify, 2) do
|
375
|
+
assert_extends 'a.foo#bar', 'h1.baz {@extend .foo}', 'a.foo#bar'
|
376
|
+
end
|
377
|
+
|
378
|
+
assert_extend_doesnt_match('.bang#baz', '.foo', :failed_to_unify, 2) do
|
379
|
+
assert_extends 'a.foo#bar', '.bang#baz {@extend .foo}', 'a.foo#bar'
|
380
|
+
end
|
345
381
|
end
|
346
382
|
|
347
383
|
## Nested Extenders
|
@@ -355,7 +391,9 @@ SCSS
|
|
355
391
|
end
|
356
392
|
|
357
393
|
def test_nested_extender_aborts_unification
|
358
|
-
|
394
|
+
assert_extend_doesnt_match('foo bar', '.foo', :failed_to_unify, 2) do
|
395
|
+
assert_extends 'baz.foo', 'foo bar {@extend .foo}', 'baz.foo'
|
396
|
+
end
|
359
397
|
end
|
360
398
|
|
361
399
|
def test_nested_extender_alternates_parents
|
@@ -771,7 +809,8 @@ SCSS
|
|
771
809
|
end
|
772
810
|
|
773
811
|
def test_placeholder_selector_as_modifier
|
774
|
-
|
812
|
+
assert_extend_doesnt_match('div', '%foo', :failed_to_unify, 3) do
|
813
|
+
assert_equal <<CSS, render(<<SCSS)
|
775
814
|
a.baz.bar {
|
776
815
|
color: blue; }
|
777
816
|
CSS
|
@@ -779,6 +818,7 @@ a%foo.baz {color: blue}
|
|
779
818
|
.bar {@extend %foo}
|
780
819
|
div {@extend %foo}
|
781
820
|
SCSS
|
821
|
+
end
|
782
822
|
end
|
783
823
|
|
784
824
|
def test_placeholder_interpolation
|
@@ -805,7 +845,7 @@ SCSS
|
|
805
845
|
|
806
846
|
def test_extend_out_of_media
|
807
847
|
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
808
|
-
DEPRECATION WARNING on line 3 of test_extend_out_of_media_inline.
|
848
|
+
DEPRECATION WARNING on line 3 of test_extend_out_of_media_inline.scss:
|
809
849
|
@extending an outer selector from within @media is deprecated.
|
810
850
|
You may only @extend selectors within the same directive.
|
811
851
|
This will be an error in Sass 3.3.
|
@@ -823,7 +863,7 @@ SCSS
|
|
823
863
|
|
824
864
|
def test_extend_out_of_unknown_directive
|
825
865
|
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
826
|
-
DEPRECATION WARNING on line 3 of test_extend_out_of_unknown_directive_inline.
|
866
|
+
DEPRECATION WARNING on line 3 of test_extend_out_of_unknown_directive_inline.scss:
|
827
867
|
@extending an outer selector from within @flooblehoof is deprecated.
|
828
868
|
You may only @extend selectors within the same directive.
|
829
869
|
This will be an error in Sass 3.3.
|
@@ -843,7 +883,7 @@ SCSS
|
|
843
883
|
|
844
884
|
def test_extend_out_of_nested_directives
|
845
885
|
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
846
|
-
DEPRECATION WARNING on line 4 of test_extend_out_of_nested_directives_inline.
|
886
|
+
DEPRECATION WARNING on line 4 of test_extend_out_of_nested_directives_inline.scss:
|
847
887
|
@extending an outer selector from within @flooblehoof is deprecated.
|
848
888
|
You may only @extend selectors within the same directive.
|
849
889
|
This will be an error in Sass 3.3.
|
@@ -946,7 +986,7 @@ SCSS
|
|
946
986
|
|
947
987
|
def test_extend_within_and_without_media
|
948
988
|
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
949
|
-
DEPRECATION WARNING on line 4 of test_extend_within_and_without_media_inline.
|
989
|
+
DEPRECATION WARNING on line 4 of test_extend_within_and_without_media_inline.scss:
|
950
990
|
@extending an outer selector from within @media is deprecated.
|
951
991
|
You may only @extend selectors within the same directive.
|
952
992
|
This will be an error in Sass 3.3.
|
@@ -969,7 +1009,7 @@ SCSS
|
|
969
1009
|
|
970
1010
|
def test_extend_within_and_without_unknown_directive
|
971
1011
|
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
972
|
-
DEPRECATION WARNING on line 4 of test_extend_within_and_without_unknown_directive_inline.
|
1012
|
+
DEPRECATION WARNING on line 4 of test_extend_within_and_without_unknown_directive_inline.scss:
|
973
1013
|
@extending an outer selector from within @flooblehoof is deprecated.
|
974
1014
|
You may only @extend selectors within the same directive.
|
975
1015
|
This will be an error in Sass 3.3.
|
@@ -992,7 +1032,7 @@ SCSS
|
|
992
1032
|
|
993
1033
|
def test_extend_within_and_without_nested_directives
|
994
1034
|
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
995
|
-
DEPRECATION WARNING on line 5 of test_extend_within_and_without_nested_directives_inline.
|
1035
|
+
DEPRECATION WARNING on line 5 of test_extend_within_and_without_nested_directives_inline.scss:
|
996
1036
|
@extending an outer selector from within @flooblehoof is deprecated.
|
997
1037
|
You may only @extend selectors within the same directive.
|
998
1038
|
This will be an error in Sass 3.3.
|
@@ -1071,6 +1111,74 @@ x! .bar {
|
|
1071
1111
|
CSS
|
1072
1112
|
x! .bar {a: b}
|
1073
1113
|
y! .bap {@extend .bar}
|
1114
|
+
SCSS
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
def test_extend_warns_when_extendee_doesnt_exist
|
1118
|
+
assert_warning(<<WARN) {assert_equal("", render(<<SCSS))}
|
1119
|
+
WARNING on line 1 of test_extend_warns_when_extendee_doesnt_exist_inline.scss: ".foo" failed to @extend ".bar".
|
1120
|
+
The selector ".bar" was not found.
|
1121
|
+
This will be an error in future releases of Sass.
|
1122
|
+
WARN
|
1123
|
+
.foo {@extend .bar}
|
1124
|
+
SCSS
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
def test_extend_warns_when_extension_fails
|
1128
|
+
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
1129
|
+
WARNING on line 2 of test_extend_warns_when_extension_fails_inline.scss: "b.foo" failed to @extend ".bar".
|
1130
|
+
No selectors matching ".bar" could be unified with "b.foo".
|
1131
|
+
This will be an error in future releases of Sass.
|
1132
|
+
WARN
|
1133
|
+
a.bar {
|
1134
|
+
a: b; }
|
1135
|
+
CSS
|
1136
|
+
a.bar {a: b}
|
1137
|
+
b.foo {@extend .bar}
|
1138
|
+
SCSS
|
1139
|
+
end
|
1140
|
+
|
1141
|
+
def test_extend_does_not_warn_when_one_extension_fails_but_others_dont
|
1142
|
+
assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
|
1143
|
+
a.bar {
|
1144
|
+
a: b; }
|
1145
|
+
|
1146
|
+
.bar, b.foo {
|
1147
|
+
c: d; }
|
1148
|
+
CSS
|
1149
|
+
a.bar {a: b}
|
1150
|
+
.bar {c: d}
|
1151
|
+
b.foo {@extend .bar}
|
1152
|
+
SCSS
|
1153
|
+
end
|
1154
|
+
|
1155
|
+
def test_extend_does_not_warn_when_one_extension_fails_but_others_dont
|
1156
|
+
assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
|
1157
|
+
a.bar {
|
1158
|
+
a: b; }
|
1159
|
+
|
1160
|
+
.bar, b.foo {
|
1161
|
+
c: d; }
|
1162
|
+
CSS
|
1163
|
+
a.bar {a: b}
|
1164
|
+
.bar {c: d}
|
1165
|
+
b.foo {@extend .bar}
|
1166
|
+
SCSS
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
def test_optional_extend_does_not_warn_when_extendee_doesnt_exist
|
1170
|
+
assert_no_warning {assert_equal("", render(<<SCSS))}
|
1171
|
+
.foo {@extend .bar !optional}
|
1172
|
+
SCSS
|
1173
|
+
end
|
1174
|
+
|
1175
|
+
def test_optional_extend_does_not_warn_when_extension_fails
|
1176
|
+
assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
|
1177
|
+
a.bar {
|
1178
|
+
a: b; }
|
1179
|
+
CSS
|
1180
|
+
a.bar {a: b}
|
1181
|
+
b.foo {@extend .bar !optional}
|
1074
1182
|
SCSS
|
1075
1183
|
end
|
1076
1184
|
|
@@ -1184,6 +1292,22 @@ SCSS
|
|
1184
1292
|
|
1185
1293
|
private
|
1186
1294
|
|
1295
|
+
def assert_extend_doesnt_match(extender, target, reason, line, syntax = :scss)
|
1296
|
+
warn = "\"#{extender}\" failed to @extend \"#{target}\"."
|
1297
|
+
reason =
|
1298
|
+
if reason == :not_found
|
1299
|
+
"The selector \"#{target}\" was not found."
|
1300
|
+
else
|
1301
|
+
"No selectors matching \"#{target}\" could be unified with \"#{extender}\"."
|
1302
|
+
end
|
1303
|
+
|
1304
|
+
assert_warning(<<WARNING) {yield}
|
1305
|
+
WARNING on line #{line} of #{filename_for_test syntax}: #{warn}
|
1306
|
+
#{reason}
|
1307
|
+
This will be an error in future releases of Sass.
|
1308
|
+
WARNING
|
1309
|
+
end
|
1310
|
+
|
1187
1311
|
def assert_unification(selector, extension, unified)
|
1188
1312
|
# Do some trickery so the first law of extend doesn't get in our way.
|
1189
1313
|
assert_extends(
|
@@ -1203,7 +1327,8 @@ SCSS
|
|
1203
1327
|
end
|
1204
1328
|
|
1205
1329
|
def render(sass, options = {})
|
1330
|
+
options = {:syntax => :scss}.merge(options)
|
1206
1331
|
munge_filename options
|
1207
|
-
Sass::Engine.new(sass,
|
1332
|
+
Sass::Engine.new(sass, options).render
|
1208
1333
|
end
|
1209
1334
|
end
|
data/test/test_helper.rb
CHANGED
@@ -47,6 +47,15 @@ class Test::Unit::TestCase
|
|
47
47
|
$stderr = the_real_stderr
|
48
48
|
end
|
49
49
|
|
50
|
+
def assert_no_warning
|
51
|
+
the_real_stderr, $stderr = $stderr, StringIO.new
|
52
|
+
yield
|
53
|
+
|
54
|
+
assert_equal '', $stderr.string
|
55
|
+
ensure
|
56
|
+
$stderr = the_real_stderr
|
57
|
+
end
|
58
|
+
|
50
59
|
def silence_warnings(&block)
|
51
60
|
Sass::Util.silence_warnings(&block)
|
52
61
|
end
|
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: 592302341
|
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
|
+
- 268
|
12
|
+
version: 3.2.0.alpha.268
|
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-07-13 00:00:00 -04:00
|
23
23
|
default_executable:
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|