sass 3.2.0.alpha.237 → 3.2.0.alpha.240
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 +1 -0
- data/lib/sass/exec.rb +2 -2
- data/lib/sass/selector/comma_sequence.rb +6 -3
- data/lib/sass/selector/sequence.rb +7 -4
- data/lib/sass/selector/simple_sequence.rb +24 -5
- data/lib/sass/tree/node.rb +0 -21
- data/lib/sass/tree/root_node.rb +1 -1
- data/lib/sass/tree/rule_node.rb +0 -9
- data/lib/sass/tree/visitors/check_nesting.rb +0 -8
- data/lib/sass/tree/visitors/convert.rb +1 -1
- data/lib/sass/tree/visitors/cssize.rb +16 -1
- data/lib/sass/tree/visitors/extend.rb +42 -0
- data/lib/sass/tree/visitors/to_css.rb +4 -3
- data/lib/sass/util.rb +17 -0
- data/test/sass/conversion_test.rb +16 -1
- data/test/sass/engine_test.rb +16 -2
- data/test/sass/extend_test.rb +213 -0
- data/test/sass/util_test.rb +10 -0
- metadata +5 -4
data/REVISION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
e215507545439a84c2b2bc01d454ebab722fe209
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.2.0.alpha.
|
|
1
|
+
3.2.0.alpha.240
|
data/lib/sass/engine.rb
CHANGED
|
@@ -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'
|
data/lib/sass/exec.rb
CHANGED
|
@@ -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 =>
|
|
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 =>
|
|
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,
|
|
76
|
-
# @param extends [{Selector::Simple =>
|
|
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)) {|
|
|
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
|
data/lib/sass/tree/node.rb
CHANGED
|
@@ -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
|
#
|
data/lib/sass/tree/root_node.rb
CHANGED
|
@@ -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
|
|
23
|
+
Visitors::Extend.visit(result, extends)
|
|
24
24
|
result.to_s
|
|
25
25
|
end
|
|
26
26
|
end
|
data/lib/sass/tree/rule_node.rb
CHANGED
|
@@ -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 = (
|
|
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
|
-
|
|
72
|
-
return node.resolved_value + "
|
|
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
|
-
"#{
|
|
78
|
+
"#{tab_str}#{node.resolved_value} {" + (node.style == :compact ? ' ' : "\n")
|
|
78
79
|
end
|
|
79
80
|
was_prop = false
|
|
80
81
|
first = true
|
data/lib/sass/util.rb
CHANGED
|
@@ -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'}
|
|
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 = {})
|
data/test/sass/engine_test.rb
CHANGED
|
@@ -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?
|
data/test/sass/extend_test.rb
CHANGED
|
@@ -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
|
data/test/sass/util_test.rb
CHANGED
|
@@ -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:
|
|
4
|
+
hash: 592302845
|
|
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
|
+
- 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-
|
|
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
|