sass 3.2.0.alpha.261 → 3.2.0.alpha.268
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/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
|