drnic-haml 2.3.0

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.
Files changed (190) hide show
  1. data/.yardopts +5 -0
  2. data/CONTRIBUTING +4 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +347 -0
  5. data/REVISION +1 -0
  6. data/Rakefile +371 -0
  7. data/VERSION +1 -0
  8. data/VERSION_NAME +1 -0
  9. data/bin/css2sass +7 -0
  10. data/bin/haml +9 -0
  11. data/bin/html2haml +7 -0
  12. data/bin/sass +8 -0
  13. data/extra/haml-mode.el +663 -0
  14. data/extra/sass-mode.el +205 -0
  15. data/extra/update_watch.rb +13 -0
  16. data/init.rb +8 -0
  17. data/lib/haml.rb +40 -0
  18. data/lib/haml/buffer.rb +307 -0
  19. data/lib/haml/engine.rb +301 -0
  20. data/lib/haml/error.rb +22 -0
  21. data/lib/haml/exec.rb +470 -0
  22. data/lib/haml/filters.rb +341 -0
  23. data/lib/haml/helpers.rb +560 -0
  24. data/lib/haml/helpers/action_view_extensions.rb +40 -0
  25. data/lib/haml/helpers/action_view_mods.rb +176 -0
  26. data/lib/haml/herb.rb +96 -0
  27. data/lib/haml/html.rb +308 -0
  28. data/lib/haml/precompiler.rb +997 -0
  29. data/lib/haml/shared.rb +78 -0
  30. data/lib/haml/template.rb +51 -0
  31. data/lib/haml/template/patch.rb +58 -0
  32. data/lib/haml/template/plugin.rb +71 -0
  33. data/lib/haml/util.rb +244 -0
  34. data/lib/haml/version.rb +64 -0
  35. data/lib/sass.rb +24 -0
  36. data/lib/sass/css.rb +423 -0
  37. data/lib/sass/engine.rb +491 -0
  38. data/lib/sass/environment.rb +79 -0
  39. data/lib/sass/error.rb +162 -0
  40. data/lib/sass/files.rb +133 -0
  41. data/lib/sass/plugin.rb +170 -0
  42. data/lib/sass/plugin/merb.rb +57 -0
  43. data/lib/sass/plugin/rails.rb +23 -0
  44. data/lib/sass/repl.rb +58 -0
  45. data/lib/sass/script.rb +55 -0
  46. data/lib/sass/script/bool.rb +17 -0
  47. data/lib/sass/script/color.rb +183 -0
  48. data/lib/sass/script/funcall.rb +50 -0
  49. data/lib/sass/script/functions.rb +199 -0
  50. data/lib/sass/script/lexer.rb +191 -0
  51. data/lib/sass/script/literal.rb +177 -0
  52. data/lib/sass/script/node.rb +14 -0
  53. data/lib/sass/script/number.rb +381 -0
  54. data/lib/sass/script/operation.rb +45 -0
  55. data/lib/sass/script/parser.rb +222 -0
  56. data/lib/sass/script/string.rb +12 -0
  57. data/lib/sass/script/unary_operation.rb +34 -0
  58. data/lib/sass/script/variable.rb +31 -0
  59. data/lib/sass/tree/comment_node.rb +84 -0
  60. data/lib/sass/tree/debug_node.rb +30 -0
  61. data/lib/sass/tree/directive_node.rb +70 -0
  62. data/lib/sass/tree/for_node.rb +48 -0
  63. data/lib/sass/tree/if_node.rb +54 -0
  64. data/lib/sass/tree/import_node.rb +69 -0
  65. data/lib/sass/tree/mixin_def_node.rb +29 -0
  66. data/lib/sass/tree/mixin_node.rb +48 -0
  67. data/lib/sass/tree/node.rb +252 -0
  68. data/lib/sass/tree/prop_node.rb +106 -0
  69. data/lib/sass/tree/root_node.rb +56 -0
  70. data/lib/sass/tree/rule_node.rb +220 -0
  71. data/lib/sass/tree/variable_node.rb +34 -0
  72. data/lib/sass/tree/while_node.rb +31 -0
  73. data/rails/init.rb +1 -0
  74. data/test/benchmark.rb +99 -0
  75. data/test/haml/engine_test.rb +1129 -0
  76. data/test/haml/helper_test.rb +282 -0
  77. data/test/haml/html2haml_test.rb +258 -0
  78. data/test/haml/markaby/standard.mab +52 -0
  79. data/test/haml/mocks/article.rb +6 -0
  80. data/test/haml/results/content_for_layout.xhtml +12 -0
  81. data/test/haml/results/eval_suppressed.xhtml +9 -0
  82. data/test/haml/results/filters.xhtml +62 -0
  83. data/test/haml/results/helpers.xhtml +93 -0
  84. data/test/haml/results/helpful.xhtml +10 -0
  85. data/test/haml/results/just_stuff.xhtml +68 -0
  86. data/test/haml/results/list.xhtml +12 -0
  87. data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
  88. data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
  89. data/test/haml/results/original_engine.xhtml +20 -0
  90. data/test/haml/results/partial_layout.xhtml +5 -0
  91. data/test/haml/results/partials.xhtml +21 -0
  92. data/test/haml/results/render_layout.xhtml +3 -0
  93. data/test/haml/results/silent_script.xhtml +74 -0
  94. data/test/haml/results/standard.xhtml +162 -0
  95. data/test/haml/results/tag_parsing.xhtml +23 -0
  96. data/test/haml/results/very_basic.xhtml +5 -0
  97. data/test/haml/results/whitespace_handling.xhtml +89 -0
  98. data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
  99. data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
  100. data/test/haml/rhtml/action_view.rhtml +62 -0
  101. data/test/haml/rhtml/standard.rhtml +54 -0
  102. data/test/haml/spec_test.rb +44 -0
  103. data/test/haml/template_test.rb +217 -0
  104. data/test/haml/templates/_av_partial_1.haml +9 -0
  105. data/test/haml/templates/_av_partial_1_ugly.haml +9 -0
  106. data/test/haml/templates/_av_partial_2.haml +5 -0
  107. data/test/haml/templates/_av_partial_2_ugly.haml +5 -0
  108. data/test/haml/templates/_layout.erb +3 -0
  109. data/test/haml/templates/_layout_for_partial.haml +3 -0
  110. data/test/haml/templates/_partial.haml +8 -0
  111. data/test/haml/templates/_text_area.haml +3 -0
  112. data/test/haml/templates/action_view.haml +47 -0
  113. data/test/haml/templates/action_view_ugly.haml +47 -0
  114. data/test/haml/templates/breakage.haml +8 -0
  115. data/test/haml/templates/content_for_layout.haml +8 -0
  116. data/test/haml/templates/eval_suppressed.haml +11 -0
  117. data/test/haml/templates/filters.haml +66 -0
  118. data/test/haml/templates/helpers.haml +95 -0
  119. data/test/haml/templates/helpful.haml +11 -0
  120. data/test/haml/templates/just_stuff.haml +83 -0
  121. data/test/haml/templates/list.haml +12 -0
  122. data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
  123. data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
  124. data/test/haml/templates/original_engine.haml +17 -0
  125. data/test/haml/templates/partial_layout.haml +3 -0
  126. data/test/haml/templates/partialize.haml +1 -0
  127. data/test/haml/templates/partials.haml +12 -0
  128. data/test/haml/templates/render_layout.haml +2 -0
  129. data/test/haml/templates/silent_script.haml +40 -0
  130. data/test/haml/templates/standard.haml +42 -0
  131. data/test/haml/templates/standard_ugly.haml +42 -0
  132. data/test/haml/templates/tag_parsing.haml +21 -0
  133. data/test/haml/templates/very_basic.haml +4 -0
  134. data/test/haml/templates/whitespace_handling.haml +87 -0
  135. data/test/haml/util_test.rb +92 -0
  136. data/test/linked_rails.rb +12 -0
  137. data/test/sass/css2sass_test.rb +294 -0
  138. data/test/sass/engine_test.rb +956 -0
  139. data/test/sass/functions_test.rb +126 -0
  140. data/test/sass/more_results/more1.css +9 -0
  141. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  142. data/test/sass/more_results/more_import.css +29 -0
  143. data/test/sass/more_templates/_more_partial.sass +2 -0
  144. data/test/sass/more_templates/more1.sass +23 -0
  145. data/test/sass/more_templates/more_import.sass +11 -0
  146. data/test/sass/plugin_test.rb +229 -0
  147. data/test/sass/results/alt.css +4 -0
  148. data/test/sass/results/basic.css +9 -0
  149. data/test/sass/results/compact.css +5 -0
  150. data/test/sass/results/complex.css +87 -0
  151. data/test/sass/results/compressed.css +1 -0
  152. data/test/sass/results/expanded.css +19 -0
  153. data/test/sass/results/import.css +29 -0
  154. data/test/sass/results/line_numbers.css +49 -0
  155. data/test/sass/results/mixins.css +95 -0
  156. data/test/sass/results/multiline.css +24 -0
  157. data/test/sass/results/nested.css +22 -0
  158. data/test/sass/results/parent_ref.css +13 -0
  159. data/test/sass/results/script.css +16 -0
  160. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  161. data/test/sass/results/subdir/subdir.css +3 -0
  162. data/test/sass/results/units.css +11 -0
  163. data/test/sass/script_test.rb +261 -0
  164. data/test/sass/templates/_partial.sass +2 -0
  165. data/test/sass/templates/alt.sass +16 -0
  166. data/test/sass/templates/basic.sass +23 -0
  167. data/test/sass/templates/bork1.sass +2 -0
  168. data/test/sass/templates/bork2.sass +2 -0
  169. data/test/sass/templates/bork3.sass +2 -0
  170. data/test/sass/templates/compact.sass +17 -0
  171. data/test/sass/templates/complex.sass +307 -0
  172. data/test/sass/templates/compressed.sass +15 -0
  173. data/test/sass/templates/expanded.sass +17 -0
  174. data/test/sass/templates/import.sass +11 -0
  175. data/test/sass/templates/importee.sass +19 -0
  176. data/test/sass/templates/line_numbers.sass +13 -0
  177. data/test/sass/templates/mixins.sass +76 -0
  178. data/test/sass/templates/multiline.sass +20 -0
  179. data/test/sass/templates/nested.sass +25 -0
  180. data/test/sass/templates/nested_bork1.sass +2 -0
  181. data/test/sass/templates/nested_bork2.sass +2 -0
  182. data/test/sass/templates/nested_bork3.sass +2 -0
  183. data/test/sass/templates/parent_ref.sass +25 -0
  184. data/test/sass/templates/script.sass +101 -0
  185. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  186. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  187. data/test/sass/templates/subdir/subdir.sass +6 -0
  188. data/test/sass/templates/units.sass +11 -0
  189. data/test/test_helper.rb +44 -0
  190. metadata +298 -0
@@ -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}'.") 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, ((var, default), value)|
36
+ env.set_local_var(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 #{var.inspect}.") unless env.var(var.name)
43
+ env
44
+ end
45
+ mixin.tree.map {|c| c.perform(environment)}.flatten
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,252 @@
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**.
17
+ module Tree
18
+ # The abstract superclass of all parse-tree nodes.
19
+ class Node
20
+ # The child nodes of this node.
21
+ #
22
+ # @return [Array<Tree::Node>]
23
+ attr_accessor :children
24
+
25
+ # The line of the document on which this node appeared.
26
+ #
27
+ # @return [Fixnum]
28
+ attr_accessor :line
29
+
30
+ # The name of the document on which this node appeared.
31
+ #
32
+ # @return [String]
33
+ attr_writer :filename
34
+
35
+ # The options hash for the node.
36
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
37
+ #
38
+ # @return [Hash<Symbol, Object>]
39
+ attr_reader :options
40
+
41
+ def initialize
42
+ @children = []
43
+ end
44
+
45
+ # Sets the options hash for the node and all its children.
46
+ #
47
+ # @param options [Hash<Symbol, Object>] The options
48
+ # @see #options
49
+ def options=(options)
50
+ children.each {|c| c.options = options}
51
+ @options = options
52
+ end
53
+
54
+ # The name of the document on which this node appeared.
55
+ #
56
+ # @return [String]
57
+ def filename
58
+ @filename || @options[:filename]
59
+ end
60
+
61
+ # Appends a child to the node.
62
+ #
63
+ # @param child [Tree::Node] The child node
64
+ # @raise [Sass::SyntaxError] if `child` is invalid
65
+ # @see #invalid_child?
66
+ def <<(child)
67
+ if msg = invalid_child?(child)
68
+ raise Sass::SyntaxError.new(msg, :line => child.line)
69
+ end
70
+ @children << child
71
+ end
72
+
73
+ # Return the last child node.
74
+ #
75
+ # We need this because {Tree::Node} duck types as an Array for {Sass::Engine}.
76
+ #
77
+ # @return [Tree::Node] The last child node
78
+ def last
79
+ children.last
80
+ end
81
+
82
+ # Compares this node and another object (only other {Tree::Node}s will be equal).
83
+ # This does a structural comparison;
84
+ # if the contents of the nodes and all the child nodes are equivalent,
85
+ # then the nodes are as well.
86
+ #
87
+ # Only static nodes need to override this.
88
+ #
89
+ # @param other [Object] The object to compare with
90
+ # @return [Boolean] Whether or not this node and the other object
91
+ # are the same
92
+ # @see Sass::Tree
93
+ def ==(other)
94
+ self.class == other.class && other.children == children
95
+ end
96
+
97
+ # Runs the dynamic Sass code *and* computes the CSS for the tree.
98
+ #
99
+ # @see #perform
100
+ # @see #to_s
101
+ def render
102
+ perform(Environment.new).to_s
103
+ end
104
+
105
+ # True if \{#to\_s} will return `nil`;
106
+ # that is, if the node shouldn't be rendered.
107
+ # Should only be called in a static tree.
108
+ #
109
+ # @return [Boolean]
110
+ def invisible?; false; end
111
+
112
+ # The output style. See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
113
+ #
114
+ # @return [Symbol]
115
+ def style
116
+ @options[:style]
117
+ end
118
+
119
+ # Computes the CSS corresponding to this Sass tree.
120
+ #
121
+ # Only static-node subclasses need to implement \{#to\_s}.
122
+ #
123
+ # This may return `nil`, but it will only do so if \{#invisible?} is true.
124
+ #
125
+ # @param args [Array] Passed on to \{#\_to\_s}
126
+ # @return [String, nil] The resulting CSS
127
+ # @raise [Sass::SyntaxError] if some element of the tree is invalid
128
+ # @see Sass::Tree
129
+ def to_s(*args)
130
+ _to_s(*args)
131
+ rescue Sass::SyntaxError => e
132
+ e.modify_backtrace(:filename => filename, :line => line)
133
+ raise e
134
+ end
135
+
136
+ # Runs the dynamic Sass code:
137
+ # mixins, variables, control directives, and so forth.
138
+ # This doesn't modify this node or any of its children.
139
+ #
140
+ # \{#perform} shouldn't be overridden directly;
141
+ # if you want to return a new node (or list of nodes),
142
+ # override \{#\_perform};
143
+ # if you want to destructively modify this node,
144
+ # override \{#perform!}.
145
+ #
146
+ # @param environment [Sass::Environment] The lexical environment containing
147
+ # variable and mixin values
148
+ # @return [Tree::Node] The resulting tree of static nodes
149
+ # @raise [Sass::SyntaxError] if some element of the tree is invalid
150
+ # @see Sass::Tree
151
+ def perform(environment)
152
+ environment.options = @options if self.class == Tree::Node
153
+ _perform(environment)
154
+ rescue Sass::SyntaxError => e
155
+ e.modify_backtrace(:filename => filename, :line => line)
156
+ raise e
157
+ end
158
+
159
+ protected
160
+
161
+ # Computes the CSS corresponding to this particular Sass node.
162
+ #
163
+ # @param args [Array] ignored
164
+ # @return [String, nil] The resulting CSS
165
+ # @raise [Sass::SyntaxError] if some element of the tree is invalid
166
+ # @see #to_s
167
+ # @see Sass::Tree
168
+ def _to_s
169
+ raise NotImplementedError.new("All static-node subclasses of Sass::Tree::Node must override #_to_s or #to_s.")
170
+ end
171
+
172
+ # Runs any dynamic Sass code in this particular node.
173
+ # This doesn't modify this node or any of its children.
174
+ #
175
+ # @param environment [Sass::Environment] The lexical environment containing
176
+ # variable and mixin values
177
+ # @return [Tree::Node, Array<Tree::Node>] The resulting static nodes
178
+ # @see #perform
179
+ # @see Sass::Tree
180
+ def _perform(environment)
181
+ node = dup
182
+ node.perform!(environment)
183
+ node
184
+ end
185
+
186
+ # Destructively runs dynamic Sass code in this particular node.
187
+ # This *does* modify this node,
188
+ # but will be run non-destructively by \{#\_perform\}.
189
+ #
190
+ # @param environment [Sass::Environment] The lexical environment containing
191
+ # variable and mixin values
192
+ # @see #perform
193
+ def perform!(environment)
194
+ self.children = perform_children(Environment.new(environment))
195
+ end
196
+
197
+ # Non-destructively runs \{#perform} on all children of the current node.
198
+ #
199
+ # @param environment [Sass::Environment] The lexical environment containing
200
+ # variable and mixin values
201
+ # @return [Array<Tree::Node>] The resulting static nodes
202
+ def perform_children(environment)
203
+ children.map {|c| c.perform(environment)}.flatten
204
+ end
205
+
206
+ # Replaces SassScript in a chunk of text (via `#{}`)
207
+ # with the resulting value.
208
+ #
209
+ # @param text [String] The text to interpolate
210
+ # @param environment [Sass::Environment] The lexical environment containing
211
+ # variable and mixin values
212
+ # @return [String] The interpolated text
213
+ def interpolate(text, environment)
214
+ res = ''
215
+ rest = Haml::Shared.handle_interpolation text do |scan|
216
+ escapes = scan[2].size
217
+ res << scan.matched[0...-2 - escapes]
218
+ if escapes % 2 == 1
219
+ res << "\\" * (escapes - 1) << '#{'
220
+ else
221
+ res << "\\" * [0, escapes - 1].max
222
+ res << Script::Parser.new(scan, line, scan.pos - scan.matched_size, filename).
223
+ parse_interpolated.perform(environment).to_s
224
+ end
225
+ end
226
+ res + rest
227
+ end
228
+
229
+ # @see Haml::Shared.balance
230
+ # @raise [Sass::SyntaxError] if the brackets aren't balanced
231
+ def balance(*args)
232
+ res = Haml::Shared.balance(*args)
233
+ return res if res
234
+ raise Sass::SyntaxError.new("Unbalanced brackets.", :line => line)
235
+ end
236
+
237
+ # Returns an error message if the given child node is invalid,
238
+ # and false otherwise.
239
+ #
240
+ # By default, all child nodes are valid.
241
+ # This is expected to be overriden by subclasses
242
+ # for which some children are invalid.
243
+ #
244
+ # @param child [Tree::Node] A potential child node
245
+ # @return [Boolean, String] Whether or not the child node is valid,
246
+ # as well as the error message to display if it is invalid
247
+ def invalid_child?(child)
248
+ false
249
+ end
250
+ end
251
+ end
252
+ end
@@ -0,0 +1,106 @@
1
+ module Sass::Tree
2
+ # A static node reprenting a CSS property.
3
+ #
4
+ # @see Sass::Tree
5
+ class PropNode < Node
6
+ # The name of the property.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :name
10
+
11
+ # The value of the property,
12
+ # either a plain string or a SassScript parse tree.
13
+ #
14
+ # @return [String, Script::Node]
15
+ attr_accessor :value
16
+
17
+ # @param name [String] See \{#name}
18
+ # @param value [String] See \{#value}
19
+ # @param prop_syntax [Symbol] `:new` if this property uses `a: b`-style syntax,
20
+ # `:old` if it uses `:a b`-style syntax
21
+ def initialize(name, value, prop_syntax)
22
+ @name = name
23
+ @value = value
24
+ @prop_syntax = prop_syntax
25
+ super()
26
+ end
27
+
28
+ # Compares the names and values of two properties.
29
+ #
30
+ # @param other [Object] The object to compare with
31
+ # @return [Boolean] Whether or not this node and the other object
32
+ # are the same
33
+ def ==(other)
34
+ self.class == other.class && name == other.name && value == other.value && super
35
+ end
36
+
37
+ protected
38
+
39
+ # Computes the CSS for the property.
40
+ #
41
+ # @param tabs [Fixnum] The level of indentation for the CSS
42
+ # @param parent_name [String] The name of the parent property (e.g. `text`) or nil
43
+ # @return [String] The resulting CSS
44
+ # @raise [Sass::SyntaxError] if the property uses invalid syntax
45
+ def _to_s(tabs, parent_name = nil)
46
+ if @options[:property_syntax] == :old && @prop_syntax == :new
47
+ raise Sass::SyntaxError.new("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.")
48
+ elsif @options[:property_syntax] == :new && @prop_syntax == :old
49
+ raise Sass::SyntaxError.new("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.")
50
+ elsif value[-1] == ?;
51
+ raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no \";\" required at end-of-line).")
52
+ elsif value.empty? && children.empty?
53
+ raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no value).")
54
+ end
55
+
56
+ real_name = name
57
+ real_name = "#{parent_name}-#{real_name}" if parent_name
58
+
59
+ join_string = case style
60
+ when :compact; ' '
61
+ when :compressed; ''
62
+ else "\n"
63
+ end
64
+ spaces = ' ' * (tabs - 1)
65
+ to_return = ''
66
+ if !value.empty?
67
+ to_return << "#{spaces}#{real_name}:#{style == :compressed ? '' : ' '}#{value};#{join_string}"
68
+ end
69
+
70
+ children.each do |kid|
71
+ next if kid.invisible?
72
+ to_return << kid.to_s(tabs, real_name) << join_string
73
+ end
74
+
75
+ (style == :compressed && parent_name) ? to_return : to_return[0...-1]
76
+ end
77
+
78
+ # Runs any SassScript that may be embedded in the property.
79
+ #
80
+ # @param environment [Sass::Environment] The lexical environment containing
81
+ # variable and mixin values
82
+ def perform!(environment)
83
+ @name = interpolate(@name, environment)
84
+ @value = @value.is_a?(String) ? interpolate(@value, environment) : @value.perform(environment).to_s
85
+ super
86
+ end
87
+
88
+ # Returns an error message if the given child node is invalid,
89
+ # and false otherwise.
90
+ #
91
+ # {PropNode} only allows other {PropNode}s and {CommentNode}s as children.
92
+ # @param child [Tree::Node] A potential child node
93
+ # @return [String] An error message if the child is invalid, or nil otherwise
94
+ def invalid_child?(child)
95
+ if !child.is_a?(PropNode) && !child.is_a?(CommentNode)
96
+ "Illegal nesting: Only properties may be nested beneath properties."
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def declaration
103
+ @prop_syntax == :new ? "#{name}: #{value}" : ":#{name} #{value}"
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,56 @@
1
+ module Sass
2
+ module Tree
3
+ # A static node that is the root node of the Sass document.
4
+ class RootNode < Node
5
+ # The Sass template from which this node was created
6
+ #
7
+ # @param template [String]
8
+ attr_reader :template
9
+
10
+ # @param template [String] The Sass template from which this node was created
11
+ def initialize(template)
12
+ super()
13
+ @template = template
14
+ end
15
+
16
+ # @see \{Node#to\_s}
17
+ def to_s(*args)
18
+ super
19
+ rescue Sass::SyntaxError => e
20
+ e.sass_template = @template
21
+ raise e
22
+ end
23
+
24
+ # @see \{Node#perform}
25
+ def perform(*args)
26
+ super
27
+ rescue Sass::SyntaxError => e
28
+ e.sass_template = @template
29
+ raise e
30
+ end
31
+
32
+ protected
33
+
34
+ # Computes the CSS corresponding to this Sass tree.
35
+ #
36
+ # @param args [Array] ignored
37
+ # @return [String] The resulting CSS
38
+ # @raise [Sass::SyntaxError] if some element of the tree is invalid
39
+ # @see Sass::Tree
40
+ def _to_s(*args)
41
+ result = String.new
42
+ children.each do |child|
43
+ raise Sass::SyntaxError.new('Properties aren\'t allowed at the root of a document.',
44
+ :line => child.line) if child.is_a? PropNode
45
+
46
+ next if child.invisible?
47
+ child_str = child.to_s(1)
48
+ result << child_str + (style == :compressed ? '' : "\n")
49
+ end
50
+ result.rstrip!
51
+ return "" if result.empty?
52
+ return result + "\n"
53
+ end
54
+ end
55
+ end
56
+ end