haml-edge 2.3.179 → 2.3.180
Sign up to get free protection for your applications and to get access to all the features.
- data/EDGE_GEM_VERSION +1 -1
- data/README.md +88 -149
- data/VERSION +1 -1
- data/bin/css2sass +7 -1
- data/bin/sass-convert +7 -0
- data/lib/haml/exec.rb +95 -22
- data/lib/haml/template.rb +1 -1
- data/lib/haml/util.rb +50 -0
- data/lib/sass.rb +1 -1
- data/lib/sass/css.rb +38 -210
- data/lib/sass/engine.rb +121 -47
- data/lib/sass/files.rb +28 -19
- data/lib/sass/plugin.rb +32 -43
- data/lib/sass/repl.rb +1 -1
- data/lib/sass/script.rb +25 -6
- data/lib/sass/script/bool.rb +1 -0
- data/lib/sass/script/color.rb +2 -2
- data/lib/sass/script/css_lexer.rb +22 -0
- data/lib/sass/script/css_parser.rb +28 -0
- data/lib/sass/script/funcall.rb +17 -9
- data/lib/sass/script/functions.rb +46 -1
- data/lib/sass/script/interpolation.rb +42 -0
- data/lib/sass/script/lexer.rb +142 -34
- data/lib/sass/script/literal.rb +28 -12
- data/lib/sass/script/node.rb +57 -1
- data/lib/sass/script/number.rb +18 -3
- data/lib/sass/script/operation.rb +44 -8
- data/lib/sass/script/parser.rb +149 -24
- data/lib/sass/script/string.rb +50 -2
- data/lib/sass/script/unary_operation.rb +25 -10
- data/lib/sass/script/variable.rb +20 -11
- data/lib/sass/scss.rb +14 -0
- data/lib/sass/scss/css_parser.rb +39 -0
- data/lib/sass/scss/parser.rb +683 -0
- data/lib/sass/scss/rx.rb +112 -0
- data/lib/sass/scss/script_lexer.rb +13 -0
- data/lib/sass/scss/script_parser.rb +25 -0
- data/lib/sass/tree/comment_node.rb +58 -16
- data/lib/sass/tree/debug_node.rb +7 -2
- data/lib/sass/tree/directive_node.rb +38 -34
- data/lib/sass/tree/for_node.rb +6 -0
- data/lib/sass/tree/if_node.rb +13 -0
- data/lib/sass/tree/import_node.rb +26 -7
- data/lib/sass/tree/mixin_def_node.rb +18 -0
- data/lib/sass/tree/mixin_node.rb +16 -1
- data/lib/sass/tree/node.rb +98 -27
- data/lib/sass/tree/prop_node.rb +97 -20
- data/lib/sass/tree/root_node.rb +37 -0
- data/lib/sass/tree/rule_node.rb +88 -60
- data/lib/sass/tree/variable_node.rb +9 -5
- data/lib/sass/tree/while_node.rb +4 -0
- data/test/haml/results/filters.xhtml +1 -1
- data/test/haml/util_test.rb +28 -0
- data/test/sass/conversion_test.rb +884 -0
- data/test/sass/css2sass_test.rb +46 -21
- data/test/sass/engine_test.rb +680 -160
- data/test/sass/functions_test.rb +27 -0
- data/test/sass/more_results/more_import.css +1 -1
- data/test/sass/more_templates/more_import.sass +3 -3
- data/test/sass/plugin_test.rb +28 -8
- data/test/sass/results/compact.css +1 -1
- data/test/sass/results/complex.css +5 -5
- data/test/sass/results/compressed.css +1 -1
- data/test/sass/results/expanded.css +1 -1
- data/test/sass/results/import.css +3 -1
- data/test/sass/results/mixins.css +12 -12
- data/test/sass/results/nested.css +1 -1
- data/test/sass/results/parent_ref.css +4 -4
- data/test/sass/results/script.css +3 -3
- data/test/sass/results/scss_import.css +15 -0
- data/test/sass/results/scss_importee.css +2 -0
- data/test/sass/script_conversion_test.rb +153 -0
- data/test/sass/script_test.rb +44 -54
- data/test/sass/scss/css_test.rb +811 -0
- data/test/sass/scss/rx_test.rb +156 -0
- data/test/sass/scss/scss_test.rb +871 -0
- data/test/sass/scss/test_helper.rb +37 -0
- data/test/sass/templates/alt.sass +2 -2
- data/test/sass/templates/bork1.sass +1 -1
- data/test/sass/templates/import.sass +4 -4
- data/test/sass/templates/importee.sass +3 -3
- data/test/sass/templates/line_numbers.sass +1 -1
- data/test/sass/templates/mixins.sass +2 -2
- data/test/sass/templates/nested_mixin_bork.sass +1 -1
- data/test/sass/templates/options.sass +1 -1
- data/test/sass/templates/parent_ref.sass +2 -2
- data/test/sass/templates/script.sass +69 -69
- data/test/sass/templates/scss_import.scss +10 -0
- data/test/sass/templates/scss_importee.scss +1 -0
- data/test/sass/templates/units.sass +10 -10
- data/test/test_helper.rb +4 -4
- metadata +27 -2
@@ -16,6 +16,24 @@ module Sass
|
|
16
16
|
|
17
17
|
protected
|
18
18
|
|
19
|
+
def to_src(tabs, opts, fmt)
|
20
|
+
args =
|
21
|
+
if @args.empty?
|
22
|
+
""
|
23
|
+
else
|
24
|
+
'(' + @args.map do |v, d|
|
25
|
+
if d
|
26
|
+
"#{v.to_sass}: #{d.to_sass}"
|
27
|
+
else
|
28
|
+
v.to_sass
|
29
|
+
end
|
30
|
+
end.join(", ") + ')'
|
31
|
+
end
|
32
|
+
|
33
|
+
"#{' ' * tabs}#{fmt == :sass ? '=' : '@mixin '}#{@name}#{args}" +
|
34
|
+
children_to_src(tabs, opts, fmt)
|
35
|
+
end
|
36
|
+
|
19
37
|
# Loads the mixin into the environment.
|
20
38
|
#
|
21
39
|
# @param environment [Sass::Environment] The lexical environment containing
|
data/lib/sass/tree/mixin_node.rb
CHANGED
@@ -7,6 +7,12 @@ module Sass::Tree
|
|
7
7
|
#
|
8
8
|
# @see Sass::Tree
|
9
9
|
class MixinNode < Node
|
10
|
+
# @see Node#options=
|
11
|
+
def options=(opts)
|
12
|
+
super
|
13
|
+
@args.each {|a| a.context = :equals} if opts[:sass2]
|
14
|
+
end
|
15
|
+
|
10
16
|
# @param name [String] The name of the mixin
|
11
17
|
# @param args [Array<Script::Node>] The arguments to the mixin
|
12
18
|
def initialize(name, args)
|
@@ -22,6 +28,11 @@ module Sass::Tree
|
|
22
28
|
|
23
29
|
protected
|
24
30
|
|
31
|
+
def to_src(tabs, opts, fmt)
|
32
|
+
args = '(' + @args.map {|a| a.to_sass}.join(", ") + ')' unless @args.empty?
|
33
|
+
"#{' ' * tabs}#{fmt == :sass ? '+' : '@include '}#{@name}#{args}#{semi fmt}\n"
|
34
|
+
end
|
35
|
+
|
25
36
|
# @see Node#_cssize
|
26
37
|
def _cssize(parent)
|
27
38
|
children.map {|c| c.cssize(parent)}.flatten
|
@@ -52,7 +63,11 @@ END
|
|
52
63
|
if value
|
53
64
|
value.perform(environment)
|
54
65
|
elsif default
|
55
|
-
default.perform(env)
|
66
|
+
val = default.perform(env)
|
67
|
+
if default.context == :equals && val.is_a?(Sass::Script::String)
|
68
|
+
val = Sass::Script::String.new(val.value)
|
69
|
+
end
|
70
|
+
val
|
56
71
|
end)
|
57
72
|
raise Sass::SyntaxError.new("Mixin #{@name} is missing parameter #{var.inspect}.") unless env.var(var.name)
|
58
73
|
env
|
data/lib/sass/tree/node.rb
CHANGED
@@ -26,11 +26,20 @@ module Sass
|
|
26
26
|
module Tree
|
27
27
|
# The abstract superclass of all parse-tree nodes.
|
28
28
|
class Node
|
29
|
+
include Enumerable
|
30
|
+
|
29
31
|
# The child nodes of this node.
|
30
32
|
#
|
31
33
|
# @return [Array<Tree::Node>]
|
32
34
|
attr_accessor :children
|
33
35
|
|
36
|
+
# Whether or not this node has child nodes.
|
37
|
+
# This may be true even when \{#children} is empty,
|
38
|
+
# in which case this node has an empty block (e.g. `{}`).
|
39
|
+
#
|
40
|
+
# @return [Boolean]
|
41
|
+
attr_accessor :has_children
|
42
|
+
|
34
43
|
# The line of the document on which this node appeared.
|
35
44
|
#
|
36
45
|
# @return [Fixnum]
|
@@ -60,6 +69,12 @@ module Sass
|
|
60
69
|
@options = options
|
61
70
|
end
|
62
71
|
|
72
|
+
# @private
|
73
|
+
def children=(children)
|
74
|
+
self.has_children ||= !children.empty?
|
75
|
+
@children = children
|
76
|
+
end
|
77
|
+
|
63
78
|
# The name of the document on which this node appeared.
|
64
79
|
#
|
65
80
|
# @return [String]
|
@@ -73,21 +88,14 @@ module Sass
|
|
73
88
|
# @raise [Sass::SyntaxError] if `child` is invalid
|
74
89
|
# @see #invalid_child?
|
75
90
|
def <<(child)
|
91
|
+
return if child.nil?
|
76
92
|
if msg = invalid_child?(child)
|
77
93
|
raise Sass::SyntaxError.new(msg, :line => child.line)
|
78
94
|
end
|
95
|
+
self.has_children = true
|
79
96
|
@children << child
|
80
97
|
end
|
81
98
|
|
82
|
-
# Return the last child node.
|
83
|
-
#
|
84
|
-
# We need this because {Tree::Node} duck types as an Array for {Sass::Engine}.
|
85
|
-
#
|
86
|
-
# @return [Tree::Node] The last child node
|
87
|
-
def last
|
88
|
-
children.last
|
89
|
-
end
|
90
|
-
|
91
99
|
# Compares this node and another object (only other {Tree::Node}s will be equal).
|
92
100
|
# This does a structural comparison;
|
93
101
|
# if the contents of the nodes and all the child nodes are equivalent,
|
@@ -180,6 +188,34 @@ module Sass
|
|
180
188
|
raise e
|
181
189
|
end
|
182
190
|
|
191
|
+
# Iterates through each node in the tree rooted at this node
|
192
|
+
# in a pre-order walk.
|
193
|
+
#
|
194
|
+
# @yield node
|
195
|
+
# @yieldparam node [Node] a node in the tree
|
196
|
+
def each(&block)
|
197
|
+
yield self
|
198
|
+
children.each {|c| c.each(&block)}
|
199
|
+
end
|
200
|
+
|
201
|
+
# Converts a node to Sass code that will generate it.
|
202
|
+
#
|
203
|
+
# @param tabs [Fixnum] The amount of tabulation to use for the Sass code
|
204
|
+
# @param opts [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
|
205
|
+
# @return [String] The Sass code corresponding to the node
|
206
|
+
def to_sass(tabs = 0, opts = {})
|
207
|
+
to_src(tabs, opts, :sass)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Converts a node to SCSS code that will generate it.
|
211
|
+
#
|
212
|
+
# @param tabs [Fixnum] The amount of tabulation to use for the SCSS code
|
213
|
+
# @param opts [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
|
214
|
+
# @return [String] The Sass code corresponding to the node
|
215
|
+
def to_scss(tabs = 0, opts = {})
|
216
|
+
to_src(tabs, opts, :scss)
|
217
|
+
end
|
218
|
+
|
183
219
|
protected
|
184
220
|
|
185
221
|
# Computes the CSS corresponding to this particular Sass node.
|
@@ -258,27 +294,21 @@ module Sass
|
|
258
294
|
children.map {|c| c.perform(environment)}.flatten
|
259
295
|
end
|
260
296
|
|
261
|
-
# Replaces SassScript in a chunk of text
|
297
|
+
# Replaces SassScript in a chunk of text
|
262
298
|
# with the resulting value.
|
263
299
|
#
|
264
|
-
# @param text [String] The text to interpolate
|
300
|
+
# @param text [Array<String, Sass::Script::Node>] The text to interpolate
|
265
301
|
# @param environment [Sass::Environment] The lexical environment containing
|
266
302
|
# variable and mixin values
|
267
303
|
# @return [String] The interpolated text
|
268
|
-
def
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
res << "\\" * [0, escapes - 1].max
|
277
|
-
res << Script::Parser.new(scan, line, scan.pos - scan.matched_size, filename).
|
278
|
-
parse_interpolated.perform(environment).to_s
|
279
|
-
end
|
280
|
-
end
|
281
|
-
res + rest
|
304
|
+
def run_interp(text, environment)
|
305
|
+
text.map do |r|
|
306
|
+
next r if r.is_a?(String)
|
307
|
+
val = r.perform(environment)
|
308
|
+
# Interpolated strings should never render with quotes
|
309
|
+
next val.value if val.is_a?(Sass::Script::String)
|
310
|
+
val.to_s
|
311
|
+
end.join.strip
|
282
312
|
end
|
283
313
|
|
284
314
|
# @see Haml::Shared.balance
|
@@ -292,7 +322,8 @@ module Sass
|
|
292
322
|
# Returns an error message if the given child node is invalid,
|
293
323
|
# and false otherwise.
|
294
324
|
#
|
295
|
-
# By default, all child nodes
|
325
|
+
# By default, all child nodes except those only allowed at root level
|
326
|
+
# ({Tree::MixinDefNode}, {Tree::ImportNode}) are valid.
|
296
327
|
# This is expected to be overriden by subclasses
|
297
328
|
# for which some children are invalid.
|
298
329
|
#
|
@@ -300,7 +331,47 @@ module Sass
|
|
300
331
|
# @return [Boolean, String] Whether or not the child node is valid,
|
301
332
|
# as well as the error message to display if it is invalid
|
302
333
|
def invalid_child?(child)
|
303
|
-
|
334
|
+
case child
|
335
|
+
when Tree::MixinDefNode
|
336
|
+
"Mixins may only be defined at the root of a document."
|
337
|
+
when Tree::ImportNode
|
338
|
+
"Import directives may only be used at the root of a document."
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
# Converts a node to Sass or SCSS code that will generate it.
|
343
|
+
#
|
344
|
+
# This method is called by the default \{#to\_sass} and \{#to\_scss} methods,
|
345
|
+
# so that the same code can be used for both with minor variations.
|
346
|
+
#
|
347
|
+
# @param tabs [Fixnum] The amount of tabulation to use for the SCSS code
|
348
|
+
# @param opts [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
|
349
|
+
# @param fmt [Symbol] `:sass` or `:scss`
|
350
|
+
# @return [String] The Sass or SCSS code corresponding to the node
|
351
|
+
def to_src(tabs, opts, fmt)
|
352
|
+
raise NotImplementedError.new("All static-node subclasses of Sass::Tree::Node must override #to_#{fmt}.")
|
353
|
+
end
|
354
|
+
|
355
|
+
# Converts the children of this node to a Sass or SCSS string.
|
356
|
+
# This will return the trailing newline for the previous line,
|
357
|
+
# including brackets if this is SCSS.
|
358
|
+
#
|
359
|
+
# @param tabs [Fixnum] The amount of tabulation to use for the Sass code
|
360
|
+
# @param opts [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
|
361
|
+
# @param fmt [Symbol] `:sass` or `:scss`
|
362
|
+
# @return [String] The Sass or CSS code corresponding to the children
|
363
|
+
def children_to_src(tabs, opts, fmt)
|
364
|
+
(fmt == :sass ? "\n" : " {\n") +
|
365
|
+
children.map {|c| c.send("to_#{fmt}", tabs + 1, opts)}.join.rstrip +
|
366
|
+
(fmt == :sass ? "\n" : " }\n")
|
367
|
+
end
|
368
|
+
|
369
|
+
# Returns a semicolon if this is SCSS, or an empty string if this is Sass.
|
370
|
+
#
|
371
|
+
# @param fmt [Symbol] `:sass` or `:scss`
|
372
|
+
# @return [String] A semicolon or the empty string
|
373
|
+
def semi(fmt)
|
374
|
+
fmt == :sass ? "" : ";"
|
304
375
|
end
|
305
376
|
end
|
306
377
|
end
|
data/lib/sass/tree/prop_node.rb
CHANGED
@@ -3,17 +3,33 @@ module Sass::Tree
|
|
3
3
|
#
|
4
4
|
# @see Sass::Tree
|
5
5
|
class PropNode < Node
|
6
|
-
# The name of the property
|
6
|
+
# The name of the property,
|
7
|
+
# interspersed with {Sass::Script::Node}s
|
8
|
+
# representing `#{}`-interpolation.
|
9
|
+
# Any adjacent strings will be merged together.
|
7
10
|
#
|
8
|
-
# @return [String]
|
11
|
+
# @return [Array<String, Sass::Script::Node>]
|
9
12
|
attr_accessor :name
|
10
13
|
|
11
|
-
# The
|
12
|
-
#
|
14
|
+
# The name of the property
|
15
|
+
# after any interpolated SassScript has been resolved.
|
16
|
+
# Only set once \{Tree::Node#perform} has been called.
|
17
|
+
#
|
18
|
+
# @return [String]
|
19
|
+
attr_accessor :resolved_name
|
20
|
+
|
21
|
+
# The value of the property.
|
13
22
|
#
|
14
|
-
# @return [
|
23
|
+
# @return [Sass::Script::Node]
|
15
24
|
attr_accessor :value
|
16
25
|
|
26
|
+
# The value of the property
|
27
|
+
# after any interpolated SassScript has been resolved.
|
28
|
+
# Only set once \{Tree::Node#perform} has been called.
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
attr_accessor :resolved_value
|
32
|
+
|
17
33
|
# How deep this property is indented
|
18
34
|
# relative to a normal property.
|
19
35
|
# This is only greater than 0 in the case that:
|
@@ -26,12 +42,13 @@ module Sass::Tree
|
|
26
42
|
# @return [Fixnum]
|
27
43
|
attr_accessor :tabs
|
28
44
|
|
29
|
-
# @param name [String] See \{#name}
|
30
|
-
# @param value [
|
45
|
+
# @param name [Array<String, Sass::Script::Node>] See \{#name}
|
46
|
+
# @param value [Sass::Script::Node] See \{#value}
|
31
47
|
# @param prop_syntax [Symbol] `:new` if this property uses `a: b`-style syntax,
|
32
48
|
# `:old` if it uses `:a b`-style syntax
|
33
49
|
def initialize(name, value, prop_syntax)
|
34
|
-
@name =
|
50
|
+
@name = Haml::Util.strip_string_array(
|
51
|
+
Haml::Util.merge_adjacent_strings(name))
|
35
52
|
@value = value
|
36
53
|
@tabs = 0
|
37
54
|
@prop_syntax = prop_syntax
|
@@ -51,21 +68,33 @@ module Sass::Tree
|
|
51
68
|
# This only applies for old-style properties with no value,
|
52
69
|
# so returns the empty string if this is new-style.
|
53
70
|
#
|
71
|
+
# This should only be called once \{#perform} has been called.
|
72
|
+
#
|
54
73
|
# @return [String] The message
|
55
74
|
def pseudo_class_selector_message
|
56
|
-
return "" if @prop_syntax == :new || !
|
75
|
+
return "" if @prop_syntax == :new || !resolved_value.empty?
|
57
76
|
"\nIf #{declaration.dump} should be a selector, use \"\\#{declaration}\" instead."
|
58
77
|
end
|
59
78
|
|
60
79
|
protected
|
61
80
|
|
81
|
+
def to_src(tabs, opts, fmt)
|
82
|
+
name = self.name.map {|n| n.is_a?(String) ? n : "\#{#{n.to_sass}}"}.join
|
83
|
+
old = opts[:old] && fmt == :sass
|
84
|
+
initial = old ? ':' : ''
|
85
|
+
mid = old ? '' : ':'
|
86
|
+
res = "#{' ' * tabs}#{initial}#{name}#{mid} #{self.class.val_to_sass(value)}"
|
87
|
+
return res + "#{semi fmt}\n" if children.empty?
|
88
|
+
res.rstrip + children_to_src(tabs, opts, fmt)
|
89
|
+
end
|
90
|
+
|
62
91
|
# Computes the CSS for the property.
|
63
92
|
#
|
64
93
|
# @param tabs [Fixnum] The level of indentation for the CSS
|
65
94
|
# @return [String] The resulting CSS
|
66
95
|
def _to_s(tabs)
|
67
|
-
to_return = ' ' * (tabs - 1 + self.tabs) +
|
68
|
-
(style == :compressed ? '' : ' ') +
|
96
|
+
to_return = ' ' * (tabs - 1 + self.tabs) + resolved_name + ":" +
|
97
|
+
(style == :compressed ? '' : ' ') + resolved_value + (style == :compressed ? "" : ";")
|
69
98
|
end
|
70
99
|
|
71
100
|
# Converts nested properties into flat properties.
|
@@ -76,7 +105,7 @@ module Sass::Tree
|
|
76
105
|
def _cssize(parent)
|
77
106
|
node = super
|
78
107
|
result = node.children.dup
|
79
|
-
if !node.
|
108
|
+
if !node.resolved_value.empty? || node.children.empty?
|
80
109
|
node.send(:check!)
|
81
110
|
result.unshift(node)
|
82
111
|
end
|
@@ -89,8 +118,8 @@ module Sass::Tree
|
|
89
118
|
# @param parent [PropNode, nil] The parent node of this node,
|
90
119
|
# or nil if the parent isn't a {PropNode}
|
91
120
|
def cssize!(parent)
|
92
|
-
self.
|
93
|
-
self.tabs = parent.tabs + (parent.
|
121
|
+
self.resolved_name = "#{parent.resolved_name}-#{resolved_name}" if parent
|
122
|
+
self.tabs = parent.tabs + (parent.resolved_value.empty? ? 0 : 1) if parent && style == :nested
|
94
123
|
super
|
95
124
|
end
|
96
125
|
|
@@ -100,8 +129,14 @@ module Sass::Tree
|
|
100
129
|
# @param environment [Sass::Environment] The lexical environment containing
|
101
130
|
# variable and mixin values
|
102
131
|
def perform!(environment)
|
103
|
-
@
|
104
|
-
|
132
|
+
@resolved_name = run_interp(@name, environment)
|
133
|
+
val = @value.perform(environment)
|
134
|
+
@resolved_value =
|
135
|
+
if @value.context == :equals && val.is_a?(Sass::Script::String)
|
136
|
+
val.value
|
137
|
+
else
|
138
|
+
val.to_s
|
139
|
+
end
|
105
140
|
super
|
106
141
|
end
|
107
142
|
|
@@ -124,16 +159,58 @@ module Sass::Tree
|
|
124
159
|
raise Sass::SyntaxError.new("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.")
|
125
160
|
elsif @options[:property_syntax] == :new && @prop_syntax == :old
|
126
161
|
raise Sass::SyntaxError.new("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.")
|
127
|
-
elsif
|
128
|
-
raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no \";\" required at end-of-line).")
|
129
|
-
elsif value.empty?
|
162
|
+
elsif resolved_value.empty?
|
130
163
|
raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no value)." +
|
131
164
|
pseudo_class_selector_message)
|
132
165
|
end
|
133
166
|
end
|
134
167
|
|
135
168
|
def declaration
|
136
|
-
|
169
|
+
if @prop_syntax == :new
|
170
|
+
"#{resolved_name}: #{resolved_value}"
|
171
|
+
else
|
172
|
+
":#{resolved_name} #{resolved_value}"
|
173
|
+
end.strip
|
174
|
+
end
|
175
|
+
|
176
|
+
class << self
|
177
|
+
# @private
|
178
|
+
def val_to_sass(value)
|
179
|
+
return value.to_sass unless value.context == :equals
|
180
|
+
val_to_sass_comma(value).to_sass
|
181
|
+
end
|
182
|
+
|
183
|
+
private
|
184
|
+
|
185
|
+
def val_to_sass_comma(node)
|
186
|
+
return node unless node.is_a?(Sass::Script::Operation)
|
187
|
+
return val_to_sass_concat(node) unless node.operator == :comma
|
188
|
+
|
189
|
+
Sass::Script::Operation.new(
|
190
|
+
val_to_sass_concat(node.operand1),
|
191
|
+
val_to_sass_comma(node.operand2),
|
192
|
+
node.operator)
|
193
|
+
end
|
194
|
+
|
195
|
+
def val_to_sass_concat(node)
|
196
|
+
return node unless node.is_a?(Sass::Script::Operation)
|
197
|
+
return val_to_sass_div(node) unless node.operator == :concat
|
198
|
+
|
199
|
+
Sass::Script::Operation.new(
|
200
|
+
val_to_sass_div(node.operand1),
|
201
|
+
val_to_sass_concat(node.operand2),
|
202
|
+
node.operator)
|
203
|
+
end
|
204
|
+
|
205
|
+
def val_to_sass_div(node)
|
206
|
+
unless node.is_a?(Sass::Script::Operation) && node.operator == :div &&
|
207
|
+
node.operand1.is_a?(Sass::Script::Number) &&
|
208
|
+
node.operand2.is_a?(Sass::Script::Number)
|
209
|
+
return node
|
210
|
+
end
|
211
|
+
|
212
|
+
Sass::Script::String.new("(#{node.to_sass})")
|
213
|
+
end
|
137
214
|
end
|
138
215
|
end
|
139
216
|
end
|
data/lib/sass/tree/root_node.rb
CHANGED
@@ -44,8 +44,37 @@ module Sass
|
|
44
44
|
super
|
45
45
|
end
|
46
46
|
|
47
|
+
# Converts a node to Sass code that will generate it.
|
48
|
+
#
|
49
|
+
# @param opts [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
|
50
|
+
# @return [String] The Sass code corresponding to the node
|
51
|
+
def to_sass(opts = {})
|
52
|
+
to_src(opts, :sass)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Converts a node to SCSS code that will generate it.
|
56
|
+
#
|
57
|
+
# @param opts [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
|
58
|
+
# @return [String] The SCSS code corresponding to the node
|
59
|
+
def to_scss(opts = {})
|
60
|
+
to_src(opts, :scss)
|
61
|
+
end
|
62
|
+
|
47
63
|
protected
|
48
64
|
|
65
|
+
def to_src(opts, fmt)
|
66
|
+
Haml::Util.enum_cons(children + [nil], 2).map do |child, nxt|
|
67
|
+
child.send("to_#{fmt}", 0, opts) +
|
68
|
+
if nxt &&
|
69
|
+
(child.is_a?(CommentNode) && child.line + child.value.count("\n") + 1 == nxt.line) ||
|
70
|
+
(child.is_a?(ImportNode) && nxt.is_a?(ImportNode) && child.line + 1 == nxt.line)
|
71
|
+
""
|
72
|
+
else
|
73
|
+
"\n"
|
74
|
+
end
|
75
|
+
end.join.rstrip + "\n"
|
76
|
+
end
|
77
|
+
|
49
78
|
# Destructively converts this static Sass node into a static CSS node,
|
50
79
|
# and checks that there are no properties at root level.
|
51
80
|
#
|
@@ -76,6 +105,14 @@ module Sass
|
|
76
105
|
return "" if result.empty?
|
77
106
|
return result + "\n"
|
78
107
|
end
|
108
|
+
|
109
|
+
# Returns false, because all nodes are allowed at the root of the document
|
110
|
+
# (properties are detected elsewhere post-mixin-resolution).
|
111
|
+
#
|
112
|
+
# @see Node#invalid_child?
|
113
|
+
def invalid_child?(child)
|
114
|
+
false
|
115
|
+
end
|
79
116
|
end
|
80
117
|
end
|
81
118
|
end
|