sass 3.1.0.alpha.48 → 3.1.0.alpha.49
Sign up to get free protection for your applications and to get access to all the features.
- data/EDGE_GEM_VERSION +1 -1
- data/VERSION +1 -1
- data/lib/sass/engine.rb +5 -0
- data/lib/sass/selector/comma_sequence.rb +2 -3
- data/lib/sass/selector/sequence.rb +2 -3
- data/lib/sass/selector/simple_sequence.rb +2 -3
- data/lib/sass/tree/charset_node.rb +0 -15
- data/lib/sass/tree/comment_node.rb +0 -72
- data/lib/sass/tree/debug_node.rb +4 -22
- data/lib/sass/tree/directive_node.rb +0 -52
- data/lib/sass/tree/each_node.rb +8 -24
- data/lib/sass/tree/extend_node.rb +12 -48
- data/lib/sass/tree/for_node.rb +20 -39
- data/lib/sass/tree/if_node.rb +7 -32
- data/lib/sass/tree/import_node.rb +0 -56
- data/lib/sass/tree/media_node.rb +0 -43
- data/lib/sass/tree/mixin_def_node.rb +12 -33
- data/lib/sass/tree/mixin_node.rb +14 -106
- data/lib/sass/tree/node.rb +12 -249
- data/lib/sass/tree/prop_node.rb +15 -78
- data/lib/sass/tree/root_node.rb +1 -121
- data/lib/sass/tree/rule_node.rb +1 -157
- data/lib/sass/tree/variable_node.rb +14 -23
- data/lib/sass/tree/visitors/base.rb +64 -0
- data/lib/sass/tree/visitors/convert.rb +234 -0
- data/lib/sass/tree/visitors/cssize.rb +177 -0
- data/lib/sass/tree/visitors/perform.rb +278 -0
- data/lib/sass/tree/visitors/to_css.rb +200 -0
- data/lib/sass/tree/warn_node.rb +4 -28
- data/lib/sass/tree/while_node.rb +5 -23
- metadata +19 -14
@@ -0,0 +1,64 @@
|
|
1
|
+
# Visitors are used to traverse the Sass parse tree.
|
2
|
+
# Visitors should extend {Visitors::Base},
|
3
|
+
# which provides a small amount of scaffolding for traversal.
|
4
|
+
module Sass::Tree::Visitors
|
5
|
+
# The abstract base class for Sass visitors.
|
6
|
+
# Visitors should extend this class,
|
7
|
+
# then implement `visit_*` methods for each node they care about
|
8
|
+
# (e.g. `visit_rule` for {RuleNode} or `visit_for` for {FileNode}).
|
9
|
+
# These methods take the node in question as argument.
|
10
|
+
# They may `yield` to visit the child nodes of the current node.
|
11
|
+
#
|
12
|
+
# *Note*: due to the unusual nature of {Sass::Tree::IfNode},
|
13
|
+
# special care must be taken to ensure that it is properly handled.
|
14
|
+
# In particular, there is no built-in scaffolding
|
15
|
+
# for dealing with the return value of `@else` nodes.
|
16
|
+
#
|
17
|
+
# @abstract
|
18
|
+
class Base
|
19
|
+
# Runs the visitor on a tree.
|
20
|
+
#
|
21
|
+
# @param root [Tree::Node] The root node of the Sass tree.
|
22
|
+
# @return [Object] The return value of \{#visit} for the root node.
|
23
|
+
def self.visit(root)
|
24
|
+
new.send(:visit, root)
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
# Runs the visitor on the given node.
|
30
|
+
# This can be overridden by subclasses that need to do something for each node.
|
31
|
+
#
|
32
|
+
# @param node [Tree::Node] The node to visit.
|
33
|
+
# @return [Object] The return value of the `visit_*` method for this node.
|
34
|
+
def visit(node)
|
35
|
+
method = "visit_#{node.class.name.gsub(/.*::(.*?)Node$/, '\\1').downcase}"
|
36
|
+
if self.respond_to?(method)
|
37
|
+
self.send(method, node) {visit_children(node)}
|
38
|
+
else
|
39
|
+
visit_children(node)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Visit the child nodes for a given node.
|
44
|
+
# This can be overridden by subclasses that need to do something
|
45
|
+
# with the child nodes' return values.
|
46
|
+
#
|
47
|
+
# This method is run when `visit_*` methods `yield`,
|
48
|
+
# and its return value is returned from the `yield`.
|
49
|
+
#
|
50
|
+
# @param parent [Tree::Node] The parent node of the children to visit.
|
51
|
+
# @return [Array<Object>] The return values of the `visit_*` methods for the children.
|
52
|
+
def visit_children(parent)
|
53
|
+
parent.children.map {|c| visit(c)}
|
54
|
+
end
|
55
|
+
|
56
|
+
# `yield`s, then runs the visitor on the `@else` clause if the node has one.
|
57
|
+
# This exists to ensure that the contents of the `@else` clause get visited.
|
58
|
+
def visit_if(node)
|
59
|
+
yield
|
60
|
+
visit(node.else) if node.else
|
61
|
+
node
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,234 @@
|
|
1
|
+
# A visitor for converting a Sass tree into a source string.
|
2
|
+
class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
3
|
+
# Runs the visitor on a tree.
|
4
|
+
#
|
5
|
+
# @param root [Tree::Node] The root node of the Sass tree.
|
6
|
+
# @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
|
7
|
+
# @param format [Symbol] `:sass` or `:scss`.
|
8
|
+
# @return [String] The Sass or SCSS source for the tree.
|
9
|
+
def self.visit(root, options, format)
|
10
|
+
new(options, format).send(:visit, root)
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def initialize(options, format)
|
16
|
+
@options = options
|
17
|
+
@format = format
|
18
|
+
@tabs = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def visit_children(parent)
|
22
|
+
@tabs += 1
|
23
|
+
return @format == :sass ? "\n" : " {}\n" if parent.children.empty?
|
24
|
+
(@format == :sass ? "\n" : " {\n") + super.join.rstrip + (@format == :sass ? "\n" : " }\n")
|
25
|
+
ensure
|
26
|
+
@tabs -= 1
|
27
|
+
end
|
28
|
+
|
29
|
+
# Ensures proper spacing between top-level nodes.
|
30
|
+
def visit_root(node)
|
31
|
+
Sass::Util.enum_cons(node.children + [nil], 2).map do |child, nxt|
|
32
|
+
visit(child) +
|
33
|
+
if nxt &&
|
34
|
+
(child.is_a?(Sass::Tree::CommentNode) &&
|
35
|
+
child.line + child.value.count("\n") + 1 == nxt.line) ||
|
36
|
+
(child.is_a?(Sass::Tree::ImportNode) && nxt.is_a?(Sass::Tree::ImportNode) &&
|
37
|
+
child.line + 1 == nxt.line) ||
|
38
|
+
(child.is_a?(Sass::Tree::VariableNode) && nxt.is_a?(Sass::Tree::VariableNode) &&
|
39
|
+
child.line + 1 == nxt.line)
|
40
|
+
""
|
41
|
+
else
|
42
|
+
"\n"
|
43
|
+
end
|
44
|
+
end.join.rstrip + "\n"
|
45
|
+
end
|
46
|
+
|
47
|
+
def visit_charset(node)
|
48
|
+
"#{tab_str}@charset \"#{node.name}\"#{semi}\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
def visit_comment(node)
|
52
|
+
if @format == :sass
|
53
|
+
content = node.value.gsub(/\*\/$/, '').rstrip
|
54
|
+
if content =~ /\A[ \t]/
|
55
|
+
# Re-indent SCSS comments like this:
|
56
|
+
# /* foo
|
57
|
+
# bar
|
58
|
+
# baz */
|
59
|
+
content.gsub!(/^/, ' ')
|
60
|
+
content.sub!(/\A([ \t]*)\/\*/, '/*\1')
|
61
|
+
end
|
62
|
+
|
63
|
+
content =
|
64
|
+
unless content.include?("\n")
|
65
|
+
content
|
66
|
+
else
|
67
|
+
content.gsub!(/\n( \*|\/\/)/, "\n ")
|
68
|
+
spaces = content.scan(/\n( *)/).map {|s| s.first.size}.min
|
69
|
+
sep = node.silent ? "\n//" : "\n *"
|
70
|
+
if spaces >= 2
|
71
|
+
content.gsub(/\n /, sep)
|
72
|
+
else
|
73
|
+
content.gsub(/\n#{' ' * spaces}/, sep)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
content.gsub!(/\A\/\*/, '//') if node.silent
|
78
|
+
content.gsub!(/^/, tab_str)
|
79
|
+
content.rstrip + "\n"
|
80
|
+
else
|
81
|
+
spaces = (' ' * [@tabs - node.value[/^ */].size, 0].max)
|
82
|
+
if node.silent
|
83
|
+
node.value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '')
|
84
|
+
else
|
85
|
+
node.value
|
86
|
+
end.gsub(/^/, spaces) + "\n"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def visit_debug(node)
|
91
|
+
"#{tab_str}@debug #{node.expr.to_sass(@options)}#{semi}\n"
|
92
|
+
end
|
93
|
+
|
94
|
+
def visit_directive(node)
|
95
|
+
res = "#{tab_str}#{node.value}"
|
96
|
+
return res + "#{semi}\n" unless node.has_children
|
97
|
+
res + yield + "\n"
|
98
|
+
end
|
99
|
+
|
100
|
+
def visit_each(node)
|
101
|
+
"#{tab_str}@each $#{dasherize(node.var)} in #{node.list.to_sass(@options)}#{yield}"
|
102
|
+
end
|
103
|
+
|
104
|
+
def visit_extend(node)
|
105
|
+
"#{tab_str}@extend #{selector_to_src(node.selector).lstrip}#{semi}\n"
|
106
|
+
end
|
107
|
+
|
108
|
+
def visit_for(node)
|
109
|
+
"#{tab_str}@for $#{dasherize(node.var)} from #{node.from.to_sass(@options)} " +
|
110
|
+
"#{node.exclusive ? "to" : "through"} #{node.to.to_sass(@options)}#{yield}"
|
111
|
+
end
|
112
|
+
|
113
|
+
def visit_if(node)
|
114
|
+
name =
|
115
|
+
if !@is_else; "if"
|
116
|
+
elsif node.expr; "else if"
|
117
|
+
else; "else"
|
118
|
+
end
|
119
|
+
str = "#{tab_str}@#{name}"
|
120
|
+
str << " #{node.expr.to_sass(@options)}" if node.expr
|
121
|
+
str << yield
|
122
|
+
@is_else = true
|
123
|
+
str << visit(node.else) if node.else
|
124
|
+
str
|
125
|
+
ensure
|
126
|
+
@is_else = false
|
127
|
+
end
|
128
|
+
|
129
|
+
def visit_import(node)
|
130
|
+
quote = @format == :scss ? '"' : ''
|
131
|
+
"#{tab_str}@import #{quote}#{node.imported_filename}#{quote}#{semi}\n"
|
132
|
+
end
|
133
|
+
|
134
|
+
def visit_media(node)
|
135
|
+
"#{tab_str}@media #{node.query}#{yield}"
|
136
|
+
end
|
137
|
+
|
138
|
+
def visit_mixindef(node)
|
139
|
+
args =
|
140
|
+
if node.args.empty?
|
141
|
+
""
|
142
|
+
else
|
143
|
+
'(' + node.args.map do |v, d|
|
144
|
+
if d
|
145
|
+
"#{v.to_sass(@options)}: #{d.to_sass(@options)}"
|
146
|
+
else
|
147
|
+
v.to_sass(@options)
|
148
|
+
end
|
149
|
+
end.join(", ") + ')'
|
150
|
+
end
|
151
|
+
|
152
|
+
"#{tab_str}#{@format == :sass ? '=' : '@mixin '}#{dasherize(node.name)}#{args}#{yield}"
|
153
|
+
end
|
154
|
+
|
155
|
+
def visit_mixin(node)
|
156
|
+
unless node.args.empty? && node.keywords.empty?
|
157
|
+
args = node.args.map {|a| a.to_sass(@options)}.join(", ")
|
158
|
+
keywords = node.keywords.map {|k, v| "$#{dasherize(k)}: #{v.to_sass(@options)}"}.join(', ')
|
159
|
+
arglist = "(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})"
|
160
|
+
end
|
161
|
+
"#{tab_str}#{@format == :sass ? '+' : '@include '}#{dasherize(node.name)}#{arglist}#{semi}\n"
|
162
|
+
end
|
163
|
+
|
164
|
+
def visit_prop(node)
|
165
|
+
res = tab_str + node.declaration(@options, @format)
|
166
|
+
return res + semi + "\n" if node.children.empty?
|
167
|
+
res + yield.rstrip + semi + "\n"
|
168
|
+
end
|
169
|
+
|
170
|
+
def visit_rule(node)
|
171
|
+
if @format == :sass
|
172
|
+
name = selector_to_sass(node.rule)
|
173
|
+
name = "\\" + name if name[0] == ?:
|
174
|
+
name.gsub(/^/, tab_str) + yield
|
175
|
+
elsif @format == :scss
|
176
|
+
name = selector_to_scss(node.rule)
|
177
|
+
res = name + yield
|
178
|
+
if node.children.last.is_a?(Sass::Tree::CommentNode) && node.children.last.silent
|
179
|
+
res.slice!(-3..-1)
|
180
|
+
res << "\n" << tab_str << "}\n"
|
181
|
+
end
|
182
|
+
res
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def visit_variable(node)
|
187
|
+
"#{tab_str}$#{dasherize(node.name)}: #{node.expr.to_sass(@options)}#{' !default' if node.guarded}#{semi}\n"
|
188
|
+
end
|
189
|
+
|
190
|
+
def visit_warn(node)
|
191
|
+
"#{tab_str}@warn #{node.expr.to_sass(@options)}#{semi}\n"
|
192
|
+
end
|
193
|
+
|
194
|
+
def visit_while(node)
|
195
|
+
"#{tab_str}@while #{node.expr.to_sass(@options)}#{yield}"
|
196
|
+
end
|
197
|
+
|
198
|
+
private
|
199
|
+
|
200
|
+
def selector_to_src(sel)
|
201
|
+
@format == :sass ? selector_to_sass(sel) : selector_to_scss(sel)
|
202
|
+
end
|
203
|
+
|
204
|
+
def selector_to_sass(sel)
|
205
|
+
sel.map do |r|
|
206
|
+
if r.is_a?(String)
|
207
|
+
r.gsub(/(,[ \t]*)?\n\s*/) {$1 ? $1 + "\n" : " "}
|
208
|
+
else
|
209
|
+
"\#{#{r.to_sass(@options)}}"
|
210
|
+
end
|
211
|
+
end.join
|
212
|
+
end
|
213
|
+
|
214
|
+
def selector_to_scss(sel)
|
215
|
+
sel.map {|r| r.is_a?(String) ? r : "\#{#{r.to_sass(@options)}}"}.
|
216
|
+
join.gsub(/^[ \t]*/, tab_str)
|
217
|
+
end
|
218
|
+
|
219
|
+
def semi
|
220
|
+
@format == :sass ? "" : ";"
|
221
|
+
end
|
222
|
+
|
223
|
+
def tab_str
|
224
|
+
' ' * @tabs
|
225
|
+
end
|
226
|
+
|
227
|
+
def dasherize(s)
|
228
|
+
if @options[:dasherize]
|
229
|
+
s.gsub('_', '-')
|
230
|
+
else
|
231
|
+
s
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
# A visitor for converting a static Sass tree into a static CSS tree.
|
2
|
+
class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
3
|
+
# @param root [Tree::Node] The root node of the tree to visit.
|
4
|
+
# @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes
|
5
|
+
# *and* the extensions defined for this tree
|
6
|
+
def self.visit(root); super; end
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
# Returns the immediate parent of the current node.
|
11
|
+
# @return [Tree::Node]
|
12
|
+
attr_reader :parent
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@extends = Sass::Util::SubsetMap.new
|
16
|
+
end
|
17
|
+
|
18
|
+
# If an exception is raised, this adds proper metadata to the backtrace.
|
19
|
+
def visit(node)
|
20
|
+
super(node.dup)
|
21
|
+
rescue Sass::SyntaxError => e
|
22
|
+
e.modify_backtrace(:filename => node.filename, :line => node.line)
|
23
|
+
raise e
|
24
|
+
end
|
25
|
+
|
26
|
+
# Keeps track of the current parent node.
|
27
|
+
def visit_children(parent)
|
28
|
+
with_parent parent do
|
29
|
+
parent.children = super.flatten
|
30
|
+
parent
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Runs a block of code with the current parent node
|
35
|
+
# replaced with the given node.
|
36
|
+
#
|
37
|
+
# @param parent [Tree::Node] The new parent for the duration of the block.
|
38
|
+
# @yield A block in which the parent is set to `parent`.
|
39
|
+
# @return [Object] The return value of the block.
|
40
|
+
def with_parent(parent)
|
41
|
+
old_parent, @parent = @parent, parent
|
42
|
+
yield
|
43
|
+
ensure
|
44
|
+
@parent = old_parent
|
45
|
+
end
|
46
|
+
|
47
|
+
# In Ruby 1.8, ensures that there's only one `@charset` directive
|
48
|
+
# and that it's at the top of the document.
|
49
|
+
#
|
50
|
+
# @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes
|
51
|
+
# *and* the extensions defined for this tree
|
52
|
+
def visit_root(node)
|
53
|
+
yield
|
54
|
+
|
55
|
+
# In Ruby 1.9 we can make all @charset nodes invisible
|
56
|
+
# and infer the final @charset from the encoding of the final string.
|
57
|
+
if Sass::Util.ruby1_8? && parent.nil?
|
58
|
+
charset = node.children.find {|c| c.is_a?(Sass::Tree::CharsetNode)}
|
59
|
+
node.children.reject! {|c| c.is_a?(Sass::Tree::CharsetNode)}
|
60
|
+
node.children.unshift charset if charset
|
61
|
+
end
|
62
|
+
|
63
|
+
return node, @extends
|
64
|
+
rescue Sass::SyntaxError => e
|
65
|
+
e.sass_template ||= node.template
|
66
|
+
raise e
|
67
|
+
end
|
68
|
+
|
69
|
+
# Registers an extension in the `@extends` subset map.
|
70
|
+
def visit_extend(node)
|
71
|
+
node.resolved_selector.members.each do |seq|
|
72
|
+
if seq.members.size > 1
|
73
|
+
raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend nested selectors")
|
74
|
+
end
|
75
|
+
|
76
|
+
sseq = seq.members.first
|
77
|
+
if !sseq.is_a?(Sass::Selector::SimpleSequence)
|
78
|
+
raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: invalid selector")
|
79
|
+
end
|
80
|
+
|
81
|
+
sel = sseq.members
|
82
|
+
parent.resolved_rules.members.each do |seq|
|
83
|
+
if !seq.members.last.is_a?(Sass::Selector::SimpleSequence)
|
84
|
+
raise Sass::SyntaxError.new("#{seq} can't extend: invalid selector")
|
85
|
+
end
|
86
|
+
|
87
|
+
@extends[sel] = seq
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
[]
|
92
|
+
end
|
93
|
+
|
94
|
+
# Modifies exception backtraces to include the imported file.
|
95
|
+
def visit_import(node)
|
96
|
+
yield
|
97
|
+
node.children
|
98
|
+
rescue Sass::SyntaxError => e
|
99
|
+
e.modify_backtrace(:filename => node.children.first.filename)
|
100
|
+
e.add_backtrace(:filename => node.filename, :line => node.line)
|
101
|
+
raise e
|
102
|
+
end
|
103
|
+
|
104
|
+
# Bubbles the `@media` directive up through RuleNodes
|
105
|
+
# and merges it with other `@media` directives.
|
106
|
+
def visit_media(node)
|
107
|
+
if parent.is_a?(Sass::Tree::RuleNode)
|
108
|
+
new_rule = parent.dup
|
109
|
+
new_rule.children = node.children
|
110
|
+
node.children = with_parent(node) {Array(visit(new_rule))}
|
111
|
+
# If the last child is actually the end of the group,
|
112
|
+
# the parent's cssize will set it properly
|
113
|
+
node.children.last.group_end = false unless node.children.empty?
|
114
|
+
else
|
115
|
+
yield
|
116
|
+
end
|
117
|
+
|
118
|
+
media = node.children.select {|c| c.is_a?(Sass::Tree::MediaNode)}
|
119
|
+
node.children.reject! {|c| c.is_a?(Sass::Tree::MediaNode)}
|
120
|
+
media.each {|n| n.query = "#{node.query} and #{n.query}"}
|
121
|
+
(node.children.empty? ? [] : [node]) + media
|
122
|
+
end
|
123
|
+
|
124
|
+
# Asserts that all the mixin's children are valid in their new location.
|
125
|
+
def visit_mixin(node)
|
126
|
+
node.children.map do |c|
|
127
|
+
parent.check_child! c
|
128
|
+
# Don't use #visit_children to avoid adding the mixin node to the list of parents.
|
129
|
+
visit(c)
|
130
|
+
end.flatten
|
131
|
+
rescue Sass::SyntaxError => e
|
132
|
+
e.modify_backtrace(:mixin => node.name, :filename => node.filename, :line => node.line)
|
133
|
+
e.add_backtrace(:filename => node.filename, :line => node.line)
|
134
|
+
raise e
|
135
|
+
end
|
136
|
+
|
137
|
+
# Converts nested properties into flat properties
|
138
|
+
# and updates the indentation of the prop node based on the nesting level.
|
139
|
+
def visit_prop(node)
|
140
|
+
if parent.is_a?(Sass::Tree::PropNode)
|
141
|
+
node.resolved_name = "#{parent.resolved_name}-#{node.resolved_name}"
|
142
|
+
node.tabs = parent.tabs + (parent.resolved_value.empty? ? 0 : 1) if node.style == :nested
|
143
|
+
end
|
144
|
+
|
145
|
+
yield
|
146
|
+
|
147
|
+
if !node.resolved_value.empty? || node.children.empty?
|
148
|
+
node.send(:check!)
|
149
|
+
node.children.unshift(node)
|
150
|
+
end
|
151
|
+
|
152
|
+
node.children
|
153
|
+
end
|
154
|
+
|
155
|
+
# Resolves parent references and nested selectors,
|
156
|
+
# and updates the indentation of the rule node based on the nesting level.
|
157
|
+
def visit_rule(node)
|
158
|
+
parent_resolved_rules = parent.is_a?(Sass::Tree::RuleNode) ? parent.resolved_rules : nil
|
159
|
+
# It's possible for resolved_rules to be set if we've duplicated this node during @media bubbling
|
160
|
+
node.resolved_rules ||= node.parsed_rules.resolve_parent_refs(parent_resolved_rules)
|
161
|
+
|
162
|
+
yield
|
163
|
+
|
164
|
+
rules = node.children.select {|c| c.is_a?(Sass::Tree::RuleNode) || c.is_a?(Sass::Tree::MediaNode)}
|
165
|
+
props = node.children.reject {|c| c.is_a?(Sass::Tree::RuleNode) || c.is_a?(Sass::Tree::MediaNode) || c.invisible?}
|
166
|
+
|
167
|
+
unless props.empty?
|
168
|
+
node.children = props
|
169
|
+
rules.each {|r| r.tabs += 1} if node.style == :nested
|
170
|
+
rules.unshift(node)
|
171
|
+
end
|
172
|
+
|
173
|
+
rules.last.group_end = true unless parent.is_a?(Sass::Tree::RuleNode) || rules.empty?
|
174
|
+
|
175
|
+
rules
|
176
|
+
end
|
177
|
+
end
|