haml 3.1.3 → 3.1.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of haml might be problematic. Click here for more details.

Files changed (134) hide show
  1. data/Rakefile +42 -17
  2. data/VERSION +1 -1
  3. data/lib/haml/compiler.rb +3 -3
  4. data/lib/haml/helpers/action_view_mods.rb +4 -3
  5. data/lib/haml/template.rb +3 -1
  6. data/test/gemfiles/Gemfile.rails-2.0.x +8 -0
  7. data/test/gemfiles/Gemfile.rails-2.0.x.lock +38 -0
  8. data/test/gemfiles/Gemfile.rails-2.1.x +8 -0
  9. data/test/gemfiles/Gemfile.rails-2.1.x.lock +38 -0
  10. data/test/gemfiles/Gemfile.rails-2.2.x +8 -0
  11. data/test/gemfiles/Gemfile.rails-2.2.x.lock +38 -0
  12. data/test/gemfiles/Gemfile.rails-2.3.x +8 -0
  13. data/test/gemfiles/Gemfile.rails-2.3.x.lock +40 -0
  14. data/test/gemfiles/Gemfile.rails-3.0.x +8 -0
  15. data/test/gemfiles/Gemfile.rails-3.0.x.lock +85 -0
  16. data/test/gemfiles/Gemfile.rails-3.1.x +8 -0
  17. data/test/gemfiles/Gemfile.rails-3.1.x.lock +98 -0
  18. data/test/gemfiles/Gemfile.rails-xss-2.3.x +9 -0
  19. data/test/gemfiles/Gemfile.rails-xss-2.3.x.lock +42 -0
  20. data/test/haml/engine_test.rb +19 -0
  21. data/test/haml/html2haml_test.rb +1 -1
  22. data/test/haml/template_test.rb +20 -2
  23. data/test/haml/templates/partial_layout.haml +4 -1
  24. data/test/linked_rails.rb +4 -4
  25. data/vendor/sass/VERSION +1 -1
  26. data/vendor/sass/doc-src/SASS_CHANGELOG.md +115 -2
  27. data/vendor/sass/doc-src/SASS_REFERENCE.md +12 -4
  28. data/vendor/sass/lib/sass.rb +1 -0
  29. data/vendor/sass/lib/sass/cache_stores/base.rb +3 -1
  30. data/vendor/sass/lib/sass/cache_stores/filesystem.rb +2 -0
  31. data/vendor/sass/lib/sass/css.rb +2 -1
  32. data/vendor/sass/lib/sass/engine.rb +39 -23
  33. data/vendor/sass/lib/sass/environment.rb +11 -0
  34. data/vendor/sass/lib/sass/exec.rb +14 -1
  35. data/vendor/sass/lib/sass/importers/base.rb +2 -1
  36. data/vendor/sass/lib/sass/importers/filesystem.rb +18 -13
  37. data/vendor/sass/lib/sass/less.rb +2 -2
  38. data/vendor/sass/lib/sass/logger.rb +15 -0
  39. data/vendor/sass/lib/sass/logger/base.rb +32 -0
  40. data/vendor/sass/lib/sass/logger/log_level.rb +49 -0
  41. data/vendor/sass/lib/sass/plugin.rb +4 -8
  42. data/vendor/sass/lib/sass/plugin/compiler.rb +42 -17
  43. data/vendor/sass/lib/sass/plugin/configuration.rb +0 -2
  44. data/vendor/sass/lib/sass/railtie.rb +1 -1
  45. data/vendor/sass/lib/sass/script/funcall.rb +14 -1
  46. data/vendor/sass/lib/sass/script/functions.rb +44 -1
  47. data/vendor/sass/lib/sass/script/interpolation.rb +9 -0
  48. data/vendor/sass/lib/sass/script/lexer.rb +6 -1
  49. data/vendor/sass/lib/sass/script/list.rb +7 -0
  50. data/vendor/sass/lib/sass/script/literal.rb +5 -0
  51. data/vendor/sass/lib/sass/script/node.rb +8 -0
  52. data/vendor/sass/lib/sass/script/number.rb +28 -5
  53. data/vendor/sass/lib/sass/script/operation.rb +8 -0
  54. data/vendor/sass/lib/sass/script/parser.rb +12 -5
  55. data/vendor/sass/lib/sass/script/string_interpolation.rb +9 -0
  56. data/vendor/sass/lib/sass/script/unary_operation.rb +7 -0
  57. data/vendor/sass/lib/sass/script/variable.rb +5 -0
  58. data/vendor/sass/lib/sass/scss/parser.rb +78 -38
  59. data/vendor/sass/lib/sass/scss/rx.rb +2 -1
  60. data/vendor/sass/lib/sass/scss/static_parser.rb +2 -2
  61. data/vendor/sass/lib/sass/shared.rb +1 -1
  62. data/vendor/sass/lib/sass/tree/comment_node.rb +24 -11
  63. data/vendor/sass/lib/sass/tree/debug_node.rb +1 -1
  64. data/vendor/sass/lib/sass/tree/each_node.rb +1 -1
  65. data/vendor/sass/lib/sass/tree/extend_node.rb +1 -1
  66. data/vendor/sass/lib/sass/tree/for_node.rb +2 -2
  67. data/vendor/sass/lib/sass/tree/function_node.rb +1 -1
  68. data/vendor/sass/lib/sass/tree/if_node.rb +1 -14
  69. data/vendor/sass/lib/sass/tree/mixin_def_node.rb +1 -1
  70. data/vendor/sass/lib/sass/tree/mixin_node.rb +2 -2
  71. data/vendor/sass/lib/sass/tree/node.rb +2 -5
  72. data/vendor/sass/lib/sass/tree/prop_node.rb +2 -9
  73. data/vendor/sass/lib/sass/tree/return_node.rb +1 -1
  74. data/vendor/sass/lib/sass/tree/rule_node.rb +9 -2
  75. data/vendor/sass/lib/sass/tree/variable_node.rb +1 -1
  76. data/vendor/sass/lib/sass/tree/visitors/check_nesting.rb +17 -18
  77. data/vendor/sass/lib/sass/tree/visitors/convert.rb +10 -5
  78. data/vendor/sass/lib/sass/tree/visitors/deep_copy.rb +87 -0
  79. data/vendor/sass/lib/sass/tree/visitors/perform.rb +50 -19
  80. data/vendor/sass/lib/sass/tree/visitors/set_options.rb +97 -0
  81. data/vendor/sass/lib/sass/tree/visitors/to_css.rb +9 -15
  82. data/vendor/sass/lib/sass/tree/warn_node.rb +1 -1
  83. data/vendor/sass/lib/sass/tree/while_node.rb +1 -1
  84. data/vendor/sass/lib/sass/util.rb +58 -6
  85. data/vendor/sass/sass.gemspec +2 -1
  86. data/vendor/sass/test/Gemfile +4 -0
  87. data/vendor/sass/test/Gemfile.lock +19 -0
  88. data/vendor/sass/test/sass/cache_test.rb +15 -0
  89. data/vendor/sass/test/sass/conversion_test.rb +2 -6
  90. data/vendor/sass/test/sass/css2sass_test.rb +9 -0
  91. data/vendor/sass/test/sass/engine_test.rb +124 -26
  92. data/vendor/sass/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  93. data/vendor/sass/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  94. data/vendor/sass/test/sass/functions_test.rb +13 -0
  95. data/vendor/sass/test/sass/importer_test.rb +110 -0
  96. data/vendor/sass/test/sass/logger_test.rb +58 -0
  97. data/vendor/sass/test/sass/plugin_test.rb +16 -13
  98. data/vendor/sass/test/sass/script_conversion_test.rb +2 -0
  99. data/vendor/sass/test/sass/script_test.rb +18 -0
  100. data/vendor/sass/test/sass/scss/css_test.rb +7 -1
  101. data/vendor/sass/test/sass/scss/scss_test.rb +37 -13
  102. data/vendor/sass/test/sass/templates/bork5.sass +3 -0
  103. data/vendor/sass/test/sass/templates/nested_bork5.sass +2 -0
  104. data/vendor/sass/test/sass/test_helper.rb +1 -1
  105. data/vendor/sass/test/sass/util_test.rb +12 -0
  106. data/vendor/sass/vendor/fssm/Gemfile +3 -0
  107. data/vendor/sass/vendor/fssm/LICENSE +1 -1
  108. data/vendor/sass/vendor/fssm/README.markdown +55 -27
  109. data/vendor/sass/vendor/fssm/Rakefile +6 -54
  110. data/vendor/sass/vendor/fssm/example.rb +6 -3
  111. data/vendor/sass/vendor/fssm/fssm.gemspec +17 -70
  112. data/vendor/sass/vendor/fssm/lib/fssm.rb +7 -3
  113. data/vendor/sass/vendor/fssm/lib/fssm/backends/fsevents.rb +1 -1
  114. data/vendor/sass/vendor/fssm/lib/fssm/backends/inotify.rb +2 -2
  115. data/vendor/sass/vendor/fssm/lib/fssm/backends/polling.rb +2 -2
  116. data/vendor/sass/vendor/fssm/lib/fssm/backends/rbfsevent.rb +42 -0
  117. data/vendor/sass/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +10 -10
  118. data/vendor/sass/vendor/fssm/lib/fssm/monitor.rb +19 -9
  119. data/vendor/sass/vendor/fssm/lib/fssm/path.rb +24 -21
  120. data/vendor/sass/vendor/fssm/lib/fssm/pathname.rb +13 -479
  121. data/vendor/sass/vendor/fssm/lib/fssm/state/directory.rb +29 -11
  122. data/vendor/sass/vendor/fssm/lib/fssm/state/file.rb +1 -1
  123. data/vendor/sass/vendor/fssm/lib/fssm/support.rb +41 -12
  124. data/vendor/sass/vendor/fssm/lib/fssm/tree.rb +6 -6
  125. data/vendor/sass/vendor/fssm/lib/fssm/version.rb +3 -0
  126. data/vendor/sass/vendor/fssm/profile/prof-cache.rb +3 -3
  127. data/vendor/sass/vendor/fssm/profile/prof-pathname-rubinius.rb +35 -0
  128. data/vendor/sass/vendor/fssm/profile/prof-pathname.rb +7 -7
  129. data/vendor/sass/vendor/fssm/spec/count_down_latch.rb +151 -0
  130. data/vendor/sass/vendor/fssm/spec/monitor_spec.rb +202 -0
  131. data/vendor/sass/vendor/fssm/spec/path_spec.rb +36 -15
  132. data/vendor/sass/vendor/fssm/spec/spec_helper.rb +6 -6
  133. metadata +36 -5
  134. data/vendor/sass/vendor/fssm/VERSION.yml +0 -5
@@ -92,14 +92,10 @@ module Sass
92
92
  # the second is the location of the CSS file that it should be compiled to.
93
93
  # @see #update_stylesheets
94
94
  def force_update_stylesheets(individual_files = [])
95
- old_options = options
96
- self.options = options.dup
97
- options[:never_update] = false
98
- options[:always_update] = true
99
- options[:cache] = false
100
- update_stylesheets(individual_files)
101
- ensure
102
- self.options = old_options
95
+ Compiler.new(options.dup.merge(
96
+ :never_update => false,
97
+ :always_update => true,
98
+ :cache => false)).update_stylesheets(individual_files)
103
99
  end
104
100
 
105
101
  # All other method invocations are proxied to the \{#compiler}.
@@ -38,7 +38,7 @@ module Sass::Plugin
38
38
  self.options.merge!(options)
39
39
  end
40
40
 
41
- # Register a callback to be run before stylesheets are mass-updated.
41
+ # Register a callback to be run after stylesheets are mass-updated.
42
42
  # This is run whenever \{#update\_stylesheets} is called,
43
43
  # unless the \{file:SASS_REFERENCE.md#never_update-option `:never_update` option}
44
44
  # is enabled.
@@ -51,6 +51,22 @@ module Sass::Plugin
51
51
  # the second is the target CSS file.
52
52
  define_callback :updating_stylesheets
53
53
 
54
+ # Register a callback to be run after a single stylesheet is updated.
55
+ # The callback is only run if the stylesheet is really updated;
56
+ # if the CSS file is fresh, this won't be run.
57
+ #
58
+ # Even if the \{file:SASS_REFERENCE.md#full_exception-option `:full_exception` option}
59
+ # is enabled, this callback won't be run
60
+ # when an exception CSS file is being written.
61
+ # To run an action for those files, use \{#on\_compilation\_error}.
62
+ #
63
+ # @yield [template, css]
64
+ # @yieldparam template [String]
65
+ # The location of the Sass/SCSS file being updated.
66
+ # @yieldparam css [String]
67
+ # The location of the CSS file being generated.
68
+ define_callback :updated_stylesheet
69
+
54
70
  # Register a callback to be run before a single stylesheet is updated.
55
71
  # The callback is only run if the stylesheet is guaranteed to be updated;
56
72
  # if the CSS file is fresh, this won't be run.
@@ -67,6 +83,13 @@ module Sass::Plugin
67
83
  # The location of the CSS file being generated.
68
84
  define_callback :updating_stylesheet
69
85
 
86
+ def on_updating_stylesheet_with_deprecation_warning(&block)
87
+ Sass::Util.sass_warn("Sass::Compiler#on_updating_stylesheet callback is deprecated and will be removed in a future release. Use Sass::Compiler#on_updated_stylesheet instead, which is run after stylesheet compilation.")
88
+ on_updating_stylesheet_without_deprecation_warning(&block)
89
+ end
90
+ alias_method :on_updating_stylesheet_without_deprecation_warning, :on_updating_stylesheet
91
+ alias_method :on_updating_stylesheet, :on_updating_stylesheet_with_deprecation_warning
92
+
70
93
  # Register a callback to be run when Sass decides not to update a stylesheet.
71
94
  # In particular, the callback is run when Sass finds that
72
95
  # the template file and none of its dependencies
@@ -160,28 +183,25 @@ module Sass::Plugin
160
183
  # The first string in each pair is the location of the Sass/SCSS file,
161
184
  # the second is the location of the CSS file that it should be compiled to.
162
185
  def update_stylesheets(individual_files = [])
163
- run_updating_stylesheets individual_files
164
186
  Sass::Plugin.checked_for_updates = true
165
187
  staleness_checker = StalenessChecker.new(engine_options)
166
188
 
167
- individual_files.each do |t, c|
168
- if options[:always_update] || staleness_checker.stylesheet_needs_update?(c, t)
169
- update_stylesheet(t, c)
170
- end
171
- end
172
-
173
189
  template_location_array.each do |template_location, css_location|
174
-
175
190
  Dir.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file|
176
191
  # Get the relative path to the file
177
192
  name = file.sub(template_location.to_s.sub(/\/*$/, '/'), "")
178
193
  css = css_filename(name, css_location)
194
+ individual_files << [file, css]
195
+ end
196
+ end
179
197
 
180
- if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
181
- update_stylesheet file, css
182
- else
183
- run_not_updating_stylesheet file, css
184
- end
198
+ run_updating_stylesheets individual_files
199
+
200
+ individual_files.each do |file, css|
201
+ if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
202
+ update_stylesheet(file, css)
203
+ else
204
+ run_not_updating_stylesheet(file, css)
185
205
  end
186
206
  end
187
207
  end
@@ -318,18 +338,23 @@ module Sass::Plugin
318
338
  engine_opts = engine_options(:css_filename => css, :filename => filename)
319
339
  result = Sass::Engine.for_file(filename, engine_opts).render
320
340
  rescue Exception => e
341
+ compilation_error_occured = true
321
342
  run_compilation_error e, filename, css
322
343
  result = Sass::SyntaxError.exception_to_css(e, options)
323
344
  else
324
345
  run_updating_stylesheet filename, css
325
346
  end
326
347
 
327
- # Finally, write the file
348
+ write_file(css, result)
349
+ run_updated_stylesheet(filename, css) unless compilation_error_occured
350
+ end
351
+
352
+ def write_file(css, content)
328
353
  flag = 'w'
329
354
  flag = 'wb' if Sass::Util.windows? && options[:unix_newlines]
330
355
  File.open(css, flag) do |file|
331
- file.set_encoding(result.encoding) unless Sass::Util.ruby1_8?
332
- file.print(result)
356
+ file.set_encoding(content.encoding) unless Sass::Util.ruby1_8?
357
+ file.print(content)
333
358
  end
334
359
  end
335
360
 
@@ -31,8 +31,6 @@ module Sass
31
31
  # @return [{Symbol => Object}]
32
32
  def options
33
33
  @options ||= default_options.dup
34
- @options[:cache_store] ||= Sass::CacheStores::Filesystem.new(@options[:cache_location])
35
- @options
36
34
  end
37
35
 
38
36
  # Sets the options hash.
@@ -2,7 +2,7 @@
2
2
  if defined?(ActiveSupport) && Sass::Util.has?(:public_method, ActiveSupport, :on_load) &&
3
3
  !Sass::Util.ap_geq?('3.1.0.beta')
4
4
  require 'sass/plugin/configuration'
5
- ActiveSupport.on_load(:before_initialize) do
5
+ ActiveSupport.on_load(:before_configuration) do
6
6
  require 'sass'
7
7
  require 'sass/plugin'
8
8
  end
@@ -57,6 +57,14 @@ module Sass
57
57
  @args + @keywords.values
58
58
  end
59
59
 
60
+ # @see Node#deep_copy
61
+ def deep_copy
62
+ node = dup
63
+ node.instance_variable_set('@args', args.map {|a| a.deep_copy})
64
+ node.instance_variable_set('@keywords', Hash[keywords.map {|k, v| [k, v.deep_copy]}])
65
+ node
66
+ end
67
+
60
68
  protected
61
69
 
62
70
  # Evaluates the function call.
@@ -80,7 +88,12 @@ module Sass
80
88
  opts(Functions::EvaluationContext.new(environment.options).send(ruby_name, *args))
81
89
  end
82
90
  rescue ArgumentError => e
83
- raise e unless e.backtrace.any? {|t| t =~ /:in `(block in )?(#{name}|perform)'$/}
91
+ # If this is a legitimate Ruby-raised argument error, re-raise it.
92
+ # Otherwise, it's an error in the user's stylesheet, so wrap it.
93
+ if e.message =~ /^wrong number of arguments \(\d+ for \d+\)/ &&
94
+ e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
95
+ raise e
96
+ end
84
97
  raise Sass::SyntaxError.new("#{e.message} for `#{name}'")
85
98
  end
86
99
 
@@ -93,7 +93,7 @@ module Sass::Script
93
93
  # \{#adjust_color adjust-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\]}
94
94
  # : Increase or decrease any of the components of a color.
95
95
  #
96
- # \{#scale_color scale-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\]}
96
+ # \{#scale_color scale-color($color, \[$red\], \[$green\], \[$blue\], \[$saturation\], \[$lightness\], \[$alpha\]}
97
97
  # : Fluidly scale one or more components of a color.
98
98
  #
99
99
  # \{#change_color change-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\]}
@@ -1299,6 +1299,49 @@ module Sass::Script
1299
1299
  declare :append, [:list, :val]
1300
1300
  declare :append, [:list, :val, :separator]
1301
1301
 
1302
+ # Combines several lists into a single comma separated list
1303
+ # space separated lists.
1304
+ #
1305
+ # The length of the resulting list is the length of the
1306
+ # shortest list.
1307
+ #
1308
+ # @example
1309
+ # zip(1px 1px 3px, solid dashed solid, red green blue)
1310
+ # => 1px solid red, 1px dashed green, 3px solid blue
1311
+ def zip(*lists)
1312
+ length = nil
1313
+ values = []
1314
+ lists.each do |list|
1315
+ assert_type list, :List
1316
+ values << list.value.dup
1317
+ length = length.nil? ? list.value.length : [length, list.value.length].min
1318
+ end
1319
+ values.each do |value|
1320
+ value.slice!(length)
1321
+ end
1322
+ new_list_value = values.first.zip(*values[1..-1])
1323
+ List.new(new_list_value.map{|list| List.new(list, :space)}, :comma)
1324
+ end
1325
+ declare :zip, [], :var_args => true
1326
+
1327
+
1328
+ # Returns the position of the given value within the given
1329
+ # list. If not found, returns false.
1330
+ #
1331
+ # @example
1332
+ # index(1px solid red, solid) => 2
1333
+ # index(1px solid red, dashed) => false
1334
+ def index(list, value)
1335
+ assert_type list, :List
1336
+ index = list.value.index {|e| e.eq(value).to_bool }
1337
+ if index
1338
+ Number.new(index + 1)
1339
+ else
1340
+ Bool.new(false)
1341
+ end
1342
+ end
1343
+ declare :index, [:list, :value]
1344
+
1302
1345
  # Returns one of two values based on the truth value of the first argument.
1303
1346
  #
1304
1347
  # @example
@@ -50,6 +50,15 @@ module Sass::Script
50
50
  [@before, @mid, @after].compact
51
51
  end
52
52
 
53
+ # @see Node#deep_copy
54
+ def deep_copy
55
+ node = dup
56
+ node.instance_variable_set('@before', @before.deep_copy) if @before
57
+ node.instance_variable_set('@mid', @mid.deep_copy)
58
+ node.instance_variable_set('@after', @after.deep_copy) if @after
59
+ node
60
+ end
61
+
53
62
  protected
54
63
 
55
64
  # Evaluates the interpolation.
@@ -231,7 +231,7 @@ module Sass
231
231
 
232
232
  variable || string(:double, false) || string(:single, false) || number ||
233
233
  color || bool || string(:uri, false) || raw(UNICODERANGE) ||
234
- special_fun || ident_op || ident || op
234
+ special_fun || special_val || ident_op || ident || op
235
235
  end
236
236
 
237
237
  def variable
@@ -302,6 +302,11 @@ MESSAGE
302
302
  str1.size + str2.size]
303
303
  end
304
304
 
305
+ def special_val
306
+ return unless scan(/!important/i)
307
+ [:string, Script::String.new("!important")]
308
+ end
309
+
305
310
  def ident_op
306
311
  return unless op = scan(REGULAR_EXPRESSIONS[:ident_op])
307
312
  [OPERATORS[op]]
@@ -24,6 +24,13 @@ module Sass::Script
24
24
  @separator = separator
25
25
  end
26
26
 
27
+ # @see Node#deep_copy
28
+ def deep_copy
29
+ node = dup
30
+ node.instance_variable_set('@value', value.map {|c| c.deep_copy})
31
+ node
32
+ end
33
+
27
34
  # @see Node#eq
28
35
  def eq(other)
29
36
  Sass::Script::Bool.new(
@@ -33,6 +33,11 @@ module Sass::Script
33
33
  []
34
34
  end
35
35
 
36
+ # @see Node#deep_copy
37
+ def deep_copy
38
+ dup
39
+ end
40
+
36
41
  # Returns the options hash for this node.
37
42
  #
38
43
  # @return [{Symbol => Object}]
@@ -57,6 +57,14 @@ module Sass::Script
57
57
  Sass::Util.abstract(self)
58
58
  end
59
59
 
60
+ # Returns a deep clone of this node.
61
+ # The child nodes are cloned, but options are not.
62
+ #
63
+ # @return [Node]
64
+ def deep_copy
65
+ Sass::Util.abstract(self)
66
+ end
67
+
60
68
  protected
61
69
 
62
70
  # Converts underscores to dashes if the :dasherize option is set.
@@ -35,11 +35,34 @@ module Sass::Script
35
35
  # @return [Boolean, nil]
36
36
  attr_accessor :original
37
37
 
38
- # The precision with which numbers will be printed to CSS files.
39
- # For example, if this is `1000.0`,
38
+ def self.precision
39
+ @precision ||= 3
40
+ end
41
+
42
+ # Sets the number of digits of precision
43
+ # For example, if this is `3`,
40
44
  # `3.1415926` will be printed as `3.142`.
41
- # @api public
42
- PRECISION = 1000.0
45
+ def self.precision=(digits)
46
+ @precision = digits.round
47
+ @precision_factor = 10.0**@precision
48
+ end
49
+
50
+ # the precision factor used in numeric output
51
+ # it is derived from the `precision` method.
52
+ def self.precision_factor
53
+ @precision_factor ||= 10.0**precision
54
+ end
55
+
56
+ # Handles the deprecation warning for the PRECISION constant
57
+ # This can be removed in 3.2.
58
+ def self.const_missing(const)
59
+ if const == :PRECISION
60
+ Sass::Util.sass_warn("Sass::Script::Number::PRECISION is deprecated and will be removed in a future release. Use Sass::Script::Number.precision_factor instead.")
61
+ const_set(:PRECISION, self.precision_factor)
62
+ else
63
+ super
64
+ end
65
+ end
43
66
 
44
67
  # Used so we don't allocate two new arrays for each new number.
45
68
  NO_UNITS = []
@@ -337,7 +360,7 @@ module Sass::Script
337
360
  elsif num % 1 == 0.0
338
361
  num.to_i
339
362
  else
340
- (num * PRECISION).round / PRECISION
363
+ (num * self.precision_factor).round / self.precision_factor
341
364
  end
342
365
  end
343
366
 
@@ -55,6 +55,14 @@ module Sass::Script
55
55
  [@operand1, @operand2]
56
56
  end
57
57
 
58
+ # @see Node#deep_copy
59
+ def deep_copy
60
+ node = dup
61
+ node.instance_variable_set('@operand1', @operand1.deep_copy)
62
+ node.instance_variable_set('@operand2', @operand2.deep_copy)
63
+ node
64
+ end
65
+
58
66
  protected
59
67
 
60
68
  # Evaluates the operation.
@@ -182,7 +182,11 @@ module Sass
182
182
  interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}) and return interp
183
183
  return unless e = #{sub}
184
184
  while tok = try_tok(#{ops.map {|o| o.inspect}.join(', ')})
185
- interp = try_op_before_interp(tok, e) and return interp
185
+ if interp = try_op_before_interp(tok, e)
186
+ return interp unless other_interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}, interp)
187
+ return other_interp
188
+ end
189
+
186
190
  line = @lexer.line
187
191
  e = Operation.new(e, assert_expr(#{sub.inspect}), tok.type)
188
192
  e.line = line
@@ -217,7 +221,10 @@ RUBY
217
221
  return unless e = interpolation
218
222
  arr = [e]
219
223
  while tok = try_tok(:comma)
220
- interp = try_op_before_interp(tok, e) and return interp
224
+ if interp = try_op_before_interp(tok, e)
225
+ return interp unless other_interp = try_ops_after_interp([:comma], :expr, interp)
226
+ return other_interp
227
+ end
221
228
  arr << assert_expr(:interpolation)
222
229
  end
223
230
  arr.size == 1 ? arr.first : node(List.new(arr, :comma), line)
@@ -235,15 +242,15 @@ RUBY
235
242
  interpolation(interp)
236
243
  end
237
244
 
238
- def try_ops_after_interp(ops, name)
245
+ def try_ops_after_interp(ops, name, prev = nil)
239
246
  return unless @lexer.after_interpolation?
240
247
  return unless op = try_tok(*ops)
241
- interp = try_op_before_interp(op) and return interp
248
+ interp = try_op_before_interp(op, prev) and return interp
242
249
 
243
250
  wa = @lexer.whitespace?
244
251
  str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
245
252
  str.line = @lexer.line
246
- interp = Script::Interpolation.new(nil, str, assert_expr(name), !:wb, wa, :originally_text)
253
+ interp = Script::Interpolation.new(prev, str, assert_expr(name), !:wb, wa, :originally_text)
247
254
  interp.line = @lexer.line
248
255
  return interp
249
256
  end
@@ -60,6 +60,15 @@ module Sass::Script
60
60
  [@before, @mid, @after].compact
61
61
  end
62
62
 
63
+ # @see Node#deep_copy
64
+ def deep_copy
65
+ node = dup
66
+ node.instance_variable_set('@before', @before.deep_copy) if @before
67
+ node.instance_variable_set('@mid', @mid.deep_copy)
68
+ node.instance_variable_set('@after', @after.deep_copy) if @after
69
+ node
70
+ end
71
+
63
72
  protected
64
73
 
65
74
  # Evaluates the interpolation.
@@ -38,6 +38,13 @@ module Sass::Script
38
38
  [@operand]
39
39
  end
40
40
 
41
+ # @see Node#deep_copy
42
+ def deep_copy
43
+ node = dup
44
+ node.instance_variable_set('@operand', @operand.deep_copy)
45
+ node
46
+ end
47
+
41
48
  protected
42
49
 
43
50
  # Evaluates the operation.