sass 3.7.4 → 4.0.0.alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. checksums.yaml +13 -5
  2. data/.yardopts +1 -1
  3. data/CODE_OF_CONDUCT.md +1 -1
  4. data/CONTRIBUTING.md +1 -146
  5. data/MIT-LICENSE +1 -1
  6. data/README.md +25 -39
  7. data/Rakefile +274 -0
  8. data/VERSION +1 -1
  9. data/VERSION_DATE +1 -1
  10. data/lib/sass.rb +3 -3
  11. data/lib/sass/cache_stores/filesystem.rb +2 -2
  12. data/lib/sass/cache_stores/memory.rb +5 -4
  13. data/lib/sass/callbacks.rb +2 -2
  14. data/lib/sass/css.rb +12 -12
  15. data/lib/sass/engine.rb +44 -62
  16. data/lib/sass/environment.rb +7 -35
  17. data/lib/sass/error.rb +14 -14
  18. data/lib/sass/exec/base.rb +14 -3
  19. data/lib/sass/exec/sass_convert.rb +6 -20
  20. data/lib/sass/exec/sass_scss.rb +29 -5
  21. data/lib/sass/features.rb +2 -3
  22. data/lib/sass/importers/filesystem.rb +6 -11
  23. data/lib/sass/logger.rb +3 -8
  24. data/lib/sass/logger/base.rb +2 -19
  25. data/lib/sass/plugin.rb +2 -3
  26. data/lib/sass/plugin/compiler.rb +67 -48
  27. data/lib/sass/plugin/configuration.rb +3 -3
  28. data/lib/sass/plugin/merb.rb +1 -1
  29. data/lib/sass/plugin/rack.rb +3 -3
  30. data/lib/sass/plugin/staleness_checker.rb +3 -3
  31. data/lib/sass/railtie.rb +1 -1
  32. data/lib/sass/script.rb +3 -3
  33. data/lib/sass/script/css_parser.rb +15 -5
  34. data/lib/sass/script/functions.rb +121 -337
  35. data/lib/sass/script/lexer.rb +36 -102
  36. data/lib/sass/script/parser.rb +153 -529
  37. data/lib/sass/script/tree/funcall.rb +34 -42
  38. data/lib/sass/script/tree/interpolation.rb +26 -171
  39. data/lib/sass/script/tree/list_literal.rb +8 -23
  40. data/lib/sass/script/tree/map_literal.rb +2 -2
  41. data/lib/sass/script/tree/node.rb +3 -3
  42. data/lib/sass/script/tree/operation.rb +16 -43
  43. data/lib/sass/script/tree/string_interpolation.rb +43 -64
  44. data/lib/sass/script/tree/variable.rb +1 -1
  45. data/lib/sass/script/value.rb +0 -2
  46. data/lib/sass/script/value/arg_list.rb +1 -1
  47. data/lib/sass/script/value/base.rb +9 -27
  48. data/lib/sass/script/value/color.rb +18 -26
  49. data/lib/sass/script/value/helpers.rb +18 -44
  50. data/lib/sass/script/value/list.rb +14 -35
  51. data/lib/sass/script/value/map.rb +2 -2
  52. data/lib/sass/script/value/number.rb +16 -26
  53. data/lib/sass/script/value/string.rb +1 -30
  54. data/lib/sass/scss.rb +2 -0
  55. data/lib/sass/scss/css_parser.rb +3 -7
  56. data/lib/sass/scss/parser.rb +78 -196
  57. data/lib/sass/scss/rx.rb +14 -7
  58. data/lib/sass/scss/script_lexer.rb +15 -0
  59. data/lib/sass/scss/script_parser.rb +25 -0
  60. data/lib/sass/scss/static_parser.rb +55 -38
  61. data/lib/sass/selector.rb +10 -7
  62. data/lib/sass/selector/abstract_sequence.rb +12 -15
  63. data/lib/sass/selector/comma_sequence.rb +6 -24
  64. data/lib/sass/selector/pseudo.rb +6 -19
  65. data/lib/sass/selector/sequence.rb +16 -14
  66. data/lib/sass/selector/simple.rb +7 -9
  67. data/lib/sass/selector/simple_sequence.rb +12 -16
  68. data/lib/sass/shared.rb +1 -1
  69. data/lib/sass/source/map.rb +9 -7
  70. data/lib/sass/source/position.rb +4 -4
  71. data/lib/sass/stack.rb +3 -23
  72. data/lib/sass/tree/charset_node.rb +1 -1
  73. data/lib/sass/tree/comment_node.rb +1 -1
  74. data/lib/sass/tree/function_node.rb +3 -2
  75. data/lib/sass/tree/node.rb +3 -5
  76. data/lib/sass/tree/prop_node.rb +58 -49
  77. data/lib/sass/tree/rule_node.rb +8 -15
  78. data/lib/sass/tree/visitors/check_nesting.rb +23 -19
  79. data/lib/sass/tree/visitors/convert.rb +13 -15
  80. data/lib/sass/tree/visitors/cssize.rb +15 -4
  81. data/lib/sass/tree/visitors/deep_copy.rb +2 -2
  82. data/lib/sass/tree/visitors/extend.rb +14 -10
  83. data/lib/sass/tree/visitors/perform.rb +18 -29
  84. data/lib/sass/tree/visitors/set_options.rb +2 -2
  85. data/lib/sass/tree/visitors/to_css.rb +47 -77
  86. data/lib/sass/util.rb +311 -98
  87. data/lib/sass/util/cross_platform_random.rb +19 -0
  88. data/lib/sass/util/multibyte_string_scanner.rb +133 -127
  89. data/lib/sass/util/normalized_map.rb +8 -1
  90. data/lib/sass/util/ordered_hash.rb +192 -0
  91. data/lib/sass/version.rb +6 -2
  92. data/test/sass/cache_test.rb +131 -0
  93. data/test/sass/callbacks_test.rb +61 -0
  94. data/test/sass/compiler_test.rb +236 -0
  95. data/test/sass/conversion_test.rb +2171 -0
  96. data/test/sass/css2sass_test.rb +526 -0
  97. data/test/sass/data/hsl-rgb.txt +319 -0
  98. data/test/sass/encoding_test.rb +219 -0
  99. data/test/sass/engine_test.rb +3400 -0
  100. data/test/sass/exec_test.rb +86 -0
  101. data/test/sass/extend_test.rb +1719 -0
  102. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  103. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  104. data/test/sass/functions_test.rb +1984 -0
  105. data/test/sass/importer_test.rb +421 -0
  106. data/test/sass/logger_test.rb +58 -0
  107. data/test/sass/mock_importer.rb +49 -0
  108. data/test/sass/more_results/more1.css +9 -0
  109. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  110. data/test/sass/more_results/more_import.css +29 -0
  111. data/test/sass/more_templates/_more_partial.sass +2 -0
  112. data/test/sass/more_templates/more1.sass +23 -0
  113. data/test/sass/more_templates/more_import.sass +11 -0
  114. data/test/sass/plugin_test.rb +556 -0
  115. data/test/sass/results/alt.css +4 -0
  116. data/test/sass/results/basic.css +9 -0
  117. data/test/sass/results/cached_import_option.css +3 -0
  118. data/test/sass/results/compact.css +5 -0
  119. data/test/sass/results/complex.css +86 -0
  120. data/test/sass/results/compressed.css +1 -0
  121. data/test/sass/results/expanded.css +19 -0
  122. data/test/sass/results/filename_fn.css +3 -0
  123. data/test/sass/results/if.css +3 -0
  124. data/test/sass/results/import.css +31 -0
  125. data/test/sass/results/import_charset.css +5 -0
  126. data/test/sass/results/import_charset_1_8.css +5 -0
  127. data/test/sass/results/import_charset_ibm866.css +5 -0
  128. data/test/sass/results/import_content.css +1 -0
  129. data/test/sass/results/line_numbers.css +49 -0
  130. data/test/sass/results/mixins.css +95 -0
  131. data/test/sass/results/multiline.css +24 -0
  132. data/test/sass/results/nested.css +22 -0
  133. data/test/sass/results/options.css +1 -0
  134. data/test/sass/results/parent_ref.css +13 -0
  135. data/test/sass/results/script.css +16 -0
  136. data/test/sass/results/scss_import.css +31 -0
  137. data/test/sass/results/scss_importee.css +2 -0
  138. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  139. data/test/sass/results/subdir/subdir.css +3 -0
  140. data/test/sass/results/units.css +11 -0
  141. data/test/sass/results/warn.css +0 -0
  142. data/test/sass/results/warn_imported.css +0 -0
  143. data/test/sass/script_conversion_test.rb +306 -0
  144. data/test/sass/script_test.rb +1206 -0
  145. data/test/sass/scss/css_test.rb +1281 -0
  146. data/test/sass/scss/rx_test.rb +160 -0
  147. data/test/sass/scss/scss_test.rb +4147 -0
  148. data/test/sass/scss/test_helper.rb +37 -0
  149. data/test/sass/source_map_test.rb +1055 -0
  150. data/test/sass/superselector_test.rb +210 -0
  151. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  152. data/test/sass/templates/_double_import_loop2.sass +1 -0
  153. data/test/sass/templates/_filename_fn_import.scss +11 -0
  154. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  155. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  156. data/test/sass/templates/_imported_content.sass +3 -0
  157. data/test/sass/templates/_partial.sass +2 -0
  158. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  159. data/test/sass/templates/alt.sass +16 -0
  160. data/test/sass/templates/basic.sass +23 -0
  161. data/test/sass/templates/bork1.sass +2 -0
  162. data/test/sass/templates/bork2.sass +2 -0
  163. data/test/sass/templates/bork3.sass +2 -0
  164. data/test/sass/templates/bork4.sass +2 -0
  165. data/test/sass/templates/bork5.sass +3 -0
  166. data/test/sass/templates/cached_import_option.scss +3 -0
  167. data/test/sass/templates/compact.sass +17 -0
  168. data/test/sass/templates/complex.sass +305 -0
  169. data/test/sass/templates/compressed.sass +15 -0
  170. data/test/sass/templates/double_import_loop1.sass +1 -0
  171. data/test/sass/templates/expanded.sass +17 -0
  172. data/test/sass/templates/filename_fn.scss +18 -0
  173. data/test/sass/templates/if.sass +11 -0
  174. data/test/sass/templates/import.sass +12 -0
  175. data/test/sass/templates/import_charset.sass +9 -0
  176. data/test/sass/templates/import_charset_1_8.sass +6 -0
  177. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  178. data/test/sass/templates/import_content.sass +4 -0
  179. data/test/sass/templates/importee.less +2 -0
  180. data/test/sass/templates/importee.sass +19 -0
  181. data/test/sass/templates/line_numbers.sass +13 -0
  182. data/test/sass/templates/mixin_bork.sass +5 -0
  183. data/test/sass/templates/mixins.sass +76 -0
  184. data/test/sass/templates/multiline.sass +20 -0
  185. data/test/sass/templates/nested.sass +25 -0
  186. data/test/sass/templates/nested_bork1.sass +2 -0
  187. data/test/sass/templates/nested_bork2.sass +2 -0
  188. data/test/sass/templates/nested_bork3.sass +2 -0
  189. data/test/sass/templates/nested_bork4.sass +2 -0
  190. data/test/sass/templates/nested_import.sass +2 -0
  191. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  192. data/test/sass/templates/options.sass +2 -0
  193. data/test/sass/templates/parent_ref.sass +25 -0
  194. data/test/sass/templates/same_name_different_ext.sass +2 -0
  195. data/test/sass/templates/same_name_different_ext.scss +1 -0
  196. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  197. data/test/sass/templates/script.sass +101 -0
  198. data/test/sass/templates/scss_import.scss +12 -0
  199. data/test/sass/templates/scss_importee.scss +1 -0
  200. data/test/sass/templates/single_import_loop.sass +1 -0
  201. data/test/sass/templates/subdir/import_up1.scss +1 -0
  202. data/test/sass/templates/subdir/import_up2.scss +1 -0
  203. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  204. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  205. data/test/sass/templates/subdir/subdir.sass +6 -0
  206. data/test/sass/templates/units.sass +11 -0
  207. data/test/sass/templates/warn.sass +3 -0
  208. data/test/sass/templates/warn_imported.sass +4 -0
  209. data/test/sass/test_helper.rb +8 -0
  210. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  211. data/test/sass/util/normalized_map_test.rb +51 -0
  212. data/test/sass/util/subset_map_test.rb +91 -0
  213. data/test/sass/util_test.rb +438 -0
  214. data/test/sass/value_helpers_test.rb +179 -0
  215. data/test/test_helper.rb +110 -0
  216. data/vendor/listen/CHANGELOG.md +1 -0
  217. data/vendor/listen/CONTRIBUTING.md +38 -0
  218. data/vendor/listen/Gemfile +20 -0
  219. data/vendor/listen/Guardfile +8 -0
  220. data/vendor/listen/LICENSE +20 -0
  221. data/vendor/listen/README.md +349 -0
  222. data/vendor/listen/Rakefile +5 -0
  223. data/vendor/listen/Vagrantfile +96 -0
  224. data/vendor/listen/lib/listen.rb +54 -0
  225. data/vendor/listen/lib/listen/adapter.rb +327 -0
  226. data/vendor/listen/lib/listen/adapters/bsd.rb +75 -0
  227. data/vendor/listen/lib/listen/adapters/darwin.rb +48 -0
  228. data/vendor/listen/lib/listen/adapters/linux.rb +81 -0
  229. data/vendor/listen/lib/listen/adapters/polling.rb +58 -0
  230. data/vendor/listen/lib/listen/adapters/windows.rb +91 -0
  231. data/vendor/listen/lib/listen/directory_record.rb +406 -0
  232. data/vendor/listen/lib/listen/listener.rb +323 -0
  233. data/vendor/listen/lib/listen/turnstile.rb +32 -0
  234. data/vendor/listen/lib/listen/version.rb +3 -0
  235. data/vendor/listen/listen.gemspec +28 -0
  236. data/vendor/listen/spec/listen/adapter_spec.rb +149 -0
  237. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  238. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  239. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  240. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  241. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  242. data/vendor/listen/spec/listen/directory_record_spec.rb +1250 -0
  243. data/vendor/listen/spec/listen/listener_spec.rb +258 -0
  244. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  245. data/vendor/listen/spec/listen_spec.rb +67 -0
  246. data/vendor/listen/spec/spec_helper.rb +25 -0
  247. data/vendor/listen/spec/support/adapter_helper.rb +666 -0
  248. data/vendor/listen/spec/support/directory_record_helper.rb +57 -0
  249. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  250. data/vendor/listen/spec/support/listeners_helper.rb +179 -0
  251. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  252. metadata +217 -76
  253. data/extra/sass-spec-ref.sh +0 -40
  254. data/lib/sass/deprecation.rb +0 -55
  255. data/lib/sass/logger/delayed.rb +0 -50
  256. data/lib/sass/script/value/callable.rb +0 -25
  257. data/lib/sass/script/value/function.rb +0 -19
@@ -13,11 +13,6 @@ 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
-
21
16
  # The arguments to the function.
22
17
  #
23
18
  # @return [Array<Node>]
@@ -44,19 +39,13 @@ module Sass::Script::Tree
44
39
  # @return [Node?]
45
40
  attr_accessor :kwarg_splat
46
41
 
47
- # @param name_or_callable [String, Sass::Callable] See \{#name}
42
+ # @param name [String] See \{#name}
48
43
  # @param args [Array<Node>] See \{#args}
49
44
  # @param keywords [Sass::Util::NormalizedMap<Node>] See \{#keywords}
50
45
  # @param splat [Node] See \{#splat}
51
46
  # @param kwarg_splat [Node] See \{#kwarg_splat}
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
47
+ def initialize(name, args, keywords, splat, kwarg_splat)
48
+ @name = name
60
49
  @args = args
61
50
  @keywords = keywords
62
51
  @splat = splat
@@ -67,12 +56,15 @@ module Sass::Script::Tree
67
56
  # @return [String] A string representation of the function call
68
57
  def inspect
69
58
  args = @args.map {|a| a.inspect}.join(', ')
70
- keywords = @keywords.as_stored.to_a.map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
59
+ keywords = Sass::Util.hash_to_a(@keywords.as_stored).
60
+ map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
61
+ # rubocop:disable RedundantSelf
71
62
  if self.splat
72
63
  splat = args.empty? && keywords.empty? ? "" : ", "
73
64
  splat = "#{splat}#{self.splat.inspect}..."
74
65
  splat = "#{splat}, #{kwarg_splat.inspect}..." if kwarg_splat
75
66
  end
67
+ # rubocop:enable RedundantSelf
76
68
  "#{name}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
77
69
  end
78
70
 
@@ -85,12 +77,15 @@ module Sass::Script::Tree
85
77
  end
86
78
 
87
79
  args = @args.map(&arg_to_sass)
88
- keywords = @keywords.as_stored.to_a.map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}
80
+ keywords = Sass::Util.hash_to_a(@keywords.as_stored).
81
+ map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}
89
82
 
83
+ # rubocop:disable RedundantSelf
90
84
  if self.splat
91
85
  splat = "#{arg_to_sass[self.splat]}..."
92
86
  kwarg_splat = "#{arg_to_sass[self.kwarg_splat]}..." if self.kwarg_splat
93
87
  end
88
+ # rubocop:enable RedundantSelf
94
89
 
95
90
  arglist = [args, splat, keywords, kwarg_splat].flatten.compact.join(', ')
96
91
  "#{dasherize(name, opts)}(#{arglist})"
@@ -125,31 +120,24 @@ module Sass::Script::Tree
125
120
  # @return [Sass::Script::Value] The SassScript object that is the value of the function call
126
121
  # @raise [Sass::SyntaxError] if the function call raises an ArgumentError
127
122
  def _perform(environment)
128
- args = @args.each_with_index.
123
+ args = Sass::Util.enum_with_index(@args).
129
124
  map {|a, i| perform_arg(a, environment, signature && signature.args[i])}
130
125
  keywords = Sass::Util.map_hash(@keywords) do |k, v|
131
126
  [k, perform_arg(v, environment, k.tr('-', '_'))]
132
127
  end
133
128
  splat = Sass::Tree::Visitors::Perform.perform_splat(
134
129
  @splat, keywords, @kwarg_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
130
+ if (fn = environment.function(@name))
131
+ return without_original(perform_sass_fn(fn, args, splat, environment))
142
132
  end
143
133
 
144
134
  args = construct_ruby_args(ruby_name, args, splat, environment)
145
135
 
146
- if Sass::Script::Functions.callable?(ruby_name) && (!fn || fn.origin == :builtin)
136
+ if Sass::Script::Functions.callable?(ruby_name)
147
137
  local_environment = Sass::Environment.new(environment.global_env, environment.options)
148
138
  local_environment.caller = Sass::ReadOnlyEnvironment.new(environment, environment.options)
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
139
+ result = opts(Sass::Script::Functions::EvaluationContext.new(
140
+ local_environment).send(ruby_name, *args))
153
141
  without_original(result)
154
142
  else
155
143
  opts(to_literal(args))
@@ -215,13 +203,12 @@ module Sass::Script::Tree
215
203
  raise Sass::SyntaxError.new(
216
204
  "#{args[signature.args.size].inspect} is not a keyword argument for `#{name}'")
217
205
  elsif keywords.empty?
218
- args << {} if signature.var_kwargs
219
206
  return args
220
207
  end
221
208
 
222
209
  argnames = signature.args[args.size..-1] || []
223
210
  deprecated_argnames = (signature.deprecated && signature.deprecated[args.size..-1]) || []
224
- args += argnames.zip(deprecated_argnames).map do |(argname, deprecated_argname)|
211
+ args = args + argnames.zip(deprecated_argnames).map do |(argname, deprecated_argname)|
225
212
  if keywords.has_key?(argname)
226
213
  keywords.delete(argname)
227
214
  elsif deprecated_argname && keywords.has_key?(deprecated_argname)
@@ -281,31 +268,36 @@ module Sass::Script::Tree
281
268
  message = "wrong number of arguments (#{given} for #{expected})"
282
269
  end
283
270
  elsif Sass::Util.jruby?
284
- should_maybe_raise =
285
- e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for (\d+)\)/
286
- given, expected = $1, $2
271
+ if Sass::Util.jruby1_6?
272
+ should_maybe_raise = e.message =~ /^wrong number of arguments \((\d+) for (\d+)\)/ &&
273
+ # The one case where JRuby does include the Ruby name of the function
274
+ # is manually-thrown ArgumentErrors, which are indistinguishable from
275
+ # legitimate ArgumentErrors. We treat both of these as
276
+ # Sass::SyntaxErrors even though it can hide Ruby errors.
277
+ e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
278
+ else
279
+ should_maybe_raise =
280
+ e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for (\d+)\)/
281
+ given, expected = $1, $2
282
+ end
287
283
 
288
284
  if should_maybe_raise
289
285
  # JRuby 1.7 includes __send__ before send and _perform.
290
286
  trace = e.backtrace.dup
291
- raise e if trace.shift !~ /:in `__send__'$/
287
+ raise e if !Sass::Util.jruby1_6? && trace.shift !~ /:in `__send__'$/
292
288
 
293
289
  # JRuby (as of 1.7.2) doesn't put the actual method
294
290
  # for which the argument error was thrown in the backtrace, so we
295
291
  # detect whether our send threw an argument error.
296
292
  if !(trace[0] =~ /:in `send'$/ && trace[1] =~ /:in `_perform'$/)
297
293
  raise e
298
- else
294
+ elsif !Sass::Util.jruby1_6?
299
295
  # JRuby 1.7 doesn't use standard formatting for its ArgumentErrors.
300
296
  message = "wrong number of arguments (#{given} for #{expected})"
301
297
  end
302
298
  end
303
- elsif (md = /^wrong number of arguments \(given (\d+), expected (\d+)\)/.match(e.message)) &&
304
- e.backtrace[0] =~ /:in `#{ruby_name}'$/
305
- # Handle ruby 2.3 error formatting
306
- message = "wrong number of arguments (#{md[1]} for #{md[2]})"
307
- elsif e.message =~ /^wrong number of arguments/ &&
308
- e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
299
+ elsif e.message =~ /^wrong number of arguments \(\d+ for \d+\)/ &&
300
+ e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
309
301
  raise e
310
302
  end
311
303
  raise Sass::SyntaxError.new("#{message} for `#{name}'")
@@ -1,220 +1,75 @@
1
1
  module Sass::Script::Tree
2
- # A SassScript object representing `#{}` interpolation outside a string.
2
+ # A SassScript object representing a single `#{}` interpolation.
3
3
  #
4
- # @see StringInterpolation
4
+ # This is used to wrap instances of interpolation in statement-level nodes. It
5
+ # includes logic for converting back to the source representation, and it
6
+ # optionally produces warnings when the values return named colors.
7
+ #
8
+ # TODO: Rather than representing this as a script node, it would be cleaner to
9
+ # have a non-node Interpolation class that represents an interpolated chunk of
10
+ # text.
5
11
  class Interpolation < Node
6
- # @return [Node] The SassScript before the interpolation
7
- attr_reader :before
8
-
9
- # @return [Node] The SassScript within the interpolation
10
- attr_reader :mid
11
-
12
- # @return [Node] The SassScript after the interpolation
13
- attr_reader :after
14
-
15
- # @return [Boolean] Whether there was whitespace between `before` and `#{`
16
- attr_reader :whitespace_before
17
-
18
- # @return [Boolean] Whether there was whitespace between `}` and `after`
19
- attr_reader :whitespace_after
20
-
21
- # @return [Boolean] Whether the original format of the interpolation was
22
- # plain text, not an interpolation. This is used when converting back to
23
- # SassScript.
24
- attr_reader :originally_text
12
+ # @return [Node] The SassScript within the
13
+ attr_reader :value
25
14
 
26
15
  # @return [Boolean] Whether a color value passed to the interpolation should
27
16
  # generate a warning.
28
17
  attr_reader :warn_for_color
29
18
 
30
- # The type of interpolation deprecation for this node.
31
- #
32
- # This can be `:none`, indicating that the node doesn't use deprecated
33
- # interpolation; `:immediate`, indicating that a deprecation warning should
34
- # be emitted as soon as possible; or `:potential`, indicating that a
35
- # deprecation warning should be emitted if the resulting string is used in a
36
- # way that would distinguish it from a list.
37
- #
38
- # @return [Symbol]
39
- attr_reader :deprecation
40
-
41
- # Interpolation in a property is of the form `before #{mid} after`.
42
- #
43
- # @param before [Node] See {Interpolation#before}
44
- # @param mid [Node] See {Interpolation#mid}
45
- # @param after [Node] See {Interpolation#after}
46
- # @param wb [Boolean] See {Interpolation#whitespace_before}
47
- # @param wa [Boolean] See {Interpolation#whitespace_after}
48
- # @param originally_text [Boolean] See {Interpolation#originally_text}
19
+ # @param value [Node] See {Interpolation#value}
49
20
  # @param warn_for_color [Boolean] See {Interpolation#warn_for_color}
50
- def initialize(before, mid, after, wb, wa, opts = {})
51
- @before = before
52
- @mid = mid
53
- @after = after
54
- @whitespace_before = wb
55
- @whitespace_after = wa
56
- @originally_text = opts[:originally_text] || false
57
- @warn_for_color = opts[:warn_for_color] || false
58
- @deprecation = opts[:deprecation] || :none
21
+ def initialize(value, warn_for_color = false)
22
+ @value = value
23
+ @warn_for_color = warn_for_color
59
24
  end
60
25
 
61
26
  # @return [String] A human-readable s-expression representation of the interpolation
62
27
  def inspect
63
- "(interpolation #{@before.inspect} #{@mid.inspect} #{@after.inspect})"
28
+ "(interpolation #{@value.inspect})"
64
29
  end
65
30
 
66
31
  # @see Node#to_sass
67
32
  def to_sass(opts = {})
68
- return to_quoted_equivalent.to_sass if deprecation == :immediate
69
-
70
- res = ""
71
- res << @before.to_sass(opts) if @before
72
- res << ' ' if @before && @whitespace_before
73
- res << '#{' unless @originally_text
74
- res << @mid.to_sass(opts)
75
- res << '}' unless @originally_text
76
- res << ' ' if @after && @whitespace_after
77
- res << @after.to_sass(opts) if @after
78
- res
79
- end
80
-
81
- # Returns an `unquote()` expression that will evaluate to the same value as
82
- # this interpolation.
83
- #
84
- # @return [Sass::Script::Tree::Node]
85
- def to_quoted_equivalent
86
- Funcall.new(
87
- "unquote",
88
- [to_string_interpolation(self)],
89
- Sass::Util::NormalizedMap.new,
90
- nil,
91
- nil)
33
+ "\#{#{@value.to_sass(opts)}}"
92
34
  end
93
35
 
94
- # Returns the three components of the interpolation, `before`, `mid`, and `after`.
36
+ # Returns the three interpolation's value.
95
37
  #
96
38
  # @return [Array<Node>]
97
39
  # @see #initialize
98
40
  # @see Node#children
99
41
  def children
100
- [@before, @mid, @after].compact
42
+ [@value]
101
43
  end
102
44
 
103
45
  # @see Node#deep_copy
104
46
  def deep_copy
105
47
  node = dup
106
- node.instance_variable_set('@before', @before.deep_copy) if @before
107
- node.instance_variable_set('@mid', @mid.deep_copy)
108
- node.instance_variable_set('@after', @after.deep_copy) if @after
48
+ node.instance_variable_set('@value', @value.deep_copy)
109
49
  node
110
50
  end
111
51
 
112
52
  protected
113
53
 
114
- # Converts a script node into a corresponding string interpolation
115
- # expression.
116
- #
117
- # @param node_or_interp [Sass::Script::Tree::Node]
118
- # @return [Sass::Script::Tree::StringInterpolation]
119
- def to_string_interpolation(node_or_interp)
120
- unless node_or_interp.is_a?(Interpolation)
121
- node = node_or_interp
122
- return string_literal(node.value.to_s) if node.is_a?(Literal)
123
- if node.is_a?(StringInterpolation)
124
- return concat(string_literal(node.quote), concat(node, string_literal(node.quote)))
125
- end
126
- return StringInterpolation.new(string_literal(""), node, string_literal(""))
127
- end
128
-
129
- interp = node_or_interp
130
- after_string_or_interp =
131
- if interp.after
132
- to_string_interpolation(interp.after)
133
- else
134
- string_literal("")
135
- end
136
- if interp.after && interp.whitespace_after
137
- after_string_or_interp = concat(string_literal(' '), after_string_or_interp)
138
- end
139
-
140
- mid_string_or_interp = to_string_interpolation(interp.mid)
141
-
142
- before_string_or_interp =
143
- if interp.before
144
- to_string_interpolation(interp.before)
145
- else
146
- string_literal("")
147
- end
148
- if interp.before && interp.whitespace_before
149
- before_string_or_interp = concat(before_string_or_interp, string_literal(' '))
150
- end
151
-
152
- concat(before_string_or_interp, concat(mid_string_or_interp, after_string_or_interp))
153
- end
154
-
155
- private
156
-
157
54
  # Evaluates the interpolation.
158
55
  #
159
56
  # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
160
57
  # @return [Sass::Script::Value::String]
161
58
  # The SassScript string that is the value of the interpolation
162
59
  def _perform(environment)
163
- res = ""
164
- res << @before.perform(environment).to_s if @before
165
- res << " " if @before && @whitespace_before
166
-
167
- val = @mid.perform(environment)
168
- if @warn_for_color && val.is_a?(Sass::Script::Value::Color) && val.name
169
- alternative = Operation.new(Sass::Script::Value::String.new("", :string), @mid, :plus)
60
+ result = @value.perform(environment)
61
+ if @warn_for_color && result.is_a?(Sass::Script::Value::Color) && result.name
62
+ alternative = Operation.new(Sass::Script::Value::String.new("", :string), @value, :plus)
170
63
  Sass::Util.sass_warn <<MESSAGE
171
64
  WARNING on line #{line}, column #{source_range.start_pos.offset}#{" of #{filename}" if filename}:
172
- You probably don't mean to use the color value `#{val}' in interpolation here.
173
- It may end up represented as #{val.inspect}, which will likely produce invalid CSS.
174
- Always quote color names when using them as strings (for example, "#{val}").
65
+ You probably don't mean to use the color value `#{result}' in interpolation here.
66
+ It may end up represented as #{result.inspect}, which will likely produce invalid CSS.
67
+ Always quote color names when using them as strings (for example, "#{result}").
175
68
  If you really want to use the color value here, use `#{alternative.to_sass}'.
176
69
  MESSAGE
177
70
  end
178
71
 
179
- res << val.to_s(:quote => :none)
180
- res << " " if @after && @whitespace_after
181
- res << @after.perform(environment).to_s if @after
182
- str = Sass::Script::Value::String.new(
183
- res, :identifier,
184
- (to_quoted_equivalent.to_sass if deprecation == :potential))
185
- str.source_range = source_range
186
- opts(str)
187
- end
188
-
189
- # Concatenates two string literals or string interpolation expressions.
190
- #
191
- # @param string_or_interp1 [Sass::Script::Tree::Literal|Sass::Script::Tree::StringInterpolation]
192
- # @param string_or_interp2 [Sass::Script::Tree::Literal|Sass::Script::Tree::StringInterpolation]
193
- # @return [Sass::Script::Tree::StringInterpolation]
194
- def concat(string_or_interp1, string_or_interp2)
195
- if string_or_interp1.is_a?(Literal) && string_or_interp2.is_a?(Literal)
196
- return string_literal(string_or_interp1.value.value + string_or_interp2.value.value)
197
- end
198
-
199
- if string_or_interp1.is_a?(Literal)
200
- string = string_or_interp1
201
- interp = string_or_interp2
202
- before = string_literal(string.value.value + interp.before.value.value)
203
- return StringInterpolation.new(before, interp.mid, interp.after)
204
- end
205
-
206
- StringInterpolation.new(
207
- string_or_interp1.before,
208
- string_or_interp1.mid,
209
- concat(string_or_interp1.after, string_or_interp2))
210
- end
211
-
212
- # Returns a string literal with the given contents.
213
- #
214
- # @param string [String]
215
- # @return string [Sass::Script::Tree::Literal]
216
- def string_literal(string)
217
- Literal.new(Sass::Script::Value::String.new(string, :string))
72
+ opts(Sass::Script::Value::String.new(result.to_s(:quote => :none)))
218
73
  end
219
74
  end
220
75
  end
@@ -13,20 +13,13 @@ 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
-
21
16
  # Creates a new list literal.
22
17
  #
23
18
  # @param elements [Array<Node>] See \{#elements}
24
19
  # @param separator [Symbol] See \{#separator}
25
- # @param bracketed [Boolean] See \{#bracketed}
26
- def initialize(elements, separator: nil, bracketed: false)
20
+ def initialize(elements, separator)
27
21
  @elements = elements
28
22
  @separator = separator
29
- @bracketed = bracketed
30
23
  end
31
24
 
32
25
  # @see Node#children
@@ -34,7 +27,7 @@ module Sass::Script::Tree
34
27
 
35
28
  # @see Value#to_sass
36
29
  def to_sass(opts = {})
37
- return bracketed ? "[]" : "()" if elements.empty?
30
+ return "()" if elements.empty?
38
31
  members = elements.map do |v|
39
32
  if element_needs_parens?(v)
40
33
  "(#{v.to_sass(opts)})"
@@ -43,12 +36,9 @@ module Sass::Script::Tree
43
36
  end
44
37
  end
45
38
 
46
- if separator == :comma && members.length == 1
47
- return "#{bracketed ? '[' : '('}#{members.first},#{bracketed ? ']' : ')'}"
48
- end
39
+ return "(#{members.first},)" if separator == :comma && members.length == 1
49
40
 
50
- contents = members.join(sep_str(nil))
51
- bracketed ? "[#{contents}]" : contents
41
+ members.join(sep_str(nil))
52
42
  end
53
43
 
54
44
  # @see Node#deep_copy
@@ -59,9 +49,7 @@ module Sass::Script::Tree
59
49
  end
60
50
 
61
51
  def inspect
62
- (bracketed ? '[' : '(') +
63
- elements.map {|e| e.inspect}.join(separator == :space ? ' ' : ', ') +
64
- (bracketed ? ']' : ')')
52
+ "(#{elements.map {|e| e.inspect}.join(separator == :space ? ' ' : ', ')})"
65
53
  end
66
54
 
67
55
  def force_division!
@@ -73,8 +61,7 @@ module Sass::Script::Tree
73
61
  def _perform(environment)
74
62
  list = Sass::Script::Value::List.new(
75
63
  elements.map {|e| e.perform(environment)},
76
- separator: separator,
77
- bracketed: bracketed)
64
+ separator)
78
65
  list.source_range = source_range
79
66
  list.options = options
80
67
  list
@@ -86,10 +73,8 @@ module Sass::Script::Tree
86
73
  # when serialized to Sass.
87
74
  def element_needs_parens?(element)
88
75
  if element.is_a?(ListLiteral)
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)
76
+ return Sass::Script::Parser.precedence_of(element.separator) <=
77
+ Sass::Script::Parser.precedence_of(separator)
93
78
  end
94
79
 
95
80
  return false unless separator == :space