sass 3.4.25 → 3.5.0.pre.rc.1

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 (156) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/README.md +1 -1
  4. data/Rakefile +13 -157
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/VERSION_NAME +1 -1
  8. data/lib/sass.rb +3 -10
  9. data/lib/sass/cache_stores/filesystem.rb +1 -1
  10. data/lib/sass/css.rb +2 -3
  11. data/lib/sass/engine.rb +46 -32
  12. data/lib/sass/environment.rb +27 -6
  13. data/lib/sass/error.rb +5 -5
  14. data/lib/sass/exec/base.rb +3 -12
  15. data/lib/sass/features.rb +1 -0
  16. data/lib/sass/importers/filesystem.rb +2 -2
  17. data/lib/sass/plugin.rb +1 -1
  18. data/lib/sass/plugin/compiler.rb +21 -51
  19. data/lib/sass/plugin/configuration.rb +1 -1
  20. data/lib/sass/plugin/rack.rb +3 -3
  21. data/lib/sass/plugin/staleness_checker.rb +3 -3
  22. data/lib/sass/railtie.rb +1 -1
  23. data/lib/sass/script.rb +3 -3
  24. data/lib/sass/script/functions.rb +238 -47
  25. data/lib/sass/script/lexer.rb +8 -6
  26. data/lib/sass/script/parser.rb +76 -75
  27. data/lib/sass/script/tree/funcall.rb +35 -30
  28. data/lib/sass/script/tree/list_literal.rb +23 -8
  29. data/lib/sass/script/tree/map_literal.rb +2 -2
  30. data/lib/sass/script/tree/node.rb +2 -10
  31. data/lib/sass/script/tree/operation.rb +16 -50
  32. data/lib/sass/script/value.rb +2 -0
  33. data/lib/sass/script/value/arg_list.rb +1 -1
  34. data/lib/sass/script/value/base.rb +20 -3
  35. data/lib/sass/script/value/callable.rb +25 -0
  36. data/lib/sass/script/value/color.rb +10 -10
  37. data/lib/sass/script/value/function.rb +19 -0
  38. data/lib/sass/script/value/helpers.rb +16 -7
  39. data/lib/sass/script/value/list.rb +33 -12
  40. data/lib/sass/script/value/map.rb +2 -2
  41. data/lib/sass/script/value/number.rb +3 -3
  42. data/lib/sass/script/value/string.rb +12 -5
  43. data/lib/sass/scss/parser.rb +101 -45
  44. data/lib/sass/scss/rx.rb +5 -11
  45. data/lib/sass/scss/static_parser.rb +0 -7
  46. data/lib/sass/selector.rb +4 -0
  47. data/lib/sass/selector/abstract_sequence.rb +5 -5
  48. data/lib/sass/selector/comma_sequence.rb +3 -15
  49. data/lib/sass/selector/pseudo.rb +4 -0
  50. data/lib/sass/selector/sequence.rb +30 -3
  51. data/lib/sass/selector/simple.rb +13 -7
  52. data/lib/sass/selector/simple_sequence.rb +1 -1
  53. data/lib/sass/shared.rb +3 -5
  54. data/lib/sass/source/map.rb +4 -4
  55. data/lib/sass/source/position.rb +4 -4
  56. data/lib/sass/stack.rb +21 -1
  57. data/lib/sass/tree/charset_node.rb +1 -1
  58. data/lib/sass/tree/comment_node.rb +1 -1
  59. data/lib/sass/tree/node.rb +3 -3
  60. data/lib/sass/tree/prop_node.rb +46 -54
  61. data/lib/sass/tree/rule_node.rb +7 -15
  62. data/lib/sass/tree/visitors/check_nesting.rb +1 -1
  63. data/lib/sass/tree/visitors/convert.rb +2 -3
  64. data/lib/sass/tree/visitors/cssize.rb +1 -10
  65. data/lib/sass/tree/visitors/deep_copy.rb +2 -2
  66. data/lib/sass/tree/visitors/perform.rb +23 -12
  67. data/lib/sass/tree/visitors/set_options.rb +1 -1
  68. data/lib/sass/tree/visitors/to_css.rb +46 -12
  69. data/lib/sass/util.rb +16 -321
  70. data/lib/sass/util/multibyte_string_scanner.rb +127 -131
  71. data/lib/sass/util/normalized_map.rb +1 -8
  72. data/lib/sass/version.rb +2 -2
  73. data/test/sass-spec.yml +1 -1
  74. data/test/sass/compiler_test.rb +4 -14
  75. data/test/sass/conversion_test.rb +113 -162
  76. data/test/sass/css2sass_test.rb +17 -19
  77. data/test/sass/css_variable_test.rb +176 -70
  78. data/test/sass/encoding_test.rb +2 -32
  79. data/test/sass/engine_test.rb +114 -65
  80. data/test/sass/extend_test.rb +37 -51
  81. data/test/sass/functions_test.rb +57 -15
  82. data/test/sass/importer_test.rb +2 -2
  83. data/test/sass/more_templates/more1.sass +10 -10
  84. data/test/sass/more_templates/more_import.sass +2 -2
  85. data/test/sass/plugin_test.rb +9 -12
  86. data/test/sass/script_conversion_test.rb +9 -0
  87. data/test/sass/script_test.rb +38 -48
  88. data/test/sass/scss/css_test.rb +5 -19
  89. data/test/sass/scss/scss_test.rb +58 -39
  90. data/test/sass/source_map_test.rb +26 -28
  91. data/test/sass/templates/_partial.sass +1 -1
  92. data/test/sass/templates/basic.sass +10 -10
  93. data/test/sass/templates/bork1.sass +1 -1
  94. data/test/sass/templates/bork5.sass +1 -1
  95. data/test/sass/templates/compact.sass +10 -10
  96. data/test/sass/templates/complex.sass +187 -187
  97. data/test/sass/templates/compressed.sass +10 -10
  98. data/test/sass/templates/expanded.sass +10 -10
  99. data/test/sass/templates/import.sass +2 -2
  100. data/test/sass/templates/importee.sass +3 -3
  101. data/test/sass/templates/mixins.sass +22 -22
  102. data/test/sass/templates/multiline.sass +4 -4
  103. data/test/sass/templates/nested.sass +13 -13
  104. data/test/sass/templates/parent_ref.sass +12 -12
  105. data/test/sass/templates/script.sass +70 -70
  106. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +1 -1
  107. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +2 -2
  108. data/test/sass/templates/subdir/subdir.sass +3 -3
  109. data/test/sass/templates/units.sass +10 -10
  110. data/test/sass/util/multibyte_string_scanner_test.rb +139 -149
  111. data/test/sass/util_test.rb +0 -36
  112. data/test/test_helper.rb +39 -0
  113. metadata +30 -57
  114. data/extra/sass-spec-ref.sh +0 -32
  115. data/lib/sass/deprecation.rb +0 -55
  116. data/lib/sass/script/css_variable_warning.rb +0 -52
  117. data/lib/sass/util/cross_platform_random.rb +0 -19
  118. data/lib/sass/util/ordered_hash.rb +0 -192
  119. data/test/sass/results/import_charset_1_8.css +0 -5
  120. data/test/sass/templates/import_charset_1_8.sass +0 -6
  121. data/vendor/listen/CHANGELOG.md +0 -1
  122. data/vendor/listen/CONTRIBUTING.md +0 -38
  123. data/vendor/listen/Gemfile +0 -20
  124. data/vendor/listen/Guardfile +0 -8
  125. data/vendor/listen/LICENSE +0 -20
  126. data/vendor/listen/README.md +0 -349
  127. data/vendor/listen/Rakefile +0 -5
  128. data/vendor/listen/Vagrantfile +0 -96
  129. data/vendor/listen/lib/listen.rb +0 -54
  130. data/vendor/listen/lib/listen/adapter.rb +0 -327
  131. data/vendor/listen/lib/listen/adapters/bsd.rb +0 -75
  132. data/vendor/listen/lib/listen/adapters/darwin.rb +0 -48
  133. data/vendor/listen/lib/listen/adapters/linux.rb +0 -81
  134. data/vendor/listen/lib/listen/adapters/polling.rb +0 -58
  135. data/vendor/listen/lib/listen/adapters/windows.rb +0 -91
  136. data/vendor/listen/lib/listen/directory_record.rb +0 -406
  137. data/vendor/listen/lib/listen/listener.rb +0 -323
  138. data/vendor/listen/lib/listen/turnstile.rb +0 -32
  139. data/vendor/listen/lib/listen/version.rb +0 -3
  140. data/vendor/listen/listen.gemspec +0 -28
  141. data/vendor/listen/spec/listen/adapter_spec.rb +0 -149
  142. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +0 -36
  143. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -37
  144. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -47
  145. data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
  146. data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -30
  147. data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1250
  148. data/vendor/listen/spec/listen/listener_spec.rb +0 -258
  149. data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
  150. data/vendor/listen/spec/listen_spec.rb +0 -67
  151. data/vendor/listen/spec/spec_helper.rb +0 -25
  152. data/vendor/listen/spec/support/adapter_helper.rb +0 -666
  153. data/vendor/listen/spec/support/directory_record_helper.rb +0 -57
  154. data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
  155. data/vendor/listen/spec/support/listeners_helper.rb +0 -179
  156. data/vendor/listen/spec/support/platform_helper.rb +0 -15
@@ -19,13 +19,13 @@ module Sass
19
19
  # `source_range`: \[`Sass::Source::Range`\]
20
20
  # : The range in the source file in which the token appeared.
21
21
  #
22
- # `pos`: \[`Integer`\]
22
+ # `pos`: \[`Fixnum`\]
23
23
  # : The scanner position at which the SassScript token appeared.
24
24
  Token = Struct.new(:type, :value, :source_range, :pos)
25
25
 
26
26
  # The line number of the lexer's current position.
27
27
  #
28
- # @return [Integer]
28
+ # @return [Fixnum]
29
29
  def line
30
30
  return @line unless @tok
31
31
  @tok.source_range.start_pos.line
@@ -34,7 +34,7 @@ module Sass
34
34
  # The number of bytes into the current line
35
35
  # of the lexer's current position (1-based).
36
36
  #
37
- # @return [Integer]
37
+ # @return [Fixnum]
38
38
  def offset
39
39
  return @offset unless @tok
40
40
  @tok.source_range.start_pos.offset
@@ -51,6 +51,8 @@ module Sass
51
51
  ':' => :colon,
52
52
  '(' => :lparen,
53
53
  ')' => :rparen,
54
+ '[' => :lsquare,
55
+ ']' => :rsquare,
54
56
  ',' => :comma,
55
57
  'and' => :and,
56
58
  'or' => :or,
@@ -142,12 +144,12 @@ module Sass
142
144
  }
143
145
 
144
146
  # @param str [String, StringScanner] The source text to lex
145
- # @param line [Integer] The 1-based line on which the SassScript appears.
147
+ # @param line [Fixnum] The 1-based line on which the SassScript appears.
146
148
  # Used for error reporting and sourcemap building
147
- # @param offset [Integer] The 1-based character (not byte) offset in the line in the source.
149
+ # @param offset [Fixnum] The 1-based character (not byte) offset in the line in the source.
148
150
  # Used for error reporting and sourcemap building
149
151
  # @param options [{Symbol => Object}] An options hash;
150
- # see {file:SASS_REFERENCE.md#Options the Sass options documentation}
152
+ # see {file:SASS_REFERENCE.md#options the Sass options documentation}
151
153
  def initialize(str, line, offset, options)
152
154
  @scanner = str.is_a?(StringScanner) ? str : Sass::Util::MultibyteStringScanner.new(str)
153
155
  @line = line
@@ -1,5 +1,4 @@
1
1
  require 'sass/script/lexer'
2
- require 'sass/script/css_variable_warning'
3
2
 
4
3
  module Sass
5
4
  module Script
@@ -8,25 +7,25 @@ module Sass
8
7
  class Parser
9
8
  # The line number of the parser's current position.
10
9
  #
11
- # @return [Integer]
10
+ # @return [Fixnum]
12
11
  def line
13
12
  @lexer.line
14
13
  end
15
14
 
16
15
  # The column number of the parser's current position.
17
16
  #
18
- # @return [Integer]
17
+ # @return [Fixnum]
19
18
  def offset
20
19
  @lexer.offset
21
20
  end
22
21
 
23
22
  # @param str [String, StringScanner] The source text to parse
24
- # @param line [Integer] The line on which the SassScript appears.
23
+ # @param line [Fixnum] The line on which the SassScript appears.
25
24
  # Used for error reporting and sourcemap building
26
- # @param offset [Integer] The character (not byte) offset where the script starts in the line.
25
+ # @param offset [Fixnum] The character (not byte) offset where the script starts in the line.
27
26
  # Used for error reporting and sourcemap building
28
27
  # @param options [{Symbol => Object}] An options hash; see
29
- # {file:SASS_REFERENCE.md#Options the Sass options documentation}.
28
+ # {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
30
29
  # This supports an additional `:allow_extra_text` option that controls
31
30
  # whether the parser throws an error when extra text is encountered
32
31
  # after the parsed construct.
@@ -35,7 +34,6 @@ module Sass
35
34
  @allow_extra_text = options.delete(:allow_extra_text)
36
35
  @lexer = lexer_class.new(str, line, offset, options)
37
36
  @stop_at = nil
38
- @css_variable_warning = nil
39
37
  end
40
38
 
41
39
  # Parses a SassScript expression within an interpolated segment (`#{}`).
@@ -64,23 +62,13 @@ module Sass
64
62
 
65
63
  # Parses a SassScript expression.
66
64
  #
67
- # @param css_variable [Boolean] Whether this is the value of a CSS variable.
68
65
  # @return [Script::Tree::Node] The root node of the parse tree
69
66
  # @raise [Sass::SyntaxError] if the expression isn't valid SassScript
70
- def parse(css_variable = false)
71
- if css_variable
72
- @css_variable_warning = CssVariableWarning.new
73
- end
74
-
67
+ def parse
75
68
  expr = assert_expr :expr
76
69
  assert_done
77
70
  expr.options = @options
78
71
  check_for_interpolation expr
79
-
80
- if css_variable
81
- @css_variable_warning.value = expr
82
- end
83
-
84
72
  expr
85
73
  rescue Sass::SyntaxError => e
86
74
  e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
@@ -127,7 +115,7 @@ module Sass
127
115
  a.options = @options
128
116
  end
129
117
 
130
- keywords.each do |_k, v|
118
+ keywords.each do |_, v|
131
119
  check_for_interpolation v
132
120
  v.options = @options
133
121
  end
@@ -232,12 +220,12 @@ module Sass
232
220
 
233
221
  # Parses a SassScript expression.
234
222
  #
223
+ # @overload parse(str, line, offset, filename = nil)
235
224
  # @return [Script::Tree::Node] The root node of the parse tree
236
225
  # @see Parser#initialize
237
226
  # @see Parser#parse
238
- def self.parse(value, line, offset, options = {})
239
- css_variable = options.delete :css_variable
240
- new(value, line, offset, options).parse(css_variable)
227
+ def self.parse(*args)
228
+ new(*args).parse
241
229
  end
242
230
 
243
231
  PRECEDENCE = [
@@ -250,8 +238,6 @@ module Sass
250
238
 
251
239
  ASSOCIATIVE = [:plus, :times]
252
240
 
253
- VALID_CSS_OPS = [:comma, :single_eq, :space, :div]
254
-
255
241
  class << self
256
242
  # Returns an integer representing the precedence
257
243
  # of the given operator.
@@ -291,10 +277,6 @@ module Sass
291
277
  return other_interp
292
278
  end
293
279
 
294
- if @css_variable_warning && !VALID_CSS_OPS.include?(tok.type)
295
- @css_variable_warning.warn!
296
- end
297
-
298
280
  e = node(Tree::Operation.new(e, assert_expr(#{sub.inspect}), tok.type),
299
281
  e.source_range.start_pos)
300
282
  end
@@ -310,8 +292,6 @@ RUBY
310
292
  interp = try_op_before_interp(tok)
311
293
  return interp if interp
312
294
  start_pos = source_position
313
-
314
- @css_variable_warning.warn! if @css_variable_warning
315
295
  node(Tree::UnaryOperation.new(assert_expr(:unary_#{op}), :#{op}), start_pos)
316
296
  end
317
297
  RUBY
@@ -338,7 +318,6 @@ RUBY
338
318
  return list e, start_pos unless @lexer.peek && @lexer.peek.type == :colon
339
319
 
340
320
  pair = map_pair(e)
341
- @css_variable_warning.warn! if @css_variable_warning
342
321
  map = node(Sass::Script::Tree::MapLiteral.new([pair]), start_pos)
343
322
  while try_tok(:comma)
344
323
  pair = map_pair
@@ -364,7 +343,7 @@ RUBY
364
343
  def list(first, start_pos)
365
344
  return first unless @lexer.peek && @lexer.peek.type == :comma
366
345
 
367
- list = node(Sass::Script::Tree::ListLiteral.new([first], :comma), start_pos)
346
+ list = node(Sass::Script::Tree::ListLiteral.new([first], separator: :comma), start_pos)
368
347
  while (tok = try_tok(:comma))
369
348
  element_before_interp = list.elements.length == 1 ? list.elements.first : list
370
349
  if (interp = try_op_before_interp(tok, element_before_interp))
@@ -401,7 +380,7 @@ RUBY
401
380
  Script::Tree::Interpolation.new(
402
381
  prev, str, nil, wb, false, :originally_text => true, :deprecation => deprecation),
403
382
  (prev || str).source_range.start_pos)
404
- interpolation(interp)
383
+ interpolation(first: interp)
405
384
  end
406
385
 
407
386
  def try_ops_after_interp(ops, name, prev = nil)
@@ -431,17 +410,17 @@ RUBY
431
410
  interp
432
411
  end
433
412
 
434
- def interpolation(first = space)
435
- e = first
413
+ def interpolation(first: nil, inner: :space)
414
+ e = first || send(inner)
436
415
  while (interp = try_tok(:begin_interpolation))
437
416
  wb = @lexer.whitespace?(interp)
438
417
  char_before = @lexer.char(interp.pos - 1)
439
- mid = without_css_variable_warning {assert_expr :expr}
418
+ mid = assert_expr :expr
440
419
  assert_tok :end_interpolation
441
420
  wa = @lexer.whitespace?
442
421
  char_after = @lexer.char
443
422
 
444
- after = space
423
+ after = send(inner)
445
424
  before_deprecation = e.is_a?(Script::Tree::Interpolation) ? e.deprecation : :none
446
425
  after_deprecation = after.is_a?(Script::Tree::Interpolation) ? after.deprecation : :none
447
426
 
@@ -500,7 +479,7 @@ RUBY
500
479
  if arr.size == 1
501
480
  arr.first
502
481
  else
503
- node(Sass::Script::Tree::ListLiteral.new(arr, :space), start_pos)
482
+ node(Sass::Script::Tree::ListLiteral.new(arr, separator: :space), start_pos)
504
483
  end
505
484
  end
506
485
 
@@ -549,12 +528,12 @@ RUBY
549
528
  else
550
529
  return [], nil unless try_tok(:lparen)
551
530
  end
552
- return [], nil if try_tok(:rparen)
553
531
 
554
532
  res = []
555
533
  splat = nil
556
534
  must_have_default = false
557
535
  loop do
536
+ break if peek_tok(:rparen)
558
537
  c = assert_tok(:const)
559
538
  var = node(Script::Tree::Variable.new(c.value), c.source_range)
560
539
  if try_tok(:colon)
@@ -585,12 +564,8 @@ RUBY
585
564
  def arglist(subexpr, description)
586
565
  args = []
587
566
  keywords = Sass::Util::NormalizedMap.new
588
- e = send(subexpr)
589
-
590
- return [args, keywords] unless e
591
-
592
567
  splat = nil
593
- loop do
568
+ while (e = send(subexpr))
594
569
  if @lexer.peek && @lexer.peek.type == :colon
595
570
  name = e
596
571
  @lexer.expected!("comma") unless name.is_a?(Tree::Variable)
@@ -611,13 +586,12 @@ RUBY
611
586
  elsif !keywords.empty?
612
587
  raise SyntaxError.new("Positional arguments must come before keyword arguments.")
613
588
  end
614
-
615
589
  args << e if e
616
590
  end
617
591
 
618
592
  return args, keywords, splat unless try_tok(:comma)
619
- e = assert_expr(subexpr, description)
620
593
  end
594
+ return args, keywords
621
595
  end
622
596
 
623
597
  def raw
@@ -628,10 +602,10 @@ RUBY
628
602
 
629
603
  def special_fun
630
604
  first = try_tok(:special_fun)
631
- return paren unless first
605
+ return square_list unless first
632
606
  str = literal_node(first.value, first.source_range)
633
607
  return str unless try_tok(:string_interpolation)
634
- mid = without_css_variable_warning {assert_expr :expr}
608
+ mid = assert_expr :expr
635
609
  assert_tok :end_interpolation
636
610
  last = assert_expr(:special_fun)
637
611
  node(
@@ -639,6 +613,50 @@ RUBY
639
613
  first.source_range.start_pos)
640
614
  end
641
615
 
616
+ def square_list
617
+ start_pos = source_position
618
+ return paren unless try_tok(:lsquare)
619
+
620
+ space_start_pos = source_position
621
+ e = interpolation(inner: :or_expr)
622
+ separator = nil
623
+ if e
624
+ elements = [e]
625
+ while (e = interpolation(inner: :or_expr))
626
+ elements << e
627
+ end
628
+
629
+ # If there's a comma after a space-separated list, it's actually a
630
+ # space-separated list nested in a comma-separated list.
631
+ if try_tok(:comma)
632
+ e = if elements.length == 1
633
+ elements.first
634
+ else
635
+ node(
636
+ Sass::Script::Tree::ListLiteral.new(elements, separator: :space),
637
+ space_start_pos)
638
+ end
639
+ elements = [e]
640
+
641
+ while (e = space)
642
+ elements << e
643
+ break unless try_tok(:comma)
644
+ end
645
+ separator = :comma
646
+ else
647
+ separator = :space if elements.length > 1
648
+ end
649
+ else
650
+ elements = []
651
+ end
652
+
653
+ assert_tok(:rsquare)
654
+ end_pos = source_position
655
+
656
+ node(Sass::Script::Tree::ListLiteral.new(elements, separator: separator, bracketed: true),
657
+ start_pos, end_pos)
658
+ end
659
+
642
660
  def paren
643
661
  return variable unless try_tok(:lparen)
644
662
  start_pos = source_position
@@ -646,17 +664,13 @@ RUBY
646
664
  e.force_division! if e
647
665
  end_pos = source_position
648
666
  assert_tok(:rparen)
649
-
650
- @css_variable_warning.warn! if @css_variable_warning
651
- e || node(Sass::Script::Tree::ListLiteral.new([], nil), start_pos, end_pos)
667
+ e || node(Sass::Script::Tree::ListLiteral.new([]), start_pos, end_pos)
652
668
  end
653
669
 
654
670
  def variable
655
671
  start_pos = source_position
656
672
  c = try_tok(:const)
657
673
  return string unless c
658
-
659
- @css_variable_warning.warn! if @css_variable_warning
660
674
  node(Tree::Variable.new(*c.value), start_pos)
661
675
  end
662
676
 
@@ -665,7 +679,7 @@ RUBY
665
679
  return number unless first
666
680
  str = literal_node(first.value, first.source_range)
667
681
  return str unless try_tok(:string_interpolation)
668
- mid = without_css_variable_warning {assert_expr :expr}
682
+ mid = assert_expr :expr
669
683
  assert_tok :end_interpolation
670
684
  last = assert_expr(:string)
671
685
  node(Tree::StringInterpolation.new(str, mid, last), first.source_range.start_pos)
@@ -683,7 +697,6 @@ RUBY
683
697
  def selector
684
698
  tok = try_tok(:selector)
685
699
  return literal unless tok
686
- @css_variable_warning.warn! if @css_variable_warning
687
700
  node(tok.value, tok.source_range.start_pos)
688
701
  end
689
702
 
@@ -723,10 +736,14 @@ RUBY
723
736
  @lexer.expected!(names.map {|tok| Lexer::TOKEN_NAMES[tok] || tok}.join(" or "))
724
737
  end
725
738
 
726
- def try_tok(name)
739
+ def peek_tok(name)
727
740
  # Avoids an array allocation caused by argument globbing in the try_toks method.
728
741
  peeked = @lexer.peek
729
- peeked && name == peeked.type && @lexer.next
742
+ peeked && name == peeked.type
743
+ end
744
+
745
+ def try_tok(name)
746
+ peek_tok(name) && @lexer.next
730
747
  end
731
748
 
732
749
  def try_toks(*names)
@@ -771,27 +788,12 @@ RUBY
771
788
  range(source_range_or_start_pos, end_pos)
772
789
  end
773
790
 
774
- node.css_variable_warning = @css_variable_warning
775
791
  node.line = source_range.start_pos.line
776
792
  node.source_range = source_range
777
793
  node.filename = @options[:filename]
778
794
  node
779
795
  end
780
796
 
781
- # Runs the given block without CSS variable warnings enabled.
782
- #
783
- # CSS warnings don't apply within interpolation, so this is used to
784
- # disable them.
785
- #
786
- # @yield []
787
- def without_css_variable_warning
788
- old_css_variable_warning = @css_variable_warning
789
- @css_variable_warning = nil
790
- yield
791
- ensure
792
- @css_variable_warning = old_css_variable_warning
793
- end
794
-
795
797
  # Checks a script node for any immediately-deprecated interpolations, and
796
798
  # emits warnings for them.
797
799
  #
@@ -818,9 +820,8 @@ RUBY
818
820
  location = "on line #{interpolation.line}"
819
821
  location << " of #{interpolation.filename}" if interpolation.filename
820
822
  Sass::Util.sass_warn <<WARNING
821
- DEPRECATION WARNING #{location}:
822
- \#{} interpolation near operators will be simplified in a future version of Sass.
823
- To preserve the current behavior, use quotes:
823
+ DEPRECATION WARNING #{location}: \#{} interpolation near operators will be simplified
824
+ in a future version of Sass. To preserve the current behavior, use quotes:
824
825
 
825
826
  #{interpolation.to_quoted_equivalent.to_sass}
826
827
 
@@ -13,6 +13,11 @@ module Sass::Script::Tree
13
13
  # @return [String]
14
14
  attr_reader :name
15
15
 
16
+ # The callable to be invoked
17
+ #
18
+ # @return [Sass::Callable] or nil if no callable is provided.
19
+ attr_reader :callable
20
+
16
21
  # The arguments to the function.
17
22
  #
18
23
  # @return [Array<Node>]
@@ -39,13 +44,19 @@ module Sass::Script::Tree
39
44
  # @return [Node?]
40
45
  attr_accessor :kwarg_splat
41
46
 
42
- # @param name [String] See \{#name}
47
+ # @param name_or_callable [String, Sass::Callable] See \{#name}
43
48
  # @param args [Array<Node>] See \{#args}
44
49
  # @param keywords [Sass::Util::NormalizedMap<Node>] See \{#keywords}
45
50
  # @param splat [Node] See \{#splat}
46
51
  # @param kwarg_splat [Node] See \{#kwarg_splat}
47
- def initialize(name, args, keywords, splat, kwarg_splat)
48
- @name = name
52
+ def initialize(name_or_callable, args, keywords, splat, kwarg_splat)
53
+ if name_or_callable.is_a?(Sass::Callable)
54
+ @callable = name_or_callable
55
+ @name = name_or_callable.name
56
+ else
57
+ @callable = nil
58
+ @name = name_or_callable
59
+ end
49
60
  @args = args
50
61
  @keywords = keywords
51
62
  @splat = splat
@@ -56,8 +67,7 @@ module Sass::Script::Tree
56
67
  # @return [String] A string representation of the function call
57
68
  def inspect
58
69
  args = @args.map {|a| a.inspect}.join(', ')
59
- keywords = Sass::Util.hash_to_a(@keywords.as_stored).
60
- map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
70
+ keywords = @keywords.as_stored.to_a.map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
61
71
  # rubocop:disable RedundantSelf
62
72
  if self.splat
63
73
  splat = args.empty? && keywords.empty? ? "" : ", "
@@ -77,8 +87,7 @@ module Sass::Script::Tree
77
87
  end
78
88
 
79
89
  args = @args.map(&arg_to_sass)
80
- keywords = Sass::Util.hash_to_a(@keywords.as_stored).
81
- map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}
90
+ keywords = @keywords.as_stored.to_a.map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}
82
91
 
83
92
  # rubocop:disable RedundantSelf
84
93
  if self.splat
@@ -120,27 +129,31 @@ module Sass::Script::Tree
120
129
  # @return [Sass::Script::Value] The SassScript object that is the value of the function call
121
130
  # @raise [Sass::SyntaxError] if the function call raises an ArgumentError
122
131
  def _perform(environment)
123
- args = Sass::Util.enum_with_index(@args).
132
+ args = @args.each_with_index.
124
133
  map {|a, i| perform_arg(a, environment, signature && signature.args[i])}
125
134
  keywords = Sass::Util.map_hash(@keywords) do |k, v|
126
135
  [k, perform_arg(v, environment, k.tr('-', '_'))]
127
136
  end
128
137
  splat = Sass::Tree::Visitors::Perform.perform_splat(
129
138
  @splat, keywords, @kwarg_splat, environment)
130
- if (fn = environment.function(@name))
131
- css_variable_warning.warn! if css_variable_warning
132
- return without_original(perform_sass_fn(fn, args, splat, environment))
139
+
140
+ fn = @callable || environment.function(@name)
141
+
142
+ if fn && fn.origin == :stylesheet
143
+ environment.stack.with_function(filename, line, name) do
144
+ return without_original(perform_sass_fn(fn, args, splat, environment))
145
+ end
133
146
  end
134
147
 
135
148
  args = construct_ruby_args(ruby_name, args, splat, environment)
136
149
 
137
- if Sass::Script::Functions.callable?(ruby_name)
138
- css_variable_warning.warn! if css_variable_warning
139
-
150
+ if Sass::Script::Functions.callable?(ruby_name) && (!fn || fn.origin == :builtin)
140
151
  local_environment = Sass::Environment.new(environment.global_env, environment.options)
141
152
  local_environment.caller = Sass::ReadOnlyEnvironment.new(environment, environment.options)
142
- result = opts(Sass::Script::Functions::EvaluationContext.new(
143
- local_environment).send(ruby_name, *args))
153
+ result = local_environment.stack.with_function(filename, line, name) do
154
+ opts(Sass::Script::Functions::EvaluationContext.new(
155
+ local_environment).send(ruby_name, *args))
156
+ end
144
157
  without_original(result)
145
158
  else
146
159
  opts(to_literal(args))
@@ -206,6 +219,7 @@ module Sass::Script::Tree
206
219
  raise Sass::SyntaxError.new(
207
220
  "#{args[signature.args.size].inspect} is not a keyword argument for `#{name}'")
208
221
  elsif keywords.empty?
222
+ args << {} if signature.var_kwargs
209
223
  return args
210
224
  end
211
225
 
@@ -271,30 +285,21 @@ module Sass::Script::Tree
271
285
  message = "wrong number of arguments (#{given} for #{expected})"
272
286
  end
273
287
  elsif Sass::Util.jruby?
274
- if Sass::Util.jruby1_6?
275
- should_maybe_raise = e.message =~ /^wrong number of arguments \((\d+) for (\d+)\)/ &&
276
- # The one case where JRuby does include the Ruby name of the function
277
- # is manually-thrown ArgumentErrors, which are indistinguishable from
278
- # legitimate ArgumentErrors. We treat both of these as
279
- # Sass::SyntaxErrors even though it can hide Ruby errors.
280
- e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
281
- else
282
- should_maybe_raise =
283
- e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for (\d+)\)/
284
- given, expected = $1, $2
285
- end
288
+ should_maybe_raise =
289
+ e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for (\d+)\)/
290
+ given, expected = $1, $2
286
291
 
287
292
  if should_maybe_raise
288
293
  # JRuby 1.7 includes __send__ before send and _perform.
289
294
  trace = e.backtrace.dup
290
- raise e if !Sass::Util.jruby1_6? && trace.shift !~ /:in `__send__'$/
295
+ raise e if trace.shift !~ /:in `__send__'$/
291
296
 
292
297
  # JRuby (as of 1.7.2) doesn't put the actual method
293
298
  # for which the argument error was thrown in the backtrace, so we
294
299
  # detect whether our send threw an argument error.
295
300
  if !(trace[0] =~ /:in `send'$/ && trace[1] =~ /:in `_perform'$/)
296
301
  raise e
297
- elsif !Sass::Util.jruby1_6?
302
+ else
298
303
  # JRuby 1.7 doesn't use standard formatting for its ArgumentErrors.
299
304
  message = "wrong number of arguments (#{given} for #{expected})"
300
305
  end