sass 3.3.0.alpha.149 → 3.3.0.alpha.162

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 (71) hide show
  1. data/REVISION +1 -1
  2. data/VERSION +1 -1
  3. data/VERSION_DATE +1 -1
  4. data/lib/sass/css.rb +1 -1
  5. data/lib/sass/engine.rb +4 -4
  6. data/lib/sass/environment.rb +1 -1
  7. data/lib/sass/exec.rb +1 -1
  8. data/lib/sass/media.rb +15 -15
  9. data/lib/sass/script.rb +32 -7
  10. data/lib/sass/script/css_lexer.rb +2 -2
  11. data/lib/sass/script/css_parser.rb +1 -1
  12. data/lib/sass/script/functions.rb +246 -232
  13. data/lib/sass/script/lexer.rb +24 -32
  14. data/lib/sass/script/parser.rb +84 -65
  15. data/lib/sass/script/tree.rb +14 -0
  16. data/lib/sass/script/tree/funcall.rb +242 -0
  17. data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +30 -13
  18. data/lib/sass/script/tree/list_literal.rb +65 -0
  19. data/lib/sass/script/tree/literal.rb +46 -0
  20. data/lib/sass/script/{node.rb → tree/node.rb} +10 -10
  21. data/lib/sass/script/{operation.rb → tree/operation.rb} +16 -27
  22. data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +4 -4
  23. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +7 -8
  24. data/lib/sass/script/tree/variable.rb +56 -0
  25. data/lib/sass/script/value.rb +10 -0
  26. data/lib/sass/script/{arg_list.rb → value/arg_list.rb} +5 -20
  27. data/lib/sass/script/value/base.rb +222 -0
  28. data/lib/sass/script/{bool.rb → value/bool.rb} +2 -2
  29. data/lib/sass/script/{color.rb → value/color.rb} +22 -20
  30. data/lib/sass/script/{list.rb → value/list.rb} +15 -28
  31. data/lib/sass/script/{null.rb → value/null.rb} +3 -3
  32. data/lib/sass/script/{number.rb → value/number.rb} +19 -19
  33. data/lib/sass/script/{string.rb → value/string.rb} +7 -7
  34. data/lib/sass/scss/parser.rb +14 -4
  35. data/lib/sass/selector.rb +26 -26
  36. data/lib/sass/selector/abstract_sequence.rb +1 -1
  37. data/lib/sass/selector/simple.rb +6 -7
  38. data/lib/sass/source/position.rb +13 -0
  39. data/lib/sass/supports.rb +4 -4
  40. data/lib/sass/tree/comment_node.rb +3 -3
  41. data/lib/sass/tree/css_import_node.rb +7 -7
  42. data/lib/sass/tree/debug_node.rb +2 -2
  43. data/lib/sass/tree/directive_node.rb +2 -2
  44. data/lib/sass/tree/each_node.rb +2 -2
  45. data/lib/sass/tree/extend_node.rb +4 -4
  46. data/lib/sass/tree/for_node.rb +4 -4
  47. data/lib/sass/tree/function_node.rb +4 -4
  48. data/lib/sass/tree/media_node.rb +3 -3
  49. data/lib/sass/tree/mixin_def_node.rb +4 -4
  50. data/lib/sass/tree/mixin_node.rb +6 -6
  51. data/lib/sass/tree/prop_node.rb +23 -15
  52. data/lib/sass/tree/return_node.rb +2 -2
  53. data/lib/sass/tree/rule_node.rb +3 -3
  54. data/lib/sass/tree/variable_node.rb +2 -2
  55. data/lib/sass/tree/visitors/convert.rb +2 -2
  56. data/lib/sass/tree/visitors/deep_copy.rb +5 -5
  57. data/lib/sass/tree/visitors/perform.rb +7 -7
  58. data/lib/sass/tree/visitors/set_options.rb +6 -6
  59. data/lib/sass/tree/visitors/to_css.rb +1 -1
  60. data/lib/sass/tree/warn_node.rb +2 -2
  61. data/lib/sass/tree/while_node.rb +2 -2
  62. data/lib/sass/util.rb +2 -2
  63. data/test/sass/engine_test.rb +6 -6
  64. data/test/sass/functions_test.rb +20 -20
  65. data/test/sass/plugin_test.rb +2 -2
  66. data/test/sass/script_test.rb +38 -29
  67. data/test/test_helper.rb +1 -1
  68. metadata +23 -19
  69. data/lib/sass/script/funcall.rb +0 -238
  70. data/lib/sass/script/literal.rb +0 -221
  71. data/lib/sass/script/variable.rb +0 -58
@@ -16,26 +16,29 @@ module Sass
16
16
  # `value`: \[`Object`\]
17
17
  # : The Ruby object corresponding to the value of the token.
18
18
  #
19
- # `line`: \[`Fixnum`\]
20
- # : The line of the source file on which the token appears (1-based).
21
- #
22
- # `offset`: \[`Fixnum`\]
23
- # : The number of characters into the line the SassScript token appeared (1-based).
19
+ # `source_range`: [`Sass::Source::Range`\]
20
+ # : The range in the source file in which the token appeared.
24
21
  #
25
22
  # `pos`: \[`Fixnum`\]
26
23
  # : The scanner position at which the SassScript token appeared.
27
- Token = Struct.new(:type, :value, :line, :offset, :pos)
24
+ Token = Struct.new(:type, :value, :source_range, :pos)
28
25
 
29
26
  # The line number of the lexer's current position.
30
27
  #
31
28
  # @return [Fixnum]
32
- attr_reader :line
29
+ def line
30
+ return @line unless @tok
31
+ @tok.source_range.start_pos.line
32
+ end
33
33
 
34
34
  # The number of bytes into the current line
35
35
  # of the lexer's current position (1-based).
36
36
  #
37
37
  # @return [Fixnum]
38
- attr_reader :offset
38
+ def offset
39
+ return @offset unless @tok
40
+ @tok.source_range.start_pos.offset
41
+ end
39
42
 
40
43
  # A hash from operator strings to the corresponding token types.
41
44
  OPERATORS = {
@@ -174,8 +177,8 @@ module Sass
174
177
  def unpeek!
175
178
  if @tok
176
179
  @scanner.pos = @tok.pos
177
- @line = @tok.line
178
- @offset = @tok.offset
180
+ @line = @tok.source_range.start_pos.line
181
+ @offset = @tok.source_range.start_pos.offset
179
182
  end
180
183
  end
181
184
 
@@ -219,12 +222,11 @@ module Sass
219
222
 
220
223
  def read_token
221
224
  return if done?
225
+ start_pos = source_position
226
+ start_index = @scanner.pos
222
227
  return unless value = token
223
- type, val, size = value
224
- size ||= @scanner.matched_size
225
-
226
- val.line = @line if val.is_a?(Script::Node)
227
- Token.new(type, val, @line, @offset - size, @scanner.pos - size)
228
+ type, val = value
229
+ Token.new(type, val, range(start_pos), @scanner.pos - @scanner.matched_size)
228
230
  end
229
231
 
230
232
  def whitespace
@@ -259,7 +261,6 @@ module Sass
259
261
  end
260
262
 
261
263
  def string(re, open)
262
- start_pos = source_position
263
264
  return unless scan(STRING_REGULAR_EXPRESSIONS[[re, open]])
264
265
  if @scanner[2] == '#{' #'
265
266
  @scanner.pos -= 2 # Don't actually consume the #{
@@ -268,50 +269,41 @@ module Sass
268
269
  end
269
270
  str =
270
271
  if re == :uri
271
- Script::String.new("#{'url(' unless open}#{@scanner[1]}#{')' unless @scanner[2] == '#{'}")
272
+ Script::Value::String.new("#{'url(' unless open}#{@scanner[1]}#{')' unless @scanner[2] == '#{'}")
272
273
  else
273
- Script::String.new(@scanner[1].gsub(/\\(['"]|\#\{)/, '\1'), :string)
274
+ Script::Value::String.new(@scanner[1].gsub(/\\(['"]|\#\{)/, '\1'), :string)
274
275
  end
275
- str.source_range = range(start_pos)
276
276
  [:string, str]
277
277
  end
278
278
 
279
279
  def number
280
- start_pos = source_position
281
280
  return unless scan(REGULAR_EXPRESSIONS[:number])
282
281
  value = @scanner[2] ? @scanner[2].to_f : @scanner[3].to_i
283
282
  value = -value if @scanner[1]
284
- script_number = Script::Number.new(value, Array(@scanner[4]))
285
- script_number.source_range = range(start_pos)
283
+ script_number = Script::Value::Number.new(value, Array(@scanner[4]))
286
284
  [:number, script_number]
287
285
  end
288
286
 
289
287
  def color
290
- start_pos = source_position
291
288
  return unless s = scan(REGULAR_EXPRESSIONS[:color])
292
289
  raise Sass::SyntaxError.new(<<MESSAGE.rstrip) unless s.size == 4 || s.size == 7
293
290
  Colors must have either three or six digits: '#{s}'
294
291
  MESSAGE
295
292
  value = s.scan(/^#(..?)(..?)(..?)$/).first.
296
293
  map {|num| num.ljust(2, num).to_i(16)}
297
- script_color = Script::Color.new(value)
298
- script_color.source_range = range(start_pos)
294
+ script_color = Script::Value::Color.new(value)
299
295
  [:color, script_color]
300
296
  end
301
297
 
302
298
  def bool
303
- start_pos = source_position
304
299
  return unless s = scan(REGULAR_EXPRESSIONS[:bool])
305
- script_bool = Script::Bool.new(s == 'true')
306
- script_bool.source_range = range(start_pos)
300
+ script_bool = Script::Value::Bool.new(s == 'true')
307
301
  [:bool, script_bool]
308
302
  end
309
303
 
310
304
  def null
311
- start_pos = source_position
312
305
  return unless scan(REGULAR_EXPRESSIONS[:null])
313
- script_null = Script::Null.new
314
- script_null.source_range = range(start_pos)
306
+ script_null = Script::Value::Null.new
315
307
  [:null, script_null]
316
308
  end
317
309
 
@@ -331,7 +323,7 @@ MESSAGE
331
323
 
332
324
  def special_val
333
325
  return unless scan(/!important/i)
334
- [:string, Script::String.new("!important")]
326
+ [:string, Script::Value::String.new("!important")]
335
327
  end
336
328
 
337
329
  def ident_op
@@ -3,7 +3,7 @@ require 'sass/script/lexer'
3
3
  module Sass
4
4
  module Script
5
5
  # The parser for SassScript.
6
- # It parses a string of code into a tree of {Script::Node}s.
6
+ # It parses a string of code into a tree of {Script::Tree::Node}s.
7
7
  class Parser
8
8
  # The line number of the parser's current position.
9
9
  #
@@ -36,14 +36,12 @@ module Sass
36
36
  # which signals the end of an interpolated segment,
37
37
  # it returns rather than throwing an error.
38
38
  #
39
- # @return [Script::Node] The root node of the parse tree
39
+ # @return [Script::Tree::Node] The root node of the parse tree
40
40
  # @raise [Sass::SyntaxError] if the expression isn't valid SassScript
41
41
  def parse_interpolated
42
- start_pos = source_position
43
42
  expr = assert_expr :expr
44
43
  assert_tok :end_interpolation
45
44
  expr.options = @options
46
- expr.source_range = range(start_pos)
47
45
  expr
48
46
  rescue Sass::SyntaxError => e
49
47
  e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
@@ -52,14 +50,12 @@ module Sass
52
50
 
53
51
  # Parses a SassScript expression.
54
52
  #
55
- # @return [Script::Node] The root node of the parse tree
53
+ # @return [Script::Tree::Node] The root node of the parse tree
56
54
  # @raise [Sass::SyntaxError] if the expression isn't valid SassScript
57
55
  def parse
58
- start_pos = source_position
59
56
  expr = assert_expr :expr
60
57
  assert_done
61
58
  expr.options = @options
62
- expr.source_range = range(start_pos)
63
59
  expr
64
60
  rescue Sass::SyntaxError => e
65
61
  e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
@@ -70,7 +66,7 @@ module Sass
70
66
  # ending it when it encounters one of the given identifier tokens.
71
67
  #
72
68
  # @param [#include?(String)] A set of strings that delimit the expression.
73
- # @return [Script::Node] The root node of the parse tree
69
+ # @return [Script::Tree::Node] The root node of the parse tree
74
70
  # @raise [Sass::SyntaxError] if the expression isn't valid SassScript
75
71
  def parse_until(tokens)
76
72
  @stop_at = tokens
@@ -85,7 +81,7 @@ module Sass
85
81
 
86
82
  # Parses the argument list for a mixin include.
87
83
  #
88
- # @return [(Array<Script::Node>, {String => Script::Node}, Script::Node)]
84
+ # @return [(Array<Script::Tree::Node>, {String => Script::Tree::Node}, Script::Tree::Node)]
89
85
  # The root nodes of the positional arguments, keyword arguments, and
90
86
  # splat argument. Keyword arguments are in a hash from names to values.
91
87
  # @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
@@ -108,7 +104,7 @@ module Sass
108
104
 
109
105
  # Parses the argument list for a mixin definition.
110
106
  #
111
- # @return [(Array<Script::Node>, Script::Node)]
107
+ # @return [(Array<Script::Tree::Node>, Script::Tree::Node)]
112
108
  # The root nodes of the arguments, and the splat argument.
113
109
  # @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
114
110
  def parse_mixin_definition_arglist
@@ -128,7 +124,7 @@ module Sass
128
124
 
129
125
  # Parses the argument list for a function definition.
130
126
  #
131
- # @return [(Array<Script::Node>, Script::Node)]
127
+ # @return [(Array<Script::Tree::Node>, Script::Tree::Node)]
132
128
  # The root nodes of the arguments, and the splat argument.
133
129
  # @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
134
130
  def parse_function_definition_arglist
@@ -149,7 +145,7 @@ module Sass
149
145
  # Parse a single string value, possibly containing interpolation.
150
146
  # Doesn't assert that the scanner is finished after parsing.
151
147
  #
152
- # @return [Script::Node] The root node of the parse tree.
148
+ # @return [Script::Tree::Node] The root node of the parse tree.
153
149
  # @raise [Sass::SyntaxError] if the string isn't valid SassScript
154
150
  def parse_string
155
151
  unless (peek = @lexer.peek) &&
@@ -170,7 +166,7 @@ module Sass
170
166
  # Parses a SassScript expression.
171
167
  #
172
168
  # @overload parse(str, line, offset, filename = nil)
173
- # @return [Script::Node] The root node of the parse tree
169
+ # @return [Script::Tree::Node] The root node of the parse tree
174
170
  # @see Parser#initialize
175
171
  # @see Parser#parse
176
172
  def self.parse(*args)
@@ -225,9 +221,7 @@ module Sass
225
221
  end
226
222
 
227
223
  start_pos = source_position
228
- e = Operation.new(e, assert_expr(#{sub.inspect}), tok.type)
229
- e.line = start_pos.line
230
- e.source_range = range(start_pos)
224
+ e = node(Tree::Operation.new(e, assert_expr(#{sub.inspect}), tok.type), start_pos)
231
225
  end
232
226
  e
233
227
  end
@@ -239,10 +233,8 @@ RUBY
239
233
  def unary_#{op}
240
234
  return #{sub} unless tok = try_tok(:#{op})
241
235
  interp = try_op_before_interp(tok) and return interp
242
- line = @lexer.line
243
- op = UnaryOperation.new(assert_expr(:unary_#{op}), :#{op})
244
- op.line = line
245
- op
236
+ start_pos = source_position
237
+ node(Tree::UnaryOperation.new(assert_expr(:unary_#{op}), :#{op}), start_pos)
246
238
  end
247
239
  RUBY
248
240
  end
@@ -254,10 +246,6 @@ RUBY
254
246
  Sass::Source::Position.new(line, offset)
255
247
  end
256
248
 
257
- def token_start_position(token)
258
- Sass::Source::Position.new(token.line, token.offset)
259
- end
260
-
261
249
  def range(start_pos, end_pos=source_position)
262
250
  Sass::Source::Range.new(start_pos, end_pos, @options[:filename], @options[:importer])
263
251
  end
@@ -269,15 +257,15 @@ RUBY
269
257
  interp = try_ops_after_interp([:comma], :expr) and return interp
270
258
  start_pos = source_position
271
259
  return unless e = interpolation
272
- list = node(List.new([e], :comma), start_pos)
260
+ list = node(Sass::Script::Tree::ListLiteral.new([e], :comma), start_pos)
273
261
  while tok = try_tok(:comma)
274
262
  if interp = try_op_before_interp(tok, list)
275
263
  return interp unless other_interp = try_ops_after_interp([:comma], :expr, interp)
276
264
  return other_interp
277
265
  end
278
- list.value << assert_expr(:interpolation)
266
+ list.elements << assert_expr(:interpolation)
279
267
  end
280
- list.value.size == 1 ? list.value.first : list
268
+ list.elements.size == 1 ? list.elements.first : list
281
269
  end
282
270
 
283
271
  production :equals, :interpolation, :single_eq
@@ -285,10 +273,10 @@ RUBY
285
273
  def try_op_before_interp(op, prev = nil)
286
274
  return unless @lexer.peek && @lexer.peek.type == :begin_interpolation
287
275
  wb = @lexer.whitespace?(op)
288
- str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
289
- str.line = @lexer.line
290
- interp = Script::Interpolation.new(prev, str, nil, wb, !:wa, :originally_text)
291
- interp.line = @lexer.line
276
+ str = literal_node(Script::Value::String.new(Lexer::OPERATORS_REVERSE[op.type]), op.source_range)
277
+ interp = node(
278
+ Script::Tree::Interpolation.new(prev, str, nil, wb, !:wa, :originally_text),
279
+ (prev || str).source_range.start_pos)
292
280
  interpolation(interp)
293
281
  end
294
282
 
@@ -298,12 +286,11 @@ RUBY
298
286
  interp = try_op_before_interp(op, prev) and return interp
299
287
 
300
288
  wa = @lexer.whitespace?
301
- str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
289
+ str = literal_node(Script::Value::String.new(Lexer::OPERATORS_REVERSE[op.type]), op.source_range)
302
290
  str.line = @lexer.line
303
- start_pos = source_position
304
- interp = Script::Interpolation.new(prev, str, assert_expr(name), !:wb, wa, :originally_text)
305
- interp.line = @lexer.line
306
- interp.source_range = range(start_pos)
291
+ interp = node(
292
+ Script::Tree::Interpolation.new(prev, str, assert_expr(name), !:wb, wa, :originally_text),
293
+ (prev || str).source_range.start_pos)
307
294
  return interp
308
295
  end
309
296
 
@@ -314,8 +301,9 @@ RUBY
314
301
  line = @lexer.line
315
302
  mid = parse_interpolated
316
303
  wa = @lexer.whitespace?
317
- e = Script::Interpolation.new(e, mid, space, wb, wa)
318
- e.line = line
304
+ e = node(
305
+ Script::Tree::Interpolation.new(e, mid, space, wb, wa),
306
+ (e || mid).source_range.start_pos)
319
307
  end
320
308
  e
321
309
  end
@@ -327,7 +315,7 @@ RUBY
327
315
  while e = or_expr
328
316
  arr << e
329
317
  end
330
- arr.size == 1 ? arr.first : node(List.new(arr, :space), start_pos)
318
+ arr.size == 1 ? arr.first : node(Sass::Script::Tree::ListLiteral.new(arr, :space), start_pos)
331
319
  end
332
320
 
333
321
  production :or_expr, :and_expr, :or
@@ -347,17 +335,18 @@ RUBY
347
335
  return if @stop_at && @stop_at.include?(@lexer.peek.value)
348
336
 
349
337
  name = @lexer.next
350
- if color = Color::COLOR_NAMES[name.value.downcase]
351
- return node(Color.new(color), token_start_position(name), source_position)
338
+ if color = Sass::Script::Value::Color::COLOR_NAMES[name.value.downcase]
339
+ return literal_node(Sass::Script::Value::Color.new(color), name.source_range)
352
340
  end
353
- node(Script::String.new(name.value, :identifier), token_start_position(name), source_position)
341
+ literal_node(Script::Value::String.new(name.value, :identifier), name.source_range)
354
342
  end
355
343
 
356
344
  def funcall
357
345
  return raw unless tok = try_tok(:funcall)
358
346
  args, keywords, splat = fn_arglist || [[], {}]
359
347
  assert_tok(:rparen)
360
- node(Script::Funcall.new(tok.value, args, keywords, splat), token_start_position(tok), source_position)
348
+ node(Script::Tree::Funcall.new(tok.value, args, keywords, splat),
349
+ tok.source_range.start_pos, source_position)
361
350
  end
362
351
 
363
352
  def defn_arglist!(must_have_parens)
@@ -373,8 +362,7 @@ RUBY
373
362
  must_have_default = false
374
363
  loop do
375
364
  c = assert_tok(:const)
376
- var = Script::Variable.new(c.value)
377
- var.source_range = range(c.offset)
365
+ var = node(Script::Tree::Variable.new(c.value), c.source_range)
378
366
  if try_tok(:colon)
379
367
  val = assert_expr(:space)
380
368
  must_have_default = true
@@ -407,7 +395,7 @@ RUBY
407
395
  loop do
408
396
  if @lexer.peek && @lexer.peek.type == :colon
409
397
  name = e
410
- @lexer.expected!("comma") unless name.is_a?(Variable)
398
+ @lexer.expected!("comma") unless name.is_a?(Tree::Variable)
411
399
  assert_tok(:colon)
412
400
  value = assert_expr(subexpr, description)
413
401
 
@@ -431,17 +419,26 @@ RUBY
431
419
  end
432
420
 
433
421
  def raw
422
+ start_pos = source_position
434
423
  return special_fun unless tok = try_tok(:raw)
435
- node(Script::String.new(tok.value))
424
+ literal_node(Script::Value::String.new(tok.value), tok.source_range)
436
425
  end
437
426
 
438
427
  def special_fun
428
+ start_pos = source_position
439
429
  return paren unless tok = try_tok(:special_fun)
440
- first = node(Script::String.new(tok.value.first))
430
+ first = literal_node(Script::Value::String.new(tok.value.first),
431
+ start_pos, start_pos.after(tok.value.first))
441
432
  Sass::Util.enum_slice(tok.value[1..-1], 2).inject(first) do |l, (i, r)|
442
- Script::Interpolation.new(
443
- l, i, r && node(Script::String.new(r)),
444
- false, false)
433
+ end_pos = i.source_range.end_pos
434
+ end_pos = end_pos.after(r) if r
435
+ node(
436
+ Script::Tree::Interpolation.new(
437
+ l, i,
438
+ r && literal_node(Script::Value::String.new(r),
439
+ i.source_range.end_pos, end_pos),
440
+ false, false),
441
+ start_pos, end_pos)
445
442
  end
446
443
  end
447
444
 
@@ -451,8 +448,9 @@ RUBY
451
448
  @in_parens = true
452
449
  start_pos = source_position
453
450
  e = expr
451
+ end_pos = source_position
454
452
  assert_tok(:rparen)
455
- return e || node(List.new([], :space), start_pos)
453
+ return e || node(Sass::Script::Tree::ListLiteral.new([], :space), start_pos, end_pos)
456
454
  ensure
457
455
  @in_parens = was_in_parens
458
456
  end
@@ -460,31 +458,27 @@ RUBY
460
458
  def variable
461
459
  start_pos = source_position
462
460
  return string unless c = try_tok(:const)
463
- node(Variable.new(*c.value), start_pos, source_position)
461
+ node(Tree::Variable.new(*c.value), start_pos)
464
462
  end
465
463
 
466
464
  def string
467
465
  return number unless first = try_tok(:string)
468
- return first.value unless try_tok(:begin_interpolation)
469
- start_pos = source_position
470
- line = @lexer.line
466
+ str = literal_node(first.value, first.source_range)
467
+ return str unless try_tok(:begin_interpolation)
471
468
  mid = parse_interpolated
472
469
  last = assert_expr(:string)
473
- interp = StringInterpolation.new(first.value, mid, last)
474
- interp.line = line
475
- interp.source_range = range(start_pos)
476
- interp
470
+ node(Tree::StringInterpolation.new(str, mid, last), first.source_range.start_pos)
477
471
  end
478
472
 
479
473
  def number
480
474
  return literal unless tok = try_tok(:number)
481
475
  num = tok.value
482
476
  num.original = num.to_s unless @in_parens
483
- num
477
+ literal_node(num, tok.source_range.start_pos)
484
478
  end
485
479
 
486
480
  def literal
487
- (t = try_tok(:color, :bool, :null)) && (return t.value)
481
+ (t = try_tok(:color, :bool, :null)) && (return literal_node(t.value, t.source_range))
488
482
  end
489
483
 
490
484
  # It would be possible to have unified #assert and #try methods,
@@ -517,10 +511,35 @@ RUBY
517
511
  @lexer.expected!(EXPR_NAMES[:default])
518
512
  end
519
513
 
520
- def node(node, start_pos = source_position, end_pos = nil)
521
- node.line = start_pos.line
514
+ # @overload node(value, source_range)
515
+ # @param value [Sass::Script::Value::Base]
516
+ # @param source_range [Sass::Source::Range]
517
+ # @overload node(value, start_pos, end_pos = source_position)
518
+ # @param value [Sass::Script::Value::Base]
519
+ # @param start_pos [Sass::Source::Position]
520
+ # @param end_pos [Sass::Source::Position]
521
+ def literal_node(value, source_range_or_start_pos, end_pos = source_position)
522
+ node(Sass::Script::Tree::Literal.new(value), source_range_or_start_pos, end_pos)
523
+ end
524
+
525
+ # @overload node(node, source_range)
526
+ # @param node [Sass::Script::Tree::Node]
527
+ # @param source_range [Sass::Source::Range]
528
+ # @overload node(node, start_pos, end_pos = source_position)
529
+ # @param node [Sass::Script::Tree::Node]
530
+ # @param start_pos [Sass::Source::Position]
531
+ # @param end_pos [Sass::Source::Position]
532
+ def node(node, source_range_or_start_pos, end_pos = source_position)
533
+ source_range =
534
+ if source_range_or_start_pos.is_a?(Sass::Source::Range)
535
+ source_range_or_start_pos
536
+ else
537
+ range(source_range_or_start_pos, end_pos)
538
+ end
539
+
540
+ node.line = source_range.start_pos.line
541
+ node.source_range = source_range
522
542
  node.filename = @options[:filename]
523
- node.source_range = range(start_pos, end_pos) if end_pos
524
543
  node
525
544
  end
526
545
  end