sass 3.1.0 → 3.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 (260) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING +1 -1
  3. data/MIT-LICENSE +2 -2
  4. data/README.md +29 -17
  5. data/Rakefile +43 -9
  6. data/VERSION +1 -1
  7. data/VERSION_DATE +1 -0
  8. data/VERSION_NAME +1 -1
  9. data/bin/sass +6 -1
  10. data/bin/sass-convert +6 -1
  11. data/bin/scss +6 -1
  12. data/ext/mkrf_conf.rb +27 -0
  13. data/lib/sass/cache_stores/base.rb +7 -3
  14. data/lib/sass/cache_stores/chain.rb +3 -2
  15. data/lib/sass/cache_stores/filesystem.rb +5 -7
  16. data/lib/sass/cache_stores/memory.rb +1 -1
  17. data/lib/sass/cache_stores/null.rb +2 -2
  18. data/lib/sass/callbacks.rb +2 -1
  19. data/lib/sass/css.rb +168 -53
  20. data/lib/sass/engine.rb +502 -174
  21. data/lib/sass/environment.rb +151 -111
  22. data/lib/sass/error.rb +7 -7
  23. data/lib/sass/exec.rb +176 -60
  24. data/lib/sass/features.rb +40 -0
  25. data/lib/sass/importers/base.rb +46 -7
  26. data/lib/sass/importers/deprecated_path.rb +51 -0
  27. data/lib/sass/importers/filesystem.rb +113 -30
  28. data/lib/sass/importers.rb +1 -0
  29. data/lib/sass/logger/base.rb +30 -0
  30. data/lib/sass/logger/log_level.rb +45 -0
  31. data/lib/sass/logger.rb +12 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin/compiler.rb +194 -104
  34. data/lib/sass/plugin/configuration.rb +18 -25
  35. data/lib/sass/plugin/merb.rb +1 -1
  36. data/lib/sass/plugin/staleness_checker.rb +37 -11
  37. data/lib/sass/plugin.rb +10 -13
  38. data/lib/sass/railtie.rb +2 -1
  39. data/lib/sass/repl.rb +5 -6
  40. data/lib/sass/script/css_lexer.rb +8 -4
  41. data/lib/sass/script/css_parser.rb +5 -2
  42. data/lib/sass/script/functions.rb +1547 -618
  43. data/lib/sass/script/lexer.rb +122 -72
  44. data/lib/sass/script/parser.rb +304 -135
  45. data/lib/sass/script/tree/funcall.rb +306 -0
  46. data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
  47. data/lib/sass/script/tree/list_literal.rb +77 -0
  48. data/lib/sass/script/tree/literal.rb +45 -0
  49. data/lib/sass/script/tree/map_literal.rb +64 -0
  50. data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
  51. data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
  52. data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
  53. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
  54. data/lib/sass/script/tree/variable.rb +57 -0
  55. data/lib/sass/script/tree.rb +15 -0
  56. data/lib/sass/script/value/arg_list.rb +36 -0
  57. data/lib/sass/script/value/base.rb +238 -0
  58. data/lib/sass/script/value/bool.rb +40 -0
  59. data/lib/sass/script/{color.rb → value/color.rb} +256 -74
  60. data/lib/sass/script/value/deprecated_false.rb +55 -0
  61. data/lib/sass/script/value/helpers.rb +155 -0
  62. data/lib/sass/script/value/list.rb +128 -0
  63. data/lib/sass/script/value/map.rb +70 -0
  64. data/lib/sass/script/value/null.rb +49 -0
  65. data/lib/sass/script/{number.rb → value/number.rb} +115 -62
  66. data/lib/sass/script/{string.rb → value/string.rb} +9 -11
  67. data/lib/sass/script/value.rb +12 -0
  68. data/lib/sass/script.rb +35 -9
  69. data/lib/sass/scss/css_parser.rb +2 -12
  70. data/lib/sass/scss/parser.rb +657 -230
  71. data/lib/sass/scss/rx.rb +17 -12
  72. data/lib/sass/scss/static_parser.rb +37 -6
  73. data/lib/sass/scss.rb +0 -1
  74. data/lib/sass/selector/abstract_sequence.rb +35 -3
  75. data/lib/sass/selector/comma_sequence.rb +29 -14
  76. data/lib/sass/selector/sequence.rb +371 -74
  77. data/lib/sass/selector/simple.rb +28 -13
  78. data/lib/sass/selector/simple_sequence.rb +163 -36
  79. data/lib/sass/selector.rb +138 -36
  80. data/lib/sass/shared.rb +3 -5
  81. data/lib/sass/source/map.rb +196 -0
  82. data/lib/sass/source/position.rb +39 -0
  83. data/lib/sass/source/range.rb +41 -0
  84. data/lib/sass/stack.rb +126 -0
  85. data/lib/sass/supports.rb +228 -0
  86. data/lib/sass/tree/at_root_node.rb +82 -0
  87. data/lib/sass/tree/comment_node.rb +34 -29
  88. data/lib/sass/tree/content_node.rb +9 -0
  89. data/lib/sass/tree/css_import_node.rb +60 -0
  90. data/lib/sass/tree/debug_node.rb +3 -3
  91. data/lib/sass/tree/directive_node.rb +33 -3
  92. data/lib/sass/tree/each_node.rb +9 -9
  93. data/lib/sass/tree/extend_node.rb +20 -6
  94. data/lib/sass/tree/for_node.rb +6 -6
  95. data/lib/sass/tree/function_node.rb +12 -4
  96. data/lib/sass/tree/if_node.rb +2 -15
  97. data/lib/sass/tree/import_node.rb +11 -5
  98. data/lib/sass/tree/media_node.rb +27 -11
  99. data/lib/sass/tree/mixin_def_node.rb +15 -4
  100. data/lib/sass/tree/mixin_node.rb +27 -7
  101. data/lib/sass/tree/node.rb +69 -35
  102. data/lib/sass/tree/prop_node.rb +47 -31
  103. data/lib/sass/tree/return_node.rb +4 -3
  104. data/lib/sass/tree/root_node.rb +20 -4
  105. data/lib/sass/tree/rule_node.rb +37 -26
  106. data/lib/sass/tree/supports_node.rb +38 -0
  107. data/lib/sass/tree/trace_node.rb +33 -0
  108. data/lib/sass/tree/variable_node.rb +10 -4
  109. data/lib/sass/tree/visitors/base.rb +5 -8
  110. data/lib/sass/tree/visitors/check_nesting.rb +67 -52
  111. data/lib/sass/tree/visitors/convert.rb +134 -53
  112. data/lib/sass/tree/visitors/cssize.rb +245 -51
  113. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  114. data/lib/sass/tree/visitors/extend.rb +68 -0
  115. data/lib/sass/tree/visitors/perform.rb +331 -105
  116. data/lib/sass/tree/visitors/set_options.rb +125 -0
  117. data/lib/sass/tree/visitors/to_css.rb +259 -95
  118. data/lib/sass/tree/warn_node.rb +3 -3
  119. data/lib/sass/tree/while_node.rb +3 -3
  120. data/lib/sass/util/cross_platform_random.rb +19 -0
  121. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  122. data/lib/sass/util/normalized_map.rb +130 -0
  123. data/lib/sass/util/ordered_hash.rb +192 -0
  124. data/lib/sass/util/subset_map.rb +11 -2
  125. data/lib/sass/util/test.rb +9 -0
  126. data/lib/sass/util.rb +565 -39
  127. data/lib/sass/version.rb +27 -15
  128. data/lib/sass.rb +39 -4
  129. data/test/sass/cache_test.rb +15 -0
  130. data/test/sass/compiler_test.rb +223 -0
  131. data/test/sass/conversion_test.rb +901 -107
  132. data/test/sass/css2sass_test.rb +94 -0
  133. data/test/sass/engine_test.rb +1059 -164
  134. data/test/sass/exec_test.rb +86 -0
  135. data/test/sass/extend_test.rb +933 -837
  136. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  137. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  138. data/test/sass/functions_test.rb +995 -136
  139. data/test/sass/importer_test.rb +338 -18
  140. data/test/sass/logger_test.rb +58 -0
  141. data/test/sass/more_results/more_import.css +2 -2
  142. data/test/sass/plugin_test.rb +114 -30
  143. data/test/sass/results/cached_import_option.css +3 -0
  144. data/test/sass/results/filename_fn.css +3 -0
  145. data/test/sass/results/import.css +2 -2
  146. data/test/sass/results/import_charset.css +1 -0
  147. data/test/sass/results/import_charset_1_8.css +1 -0
  148. data/test/sass/results/import_charset_ibm866.css +1 -0
  149. data/test/sass/results/import_content.css +1 -0
  150. data/test/sass/results/script.css +1 -1
  151. data/test/sass/results/scss_import.css +2 -2
  152. data/test/sass/results/units.css +2 -2
  153. data/test/sass/script_conversion_test.rb +43 -1
  154. data/test/sass/script_test.rb +380 -36
  155. data/test/sass/scss/css_test.rb +257 -75
  156. data/test/sass/scss/scss_test.rb +2322 -110
  157. data/test/sass/source_map_test.rb +887 -0
  158. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  159. data/test/sass/templates/_double_import_loop2.sass +1 -0
  160. data/test/sass/templates/_filename_fn_import.scss +11 -0
  161. data/test/sass/templates/_imported_content.sass +3 -0
  162. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  163. data/test/sass/templates/bork5.sass +3 -0
  164. data/test/sass/templates/cached_import_option.scss +3 -0
  165. data/test/sass/templates/double_import_loop1.sass +1 -0
  166. data/test/sass/templates/filename_fn.scss +18 -0
  167. data/test/sass/templates/import_charset.sass +2 -0
  168. data/test/sass/templates/import_charset_1_8.sass +2 -0
  169. data/test/sass/templates/import_charset_ibm866.sass +2 -0
  170. data/test/sass/templates/import_content.sass +4 -0
  171. data/test/sass/templates/same_name_different_ext.sass +2 -0
  172. data/test/sass/templates/same_name_different_ext.scss +1 -0
  173. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  174. data/test/sass/templates/single_import_loop.sass +1 -0
  175. data/test/sass/templates/subdir/import_up1.scss +1 -0
  176. data/test/sass/templates/subdir/import_up2.scss +1 -0
  177. data/test/sass/test_helper.rb +1 -1
  178. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  179. data/test/sass/util/normalized_map_test.rb +51 -0
  180. data/test/sass/util_test.rb +183 -0
  181. data/test/sass/value_helpers_test.rb +181 -0
  182. data/test/test_helper.rb +45 -5
  183. data/vendor/listen/CHANGELOG.md +228 -0
  184. data/vendor/listen/CONTRIBUTING.md +38 -0
  185. data/vendor/listen/Gemfile +30 -0
  186. data/vendor/listen/Guardfile +8 -0
  187. data/vendor/{fssm → listen}/LICENSE +1 -1
  188. data/vendor/listen/README.md +315 -0
  189. data/vendor/listen/Rakefile +47 -0
  190. data/vendor/listen/Vagrantfile +96 -0
  191. data/vendor/listen/lib/listen/adapter.rb +214 -0
  192. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  193. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  194. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  195. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  196. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  197. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  198. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  199. data/vendor/listen/lib/listen/listener.rb +225 -0
  200. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  201. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  202. data/vendor/listen/lib/listen/version.rb +3 -0
  203. data/vendor/listen/lib/listen.rb +40 -0
  204. data/vendor/listen/listen.gemspec +22 -0
  205. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  206. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  207. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  208. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  209. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  210. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  211. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  212. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  213. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  214. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  215. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  216. data/vendor/listen/spec/listen_spec.rb +73 -0
  217. data/vendor/listen/spec/spec_helper.rb +21 -0
  218. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  219. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  220. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  221. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  222. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  223. metadata +344 -271
  224. data/lib/sass/less.rb +0 -382
  225. data/lib/sass/script/bool.rb +0 -18
  226. data/lib/sass/script/funcall.rb +0 -162
  227. data/lib/sass/script/list.rb +0 -76
  228. data/lib/sass/script/literal.rb +0 -245
  229. data/lib/sass/script/variable.rb +0 -54
  230. data/lib/sass/scss/sass_parser.rb +0 -11
  231. data/test/sass/less_conversion_test.rb +0 -653
  232. data/vendor/fssm/README.markdown +0 -55
  233. data/vendor/fssm/Rakefile +0 -59
  234. data/vendor/fssm/VERSION.yml +0 -5
  235. data/vendor/fssm/example.rb +0 -9
  236. data/vendor/fssm/fssm.gemspec +0 -77
  237. data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
  238. data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
  239. data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
  240. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
  241. data/vendor/fssm/lib/fssm/monitor.rb +0 -26
  242. data/vendor/fssm/lib/fssm/path.rb +0 -91
  243. data/vendor/fssm/lib/fssm/pathname.rb +0 -502
  244. data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
  245. data/vendor/fssm/lib/fssm/state/file.rb +0 -24
  246. data/vendor/fssm/lib/fssm/support.rb +0 -63
  247. data/vendor/fssm/lib/fssm/tree.rb +0 -176
  248. data/vendor/fssm/lib/fssm.rb +0 -33
  249. data/vendor/fssm/profile/prof-cache.rb +0 -40
  250. data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
  251. data/vendor/fssm/profile/prof-pathname.rb +0 -68
  252. data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
  253. data/vendor/fssm/profile/prof.html +0 -2379
  254. data/vendor/fssm/spec/path_spec.rb +0 -75
  255. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  256. data/vendor/fssm/spec/root/file.css +0 -0
  257. data/vendor/fssm/spec/root/file.rb +0 -0
  258. data/vendor/fssm/spec/root/file.yml +0 -0
  259. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  260. data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -8,13 +8,15 @@ module Sass
8
8
  # in addition to nodes for CSS rules and properties.
9
9
  # Nodes that only appear in this state are called **dynamic nodes**.
10
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**.
11
+ # {Tree::Visitors::Perform} creates a static Sass tree, which is
12
+ # different. It still has nodes for CSS rules and properties but it
13
+ # doesn't have any dynamic-generation-related nodes. The nodes in
14
+ # this state are in a similar structure to the Sass document: rules
15
+ # and properties are nested beneath one another, although the
16
+ # {Tree::RuleNode} selectors are already in their final state. Nodes
17
+ # that can be in this state or in the dynamic state are called
18
+ # **static nodes**; nodes that can only be in this state are called
19
+ # **solely static nodes**.
18
20
  #
19
21
  # {Tree::Visitors::Cssize} is then used to create a static CSS tree.
20
22
  # This is like a static Sass tree,
@@ -28,10 +30,35 @@ module Sass
28
30
  class Node
29
31
  include Enumerable
30
32
 
33
+ def self.inherited(base)
34
+ node_name = base.name.gsub(/.*::(.*?)Node$/, '\\1').downcase
35
+ base.instance_eval <<-METHODS
36
+ # @return [Symbol] The name that is used for this node when visiting.
37
+ def node_name
38
+ :#{node_name}
39
+ end
40
+
41
+ # @return [Symbol] The method that is used on the visitor to visit nodes of this type.
42
+ def visit_method
43
+ :visit_#{node_name}
44
+ end
45
+
46
+ # @return [Symbol] The method name that determines if the parent is invalid.
47
+ def invalid_child_method_name
48
+ :"invalid_#{node_name}_child?"
49
+ end
50
+
51
+ # @return [Symbol] The method name that determines if the node is an invalid parent.
52
+ def invalid_parent_method_name
53
+ :"invalid_#{node_name}_parent?"
54
+ end
55
+ METHODS
56
+ end
57
+
31
58
  # The child nodes of this node.
32
59
  #
33
60
  # @return [Array<Tree::Node>]
34
- attr_accessor :children
61
+ attr_reader :children
35
62
 
36
63
  # Whether or not this node has child nodes.
37
64
  # This may be true even when \{#children} is empty,
@@ -45,6 +72,11 @@ module Sass
45
72
  # @return [Fixnum]
46
73
  attr_accessor :line
47
74
 
75
+ # The source range in the document on which this node appeared.
76
+ #
77
+ # @return [Sass::Source::Range]
78
+ attr_accessor :source_range
79
+
48
80
  # The name of the document on which this node appeared.
49
81
  #
50
82
  # @return [String]
@@ -65,8 +97,7 @@ module Sass
65
97
  # @param options [{Symbol => Object}] The options
66
98
  # @see #options
67
99
  def options=(options)
68
- children.each {|c| c.options = options}
69
- @options = options
100
+ Sass::Tree::Visitors::SetOptions.visit(self, options)
70
101
  end
71
102
 
72
103
  # @private
@@ -127,31 +158,29 @@ module Sass
127
158
 
128
159
  # Computes the CSS corresponding to this static CSS tree.
129
160
  #
130
- # @return [String, nil] The resulting CSS
161
+ # @return [String] The resulting CSS
131
162
  # @see Sass::Tree
132
- def to_s
133
- Sass::Tree::Visitors::ToCss.visit(self)
163
+ def css
164
+ Sass::Tree::Visitors::ToCss.new.visit(self)
134
165
  end
135
166
 
136
- # Converts a static CSS tree (e.g. the output of \{Tree::Visitors::Cssize})
137
- # into another static CSS tree,
138
- # with the given extensions applied to all relevant {RuleNode}s.
167
+ # Computes the CSS corresponding to this static CSS tree, along with
168
+ # the respective source map.
139
169
  #
140
- # @todo Link this to the reference documentation on `@extend`
141
- # when such a thing exists.
170
+ # @return [(String, Sass::Source::Map)] The resulting CSS and the source map
171
+ # @see Sass::Tree
172
+ def css_with_sourcemap
173
+ visitor = Sass::Tree::Visitors::ToCss.new(:build_source_mapping)
174
+ result = visitor.visit(self)
175
+ return result, visitor.source_mapping
176
+ end
177
+
178
+ # Returns a representation of the node for debugging purposes.
142
179
  #
143
- # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
144
- # The extensions to perform on this tree
145
- # @return [Tree::Node] The resulting tree of static CSS nodes.
146
- # @raise [Sass::SyntaxError] Only if there's a programmer error
147
- # and this is not a static CSS tree
148
- def do_extend(extends)
149
- node = dup
150
- node.children = children.map {|c| c.do_extend(extends)}
151
- node
152
- rescue Sass::SyntaxError => e
153
- e.modify_backtrace(:filename => filename, :line => line)
154
- raise e
180
+ # @return [String]
181
+ def inspect
182
+ return self.class.to_s unless has_children
183
+ "(#{self.class} #{children.map {|c| c.inspect}.join(' ')})"
155
184
  end
156
185
 
157
186
  # Iterates through each node in the tree rooted at this node
@@ -159,9 +188,9 @@ module Sass
159
188
  #
160
189
  # @yield node
161
190
  # @yieldparam node [Node] a node in the tree
162
- def each(&block)
191
+ def each
163
192
  yield self
164
- children.each {|c| c.each(&block)}
193
+ children.each {|c| c.each {|n| yield n}}
165
194
  end
166
195
 
167
196
  # Converts a node to Sass code that will generate it.
@@ -185,9 +214,14 @@ module Sass
185
214
  #
186
215
  # @return [Node]
187
216
  def deep_copy
188
- node = dup
189
- node.children = children.map {|c| c.deep_copy}
190
- node
217
+ Sass::Tree::Visitors::DeepCopy.visit(self)
218
+ end
219
+
220
+ # Whether or not this node bubbles up through RuleNodes.
221
+ #
222
+ # @return [Boolean]
223
+ def bubbles?
224
+ false
191
225
  end
192
226
 
193
227
  protected
@@ -1,14 +1,14 @@
1
1
  module Sass::Tree
2
- # A static node reprenting a CSS property.
2
+ # A static node representing a CSS property.
3
3
  #
4
4
  # @see Sass::Tree
5
5
  class PropNode < Node
6
6
  # The name of the property,
7
- # interspersed with {Sass::Script::Node}s
7
+ # interspersed with {Sass::Script::Tree::Node}s
8
8
  # representing `#{}`-interpolation.
9
9
  # Any adjacent strings will be merged together.
10
10
  #
11
- # @return [Array<String, Sass::Script::Node>]
11
+ # @return [Array<String, Sass::Script::Tree::Node>]
12
12
  attr_accessor :name
13
13
 
14
14
  # The name of the property
@@ -20,14 +20,9 @@ module Sass::Tree
20
20
 
21
21
  # The value of the property.
22
22
  #
23
- # @return [Sass::Script::Node]
23
+ # @return [Sass::Script::Tree::Node]
24
24
  attr_accessor :value
25
25
 
26
- # Whether the property was marked as !important.
27
- #
28
- # @return [Boolean]
29
- attr_accessor :important
30
-
31
26
  # The value of the property
32
27
  # after any interpolated SassScript has been resolved.
33
28
  # Only set once \{Tree::Visitors::Perform} has been run.
@@ -47,18 +42,26 @@ module Sass::Tree
47
42
  # @return [Fixnum]
48
43
  attr_accessor :tabs
49
44
 
50
- # @param name [Array<String, Sass::Script::Node>] See \{#name}
51
- # @param value [Sass::Script::Node] See \{#value}
52
- # @param important [Boolean] whether this is an !important property
45
+ # The source range in which the property name appears.
46
+ #
47
+ # @return [Sass::Source::Range]
48
+ attr_accessor :name_source_range
49
+
50
+ # The source range in which the property value appears.
51
+ #
52
+ # @return [Sass::Source::Range]
53
+ attr_accessor :value_source_range
54
+
55
+ # @param name [Array<String, Sass::Script::Tree::Node>] See \{#name}
56
+ # @param value [Sass::Script::Tree::Node] See \{#value}
53
57
  # @param prop_syntax [Symbol] `:new` if this property uses `a: b`-style syntax,
54
58
  # `:old` if it uses `:a b`-style syntax
55
- def initialize(name, value, important, prop_syntax)
59
+ def initialize(name, value, prop_syntax)
56
60
  @name = Sass::Util.strip_string_array(
57
61
  Sass::Util.merge_adjacent_strings(name))
58
62
  @value = value
59
63
  @tabs = 0
60
64
  @prop_syntax = prop_syntax
61
- @important = important
62
65
  super()
63
66
  end
64
67
 
@@ -77,7 +80,13 @@ module Sass::Tree
77
80
  #
78
81
  # @return [String] The message
79
82
  def pseudo_class_selector_message
80
- return "" if @prop_syntax == :new || !value.is_a?(Sass::Script::String) || !value.value.empty?
83
+ if @prop_syntax == :new ||
84
+ !value.is_a?(Sass::Script::Tree::Literal) ||
85
+ !value.value.is_a?(Sass::Script::Value::String) ||
86
+ !value.value.value.empty?
87
+ return ""
88
+ end
89
+
81
90
  "\nIf #{declaration.dump} should be a selector, use \"\\#{declaration}\" instead."
82
91
  end
83
92
 
@@ -90,13 +99,21 @@ module Sass::Tree
90
99
  def declaration(opts = {:old => @prop_syntax == :old}, fmt = :sass)
91
100
  name = self.name.map {|n| n.is_a?(String) ? n : "\#{#{n.to_sass(opts)}}"}.join
92
101
  if name[0] == ?:
93
- raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\" hack is not allowed in the Sass indented syntax")
102
+ raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\"" +
103
+ " hack is not allowed in the Sass indented syntax")
94
104
  end
95
105
 
96
106
  old = opts[:old] && fmt == :sass
97
107
  initial = old ? ':' : ''
98
108
  mid = old ? '' : ':'
99
- "#{initial}#{name}#{mid} #{self.class.val_to_sass(value, opts)}#{' !important' if important}".rstrip
109
+ "#{initial}#{name}#{mid} #{self.class.val_to_sass(value, opts)}".rstrip
110
+ end
111
+
112
+ # A property node is invisible if its value is empty.
113
+ #
114
+ # @return [Boolean]
115
+ def invisible?
116
+ resolved_value.empty?
100
117
  end
101
118
 
102
119
  private
@@ -104,10 +121,8 @@ module Sass::Tree
104
121
  def check!
105
122
  if @options[:property_syntax] && @options[:property_syntax] != @prop_syntax
106
123
  raise Sass::SyntaxError.new(
107
- "Illegal property syntax: can't use #{@prop_syntax} syntax when :property_syntax => #{@options[:property_syntax].inspect} is set.")
108
- elsif resolved_value.empty?
109
- raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no value)." +
110
- pseudo_class_selector_message)
124
+ "Illegal property syntax: can't use #{@prop_syntax} syntax when " +
125
+ ":property_syntax => #{@options[:property_syntax].inspect} is set.")
111
126
  end
112
127
  end
113
128
 
@@ -120,36 +135,37 @@ module Sass::Tree
120
135
  private
121
136
 
122
137
  def val_to_sass_comma(node, opts)
123
- return node unless node.is_a?(Sass::Script::Operation)
138
+ return node unless node.is_a?(Sass::Script::Tree::Operation)
124
139
  return val_to_sass_concat(node, opts) unless node.operator == :comma
125
140
 
126
- Sass::Script::Operation.new(
141
+ Sass::Script::Tree::Operation.new(
127
142
  val_to_sass_concat(node.operand1, opts),
128
143
  val_to_sass_comma(node.operand2, opts),
129
144
  node.operator)
130
145
  end
131
146
 
132
147
  def val_to_sass_concat(node, opts)
133
- return node unless node.is_a?(Sass::Script::Operation)
148
+ return node unless node.is_a?(Sass::Script::Tree::Operation)
134
149
  return val_to_sass_div(node, opts) unless node.operator == :space
135
150
 
136
- Sass::Script::Operation.new(
151
+ Sass::Script::Tree::Operation.new(
137
152
  val_to_sass_div(node.operand1, opts),
138
153
  val_to_sass_concat(node.operand2, opts),
139
154
  node.operator)
140
155
  end
141
156
 
142
157
  def val_to_sass_div(node, opts)
143
- unless node.is_a?(Sass::Script::Operation) && node.operator == :div &&
144
- node.operand1.is_a?(Sass::Script::Number) &&
145
- node.operand2.is_a?(Sass::Script::Number) &&
146
- (!node.operand1.original || !node.operand2.original)
158
+ unless node.is_a?(Sass::Script::Tree::Operation) && node.operator == :div &&
159
+ node.operand1.is_a?(Sass::Script::Tree::Literal) &&
160
+ node.operand1.value.is_a?(Sass::Script::Value::Number) &&
161
+ node.operand2.is_a?(Sass::Script::Tree::Literal) &&
162
+ node.operand2.value.is_a?(Sass::Script::Value::Number) &&
163
+ (!node.operand1.value.original || !node.operand2.value.original)
147
164
  return node
148
165
  end
149
166
 
150
- Sass::Script::String.new("(#{node.to_sass(opts)})")
167
+ Sass::Script::Value::String.new("(#{node.to_sass(opts)})")
151
168
  end
152
-
153
169
  end
154
170
  end
155
171
  end
@@ -5,10 +5,11 @@ module Sass
5
5
  # @see Sass::Tree
6
6
  class ReturnNode < Node
7
7
  # The expression to return.
8
- # @type [Script::Node]
9
- attr_reader :expr
8
+ #
9
+ # @return [Script::Tree::Node]
10
+ attr_accessor :expr
10
11
 
11
- # @param expr [Script::Node] The expression to return
12
+ # @param expr [Script::Tree::Node] The expression to return
12
13
  def initialize(expr)
13
14
  @expr = expr
14
15
  super()
@@ -13,15 +13,31 @@ module Sass
13
13
  @template = template
14
14
  end
15
15
 
16
- # Runs the dynamic Sass code *and* computes the CSS for the tree.
17
- # @see #to_s
16
+ # Runs the dynamic Sass code and computes the CSS for the tree.
17
+ #
18
+ # @return [String] The compiled CSS.
18
19
  def render
20
+ css_tree.css
21
+ end
22
+
23
+ # Runs the dynamic Sass code and computes the CSS for the tree, along with
24
+ # the sourcemap.
25
+ #
26
+ # @return [(String, Sass::Source::Map)] The compiled CSS, as well as
27
+ # the source map. @see #render
28
+ def render_with_sourcemap
29
+ css_tree.css_with_sourcemap
30
+ end
31
+
32
+ private
33
+
34
+ def css_tree
19
35
  Visitors::CheckNesting.visit(self)
20
36
  result = Visitors::Perform.visit(self)
21
37
  Visitors::CheckNesting.visit(result) # Check again to validate mixins
22
38
  result, extends = Visitors::Cssize.visit(result)
23
- result = result.do_extend(extends) unless extends.empty?
24
- result.to_s
39
+ Visitors::Extend.visit(result, extends)
40
+ result
25
41
  end
26
42
  end
27
43
  end
@@ -1,5 +1,4 @@
1
1
  require 'pathname'
2
- require 'uri'
3
2
 
4
3
  module Sass::Tree
5
4
  # A static node reprenting a CSS rule.
@@ -10,24 +9,24 @@ module Sass::Tree
10
9
  PARENT = '&'
11
10
 
12
11
  # The CSS selector for this rule,
13
- # interspersed with {Sass::Script::Node}s
12
+ # interspersed with {Sass::Script::Tree::Node}s
14
13
  # representing `#{}`-interpolation.
15
14
  # Any adjacent strings will be merged together.
16
15
  #
17
- # @return [Array<String, Sass::Script::Node>]
16
+ # @return [Array<String, Sass::Script::Tree::Node>]
18
17
  attr_accessor :rule
19
18
 
20
- # The CSS selector for this rule,
21
- # without any unresolved interpolation
22
- # but with parent references still intact.
23
- # It's only set once {Tree::Node#perform} has been called.
19
+ # The CSS selector for this rule, without any unresolved
20
+ # interpolation but with parent references still intact. It's only
21
+ # guaranteed to be set once {Tree::Visitors::Perform} has been
22
+ # run, but it may be set before then for optimization reasons.
24
23
  #
25
24
  # @return [Selector::CommaSequence]
26
25
  attr_accessor :parsed_rules
27
26
 
28
- # The CSS selector for this rule,
29
- # without any unresolved interpolation or parent references.
30
- # It's only set once {Tree::Visitors::Cssize} has been run.
27
+ # The CSS selector for this rule, without any unresolved
28
+ # interpolation or parent references. It's only set once
29
+ # {Tree::Visitors::Perform} has been run.
31
30
  #
32
31
  # @return [Selector::CommaSequence]
33
32
  attr_accessor :resolved_rules
@@ -44,17 +43,30 @@ module Sass::Tree
44
43
  # @return [Fixnum]
45
44
  attr_accessor :tabs
46
45
 
46
+ # The entire selector source range for this rule.
47
+ # @return [Sass::Source::Range]
48
+ attr_accessor :selector_source_range
49
+
47
50
  # Whether or not this rule is the last rule in a nested group.
48
51
  # This is only set in a CSS tree.
49
52
  #
50
53
  # @return [Boolean]
51
54
  attr_accessor :group_end
52
55
 
53
- # @param rule [Array<String, Sass::Script::Node>]
56
+ # The stack trace.
57
+ # This is only readable in a CSS tree as it is written during the perform step
58
+ # and only when the :trace_selectors option is set.
59
+ #
60
+ # @return [String]
61
+ attr_accessor :stack_trace
62
+
63
+ # @param rule [Array<String, Sass::Script::Tree::Node>]
64
+ # @param selector_source_range [Sass::Source::Range]
54
65
  # The CSS rule. See \{#rule}
55
- def initialize(rule)
66
+ def initialize(rule, selector_source_range = nil)
56
67
  merged = Sass::Util.merge_adjacent_strings(rule)
57
68
  @rule = Sass::Util.strip_string_array(merged)
69
+ @selector_source_range = selector_source_range
58
70
  @tabs = 0
59
71
  try_to_parse_non_interpolated_rules
60
72
  super()
@@ -96,23 +108,20 @@ module Sass::Tree
96
108
  last.is_a?(String) && last[-1] == ?,
97
109
  end
98
110
 
99
- # Extends this Rule's selector with the given `extends`.
100
- #
101
- # @see Node#do_extend
102
- def do_extend(extends)
103
- node = dup
104
- node.resolved_rules = resolved_rules.do_extend(extends)
105
- node
106
- end
107
-
108
111
  # A hash that will be associated with this rule in the CSS document
109
112
  # if the {file:SASS_REFERENCE.md#debug_info-option `:debug_info` option} is enabled.
110
- # This data is used by e.g. [the FireSass Firebug extension](https://addons.mozilla.org/en-US/firefox/addon/103988).
113
+ # This data is used by e.g. [the FireSass Firebug
114
+ # extension](https://addons.mozilla.org/en-US/firefox/addon/103988).
111
115
  #
112
116
  # @return [{#to_s => #to_s}]
113
117
  def debug_info
114
- {:filename => filename && ("file://" + URI.escape(File.expand_path(filename))),
115
- :line => self.line}
118
+ {:filename => filename && ("file://" + Sass::Util.escape_uri(File.expand_path(filename))),
119
+ :line => line}
120
+ end
121
+
122
+ # A rule node is invisible if it has only placeholder selectors.
123
+ def invisible?
124
+ resolved_rules.members.all? {|seq| seq.has_placeholder?}
116
125
  end
117
126
 
118
127
  private
@@ -121,8 +130,10 @@ module Sass::Tree
121
130
  if @rule.all? {|t| t.kind_of?(String)}
122
131
  # We don't use real filename/line info because we don't have it yet.
123
132
  # When we get it, we'll set it on the parsed rules if possible.
124
- parser = Sass::SCSS::StaticParser.new(@rule.join.strip, 1)
125
- @parsed_rules = parser.parse_selector('') rescue nil
133
+ parser = Sass::SCSS::StaticParser.new(@rule.join.strip, '', nil, 1)
134
+ # rubocop:disable RescueModifier
135
+ @parsed_rules = parser.parse_selector rescue nil
136
+ # rubocop:enable RescueModifier
126
137
  end
127
138
  end
128
139
  end
@@ -0,0 +1,38 @@
1
+ module Sass::Tree
2
+ # A static node representing a `@supports` rule.
3
+ #
4
+ # @see Sass::Tree
5
+ class SupportsNode < DirectiveNode
6
+ # The name, which may include a browser prefix.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :name
10
+
11
+ # The supports condition.
12
+ #
13
+ # @return [Sass::Supports::Condition]
14
+ attr_accessor :condition
15
+
16
+ # @param condition [Sass::Supports::Condition] See \{#condition}
17
+ def initialize(name, condition)
18
+ @name = name
19
+ @condition = condition
20
+ super('')
21
+ end
22
+
23
+ # @see DirectiveNode#value
24
+ def value; raise NotImplementedError; end
25
+
26
+ # @see DirectiveNode#resolved_value
27
+ def resolved_value
28
+ @resolved_value ||= "@#{name} #{condition.to_css}"
29
+ end
30
+
31
+ # True when the directive has no visible children.
32
+ #
33
+ # @return [Boolean]
34
+ def invisible?
35
+ children.all? {|c| c.invisible?}
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
1
+ require 'sass/tree/node'
2
+
3
+ module Sass::Tree
4
+ # A solely static node left over after a mixin include or @content has been performed.
5
+ # Its sole purpose is to wrap exceptions to add to the backtrace.
6
+ #
7
+ # @see Sass::Tree
8
+ class TraceNode < Node
9
+ # The name of the trace entry to add.
10
+ #
11
+ # @return [String]
12
+ attr_reader :name
13
+
14
+ # @param name [String] The name of the trace entry to add.
15
+ def initialize(name)
16
+ @name = name
17
+ self.has_children = true
18
+ super()
19
+ end
20
+
21
+ # Initializes this node from an existing node.
22
+ # @param name [String] The name of the trace entry to add.
23
+ # @param node [Node] The node to copy information from.
24
+ # @return [TraceNode]
25
+ def self.from_node(name, node)
26
+ trace = new(name)
27
+ trace.line = node.line
28
+ trace.filename = node.filename
29
+ trace.options = node.options
30
+ trace
31
+ end
32
+ end
33
+ end
@@ -9,20 +9,26 @@ module Sass
9
9
  attr_reader :name
10
10
 
11
11
  # The parse tree for the variable value.
12
- # @return [Script::Node]
13
- attr_reader :expr
12
+ # @return [Script::Tree::Node]
13
+ attr_accessor :expr
14
14
 
15
15
  # Whether this is a guarded variable assignment (`!default`).
16
16
  # @return [Boolean]
17
17
  attr_reader :guarded
18
18
 
19
+ # Whether this is a global variable assignment (`!global`).
20
+ # @return [Boolean]
21
+ attr_reader :global
22
+
19
23
  # @param name [String] The name of the variable
20
- # @param expr [Script::Node] See \{#expr}
24
+ # @param expr [Script::Tree::Node] See \{#expr}
21
25
  # @param guarded [Boolean] See \{#guarded}
22
- def initialize(name, expr, guarded)
26
+ # @param global [Boolean] See \{#global}
27
+ def initialize(name, expr, guarded, global)
23
28
  @name = name
24
29
  @expr = expr
25
30
  @guarded = guarded
31
+ @global = global
26
32
  super()
27
33
  end
28
34
  end
@@ -32,9 +32,8 @@ module Sass::Tree::Visitors
32
32
  # @param node [Tree::Node] The node to visit.
33
33
  # @return [Object] The return value of the `visit_*` method for this node.
34
34
  def visit(node)
35
- method = "visit_#{node_name node}"
36
- if self.respond_to?(method)
37
- self.send(method, node) {visit_children(node)}
35
+ if respond_to?(node.class.visit_method, true)
36
+ send(node.class.visit_method, node) {visit_children(node)}
38
37
  else
39
38
  visit_children(node)
40
39
  end
@@ -53,15 +52,13 @@ module Sass::Tree::Visitors
53
52
  parent.children.map {|c| visit(c)}
54
53
  end
55
54
 
56
- NODE_NAME_RE = /.*::(.*?)Node$/
57
-
58
55
  # Returns the name of a node as used in the `visit_*` method.
59
56
  #
60
57
  # @param [Tree::Node] node The node.
61
58
  # @return [String] The name.
62
- def node_name(node)
63
- @@node_names ||= {}
64
- @@node_names[node.class.name] ||= node.class.name.gsub(NODE_NAME_RE, '\\1').downcase
59
+ def self.node_name(node)
60
+ Sass::Util.deprecated(self, "Call node.class.node_name instead.")
61
+ node.class.node_name
65
62
  end
66
63
 
67
64
  # `yield`s, then runs the visitor on the `@else` clause if the node has one.