sass 3.1.21 → 3.2.0.alpha.3

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 (180) hide show
  1. data/README.md +5 -4
  2. data/REVISION +1 -1
  3. data/Rakefile +6 -15
  4. data/VERSION +1 -1
  5. data/VERSION_NAME +1 -1
  6. data/lib/sass.rb +0 -1
  7. data/lib/sass/cache_stores/base.rb +1 -3
  8. data/lib/sass/cache_stores/filesystem.rb +0 -3
  9. data/lib/sass/css.rb +49 -145
  10. data/lib/sass/engine.rb +23 -47
  11. data/lib/sass/environment.rb +5 -30
  12. data/lib/sass/exec.rb +7 -30
  13. data/lib/sass/importers/base.rb +1 -2
  14. data/lib/sass/importers/filesystem.rb +13 -18
  15. data/lib/sass/less.rb +1 -1
  16. data/lib/sass/plugin.rb +8 -4
  17. data/lib/sass/plugin/compiler.rb +67 -93
  18. data/lib/sass/plugin/configuration.rb +2 -0
  19. data/lib/sass/plugin/staleness_checker.rb +4 -14
  20. data/lib/sass/repl.rb +3 -2
  21. data/lib/sass/script.rb +1 -0
  22. data/lib/sass/script/color.rb +9 -4
  23. data/lib/sass/script/funcall.rb +3 -16
  24. data/lib/sass/script/functions.rb +55 -98
  25. data/lib/sass/script/interpolation.rb +0 -9
  26. data/lib/sass/script/lexer.rb +4 -2
  27. data/lib/sass/script/list.rb +0 -8
  28. data/lib/sass/script/literal.rb +20 -5
  29. data/lib/sass/script/node.rb +0 -8
  30. data/lib/sass/script/number.rb +11 -35
  31. data/lib/sass/script/operation.rb +0 -16
  32. data/lib/sass/script/parser.rb +5 -12
  33. data/lib/sass/script/string_interpolation.rb +0 -9
  34. data/lib/sass/script/unary_operation.rb +0 -7
  35. data/lib/sass/script/variable.rb +1 -5
  36. data/lib/sass/scss/parser.rb +54 -191
  37. data/lib/sass/scss/rx.rb +3 -15
  38. data/lib/sass/scss/static_parser.rb +3 -3
  39. data/lib/sass/selector.rb +3 -15
  40. data/lib/sass/selector/abstract_sequence.rb +2 -11
  41. data/lib/sass/selector/comma_sequence.rb +3 -8
  42. data/lib/sass/selector/sequence.rb +11 -74
  43. data/lib/sass/selector/simple.rb +1 -7
  44. data/lib/sass/selector/simple_sequence.rb +8 -28
  45. data/lib/sass/shared.rb +5 -3
  46. data/lib/sass/tree/comment_node.rb +12 -25
  47. data/lib/sass/tree/debug_node.rb +1 -1
  48. data/lib/sass/tree/directive_node.rb +0 -5
  49. data/lib/sass/tree/each_node.rb +1 -1
  50. data/lib/sass/tree/extend_node.rb +1 -1
  51. data/lib/sass/tree/for_node.rb +2 -2
  52. data/lib/sass/tree/function_node.rb +1 -1
  53. data/lib/sass/tree/if_node.rb +14 -1
  54. data/lib/sass/tree/media_node.rb +4 -4
  55. data/lib/sass/tree/mixin_def_node.rb +1 -1
  56. data/lib/sass/tree/mixin_node.rb +2 -2
  57. data/lib/sass/tree/node.rb +26 -10
  58. data/lib/sass/tree/return_node.rb +1 -1
  59. data/lib/sass/tree/root_node.rb +1 -1
  60. data/lib/sass/tree/rule_node.rb +11 -9
  61. data/lib/sass/tree/variable_node.rb +1 -1
  62. data/lib/sass/tree/visitors/base.rb +1 -1
  63. data/lib/sass/tree/visitors/check_nesting.rb +36 -29
  64. data/lib/sass/tree/visitors/convert.rb +9 -16
  65. data/lib/sass/tree/visitors/cssize.rb +9 -40
  66. data/lib/sass/tree/visitors/perform.rb +23 -79
  67. data/lib/sass/tree/visitors/to_css.rb +21 -23
  68. data/lib/sass/tree/warn_node.rb +1 -1
  69. data/lib/sass/tree/while_node.rb +1 -1
  70. data/lib/sass/util.rb +9 -147
  71. data/lib/sass/version.rb +0 -14
  72. data/test/sass/cache_test.rb +0 -15
  73. data/test/sass/conversion_test.rb +8 -50
  74. data/test/sass/css2sass_test.rb +0 -33
  75. data/test/sass/engine_test.rb +32 -283
  76. data/test/sass/extend_test.rb +0 -315
  77. data/test/sass/functions_test.rb +23 -60
  78. data/test/sass/importer_test.rb +0 -110
  79. data/test/sass/more_results/more_import.css +2 -2
  80. data/test/sass/plugin_test.rb +13 -40
  81. data/test/sass/results/import.css +2 -2
  82. data/test/sass/results/import_charset.css +0 -1
  83. data/test/sass/results/import_charset_1_8.css +0 -1
  84. data/test/sass/results/import_charset_ibm866.css +0 -1
  85. data/test/sass/results/scss_import.css +2 -2
  86. data/test/sass/results/units.css +1 -1
  87. data/test/sass/script_conversion_test.rb +0 -2
  88. data/test/sass/script_test.rb +4 -28
  89. data/test/sass/scss/css_test.rb +1 -79
  90. data/test/sass/scss/scss_test.rb +16 -96
  91. data/test/sass/templates/import_charset.sass +0 -2
  92. data/test/sass/templates/import_charset_1_8.sass +0 -2
  93. data/test/sass/templates/import_charset_ibm866.sass +0 -2
  94. data/test/sass/test_helper.rb +1 -1
  95. data/test/sass/util_test.rb +0 -28
  96. data/test/test_helper.rb +0 -2
  97. data/vendor/{listen → fssm}/LICENSE +1 -1
  98. data/vendor/fssm/README.markdown +55 -0
  99. data/vendor/fssm/Rakefile +59 -0
  100. data/vendor/fssm/VERSION.yml +5 -0
  101. data/vendor/fssm/example.rb +9 -0
  102. data/vendor/fssm/fssm.gemspec +77 -0
  103. data/vendor/fssm/lib/fssm.rb +33 -0
  104. data/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  105. data/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  106. data/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  107. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  108. data/vendor/fssm/lib/fssm/monitor.rb +26 -0
  109. data/vendor/fssm/lib/fssm/path.rb +91 -0
  110. data/vendor/fssm/lib/fssm/pathname.rb +502 -0
  111. data/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  112. data/vendor/fssm/lib/fssm/state/file.rb +24 -0
  113. data/vendor/fssm/lib/fssm/support.rb +63 -0
  114. data/vendor/fssm/lib/fssm/tree.rb +176 -0
  115. data/vendor/fssm/profile/prof-cache.rb +40 -0
  116. data/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  117. data/vendor/fssm/profile/prof-pathname.rb +68 -0
  118. data/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  119. data/vendor/fssm/profile/prof.html +2379 -0
  120. data/vendor/fssm/spec/path_spec.rb +75 -0
  121. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  122. data/vendor/fssm/spec/root/file.css +0 -0
  123. data/vendor/fssm/spec/root/file.rb +0 -0
  124. data/vendor/fssm/spec/root/file.yml +0 -0
  125. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  126. data/vendor/fssm/spec/spec_helper.rb +14 -0
  127. metadata +246 -281
  128. data/VERSION_DATE +0 -1
  129. data/lib/sass/logger.rb +0 -15
  130. data/lib/sass/logger/base.rb +0 -32
  131. data/lib/sass/logger/log_level.rb +0 -49
  132. data/lib/sass/tree/visitors/deep_copy.rb +0 -87
  133. data/lib/sass/tree/visitors/extend.rb +0 -42
  134. data/lib/sass/tree/visitors/set_options.rb +0 -97
  135. data/lib/sass/util/multibyte_string_scanner.rb +0 -134
  136. data/test/Gemfile +0 -4
  137. data/test/Gemfile.lock +0 -19
  138. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  139. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  140. data/test/sass/logger_test.rb +0 -58
  141. data/test/sass/templates/_double_import_loop2.sass +0 -1
  142. data/test/sass/templates/bork5.sass +0 -3
  143. data/test/sass/templates/double_import_loop1.sass +0 -1
  144. data/test/sass/templates/nested_bork5.sass +0 -2
  145. data/test/sass/templates/single_import_loop.sass +0 -1
  146. data/test/sass/util/multibyte_string_scanner_test.rb +0 -147
  147. data/vendor/listen/CHANGELOG.md +0 -147
  148. data/vendor/listen/Gemfile +0 -23
  149. data/vendor/listen/Guardfile +0 -8
  150. data/vendor/listen/README.md +0 -312
  151. data/vendor/listen/Rakefile +0 -47
  152. data/vendor/listen/Vagrantfile +0 -96
  153. data/vendor/listen/lib/listen.rb +0 -38
  154. data/vendor/listen/lib/listen/adapter.rb +0 -167
  155. data/vendor/listen/lib/listen/adapters/darwin.rb +0 -84
  156. data/vendor/listen/lib/listen/adapters/linux.rb +0 -110
  157. data/vendor/listen/lib/listen/adapters/polling.rb +0 -66
  158. data/vendor/listen/lib/listen/adapters/windows.rb +0 -81
  159. data/vendor/listen/lib/listen/directory_record.rb +0 -318
  160. data/vendor/listen/lib/listen/listener.rb +0 -203
  161. data/vendor/listen/lib/listen/multi_listener.rb +0 -121
  162. data/vendor/listen/lib/listen/turnstile.rb +0 -28
  163. data/vendor/listen/lib/listen/version.rb +0 -3
  164. data/vendor/listen/listen.gemspec +0 -26
  165. data/vendor/listen/spec/listen/adapter_spec.rb +0 -142
  166. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -31
  167. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -41
  168. data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
  169. data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -24
  170. data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1138
  171. data/vendor/listen/spec/listen/listener_spec.rb +0 -155
  172. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -156
  173. data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
  174. data/vendor/listen/spec/listen_spec.rb +0 -73
  175. data/vendor/listen/spec/spec_helper.rb +0 -18
  176. data/vendor/listen/spec/support/adapter_helper.rb +0 -716
  177. data/vendor/listen/spec/support/directory_record_helper.rb +0 -55
  178. data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
  179. data/vendor/listen/spec/support/listeners_helper.rb +0 -144
  180. data/vendor/listen/spec/support/platform_helper.rb +0 -11
@@ -12,13 +12,12 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
12
12
  attr_reader :parent
13
13
 
14
14
  def initialize
15
- @parent_directives = []
16
15
  @extends = Sass::Util::SubsetMap.new
17
16
  end
18
17
 
19
18
  # If an exception is raised, this adds proper metadata to the backtrace.
20
19
  def visit(node)
21
- super(node)
20
+ super(node.dup)
22
21
  rescue Sass::SyntaxError => e
23
22
  e.modify_backtrace(:filename => node.filename, :line => node.line)
24
23
  raise e
@@ -39,11 +38,9 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
39
38
  # @yield A block in which the parent is set to `parent`.
40
39
  # @return [Object] The return value of the block.
41
40
  def with_parent(parent)
42
- @parent_directives.push parent if parent.is_a?(Sass::Tree::DirectiveNode)
43
41
  old_parent, @parent = @parent, parent
44
42
  yield
45
43
  ensure
46
- @parent_directives.pop if parent.is_a?(Sass::Tree::DirectiveNode)
47
44
  @parent = old_parent
48
45
  end
49
46
 
@@ -55,26 +52,12 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
55
52
  def visit_root(node)
56
53
  yield
57
54
 
58
- if parent.nil?
59
- # In Ruby 1.9 we can make all @charset nodes invisible
60
- # and infer the final @charset from the encoding of the final string.
61
- if Sass::Util.ruby1_8?
62
- charset = node.children.find {|c| c.is_a?(Sass::Tree::CharsetNode)}
63
- node.children.reject! {|c| c.is_a?(Sass::Tree::CharsetNode)}
64
- node.children.unshift charset if charset
65
- end
66
-
67
- imports = Sass::Util.extract!(node.children) do |c|
68
- c.is_a?(Sass::Tree::DirectiveNode) && c.value =~ /^@import /i
69
- end
70
- charset_and_index = Sass::Util.ruby1_8? &&
71
- node.children.each_with_index.find {|c, _| c.is_a?(Sass::Tree::CharsetNode)}
72
- if charset_and_index
73
- index = charset_and_index.last
74
- node.children = node.children[0..index] + imports + node.children[index+1..-1]
75
- else
76
- node.children = imports + node.children
77
- end
55
+ # In Ruby 1.9 we can make all @charset nodes invisible
56
+ # and infer the final @charset from the encoding of the final string.
57
+ if Sass::Util.ruby1_8? && parent.nil?
58
+ charset = node.children.find {|c| c.is_a?(Sass::Tree::CharsetNode)}
59
+ node.children.reject! {|c| c.is_a?(Sass::Tree::CharsetNode)}
60
+ node.children.unshift charset if charset
78
61
  end
79
62
 
80
63
  return node, @extends
@@ -83,18 +66,6 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
83
66
  raise e
84
67
  end
85
68
 
86
- # A simple struct wrapping up information about a single `@extend` instance. A
87
- # single [ExtendNode] can have multiple Extends if either the parent node or
88
- # the extended selector is a comma sequence.
89
- #
90
- # @attr extender [Array<Sass::Selector::SimpleSequence, String>]
91
- # The selector of the CSS rule containing the `@extend`.
92
- # @attr target [Array<Sass::Selector::Simple>] The selector being `@extend`ed.
93
- # @attr node [Sass::Tree::ExtendNode] The node that produced this extend.
94
- # @attr directives [Array<Sass::Tree::DirectiveNode>]
95
- # The directives containing the `@extend`.
96
- Extend = Struct.new(:extender, :target, :node, :directives)
97
-
98
69
  # Registers an extension in the `@extends` subset map.
99
70
  def visit_extend(node)
100
71
  node.resolved_selector.members.each do |seq|
@@ -113,7 +84,7 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
113
84
  raise Sass::SyntaxError.new("#{seq} can't extend: invalid selector")
114
85
  end
115
86
 
116
- @extends[sel] = Extend.new(seq, sel, node, @parent_directives.dup)
87
+ @extends[sel] = seq
117
88
  end
118
89
  end
119
90
 
@@ -146,9 +117,7 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
146
117
 
147
118
  media = node.children.select {|c| c.is_a?(Sass::Tree::MediaNode)}
148
119
  node.children.reject! {|c| c.is_a?(Sass::Tree::MediaNode)}
149
- media.each do |n|
150
- n.query = node.query.map {|pq| n.query.map {|cq| "#{pq} and #{cq}"}}.flatten
151
- end
120
+ media.each {|n| n.query = "#{node.query} and #{n.query}"}
152
121
  (node.children.empty? ? [] : [node]) + media
153
122
  end
154
123
 
@@ -53,10 +53,12 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
53
53
  # Removes this node from the tree if it's a silent comment.
54
54
  def visit_comment(node)
55
55
  return [] if node.invisible?
56
- check_for_loud_silent_comment node
57
- check_for_comment_interp node
58
- node.resolved_value = run_interp_no_strip(node.value)
59
- node.resolved_value.gsub!(/\\([\\#])/, '\1')
56
+ if node.evaluated?
57
+ node.value.gsub!(/(^|[^\\])\#\{([^}]*)\}/) do |md|
58
+ $1+Sass::Script.parse($2, node.line, 0, node.options).perform(@environment).to_s
59
+ end
60
+ node.value = run_interp([Sass::Script::String.new(node.value)])
61
+ end
60
62
  node
61
63
  end
62
64
 
@@ -87,8 +89,8 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
87
89
  # Runs SassScript interpolation in the selector,
88
90
  # and then parses the result into a {Sass::Selector::CommaSequence}.
89
91
  def visit_extend(node)
90
- parser = Sass::SCSS::CssParser.new(run_interp(node.selector), node.filename, node.line)
91
- node.resolved_selector = parser.parse_selector
92
+ parser = Sass::SCSS::CssParser.new(run_interp(node.selector), node.line)
93
+ node.resolved_selector = parser.parse_selector(node.filename)
92
94
  node
93
95
  end
94
96
 
@@ -137,12 +139,9 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
137
139
  if path = node.css_import?
138
140
  return Sass::Tree::DirectiveNode.new("@import url(#{path})")
139
141
  end
140
- file = node.imported_file
141
- handle_import_loop!(node) if @environment.files_in_use.include?(file.options[:filename])
142
142
 
143
143
  @environment.push_frame(:filename => node.filename, :line => node.line)
144
- root = file.to_tree
145
- Sass::Tree::Visitors::CheckNesting.visit(root)
144
+ root = node.imported_file.to_tree
146
145
  node.children = root.children.map {|c| visit(c)}.flatten
147
146
  node
148
147
  rescue Sass::SyntaxError => e
@@ -226,15 +225,8 @@ END
226
225
  # Runs SassScript interpolation in the selector,
227
226
  # and then parses the result into a {Sass::Selector::CommaSequence}.
228
227
  def visit_rule(node)
229
- rule = node.rule
230
- rule = rule.map {|e| e.is_a?(String) && e != ' ' ? e.strip : e} if node.style == :compressed
231
- parser = Sass::SCSS::StaticParser.new(run_interp(node.rule), node.filename, node.line)
232
- node.parsed_rules ||= parser.parse_selector
233
- if node.options[:trace_selectors]
234
- @environment.push_frame(:filename => node.filename, :line => node.line)
235
- node.stack_trace = @environment.stack_trace
236
- @environment.pop_frame
237
- end
228
+ parser = Sass::SCSS::StaticParser.new(run_interp(node.rule), node.line)
229
+ node.parsed_rules ||= parser.parse_selector(node.filename)
238
230
  yield
239
231
  end
240
232
 
@@ -251,10 +243,13 @@ END
251
243
  @environment.push_frame(:filename => node.filename, :line => node.line)
252
244
  res = node.expr.perform(@environment)
253
245
  res = res.value if res.is_a?(Sass::Script::String)
254
- msg = "WARNING: #{res}\n "
255
- msg << @environment.stack_trace.join("\n ")
256
- # JRuby doesn't automatically add a newline for #warn
257
- msg << (RUBY_PLATFORM =~ /java/ ? "\n\n" : "\n")
246
+ msg = "WARNING: #{res}\n"
247
+ @environment.stack.reverse.each_with_index do |entry, i|
248
+ msg << " #{i == 0 ? "on" : "from"} line #{entry[:line]}" <<
249
+ " of #{entry[:filename] || "an unknown file"}"
250
+ msg << ", in `#{entry[:mixin]}'" if entry[:mixin]
251
+ msg << "\n"
252
+ end
258
253
  Sass::Util.sass_warn msg
259
254
  []
260
255
  ensure
@@ -272,15 +267,6 @@ END
272
267
 
273
268
  def visit_directive(node)
274
269
  if node.value['#{']
275
- if node.value =~ /^@import (?!url\()/
276
- Sass::Util.sass_warn <<WARNING
277
- DEPRECATION WARNING on line #{node.line}#{" of #{node.filename}" if node.filename}:
278
- @import directives using \#{} interpolation will need to use url() in Sass 3.2.
279
- For example:
280
-
281
- @import url("http://\#{$url}/style.css");
282
- WARNING
283
- end
284
270
  node.value = run_interp(Sass::Engine.parse_interp(node.value, node.line, 0, node.options))
285
271
  end
286
272
  yield
@@ -289,24 +275,22 @@ WARNING
289
275
 
290
276
  private
291
277
 
292
- def run_interp_no_strip(text)
278
+ def run_interp(text)
293
279
  text.map do |r|
294
280
  next r if r.is_a?(String)
295
281
  val = r.perform(@environment)
296
282
  # Interpolated strings should never render with quotes
297
283
  next val.value if val.is_a?(Sass::Script::String)
298
284
  val.to_s
299
- end.join
300
- end
301
-
302
- def run_interp(text)
303
- run_interp_no_strip(text).strip
285
+ end.join.strip
304
286
  end
305
287
 
306
288
  def handle_include_loop!(node)
307
289
  msg = "An @include loop has been found:"
308
290
  mixins = @environment.stack.map {|s| s[:mixin]}.compact
309
- raise Sass::SyntaxError.new("#{msg} #{node.name} includes itself") if mixins.size == 1
291
+ if mixins.size == 2 && mixins[0] == mixins[1]
292
+ raise Sass::SyntaxError.new("#{msg} #{node.name} includes itself")
293
+ end
310
294
 
311
295
  mixins << node.name
312
296
  msg << "\n" << Sass::Util.enum_cons(mixins, 2).map do |m1, m2|
@@ -314,44 +298,4 @@ WARNING
314
298
  end.join("\n")
315
299
  raise Sass::SyntaxError.new(msg)
316
300
  end
317
-
318
- def handle_import_loop!(node)
319
- msg = "An @import loop has been found:"
320
- files = @environment.stack.map {|s| s[:filename]}.compact
321
- if node.filename == node.imported_file.options[:filename]
322
- raise Sass::SyntaxError.new("#{msg} #{node.filename} imports itself")
323
- end
324
-
325
- files << node.filename << node.imported_file.options[:filename]
326
- msg << "\n" << Sass::Util.enum_cons(files, 2).map do |m1, m2|
327
- " #{m1} imports #{m2}"
328
- end.join("\n")
329
- raise Sass::SyntaxError.new(msg)
330
- end
331
-
332
- def check_for_loud_silent_comment(node)
333
- return unless node.loud && node.silent
334
- Sass::Util.sass_warn <<MESSAGE
335
- WARNING:
336
- On line #{node.line}#{" of '#{node.filename}'" if node.filename}
337
- `//` comments will no longer be allowed to use the `!` flag in Sass 3.2.
338
- Please change to `/*` comments.
339
- MESSAGE
340
- end
341
-
342
- def check_for_comment_interp(node)
343
- return if node.loud
344
- node.value.each do |e|
345
- next unless e.is_a?(String)
346
- e.scan(/(\\*)#\{/) do |esc|
347
- Sass::Util.sass_warn <<MESSAGE if esc.first.size.even?
348
- WARNING:
349
- On line #{node.line}#{" of '#{node.filename}'" if node.filename}
350
- Comments will evaluate the contents of interpolations (\#{ ... }) in Sass 3.2.
351
- Please escape the interpolation by adding a backslash before the `#`.
352
- MESSAGE
353
- return
354
- end
355
- end
356
- end
357
301
  end
@@ -57,24 +57,32 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
57
57
 
58
58
  def visit_comment(node)
59
59
  return if node.invisible?
60
- spaces = (' ' * [@tabs - node.resolved_value[/^ */].size, 0].max)
60
+ spaces = (' ' * [@tabs - node.value[/^ */].size, 0].max)
61
61
 
62
- content = node.resolved_value.gsub(/^/, spaces)
63
- content.gsub!(%r{^(\s*)//(.*)$}) {|md| "#{$1}/*#{$2} */"} if node.silent
62
+ content = node.value.gsub(/^/, spaces).gsub(%r{^(\s*)//(.*)$}) do |md|
63
+ "#{$1}/*#{$2} */"
64
+ end
65
+ if content =~ /[^\\]\#\{.*\}/
66
+ Sass::Util.sass_warn <<MESSAGE
67
+ WARNING:
68
+ On line #{node.line}#{" of '#{node.filename}'" if node.filename}
69
+ Comments will evaluate the contents of interpolations (\#{ ... }) in Sass 3.2.
70
+ Please escape the interpolation by adding a backslash before the hash sign.
71
+ MESSAGE
72
+ elsif content =~ /\\\#\{.*\}/
73
+ content.gsub!(/\\(\#\{.*\})/, '\1')
74
+ end
64
75
  content.gsub!(/\n +(\* *(?!\/))?/, ' ') if (node.style == :compact || node.style == :compressed) && !node.loud
65
76
  content
66
77
  end
67
78
 
68
79
  def visit_directive(node)
69
- was_in_directive = @in_directive
70
- tab_str = ' ' * @tabs
71
- return tab_str + node.value + ";" unless node.has_children
72
- return tab_str + node.value + " {}" if node.children.empty?
73
- @in_directive = @in_directive || !node.is_a?(Sass::Tree::MediaNode)
80
+ return node.value + ";" unless node.has_children
81
+ return node.value + " {}" if node.children.empty?
74
82
  result = if node.style == :compressed
75
83
  "#{node.value}{"
76
84
  else
77
- "#{tab_str}#{node.value} {" + (node.style == :compact ? ' ' : "\n")
85
+ "#{' ' * @tabs}#{node.value} {" + (node.style == :compact ? ' ' : "\n")
78
86
  end
79
87
  was_prop = false
80
88
  first = true
@@ -103,8 +111,6 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
103
111
  else
104
112
  (node.style == :expanded ? "\n" : " ") + "}\n"
105
113
  end
106
- ensure
107
- @in_directive = was_in_directive
108
114
  end
109
115
 
110
116
  def visit_media(node)
@@ -136,11 +142,7 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
136
142
 
137
143
  joined_rules = node.resolved_rules.members.map do |seq|
138
144
  rule_part = seq.to_a.join
139
- if node.style == :compressed
140
- rule_part.gsub!(/([^,])\s*\n\s*/m, '\1 ')
141
- rule_part.gsub!(/\s*([,+>])\s*/m, '\1')
142
- rule_part.strip!
143
- end
145
+ rule_part.gsub!(/\s*([^,])\s*\n\s*/m, '\1 ') if node.style == :compressed
144
146
  rule_part
145
147
  end.join(rule_separator)
146
148
 
@@ -152,12 +154,8 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
152
154
  old_spaces = ' ' * @tabs
153
155
  spaces = ' ' * (@tabs + 1)
154
156
  if node.style != :compressed
155
- if node.options[:debug_info] && !@in_directive
157
+ if node.options[:debug_info]
156
158
  to_return << visit(debug_info_rule(node.debug_info, node.options)) << "\n"
157
- elsif node.options[:trace_selectors]
158
- to_return << "#{old_spaces}/* "
159
- to_return << node.stack_trace.join("\n #{old_spaces}")
160
- to_return << " */\n"
161
159
  elsif node.options[:line_comments]
162
160
  to_return << "#{old_spaces}/* line #{node.line}"
163
161
 
@@ -198,7 +196,7 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
198
196
 
199
197
  def debug_info_rule(debug_info, options)
200
198
  node = Sass::Tree::DirectiveNode.new("@media -sass-debug-info")
201
- Sass::Util.hash_to_a(debug_info.map {|k, v| [k.to_s, v.to_s]}).each do |k, v|
199
+ debug_info.map {|k, v| [k.to_s, v.to_s]}.sort.each do |k, v|
202
200
  rule = Sass::Tree::RuleNode.new([""])
203
201
  rule.resolved_rules = Sass::Selector::CommaSequence.new(
204
202
  [Sass::Selector::Sequence.new(
@@ -206,7 +204,7 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
206
204
  [Sass::Selector::Element.new(k.to_s.gsub(/[^\w-]/, "\\\\\\0"), nil)])
207
205
  ])
208
206
  ])
209
- prop = Sass::Tree::PropNode.new([""], Sass::Script::String.new(''), :new)
207
+ prop = Sass::Tree::PropNode.new([""], "", :new)
210
208
  prop.resolved_name = "font-family"
211
209
  prop.resolved_value = Sass::SCSS::RX.escape_ident(v.to_s)
212
210
  rule << prop
@@ -6,7 +6,7 @@ module Sass
6
6
  class WarnNode < Node
7
7
  # The expression to print.
8
8
  # @return [Script::Node]
9
- attr_accessor :expr
9
+ attr_reader :expr
10
10
 
11
11
  # @param expr [Script::Node] The expression to print
12
12
  def initialize(expr)
@@ -7,7 +7,7 @@ module Sass::Tree
7
7
  class WhileNode < Node
8
8
  # The parse tree for the continuation expression.
9
9
  # @return [Script::Node]
10
- attr_accessor :expr
10
+ attr_reader :expr
11
11
 
12
12
  # @param expr [Script::Node] See \{#expr}
13
13
  def initialize(expr)
@@ -2,6 +2,7 @@ require 'erb'
2
2
  require 'set'
3
3
  require 'enumerator'
4
4
  require 'stringio'
5
+ require 'strscan'
5
6
  require 'rbconfig'
6
7
 
7
8
  require 'sass/root'
@@ -85,9 +86,8 @@ module Sass
85
86
  # @return [Hash] The mapped hash
86
87
  # @see #map_keys
87
88
  # @see #map_vals
88
- def map_hash(hash)
89
- # Using &block here completely hoses performance on 1.8.
90
- to_hash(hash.map {|k, v| yield k, v})
89
+ def map_hash(hash, &block)
90
+ to_hash(hash.map(&block))
91
91
  end
92
92
 
93
93
  # Computes the powerset of the given array.
@@ -219,57 +219,6 @@ module Sass
219
219
  lcs_backtrace(lcs_table(x, y, &block), x, y, x.size-1, y.size-1, &block)
220
220
  end
221
221
 
222
- # Converts a Hash to an Array. This is usually identical to `Hash#to_a`,
223
- # with the following exceptions:
224
- #
225
- # * In Ruby 1.8, `Hash#to_a` is not deterministically ordered, but this is.
226
- # * In Ruby 1.9 when running tests, this is ordered in the same way it would
227
- # be under Ruby 1.8 (sorted key order rather than insertion order).
228
- #
229
- # @param hash [Hash]
230
- # @return [Array]
231
- def hash_to_a(hash)
232
- return hash.to_a unless ruby1_8? || defined?(Test::Unit)
233
- return hash.sort_by {|k, v| k}
234
- end
235
-
236
- # Asserts that `value` falls within `range` (inclusive), leaving
237
- # room for slight floating-point errors.
238
- #
239
- # @param name [String] The name of the value. Used in the error message.
240
- # @param range [Range] The allowed range of values.
241
- # @param value [Numeric, Sass::Script::Number] The value to check.
242
- # @param unit [String] The unit of the value. Used in error reporting.
243
- # @return [Numeric] `value` adjusted to fall within range, if it
244
- # was outside by a floating-point margin.
245
- def check_range(name, range, value, unit='')
246
- grace = (-0.00001..0.00001)
247
- str = value.to_s
248
- value = value.value if value.is_a?(Sass::Script::Number)
249
- return value if range.include?(value)
250
- return range.first if grace.include?(value - range.first)
251
- return range.last if grace.include?(value - range.last)
252
- raise ArgumentError.new(
253
- "#{name} #{str} must be between #{range.first}#{unit} and #{range.last}#{unit}")
254
- end
255
-
256
- # Returns whether or not `seq1` is a subsequence of `seq2`. That is, whether
257
- # or not `seq2` contains every element in `seq1` in the same order (and
258
- # possibly more elements besides).
259
- #
260
- # @param seq1 [Array]
261
- # @param seq2 [Array]
262
- # @return [Boolean]
263
- def subsequence?(seq1, seq2)
264
- i = j = 0
265
- loop do
266
- return true if i == seq1.size
267
- return false if j == seq2.size
268
- i += 1 if seq1[i] == seq2[j]
269
- j += 1
270
- end
271
- end
272
-
273
222
  # Returns information about the caller of the previous method.
274
223
  #
275
224
  # @param entry [String] An entry in the `#caller` list, or a similarly formatted string
@@ -344,17 +293,19 @@ module Sass
344
293
  #
345
294
  # @yield A block in which no Sass warnings will be printed
346
295
  def silence_sass_warnings
347
- old_level, Sass.logger.log_level = Sass.logger.log_level, :error
296
+ old_silence_warnings = @@silence_warnings
297
+ @@silence_warnings = true
348
298
  yield
349
299
  ensure
350
- Sass.logger.log_level = old_level
300
+ @@silence_warnings = old_silence_warnings
351
301
  end
352
302
 
353
303
  # The same as `Kernel#warn`, but is silenced by \{#silence\_sass\_warnings}.
354
304
  #
355
305
  # @param msg [String]
356
306
  def sass_warn(msg)
357
- Sass.logger.warn(msg)
307
+ return if @@silence_warnings
308
+ warn(msg)
358
309
  end
359
310
 
360
311
  ## Cross Rails Version Compatibility
@@ -436,14 +387,6 @@ module Sass
436
387
  RUBY_ENGINE == "ironruby"
437
388
  end
438
389
 
439
- # Like `Dir.glob`, but works with backslash-separated paths on Windows.
440
- #
441
- # @param path [String]
442
- def glob(path, &block)
443
- path = path.gsub('\\', '/') if windows?
444
- Dir.glob(path, &block)
445
- end
446
-
447
390
  ## Cross-Ruby-Version Compatibility
448
391
 
449
392
  # Whether or not this is running under Ruby 1.8 or lower.
@@ -466,13 +409,6 @@ module Sass
466
409
  ruby1_8? && Sass::Util::RUBY_VERSION[2] < 7
467
410
  end
468
411
 
469
- # Whether or not this is running under MacRuby.
470
- #
471
- # @return [Boolean]
472
- def macruby?
473
- RUBY_ENGINE == 'macruby'
474
- end
475
-
476
412
  # Checks that the encoding of a string is valid in Ruby 1.9
477
413
  # and cleans up potential encoding gotchas like the UTF-8 BOM.
478
414
  # If it's not, yields an error string describing the invalid character
@@ -533,8 +469,7 @@ MSG
533
469
  # We allow any printable ASCII characters but double quotes in the charset decl
534
470
  bin = str.dup.force_encoding("BINARY")
535
471
  encoding = Sass::Util::ENCODINGS_TO_CHECK.find do |enc|
536
- re = Sass::Util::CHARSET_REGEXPS[enc]
537
- re && bin =~ re
472
+ bin =~ Sass::Util::CHARSET_REGEXPS[enc]
538
473
  end
539
474
  charset, bom = $1, $2
540
475
  if charset
@@ -575,8 +510,6 @@ MSG
575
510
  Regexp.new(/\A(?:#{_enc("\uFEFF", e)})?#{
576
511
  _enc('@charset "', e)}(.*?)#{_enc('"', e)}|\A(#{
577
512
  _enc("\uFEFF", e)})/)
578
- rescue Encoding::ConverterNotFoundError => _
579
- nil # JRuby on Java 5 doesn't support UTF-32
580
513
  rescue
581
514
  # /\A@charset "(.*?)"/
582
515
  Regexp.new(/\A#{_enc('@charset "', e)}(.*?)#{_enc('"', e)}/)
@@ -628,24 +561,6 @@ MSG
628
561
  ruby1_8? ? enum.enum_slice(n) : enum.each_slice(n)
629
562
  end
630
563
 
631
- # Destructively removes all elements from an array that match a block, and
632
- # returns the removed elements.
633
- #
634
- # @param array [Array] The array from which to remove elements.
635
- # @yield [el] Called for each element.
636
- # @yieldparam el [*] The element to test.
637
- # @yieldreturn [Boolean] Whether or not to extract the element.
638
- # @return [Array] The extracted elements.
639
- def extract!(array)
640
- out = []
641
- array.reject! do |e|
642
- next false unless yield e
643
- out << e
644
- true
645
- end
646
- out
647
- end
648
-
649
564
  # Returns the ASCII code of the given character.
650
565
  #
651
566
  # @param c [String] All characters but the first are ignored.
@@ -699,57 +614,6 @@ MSG
699
614
  '"' + obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]} + '"'
700
615
  end
701
616
 
702
- # Extracts the non-string vlaues from an array containing both strings and non-strings.
703
- # These values are replaced with escape sequences.
704
- # This can be undone using \{#inject\_values}.
705
- #
706
- # This is useful e.g. when we want to do string manipulation
707
- # on an interpolated string.
708
- #
709
- # The precise format of the resulting string is not guaranteed.
710
- # However, it is guaranteed that newlines and whitespace won't be affected.
711
- #
712
- # @param arr [Array] The array from which values are extracted.
713
- # @return [(String, Array)] The resulting string, and an array of extracted values.
714
- def extract_values(arr)
715
- values = []
716
- return arr.map do |e|
717
- next e.gsub('{', '{{') if e.is_a?(String)
718
- values << e
719
- next "{#{values.count - 1}}"
720
- end.join, values
721
- end
722
-
723
- # Undoes \{#extract\_values} by transforming a string with escape sequences
724
- # into an array of strings and non-string values.
725
- #
726
- # @param str [String] The string with escape sequences.
727
- # @param values [Array] The array of values to inject.
728
- # @return [Array] The array of strings and values.
729
- def inject_values(str, values)
730
- return [str.gsub('{{', '{')] if values.empty?
731
- # Add an extra { so that we process the tail end of the string
732
- result = (str + '{{').scan(/(.*?)(?:(\{\{)|\{(\d+)\})/m).map do |(pre, esc, n)|
733
- [pre, esc ? '{' : '', n ? values[n.to_i] : '']
734
- end.flatten(1)
735
- result[-2] = '' # Get rid of the extra {
736
- merge_adjacent_strings(result).reject {|s| s == ''}
737
- end
738
-
739
- # Allows modifications to be performed on the string form
740
- # of an array containing both strings and non-strings.
741
- #
742
- # @param arr [Array] The array from which values are extracted.
743
- # @yield [str] A block in which string manipulation can be done to the array.
744
- # @yieldparam str [String] The string form of `arr`.
745
- # @yieldreturn [String] The modified string.
746
- # @return [Array] The modified, interpolated array.
747
- def with_extracted_values(arr)
748
- str, vals = extract_values(arr)
749
- str = yield str
750
- inject_values(str, vals)
751
- end
752
-
753
617
  ## Static Method Stuff
754
618
 
755
619
  # The context in which the ERB for \{#def\_static\_method} will be run.
@@ -803,5 +667,3 @@ MSG
803
667
  end
804
668
  end
805
669
  end
806
-
807
- require 'sass/util/multibyte_string_scanner'