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/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
|