sass 3.4.25 → 3.5.0.pre.rc.1

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