sass 3.4.25 → 3.7.4
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.
- checksums.yaml +4 -4
- data/CODE_OF_CONDUCT.md +1 -1
- data/CONTRIBUTING.md +3 -3
- data/README.md +17 -9
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/VERSION_NAME +1 -1
- data/extra/sass-spec-ref.sh +9 -1
- data/lib/sass.rb +0 -7
- data/lib/sass/cache_stores/filesystem.rb +1 -1
- data/lib/sass/css.rb +1 -2
- data/lib/sass/engine.rb +39 -29
- data/lib/sass/environment.rb +26 -5
- data/lib/sass/error.rb +2 -2
- data/lib/sass/exec/base.rb +2 -13
- data/lib/sass/exec/sass_scss.rb +1 -5
- data/lib/sass/features.rb +1 -0
- data/lib/sass/importers/filesystem.rb +6 -4
- data/lib/sass/logger/base.rb +11 -0
- data/lib/sass/plugin/compiler.rb +20 -50
- data/lib/sass/plugin/configuration.rb +2 -2
- data/lib/sass/railtie.rb +1 -1
- data/lib/sass/script/css_parser.rb +4 -1
- data/lib/sass/script/functions.rb +308 -81
- data/lib/sass/script/lexer.rb +63 -9
- data/lib/sass/script/parser.rb +287 -118
- data/lib/sass/script/tree/funcall.rb +35 -34
- data/lib/sass/script/tree/interpolation.rb +0 -3
- data/lib/sass/script/tree/list_literal.rb +23 -8
- data/lib/sass/script/tree/map_literal.rb +2 -2
- data/lib/sass/script/tree/node.rb +0 -8
- data/lib/sass/script/tree/operation.rb +1 -8
- data/lib/sass/script/value.rb +2 -0
- data/lib/sass/script/value/arg_list.rb +1 -1
- data/lib/sass/script/value/base.rb +17 -0
- data/lib/sass/script/value/callable.rb +25 -0
- data/lib/sass/script/value/color.rb +8 -2
- data/lib/sass/script/value/function.rb +19 -0
- data/lib/sass/script/value/helpers.rb +37 -11
- data/lib/sass/script/value/list.rb +35 -14
- data/lib/sass/script/value/map.rb +2 -2
- data/lib/sass/script/value/number.rb +3 -2
- data/lib/sass/scss/css_parser.rb +6 -1
- data/lib/sass/scss/parser.rb +145 -56
- data/lib/sass/scss/rx.rb +5 -11
- data/lib/sass/scss/static_parser.rb +20 -42
- data/lib/sass/selector.rb +4 -0
- data/lib/sass/selector/abstract_sequence.rb +7 -6
- data/lib/sass/selector/comma_sequence.rb +9 -5
- data/lib/sass/selector/pseudo.rb +20 -3
- data/lib/sass/selector/sequence.rb +35 -10
- data/lib/sass/selector/simple.rb +9 -2
- data/lib/sass/selector/simple_sequence.rb +8 -4
- data/lib/sass/source/map.rb +2 -6
- data/lib/sass/stack.rb +21 -1
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/prop_node.rb +45 -53
- data/lib/sass/tree/rule_node.rb +6 -8
- data/lib/sass/tree/visitors/check_nesting.rb +1 -1
- data/lib/sass/tree/visitors/convert.rb +2 -3
- data/lib/sass/tree/visitors/cssize.rb +4 -15
- data/lib/sass/tree/visitors/deep_copy.rb +1 -1
- data/lib/sass/tree/visitors/extend.rb +2 -8
- data/lib/sass/tree/visitors/perform.rb +23 -15
- data/lib/sass/tree/visitors/set_options.rb +1 -1
- data/lib/sass/tree/visitors/to_css.rb +49 -22
- data/lib/sass/util.rb +72 -310
- data/lib/sass/util/multibyte_string_scanner.rb +127 -131
- data/lib/sass/util/normalized_map.rb +1 -8
- data/lib/sass/version.rb +0 -4
- metadata +55 -202
- data/Rakefile +0 -453
- data/lib/sass/script/css_variable_warning.rb +0 -52
- data/lib/sass/util/cross_platform_random.rb +0 -19
- data/lib/sass/util/ordered_hash.rb +0 -192
- data/test/sass-spec.yml +0 -3
- data/test/sass/cache_test.rb +0 -131
- data/test/sass/callbacks_test.rb +0 -61
- data/test/sass/compiler_test.rb +0 -236
- data/test/sass/conversion_test.rb +0 -2188
- data/test/sass/css2sass_test.rb +0 -526
- data/test/sass/css_variable_test.rb +0 -132
- data/test/sass/data/hsl-rgb.txt +0 -319
- data/test/sass/encoding_test.rb +0 -219
- data/test/sass/engine_test.rb +0 -3447
- data/test/sass/exec_test.rb +0 -96
- data/test/sass/extend_test.rb +0 -1733
- data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
- data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
- data/test/sass/functions_test.rb +0 -1977
- data/test/sass/importer_test.rb +0 -421
- data/test/sass/logger_test.rb +0 -58
- data/test/sass/mock_importer.rb +0 -49
- data/test/sass/more_results/more1.css +0 -9
- data/test/sass/more_results/more1_with_line_comments.css +0 -26
- data/test/sass/more_results/more_import.css +0 -29
- data/test/sass/more_templates/_more_partial.sass +0 -2
- data/test/sass/more_templates/more1.sass +0 -23
- data/test/sass/more_templates/more_import.sass +0 -11
- data/test/sass/plugin_test.rb +0 -556
- data/test/sass/results/alt.css +0 -4
- data/test/sass/results/basic.css +0 -9
- data/test/sass/results/cached_import_option.css +0 -3
- data/test/sass/results/compact.css +0 -5
- data/test/sass/results/complex.css +0 -86
- data/test/sass/results/compressed.css +0 -1
- data/test/sass/results/expanded.css +0 -19
- data/test/sass/results/filename_fn.css +0 -3
- data/test/sass/results/if.css +0 -3
- data/test/sass/results/import.css +0 -31
- data/test/sass/results/import_charset.css +0 -5
- data/test/sass/results/import_charset_1_8.css +0 -5
- data/test/sass/results/import_charset_ibm866.css +0 -5
- data/test/sass/results/import_content.css +0 -1
- data/test/sass/results/line_numbers.css +0 -49
- data/test/sass/results/mixins.css +0 -95
- data/test/sass/results/multiline.css +0 -24
- data/test/sass/results/nested.css +0 -22
- data/test/sass/results/options.css +0 -1
- data/test/sass/results/parent_ref.css +0 -13
- data/test/sass/results/script.css +0 -16
- data/test/sass/results/scss_import.css +0 -31
- data/test/sass/results/scss_importee.css +0 -2
- data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
- data/test/sass/results/subdir/subdir.css +0 -3
- data/test/sass/results/units.css +0 -11
- data/test/sass/results/warn.css +0 -0
- data/test/sass/results/warn_imported.css +0 -0
- data/test/sass/script_conversion_test.rb +0 -357
- data/test/sass/script_test.rb +0 -1431
- data/test/sass/scss/css_test.rb +0 -1281
- data/test/sass/scss/rx_test.rb +0 -160
- data/test/sass/scss/scss_test.rb +0 -4205
- data/test/sass/scss/test_helper.rb +0 -37
- data/test/sass/source_map_test.rb +0 -1055
- data/test/sass/superselector_test.rb +0 -210
- data/test/sass/templates/_cached_import_option_partial.scss +0 -1
- data/test/sass/templates/_double_import_loop2.sass +0 -1
- data/test/sass/templates/_filename_fn_import.scss +0 -11
- data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
- data/test/sass/templates/_imported_charset_utf8.sass +0 -4
- data/test/sass/templates/_imported_content.sass +0 -3
- data/test/sass/templates/_partial.sass +0 -2
- data/test/sass/templates/_same_name_different_partiality.scss +0 -1
- data/test/sass/templates/alt.sass +0 -16
- data/test/sass/templates/basic.sass +0 -23
- data/test/sass/templates/bork1.sass +0 -2
- data/test/sass/templates/bork2.sass +0 -2
- data/test/sass/templates/bork3.sass +0 -2
- data/test/sass/templates/bork4.sass +0 -2
- data/test/sass/templates/bork5.sass +0 -3
- data/test/sass/templates/cached_import_option.scss +0 -3
- data/test/sass/templates/compact.sass +0 -17
- data/test/sass/templates/complex.sass +0 -305
- data/test/sass/templates/compressed.sass +0 -15
- data/test/sass/templates/double_import_loop1.sass +0 -1
- data/test/sass/templates/expanded.sass +0 -17
- data/test/sass/templates/filename_fn.scss +0 -18
- data/test/sass/templates/if.sass +0 -11
- data/test/sass/templates/import.sass +0 -12
- data/test/sass/templates/import_charset.sass +0 -9
- data/test/sass/templates/import_charset_1_8.sass +0 -6
- data/test/sass/templates/import_charset_ibm866.sass +0 -11
- data/test/sass/templates/import_content.sass +0 -4
- data/test/sass/templates/importee.less +0 -2
- data/test/sass/templates/importee.sass +0 -19
- data/test/sass/templates/line_numbers.sass +0 -13
- data/test/sass/templates/mixin_bork.sass +0 -5
- data/test/sass/templates/mixins.sass +0 -76
- data/test/sass/templates/multiline.sass +0 -20
- data/test/sass/templates/nested.sass +0 -25
- data/test/sass/templates/nested_bork1.sass +0 -2
- data/test/sass/templates/nested_bork2.sass +0 -2
- data/test/sass/templates/nested_bork3.sass +0 -2
- data/test/sass/templates/nested_bork4.sass +0 -2
- data/test/sass/templates/nested_import.sass +0 -2
- data/test/sass/templates/nested_mixin_bork.sass +0 -6
- data/test/sass/templates/options.sass +0 -2
- data/test/sass/templates/parent_ref.sass +0 -25
- data/test/sass/templates/same_name_different_ext.sass +0 -2
- data/test/sass/templates/same_name_different_ext.scss +0 -1
- data/test/sass/templates/same_name_different_partiality.scss +0 -1
- data/test/sass/templates/script.sass +0 -101
- data/test/sass/templates/scss_import.scss +0 -12
- data/test/sass/templates/scss_importee.scss +0 -1
- data/test/sass/templates/single_import_loop.sass +0 -1
- data/test/sass/templates/subdir/import_up1.scss +0 -1
- data/test/sass/templates/subdir/import_up2.scss +0 -1
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
- data/test/sass/templates/subdir/subdir.sass +0 -6
- data/test/sass/templates/units.sass +0 -11
- data/test/sass/templates/warn.sass +0 -3
- data/test/sass/templates/warn_imported.sass +0 -4
- data/test/sass/test_helper.rb +0 -8
- data/test/sass/util/multibyte_string_scanner_test.rb +0 -155
- data/test/sass/util/normalized_map_test.rb +0 -51
- data/test/sass/util/subset_map_test.rb +0 -91
- data/test/sass/util_test.rb +0 -438
- data/test/sass/value_helpers_test.rb +0 -179
- data/test/test_helper.rb +0 -110
- data/vendor/listen/CHANGELOG.md +0 -1
- data/vendor/listen/CONTRIBUTING.md +0 -38
- data/vendor/listen/Gemfile +0 -20
- data/vendor/listen/Guardfile +0 -8
- data/vendor/listen/LICENSE +0 -20
- data/vendor/listen/README.md +0 -349
- data/vendor/listen/Rakefile +0 -5
- data/vendor/listen/Vagrantfile +0 -96
- data/vendor/listen/lib/listen.rb +0 -54
- data/vendor/listen/lib/listen/adapter.rb +0 -327
- data/vendor/listen/lib/listen/adapters/bsd.rb +0 -75
- data/vendor/listen/lib/listen/adapters/darwin.rb +0 -48
- data/vendor/listen/lib/listen/adapters/linux.rb +0 -81
- data/vendor/listen/lib/listen/adapters/polling.rb +0 -58
- data/vendor/listen/lib/listen/adapters/windows.rb +0 -91
- data/vendor/listen/lib/listen/directory_record.rb +0 -406
- data/vendor/listen/lib/listen/listener.rb +0 -323
- data/vendor/listen/lib/listen/turnstile.rb +0 -32
- data/vendor/listen/lib/listen/version.rb +0 -3
- data/vendor/listen/listen.gemspec +0 -28
- data/vendor/listen/spec/listen/adapter_spec.rb +0 -149
- data/vendor/listen/spec/listen/adapters/bsd_spec.rb +0 -36
- data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -37
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -47
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
- data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -30
- data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1250
- data/vendor/listen/spec/listen/listener_spec.rb +0 -258
- data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
- data/vendor/listen/spec/listen_spec.rb +0 -67
- data/vendor/listen/spec/spec_helper.rb +0 -25
- data/vendor/listen/spec/support/adapter_helper.rb +0 -666
- data/vendor/listen/spec/support/directory_record_helper.rb +0 -57
- data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
- data/vendor/listen/spec/support/listeners_helper.rb +0 -179
- data/vendor/listen/spec/support/platform_helper.rb +0 -15
data/lib/sass/script/lexer.rb
CHANGED
|
@@ -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,
|
|
@@ -188,6 +190,14 @@ module Sass
|
|
|
188
190
|
@scanner.string[pos, 1]
|
|
189
191
|
end
|
|
190
192
|
|
|
193
|
+
# Consumes and returns single raw character from the input stream.
|
|
194
|
+
#
|
|
195
|
+
# @return [String]
|
|
196
|
+
def next_char
|
|
197
|
+
unpeek!
|
|
198
|
+
scan(/./)
|
|
199
|
+
end
|
|
200
|
+
|
|
191
201
|
# Returns the next token without moving the lexer forward.
|
|
192
202
|
#
|
|
193
203
|
# @return [Token] The next token
|
|
@@ -198,6 +208,7 @@ module Sass
|
|
|
198
208
|
# Rewinds the underlying StringScanner
|
|
199
209
|
# to before the token returned by \{#peek}.
|
|
200
210
|
def unpeek!
|
|
211
|
+
raise "[BUG] Can't unpeek before a queued token!" if @next_tok
|
|
201
212
|
return unless @tok
|
|
202
213
|
@scanner.pos = @tok.pos
|
|
203
214
|
@line = @tok.source_range.start_pos.line
|
|
@@ -241,6 +252,30 @@ module Sass
|
|
|
241
252
|
@scanner.string[old_pos...new_pos]
|
|
242
253
|
end
|
|
243
254
|
|
|
255
|
+
# Runs a block, and rewinds the state of the lexer to the beginning of the
|
|
256
|
+
# block if it returns `nil` or `false`.
|
|
257
|
+
def try
|
|
258
|
+
old_pos = @scanner.pos
|
|
259
|
+
old_line = @line
|
|
260
|
+
old_offset = @offset
|
|
261
|
+
old_interpolation_stack = @interpolation_stack.dup
|
|
262
|
+
old_prev = @prev
|
|
263
|
+
old_tok = @tok
|
|
264
|
+
old_next_tok = @next_tok
|
|
265
|
+
|
|
266
|
+
result = yield
|
|
267
|
+
return result if result
|
|
268
|
+
|
|
269
|
+
@scanner.pos = old_pos
|
|
270
|
+
@line = old_line
|
|
271
|
+
@offset = old_offset
|
|
272
|
+
@interpolation_stack = old_interpolation_stack
|
|
273
|
+
@prev = old_prev
|
|
274
|
+
@tok = old_tok
|
|
275
|
+
@next_tok = old_next_tok
|
|
276
|
+
nil
|
|
277
|
+
end
|
|
278
|
+
|
|
244
279
|
private
|
|
245
280
|
|
|
246
281
|
def read_token
|
|
@@ -264,10 +299,14 @@ module Sass
|
|
|
264
299
|
end
|
|
265
300
|
|
|
266
301
|
def token
|
|
267
|
-
if after_interpolation?
|
|
268
|
-
interp_type, interp_value =
|
|
302
|
+
if after_interpolation?
|
|
303
|
+
interp_type, interp_value = @interpolation_stack.pop
|
|
269
304
|
if interp_type == :special_fun
|
|
270
305
|
return special_fun_body(interp_value)
|
|
306
|
+
elsif interp_type.nil?
|
|
307
|
+
if @scanner.string[@scanner.pos - 1] == '}' && scan(REGULAR_EXPRESSIONS[:ident])
|
|
308
|
+
return [@scanner[2] ? :funcall : :ident, Sass::Util.normalize_ident_escapes(@scanner[1], start: false)]
|
|
309
|
+
end
|
|
271
310
|
else
|
|
272
311
|
raise "[BUG]: Unknown interp_type #{interp_type}" unless interp_type == :string
|
|
273
312
|
return string(interp_value, true)
|
|
@@ -285,13 +324,12 @@ module Sass
|
|
|
285
324
|
|
|
286
325
|
def _variable(rx)
|
|
287
326
|
return unless scan(rx)
|
|
288
|
-
|
|
289
|
-
[:const, @scanner[2]]
|
|
327
|
+
[:const, Sass::Util.normalize_ident_escapes(@scanner[2])]
|
|
290
328
|
end
|
|
291
329
|
|
|
292
330
|
def ident
|
|
293
331
|
return unless scan(REGULAR_EXPRESSIONS[:ident])
|
|
294
|
-
[@scanner[2] ? :funcall : :ident, @scanner[1]]
|
|
332
|
+
[@scanner[2] ? :funcall : :ident, Sass::Util.normalize_ident_escapes(@scanner[1])]
|
|
295
333
|
end
|
|
296
334
|
|
|
297
335
|
def string(re, open)
|
|
@@ -347,7 +385,9 @@ MESSAGE
|
|
|
347
385
|
|
|
348
386
|
value = (@scanner[1] ? @scanner[1].to_f : @scanner[2].to_i) * (minus ? -1 : 1)
|
|
349
387
|
value *= 10**@scanner[3].to_i if @scanner[3]
|
|
350
|
-
|
|
388
|
+
units = @scanner[4]
|
|
389
|
+
units = Sass::Util::normalize_ident_escapes(units) if units
|
|
390
|
+
script_number = Script::Value::Number.new(value, Array(units))
|
|
351
391
|
[:number, script_number]
|
|
352
392
|
end
|
|
353
393
|
|
|
@@ -366,15 +406,20 @@ MESSAGE
|
|
|
366
406
|
# IDs in properties are used in the Basic User Interface Module
|
|
367
407
|
# (http://www.w3.org/TR/css3-ui/).
|
|
368
408
|
return unless scan(REGULAR_EXPRESSIONS[:id])
|
|
369
|
-
if @scanner[0] =~ /^\#[0-9a-fA-F]+$/ &&
|
|
409
|
+
if @scanner[0] =~ /^\#[0-9a-fA-F]+$/ &&
|
|
410
|
+
(@scanner[0].length == 4 || @scanner[0].length == 5 ||
|
|
411
|
+
@scanner[0].length == 7 || @scanner[0].length == 9)
|
|
370
412
|
return [:color, Script::Value::Color.from_hex(@scanner[0])]
|
|
371
413
|
end
|
|
372
|
-
[:ident, @scanner[0]]
|
|
414
|
+
[:ident, Sass::Util.normalize_ident_escapes(@scanner[0])]
|
|
373
415
|
end
|
|
374
416
|
|
|
375
417
|
def color
|
|
376
418
|
return unless @scanner.match?(REGULAR_EXPRESSIONS[:color])
|
|
377
|
-
|
|
419
|
+
unless @scanner[0].length == 4 || @scanner[0].length == 5 ||
|
|
420
|
+
@scanner[0].length == 7 || @scanner[0].length == 9
|
|
421
|
+
return
|
|
422
|
+
end
|
|
378
423
|
script_color = Script::Value::Color.from_hex(scan(REGULAR_EXPRESSIONS[:color]))
|
|
379
424
|
[:color, script_color]
|
|
380
425
|
end
|
|
@@ -382,6 +427,15 @@ MESSAGE
|
|
|
382
427
|
def selector
|
|
383
428
|
start_pos = source_position
|
|
384
429
|
return unless scan(REGULAR_EXPRESSIONS[:selector])
|
|
430
|
+
|
|
431
|
+
if @scanner.peek(1) == '&'
|
|
432
|
+
filename = @options[:filename]
|
|
433
|
+
Sass::Util.sass_warn <<MESSAGE
|
|
434
|
+
WARNING on line #{line}, column #{offset}#{" of #{filename}" if filename}:
|
|
435
|
+
In Sass, "&&" means two copies of the parent selector. You probably want to use "and" instead.
|
|
436
|
+
MESSAGE
|
|
437
|
+
end
|
|
438
|
+
|
|
385
439
|
script_selector = Script::Tree::Selector.new
|
|
386
440
|
script_selector.source_range = range(start_pos)
|
|
387
441
|
[:selector, script_selector]
|
data/lib/sass/script/parser.rb
CHANGED
|
@@ -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
|
|
@@ -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
|
|
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]
|
|
@@ -90,7 +78,7 @@ module Sass
|
|
|
90
78
|
# Parses a SassScript expression,
|
|
91
79
|
# ending it when it encounters one of the given identifier tokens.
|
|
92
80
|
#
|
|
93
|
-
# @param tokens [#include?(String)] A set of strings that delimit the expression.
|
|
81
|
+
# @param tokens [#include?(String | Symbol)] A set of strings or symbols that delimit the expression.
|
|
94
82
|
# @return [Script::Tree::Node] The root node of the parse tree
|
|
95
83
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
|
96
84
|
def parse_until(tokens)
|
|
@@ -127,7 +115,7 @@ module Sass
|
|
|
127
115
|
a.options = @options
|
|
128
116
|
end
|
|
129
117
|
|
|
130
|
-
keywords.each do |
|
|
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(
|
|
239
|
-
|
|
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.
|
|
@@ -284,17 +270,17 @@ module Sass
|
|
|
284
270
|
interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect})
|
|
285
271
|
return interp if interp
|
|
286
272
|
return unless e = #{sub}
|
|
287
|
-
|
|
273
|
+
|
|
274
|
+
while tok = peek_toks(#{ops.map {|o| o.inspect}.join(', ')})
|
|
275
|
+
return e if @stop_at && @stop_at.include?(tok.type)
|
|
276
|
+
@lexer.next
|
|
277
|
+
|
|
288
278
|
if interp = try_op_before_interp(tok, e)
|
|
289
279
|
other_interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}, interp)
|
|
290
280
|
return interp unless other_interp
|
|
291
281
|
return other_interp
|
|
292
282
|
end
|
|
293
283
|
|
|
294
|
-
if @css_variable_warning && !VALID_CSS_OPS.include?(tok.type)
|
|
295
|
-
@css_variable_warning.warn!
|
|
296
|
-
end
|
|
297
|
-
|
|
298
284
|
e = node(Tree::Operation.new(e, assert_expr(#{sub.inspect}), tok.type),
|
|
299
285
|
e.source_range.start_pos)
|
|
300
286
|
end
|
|
@@ -310,8 +296,6 @@ RUBY
|
|
|
310
296
|
interp = try_op_before_interp(tok)
|
|
311
297
|
return interp if interp
|
|
312
298
|
start_pos = source_position
|
|
313
|
-
|
|
314
|
-
@css_variable_warning.warn! if @css_variable_warning
|
|
315
299
|
node(Tree::UnaryOperation.new(assert_expr(:unary_#{op}), :#{op}), start_pos)
|
|
316
300
|
end
|
|
317
301
|
RUBY
|
|
@@ -338,12 +322,12 @@ RUBY
|
|
|
338
322
|
return list e, start_pos unless @lexer.peek && @lexer.peek.type == :colon
|
|
339
323
|
|
|
340
324
|
pair = map_pair(e)
|
|
341
|
-
@css_variable_warning.warn! if @css_variable_warning
|
|
342
325
|
map = node(Sass::Script::Tree::MapLiteral.new([pair]), start_pos)
|
|
343
326
|
while try_tok(:comma)
|
|
344
327
|
pair = map_pair
|
|
345
328
|
return map unless pair
|
|
346
329
|
map.pairs << pair
|
|
330
|
+
map.source_range.end_pos = map.pairs.last.last.source_range.end_pos
|
|
347
331
|
end
|
|
348
332
|
map
|
|
349
333
|
end
|
|
@@ -364,7 +348,7 @@ RUBY
|
|
|
364
348
|
def list(first, start_pos)
|
|
365
349
|
return first unless @lexer.peek && @lexer.peek.type == :comma
|
|
366
350
|
|
|
367
|
-
list = node(Sass::Script::Tree::ListLiteral.new([first], :comma), start_pos)
|
|
351
|
+
list = node(Sass::Script::Tree::ListLiteral.new([first], separator: :comma), start_pos)
|
|
368
352
|
while (tok = try_tok(:comma))
|
|
369
353
|
element_before_interp = list.elements.length == 1 ? list.elements.first : list
|
|
370
354
|
if (interp = try_op_before_interp(tok, element_before_interp))
|
|
@@ -401,13 +385,16 @@ RUBY
|
|
|
401
385
|
Script::Tree::Interpolation.new(
|
|
402
386
|
prev, str, nil, wb, false, :originally_text => true, :deprecation => deprecation),
|
|
403
387
|
(prev || str).source_range.start_pos)
|
|
404
|
-
interpolation(interp)
|
|
388
|
+
interpolation(first: interp)
|
|
405
389
|
end
|
|
406
390
|
|
|
407
391
|
def try_ops_after_interp(ops, name, prev = nil)
|
|
408
392
|
return unless @lexer.after_interpolation?
|
|
409
|
-
op =
|
|
393
|
+
op = peek_toks(*ops)
|
|
410
394
|
return unless op
|
|
395
|
+
return if @stop_at && @stop_at.include?(op.type)
|
|
396
|
+
@lexer.next
|
|
397
|
+
|
|
411
398
|
interp = try_op_before_interp(op, prev, :after_interp)
|
|
412
399
|
return interp if interp
|
|
413
400
|
|
|
@@ -431,17 +418,17 @@ RUBY
|
|
|
431
418
|
interp
|
|
432
419
|
end
|
|
433
420
|
|
|
434
|
-
def interpolation(first
|
|
435
|
-
e = first
|
|
421
|
+
def interpolation(first: nil, inner: :space)
|
|
422
|
+
e = first || send(inner)
|
|
436
423
|
while (interp = try_tok(:begin_interpolation))
|
|
437
424
|
wb = @lexer.whitespace?(interp)
|
|
438
425
|
char_before = @lexer.char(interp.pos - 1)
|
|
439
|
-
mid =
|
|
426
|
+
mid = without_stop_at {assert_expr :expr}
|
|
440
427
|
assert_tok :end_interpolation
|
|
441
428
|
wa = @lexer.whitespace?
|
|
442
429
|
char_after = @lexer.char
|
|
443
430
|
|
|
444
|
-
after =
|
|
431
|
+
after = send(inner)
|
|
445
432
|
before_deprecation = e.is_a?(Script::Tree::Interpolation) ? e.deprecation : :none
|
|
446
433
|
after_deprecation = after.is_a?(Script::Tree::Interpolation) ? after.deprecation : :none
|
|
447
434
|
|
|
@@ -500,7 +487,7 @@ RUBY
|
|
|
500
487
|
if arr.size == 1
|
|
501
488
|
arr.first
|
|
502
489
|
else
|
|
503
|
-
node(Sass::Script::Tree::ListLiteral.new(arr, :space), start_pos)
|
|
490
|
+
node(Sass::Script::Tree::ListLiteral.new(arr, separator: :space), start_pos)
|
|
504
491
|
end
|
|
505
492
|
end
|
|
506
493
|
|
|
@@ -517,7 +504,7 @@ RUBY
|
|
|
517
504
|
unary :not, :ident
|
|
518
505
|
|
|
519
506
|
def ident
|
|
520
|
-
return
|
|
507
|
+
return css_min_max unless @lexer.peek && @lexer.peek.type == :ident
|
|
521
508
|
return if @stop_at && @stop_at.include?(@lexer.peek.value)
|
|
522
509
|
|
|
523
510
|
name = @lexer.next
|
|
@@ -534,6 +521,122 @@ RUBY
|
|
|
534
521
|
end
|
|
535
522
|
end
|
|
536
523
|
|
|
524
|
+
def css_min_max
|
|
525
|
+
@lexer.try do
|
|
526
|
+
next unless tok = try_tok(:funcall)
|
|
527
|
+
next unless %w[min max].include?(tok.value.downcase)
|
|
528
|
+
next unless contents = min_max_contents
|
|
529
|
+
node(array_to_interpolation(["#{tok.value}(", *contents]),
|
|
530
|
+
tok.source_range.start_pos, source_position)
|
|
531
|
+
end || funcall
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
def min_max_contents(allow_comma: true)
|
|
535
|
+
result = []
|
|
536
|
+
loop do
|
|
537
|
+
if tok = try_tok(:number)
|
|
538
|
+
result << tok.value.to_s
|
|
539
|
+
elsif value = min_max_interpolation
|
|
540
|
+
result << value
|
|
541
|
+
elsif value = min_max_calc
|
|
542
|
+
result << value.value
|
|
543
|
+
elsif value = min_max_function ||
|
|
544
|
+
min_max_parens ||
|
|
545
|
+
nested_min_max
|
|
546
|
+
result.concat value
|
|
547
|
+
else
|
|
548
|
+
return
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
if try_tok(:rparen)
|
|
552
|
+
result << ")"
|
|
553
|
+
return result
|
|
554
|
+
elsif tok = try_tok(:plus) || try_tok(:minus) || try_tok(:times) || try_tok(:div)
|
|
555
|
+
result << " #{Lexer::OPERATORS_REVERSE[tok.type]} "
|
|
556
|
+
elsif allow_comma && try_tok(:comma)
|
|
557
|
+
result << ", "
|
|
558
|
+
else
|
|
559
|
+
return
|
|
560
|
+
end
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def min_max_interpolation
|
|
565
|
+
without_stop_at do
|
|
566
|
+
tok = try_tok(:begin_interpolation)
|
|
567
|
+
return unless tok
|
|
568
|
+
expr = without_stop_at {assert_expr :expr}
|
|
569
|
+
assert_tok :end_interpolation
|
|
570
|
+
expr
|
|
571
|
+
end
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
def min_max_function
|
|
575
|
+
return unless tok = peek_tok(:funcall)
|
|
576
|
+
return unless %w[calc env var].include?(tok.value.downcase)
|
|
577
|
+
@lexer.next
|
|
578
|
+
result = [tok.value, '(', *declaration_value, ')']
|
|
579
|
+
assert_tok :rparen
|
|
580
|
+
result
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
def min_max_calc
|
|
584
|
+
return unless tok = peek_tok(:special_fun)
|
|
585
|
+
return unless tok.value.value.downcase.start_with?("calc(")
|
|
586
|
+
@lexer.next.value
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
def min_max_parens
|
|
590
|
+
return unless try_tok :lparen
|
|
591
|
+
return unless contents = min_max_contents(allow_comma: false)
|
|
592
|
+
['(', *contents]
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
def nested_min_max
|
|
596
|
+
return unless tok = peek_tok(:funcall)
|
|
597
|
+
return unless %w[min max].include?(tok.value.downcase)
|
|
598
|
+
@lexer.next
|
|
599
|
+
return unless contents = min_max_contents
|
|
600
|
+
[tok.value, '(', *contents]
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
def declaration_value
|
|
604
|
+
result = []
|
|
605
|
+
brackets = []
|
|
606
|
+
loop do
|
|
607
|
+
result << @lexer.str do
|
|
608
|
+
until @lexer.done? ||
|
|
609
|
+
peek_toks(:begin_interpolation,
|
|
610
|
+
:end_interpolation,
|
|
611
|
+
:lcurly,
|
|
612
|
+
:lparen,
|
|
613
|
+
:lsquare,
|
|
614
|
+
:rparen,
|
|
615
|
+
:rsquare)
|
|
616
|
+
@lexer.next || @lexer.next_char
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
if try_tok(:begin_interpolation)
|
|
621
|
+
result << assert_expr(:expr)
|
|
622
|
+
assert_tok :end_interpolation
|
|
623
|
+
elsif tok = try_toks(:lcurly, :lparen, :lsquare)
|
|
624
|
+
brackets << case tok.type
|
|
625
|
+
when :lcurly; :end_interpolation
|
|
626
|
+
when :lparen; :rparen
|
|
627
|
+
when :lsquare; :rsquare
|
|
628
|
+
end
|
|
629
|
+
result << Lexer::OPERATORS_REVERSE[tok.type]
|
|
630
|
+
elsif brackets.empty?
|
|
631
|
+
return result
|
|
632
|
+
else
|
|
633
|
+
bracket = brackets.pop
|
|
634
|
+
assert_tok bracket
|
|
635
|
+
result << Lexer::OPERATORS_REVERSE[bracket]
|
|
636
|
+
end
|
|
637
|
+
end
|
|
638
|
+
end
|
|
639
|
+
|
|
537
640
|
def funcall
|
|
538
641
|
tok = try_tok(:funcall)
|
|
539
642
|
return raw unless tok
|
|
@@ -549,29 +652,31 @@ RUBY
|
|
|
549
652
|
else
|
|
550
653
|
return [], nil unless try_tok(:lparen)
|
|
551
654
|
end
|
|
552
|
-
return [], nil if try_tok(:rparen)
|
|
553
655
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
656
|
+
without_stop_at do
|
|
657
|
+
res = []
|
|
658
|
+
splat = nil
|
|
659
|
+
must_have_default = false
|
|
660
|
+
loop do
|
|
661
|
+
break if peek_tok(:rparen)
|
|
662
|
+
c = assert_tok(:const)
|
|
663
|
+
var = node(Script::Tree::Variable.new(c.value), c.source_range)
|
|
664
|
+
if try_tok(:colon)
|
|
665
|
+
val = assert_expr(:space)
|
|
666
|
+
must_have_default = true
|
|
667
|
+
elsif try_tok(:splat)
|
|
668
|
+
splat = var
|
|
669
|
+
break
|
|
670
|
+
elsif must_have_default
|
|
671
|
+
raise SyntaxError.new(
|
|
672
|
+
"Required argument #{var.inspect} must come before any optional arguments.")
|
|
673
|
+
end
|
|
674
|
+
res << [var, val]
|
|
675
|
+
break unless try_tok(:comma)
|
|
569
676
|
end
|
|
570
|
-
|
|
571
|
-
|
|
677
|
+
assert_tok(:rparen)
|
|
678
|
+
return res, splat
|
|
572
679
|
end
|
|
573
|
-
assert_tok(:rparen)
|
|
574
|
-
return res, splat
|
|
575
680
|
end
|
|
576
681
|
|
|
577
682
|
def fn_arglist
|
|
@@ -583,40 +688,37 @@ RUBY
|
|
|
583
688
|
end
|
|
584
689
|
|
|
585
690
|
def arglist(subexpr, description)
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
if keywords[name.name]
|
|
601
|
-
raise SyntaxError.new("Keyword argument \"#{name.to_sass}\" passed more than once")
|
|
602
|
-
end
|
|
691
|
+
without_stop_at do
|
|
692
|
+
args = []
|
|
693
|
+
keywords = Sass::Util::NormalizedMap.new
|
|
694
|
+
splat = nil
|
|
695
|
+
while (e = send(subexpr))
|
|
696
|
+
if @lexer.peek && @lexer.peek.type == :colon
|
|
697
|
+
name = e
|
|
698
|
+
@lexer.expected!("comma") unless name.is_a?(Tree::Variable)
|
|
699
|
+
assert_tok(:colon)
|
|
700
|
+
value = assert_expr(subexpr, description)
|
|
701
|
+
|
|
702
|
+
if keywords[name.name]
|
|
703
|
+
raise SyntaxError.new("Keyword argument \"#{name.to_sass}\" passed more than once")
|
|
704
|
+
end
|
|
603
705
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
706
|
+
keywords[name.name] = value
|
|
707
|
+
else
|
|
708
|
+
if try_tok(:splat)
|
|
709
|
+
return args, keywords, splat, e if splat
|
|
710
|
+
splat, e = e, nil
|
|
711
|
+
elsif splat
|
|
712
|
+
raise SyntaxError.new("Only keyword arguments may follow variable arguments (...).")
|
|
713
|
+
elsif !keywords.empty?
|
|
714
|
+
raise SyntaxError.new("Positional arguments must come before keyword arguments.")
|
|
715
|
+
end
|
|
716
|
+
args << e if e
|
|
613
717
|
end
|
|
614
718
|
|
|
615
|
-
args
|
|
719
|
+
return args, keywords, splat unless try_tok(:comma)
|
|
616
720
|
end
|
|
617
|
-
|
|
618
|
-
return args, keywords, splat unless try_tok(:comma)
|
|
619
|
-
e = assert_expr(subexpr, description)
|
|
721
|
+
return args, keywords
|
|
620
722
|
end
|
|
621
723
|
end
|
|
622
724
|
|
|
@@ -628,10 +730,10 @@ RUBY
|
|
|
628
730
|
|
|
629
731
|
def special_fun
|
|
630
732
|
first = try_tok(:special_fun)
|
|
631
|
-
return
|
|
733
|
+
return square_list unless first
|
|
632
734
|
str = literal_node(first.value, first.source_range)
|
|
633
735
|
return str unless try_tok(:string_interpolation)
|
|
634
|
-
mid =
|
|
736
|
+
mid = without_stop_at {assert_expr :expr}
|
|
635
737
|
assert_tok :end_interpolation
|
|
636
738
|
last = assert_expr(:special_fun)
|
|
637
739
|
node(
|
|
@@ -639,24 +741,68 @@ RUBY
|
|
|
639
741
|
first.source_range.start_pos)
|
|
640
742
|
end
|
|
641
743
|
|
|
642
|
-
def
|
|
643
|
-
return variable unless try_tok(:lparen)
|
|
744
|
+
def square_list
|
|
644
745
|
start_pos = source_position
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
746
|
+
return paren unless try_tok(:lsquare)
|
|
747
|
+
|
|
748
|
+
without_stop_at do
|
|
749
|
+
space_start_pos = source_position
|
|
750
|
+
e = interpolation(inner: :or_expr)
|
|
751
|
+
separator = nil
|
|
752
|
+
if e
|
|
753
|
+
elements = [e]
|
|
754
|
+
while (e = interpolation(inner: :or_expr))
|
|
755
|
+
elements << e
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
# If there's a comma after a space-separated list, it's actually a
|
|
759
|
+
# space-separated list nested in a comma-separated list.
|
|
760
|
+
if try_tok(:comma)
|
|
761
|
+
e = if elements.length == 1
|
|
762
|
+
elements.first
|
|
763
|
+
else
|
|
764
|
+
node(
|
|
765
|
+
Sass::Script::Tree::ListLiteral.new(elements, separator: :space),
|
|
766
|
+
space_start_pos)
|
|
767
|
+
end
|
|
768
|
+
elements = [e]
|
|
769
|
+
|
|
770
|
+
while (e = space)
|
|
771
|
+
elements << e
|
|
772
|
+
break unless try_tok(:comma)
|
|
773
|
+
end
|
|
774
|
+
separator = :comma
|
|
775
|
+
else
|
|
776
|
+
separator = :space if elements.length > 1
|
|
777
|
+
end
|
|
778
|
+
else
|
|
779
|
+
elements = []
|
|
780
|
+
end
|
|
781
|
+
|
|
782
|
+
assert_tok(:rsquare)
|
|
783
|
+
end_pos = source_position
|
|
649
784
|
|
|
650
|
-
|
|
651
|
-
|
|
785
|
+
node(Sass::Script::Tree::ListLiteral.new(elements, separator: separator, bracketed: true),
|
|
786
|
+
start_pos, end_pos)
|
|
787
|
+
end
|
|
788
|
+
end
|
|
789
|
+
|
|
790
|
+
def paren
|
|
791
|
+
return variable unless try_tok(:lparen)
|
|
792
|
+
without_stop_at do
|
|
793
|
+
start_pos = source_position
|
|
794
|
+
e = map
|
|
795
|
+
e.force_division! if e
|
|
796
|
+
end_pos = source_position
|
|
797
|
+
assert_tok(:rparen)
|
|
798
|
+
e || node(Sass::Script::Tree::ListLiteral.new([]), start_pos, end_pos)
|
|
799
|
+
end
|
|
652
800
|
end
|
|
653
801
|
|
|
654
802
|
def variable
|
|
655
803
|
start_pos = source_position
|
|
656
804
|
c = try_tok(:const)
|
|
657
805
|
return string unless c
|
|
658
|
-
|
|
659
|
-
@css_variable_warning.warn! if @css_variable_warning
|
|
660
806
|
node(Tree::Variable.new(*c.value), start_pos)
|
|
661
807
|
end
|
|
662
808
|
|
|
@@ -665,9 +811,9 @@ RUBY
|
|
|
665
811
|
return number unless first
|
|
666
812
|
str = literal_node(first.value, first.source_range)
|
|
667
813
|
return str unless try_tok(:string_interpolation)
|
|
668
|
-
mid =
|
|
814
|
+
mid = assert_expr :expr
|
|
669
815
|
assert_tok :end_interpolation
|
|
670
|
-
last = assert_expr(:string)
|
|
816
|
+
last = without_stop_at {assert_expr(:string)}
|
|
671
817
|
node(Tree::StringInterpolation.new(str, mid, last), first.source_range.start_pos)
|
|
672
818
|
end
|
|
673
819
|
|
|
@@ -683,7 +829,6 @@ RUBY
|
|
|
683
829
|
def selector
|
|
684
830
|
tok = try_tok(:selector)
|
|
685
831
|
return literal unless tok
|
|
686
|
-
@css_variable_warning.warn! if @css_variable_warning
|
|
687
832
|
node(tok.value, tok.source_range.start_pos)
|
|
688
833
|
end
|
|
689
834
|
|
|
@@ -723,15 +868,23 @@ RUBY
|
|
|
723
868
|
@lexer.expected!(names.map {|tok| Lexer::TOKEN_NAMES[tok] || tok}.join(" or "))
|
|
724
869
|
end
|
|
725
870
|
|
|
726
|
-
def
|
|
871
|
+
def peek_tok(name)
|
|
727
872
|
# Avoids an array allocation caused by argument globbing in the try_toks method.
|
|
728
873
|
peeked = @lexer.peek
|
|
729
|
-
peeked && name == peeked.type &&
|
|
874
|
+
peeked && name == peeked.type && peeked
|
|
730
875
|
end
|
|
731
876
|
|
|
732
|
-
def
|
|
877
|
+
def peek_toks(*names)
|
|
733
878
|
peeked = @lexer.peek
|
|
734
|
-
peeked && names.include?(peeked.type) &&
|
|
879
|
+
peeked && names.include?(peeked.type) && peeked
|
|
880
|
+
end
|
|
881
|
+
|
|
882
|
+
def try_tok(name)
|
|
883
|
+
peek_tok(name) && @lexer.next
|
|
884
|
+
end
|
|
885
|
+
|
|
886
|
+
def try_toks(*names)
|
|
887
|
+
peek_toks(*names) && @lexer.next
|
|
735
888
|
end
|
|
736
889
|
|
|
737
890
|
def assert_done
|
|
@@ -745,6 +898,14 @@ RUBY
|
|
|
745
898
|
end
|
|
746
899
|
end
|
|
747
900
|
|
|
901
|
+
def without_stop_at
|
|
902
|
+
old_stop_at = @stop_at
|
|
903
|
+
@stop_at = nil
|
|
904
|
+
yield
|
|
905
|
+
ensure
|
|
906
|
+
@stop_at = old_stop_at
|
|
907
|
+
end
|
|
908
|
+
|
|
748
909
|
# @overload node(value, source_range)
|
|
749
910
|
# @param value [Sass::Script::Value::Base]
|
|
750
911
|
# @param source_range [Sass::Source::Range]
|
|
@@ -771,25 +932,33 @@ RUBY
|
|
|
771
932
|
range(source_range_or_start_pos, end_pos)
|
|
772
933
|
end
|
|
773
934
|
|
|
774
|
-
node.css_variable_warning = @css_variable_warning
|
|
775
935
|
node.line = source_range.start_pos.line
|
|
776
936
|
node.source_range = source_range
|
|
777
937
|
node.filename = @options[:filename]
|
|
778
938
|
node
|
|
779
939
|
end
|
|
780
940
|
|
|
781
|
-
#
|
|
782
|
-
#
|
|
783
|
-
# CSS warnings don't apply within interpolation, so this is used to
|
|
784
|
-
# disable them.
|
|
941
|
+
# Converts an array of strings and expressions to a string interoplation
|
|
942
|
+
# object.
|
|
785
943
|
#
|
|
786
|
-
# @
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
944
|
+
# @param array [Array<Script::Tree:Node | String>]
|
|
945
|
+
# @return [Script::Tree::StringInterpolation]
|
|
946
|
+
def array_to_interpolation(array)
|
|
947
|
+
Sass::Util.merge_adjacent_strings(array).reverse.inject(nil) do |after, value|
|
|
948
|
+
if value.is_a?(::String)
|
|
949
|
+
literal = Sass::Script::Tree::Literal.new(
|
|
950
|
+
Sass::Script::Value::String.new(value))
|
|
951
|
+
next literal unless after
|
|
952
|
+
Sass::Script::Tree::StringInterpolation.new(literal, after.mid, after.after)
|
|
953
|
+
else
|
|
954
|
+
Sass::Script::Tree::StringInterpolation.new(
|
|
955
|
+
Sass::Script::Tree::Literal.new(
|
|
956
|
+
Sass::Script::Value::String.new('')),
|
|
957
|
+
value,
|
|
958
|
+
after || Sass::Script::Tree::Literal.new(
|
|
959
|
+
Sass::Script::Value::String.new('')))
|
|
960
|
+
end
|
|
961
|
+
end
|
|
793
962
|
end
|
|
794
963
|
|
|
795
964
|
# Checks a script node for any immediately-deprecated interpolations, and
|