haml 3.1.0.alpha.14 → 3.1.0.alpha.17

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.

Files changed (222) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/VERSION +1 -1
  3. data/lib/haml.rb +3 -2
  4. data/lib/haml/exec.rb +0 -226
  5. data/lib/sass.rb +8 -0
  6. data/lib/sass/plugin.rb +8 -0
  7. data/lib/sass/rails2_shim.rb +9 -0
  8. data/lib/sass/rails3_shim.rb +16 -0
  9. data/vendor/sass/CONTRIBUTING +3 -0
  10. data/vendor/sass/MIT-LICENSE +20 -0
  11. data/vendor/sass/README.md +201 -0
  12. data/vendor/sass/Rakefile +363 -0
  13. data/vendor/sass/TODO +39 -0
  14. data/vendor/sass/VERSION +1 -0
  15. data/vendor/sass/VERSION_NAME +1 -0
  16. data/vendor/sass/bin/css2sass +13 -0
  17. data/vendor/sass/bin/sass +8 -0
  18. data/vendor/sass/bin/sass-convert +7 -0
  19. data/vendor/sass/doc-src/FAQ.md +35 -0
  20. data/vendor/sass/doc-src/INDENTED_SYNTAX.md +210 -0
  21. data/vendor/sass/doc-src/SASS_CHANGELOG.md +1878 -0
  22. data/vendor/sass/doc-src/SASS_REFERENCE.md +1713 -0
  23. data/vendor/sass/doc-src/SCSS_FOR_SASS_USERS.md +155 -0
  24. data/vendor/sass/ext/extconf.rb +10 -0
  25. data/vendor/sass/extra/update_watch.rb +13 -0
  26. data/vendor/sass/init.rb +18 -0
  27. data/vendor/sass/lib/sass.rb +71 -0
  28. data/vendor/sass/lib/sass/cache_store.rb +208 -0
  29. data/vendor/sass/lib/sass/callbacks.rb +66 -0
  30. data/vendor/sass/lib/sass/css.rb +294 -0
  31. data/vendor/sass/lib/sass/engine.rb +792 -0
  32. data/vendor/sass/lib/sass/environment.rb +143 -0
  33. data/vendor/sass/lib/sass/error.rb +201 -0
  34. data/vendor/sass/lib/sass/exec.rb +619 -0
  35. data/vendor/sass/lib/sass/importers.rb +22 -0
  36. data/vendor/sass/lib/sass/importers/base.rb +138 -0
  37. data/vendor/sass/lib/sass/importers/filesystem.rb +121 -0
  38. data/vendor/sass/lib/sass/less.rb +363 -0
  39. data/vendor/sass/lib/sass/plugin.rb +126 -0
  40. data/vendor/sass/lib/sass/plugin/compiler.rb +346 -0
  41. data/vendor/sass/lib/sass/plugin/configuration.rb +123 -0
  42. data/vendor/sass/lib/sass/plugin/generic.rb +15 -0
  43. data/vendor/sass/lib/sass/plugin/merb.rb +48 -0
  44. data/vendor/sass/lib/sass/plugin/rack.rb +47 -0
  45. data/vendor/sass/lib/sass/plugin/rails.rb +41 -0
  46. data/vendor/sass/lib/sass/plugin/staleness_checker.rb +145 -0
  47. data/vendor/sass/lib/sass/railtie.rb +8 -0
  48. data/vendor/sass/lib/sass/repl.rb +58 -0
  49. data/vendor/sass/lib/sass/root.rb +7 -0
  50. data/vendor/sass/lib/sass/script.rb +63 -0
  51. data/vendor/sass/lib/sass/script/bool.rb +18 -0
  52. data/vendor/sass/lib/sass/script/color.rb +491 -0
  53. data/vendor/sass/lib/sass/script/css_lexer.rb +29 -0
  54. data/vendor/sass/lib/sass/script/css_parser.rb +31 -0
  55. data/vendor/sass/lib/sass/script/funcall.rb +76 -0
  56. data/vendor/sass/lib/sass/script/functions.rb +852 -0
  57. data/vendor/sass/lib/sass/script/interpolation.rb +70 -0
  58. data/vendor/sass/lib/sass/script/lexer.rb +337 -0
  59. data/vendor/sass/lib/sass/script/literal.rb +236 -0
  60. data/vendor/sass/lib/sass/script/node.rb +112 -0
  61. data/vendor/sass/lib/sass/script/number.rb +423 -0
  62. data/vendor/sass/lib/sass/script/operation.rb +90 -0
  63. data/vendor/sass/lib/sass/script/parser.rb +392 -0
  64. data/vendor/sass/lib/sass/script/string.rb +67 -0
  65. data/vendor/sass/lib/sass/script/string_interpolation.rb +93 -0
  66. data/vendor/sass/lib/sass/script/unary_operation.rb +57 -0
  67. data/vendor/sass/lib/sass/script/variable.rb +48 -0
  68. data/vendor/sass/lib/sass/scss.rb +17 -0
  69. data/vendor/sass/lib/sass/scss/css_parser.rb +51 -0
  70. data/vendor/sass/lib/sass/scss/parser.rb +838 -0
  71. data/vendor/sass/lib/sass/scss/rx.rb +126 -0
  72. data/vendor/sass/lib/sass/scss/sass_parser.rb +11 -0
  73. data/vendor/sass/lib/sass/scss/script_lexer.rb +15 -0
  74. data/vendor/sass/lib/sass/scss/script_parser.rb +25 -0
  75. data/vendor/sass/lib/sass/scss/static_parser.rb +40 -0
  76. data/vendor/sass/lib/sass/selector.rb +361 -0
  77. data/vendor/sass/lib/sass/selector/abstract_sequence.rb +62 -0
  78. data/vendor/sass/lib/sass/selector/comma_sequence.rb +82 -0
  79. data/vendor/sass/lib/sass/selector/sequence.rb +236 -0
  80. data/vendor/sass/lib/sass/selector/simple.rb +113 -0
  81. data/vendor/sass/lib/sass/selector/simple_sequence.rb +135 -0
  82. data/vendor/sass/lib/sass/shared.rb +78 -0
  83. data/vendor/sass/lib/sass/tree/comment_node.rb +128 -0
  84. data/vendor/sass/lib/sass/tree/debug_node.rb +36 -0
  85. data/vendor/sass/lib/sass/tree/directive_node.rb +75 -0
  86. data/vendor/sass/lib/sass/tree/extend_node.rb +65 -0
  87. data/vendor/sass/lib/sass/tree/for_node.rb +67 -0
  88. data/vendor/sass/lib/sass/tree/if_node.rb +81 -0
  89. data/vendor/sass/lib/sass/tree/import_node.rb +124 -0
  90. data/vendor/sass/lib/sass/tree/mixin_def_node.rb +60 -0
  91. data/vendor/sass/lib/sass/tree/mixin_node.rb +123 -0
  92. data/vendor/sass/lib/sass/tree/node.rb +490 -0
  93. data/vendor/sass/lib/sass/tree/prop_node.rb +220 -0
  94. data/vendor/sass/lib/sass/tree/root_node.rb +125 -0
  95. data/vendor/sass/lib/sass/tree/rule_node.rb +273 -0
  96. data/vendor/sass/lib/sass/tree/variable_node.rb +39 -0
  97. data/vendor/sass/lib/sass/tree/warn_node.rb +42 -0
  98. data/vendor/sass/lib/sass/tree/while_node.rb +48 -0
  99. data/vendor/sass/lib/sass/util.rb +700 -0
  100. data/vendor/sass/lib/sass/util/subset_map.rb +101 -0
  101. data/vendor/sass/lib/sass/version.rb +109 -0
  102. data/vendor/sass/rails/init.rb +1 -0
  103. data/vendor/sass/sass.gemspec +32 -0
  104. data/vendor/sass/test/sass/cache_test.rb +74 -0
  105. data/vendor/sass/test/sass/callbacks_test.rb +61 -0
  106. data/vendor/sass/test/sass/conversion_test.rb +1210 -0
  107. data/vendor/sass/test/sass/css2sass_test.rb +364 -0
  108. data/vendor/sass/test/sass/data/hsl-rgb.txt +319 -0
  109. data/vendor/sass/test/sass/engine_test.rb +2305 -0
  110. data/vendor/sass/test/sass/extend_test.rb +1348 -0
  111. data/vendor/sass/test/sass/functions_test.rb +565 -0
  112. data/vendor/sass/test/sass/importer_test.rb +104 -0
  113. data/vendor/sass/test/sass/less_conversion_test.rb +632 -0
  114. data/vendor/sass/test/sass/mock_importer.rb +49 -0
  115. data/vendor/sass/test/sass/more_results/more1.css +9 -0
  116. data/vendor/sass/test/sass/more_results/more1_with_line_comments.css +26 -0
  117. data/vendor/sass/test/sass/more_results/more_import.css +29 -0
  118. data/vendor/sass/test/sass/more_templates/_more_partial.sass +2 -0
  119. data/vendor/sass/test/sass/more_templates/more1.sass +23 -0
  120. data/vendor/sass/test/sass/more_templates/more_import.sass +11 -0
  121. data/vendor/sass/test/sass/plugin_test.rb +430 -0
  122. data/vendor/sass/test/sass/results/alt.css +4 -0
  123. data/vendor/sass/test/sass/results/basic.css +9 -0
  124. data/vendor/sass/test/sass/results/compact.css +5 -0
  125. data/vendor/sass/test/sass/results/complex.css +86 -0
  126. data/vendor/sass/test/sass/results/compressed.css +1 -0
  127. data/vendor/sass/test/sass/results/expanded.css +19 -0
  128. data/vendor/sass/test/sass/results/import.css +31 -0
  129. data/vendor/sass/test/sass/results/line_numbers.css +49 -0
  130. data/vendor/sass/test/sass/results/mixins.css +95 -0
  131. data/vendor/sass/test/sass/results/multiline.css +24 -0
  132. data/vendor/sass/test/sass/results/nested.css +22 -0
  133. data/vendor/sass/test/sass/results/options.css +1 -0
  134. data/vendor/sass/test/sass/results/parent_ref.css +13 -0
  135. data/vendor/sass/test/sass/results/script.css +16 -0
  136. data/vendor/sass/test/sass/results/scss_import.css +31 -0
  137. data/vendor/sass/test/sass/results/scss_importee.css +2 -0
  138. data/vendor/sass/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  139. data/vendor/sass/test/sass/results/subdir/subdir.css +3 -0
  140. data/vendor/sass/test/sass/results/units.css +11 -0
  141. data/vendor/sass/test/sass/results/warn.css +0 -0
  142. data/vendor/sass/test/sass/results/warn_imported.css +0 -0
  143. data/vendor/sass/test/sass/script_conversion_test.rb +254 -0
  144. data/vendor/sass/test/sass/script_test.rb +470 -0
  145. data/vendor/sass/test/sass/scss/css_test.rb +897 -0
  146. data/vendor/sass/test/sass/scss/rx_test.rb +156 -0
  147. data/vendor/sass/test/sass/scss/scss_test.rb +1088 -0
  148. data/vendor/sass/test/sass/scss/test_helper.rb +37 -0
  149. data/vendor/sass/test/sass/templates/_partial.sass +2 -0
  150. data/vendor/sass/test/sass/templates/alt.sass +16 -0
  151. data/vendor/sass/test/sass/templates/basic.sass +23 -0
  152. data/vendor/sass/test/sass/templates/bork1.sass +2 -0
  153. data/vendor/sass/test/sass/templates/bork2.sass +2 -0
  154. data/vendor/sass/test/sass/templates/bork3.sass +2 -0
  155. data/vendor/sass/test/sass/templates/bork4.sass +2 -0
  156. data/vendor/sass/test/sass/templates/compact.sass +17 -0
  157. data/vendor/sass/test/sass/templates/complex.sass +305 -0
  158. data/vendor/sass/test/sass/templates/compressed.sass +15 -0
  159. data/vendor/sass/test/sass/templates/expanded.sass +17 -0
  160. data/vendor/sass/test/sass/templates/import.sass +12 -0
  161. data/vendor/sass/test/sass/templates/importee.less +2 -0
  162. data/vendor/sass/test/sass/templates/importee.sass +19 -0
  163. data/vendor/sass/test/sass/templates/line_numbers.sass +13 -0
  164. data/vendor/sass/test/sass/templates/mixin_bork.sass +5 -0
  165. data/vendor/sass/test/sass/templates/mixins.sass +76 -0
  166. data/vendor/sass/test/sass/templates/multiline.sass +20 -0
  167. data/vendor/sass/test/sass/templates/nested.sass +25 -0
  168. data/vendor/sass/test/sass/templates/nested_bork1.sass +2 -0
  169. data/vendor/sass/test/sass/templates/nested_bork2.sass +2 -0
  170. data/vendor/sass/test/sass/templates/nested_bork3.sass +2 -0
  171. data/vendor/sass/test/sass/templates/nested_bork4.sass +2 -0
  172. data/vendor/sass/test/sass/templates/nested_mixin_bork.sass +6 -0
  173. data/vendor/sass/test/sass/templates/options.sass +2 -0
  174. data/vendor/sass/test/sass/templates/parent_ref.sass +25 -0
  175. data/vendor/sass/test/sass/templates/script.sass +101 -0
  176. data/vendor/sass/test/sass/templates/scss_import.scss +11 -0
  177. data/vendor/sass/test/sass/templates/scss_importee.scss +1 -0
  178. data/vendor/sass/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  179. data/vendor/sass/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  180. data/vendor/sass/test/sass/templates/subdir/subdir.sass +6 -0
  181. data/vendor/sass/test/sass/templates/units.sass +11 -0
  182. data/vendor/sass/test/sass/templates/warn.sass +3 -0
  183. data/vendor/sass/test/sass/templates/warn_imported.sass +4 -0
  184. data/vendor/sass/test/sass/test_helper.rb +8 -0
  185. data/vendor/sass/test/sass/util/subset_map_test.rb +91 -0
  186. data/vendor/sass/test/sass/util_test.rb +275 -0
  187. data/vendor/sass/test/test_helper.rb +64 -0
  188. data/vendor/sass/vendor/fssm/LICENSE +20 -0
  189. data/vendor/sass/vendor/fssm/README.markdown +55 -0
  190. data/vendor/sass/vendor/fssm/Rakefile +59 -0
  191. data/vendor/sass/vendor/fssm/VERSION.yml +5 -0
  192. data/vendor/sass/vendor/fssm/example.rb +9 -0
  193. data/vendor/sass/vendor/fssm/fssm.gemspec +77 -0
  194. data/vendor/sass/vendor/fssm/lib/fssm.rb +33 -0
  195. data/vendor/sass/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  196. data/vendor/sass/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  197. data/vendor/sass/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  198. data/vendor/sass/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  199. data/vendor/sass/vendor/fssm/lib/fssm/monitor.rb +26 -0
  200. data/vendor/sass/vendor/fssm/lib/fssm/path.rb +91 -0
  201. data/vendor/sass/vendor/fssm/lib/fssm/pathname.rb +502 -0
  202. data/vendor/sass/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  203. data/vendor/sass/vendor/fssm/lib/fssm/state/file.rb +24 -0
  204. data/vendor/sass/vendor/fssm/lib/fssm/support.rb +63 -0
  205. data/vendor/sass/vendor/fssm/lib/fssm/tree.rb +176 -0
  206. data/vendor/sass/vendor/fssm/profile/prof-cache.rb +40 -0
  207. data/vendor/sass/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  208. data/vendor/sass/vendor/fssm/profile/prof-pathname.rb +68 -0
  209. data/vendor/sass/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  210. data/vendor/sass/vendor/fssm/profile/prof.html +2379 -0
  211. data/vendor/sass/vendor/fssm/spec/path_spec.rb +75 -0
  212. data/vendor/sass/vendor/fssm/spec/root/duck/quack.txt +0 -0
  213. data/vendor/sass/vendor/fssm/spec/root/file.css +0 -0
  214. data/vendor/sass/vendor/fssm/spec/root/file.rb +0 -0
  215. data/vendor/sass/vendor/fssm/spec/root/file.yml +0 -0
  216. data/vendor/sass/vendor/fssm/spec/root/moo/cow.txt +0 -0
  217. data/vendor/sass/vendor/fssm/spec/spec_helper.rb +14 -0
  218. data/vendor/sass/yard/callbacks.rb +29 -0
  219. data/vendor/sass/yard/default/fulldoc/html/css/common.sass +26 -0
  220. data/vendor/sass/yard/default/layout/html/footer.erb +12 -0
  221. data/vendor/sass/yard/inherited_hash.rb +41 -0
  222. metadata +219 -2
@@ -0,0 +1,65 @@
1
+ require 'sass/tree/node'
2
+
3
+ module Sass::Tree
4
+ # A static node reprenting an `@extend` directive.
5
+ #
6
+ # @see Sass::Tree
7
+ class ExtendNode < Node
8
+ # @param selector [Array<String, Sass::Script::Node>]
9
+ # The CSS selector to extend,
10
+ # interspersed with {Sass::Script::Node}s
11
+ # representing `#{}`-interpolation.
12
+ def initialize(selector)
13
+ @selector = selector
14
+ super()
15
+ end
16
+
17
+ # Registers this extension in the `extends` subset map.
18
+ #
19
+ # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
20
+ # The extensions defined for this tree
21
+ # @param parent [RuleNode] The parent node of this node
22
+ # @see Node#cssize
23
+ def cssize(extends, parent)
24
+ @resolved_selector.members.each do |seq|
25
+ if seq.members.size > 1
26
+ raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend nested selectors")
27
+ end
28
+
29
+ sseq = seq.members.first
30
+ if !sseq.is_a?(Sass::Selector::SimpleSequence)
31
+ raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: invalid selector")
32
+ end
33
+
34
+ sel = sseq.members
35
+ parent.resolved_rules.members.each do |seq|
36
+ if !seq.members.last.is_a?(Sass::Selector::SimpleSequence)
37
+ raise Sass::SyntaxError.new("#{seq} can't extend: invalid selector")
38
+ end
39
+
40
+ extends[sel] = seq
41
+ end
42
+ end
43
+
44
+ []
45
+ end
46
+
47
+ protected
48
+
49
+ # @see Node#to_src
50
+ def to_src(tabs, opts, fmt)
51
+ "#{' ' * tabs}@extend #{selector_to_src(@selector, tabs, opts, fmt).lstrip}#{semi fmt}\n"
52
+ end
53
+
54
+ # Runs SassScript interpolation in the selector,
55
+ # and then parses the result into a {Sass::Selector::CommaSequence}.
56
+ #
57
+ # @param environment [Sass::Environment] The lexical environment containing
58
+ # variable and mixin values
59
+ def perform!(environment)
60
+ @resolved_selector = Sass::SCSS::CssParser.new(run_interp(@selector, environment), self.line).
61
+ parse_selector(self.filename)
62
+ super
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,67 @@
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
+ # @see Node#to_src
24
+ def to_src(tabs, opts, fmt)
25
+ to = @exclusive ? "to" : "through"
26
+ "#{' ' * tabs}@for $#{dasherize(@var, opts)} from #{@from.to_sass(opts)} #{to} #{@to.to_sass(opts)}" +
27
+ children_to_src(tabs, opts, fmt)
28
+ end
29
+
30
+ # Runs the child nodes once for each time through the loop,
31
+ # varying the variable each time.
32
+ #
33
+ # @param environment [Sass::Environment] The lexical environment containing
34
+ # variable and mixin values
35
+ # @return [Array<Tree::Node>] The resulting static nodes
36
+ # @see Sass::Tree
37
+ def _perform(environment)
38
+ from = @from.perform(environment)
39
+ to = @to.perform(environment)
40
+ from.assert_int!
41
+ to.assert_int!
42
+
43
+ to = to.coerce(from.numerator_units, from.denominator_units)
44
+ range = Range.new(from.to_i, to.to_i, @exclusive)
45
+
46
+ children = []
47
+ environment = Sass::Environment.new(environment)
48
+ range.each do |i|
49
+ environment.set_local_var(@var, Sass::Script::Number.new(i, from.numerator_units, from.denominator_units))
50
+ children += perform_children(environment)
51
+ end
52
+ children
53
+ end
54
+
55
+ # Returns an error message if the given child node is invalid,
56
+ # and false otherwise.
57
+ #
58
+ # {ExtendNode}s are valid within {ForNode}s.
59
+ #
60
+ # @param child [Tree::Node] A potential child node.
61
+ # @return [Boolean, String] Whether or not the child node is valid,
62
+ # as well as the error message to display if it is invalid
63
+ def invalid_child?(child)
64
+ super unless child.is_a?(ExtendNode)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,81 @@
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
+ # @see Node#options=
34
+ def options=(options)
35
+ super
36
+ self.else.options = options if self.else
37
+ end
38
+
39
+ protected
40
+
41
+ # @see Node#to_src
42
+ def to_src(tabs, opts, fmt, is_else = false)
43
+ name =
44
+ if !is_else; "if"
45
+ elsif @expr; "else if"
46
+ else; "else"
47
+ end
48
+ str = "#{' ' * tabs}@#{name}"
49
+ str << " #{@expr.to_sass(opts)}" if @expr
50
+ str << children_to_src(tabs, opts, fmt)
51
+ str << @else.send(:to_src, tabs, opts, fmt, true) if @else
52
+ str
53
+ end
54
+
55
+ # Runs the child nodes if the conditional expression is true;
56
+ # otherwise, tries the \{#else} nodes.
57
+ #
58
+ # @param environment [Sass::Environment] The lexical environment containing
59
+ # variable and mixin values
60
+ # @return [Array<Tree::Node>] The resulting static nodes
61
+ # @see Sass::Tree
62
+ def _perform(environment)
63
+ environment = Sass::Environment.new(environment)
64
+ return perform_children(environment) if @expr.nil? || @expr.perform(environment).to_bool
65
+ return @else.perform(environment) if @else
66
+ []
67
+ end
68
+
69
+ # Returns an error message if the given child node is invalid,
70
+ # and false otherwise.
71
+ #
72
+ # {ExtendNode}s are valid within {IfNode}s.
73
+ #
74
+ # @param child [Tree::Node] A potential child node.
75
+ # @return [Boolean, String] Whether or not the child node is valid,
76
+ # as well as the error message to display if it is invalid
77
+ def invalid_child?(child)
78
+ super unless child.is_a?(ExtendNode)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,124 @@
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 ImportNode < RootNode
7
+ # The name of the imported file as it appears in the Sass document.
8
+ #
9
+ # @return [String]
10
+ attr_reader :imported_filename
11
+
12
+ # @param imported_filename [String] The name of the imported file
13
+ def initialize(imported_filename)
14
+ @imported_filename = imported_filename
15
+ super(nil)
16
+ end
17
+
18
+ def invisible?; to_s.empty?; end
19
+
20
+ # Returns the imported file.
21
+ #
22
+ # @return [Sass::Engine]
23
+ # @raise [Sass::SyntaxError] If no file could be found to import.
24
+ def imported_file
25
+ @imported_file ||= import
26
+ end
27
+
28
+ # @see Node#to_sass
29
+ def to_sass(tabs = 0, opts = {})
30
+ "#{' ' * tabs}@import #{@imported_filename}\n"
31
+ end
32
+
33
+ # @see Node#to_scss
34
+ def to_scss(tabs = 0, opts = {})
35
+ "#{' ' * tabs}@import \"#{@imported_filename}\";\n"
36
+ end
37
+
38
+ # @see Node#cssize
39
+ def cssize(*args)
40
+ super.first
41
+ end
42
+
43
+ # Returns whether or not this import should emit a CSS @import declaration
44
+ #
45
+ # @return [Boolean] Whether or not this is a simple CSS @import declaration.
46
+ def css_import?
47
+ if @imported_filename =~ /\.css$/
48
+ @imported_filename
49
+ elsif imported_file.is_a?(String) && imported_file =~ /\.css$/
50
+ imported_file
51
+ end
52
+ end
53
+
54
+ protected
55
+
56
+ # @see Node#_cssize
57
+ def _cssize(*args)
58
+ super.children
59
+ rescue Sass::SyntaxError => e
60
+ e.modify_backtrace(:filename => children.first.filename)
61
+ e.add_backtrace(:filename => @filename, :line => @line)
62
+ raise e
63
+ end
64
+
65
+ # Returns a static DirectiveNode if this is importing a CSS file,
66
+ # or parses and includes the imported Sass file.
67
+ #
68
+ # @param environment [Sass::Environment] The lexical environment containing
69
+ # variable and mixin values
70
+ def _perform(environment)
71
+ if path = css_import?
72
+ return DirectiveNode.new("@import url(#{path})")
73
+ end
74
+ super
75
+ end
76
+
77
+ # Parses the imported file and runs the dynamic Sass for it.
78
+ #
79
+ # @param environment [Sass::Environment] The lexical environment containing
80
+ # variable and mixin values
81
+ def perform!(environment)
82
+ environment.push_frame(:filename => @filename, :line => @line)
83
+ # TODO: re-enable caching
84
+ root = imported_file.to_tree
85
+ self.children = root.children
86
+ self.children = perform_children(environment)
87
+ rescue Sass::SyntaxError => e
88
+ e.modify_backtrace(:filename => imported_file.options[:filename])
89
+ e.add_backtrace(:filename => @filename, :line => @line)
90
+ raise e
91
+ ensure
92
+ environment.pop_frame
93
+ end
94
+
95
+ private
96
+
97
+ def import
98
+ paths = @options[:load_paths]
99
+
100
+ if @options[:importer]
101
+ f = @options[:importer].find_relative(
102
+ @imported_filename, @options[:filename], @options.dup)
103
+ return f if f
104
+ end
105
+
106
+ paths.each do |p|
107
+ if f = p.find(@imported_filename, @options.dup)
108
+ return f
109
+ end
110
+ end
111
+
112
+ message = "File to import not found or unreadable: #{@imported_filename}.\n"
113
+ if paths.size == 1
114
+ message << "Load path: #{paths.first}"
115
+ else
116
+ message << "Load paths:\n " << paths.join("\n ")
117
+ end
118
+ raise SyntaxError.new(message)
119
+ rescue SyntaxError => e
120
+ raise SyntaxError.new(e.message, :line => self.line, :filename => @filename)
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,60 @@
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<(Script::Node, Script::Node)>] The arguments for the mixin.
9
+ # Each element is a tuple containing the variable for 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
+ # @see Node#to_src
20
+ def to_src(tabs, opts, fmt)
21
+ args =
22
+ if @args.empty?
23
+ ""
24
+ else
25
+ '(' + @args.map do |v, d|
26
+ if d
27
+ "#{v.to_sass(opts)}: #{d.to_sass(opts)}"
28
+ else
29
+ v.to_sass(opts)
30
+ end
31
+ end.join(", ") + ')'
32
+ end
33
+
34
+ "#{' ' * tabs}#{fmt == :sass ? '=' : '@mixin '}#{dasherize(@name, opts)}#{args}" +
35
+ children_to_src(tabs, opts, fmt)
36
+ end
37
+
38
+ # Loads the mixin into the environment.
39
+ #
40
+ # @param environment [Sass::Environment] The lexical environment containing
41
+ # variable and mixin values
42
+ def _perform(environment)
43
+ environment.set_mixin(@name, Sass::Mixin.new(@name, @args, environment, children))
44
+ []
45
+ end
46
+
47
+ # Returns an error message if the given child node is invalid,
48
+ # and false otherwise.
49
+ #
50
+ # {ExtendNode}s are valid within {MixinDefNode}s.
51
+ #
52
+ # @param child [Tree::Node] A potential child node.
53
+ # @return [Boolean, String] Whether or not the child node is valid,
54
+ # as well as the error message to display if it is invalid
55
+ def invalid_child?(child)
56
+ super unless child.is_a?(ExtendNode)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,123 @@
1
+ require 'sass/tree/node'
2
+
3
+ module Sass::Tree
4
+ # A static node representing a mixin include.
5
+ # When in a static tree, the sole purpose is to wrap exceptions
6
+ # to add the mixin to the backtrace.
7
+ #
8
+ # @see Sass::Tree
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
+
16
+ # @param name [String] The name of the mixin
17
+ # @param args [Array<Script::Node>] The arguments to the mixin
18
+ def initialize(name, args)
19
+ @name = name
20
+ @args = args
21
+ super()
22
+ end
23
+
24
+ # @see Node#cssize
25
+ def cssize(extends, parent = nil)
26
+ _cssize(extends, parent) # Pass on the parent even if it's not a MixinNode
27
+ end
28
+
29
+ protected
30
+
31
+ # Returns an error message if the given child node is invalid,
32
+ # and false otherwise.
33
+ #
34
+ # {ExtendNode}s are valid within {MixinNode}s.
35
+ #
36
+ # @param child [Tree::Node] A potential child node
37
+ # @return [Boolean, String] Whether or not the child node is valid,
38
+ # as well as the error message to display if it is invalid
39
+ def invalid_child?(child)
40
+ super unless child.is_a?(ExtendNode)
41
+ end
42
+
43
+ # @see Node#to_src
44
+ def to_src(tabs, opts, fmt)
45
+ args = '(' + @args.map {|a| a.to_sass(opts)}.join(", ") + ')' unless @args.empty?
46
+ "#{' ' * tabs}#{fmt == :sass ? '+' : '@include '}#{dasherize(@name, opts)}#{args}#{semi fmt}\n"
47
+ end
48
+
49
+ # @see Node#_cssize
50
+ def _cssize(extends, parent)
51
+ children.map do |c|
52
+ parent.check_child! c
53
+ c.cssize(extends, parent)
54
+ end.flatten
55
+ rescue Sass::SyntaxError => e
56
+ e.modify_backtrace(:mixin => @name, :filename => filename, :line => line)
57
+ e.add_backtrace(:filename => filename, :line => line)
58
+ raise e
59
+ end
60
+
61
+ # Runs the mixin.
62
+ #
63
+ # @param environment [Sass::Environment] The lexical environment containing
64
+ # variable and mixin values
65
+ # @raise [Sass::SyntaxError] if there is no mixin with the given name
66
+ # @raise [Sass::SyntaxError] if an incorrect number of arguments was passed
67
+ # @see Sass::Tree
68
+ def perform!(environment)
69
+ handle_include_loop!(environment) if environment.mixins_in_use.include?(@name)
70
+
71
+ original_env = environment
72
+ original_env.push_frame(:filename => filename, :line => line)
73
+ original_env.prepare_frame(:mixin => @name)
74
+ raise Sass::SyntaxError.new("Undefined mixin '#{@name}'.") unless mixin = environment.mixin(@name)
75
+
76
+ raise Sass::SyntaxError.new(<<END.gsub("\n", "")) if mixin.args.size < @args.size
77
+ Mixin #{@name} takes #{mixin.args.size} argument#{'s' if mixin.args.size != 1}
78
+ but #{@args.size} #{@args.size == 1 ? 'was' : 'were'} passed.
79
+ END
80
+ environment = mixin.args.zip(@args).
81
+ inject(Sass::Environment.new(mixin.environment)) do |env, ((var, default), value)|
82
+ env.set_local_var(var.name,
83
+ if value
84
+ value.perform(environment)
85
+ elsif default
86
+ val = default.perform(env)
87
+ if default.context == :equals && val.is_a?(Sass::Script::String)
88
+ val = Sass::Script::String.new(val.value)
89
+ end
90
+ val
91
+ end)
92
+ raise Sass::SyntaxError.new("Mixin #{@name} is missing parameter #{var.inspect}.") unless env.var(var.name)
93
+ env
94
+ end
95
+
96
+ self.children = mixin.tree.map {|c| c.perform(environment)}.flatten
97
+ rescue Sass::SyntaxError => e
98
+ if original_env # Don't add backtrace info if this is an @include loop
99
+ e.modify_backtrace(:mixin => @name, :line => @line)
100
+ e.add_backtrace(:line => @line)
101
+ end
102
+ raise e
103
+ ensure
104
+ original_env.pop_frame if original_env
105
+ end
106
+
107
+ private
108
+
109
+ def handle_include_loop!(environment)
110
+ msg = "An @include loop has been found:"
111
+ mixins = environment.stack.map {|s| s[:mixin]}.compact
112
+ if mixins.size == 2 && mixins[0] == mixins[1]
113
+ raise Sass::SyntaxError.new("#{msg} #{@name} includes itself")
114
+ end
115
+
116
+ mixins << @name
117
+ msg << "\n" << Sass::Util.enum_cons(mixins, 2).map do |m1, m2|
118
+ " #{m1} includes #{m2}"
119
+ end.join("\n")
120
+ raise Sass::SyntaxError.new(msg)
121
+ end
122
+ end
123
+ end