sass 3.1.21 → 3.2.0.alpha.3

Sign up to get free protection for your applications and to get access to all the features.
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'