haml 2.0.10 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of haml might be problematic. Click here for more details.
- data/.yardopts +5 -0
- data/MIT-LICENSE +1 -1
- data/README.md +347 -0
- data/Rakefile +124 -19
- data/VERSION +1 -1
- data/VERSION_NAME +1 -0
- data/extra/haml-mode.el +397 -78
- data/extra/sass-mode.el +148 -36
- data/extra/update_watch.rb +13 -0
- data/lib/haml.rb +15 -993
- data/lib/haml/buffer.rb +131 -84
- data/lib/haml/engine.rb +129 -97
- data/lib/haml/error.rb +7 -7
- data/lib/haml/exec.rb +127 -42
- data/lib/haml/filters.rb +107 -42
- data/lib/haml/helpers.rb +210 -156
- data/lib/haml/helpers/action_view_extensions.rb +34 -39
- data/lib/haml/helpers/action_view_mods.rb +132 -139
- data/lib/haml/html.rb +77 -65
- data/lib/haml/precompiler.rb +404 -213
- data/lib/haml/shared.rb +78 -0
- data/lib/haml/template.rb +14 -14
- data/lib/haml/template/patch.rb +2 -2
- data/lib/haml/template/plugin.rb +2 -3
- data/lib/haml/util.rb +211 -6
- data/lib/haml/version.rb +30 -13
- data/lib/sass.rb +7 -856
- data/lib/sass/css.rb +169 -161
- data/lib/sass/engine.rb +344 -328
- data/lib/sass/environment.rb +79 -0
- data/lib/sass/error.rb +33 -11
- data/lib/sass/files.rb +139 -0
- data/lib/sass/plugin.rb +160 -117
- data/lib/sass/plugin/merb.rb +7 -6
- data/lib/sass/plugin/rails.rb +5 -6
- data/lib/sass/repl.rb +58 -0
- data/lib/sass/script.rb +59 -0
- data/lib/sass/script/bool.rb +17 -0
- data/lib/sass/script/color.rb +183 -0
- data/lib/sass/script/funcall.rb +50 -0
- data/lib/sass/script/functions.rb +198 -0
- data/lib/sass/script/lexer.rb +178 -0
- data/lib/sass/script/literal.rb +177 -0
- data/lib/sass/script/node.rb +14 -0
- data/lib/sass/script/number.rb +381 -0
- data/lib/sass/script/operation.rb +45 -0
- data/lib/sass/script/parser.rb +172 -0
- data/lib/sass/script/string.rb +12 -0
- data/lib/sass/script/unary_operation.rb +34 -0
- data/lib/sass/script/variable.rb +31 -0
- data/lib/sass/tree/comment_node.rb +73 -10
- data/lib/sass/tree/debug_node.rb +30 -0
- data/lib/sass/tree/directive_node.rb +42 -17
- data/lib/sass/tree/file_node.rb +41 -0
- data/lib/sass/tree/for_node.rb +48 -0
- data/lib/sass/tree/if_node.rb +54 -0
- data/lib/sass/tree/mixin_def_node.rb +29 -0
- data/lib/sass/tree/mixin_node.rb +48 -0
- data/lib/sass/tree/node.rb +214 -11
- data/lib/sass/tree/prop_node.rb +109 -0
- data/lib/sass/tree/rule_node.rb +178 -51
- data/lib/sass/tree/variable_node.rb +34 -0
- data/lib/sass/tree/while_node.rb +31 -0
- data/test/haml/engine_test.rb +331 -36
- data/test/haml/helper_test.rb +12 -1
- data/test/haml/results/content_for_layout.xhtml +0 -3
- data/test/haml/results/filters.xhtml +2 -0
- data/test/haml/results/list.xhtml +1 -1
- data/test/haml/template_test.rb +7 -2
- data/test/haml/templates/content_for_layout.haml +0 -2
- data/test/haml/templates/list.haml +1 -1
- data/test/haml/util_test.rb +92 -0
- data/test/sass/css2sass_test.rb +69 -24
- data/test/sass/engine_test.rb +586 -64
- data/test/sass/functions_test.rb +125 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +81 -28
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/{constants.css → script.css} +4 -4
- data/test/sass/results/subdir/subdir.css +2 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/script_test.rb +258 -0
- data/test/sass/templates/import.sass +1 -1
- data/test/sass/templates/importee.sass +7 -2
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/{constants.sass → script.sass} +11 -10
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/subdir.sass +2 -2
- data/test/sass/templates/units.sass +11 -0
- data/test/test_helper.rb +14 -0
- metadata +77 -19
- data/FAQ +0 -138
- data/README.rdoc +0 -319
- data/lib/sass/constant.rb +0 -216
- data/lib/sass/constant/color.rb +0 -101
- data/lib/sass/constant/literal.rb +0 -54
- data/lib/sass/constant/nil.rb +0 -9
- data/lib/sass/constant/number.rb +0 -87
- data/lib/sass/constant/operation.rb +0 -30
- data/lib/sass/constant/string.rb +0 -22
- data/lib/sass/tree/attr_node.rb +0 -57
- data/lib/sass/tree/value_node.rb +0 -20
@@ -0,0 +1,41 @@
|
|
1
|
+
module Sass
|
2
|
+
module Tree
|
3
|
+
# A static node that wraps the {Sass::Tree} for an `@import`ed file.
|
4
|
+
# It doesn't have a functional purpose other than to add the `@import`ed file
|
5
|
+
# to the backtrace if an error occurs.
|
6
|
+
class FileNode < Node
|
7
|
+
# @param filename [String] The name of the imported file
|
8
|
+
def initialize(filename)
|
9
|
+
@filename = filename
|
10
|
+
super()
|
11
|
+
end
|
12
|
+
|
13
|
+
# Computes the CSS for the imported file.
|
14
|
+
#
|
15
|
+
# @param args [Array] Ignored
|
16
|
+
def to_s(*args)
|
17
|
+
@to_s ||= (style == :compressed ? super().strip : super())
|
18
|
+
rescue Sass::SyntaxError => e
|
19
|
+
e.add_backtrace_entry(@filename)
|
20
|
+
raise e
|
21
|
+
end
|
22
|
+
|
23
|
+
def invisible?; to_s.empty?; end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
# Parses the imported file
|
28
|
+
# and runs the dynamic Sass for it.
|
29
|
+
#
|
30
|
+
# @param environment [Sass::Environment] The lexical environment containing
|
31
|
+
# variable and mixin values
|
32
|
+
def perform!(environment)
|
33
|
+
self.children = Sass::Files.tree_for(filename, @options).children
|
34
|
+
self.children = perform_children(environment)
|
35
|
+
rescue Sass::SyntaxError => e
|
36
|
+
e.add_backtrace_entry(@filename)
|
37
|
+
raise e
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'sass/tree/node'
|
2
|
+
|
3
|
+
module Sass::Tree
|
4
|
+
# A dynamic node representing a Sass `@for` loop.
|
5
|
+
#
|
6
|
+
# @see Sass::Tree
|
7
|
+
class ForNode < Node
|
8
|
+
# @param var [String] The name of the loop variable
|
9
|
+
# @param from [Script::Node] The parse tree for the initial expression
|
10
|
+
# @param to [Script::Node] The parse tree for the final expression
|
11
|
+
# @param exclusive [Boolean] Whether to include `to` in the loop
|
12
|
+
# or stop just before
|
13
|
+
def initialize(var, from, to, exclusive)
|
14
|
+
@var = var
|
15
|
+
@from = from
|
16
|
+
@to = to
|
17
|
+
@exclusive = exclusive
|
18
|
+
super()
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
# Runs the child nodes once for each time through the loop,
|
24
|
+
# varying the variable each time.
|
25
|
+
#
|
26
|
+
# @param environment [Sass::Environment] The lexical environment containing
|
27
|
+
# variable and mixin values
|
28
|
+
# @return [Array<Tree::Node>] The resulting static nodes
|
29
|
+
# @see Sass::Tree
|
30
|
+
def _perform(environment)
|
31
|
+
from = @from.perform(environment)
|
32
|
+
to = @to.perform(environment)
|
33
|
+
from.assert_int!
|
34
|
+
to.assert_int!
|
35
|
+
|
36
|
+
to = to.coerce(from.numerator_units, from.denominator_units)
|
37
|
+
range = Range.new(from.to_i, to.to_i, @exclusive)
|
38
|
+
|
39
|
+
children = []
|
40
|
+
environment = Sass::Environment.new(environment)
|
41
|
+
range.each do |i|
|
42
|
+
environment.set_local_var(@var, Sass::Script::Number.new(i, from.numerator_units, from.denominator_units))
|
43
|
+
children += perform_children(environment)
|
44
|
+
end
|
45
|
+
children
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'sass/tree/node'
|
2
|
+
|
3
|
+
module Sass::Tree
|
4
|
+
# A dynamic node representing a Sass `@if` statement.
|
5
|
+
#
|
6
|
+
# {IfNode}s are a little odd, in that they also represent `@else` and `@else if`s.
|
7
|
+
# This is done as a linked list:
|
8
|
+
# each {IfNode} has a link (\{#else}) to the next {IfNode}.
|
9
|
+
#
|
10
|
+
# @see Sass::Tree
|
11
|
+
class IfNode < Node
|
12
|
+
# The next {IfNode} in the if-else list, or `nil`.
|
13
|
+
#
|
14
|
+
# @return [IfNode]
|
15
|
+
attr_accessor :else
|
16
|
+
|
17
|
+
# @param expr [Script::Expr] The conditional expression.
|
18
|
+
# If this is nil, this is an `@else` node, not an `@else if`
|
19
|
+
def initialize(expr)
|
20
|
+
@expr = expr
|
21
|
+
@last_else = self
|
22
|
+
super()
|
23
|
+
end
|
24
|
+
|
25
|
+
# Append an `@else` node to the end of the list.
|
26
|
+
#
|
27
|
+
# @param node [IfNode] The `@else` node to append
|
28
|
+
def add_else(node)
|
29
|
+
@last_else.else = node
|
30
|
+
@last_else = node
|
31
|
+
end
|
32
|
+
|
33
|
+
def options=(options)
|
34
|
+
super
|
35
|
+
self.else.options = options if self.else
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
# Runs the child nodes if the conditional expression is true;
|
41
|
+
# otherwise, tries the \{#else} nodes.
|
42
|
+
#
|
43
|
+
# @param environment [Sass::Environment] The lexical environment containing
|
44
|
+
# variable and mixin values
|
45
|
+
# @return [Array<Tree::Node>] The resulting static nodes
|
46
|
+
# @see Sass::Tree
|
47
|
+
def _perform(environment)
|
48
|
+
environment = Sass::Environment.new(environment)
|
49
|
+
return perform_children(environment) if @expr.nil? || @expr.perform(environment).to_bool
|
50
|
+
return @else.perform(environment) if @else
|
51
|
+
[]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Sass
|
2
|
+
module Tree
|
3
|
+
# A dynamic node representing a mixin definition.
|
4
|
+
#
|
5
|
+
# @see Sass::Tree
|
6
|
+
class MixinDefNode < Node
|
7
|
+
# @param name [String] The mixin name
|
8
|
+
# @param args [Array<(String, Script::Node)>] The arguments for the mixin.
|
9
|
+
# Each element is a tuple containing the name of the argument
|
10
|
+
# and the parse tree for the default value of the argument
|
11
|
+
def initialize(name, args)
|
12
|
+
@name = name
|
13
|
+
@args = args
|
14
|
+
super()
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
# Loads the mixin into the environment.
|
20
|
+
#
|
21
|
+
# @param environment [Sass::Environment] The lexical environment containing
|
22
|
+
# variable and mixin values
|
23
|
+
def _perform(environment)
|
24
|
+
environment.set_mixin(@name, Sass::Mixin.new(@name, @args, environment, children))
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'sass/tree/node'
|
2
|
+
|
3
|
+
module Sass::Tree
|
4
|
+
# A dynamic node representing a mixin include.
|
5
|
+
#
|
6
|
+
# @see Sass::Tree
|
7
|
+
class MixinNode < Node
|
8
|
+
# @param name [String] The name of the mixin
|
9
|
+
# @param args [Array<Script::Node>] The arguments to the mixin
|
10
|
+
def initialize(name, args)
|
11
|
+
@name = name
|
12
|
+
@args = args
|
13
|
+
super()
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
# Runs the mixin.
|
19
|
+
#
|
20
|
+
# @param environment [Sass::Environment] The lexical environment containing
|
21
|
+
# variable and mixin values
|
22
|
+
# @return [Array<Tree::Node>] The resulting static nodes
|
23
|
+
# @raise [Sass::SyntaxError] if there is no mixin with the given name
|
24
|
+
# @raise [Sass::SyntaxError] if an incorrect number of arguments was passed
|
25
|
+
# @see Sass::Tree
|
26
|
+
def _perform(environment)
|
27
|
+
raise Sass::SyntaxError.new("Undefined mixin '#{@name}'.", @line) unless mixin = environment.mixin(@name)
|
28
|
+
|
29
|
+
raise Sass::SyntaxError.new(<<END.gsub("\n", "")) if mixin.args.size < @args.size
|
30
|
+
Mixin #{@name} takes #{mixin.args.size} argument#{'s' if mixin.args.size != 1}
|
31
|
+
but #{@args.size} #{@args.size == 1 ? 'was' : 'were'} passed.
|
32
|
+
END
|
33
|
+
|
34
|
+
environment = mixin.args.zip(@args).
|
35
|
+
inject(Sass::Environment.new(mixin.environment)) do |env, ((name, default), value)|
|
36
|
+
env.set_local_var(name,
|
37
|
+
if value
|
38
|
+
value.perform(environment)
|
39
|
+
elsif default
|
40
|
+
default.perform(env)
|
41
|
+
end)
|
42
|
+
raise Sass::SyntaxError.new("Mixin #{@name} is missing parameter !#{name}.") unless env.var(name)
|
43
|
+
env
|
44
|
+
end
|
45
|
+
mixin.tree.map {|c| c.perform(environment)}.flatten
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/sass/tree/node.rb
CHANGED
@@ -1,15 +1,69 @@
|
|
1
1
|
module Sass
|
2
|
+
# A namespace for nodes in the Sass parse tree.
|
3
|
+
#
|
4
|
+
# The Sass parse tree has two states.
|
5
|
+
# When it's first parsed, it has nodes for mixin definitions
|
6
|
+
# and for loops and so forth,
|
7
|
+
# in addition to nodes for CSS rules and properties.
|
8
|
+
#
|
9
|
+
# However, {Tree::Node#perform} returns a different sort of tree.
|
10
|
+
# This tree maps more closely to the resulting CSS document
|
11
|
+
# than it does to the original Sass document.
|
12
|
+
# It still has nodes for CSS rules and properties,
|
13
|
+
# but it doesn't have any dynamic-generation-related nodes.
|
14
|
+
#
|
15
|
+
# Nodes that only appear in the pre-perform state are called **dynamic nodes**;
|
16
|
+
# those that appear in both states are called **static nodes**.
|
2
17
|
module Tree
|
18
|
+
# This class doubles as the root node of the parse tree
|
19
|
+
# and the superclass of all other parse-tree nodes.
|
3
20
|
class Node
|
21
|
+
# The child nodes of this node.
|
22
|
+
#
|
23
|
+
# @return [Array<Tree::Node>]
|
4
24
|
attr_accessor :children
|
25
|
+
|
26
|
+
# The line of the document on which this node appeared.
|
27
|
+
#
|
28
|
+
# @return [Fixnum]
|
5
29
|
attr_accessor :line
|
6
|
-
attr_accessor :filename
|
7
30
|
|
8
|
-
|
9
|
-
|
31
|
+
# The name of the document on which this node appeared.
|
32
|
+
#
|
33
|
+
# @return [String]
|
34
|
+
attr_writer :filename
|
35
|
+
|
36
|
+
# The options hash for the node.
|
37
|
+
# See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
|
38
|
+
#
|
39
|
+
# @return [Hash<Symbol, Object>]
|
40
|
+
attr_reader :options
|
41
|
+
|
42
|
+
def initialize
|
10
43
|
@children = []
|
11
44
|
end
|
12
45
|
|
46
|
+
# Sets the options hash for the node and all its children.
|
47
|
+
#
|
48
|
+
# @param options [Hash<Symbol, Object>] The options
|
49
|
+
# @see #options
|
50
|
+
def options=(options)
|
51
|
+
children.each {|c| c.options = options}
|
52
|
+
@options = options
|
53
|
+
end
|
54
|
+
|
55
|
+
# The name of the document on which this node appeared.
|
56
|
+
#
|
57
|
+
# @return [String]
|
58
|
+
def filename
|
59
|
+
@filename || @options[:filename]
|
60
|
+
end
|
61
|
+
|
62
|
+
# Appends a child to the node.
|
63
|
+
#
|
64
|
+
# @param child [Tree::Node] The child node
|
65
|
+
# @raise [Sass::SyntaxError] if `child` is invalid
|
66
|
+
# @see #invalid_child?
|
13
67
|
def <<(child)
|
14
68
|
if msg = invalid_child?(child)
|
15
69
|
raise Sass::SyntaxError.new(msg, child.line)
|
@@ -17,27 +71,176 @@ module Sass
|
|
17
71
|
@children << child
|
18
72
|
end
|
19
73
|
|
74
|
+
# Return the last child node.
|
75
|
+
#
|
76
|
+
# We need this because {Tree::Node} duck types as an Array for {Sass::Engine}.
|
77
|
+
#
|
78
|
+
# @return [Tree::Node] The last child node
|
79
|
+
def last
|
80
|
+
children.last
|
81
|
+
end
|
82
|
+
|
83
|
+
# Compares this node and another object (only other {Tree::Node}s will be equal).
|
84
|
+
# This does a structural comparison;
|
85
|
+
# if the contents of the nodes and all the child nodes are equivalent,
|
86
|
+
# then the nodes are as well.
|
87
|
+
#
|
88
|
+
# Only static nodes need to override this.
|
89
|
+
#
|
90
|
+
# @param other [Object] The object to compare with
|
91
|
+
# @return [Boolean] Whether or not this node and the other object
|
92
|
+
# are the same
|
93
|
+
# @see Sass::Tree
|
20
94
|
def ==(other)
|
21
95
|
self.class == other.class && other.children == children
|
22
96
|
end
|
23
97
|
|
98
|
+
# Runs the dynamic Sass code *and* computes the CSS for the tree.
|
99
|
+
#
|
100
|
+
# @see #perform
|
101
|
+
# @see #to_s
|
102
|
+
def render
|
103
|
+
perform(Environment.new).to_s
|
104
|
+
end
|
105
|
+
|
106
|
+
# True if \{#to\_s} will return `nil`;
|
107
|
+
# that is, if the node shouldn't be rendered.
|
108
|
+
# Should only be called in a static tree.
|
109
|
+
#
|
110
|
+
# @return [Boolean]
|
111
|
+
def invisible?; false; end
|
112
|
+
|
113
|
+
# Computes the CSS corresponding to this Sass tree.
|
114
|
+
#
|
115
|
+
# Only static-node subclasses need to implement \{#to\_s}.
|
116
|
+
#
|
117
|
+
# This may return `nil`, but it will only do so if \{#invisible?} is true.
|
118
|
+
#
|
119
|
+
# @return [String, nil] The resulting CSS
|
120
|
+
# @raise [Sass::SyntaxError] if some element of the tree is invalid
|
121
|
+
# @see Sass::Tree
|
24
122
|
def to_s
|
25
123
|
result = String.new
|
26
124
|
children.each do |child|
|
27
|
-
if child.is_a?
|
28
|
-
raise SyntaxError.new('
|
125
|
+
if child.is_a? PropNode
|
126
|
+
raise Sass::SyntaxError.new('Properties aren\'t allowed at the root of a document.', child.line)
|
29
127
|
else
|
30
|
-
|
128
|
+
next if child.invisible?
|
129
|
+
child_str = child.to_s(1)
|
130
|
+
result << child_str + (style == :compressed ? '' : "\n")
|
31
131
|
end
|
32
132
|
end
|
33
|
-
|
133
|
+
result.rstrip!
|
134
|
+
return "" if result.empty?
|
135
|
+
return result + "\n"
|
136
|
+
rescue Sass::SyntaxError => e; e.add_metadata(filename, line)
|
34
137
|
end
|
35
138
|
|
36
|
-
|
139
|
+
# Runs the dynamic Sass code:
|
140
|
+
# mixins, variables, control directives, and so forth.
|
141
|
+
# This doesn't modify this node or any of its children.
|
142
|
+
#
|
143
|
+
# \{#perform} shouldn't be overridden directly;
|
144
|
+
# if you want to return a new node (or list of nodes),
|
145
|
+
# override \{#\_perform};
|
146
|
+
# if you want to destructively modify this node,
|
147
|
+
# override \{#perform!}.
|
148
|
+
#
|
149
|
+
# @param environment [Sass::Environment] The lexical environment containing
|
150
|
+
# variable and mixin values
|
151
|
+
# @return [Tree::Node] The resulting tree of static nodes
|
152
|
+
# @raise [Sass::SyntaxError] if some element of the tree is invalid
|
153
|
+
# @see Sass::Tree
|
154
|
+
def perform(environment)
|
155
|
+
environment.options = @options if self.class == Tree::Node
|
156
|
+
_perform(environment)
|
157
|
+
rescue Sass::SyntaxError => e; e.add_metadata(filename, line)
|
158
|
+
end
|
159
|
+
|
160
|
+
# The output style. See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
|
161
|
+
#
|
162
|
+
# @return [Symbol]
|
163
|
+
def style
|
164
|
+
@options[:style]
|
165
|
+
end
|
166
|
+
|
167
|
+
protected
|
168
|
+
|
169
|
+
# Runs any dynamic Sass code in this particular node.
|
170
|
+
# This doesn't modify this node or any of its children.
|
171
|
+
#
|
172
|
+
# @param environment [Sass::Environment] The lexical environment containing
|
173
|
+
# variable and mixin values
|
174
|
+
# @return [Tree::Node, Array<Tree::Node>] The resulting static nodes
|
175
|
+
# @see #perform
|
176
|
+
# @see Sass::Tree
|
177
|
+
def _perform(environment)
|
178
|
+
node = dup
|
179
|
+
node.perform!(environment)
|
180
|
+
node
|
181
|
+
end
|
182
|
+
|
183
|
+
# Destructively runs dynamic Sass code in this particular node.
|
184
|
+
# This *does* modify this node,
|
185
|
+
# but will be run non-destructively by \{#\_perform\}.
|
186
|
+
#
|
187
|
+
# @param environment [Sass::Environment] The lexical environment containing
|
188
|
+
# variable and mixin values
|
189
|
+
# @see #perform
|
190
|
+
def perform!(environment)
|
191
|
+
self.children = perform_children(Environment.new(environment))
|
192
|
+
end
|
193
|
+
|
194
|
+
# Non-destructively runs \{#perform} on all children of the current node.
|
195
|
+
#
|
196
|
+
# @param environment [Sass::Environment] The lexical environment containing
|
197
|
+
# variable and mixin values
|
198
|
+
# @return [Array<Tree::Node>] The resulting static nodes
|
199
|
+
def perform_children(environment)
|
200
|
+
children.map {|c| c.perform(environment)}.flatten
|
201
|
+
end
|
202
|
+
|
203
|
+
# Replaces SassScript in a chunk of text (via `#{}`)
|
204
|
+
# with the resulting value.
|
205
|
+
#
|
206
|
+
# @param text [String] The text to interpolate
|
207
|
+
# @param environment [Sass::Environment] The lexical environment containing
|
208
|
+
# variable and mixin values
|
209
|
+
# @return [String] The interpolated text
|
210
|
+
def interpolate(text, environment)
|
211
|
+
res = ''
|
212
|
+
rest = Haml::Shared.handle_interpolation text do |scan|
|
213
|
+
escapes = scan[2].size
|
214
|
+
res << scan.matched[0...-2 - escapes]
|
215
|
+
if escapes % 2 == 1
|
216
|
+
res << "\\" * (escapes - 1) << '#{'
|
217
|
+
else
|
218
|
+
res << "\\" * [0, escapes - 1].max
|
219
|
+
res << Script::Parser.new(scan, line, scan.pos - scan.matched_size, filename).
|
220
|
+
parse_interpolated.perform(environment).to_s
|
221
|
+
end
|
222
|
+
end
|
223
|
+
res + rest
|
224
|
+
end
|
225
|
+
|
226
|
+
# @see Haml::Shared.balance
|
227
|
+
# @raise [Sass::SyntaxError] if the brackets aren't balanced
|
228
|
+
def balance(*args)
|
229
|
+
res = Haml::Shared.balance(*args)
|
230
|
+
return res if res
|
231
|
+
raise Sass::SyntaxError.new("Unbalanced brackets.", line)
|
232
|
+
end
|
37
233
|
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
234
|
+
# Returns an error message if the given child node is invalid,
|
235
|
+
# and false otherwise.
|
236
|
+
#
|
237
|
+
# By default, all child nodes are valid.
|
238
|
+
# This is expected to be overriden by subclasses
|
239
|
+
# for which some children are invalid.
|
240
|
+
#
|
241
|
+
# @param child [Tree::Node] A potential child node
|
242
|
+
# @return [Boolean, String] Whether or not the child node is valid,
|
243
|
+
# as well as the error message to display if it is invalid
|
41
244
|
def invalid_child?(child)
|
42
245
|
false
|
43
246
|
end
|