sass 3.4.25 → 3.7.4
Sign up to get free protection for your applications and to get access to all the features.
- 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/features.rb
CHANGED
@@ -67,7 +67,7 @@ module Sass
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def public_url(name, sourcemap_directory)
|
70
|
-
file_pathname = Sass::Util.cleanpath(
|
70
|
+
file_pathname = Sass::Util.cleanpath(File.absolute_path(name, @root))
|
71
71
|
return Sass::Util.file_uri_from_path(file_pathname) if sourcemap_directory.nil?
|
72
72
|
|
73
73
|
sourcemap_pathname = Sass::Util.cleanpath(sourcemap_directory)
|
@@ -133,7 +133,7 @@ module Sass
|
|
133
133
|
|
134
134
|
REDUNDANT_DIRECTORY = /#{Regexp.escape(File::SEPARATOR)}\.#{Regexp.escape(File::SEPARATOR)}/
|
135
135
|
# Given a base directory and an `@import`ed name,
|
136
|
-
# finds an
|
136
|
+
# finds an existent file that matches the name.
|
137
137
|
#
|
138
138
|
# @param dir [String] The directory relative to which to search.
|
139
139
|
# @param name [String] The filename to search for.
|
@@ -154,7 +154,9 @@ module Sass
|
|
154
154
|
[Sass::Util.cleanpath(full_path).to_s, s]
|
155
155
|
end
|
156
156
|
end.flatten(1)
|
157
|
-
|
157
|
+
if found.empty? && split(name)[2].nil? && File.directory?("#{dir}/#{name}")
|
158
|
+
return find_real_file("#{dir}/#{name}", "index", options)
|
159
|
+
end
|
158
160
|
|
159
161
|
if found.size > 1 && !@same_name_warnings.include?(found.first.first)
|
160
162
|
found.each {|(f, _)| @same_name_warnings << f}
|
@@ -202,7 +204,7 @@ WARNING
|
|
202
204
|
|
203
205
|
def _find(dir, name, options)
|
204
206
|
full_filename, syntax = Sass::Util.destructure(find_real_file(dir, name, options))
|
205
|
-
return unless full_filename && File.readable?(full_filename)
|
207
|
+
return unless full_filename && File.file?(full_filename) && File.readable?(full_filename)
|
206
208
|
|
207
209
|
# TODO: this preserves historical behavior, but it's possible
|
208
210
|
# :filename should be either normalized to the native format
|
data/lib/sass/logger/base.rb
CHANGED
@@ -22,6 +22,17 @@ class Sass::Logger::Base
|
|
22
22
|
!disabled && self.class.log_level?(level, log_level)
|
23
23
|
end
|
24
24
|
|
25
|
+
# Captures all logger messages emitted during a block and returns them as a
|
26
|
+
# string.
|
27
|
+
def capture
|
28
|
+
old_io = io
|
29
|
+
self.io = StringIO.new
|
30
|
+
yield
|
31
|
+
io.string
|
32
|
+
ensure
|
33
|
+
self.io = old_io
|
34
|
+
end
|
35
|
+
|
25
36
|
def log(level, message)
|
26
37
|
_log(level, message) if logging_level?(level)
|
27
38
|
end
|
data/lib/sass/plugin/compiler.rb
CHANGED
@@ -303,42 +303,30 @@ module Sass::Plugin
|
|
303
303
|
directories += @inferred_directories
|
304
304
|
directories = remove_redundant_directories(directories)
|
305
305
|
|
306
|
-
# A Listen version prior to 2.0 will write a test file to a directory to
|
307
|
-
# see if a watcher supports watching that directory. That breaks horribly
|
308
|
-
# on read-only directories, so we filter those out.
|
309
|
-
unless Sass::Util.listen_geq_2?
|
310
|
-
directories = directories.select {|d| File.directory?(d) && File.writable?(d)}
|
311
|
-
end
|
312
|
-
|
313
306
|
# TODO: Keep better track of what depends on what
|
314
307
|
# so we don't have to run a global update every time anything changes.
|
315
308
|
# XXX The :additional_watch_paths option exists for Compass to use until
|
316
309
|
# a deprecated feature is removed. It may be removed without warning.
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
# In Listen 2.0.0 and on, :force_polling is an option. In earlier
|
326
|
-
# versions, it's a method on the listener (called below).
|
327
|
-
listener_args.last[:force_polling] = true
|
328
|
-
end
|
310
|
+
directories += Array(options[:additional_watch_paths])
|
311
|
+
|
312
|
+
options = {
|
313
|
+
:relative_paths => false,
|
314
|
+
# The native windows listener is much slower than the polling option, according to
|
315
|
+
# https://github.com/nex3/sass/commit/a3031856b22bc834a5417dedecb038b7be9b9e3e
|
316
|
+
:force_polling => @options[:poll] || Sass::Util.windows?
|
317
|
+
}
|
329
318
|
|
330
|
-
listener = create_listener(*
|
319
|
+
listener = create_listener(*directories, options) do |modified, added, removed|
|
331
320
|
on_file_changed(individual_files, modified, added, removed)
|
332
321
|
yield(modified, added, removed) if block_given?
|
333
322
|
end
|
334
323
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
324
|
+
begin
|
325
|
+
listener.start
|
326
|
+
sleep
|
327
|
+
rescue Interrupt
|
328
|
+
# Squelch Interrupt for clean exit from Listen::Listener
|
339
329
|
end
|
340
|
-
|
341
|
-
listen_to(listener)
|
342
330
|
end
|
343
331
|
|
344
332
|
# Non-destructively modifies \{#options} so that default values are properly set,
|
@@ -387,28 +375,10 @@ module Sass::Plugin
|
|
387
375
|
|
388
376
|
private
|
389
377
|
|
378
|
+
# This is mocked out in compiler_test.rb.
|
390
379
|
def create_listener(*args, &block)
|
391
|
-
|
392
|
-
|
393
|
-
# Work around guard/listen#243.
|
394
|
-
options = args.pop if args.last.is_a?(Hash)
|
395
|
-
args.map do |dir|
|
396
|
-
Listen.to(dir, options, &block)
|
397
|
-
end
|
398
|
-
else
|
399
|
-
Listen::Listener.new(*args, &block)
|
400
|
-
end
|
401
|
-
end
|
402
|
-
|
403
|
-
def listen_to(listener)
|
404
|
-
if Sass::Util.listen_geq_2?
|
405
|
-
listener.map {|l| l.start}
|
406
|
-
sleep
|
407
|
-
else
|
408
|
-
listener.start!
|
409
|
-
end
|
410
|
-
rescue Interrupt
|
411
|
-
# Squelch Interrupt for clean exit from Listen::Listener
|
380
|
+
require 'sass-listen'
|
381
|
+
SassListen.to(*args, &block)
|
412
382
|
end
|
413
383
|
|
414
384
|
def remove_redundant_directories(directories)
|
@@ -494,7 +464,7 @@ module Sass::Plugin
|
|
494
464
|
rendered = engine.render
|
495
465
|
end
|
496
466
|
rescue StandardError => e
|
497
|
-
|
467
|
+
compilation_error_occurred = true
|
498
468
|
run_compilation_error e, filename, css, sourcemap
|
499
469
|
raise e unless options[:full_exception]
|
500
470
|
rendered = Sass::SyntaxError.exception_to_css(e, options[:line] || 1)
|
@@ -507,14 +477,14 @@ module Sass::Plugin
|
|
507
477
|
mapping.to_json(
|
508
478
|
:css_path => css, :sourcemap_path => sourcemap, :type => options[:sourcemap]))
|
509
479
|
end
|
510
|
-
run_updated_stylesheet(filename, css, sourcemap) unless
|
480
|
+
run_updated_stylesheet(filename, css, sourcemap) unless compilation_error_occurred
|
511
481
|
end
|
512
482
|
|
513
483
|
def write_file(fileName, content)
|
514
484
|
flag = 'w'
|
515
485
|
flag = 'wb' if Sass::Util.windows? && options[:unix_newlines]
|
516
486
|
File.open(fileName, flag) do |file|
|
517
|
-
file.set_encoding(content.encoding)
|
487
|
+
file.set_encoding(content.encoding)
|
518
488
|
file.print(content)
|
519
489
|
end
|
520
490
|
end
|
@@ -26,8 +26,8 @@ module Sass
|
|
26
26
|
clear_callbacks!
|
27
27
|
end
|
28
28
|
|
29
|
-
# An options hash.
|
30
|
-
#
|
29
|
+
# An options hash. See {file:SASS_REFERENCE.md#Options the Sass options
|
30
|
+
# documentation}.
|
31
31
|
#
|
32
32
|
# @return [{Symbol => Object}]
|
33
33
|
def options
|
data/lib/sass/railtie.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Rails 3.0.0.beta.2+, < 3.1
|
2
|
-
if defined?(ActiveSupport) &&
|
2
|
+
if defined?(ActiveSupport) && ActiveSupport.public_methods.include?(:on_load) &&
|
3
3
|
!Sass::Util.ap_geq?('3.1.0.beta')
|
4
4
|
require 'sass/plugin/configuration'
|
5
5
|
ActiveSupport.on_load(:before_configuration) do
|
@@ -24,7 +24,10 @@ module Sass
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# Short-circuit all the SassScript-only productions
|
27
|
-
|
27
|
+
def interpolation(first: nil, inner: :space)
|
28
|
+
first || send(inner)
|
29
|
+
end
|
30
|
+
|
28
31
|
alias_method :or_expr, :div
|
29
32
|
alias_method :unary_div, :ident
|
30
33
|
alias_method :paren, :string
|
@@ -1,9 +1,7 @@
|
|
1
1
|
require 'sass/script/value/helpers'
|
2
2
|
|
3
3
|
module Sass::Script
|
4
|
-
# @comment
|
5
4
|
# YARD can't handle some multiline tags, and we need really long tags for function declarations.
|
6
|
-
# rubocop:disable LineLength
|
7
5
|
# Methods in this module are accessible from the SassScript context.
|
8
6
|
# For example, you can write
|
9
7
|
#
|
@@ -77,7 +75,7 @@ module Sass::Script
|
|
77
75
|
# \{#complement complement($color)}
|
78
76
|
# : Returns the complement of a color.
|
79
77
|
#
|
80
|
-
# \{#invert invert($color)}
|
78
|
+
# \{#invert invert($color, \[$weight\])}
|
81
79
|
# : Returns the inverse of a color.
|
82
80
|
#
|
83
81
|
# ## Opacity Functions
|
@@ -176,7 +174,7 @@ module Sass::Script
|
|
176
174
|
# \{#set-nth set-nth($list, $n, $value)}
|
177
175
|
# : Replaces the nth item in a list.
|
178
176
|
#
|
179
|
-
# \{#join join($list1, $list2, \[$separator\])}
|
177
|
+
# \{#join join($list1, $list2, \[$separator, $bracketed\])}
|
180
178
|
# : Joins together two lists into one.
|
181
179
|
#
|
182
180
|
# \{#append append($list1, $val, \[$separator\])}
|
@@ -191,6 +189,9 @@ module Sass::Script
|
|
191
189
|
# \{#list_separator list-separator($list)}
|
192
190
|
# : Returns the separator of a list.
|
193
191
|
#
|
192
|
+
# \{#is_bracketed is-bracketed($list)}
|
193
|
+
# : Returns whether a list has square brackets.
|
194
|
+
#
|
194
195
|
# ## Map Functions {#map-functions}
|
195
196
|
#
|
196
197
|
# Maps in Sass are immutable; all map functions return a new map rather than
|
@@ -276,6 +277,9 @@ module Sass::Script
|
|
276
277
|
# \{#mixin_exists mixin-exists($name)}
|
277
278
|
# : Returns whether a mixin with the given name exists.
|
278
279
|
#
|
280
|
+
# \{#content_exists content-exists()}
|
281
|
+
# : Returns whether the current mixin was passed a content block.
|
282
|
+
#
|
279
283
|
# \{#inspect inspect($value)}
|
280
284
|
# : Returns the string representation of a value as it would be represented in Sass.
|
281
285
|
#
|
@@ -291,8 +295,12 @@ module Sass::Script
|
|
291
295
|
# \{#comparable comparable($number1, $number2)}
|
292
296
|
# : Returns whether two numbers can be added, subtracted, or compared.
|
293
297
|
#
|
294
|
-
# \{#call call($
|
295
|
-
# : Dynamically calls a Sass function
|
298
|
+
# \{#call call($function, $args...)}
|
299
|
+
# : Dynamically calls a Sass function reference returned by `get-function`.
|
300
|
+
#
|
301
|
+
# \{#get_function get-function($name, $css: false)}
|
302
|
+
# : Looks up a function with the given name in the current lexical scope
|
303
|
+
# and returns a reference to it.
|
296
304
|
#
|
297
305
|
# ## Miscellaneous Functions
|
298
306
|
#
|
@@ -354,9 +362,6 @@ module Sass::Script
|
|
354
362
|
# representation) on those objects without first setting {Tree::Node#options=
|
355
363
|
# the #options attribute}.
|
356
364
|
#
|
357
|
-
# @comment
|
358
|
-
# rubocop:enable LineLength
|
359
|
-
# rubocop:disable ModuleLength
|
360
365
|
module Functions
|
361
366
|
@signatures = {}
|
362
367
|
|
@@ -471,14 +476,14 @@ module Sass::Script
|
|
471
476
|
# @param seed [Integer]
|
472
477
|
# @return [Integer] The same seed.
|
473
478
|
def self.random_seed=(seed)
|
474
|
-
@random_number_generator =
|
479
|
+
@random_number_generator = Random.new(seed)
|
475
480
|
end
|
476
481
|
|
477
482
|
# Get Sass's internal random number generator.
|
478
483
|
#
|
479
484
|
# @return [Random]
|
480
485
|
def self.random_number_generator
|
481
|
-
@random_number_generator ||=
|
486
|
+
@random_number_generator ||= Random.new
|
482
487
|
end
|
483
488
|
|
484
489
|
# The context in which methods in {Script::Functions} are evaluated.
|
@@ -522,18 +527,27 @@ module Sass::Script
|
|
522
527
|
# assert_type value, :String
|
523
528
|
# assert_type value, :Number
|
524
529
|
# @param value [Sass::Script::Value::Base] A SassScript value
|
525
|
-
# @param type [Symbol] The name of the type the value is expected to be
|
530
|
+
# @param type [Symbol, Array<Symbol>] The name(s) of the type the value is expected to be
|
526
531
|
# @param name [String, Symbol, nil] The name of the argument.
|
527
532
|
# @raise [ArgumentError] if value is not of the correct type.
|
528
533
|
def assert_type(value, type, name = nil)
|
529
|
-
|
530
|
-
|
531
|
-
value.
|
534
|
+
valid_types = Array(type)
|
535
|
+
found_type = valid_types.find do |t|
|
536
|
+
value.is_a?(Sass::Script::Value.const_get(t)) ||
|
537
|
+
t == :Map && value.is_a?(Sass::Script::Value::List) && value.value.empty?
|
538
|
+
end
|
539
|
+
|
540
|
+
if found_type
|
541
|
+
value.check_deprecated_interp if found_type == :String
|
532
542
|
return
|
533
543
|
end
|
534
544
|
|
535
|
-
|
536
|
-
|
545
|
+
err = if valid_types.size == 1
|
546
|
+
"#{value.inspect} is not a #{TYPE_NAMES[type] || type.to_s.downcase}"
|
547
|
+
else
|
548
|
+
type_names = valid_types.map {|t| TYPE_NAMES[t] || t.to_s.downcase}
|
549
|
+
"#{value.inspect} is not any of #{type_names.join(', ')}"
|
550
|
+
end
|
537
551
|
err = "$#{name.to_s.tr('_', '-')}: " + err if name
|
538
552
|
raise ArgumentError.new(err)
|
539
553
|
end
|
@@ -634,23 +648,27 @@ module Sass::Script
|
|
634
648
|
# inclusive
|
635
649
|
# @return [Sass::Script::Value::Color]
|
636
650
|
# @raise [ArgumentError] if any parameter is the wrong type or out of bounds
|
637
|
-
def rgb(red, green, blue)
|
638
|
-
if
|
651
|
+
def rgb(red, green = nil, blue = nil)
|
652
|
+
if green.nil?
|
653
|
+
return unquoted_string("rgb(#{red})") if var?(red)
|
654
|
+
raise ArgumentError.new("wrong number of arguments (1 for 3)")
|
655
|
+
elsif blue.nil?
|
656
|
+
return unquoted_string("rgb(#{red}, #{green})") if var?(red) || var?(green)
|
657
|
+
raise ArgumentError.new("wrong number of arguments (2 for 3)")
|
658
|
+
end
|
659
|
+
|
660
|
+
if special_number?(red) || special_number?(green) || special_number?(blue)
|
639
661
|
return unquoted_string("rgb(#{red}, #{green}, #{blue})")
|
640
662
|
end
|
641
663
|
assert_type red, :Number, :red
|
642
664
|
assert_type green, :Number, :green
|
643
665
|
assert_type blue, :Number, :blue
|
644
666
|
|
645
|
-
color_attrs = [
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
else
|
651
|
-
raise ArgumentError.new("Expected #{c} to be unitless or have a unit of % but got #{c}")
|
652
|
-
end
|
653
|
-
end
|
667
|
+
color_attrs = [
|
668
|
+
percentage_or_unitless(red, 255, "red"),
|
669
|
+
percentage_or_unitless(green, 255, "green"),
|
670
|
+
percentage_or_unitless(blue, 255, "blue")
|
671
|
+
]
|
654
672
|
|
655
673
|
# Don't store the string representation for function-created colors, both
|
656
674
|
# because it's not very useful and because some functions aren't supported
|
@@ -658,6 +676,8 @@ module Sass::Script
|
|
658
676
|
Sass::Script::Value::Color.new(color_attrs)
|
659
677
|
end
|
660
678
|
declare :rgb, [:red, :green, :blue]
|
679
|
+
declare :rgb, [:red, :green]
|
680
|
+
declare :rgb, [:red]
|
661
681
|
|
662
682
|
# Creates a {Sass::Script::Value::Color Color} from red, green, blue, and
|
663
683
|
# alpha values.
|
@@ -692,20 +712,39 @@ module Sass::Script
|
|
692
712
|
# is the wrong type
|
693
713
|
def rgba(*args)
|
694
714
|
case args.size
|
715
|
+
when 1
|
716
|
+
return unquoted_string("rgba(#{args.first})") if var?(args.first)
|
717
|
+
raise ArgumentError.new("wrong number of arguments (1 for 4)")
|
695
718
|
when 2
|
696
719
|
color, alpha = args
|
697
720
|
|
721
|
+
if var?(color)
|
722
|
+
return unquoted_string("rgba(#{color}, #{alpha})")
|
723
|
+
elsif var?(alpha)
|
724
|
+
if color.is_a?(Sass::Script::Value::Color)
|
725
|
+
return unquoted_string("rgba(#{color.red}, #{color.green}, #{color.blue}, #{alpha})")
|
726
|
+
else
|
727
|
+
return unquoted_string("rgba(#{color}, #{alpha})")
|
728
|
+
end
|
729
|
+
end
|
730
|
+
|
698
731
|
assert_type color, :Color, :color
|
699
|
-
if
|
732
|
+
if special_number?(alpha)
|
700
733
|
unquoted_string("rgba(#{color.red}, #{color.green}, #{color.blue}, #{alpha})")
|
701
734
|
else
|
702
735
|
assert_type alpha, :Number, :alpha
|
703
|
-
|
704
|
-
|
736
|
+
color.with(:alpha => percentage_or_unitless(alpha, 1, "alpha"))
|
737
|
+
end
|
738
|
+
when 3
|
739
|
+
if var?(args[0]) || var?(args[1]) || var?(args[2])
|
740
|
+
unquoted_string("rgba(#{args.join(', ')})")
|
741
|
+
else
|
742
|
+
raise ArgumentError.new("wrong number of arguments (3 for 4)")
|
705
743
|
end
|
706
744
|
when 4
|
707
745
|
red, green, blue, alpha = args
|
708
|
-
if
|
746
|
+
if special_number?(red) || special_number?(green) ||
|
747
|
+
special_number?(blue) || special_number?(alpha)
|
709
748
|
unquoted_string("rgba(#{red}, #{green}, #{blue}, #{alpha})")
|
710
749
|
else
|
711
750
|
rgba(rgb(red, green, blue), alpha)
|
@@ -715,7 +754,9 @@ module Sass::Script
|
|
715
754
|
end
|
716
755
|
end
|
717
756
|
declare :rgba, [:red, :green, :blue, :alpha]
|
757
|
+
declare :rgba, [:red, :green, :blue]
|
718
758
|
declare :rgba, [:color, :alpha]
|
759
|
+
declare :rgba, [:red]
|
719
760
|
|
720
761
|
# Creates a {Sass::Script::Value::Color Color} from hue, saturation, and
|
721
762
|
# lightness values. Uses the algorithm from the [CSS3 spec][].
|
@@ -733,14 +774,24 @@ module Sass::Script
|
|
733
774
|
# @return [Sass::Script::Value::Color]
|
734
775
|
# @raise [ArgumentError] if `$saturation` or `$lightness` are out of bounds
|
735
776
|
# or any parameter is the wrong type
|
736
|
-
def hsl(hue, saturation, lightness)
|
737
|
-
if
|
777
|
+
def hsl(hue, saturation = nil, lightness = nil)
|
778
|
+
if saturation.nil?
|
779
|
+
return unquoted_string("hsl(#{hue})") if var?(hue)
|
780
|
+
raise ArgumentError.new("wrong number of arguments (1 for 3)")
|
781
|
+
elsif lightness.nil?
|
782
|
+
return unquoted_string("hsl(#{hue}, #{saturation})") if var?(hue) || var?(saturation)
|
783
|
+
raise ArgumentError.new("wrong number of arguments (2 for 3)")
|
784
|
+
end
|
785
|
+
|
786
|
+
if special_number?(hue) || special_number?(saturation) || special_number?(lightness)
|
738
787
|
unquoted_string("hsl(#{hue}, #{saturation}, #{lightness})")
|
739
788
|
else
|
740
789
|
hsla(hue, saturation, lightness, number(1))
|
741
790
|
end
|
742
791
|
end
|
743
792
|
declare :hsl, [:hue, :saturation, :lightness]
|
793
|
+
declare :hsl, [:hue, :saturation]
|
794
|
+
declare :hsl, [:hue]
|
744
795
|
|
745
796
|
# Creates a {Sass::Script::Value::Color Color} from hue,
|
746
797
|
# saturation, lightness, and alpha values. Uses the algorithm from
|
@@ -761,15 +812,29 @@ module Sass::Script
|
|
761
812
|
# @return [Sass::Script::Value::Color]
|
762
813
|
# @raise [ArgumentError] if `$saturation`, `$lightness`, or `$alpha` are out
|
763
814
|
# of bounds or any parameter is the wrong type
|
764
|
-
def hsla(hue, saturation, lightness, alpha)
|
765
|
-
if
|
815
|
+
def hsla(hue, saturation = nil, lightness = nil, alpha = nil)
|
816
|
+
if saturation.nil?
|
817
|
+
return unquoted_string("hsla(#{hue})") if var?(hue)
|
818
|
+
raise ArgumentError.new("wrong number of arguments (1 for 4)")
|
819
|
+
elsif lightness.nil?
|
820
|
+
return unquoted_string("hsla(#{hue}, #{saturation})") if var?(hue) || var?(saturation)
|
821
|
+
raise ArgumentError.new("wrong number of arguments (2 for 4)")
|
822
|
+
elsif alpha.nil?
|
823
|
+
if var?(hue) || var?(saturation) || var?(lightness)
|
824
|
+
return unquoted_string("hsla(#{hue}, #{saturation}, #{lightness})")
|
825
|
+
else
|
826
|
+
raise ArgumentError.new("wrong number of arguments (2 for 4)")
|
827
|
+
end
|
828
|
+
end
|
829
|
+
|
830
|
+
if special_number?(hue) || special_number?(saturation) ||
|
831
|
+
special_number?(lightness) || special_number?(alpha)
|
766
832
|
return unquoted_string("hsla(#{hue}, #{saturation}, #{lightness}, #{alpha})")
|
767
833
|
end
|
768
834
|
assert_type hue, :Number, :hue
|
769
835
|
assert_type saturation, :Number, :saturation
|
770
836
|
assert_type lightness, :Number, :lightness
|
771
837
|
assert_type alpha, :Number, :alpha
|
772
|
-
check_alpha_unit alpha, 'hsla'
|
773
838
|
|
774
839
|
h = hue.value
|
775
840
|
s = saturation.value
|
@@ -779,9 +844,13 @@ module Sass::Script
|
|
779
844
|
# because it's not very useful and because some functions aren't supported
|
780
845
|
# on older browsers.
|
781
846
|
Sass::Script::Value::Color.new(
|
782
|
-
:hue => h, :saturation => s, :lightness => l,
|
847
|
+
:hue => h, :saturation => s, :lightness => l,
|
848
|
+
:alpha => percentage_or_unitless(alpha, 1, "alpha"))
|
783
849
|
end
|
784
850
|
declare :hsla, [:hue, :saturation, :lightness, :alpha]
|
851
|
+
declare :hsla, [:hue, :saturation, :lightness]
|
852
|
+
declare :hsla, [:hue, :saturation]
|
853
|
+
declare :hsla, [:hue]
|
785
854
|
|
786
855
|
# Gets the red component of a color. Calculated from HSL where necessary via
|
787
856
|
# [this algorithm][hsl-to-rgb].
|
@@ -1384,20 +1453,28 @@ module Sass::Script
|
|
1384
1453
|
#
|
1385
1454
|
# @overload invert($color)
|
1386
1455
|
# @param $color [Sass::Script::Value::Color]
|
1456
|
+
# @overload invert($color, $weight: 100%)
|
1457
|
+
# @param $color [Sass::Script::Value::Color]
|
1458
|
+
# @param $weight [Sass::Script::Value::Number] The relative weight of the
|
1459
|
+
# color color's inverse
|
1387
1460
|
# @return [Sass::Script::Value::Color]
|
1388
|
-
# @raise [ArgumentError] if `$color` isn't a color
|
1389
|
-
|
1461
|
+
# @raise [ArgumentError] if `$color` isn't a color or `$weight`
|
1462
|
+
# isn't a percentage between 0% and 100%
|
1463
|
+
def invert(color, weight = number(100))
|
1390
1464
|
if color.is_a?(Sass::Script::Value::Number)
|
1391
1465
|
return identifier("invert(#{color})")
|
1392
1466
|
end
|
1393
1467
|
|
1394
1468
|
assert_type color, :Color, :color
|
1395
|
-
color.with(
|
1469
|
+
inv = color.with(
|
1396
1470
|
:red => (255 - color.red),
|
1397
1471
|
:green => (255 - color.green),
|
1398
1472
|
:blue => (255 - color.blue))
|
1473
|
+
|
1474
|
+
mix(inv, color, weight)
|
1399
1475
|
end
|
1400
1476
|
declare :invert, [:color]
|
1477
|
+
declare :invert, [:color, :weight]
|
1401
1478
|
|
1402
1479
|
# Removes quotes from a string. If the string is already unquoted, this will
|
1403
1480
|
# return it unmodified.
|
@@ -1413,13 +1490,11 @@ module Sass::Script
|
|
1413
1490
|
def unquote(string)
|
1414
1491
|
unless string.is_a?(Sass::Script::Value::String)
|
1415
1492
|
# Don't warn multiple times for the same source line.
|
1416
|
-
# rubocop:disable GlobalVars
|
1417
1493
|
$_sass_warned_for_unquote ||= Set.new
|
1418
1494
|
frame = environment.stack.frames.last
|
1419
1495
|
key = [frame.filename, frame.line] if frame
|
1420
1496
|
return string if frame && $_sass_warned_for_unquote.include?(key)
|
1421
1497
|
$_sass_warned_for_unquote << key if frame
|
1422
|
-
# rubocop:enable GlobalVars
|
1423
1498
|
|
1424
1499
|
Sass::Util.sass_warn(<<MESSAGE.strip)
|
1425
1500
|
DEPRECATION WARNING: Passing #{string.to_sass}, a non-string value, to unquote()
|
@@ -1612,6 +1687,10 @@ MESSAGE
|
|
1612
1687
|
# type-of(#fff) => color
|
1613
1688
|
# type-of(blue) => color
|
1614
1689
|
# type-of(null) => null
|
1690
|
+
# type-of(a b c) => list
|
1691
|
+
# type-of((a: 1, b: 2)) => map
|
1692
|
+
# type-of(get-function("foo")) => function
|
1693
|
+
#
|
1615
1694
|
# @overload type_of($value)
|
1616
1695
|
# @param $value [Sass::Script::Value::Base] The value to inspect
|
1617
1696
|
# @return [Sass::Script::Value::String] The unquoted string name of the
|
@@ -1639,6 +1718,12 @@ MESSAGE
|
|
1639
1718
|
#
|
1640
1719
|
# * `at-error` indicates that the Sass `@error` directive is supported.
|
1641
1720
|
#
|
1721
|
+
# * `custom-property` indicates that the [Custom Properties Level 1][] spec
|
1722
|
+
# is supported. This means that custom properties are parsed statically,
|
1723
|
+
# with only interpolation treated as SassScript.
|
1724
|
+
#
|
1725
|
+
# [Custom Properties Level 1]: https://www.w3.org/TR/css-variables-1/
|
1726
|
+
#
|
1642
1727
|
# @example
|
1643
1728
|
# feature-exists(some-feature-that-exists) => true
|
1644
1729
|
# feature-exists(what-is-this-i-dont-know) => false
|
@@ -1653,6 +1738,55 @@ MESSAGE
|
|
1653
1738
|
end
|
1654
1739
|
declare :feature_exists, [:feature]
|
1655
1740
|
|
1741
|
+
# Returns a reference to a function for later invocation with the `call()` function.
|
1742
|
+
#
|
1743
|
+
# If `$css` is `false`, the function reference may refer to a function
|
1744
|
+
# defined in your stylesheet or built-in to the host environment. If it's
|
1745
|
+
# `true` it will refer to a plain-CSS function.
|
1746
|
+
#
|
1747
|
+
# @example
|
1748
|
+
# get-function("rgb")
|
1749
|
+
#
|
1750
|
+
# @function myfunc { @return "something"; }
|
1751
|
+
# get-function("myfunc")
|
1752
|
+
#
|
1753
|
+
# @overload get_function($name, $css: false)
|
1754
|
+
# @param name [Sass::Script::Value::String] The name of the function being referenced.
|
1755
|
+
# @param css [Sass::Script::Value::Bool] Whether to get a plain CSS function.
|
1756
|
+
#
|
1757
|
+
# @return [Sass::Script::Value::Function] A function reference.
|
1758
|
+
def get_function(name, kwargs = {})
|
1759
|
+
assert_type name, :String, :name
|
1760
|
+
|
1761
|
+
css = if kwargs.has_key?("css")
|
1762
|
+
v = kwargs.delete("css")
|
1763
|
+
assert_type v, :Bool, :css
|
1764
|
+
v.value
|
1765
|
+
else
|
1766
|
+
false
|
1767
|
+
end
|
1768
|
+
|
1769
|
+
if kwargs.any?
|
1770
|
+
raise ArgumentError.new("Illegal keyword argument '#{kwargs.keys.first}'")
|
1771
|
+
end
|
1772
|
+
|
1773
|
+
if css
|
1774
|
+
return Sass::Script::Value::Function.new(
|
1775
|
+
Sass::Callable.new(name.value, nil, nil, nil, nil, nil, "function", :css))
|
1776
|
+
end
|
1777
|
+
|
1778
|
+
callable = environment.caller.function(name.value) ||
|
1779
|
+
(Sass::Script::Functions.callable?(name.value.tr("-", "_")) &&
|
1780
|
+
Sass::Callable.new(name.value, nil, nil, nil, nil, nil, "function", :builtin))
|
1781
|
+
|
1782
|
+
if callable
|
1783
|
+
Sass::Script::Value::Function.new(callable)
|
1784
|
+
else
|
1785
|
+
raise Sass::SyntaxError.new("Function not found: #{name}")
|
1786
|
+
end
|
1787
|
+
end
|
1788
|
+
declare :get_function, [:name], :var_kwargs => true
|
1789
|
+
|
1656
1790
|
# Returns the unit(s) associated with a number. Complex units are sorted in
|
1657
1791
|
# alphabetical order by numerator and denominator.
|
1658
1792
|
#
|
@@ -1855,7 +1989,7 @@ MESSAGE
|
|
1855
1989
|
index = n.to_i > 0 ? n.to_i - 1 : n.to_i
|
1856
1990
|
new_list = list.to_a.dup
|
1857
1991
|
new_list[index] = value
|
1858
|
-
|
1992
|
+
list.with_contents(new_list)
|
1859
1993
|
end
|
1860
1994
|
declare :set_nth, [:list, :n, :value]
|
1861
1995
|
|
@@ -1896,6 +2030,9 @@ MESSAGE
|
|
1896
2030
|
# list. If both lists have fewer than two items, spaces are used for the
|
1897
2031
|
# resulting list.
|
1898
2032
|
#
|
2033
|
+
# Unless `$bracketed` is passed, the resulting list is bracketed if the
|
2034
|
+
# first parameter is.
|
2035
|
+
#
|
1899
2036
|
# Like all list functions, `join()` returns a new list rather than modifying
|
1900
2037
|
# its arguments in place.
|
1901
2038
|
#
|
@@ -1905,27 +2042,70 @@ MESSAGE
|
|
1905
2042
|
# join(10px, 20px) => 10px 20px
|
1906
2043
|
# join(10px, 20px, comma) => 10px, 20px
|
1907
2044
|
# join((blue, red), (#abc, #def), space) => blue red #abc #def
|
1908
|
-
#
|
2045
|
+
# join([10px], 20px) => [10px 20px]
|
2046
|
+
# @overload join($list1, $list2, $separator: auto, $bracketed: auto)
|
1909
2047
|
# @param $list1 [Sass::Script::Value::Base]
|
1910
2048
|
# @param $list2 [Sass::Script::Value::Base]
|
1911
2049
|
# @param $separator [Sass::Script::Value::String] The list separator to use.
|
1912
2050
|
# If this is `comma` or `space`, that separator will be used. If this is
|
1913
2051
|
# `auto` (the default), the separator is determined as explained above.
|
2052
|
+
# @param $bracketed [Sass::Script::Value::Base] Whether the resulting list
|
2053
|
+
# will be bracketed. If this is `auto` (the default), the separator is
|
2054
|
+
# determined as explained above.
|
1914
2055
|
# @return [Sass::Script::Value::List]
|
1915
|
-
def join(list1, list2,
|
2056
|
+
def join(list1, list2,
|
2057
|
+
separator = identifier("auto"), bracketed = identifier("auto"),
|
2058
|
+
kwargs = nil, *rest)
|
2059
|
+
if separator.is_a?(Hash)
|
2060
|
+
kwargs = separator
|
2061
|
+
separator = identifier("auto")
|
2062
|
+
elsif bracketed.is_a?(Hash)
|
2063
|
+
kwargs = bracketed
|
2064
|
+
bracketed = identifier("auto")
|
2065
|
+
elsif rest.last.is_a?(Hash)
|
2066
|
+
rest.unshift kwargs
|
2067
|
+
kwargs = rest.pop
|
2068
|
+
end
|
2069
|
+
|
2070
|
+
unless rest.empty?
|
2071
|
+
# Add 4 to rest.length because we don't want to count the kwargs hash,
|
2072
|
+
# which is always passed.
|
2073
|
+
raise ArgumentError.new("wrong number of arguments (#{rest.length + 4} for 2..4)")
|
2074
|
+
end
|
2075
|
+
|
2076
|
+
if kwargs
|
2077
|
+
separator = kwargs.delete("separator") || separator
|
2078
|
+
bracketed = kwargs.delete("bracketed") || bracketed
|
2079
|
+
|
2080
|
+
unless kwargs.empty?
|
2081
|
+
name, val = kwargs.to_a.first
|
2082
|
+
raise ArgumentError.new("Unknown argument $#{name} (#{val})")
|
2083
|
+
end
|
2084
|
+
end
|
2085
|
+
|
1916
2086
|
assert_type separator, :String, :separator
|
1917
2087
|
unless %w(auto space comma).include?(separator.value)
|
1918
2088
|
raise ArgumentError.new("Separator name must be space, comma, or auto")
|
1919
2089
|
end
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
2090
|
+
|
2091
|
+
list(list1.to_a + list2.to_a,
|
2092
|
+
separator:
|
2093
|
+
if separator.value == 'auto'
|
2094
|
+
list1.separator || list2.separator || :space
|
2095
|
+
else
|
2096
|
+
separator.value.to_sym
|
2097
|
+
end,
|
2098
|
+
bracketed:
|
2099
|
+
if bracketed.is_a?(Sass::Script::Value::String) && bracketed.value == 'auto'
|
2100
|
+
list1.bracketed
|
2101
|
+
else
|
2102
|
+
bracketed.to_bool
|
2103
|
+
end)
|
1926
2104
|
end
|
1927
|
-
|
1928
|
-
|
2105
|
+
# We don't actually take variable arguments or keyword arguments, but this
|
2106
|
+
# is the best way to take either `$separator` or `$bracketed` as keywords
|
2107
|
+
# without complaining about the other missing.
|
2108
|
+
declare :join, [:list1, :list2], :var_args => true, :var_kwargs => true
|
1929
2109
|
|
1930
2110
|
# Appends a single value onto the end of a list.
|
1931
2111
|
#
|
@@ -1953,12 +2133,13 @@ MESSAGE
|
|
1953
2133
|
unless %w(auto space comma).include?(separator.value)
|
1954
2134
|
raise ArgumentError.new("Separator name must be space, comma, or auto")
|
1955
2135
|
end
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
1961
|
-
|
2136
|
+
list.with_contents(list.to_a + [val],
|
2137
|
+
separator:
|
2138
|
+
if separator.value == 'auto'
|
2139
|
+
list.separator || :space
|
2140
|
+
else
|
2141
|
+
separator.value.to_sym
|
2142
|
+
end)
|
1962
2143
|
end
|
1963
2144
|
declare :append, [:list, :val]
|
1964
2145
|
declare :append, [:list, :val, :separator]
|
@@ -2028,7 +2209,20 @@ MESSAGE
|
|
2028
2209
|
def list_separator(list)
|
2029
2210
|
identifier((list.separator || :space).to_s)
|
2030
2211
|
end
|
2031
|
-
declare :
|
2212
|
+
declare :list_separator, [:list]
|
2213
|
+
|
2214
|
+
# Returns whether a list uses square brackets.
|
2215
|
+
#
|
2216
|
+
# @example
|
2217
|
+
# is-bracketed(1px 2px 3px) => false
|
2218
|
+
# is-bracketed([1px, 2px, 3px]) => true
|
2219
|
+
# @overload is_bracketed($list)
|
2220
|
+
# @param $list [Sass::Script::Value::Base]
|
2221
|
+
# @return [Sass::Script::Value::Bool]
|
2222
|
+
def is_bracketed(list)
|
2223
|
+
bool(list.bracketed)
|
2224
|
+
end
|
2225
|
+
declare :is_bracketed, [:list]
|
2032
2226
|
|
2033
2227
|
# Returns the value in a map associated with the given key. If the map
|
2034
2228
|
# doesn't have such a key, returns `null`.
|
@@ -2214,10 +2408,24 @@ MESSAGE
|
|
2214
2408
|
# $fn: nth;
|
2215
2409
|
# call($fn, (a b c), 2) => b
|
2216
2410
|
#
|
2217
|
-
# @overload call($
|
2218
|
-
# @param $
|
2411
|
+
# @overload call($function, $args...)
|
2412
|
+
# @param $function [Sass::Script::Value::Function] The function to call.
|
2219
2413
|
def call(name, *args)
|
2220
|
-
|
2414
|
+
unless name.is_a?(Sass::Script::Value::String) ||
|
2415
|
+
name.is_a?(Sass::Script::Value::Function)
|
2416
|
+
assert_type name, :Function, :function
|
2417
|
+
end
|
2418
|
+
if name.is_a?(Sass::Script::Value::String)
|
2419
|
+
name = if function_exists(name).to_bool
|
2420
|
+
get_function(name)
|
2421
|
+
else
|
2422
|
+
get_function(name, "css" => bool(true))
|
2423
|
+
end
|
2424
|
+
Sass::Util.sass_warn(<<WARNING)
|
2425
|
+
DEPRECATION WARNING: Passing a string to call() is deprecated and will be illegal
|
2426
|
+
in Sass 4.0. Use call(#{name.to_sass}) instead.
|
2427
|
+
WARNING
|
2428
|
+
end
|
2221
2429
|
kwargs = args.last.is_a?(Hash) ? args.pop : {}
|
2222
2430
|
funcall = Sass::Script::Tree::Funcall.new(
|
2223
2431
|
name.value,
|
@@ -2225,6 +2433,8 @@ MESSAGE
|
|
2225
2433
|
Sass::Util.map_vals(kwargs) {|v| Sass::Script::Tree::Literal.new(v)},
|
2226
2434
|
nil,
|
2227
2435
|
nil)
|
2436
|
+
funcall.line = environment.stack.frames.last.line
|
2437
|
+
funcall.filename = environment.stack.frames.last.filename
|
2228
2438
|
funcall.options = options
|
2229
2439
|
perform(funcall)
|
2230
2440
|
end
|
@@ -2313,12 +2523,12 @@ MESSAGE
|
|
2313
2523
|
#
|
2314
2524
|
# @overload function_exists($name)
|
2315
2525
|
# @param name [Sass::Script::Value::String] The name of the function to
|
2316
|
-
# check.
|
2526
|
+
# check or a function reference.
|
2317
2527
|
# @return [Sass::Script::Value::Bool] Whether the function is defined.
|
2318
2528
|
def function_exists(name)
|
2319
2529
|
assert_type name, :String, :name
|
2320
2530
|
exists = Sass::Script::Functions.callable?(name.value.tr("-", "_"))
|
2321
|
-
exists ||= environment.function(name.value)
|
2531
|
+
exists ||= environment.caller.function(name.value)
|
2322
2532
|
bool(exists)
|
2323
2533
|
end
|
2324
2534
|
declare :function_exists, [:name]
|
@@ -2341,6 +2551,31 @@ MESSAGE
|
|
2341
2551
|
end
|
2342
2552
|
declare :mixin_exists, [:name]
|
2343
2553
|
|
2554
|
+
# Check whether a mixin was passed a content block.
|
2555
|
+
#
|
2556
|
+
# Unless `content-exists()` is called directly from a mixin, an error will be raised.
|
2557
|
+
#
|
2558
|
+
# @example
|
2559
|
+
# @mixin needs-content {
|
2560
|
+
# @if not content-exists() {
|
2561
|
+
# @error "You must pass a content block!"
|
2562
|
+
# }
|
2563
|
+
# @content;
|
2564
|
+
# }
|
2565
|
+
#
|
2566
|
+
# @overload content_exists()
|
2567
|
+
# @return [Sass::Script::Value::Bool] Whether a content block was passed to the mixin.
|
2568
|
+
def content_exists
|
2569
|
+
# frames.last is the stack frame for this function,
|
2570
|
+
# so we use frames[-2] to get the frame before that.
|
2571
|
+
mixin_frame = environment.stack.frames[-2]
|
2572
|
+
unless mixin_frame && mixin_frame.type == :mixin
|
2573
|
+
raise Sass::SyntaxError.new("Cannot call content-exists() except within a mixin.")
|
2574
|
+
end
|
2575
|
+
bool(!environment.caller.content.nil?)
|
2576
|
+
end
|
2577
|
+
declare :content_exists, []
|
2578
|
+
|
2344
2579
|
# Return a string containing the value as its Sass representation.
|
2345
2580
|
#
|
2346
2581
|
# @overload inspect($value)
|
@@ -2663,10 +2898,7 @@ MESSAGE
|
|
2663
2898
|
yield(value.value), value.numerator_units, value.denominator_units)
|
2664
2899
|
end
|
2665
2900
|
|
2666
|
-
# @comment
|
2667
|
-
# rubocop:disable ParameterLists
|
2668
2901
|
def _adjust(color, amount, attr, range, op, units = "")
|
2669
|
-
# rubocop:enable ParameterLists
|
2670
2902
|
assert_type color, :Color, :color
|
2671
2903
|
assert_type amount, :Number, :amount
|
2672
2904
|
Sass::Util.check_range('Amount', range, amount, units)
|
@@ -2674,19 +2906,14 @@ MESSAGE
|
|
2674
2906
|
color.with(attr => color.send(attr).send(op, amount.value))
|
2675
2907
|
end
|
2676
2908
|
|
2677
|
-
def
|
2678
|
-
|
2679
|
-
|
2680
|
-
|
2681
|
-
|
2682
|
-
DEPRECATION WARNING: Passing a percentage as the alpha value to #{function}() will be
|
2683
|
-
interpreted differently in future versions of Sass. For now, use #{alpha.value} instead.
|
2684
|
-
WARNING
|
2909
|
+
def percentage_or_unitless(number, max, name)
|
2910
|
+
if number.unitless?
|
2911
|
+
number.value
|
2912
|
+
elsif number.is_unit?("%")
|
2913
|
+
max * number.value / 100.0;
|
2685
2914
|
else
|
2686
|
-
|
2687
|
-
|
2688
|
-
deprecated and will be an error in future versions of Sass. Use #{alpha.value} instead.
|
2689
|
-
WARNING
|
2915
|
+
raise ArgumentError.new(
|
2916
|
+
"$#{name}: Expected #{number} to have no units or \"%\"");
|
2690
2917
|
end
|
2691
2918
|
end
|
2692
2919
|
end
|