aliddle-sass 1.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 (238) hide show
  1. data/.yardopts +11 -0
  2. data/CONTRIBUTING +3 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +201 -0
  5. data/Rakefile +347 -0
  6. data/VERSION +1 -0
  7. data/VERSION_NAME +1 -0
  8. data/bin/sass +9 -0
  9. data/bin/sass-convert +8 -0
  10. data/bin/scss +9 -0
  11. data/extra/update_watch.rb +13 -0
  12. data/init.rb +18 -0
  13. data/lib/sass.rb +95 -0
  14. data/lib/sass/cache_stores.rb +15 -0
  15. data/lib/sass/cache_stores/base.rb +88 -0
  16. data/lib/sass/cache_stores/chain.rb +33 -0
  17. data/lib/sass/cache_stores/filesystem.rb +60 -0
  18. data/lib/sass/cache_stores/memory.rb +47 -0
  19. data/lib/sass/cache_stores/null.rb +25 -0
  20. data/lib/sass/callbacks.rb +66 -0
  21. data/lib/sass/css.rb +409 -0
  22. data/lib/sass/engine.rb +928 -0
  23. data/lib/sass/environment.rb +101 -0
  24. data/lib/sass/error.rb +201 -0
  25. data/lib/sass/exec.rb +707 -0
  26. data/lib/sass/importers.rb +22 -0
  27. data/lib/sass/importers/base.rb +139 -0
  28. data/lib/sass/importers/filesystem.rb +190 -0
  29. data/lib/sass/logger.rb +15 -0
  30. data/lib/sass/logger/base.rb +32 -0
  31. data/lib/sass/logger/log_level.rb +49 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin.rb +132 -0
  34. data/lib/sass/plugin/compiler.rb +406 -0
  35. data/lib/sass/plugin/configuration.rb +123 -0
  36. data/lib/sass/plugin/generic.rb +15 -0
  37. data/lib/sass/plugin/merb.rb +48 -0
  38. data/lib/sass/plugin/rack.rb +60 -0
  39. data/lib/sass/plugin/rails.rb +47 -0
  40. data/lib/sass/plugin/staleness_checker.rb +183 -0
  41. data/lib/sass/railtie.rb +9 -0
  42. data/lib/sass/repl.rb +57 -0
  43. data/lib/sass/root.rb +7 -0
  44. data/lib/sass/script.rb +39 -0
  45. data/lib/sass/script/arg_list.rb +52 -0
  46. data/lib/sass/script/bool.rb +18 -0
  47. data/lib/sass/script/color.rb +606 -0
  48. data/lib/sass/script/css_lexer.rb +29 -0
  49. data/lib/sass/script/css_parser.rb +31 -0
  50. data/lib/sass/script/funcall.rb +237 -0
  51. data/lib/sass/script/functions.rb +1543 -0
  52. data/lib/sass/script/interpolation.rb +79 -0
  53. data/lib/sass/script/lexer.rb +348 -0
  54. data/lib/sass/script/list.rb +85 -0
  55. data/lib/sass/script/literal.rb +221 -0
  56. data/lib/sass/script/node.rb +99 -0
  57. data/lib/sass/script/null.rb +37 -0
  58. data/lib/sass/script/number.rb +453 -0
  59. data/lib/sass/script/operation.rb +110 -0
  60. data/lib/sass/script/parser.rb +495 -0
  61. data/lib/sass/script/string.rb +51 -0
  62. data/lib/sass/script/string_interpolation.rb +103 -0
  63. data/lib/sass/script/unary_operation.rb +69 -0
  64. data/lib/sass/script/variable.rb +58 -0
  65. data/lib/sass/scss.rb +16 -0
  66. data/lib/sass/scss/css_parser.rb +36 -0
  67. data/lib/sass/scss/parser.rb +1179 -0
  68. data/lib/sass/scss/rx.rb +133 -0
  69. data/lib/sass/scss/script_lexer.rb +15 -0
  70. data/lib/sass/scss/script_parser.rb +25 -0
  71. data/lib/sass/scss/static_parser.rb +54 -0
  72. data/lib/sass/selector.rb +452 -0
  73. data/lib/sass/selector/abstract_sequence.rb +94 -0
  74. data/lib/sass/selector/comma_sequence.rb +92 -0
  75. data/lib/sass/selector/sequence.rb +507 -0
  76. data/lib/sass/selector/simple.rb +119 -0
  77. data/lib/sass/selector/simple_sequence.rb +212 -0
  78. data/lib/sass/shared.rb +76 -0
  79. data/lib/sass/supports.rb +229 -0
  80. data/lib/sass/tree/charset_node.rb +22 -0
  81. data/lib/sass/tree/comment_node.rb +82 -0
  82. data/lib/sass/tree/content_node.rb +9 -0
  83. data/lib/sass/tree/css_import_node.rb +60 -0
  84. data/lib/sass/tree/debug_node.rb +18 -0
  85. data/lib/sass/tree/directive_node.rb +42 -0
  86. data/lib/sass/tree/each_node.rb +24 -0
  87. data/lib/sass/tree/extend_node.rb +36 -0
  88. data/lib/sass/tree/for_node.rb +36 -0
  89. data/lib/sass/tree/function_node.rb +34 -0
  90. data/lib/sass/tree/if_node.rb +52 -0
  91. data/lib/sass/tree/import_node.rb +75 -0
  92. data/lib/sass/tree/media_node.rb +58 -0
  93. data/lib/sass/tree/mixin_def_node.rb +38 -0
  94. data/lib/sass/tree/mixin_node.rb +39 -0
  95. data/lib/sass/tree/node.rb +196 -0
  96. data/lib/sass/tree/prop_node.rb +152 -0
  97. data/lib/sass/tree/return_node.rb +18 -0
  98. data/lib/sass/tree/root_node.rb +28 -0
  99. data/lib/sass/tree/rule_node.rb +132 -0
  100. data/lib/sass/tree/supports_node.rb +51 -0
  101. data/lib/sass/tree/trace_node.rb +32 -0
  102. data/lib/sass/tree/variable_node.rb +30 -0
  103. data/lib/sass/tree/visitors/base.rb +75 -0
  104. data/lib/sass/tree/visitors/check_nesting.rb +147 -0
  105. data/lib/sass/tree/visitors/convert.rb +316 -0
  106. data/lib/sass/tree/visitors/cssize.rb +229 -0
  107. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  108. data/lib/sass/tree/visitors/extend.rb +68 -0
  109. data/lib/sass/tree/visitors/perform.rb +446 -0
  110. data/lib/sass/tree/visitors/set_options.rb +125 -0
  111. data/lib/sass/tree/visitors/to_css.rb +230 -0
  112. data/lib/sass/tree/warn_node.rb +18 -0
  113. data/lib/sass/tree/while_node.rb +18 -0
  114. data/lib/sass/util.rb +906 -0
  115. data/lib/sass/util/multibyte_string_scanner.rb +155 -0
  116. data/lib/sass/util/subset_map.rb +109 -0
  117. data/lib/sass/util/test.rb +10 -0
  118. data/lib/sass/version.rb +126 -0
  119. data/rails/init.rb +1 -0
  120. data/test/Gemfile +3 -0
  121. data/test/Gemfile.lock +10 -0
  122. data/test/sass/cache_test.rb +89 -0
  123. data/test/sass/callbacks_test.rb +61 -0
  124. data/test/sass/conversion_test.rb +1760 -0
  125. data/test/sass/css2sass_test.rb +439 -0
  126. data/test/sass/data/hsl-rgb.txt +319 -0
  127. data/test/sass/engine_test.rb +3243 -0
  128. data/test/sass/exec_test.rb +86 -0
  129. data/test/sass/extend_test.rb +1461 -0
  130. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  131. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  132. data/test/sass/functions_test.rb +1139 -0
  133. data/test/sass/importer_test.rb +192 -0
  134. data/test/sass/logger_test.rb +58 -0
  135. data/test/sass/mock_importer.rb +49 -0
  136. data/test/sass/more_results/more1.css +9 -0
  137. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  138. data/test/sass/more_results/more_import.css +29 -0
  139. data/test/sass/more_templates/_more_partial.sass +2 -0
  140. data/test/sass/more_templates/more1.sass +23 -0
  141. data/test/sass/more_templates/more_import.sass +11 -0
  142. data/test/sass/plugin_test.rb +550 -0
  143. data/test/sass/results/alt.css +4 -0
  144. data/test/sass/results/basic.css +9 -0
  145. data/test/sass/results/cached_import_option.css +3 -0
  146. data/test/sass/results/compact.css +5 -0
  147. data/test/sass/results/complex.css +86 -0
  148. data/test/sass/results/compressed.css +1 -0
  149. data/test/sass/results/expanded.css +19 -0
  150. data/test/sass/results/filename_fn.css +3 -0
  151. data/test/sass/results/if.css +3 -0
  152. data/test/sass/results/import.css +31 -0
  153. data/test/sass/results/import_charset.css +5 -0
  154. data/test/sass/results/import_charset_1_8.css +5 -0
  155. data/test/sass/results/import_charset_ibm866.css +5 -0
  156. data/test/sass/results/import_content.css +1 -0
  157. data/test/sass/results/line_numbers.css +49 -0
  158. data/test/sass/results/mixins.css +95 -0
  159. data/test/sass/results/multiline.css +24 -0
  160. data/test/sass/results/nested.css +22 -0
  161. data/test/sass/results/options.css +1 -0
  162. data/test/sass/results/parent_ref.css +13 -0
  163. data/test/sass/results/script.css +16 -0
  164. data/test/sass/results/scss_import.css +31 -0
  165. data/test/sass/results/scss_importee.css +2 -0
  166. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  167. data/test/sass/results/subdir/subdir.css +3 -0
  168. data/test/sass/results/units.css +11 -0
  169. data/test/sass/results/warn.css +0 -0
  170. data/test/sass/results/warn_imported.css +0 -0
  171. data/test/sass/script_conversion_test.rb +299 -0
  172. data/test/sass/script_test.rb +591 -0
  173. data/test/sass/scss/css_test.rb +1093 -0
  174. data/test/sass/scss/rx_test.rb +156 -0
  175. data/test/sass/scss/scss_test.rb +2043 -0
  176. data/test/sass/scss/test_helper.rb +37 -0
  177. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  178. data/test/sass/templates/_double_import_loop2.sass +1 -0
  179. data/test/sass/templates/_filename_fn_import.scss +11 -0
  180. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  181. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  182. data/test/sass/templates/_imported_content.sass +3 -0
  183. data/test/sass/templates/_partial.sass +2 -0
  184. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  185. data/test/sass/templates/alt.sass +16 -0
  186. data/test/sass/templates/basic.sass +23 -0
  187. data/test/sass/templates/bork1.sass +2 -0
  188. data/test/sass/templates/bork2.sass +2 -0
  189. data/test/sass/templates/bork3.sass +2 -0
  190. data/test/sass/templates/bork4.sass +2 -0
  191. data/test/sass/templates/bork5.sass +3 -0
  192. data/test/sass/templates/cached_import_option.scss +3 -0
  193. data/test/sass/templates/compact.sass +17 -0
  194. data/test/sass/templates/complex.sass +305 -0
  195. data/test/sass/templates/compressed.sass +15 -0
  196. data/test/sass/templates/double_import_loop1.sass +1 -0
  197. data/test/sass/templates/expanded.sass +17 -0
  198. data/test/sass/templates/filename_fn.scss +18 -0
  199. data/test/sass/templates/if.sass +11 -0
  200. data/test/sass/templates/import.sass +12 -0
  201. data/test/sass/templates/import_charset.sass +9 -0
  202. data/test/sass/templates/import_charset_1_8.sass +6 -0
  203. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  204. data/test/sass/templates/import_content.sass +4 -0
  205. data/test/sass/templates/importee.less +2 -0
  206. data/test/sass/templates/importee.sass +19 -0
  207. data/test/sass/templates/line_numbers.sass +13 -0
  208. data/test/sass/templates/mixin_bork.sass +5 -0
  209. data/test/sass/templates/mixins.sass +76 -0
  210. data/test/sass/templates/multiline.sass +20 -0
  211. data/test/sass/templates/nested.sass +25 -0
  212. data/test/sass/templates/nested_bork1.sass +2 -0
  213. data/test/sass/templates/nested_bork2.sass +2 -0
  214. data/test/sass/templates/nested_bork3.sass +2 -0
  215. data/test/sass/templates/nested_bork4.sass +2 -0
  216. data/test/sass/templates/nested_import.sass +2 -0
  217. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  218. data/test/sass/templates/options.sass +2 -0
  219. data/test/sass/templates/parent_ref.sass +25 -0
  220. data/test/sass/templates/same_name_different_ext.sass +2 -0
  221. data/test/sass/templates/same_name_different_ext.scss +1 -0
  222. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  223. data/test/sass/templates/script.sass +101 -0
  224. data/test/sass/templates/scss_import.scss +11 -0
  225. data/test/sass/templates/scss_importee.scss +1 -0
  226. data/test/sass/templates/single_import_loop.sass +1 -0
  227. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  228. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  229. data/test/sass/templates/subdir/subdir.sass +6 -0
  230. data/test/sass/templates/units.sass +11 -0
  231. data/test/sass/templates/warn.sass +3 -0
  232. data/test/sass/templates/warn_imported.sass +4 -0
  233. data/test/sass/test_helper.rb +8 -0
  234. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  235. data/test/sass/util/subset_map_test.rb +91 -0
  236. data/test/sass/util_test.rb +313 -0
  237. data/test/test_helper.rb +80 -0
  238. metadata +348 -0
@@ -0,0 +1,58 @@
1
+ module Sass::Tree
2
+ # A static node representing a `@media` rule.
3
+ # `@media` rules behave differently from other directives
4
+ # in that when they're nested within rules,
5
+ # they bubble up to top-level.
6
+ #
7
+ # @see Sass::Tree
8
+ class MediaNode < DirectiveNode
9
+ # TODO: parse and cache the query immediately if it has no dynamic elements
10
+
11
+ # The media query for this rule, interspersed with {Sass::Script::Node}s
12
+ # representing `#{}`-interpolation. Any adjacent strings will be merged
13
+ # together.
14
+ #
15
+ # @return [Array<String, Sass::Script::Node>]
16
+ attr_accessor :query
17
+
18
+ # The media query for this rule, without any unresolved interpolation. It's
19
+ # only set once {Tree::Node#perform} has been called.
20
+ #
21
+ # @return [Sass::Media::QueryList]
22
+ attr_accessor :resolved_query
23
+
24
+ # @see RuleNode#tabs
25
+ attr_accessor :tabs
26
+
27
+ # @see RuleNode#group_end
28
+ attr_accessor :group_end
29
+
30
+ # @param query [Array<String, Sass::Script::Node>] See \{#query}
31
+ def initialize(query)
32
+ @query = query
33
+ @tabs = 0
34
+ super('')
35
+ end
36
+
37
+ # @see DirectiveNode#value
38
+ def value; raise NotImplementedError; end
39
+
40
+ # @see DirectiveNode#name
41
+ def name; '@media'; end
42
+
43
+ # @see DirectiveNode#resolved_value
44
+ def resolved_value
45
+ @resolved_value ||= "@media #{resolved_query.to_css}"
46
+ end
47
+
48
+ # True when the directive has no visible children.
49
+ #
50
+ # @return [Boolean]
51
+ def invisible?
52
+ children.all? {|c| c.invisible?}
53
+ end
54
+
55
+ # @see Node#bubbles?
56
+ def bubbles?; true; end
57
+ end
58
+ end
@@ -0,0 +1,38 @@
1
+ module Sass
2
+ module Tree
3
+ # A dynamic node representing a mixin definition.
4
+ #
5
+ # @see Sass::Tree
6
+ class MixinDefNode < Node
7
+ # The mixin name.
8
+ # @return [String]
9
+ attr_reader :name
10
+
11
+ # The arguments for the mixin.
12
+ # Each element is a tuple containing the variable for argument
13
+ # and the parse tree for the default value of the argument.
14
+ #
15
+ # @return [Array<(Script::Node, Script::Node)>]
16
+ attr_accessor :args
17
+
18
+ # The splat argument for this mixin, if one exists.
19
+ #
20
+ # @return [Script::Node?]
21
+ attr_accessor :splat
22
+
23
+ # Whether the mixin uses `@content`. Set during the nesting check phase.
24
+ # @return [Boolean]
25
+ attr_accessor :has_content
26
+
27
+ # @param name [String] The mixin name
28
+ # @param args [Array<(Script::Node, Script::Node)>] See \{#args}
29
+ # @param splat [Script::Node] See \{#splat}
30
+ def initialize(name, args, splat)
31
+ @name = name
32
+ @args = args
33
+ @splat = splat
34
+ super()
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,39 @@
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
+ # The name of the mixin.
11
+ # @return [String]
12
+ attr_reader :name
13
+
14
+ # The arguments to the mixin.
15
+ # @return [Array<Script::Node>]
16
+ attr_accessor :args
17
+
18
+ # A hash from keyword argument names to values.
19
+ # @return [{String => Script::Node}]
20
+ attr_accessor :keywords
21
+
22
+ # The splat argument for this mixin, if one exists.
23
+ #
24
+ # @return [Script::Node?]
25
+ attr_accessor :splat
26
+
27
+ # @param name [String] The name of the mixin
28
+ # @param args [Array<Script::Node>] See \{#args}
29
+ # @param splat [Script::Node] See \{#splat}
30
+ # @param keywords [{String => Script::Node}] See \{#keywords}
31
+ def initialize(name, args, keywords, splat)
32
+ @name = name
33
+ @args = args
34
+ @keywords = keywords
35
+ @splat = splat
36
+ super()
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,196 @@
1
+ module Sass
2
+ # A namespace for nodes in the Sass parse tree.
3
+ #
4
+ # The Sass parse tree has three states: dynamic, static Sass, and static CSS.
5
+ #
6
+ # When it's first parsed, a Sass document is in the dynamic state.
7
+ # It has nodes for mixin definitions and `@for` loops and so forth,
8
+ # in addition to nodes for CSS rules and properties.
9
+ # Nodes that only appear in this state are called **dynamic nodes**.
10
+ #
11
+ # {Tree::Visitors::Perform} creates a static Sass tree, which is different.
12
+ # It still has nodes for CSS rules and properties
13
+ # but it doesn't have any dynamic-generation-related nodes.
14
+ # The nodes in this state are in the same structure as the Sass document:
15
+ # rules and properties are nested beneath one another.
16
+ # Nodes that can be in this state or in the dynamic state
17
+ # are called **static nodes**; nodes that can only be in this state
18
+ # are called **solely static nodes**.
19
+ #
20
+ # {Tree::Visitors::Cssize} is then used to create a static CSS tree.
21
+ # This is like a static Sass tree,
22
+ # but the structure exactly mirrors that of the generated CSS.
23
+ # Rules and properties can't be nested beneath one another in this state.
24
+ #
25
+ # Finally, {Tree::Visitors::ToCss} can be called on a static CSS tree
26
+ # to get the actual CSS code as a string.
27
+ module Tree
28
+ # The abstract superclass of all parse-tree nodes.
29
+ class Node
30
+ include Enumerable
31
+
32
+ # The child nodes of this node.
33
+ #
34
+ # @return [Array<Tree::Node>]
35
+ attr_accessor :children
36
+
37
+ # Whether or not this node has child nodes.
38
+ # This may be true even when \{#children} is empty,
39
+ # in which case this node has an empty block (e.g. `{}`).
40
+ #
41
+ # @return [Boolean]
42
+ attr_accessor :has_children
43
+
44
+ # The line of the document on which this node appeared.
45
+ #
46
+ # @return [Fixnum]
47
+ attr_accessor :line
48
+
49
+ # The name of the document on which this node appeared.
50
+ #
51
+ # @return [String]
52
+ attr_writer :filename
53
+
54
+ # The options hash for the node.
55
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
56
+ #
57
+ # @return [{Symbol => Object}]
58
+ attr_reader :options
59
+
60
+ def initialize
61
+ @children = []
62
+ end
63
+
64
+ # Sets the options hash for the node and all its children.
65
+ #
66
+ # @param options [{Symbol => Object}] The options
67
+ # @see #options
68
+ def options=(options)
69
+ Sass::Tree::Visitors::SetOptions.visit(self, options)
70
+ end
71
+
72
+ # @private
73
+ def children=(children)
74
+ self.has_children ||= !children.empty?
75
+ @children = children
76
+ end
77
+
78
+ # The name of the document on which this node appeared.
79
+ #
80
+ # @return [String]
81
+ def filename
82
+ @filename || (@options && @options[:filename])
83
+ end
84
+
85
+ # Appends a child to the node.
86
+ #
87
+ # @param child [Tree::Node, Array<Tree::Node>] The child node or nodes
88
+ # @raise [Sass::SyntaxError] if `child` is invalid
89
+ def <<(child)
90
+ return if child.nil?
91
+ if child.is_a?(Array)
92
+ child.each {|c| self << c}
93
+ else
94
+ self.has_children = true
95
+ @children << child
96
+ end
97
+ end
98
+
99
+ # Compares this node and another object (only other {Tree::Node}s will be equal).
100
+ # This does a structural comparison;
101
+ # if the contents of the nodes and all the child nodes are equivalent,
102
+ # then the nodes are as well.
103
+ #
104
+ # Only static nodes need to override this.
105
+ #
106
+ # @param other [Object] The object to compare with
107
+ # @return [Boolean] Whether or not this node and the other object
108
+ # are the same
109
+ # @see Sass::Tree
110
+ def ==(other)
111
+ self.class == other.class && other.children == children
112
+ end
113
+
114
+ # True if \{#to\_s} will return `nil`;
115
+ # that is, if the node shouldn't be rendered.
116
+ # Should only be called in a static tree.
117
+ #
118
+ # @return [Boolean]
119
+ def invisible?; false; end
120
+
121
+ # The output style. See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
122
+ #
123
+ # @return [Symbol]
124
+ def style
125
+ @options[:style]
126
+ end
127
+
128
+ # Computes the CSS corresponding to this static CSS tree.
129
+ #
130
+ # @return [String, nil] The resulting CSS
131
+ # @see Sass::Tree
132
+ def to_s
133
+ Sass::Tree::Visitors::ToCss.visit(self)
134
+ end
135
+
136
+ # Returns a representation of the node for debugging purposes.
137
+ #
138
+ # @return [String]
139
+ def inspect
140
+ return self.class.to_s unless has_children
141
+ "(#{self.class} #{children.map {|c| c.inspect}.join(' ')})"
142
+ end
143
+
144
+ # Iterates through each node in the tree rooted at this node
145
+ # in a pre-order walk.
146
+ #
147
+ # @yield node
148
+ # @yieldparam node [Node] a node in the tree
149
+ def each
150
+ yield self
151
+ children.each {|c| c.each {|n| yield n}}
152
+ end
153
+
154
+ # Converts a node to Sass code that will generate it.
155
+ #
156
+ # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
157
+ # @return [String] The Sass code corresponding to the node
158
+ def to_sass(options = {})
159
+ Sass::Tree::Visitors::Convert.visit(self, options, :sass)
160
+ end
161
+
162
+ # Converts a node to SCSS code that will generate it.
163
+ #
164
+ # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
165
+ # @return [String] The Sass code corresponding to the node
166
+ def to_scss(options = {})
167
+ Sass::Tree::Visitors::Convert.visit(self, options, :scss)
168
+ end
169
+
170
+ # Return a deep clone of this node.
171
+ # The child nodes are cloned, but options are not.
172
+ #
173
+ # @return [Node]
174
+ def deep_copy
175
+ Sass::Tree::Visitors::DeepCopy.visit(self)
176
+ end
177
+
178
+ # Whether or not this node bubbles up through RuleNodes.
179
+ #
180
+ # @return [Boolean]
181
+ def bubbles?
182
+ false
183
+ end
184
+
185
+ protected
186
+
187
+ # @see Sass::Shared.balance
188
+ # @raise [Sass::SyntaxError] if the brackets aren't balanced
189
+ def balance(*args)
190
+ res = Sass::Shared.balance(*args)
191
+ return res if res
192
+ raise Sass::SyntaxError.new("Unbalanced brackets.", :line => line)
193
+ end
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,152 @@
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
+ # interspersed with {Sass::Script::Node}s
8
+ # representing `#{}`-interpolation.
9
+ # Any adjacent strings will be merged together.
10
+ #
11
+ # @return [Array<String, Sass::Script::Node>]
12
+ attr_accessor :name
13
+
14
+ # The name of the property
15
+ # after any interpolated SassScript has been resolved.
16
+ # Only set once \{Tree::Visitors::Perform} has been run.
17
+ #
18
+ # @return [String]
19
+ attr_accessor :resolved_name
20
+
21
+ # The value of the property.
22
+ #
23
+ # @return [Sass::Script::Node]
24
+ attr_accessor :value
25
+
26
+ # The value of the property
27
+ # after any interpolated SassScript has been resolved.
28
+ # Only set once \{Tree::Visitors::Perform} has been run.
29
+ #
30
+ # @return [String]
31
+ attr_accessor :resolved_value
32
+
33
+ # How deep this property is indented
34
+ # relative to a normal property.
35
+ # This is only greater than 0 in the case that:
36
+ #
37
+ # * This node is in a CSS tree
38
+ # * The style is :nested
39
+ # * This is a child property of another property
40
+ # * The parent property has a value, and thus will be rendered
41
+ #
42
+ # @return [Fixnum]
43
+ attr_accessor :tabs
44
+
45
+ # @param name [Array<String, Sass::Script::Node>] See \{#name}
46
+ # @param value [Sass::Script::Node] See \{#value}
47
+ # @param prop_syntax [Symbol] `:new` if this property uses `a: b`-style syntax,
48
+ # `:old` if it uses `:a b`-style syntax
49
+ def initialize(name, value, prop_syntax)
50
+ @name = Sass::Util.strip_string_array(
51
+ Sass::Util.merge_adjacent_strings(name))
52
+ @value = value
53
+ @tabs = 0
54
+ @prop_syntax = prop_syntax
55
+ super()
56
+ end
57
+
58
+ # Compares the names and values of two properties.
59
+ #
60
+ # @param other [Object] The object to compare with
61
+ # @return [Boolean] Whether or not this node and the other object
62
+ # are the same
63
+ def ==(other)
64
+ self.class == other.class && name == other.name && value == other.value && super
65
+ end
66
+
67
+ # Returns a appropriate message indicating how to escape pseudo-class selectors.
68
+ # This only applies for old-style properties with no value,
69
+ # so returns the empty string if this is new-style.
70
+ #
71
+ # @return [String] The message
72
+ def pseudo_class_selector_message
73
+ return "" if @prop_syntax == :new || !value.is_a?(Sass::Script::String) || !value.value.empty?
74
+ "\nIf #{declaration.dump} should be a selector, use \"\\#{declaration}\" instead."
75
+ end
76
+
77
+ # Computes the Sass or SCSS code for the variable declaration.
78
+ # This is like \{#to\_scss} or \{#to\_sass},
79
+ # except it doesn't print any child properties or a trailing semicolon.
80
+ #
81
+ # @param opts [{Symbol => Object}] The options hash for the tree.
82
+ # @param fmt [Symbol] `:scss` or `:sass`.
83
+ def declaration(opts = {:old => @prop_syntax == :old}, fmt = :sass)
84
+ name = self.name.map {|n| n.is_a?(String) ? n : "\#{#{n.to_sass(opts)}}"}.join
85
+ if name[0] == ?:
86
+ raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\" hack is not allowed in the Sass indented syntax")
87
+ end
88
+
89
+ old = opts[:old] && fmt == :sass
90
+ initial = old ? ':' : ''
91
+ mid = old ? '' : ':'
92
+ "#{initial}#{name}#{mid} #{self.class.val_to_sass(value, opts)}".rstrip
93
+ end
94
+
95
+ # A property node is invisible if its value is empty.
96
+ #
97
+ # @return [Boolean]
98
+ def invisible?
99
+ resolved_value.empty?
100
+ end
101
+
102
+ private
103
+
104
+ def check!
105
+ if @options[:property_syntax] && @options[:property_syntax] != @prop_syntax
106
+ raise Sass::SyntaxError.new(
107
+ "Illegal property syntax: can't use #{@prop_syntax} syntax when :property_syntax => #{@options[:property_syntax].inspect} is set.")
108
+ end
109
+ end
110
+
111
+ class << self
112
+ # @private
113
+ def val_to_sass(value, opts)
114
+ val_to_sass_comma(value, opts).to_sass(opts)
115
+ end
116
+
117
+ private
118
+
119
+ def val_to_sass_comma(node, opts)
120
+ return node unless node.is_a?(Sass::Script::Operation)
121
+ return val_to_sass_concat(node, opts) unless node.operator == :comma
122
+
123
+ Sass::Script::Operation.new(
124
+ val_to_sass_concat(node.operand1, opts),
125
+ val_to_sass_comma(node.operand2, opts),
126
+ node.operator)
127
+ end
128
+
129
+ def val_to_sass_concat(node, opts)
130
+ return node unless node.is_a?(Sass::Script::Operation)
131
+ return val_to_sass_div(node, opts) unless node.operator == :space
132
+
133
+ Sass::Script::Operation.new(
134
+ val_to_sass_div(node.operand1, opts),
135
+ val_to_sass_concat(node.operand2, opts),
136
+ node.operator)
137
+ end
138
+
139
+ def val_to_sass_div(node, opts)
140
+ unless node.is_a?(Sass::Script::Operation) && node.operator == :div &&
141
+ node.operand1.is_a?(Sass::Script::Number) &&
142
+ node.operand2.is_a?(Sass::Script::Number) &&
143
+ (!node.operand1.original || !node.operand2.original)
144
+ return node
145
+ end
146
+
147
+ Sass::Script::String.new("(#{node.to_sass(opts)})")
148
+ end
149
+
150
+ end
151
+ end
152
+ end