sass 3.4.25 → 3.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (237) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +1 -1
  3. data/CONTRIBUTING.md +3 -3
  4. data/README.md +17 -9
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/VERSION_NAME +1 -1
  8. data/extra/sass-spec-ref.sh +9 -1
  9. data/lib/sass.rb +0 -7
  10. data/lib/sass/cache_stores/filesystem.rb +1 -1
  11. data/lib/sass/css.rb +1 -2
  12. data/lib/sass/engine.rb +39 -29
  13. data/lib/sass/environment.rb +26 -5
  14. data/lib/sass/error.rb +2 -2
  15. data/lib/sass/exec/base.rb +2 -13
  16. data/lib/sass/exec/sass_scss.rb +1 -5
  17. data/lib/sass/features.rb +1 -0
  18. data/lib/sass/importers/filesystem.rb +6 -4
  19. data/lib/sass/logger/base.rb +11 -0
  20. data/lib/sass/plugin/compiler.rb +20 -50
  21. data/lib/sass/plugin/configuration.rb +2 -2
  22. data/lib/sass/railtie.rb +1 -1
  23. data/lib/sass/script/css_parser.rb +4 -1
  24. data/lib/sass/script/functions.rb +308 -81
  25. data/lib/sass/script/lexer.rb +63 -9
  26. data/lib/sass/script/parser.rb +287 -118
  27. data/lib/sass/script/tree/funcall.rb +35 -34
  28. data/lib/sass/script/tree/interpolation.rb +0 -3
  29. data/lib/sass/script/tree/list_literal.rb +23 -8
  30. data/lib/sass/script/tree/map_literal.rb +2 -2
  31. data/lib/sass/script/tree/node.rb +0 -8
  32. data/lib/sass/script/tree/operation.rb +1 -8
  33. data/lib/sass/script/value.rb +2 -0
  34. data/lib/sass/script/value/arg_list.rb +1 -1
  35. data/lib/sass/script/value/base.rb +17 -0
  36. data/lib/sass/script/value/callable.rb +25 -0
  37. data/lib/sass/script/value/color.rb +8 -2
  38. data/lib/sass/script/value/function.rb +19 -0
  39. data/lib/sass/script/value/helpers.rb +37 -11
  40. data/lib/sass/script/value/list.rb +35 -14
  41. data/lib/sass/script/value/map.rb +2 -2
  42. data/lib/sass/script/value/number.rb +3 -2
  43. data/lib/sass/scss/css_parser.rb +6 -1
  44. data/lib/sass/scss/parser.rb +145 -56
  45. data/lib/sass/scss/rx.rb +5 -11
  46. data/lib/sass/scss/static_parser.rb +20 -42
  47. data/lib/sass/selector.rb +4 -0
  48. data/lib/sass/selector/abstract_sequence.rb +7 -6
  49. data/lib/sass/selector/comma_sequence.rb +9 -5
  50. data/lib/sass/selector/pseudo.rb +20 -3
  51. data/lib/sass/selector/sequence.rb +35 -10
  52. data/lib/sass/selector/simple.rb +9 -2
  53. data/lib/sass/selector/simple_sequence.rb +8 -4
  54. data/lib/sass/source/map.rb +2 -6
  55. data/lib/sass/stack.rb +21 -1
  56. data/lib/sass/tree/charset_node.rb +1 -1
  57. data/lib/sass/tree/prop_node.rb +45 -53
  58. data/lib/sass/tree/rule_node.rb +6 -8
  59. data/lib/sass/tree/visitors/check_nesting.rb +1 -1
  60. data/lib/sass/tree/visitors/convert.rb +2 -3
  61. data/lib/sass/tree/visitors/cssize.rb +4 -15
  62. data/lib/sass/tree/visitors/deep_copy.rb +1 -1
  63. data/lib/sass/tree/visitors/extend.rb +2 -8
  64. data/lib/sass/tree/visitors/perform.rb +23 -15
  65. data/lib/sass/tree/visitors/set_options.rb +1 -1
  66. data/lib/sass/tree/visitors/to_css.rb +49 -22
  67. data/lib/sass/util.rb +72 -310
  68. data/lib/sass/util/multibyte_string_scanner.rb +127 -131
  69. data/lib/sass/util/normalized_map.rb +1 -8
  70. data/lib/sass/version.rb +0 -4
  71. metadata +55 -202
  72. data/Rakefile +0 -453
  73. data/lib/sass/script/css_variable_warning.rb +0 -52
  74. data/lib/sass/util/cross_platform_random.rb +0 -19
  75. data/lib/sass/util/ordered_hash.rb +0 -192
  76. data/test/sass-spec.yml +0 -3
  77. data/test/sass/cache_test.rb +0 -131
  78. data/test/sass/callbacks_test.rb +0 -61
  79. data/test/sass/compiler_test.rb +0 -236
  80. data/test/sass/conversion_test.rb +0 -2188
  81. data/test/sass/css2sass_test.rb +0 -526
  82. data/test/sass/css_variable_test.rb +0 -132
  83. data/test/sass/data/hsl-rgb.txt +0 -319
  84. data/test/sass/encoding_test.rb +0 -219
  85. data/test/sass/engine_test.rb +0 -3447
  86. data/test/sass/exec_test.rb +0 -96
  87. data/test/sass/extend_test.rb +0 -1733
  88. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  89. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  90. data/test/sass/functions_test.rb +0 -1977
  91. data/test/sass/importer_test.rb +0 -421
  92. data/test/sass/logger_test.rb +0 -58
  93. data/test/sass/mock_importer.rb +0 -49
  94. data/test/sass/more_results/more1.css +0 -9
  95. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  96. data/test/sass/more_results/more_import.css +0 -29
  97. data/test/sass/more_templates/_more_partial.sass +0 -2
  98. data/test/sass/more_templates/more1.sass +0 -23
  99. data/test/sass/more_templates/more_import.sass +0 -11
  100. data/test/sass/plugin_test.rb +0 -556
  101. data/test/sass/results/alt.css +0 -4
  102. data/test/sass/results/basic.css +0 -9
  103. data/test/sass/results/cached_import_option.css +0 -3
  104. data/test/sass/results/compact.css +0 -5
  105. data/test/sass/results/complex.css +0 -86
  106. data/test/sass/results/compressed.css +0 -1
  107. data/test/sass/results/expanded.css +0 -19
  108. data/test/sass/results/filename_fn.css +0 -3
  109. data/test/sass/results/if.css +0 -3
  110. data/test/sass/results/import.css +0 -31
  111. data/test/sass/results/import_charset.css +0 -5
  112. data/test/sass/results/import_charset_1_8.css +0 -5
  113. data/test/sass/results/import_charset_ibm866.css +0 -5
  114. data/test/sass/results/import_content.css +0 -1
  115. data/test/sass/results/line_numbers.css +0 -49
  116. data/test/sass/results/mixins.css +0 -95
  117. data/test/sass/results/multiline.css +0 -24
  118. data/test/sass/results/nested.css +0 -22
  119. data/test/sass/results/options.css +0 -1
  120. data/test/sass/results/parent_ref.css +0 -13
  121. data/test/sass/results/script.css +0 -16
  122. data/test/sass/results/scss_import.css +0 -31
  123. data/test/sass/results/scss_importee.css +0 -2
  124. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  125. data/test/sass/results/subdir/subdir.css +0 -3
  126. data/test/sass/results/units.css +0 -11
  127. data/test/sass/results/warn.css +0 -0
  128. data/test/sass/results/warn_imported.css +0 -0
  129. data/test/sass/script_conversion_test.rb +0 -357
  130. data/test/sass/script_test.rb +0 -1431
  131. data/test/sass/scss/css_test.rb +0 -1281
  132. data/test/sass/scss/rx_test.rb +0 -160
  133. data/test/sass/scss/scss_test.rb +0 -4205
  134. data/test/sass/scss/test_helper.rb +0 -37
  135. data/test/sass/source_map_test.rb +0 -1055
  136. data/test/sass/superselector_test.rb +0 -210
  137. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  138. data/test/sass/templates/_double_import_loop2.sass +0 -1
  139. data/test/sass/templates/_filename_fn_import.scss +0 -11
  140. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  141. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  142. data/test/sass/templates/_imported_content.sass +0 -3
  143. data/test/sass/templates/_partial.sass +0 -2
  144. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  145. data/test/sass/templates/alt.sass +0 -16
  146. data/test/sass/templates/basic.sass +0 -23
  147. data/test/sass/templates/bork1.sass +0 -2
  148. data/test/sass/templates/bork2.sass +0 -2
  149. data/test/sass/templates/bork3.sass +0 -2
  150. data/test/sass/templates/bork4.sass +0 -2
  151. data/test/sass/templates/bork5.sass +0 -3
  152. data/test/sass/templates/cached_import_option.scss +0 -3
  153. data/test/sass/templates/compact.sass +0 -17
  154. data/test/sass/templates/complex.sass +0 -305
  155. data/test/sass/templates/compressed.sass +0 -15
  156. data/test/sass/templates/double_import_loop1.sass +0 -1
  157. data/test/sass/templates/expanded.sass +0 -17
  158. data/test/sass/templates/filename_fn.scss +0 -18
  159. data/test/sass/templates/if.sass +0 -11
  160. data/test/sass/templates/import.sass +0 -12
  161. data/test/sass/templates/import_charset.sass +0 -9
  162. data/test/sass/templates/import_charset_1_8.sass +0 -6
  163. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  164. data/test/sass/templates/import_content.sass +0 -4
  165. data/test/sass/templates/importee.less +0 -2
  166. data/test/sass/templates/importee.sass +0 -19
  167. data/test/sass/templates/line_numbers.sass +0 -13
  168. data/test/sass/templates/mixin_bork.sass +0 -5
  169. data/test/sass/templates/mixins.sass +0 -76
  170. data/test/sass/templates/multiline.sass +0 -20
  171. data/test/sass/templates/nested.sass +0 -25
  172. data/test/sass/templates/nested_bork1.sass +0 -2
  173. data/test/sass/templates/nested_bork2.sass +0 -2
  174. data/test/sass/templates/nested_bork3.sass +0 -2
  175. data/test/sass/templates/nested_bork4.sass +0 -2
  176. data/test/sass/templates/nested_import.sass +0 -2
  177. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  178. data/test/sass/templates/options.sass +0 -2
  179. data/test/sass/templates/parent_ref.sass +0 -25
  180. data/test/sass/templates/same_name_different_ext.sass +0 -2
  181. data/test/sass/templates/same_name_different_ext.scss +0 -1
  182. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  183. data/test/sass/templates/script.sass +0 -101
  184. data/test/sass/templates/scss_import.scss +0 -12
  185. data/test/sass/templates/scss_importee.scss +0 -1
  186. data/test/sass/templates/single_import_loop.sass +0 -1
  187. data/test/sass/templates/subdir/import_up1.scss +0 -1
  188. data/test/sass/templates/subdir/import_up2.scss +0 -1
  189. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  190. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  191. data/test/sass/templates/subdir/subdir.sass +0 -6
  192. data/test/sass/templates/units.sass +0 -11
  193. data/test/sass/templates/warn.sass +0 -3
  194. data/test/sass/templates/warn_imported.sass +0 -4
  195. data/test/sass/test_helper.rb +0 -8
  196. data/test/sass/util/multibyte_string_scanner_test.rb +0 -155
  197. data/test/sass/util/normalized_map_test.rb +0 -51
  198. data/test/sass/util/subset_map_test.rb +0 -91
  199. data/test/sass/util_test.rb +0 -438
  200. data/test/sass/value_helpers_test.rb +0 -179
  201. data/test/test_helper.rb +0 -110
  202. data/vendor/listen/CHANGELOG.md +0 -1
  203. data/vendor/listen/CONTRIBUTING.md +0 -38
  204. data/vendor/listen/Gemfile +0 -20
  205. data/vendor/listen/Guardfile +0 -8
  206. data/vendor/listen/LICENSE +0 -20
  207. data/vendor/listen/README.md +0 -349
  208. data/vendor/listen/Rakefile +0 -5
  209. data/vendor/listen/Vagrantfile +0 -96
  210. data/vendor/listen/lib/listen.rb +0 -54
  211. data/vendor/listen/lib/listen/adapter.rb +0 -327
  212. data/vendor/listen/lib/listen/adapters/bsd.rb +0 -75
  213. data/vendor/listen/lib/listen/adapters/darwin.rb +0 -48
  214. data/vendor/listen/lib/listen/adapters/linux.rb +0 -81
  215. data/vendor/listen/lib/listen/adapters/polling.rb +0 -58
  216. data/vendor/listen/lib/listen/adapters/windows.rb +0 -91
  217. data/vendor/listen/lib/listen/directory_record.rb +0 -406
  218. data/vendor/listen/lib/listen/listener.rb +0 -323
  219. data/vendor/listen/lib/listen/turnstile.rb +0 -32
  220. data/vendor/listen/lib/listen/version.rb +0 -3
  221. data/vendor/listen/listen.gemspec +0 -28
  222. data/vendor/listen/spec/listen/adapter_spec.rb +0 -149
  223. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +0 -36
  224. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -37
  225. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -47
  226. data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
  227. data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -30
  228. data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1250
  229. data/vendor/listen/spec/listen/listener_spec.rb +0 -258
  230. data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
  231. data/vendor/listen/spec/listen_spec.rb +0 -67
  232. data/vendor/listen/spec/spec_helper.rb +0 -25
  233. data/vendor/listen/spec/support/adapter_helper.rb +0 -666
  234. data/vendor/listen/spec/support/directory_record_helper.rb +0 -57
  235. data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
  236. data/vendor/listen/spec/support/listeners_helper.rb +0 -179
  237. data/vendor/listen/spec/support/platform_helper.rb +0 -15
@@ -13,6 +13,11 @@ module Sass::Script::Tree
13
13
  # @return [String]
14
14
  attr_reader :name
15
15
 
16
+ # The callable to be invoked
17
+ #
18
+ # @return [Sass::Callable] or nil if no callable is provided.
19
+ attr_reader :callable
20
+
16
21
  # The arguments to the function.
17
22
  #
18
23
  # @return [Array<Node>]
@@ -39,13 +44,19 @@ module Sass::Script::Tree
39
44
  # @return [Node?]
40
45
  attr_accessor :kwarg_splat
41
46
 
42
- # @param name [String] See \{#name}
47
+ # @param name_or_callable [String, Sass::Callable] See \{#name}
43
48
  # @param args [Array<Node>] See \{#args}
44
49
  # @param keywords [Sass::Util::NormalizedMap<Node>] See \{#keywords}
45
50
  # @param splat [Node] See \{#splat}
46
51
  # @param kwarg_splat [Node] See \{#kwarg_splat}
47
- def initialize(name, args, keywords, splat, kwarg_splat)
48
- @name = name
52
+ def initialize(name_or_callable, args, keywords, splat, kwarg_splat)
53
+ if name_or_callable.is_a?(Sass::Callable)
54
+ @callable = name_or_callable
55
+ @name = name_or_callable.name
56
+ else
57
+ @callable = nil
58
+ @name = name_or_callable
59
+ end
49
60
  @args = args
50
61
  @keywords = keywords
51
62
  @splat = splat
@@ -56,15 +67,12 @@ module Sass::Script::Tree
56
67
  # @return [String] A string representation of the function call
57
68
  def inspect
58
69
  args = @args.map {|a| a.inspect}.join(', ')
59
- keywords = Sass::Util.hash_to_a(@keywords.as_stored).
60
- map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
61
- # rubocop:disable RedundantSelf
70
+ keywords = @keywords.as_stored.to_a.map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
62
71
  if self.splat
63
72
  splat = args.empty? && keywords.empty? ? "" : ", "
64
73
  splat = "#{splat}#{self.splat.inspect}..."
65
74
  splat = "#{splat}, #{kwarg_splat.inspect}..." if kwarg_splat
66
75
  end
67
- # rubocop:enable RedundantSelf
68
76
  "#{name}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
69
77
  end
70
78
 
@@ -77,15 +85,12 @@ module Sass::Script::Tree
77
85
  end
78
86
 
79
87
  args = @args.map(&arg_to_sass)
80
- keywords = Sass::Util.hash_to_a(@keywords.as_stored).
81
- map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}
88
+ keywords = @keywords.as_stored.to_a.map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}
82
89
 
83
- # rubocop:disable RedundantSelf
84
90
  if self.splat
85
91
  splat = "#{arg_to_sass[self.splat]}..."
86
92
  kwarg_splat = "#{arg_to_sass[self.kwarg_splat]}..." if self.kwarg_splat
87
93
  end
88
- # rubocop:enable RedundantSelf
89
94
 
90
95
  arglist = [args, splat, keywords, kwarg_splat].flatten.compact.join(', ')
91
96
  "#{dasherize(name, opts)}(#{arglist})"
@@ -120,27 +125,31 @@ module Sass::Script::Tree
120
125
  # @return [Sass::Script::Value] The SassScript object that is the value of the function call
121
126
  # @raise [Sass::SyntaxError] if the function call raises an ArgumentError
122
127
  def _perform(environment)
123
- args = Sass::Util.enum_with_index(@args).
128
+ args = @args.each_with_index.
124
129
  map {|a, i| perform_arg(a, environment, signature && signature.args[i])}
125
130
  keywords = Sass::Util.map_hash(@keywords) do |k, v|
126
131
  [k, perform_arg(v, environment, k.tr('-', '_'))]
127
132
  end
128
133
  splat = Sass::Tree::Visitors::Perform.perform_splat(
129
134
  @splat, keywords, @kwarg_splat, environment)
130
- if (fn = environment.function(@name))
131
- css_variable_warning.warn! if css_variable_warning
132
- return without_original(perform_sass_fn(fn, args, splat, environment))
135
+
136
+ fn = @callable || environment.function(@name)
137
+
138
+ if fn && fn.origin == :stylesheet
139
+ environment.stack.with_function(filename, line, name) do
140
+ return without_original(perform_sass_fn(fn, args, splat, environment))
141
+ end
133
142
  end
134
143
 
135
144
  args = construct_ruby_args(ruby_name, args, splat, environment)
136
145
 
137
- if Sass::Script::Functions.callable?(ruby_name)
138
- css_variable_warning.warn! if css_variable_warning
139
-
146
+ if Sass::Script::Functions.callable?(ruby_name) && (!fn || fn.origin == :builtin)
140
147
  local_environment = Sass::Environment.new(environment.global_env, environment.options)
141
148
  local_environment.caller = Sass::ReadOnlyEnvironment.new(environment, environment.options)
142
- result = opts(Sass::Script::Functions::EvaluationContext.new(
143
- local_environment).send(ruby_name, *args))
149
+ result = local_environment.stack.with_function(filename, line, name) do
150
+ opts(Sass::Script::Functions::EvaluationContext.new(
151
+ local_environment).send(ruby_name, *args))
152
+ end
144
153
  without_original(result)
145
154
  else
146
155
  opts(to_literal(args))
@@ -206,6 +215,7 @@ module Sass::Script::Tree
206
215
  raise Sass::SyntaxError.new(
207
216
  "#{args[signature.args.size].inspect} is not a keyword argument for `#{name}'")
208
217
  elsif keywords.empty?
218
+ args << {} if signature.var_kwargs
209
219
  return args
210
220
  end
211
221
 
@@ -271,30 +281,21 @@ module Sass::Script::Tree
271
281
  message = "wrong number of arguments (#{given} for #{expected})"
272
282
  end
273
283
  elsif Sass::Util.jruby?
274
- if Sass::Util.jruby1_6?
275
- should_maybe_raise = e.message =~ /^wrong number of arguments \((\d+) for (\d+)\)/ &&
276
- # The one case where JRuby does include the Ruby name of the function
277
- # is manually-thrown ArgumentErrors, which are indistinguishable from
278
- # legitimate ArgumentErrors. We treat both of these as
279
- # Sass::SyntaxErrors even though it can hide Ruby errors.
280
- e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
281
- else
282
- should_maybe_raise =
283
- e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for (\d+)\)/
284
- given, expected = $1, $2
285
- end
284
+ should_maybe_raise =
285
+ e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for (\d+)\)/
286
+ given, expected = $1, $2
286
287
 
287
288
  if should_maybe_raise
288
289
  # JRuby 1.7 includes __send__ before send and _perform.
289
290
  trace = e.backtrace.dup
290
- raise e if !Sass::Util.jruby1_6? && trace.shift !~ /:in `__send__'$/
291
+ raise e if trace.shift !~ /:in `__send__'$/
291
292
 
292
293
  # JRuby (as of 1.7.2) doesn't put the actual method
293
294
  # for which the argument error was thrown in the backtrace, so we
294
295
  # detect whether our send threw an argument error.
295
296
  if !(trace[0] =~ /:in `send'$/ && trace[1] =~ /:in `_perform'$/)
296
297
  raise e
297
- elsif !Sass::Util.jruby1_6?
298
+ else
298
299
  # JRuby 1.7 doesn't use standard formatting for its ArgumentErrors.
299
300
  message = "wrong number of arguments (#{given} for #{expected})"
300
301
  end
@@ -47,10 +47,7 @@ module Sass::Script::Tree
47
47
  # @param wa [Boolean] See {Interpolation#whitespace_after}
48
48
  # @param originally_text [Boolean] See {Interpolation#originally_text}
49
49
  # @param warn_for_color [Boolean] See {Interpolation#warn_for_color}
50
- # @comment
51
- # rubocop:disable ParameterLists
52
50
  def initialize(before, mid, after, wb, wa, opts = {})
53
- # rubocop:enable ParameterLists
54
51
  @before = before
55
52
  @mid = mid
56
53
  @after = after
@@ -13,13 +13,20 @@ module Sass::Script::Tree
13
13
  # @return [Symbol]
14
14
  attr_reader :separator
15
15
 
16
+ # Whether the list is surrounded by square brackets.
17
+ #
18
+ # @return [Boolean]
19
+ attr_reader :bracketed
20
+
16
21
  # Creates a new list literal.
17
22
  #
18
23
  # @param elements [Array<Node>] See \{#elements}
19
24
  # @param separator [Symbol] See \{#separator}
20
- def initialize(elements, separator)
25
+ # @param bracketed [Boolean] See \{#bracketed}
26
+ def initialize(elements, separator: nil, bracketed: false)
21
27
  @elements = elements
22
28
  @separator = separator
29
+ @bracketed = bracketed
23
30
  end
24
31
 
25
32
  # @see Node#children
@@ -27,7 +34,7 @@ module Sass::Script::Tree
27
34
 
28
35
  # @see Value#to_sass
29
36
  def to_sass(opts = {})
30
- return "()" if elements.empty?
37
+ return bracketed ? "[]" : "()" if elements.empty?
31
38
  members = elements.map do |v|
32
39
  if element_needs_parens?(v)
33
40
  "(#{v.to_sass(opts)})"
@@ -36,9 +43,12 @@ module Sass::Script::Tree
36
43
  end
37
44
  end
38
45
 
39
- return "(#{members.first},)" if separator == :comma && members.length == 1
46
+ if separator == :comma && members.length == 1
47
+ return "#{bracketed ? '[' : '('}#{members.first},#{bracketed ? ']' : ')'}"
48
+ end
40
49
 
41
- members.join(sep_str(nil))
50
+ contents = members.join(sep_str(nil))
51
+ bracketed ? "[#{contents}]" : contents
42
52
  end
43
53
 
44
54
  # @see Node#deep_copy
@@ -49,7 +59,9 @@ module Sass::Script::Tree
49
59
  end
50
60
 
51
61
  def inspect
52
- "(#{elements.map {|e| e.inspect}.join(separator == :space ? ' ' : ', ')})"
62
+ (bracketed ? '[' : '(') +
63
+ elements.map {|e| e.inspect}.join(separator == :space ? ' ' : ', ') +
64
+ (bracketed ? ']' : ')')
53
65
  end
54
66
 
55
67
  def force_division!
@@ -61,7 +73,8 @@ module Sass::Script::Tree
61
73
  def _perform(environment)
62
74
  list = Sass::Script::Value::List.new(
63
75
  elements.map {|e| e.perform(environment)},
64
- separator)
76
+ separator: separator,
77
+ bracketed: bracketed)
65
78
  list.source_range = source_range
66
79
  list.options = options
67
80
  list
@@ -73,8 +86,10 @@ module Sass::Script::Tree
73
86
  # when serialized to Sass.
74
87
  def element_needs_parens?(element)
75
88
  if element.is_a?(ListLiteral)
76
- return Sass::Script::Parser.precedence_of(element.separator) <=
77
- Sass::Script::Parser.precedence_of(separator)
89
+ return false if element.elements.length < 2
90
+ return false if element.bracketed
91
+ return Sass::Script::Parser.precedence_of(element.separator || :space) <=
92
+ Sass::Script::Parser.precedence_of(separator || :space)
78
93
  end
79
94
 
80
95
  return false unless separator == :space
@@ -49,14 +49,14 @@ module Sass::Script::Tree
49
49
  # @see Node#_perform
50
50
  def _perform(environment)
51
51
  keys = Set.new
52
- map = Sass::Script::Value::Map.new(Sass::Util.to_hash(pairs.map do |(k, v)|
52
+ map = Sass::Script::Value::Map.new(Hash[pairs.map do |(k, v)|
53
53
  k, v = k.perform(environment), v.perform(environment)
54
54
  if keys.include?(k)
55
55
  raise Sass::SyntaxError.new("Duplicate key #{k.inspect} in map #{to_sass}.")
56
56
  end
57
57
  keys << k
58
58
  [k, v]
59
- end))
59
+ end])
60
60
  map.options = options
61
61
  map
62
62
  end
@@ -23,14 +23,6 @@ module Sass::Script::Tree
23
23
  # @return [String]
24
24
  attr_accessor :filename
25
25
 
26
- # The warning that this node should emit if it executes in a way that's not
27
- # safe for a CSS variable value.
28
- #
29
- # This is `nil` if this is not in a CSS variable value.
30
- #
31
- # @return [Sass::Script::CssVariableWarning]
32
- attr_accessor :css_variable_warning
33
-
34
26
  # Sets the options hash for this node,
35
27
  # as well as for all child nodes.
36
28
  # See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
@@ -81,13 +81,6 @@ module Sass::Script::Tree
81
81
  "Invalid null operation: \"#{value1.inspect} #{@operator} #{value2.inspect}\".")
82
82
  end
83
83
 
84
- if css_variable_warning && @operator == :div &&
85
- !(value1.is_a?(Sass::Script::Value::Number) && value1.original &&
86
- value2.is_a?(Sass::Script::Value::Number) && value2.original) &&
87
- !(value1.is_a?(Sass::Script::Value::String) && value2.is_a?(Sass::Script::Value::String))
88
- css_variable_warning.warn!
89
- end
90
-
91
84
  begin
92
85
  result = opts(value1.send(@operator, value2))
93
86
  rescue NoMethodError => e
@@ -118,7 +111,7 @@ module Sass::Script::Tree
118
111
  @@color_arithmetic_deprecation.warn(filename, line, <<WARNING)
119
112
  The operation `#{value1} #{@operator} #{value2}` is deprecated and will be an error in future versions.
120
113
  Consider using Sass's color functions instead.
121
- http://sass-lang.com/documentation/Sass/Script/Functions.html#other_color_functions
114
+ https://sass-lang.com/documentation/Sass/Script/Functions.html#other_color_functions
122
115
  WARNING
123
116
  end
124
117
 
@@ -9,3 +9,5 @@ require 'sass/script/value/null'
9
9
  require 'sass/script/value/list'
10
10
  require 'sass/script/value/arg_list'
11
11
  require 'sass/script/value/map'
12
+ require 'sass/script/value/callable'
13
+ require 'sass/script/value/function'
@@ -17,7 +17,7 @@ module Sass::Script::Value
17
17
  # @param keywords [Hash<String, Value>, NormalizedMap<Value>] See \{#keywords}
18
18
  # @param separator [String] See \{List#separator}.
19
19
  def initialize(value, keywords, separator)
20
- super(value, separator)
20
+ super(value, separator: separator)
21
21
  if keywords.is_a?(Sass::Util::NormalizedMap)
22
22
  @keywords = keywords
23
23
  else
@@ -192,6 +192,12 @@ MSG
192
192
  # @return [Symbol]
193
193
  def separator; nil; end
194
194
 
195
+ # Whether the value is surrounded by square brackets. For non-list values,
196
+ # this will be `false`.
197
+ #
198
+ # @return [Boolean]
199
+ def bracketed; false; end
200
+
195
201
  # Returns the value of this value as a list.
196
202
  # Single values are considered the same as single-element lists.
197
203
  #
@@ -228,6 +234,17 @@ MSG
228
234
  false
229
235
  end
230
236
 
237
+ # Creates a new list containing `contents` but with the same brackets and
238
+ # separators as this object, when interpreted as a list.
239
+ #
240
+ # @param contents [Array<Value>] The contents of the new list.
241
+ # @param separator [Symbol] The separator of the new list. Defaults to \{#separator}.
242
+ # @param bracketed [Boolean] Whether the new list is bracketed. Defaults to \{#bracketed}.
243
+ # @return [Sass::Script::Value::List]
244
+ def with_contents(contents, separator: self.separator, bracketed: self.bracketed)
245
+ Sass::Script::Value::List.new(contents, separator: separator, bracketed: bracketed)
246
+ end
247
+
231
248
  protected
232
249
 
233
250
  # Evaluates the value.
@@ -0,0 +1,25 @@
1
+ module Sass::Script::Value
2
+ # A SassScript object representing a null value.
3
+ class Callable < Base
4
+ # Constructs a Callable value for use in SassScript.
5
+ #
6
+ # @param callable [Sass::Callable] The callable to be used when the
7
+ # callable is called.
8
+ def initialize(callable)
9
+ super(callable)
10
+ end
11
+
12
+ def to_s(opts = {})
13
+ raise Sass::SyntaxError.new("#{to_sass} isn't a valid CSS value.")
14
+ end
15
+
16
+ def inspect
17
+ to_sass
18
+ end
19
+
20
+ # @abstract
21
+ def to_sass
22
+ Sass::Util.abstract(self)
23
+ end
24
+ end
25
+ end
@@ -277,13 +277,14 @@ module Sass::Script::Value
277
277
  #
278
278
  # @return [Color]
279
279
  def self.from_hex(hex_string, alpha = nil)
280
- unless hex_string =~ /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i ||
281
- hex_string =~ /^#?([0-9a-f])([0-9a-f])([0-9a-f])$/i
280
+ unless hex_string =~ /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?$/i ||
281
+ hex_string =~ /^#?([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])?$/i
282
282
  raise ArgumentError.new("#{hex_string.inspect} is not a valid hex color.")
283
283
  end
284
284
  red = $1.ljust(2, $1).to_i(16)
285
285
  green = $2.ljust(2, $2).to_i(16)
286
286
  blue = $3.ljust(2, $3).to_i(16)
287
+ alpha = $4.ljust(2, $4).to_i(16).to_f / 0xff if $4
287
288
 
288
289
  hex_string = "##{hex_string}" unless hex_string[0] == ?#
289
290
  attrs = {:red => red, :green => green, :blue => blue, :representation => hex_string}
@@ -563,6 +564,11 @@ module Sass::Script::Value
563
564
  def to_s(opts = {})
564
565
  return smallest if options[:style] == :compressed
565
566
  return representation if representation
567
+
568
+ # IE10 doesn't properly support the color name "transparent", so we emit
569
+ # generated transparent colors as rgba(0, 0, 0, 0) in favor of that. See
570
+ # #1782.
571
+ return rgba_str if Number.basically_equal?(alpha, 0)
566
572
  return name if name
567
573
  alpha? ? rgba_str : hex_str
568
574
  end
@@ -0,0 +1,19 @@
1
+ module Sass::Script::Value
2
+ # A SassScript object representing a function.
3
+ class Function < Callable
4
+ # Constructs a Function value for use in SassScript.
5
+ #
6
+ # @param function [Sass::Callable] The callable to be used when the
7
+ # function is invoked.
8
+ def initialize(function)
9
+ unless function.type == "function"
10
+ raise ArgumentError.new("A callable of type function was expected.")
11
+ end
12
+ super
13
+ end
14
+
15
+ def to_sass
16
+ %{get-function("#{value.name}")}
17
+ end
18
+ end
19
+ end
@@ -1,8 +1,6 @@
1
1
  module Sass::Script::Value
2
2
  # Provides helper functions for creating sass values from within ruby methods.
3
3
  # @since `3.3.0`
4
- # @comment
5
- # rubocop:disable ModuleLength
6
4
  module Helpers
7
5
  # Construct a Sass Boolean.
8
6
  #
@@ -68,26 +66,35 @@ module Sass::Script::Value
68
66
  Number.new(number, *parse_unit_string(unit_string))
69
67
  end
70
68
 
71
- # @overload list(*elements, separator)
69
+ # @overload list(*elements, separator:, bracketed: false)
72
70
  # Create a space-separated list from the arguments given.
73
71
  # @param elements [Array<Sass::Script::Value::Base>] Each argument will be a list element.
74
72
  # @param separator [Symbol] Either :space or :comma.
73
+ # @param bracketed [Boolean] Whether the list uses square brackets.
75
74
  # @return [Sass::Script::Value::List] The space separated list.
76
75
  #
77
- # @overload list(array, separator)
76
+ # @overload list(array, separator:, bracketed: false)
78
77
  # Create a space-separated list from the array given.
79
78
  # @param array [Array<Sass::Script::Value::Base>] A ruby array of Sass values
80
79
  # to make into a list.
80
+ # @param separator [Symbol] Either :space or :comma.
81
+ # @param bracketed [Boolean] Whether the list uses square brackets.
81
82
  # @return [Sass::Script::Value::List] The space separated list.
82
- def list(*elements)
83
- unless elements.last.is_a?(Symbol)
84
- raise ArgumentError.new("A list type of :space or :comma must be specified.")
83
+ def list(*elements, separator: nil, bracketed: false)
84
+ # Support passing separator as the last value in elements for
85
+ # backwards-compatibility.
86
+ if separator.nil?
87
+ if elements.last.is_a?(Symbol)
88
+ separator = elements.pop
89
+ else
90
+ raise ArgumentError.new("A separator of :space or :comma must be specified.")
91
+ end
85
92
  end
86
- separator = elements.pop
93
+
87
94
  if elements.size == 1 && elements.first.is_a?(Array)
88
95
  elements = elements.first
89
96
  end
90
- Sass::Script::Value::List.new(elements, separator)
97
+ Sass::Script::Value::List.new(elements, separator: separator, bracketed: bracketed)
91
98
  end
92
99
 
93
100
  # Construct a Sass map.
@@ -196,14 +203,33 @@ module Sass::Script::Value
196
203
  raise ArgumentError.new(err)
197
204
  end
198
205
 
199
- # Returns true when the literal is a string containing a calc()
206
+ # Returns true when the literal is a string containing a calc().
207
+ #
208
+ # Use \{#special_number?} in preference to this.
200
209
  #
201
210
  # @param literal [Sass::Script::Value::Base] The value to check
202
- # @return boolean
211
+ # @return Boolean
203
212
  def calc?(literal)
204
213
  literal.is_a?(Sass::Script::Value::String) && literal.value =~ /calc\(/
205
214
  end
206
215
 
216
+ # Returns true when the literal is a string containing a var().
217
+ #
218
+ # @param literal [Sass::Script::Value::Base] The value to check
219
+ # @return Boolean
220
+ def var?(literal)
221
+ literal.is_a?(Sass::Script::Value::String) && literal.value =~ /var\(/
222
+ end
223
+
224
+ # Returns whether the literal is a special CSS value that may evaluate to a
225
+ # number, such as `calc()` or `var()`.
226
+ #
227
+ # @param literal [Sass::Script::Value::Base] The value to check
228
+ # @return Boolean
229
+ def special_number?(literal)
230
+ literal.is_a?(Sass::Script::Value::String) && literal.value =~ /(calc|var)\(/
231
+ end
232
+
207
233
  private
208
234
 
209
235
  # Converts a user-provided selector into string form or throws an