sass 3.7.4 → 4.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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(Hash[pairs.map do |(k, v)|
52
+ map = Sass::Script::Value::Map.new(Sass::Util.to_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
@@ -10,7 +10,7 @@ module Sass::Script::Tree
10
10
 
11
11
  # The line of the document on which this node appeared.
12
12
  #
13
- # @return [Integer]
13
+ # @return [Fixnum]
14
14
  attr_accessor :line
15
15
 
16
16
  # The source range in the document on which this node appeared.
@@ -25,7 +25,7 @@ module Sass::Script::Tree
25
25
 
26
26
  # Sets the options hash for this node,
27
27
  # as well as for all child nodes.
28
- # See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
28
+ # See {file:SASS_REFERENCE.md#options the Sass options documentation}.
29
29
  #
30
30
  # @param options [{Symbol => Object}] The options
31
31
  def options=(options)
@@ -90,7 +90,7 @@ module Sass::Script::Tree
90
90
  # Converts underscores to dashes if the :dasherize option is set.
91
91
  def dasherize(s, opts)
92
92
  if opts[:dasherize]
93
- s.tr('_', '-')
93
+ s.gsub(/_/, '-')
94
94
  else
95
95
  s
96
96
  end
@@ -2,9 +2,6 @@ module Sass::Script::Tree
2
2
  # A SassScript parse node representing a binary operation,
3
3
  # such as `$a + $b` or `"foo" + 1`.
4
4
  class Operation < Node
5
- @@color_arithmetic_deprecation = Sass::Deprecation.new
6
- @@unitless_equals_deprecation = Sass::Deprecation.new
7
-
8
5
  attr_reader :operand1
9
6
  attr_reader :operand2
10
7
  attr_reader :operator
@@ -88,52 +85,28 @@ module Sass::Script::Tree
88
85
  raise Sass::SyntaxError.new("Undefined operation: \"#{value1} #{@operator} #{value2}\".")
89
86
  end
90
87
 
91
- warn_for_color_arithmetic(value1, value2)
92
- warn_for_unitless_equals(value1, value2, result)
88
+ if (@operator == :eq || @operator == :neq) && value1.is_a?(Sass::Script::Value::Number) &&
89
+ value2.is_a?(Sass::Script::Value::Number) && value1.unitless? != value2.unitless? &&
90
+ result == (if @operator == :eq
91
+ Sass::Script::Value::Bool::TRUE
92
+ else
93
+ Sass::Script::Value::Bool::FALSE
94
+ end)
95
+
96
+ operation = "#{value1} #{@operator == :eq ? '==' : '!='} #{value2}"
97
+ future_value = @operator == :neq
98
+ Sass::Util.sass_warn <<WARNING
99
+ DEPRECATION WARNING on line #{line}#{" of #{filename}" if filename}:
100
+ The result of `#{operation}` will be `#{future_value}` in future releases of Sass.
101
+ Unitless numbers will no longer be equal to the same numbers with units.
102
+ WARNING
103
+ end
93
104
 
94
105
  result
95
106
  end
96
107
 
97
108
  private
98
109
 
99
- def warn_for_color_arithmetic(value1, value2)
100
- return unless @operator == :plus || @operator == :times || @operator == :minus ||
101
- @operator == :div || @operator == :mod
102
-
103
- if value1.is_a?(Sass::Script::Value::Number)
104
- return unless value2.is_a?(Sass::Script::Value::Color)
105
- elsif value1.is_a?(Sass::Script::Value::Color)
106
- return unless value2.is_a?(Sass::Script::Value::Color) || value2.is_a?(Sass::Script::Value::Number)
107
- else
108
- return
109
- end
110
-
111
- @@color_arithmetic_deprecation.warn(filename, line, <<WARNING)
112
- The operation `#{value1} #{@operator} #{value2}` is deprecated and will be an error in future versions.
113
- Consider using Sass's color functions instead.
114
- https://sass-lang.com/documentation/Sass/Script/Functions.html#other_color_functions
115
- WARNING
116
- end
117
-
118
- def warn_for_unitless_equals(value1, value2, result)
119
- return unless @operator == :eq || @operator == :neq
120
- return unless value1.is_a?(Sass::Script::Value::Number)
121
- return unless value2.is_a?(Sass::Script::Value::Number)
122
- return unless value1.unitless? != value2.unitless?
123
- return unless result == (if @operator == :eq
124
- Sass::Script::Value::Bool::TRUE
125
- else
126
- Sass::Script::Value::Bool::FALSE
127
- end)
128
-
129
- operation = "#{value1.to_sass} #{@operator == :eq ? '==' : '!='} #{value2.to_sass}"
130
- future_value = @operator == :neq
131
- @@unitless_equals_deprecation.warn(filename, line, <<WARNING)
132
- The result of `#{operation}` will be `#{future_value}` in future releases of Sass.
133
- Unitless numbers will no longer be equal to the same numbers with units.
134
- WARNING
135
- end
136
-
137
110
  def operand_to_sass(op, side, opts)
138
111
  return "(#{op.to_sass(opts)})" if op.is_a?(Sass::Script::Tree::ListLiteral)
139
112
  return op.to_sass(opts) unless op.is_a?(Operation)
@@ -3,15 +3,9 @@ module Sass::Script::Tree
3
3
  #
4
4
  # @see Interpolation
5
5
  class StringInterpolation < Node
6
- # @return [Literal] The string literal before this interpolation.
7
- attr_reader :before
8
-
9
- # @return [Node] The SassScript within the interpolation
10
- attr_reader :mid
11
-
12
- # @return [StringInterpolation, Literal]
13
- # The string literal or string interpolation before this interpolation.
14
- attr_reader :after
6
+ # @return [[Node, String]] The contents of the interpolation. Strings are
7
+ # literal text, nodes are interpolated segments.
8
+ attr_reader :contents
15
9
 
16
10
  # Whether this is a CSS string or a CSS identifier. The difference is that
17
11
  # strings are written with double-quotes, while identifiers aren't.
@@ -20,62 +14,56 @@ module Sass::Script::Tree
20
14
  # functions such as `url()`.
21
15
  #
22
16
  # @return [Symbol] `:string` or `:identifier`
23
- def type
24
- @before.value.type
25
- end
17
+ attr_reader :type
26
18
 
27
- # Returns the quote character that should be used to wrap a Sass
28
- # representation of this interpolation.
29
- def quote
30
- quote_for(self) || '"'
31
- end
32
-
33
- # Interpolation in a string is of the form `"before #{mid} after"`,
34
- # where `before` and `after` may include more interpolation.
19
+ # Interpolation in a string.
35
20
  #
36
- # @param before [StringInterpolation, Literal] See {StringInterpolation#before}
37
- # @param mid [Node] See {StringInterpolation#mid}
38
- # @param after [Literal] See {StringInterpolation#after}
39
- def initialize(before, mid, after)
40
- @before = before
41
- @mid = mid
42
- @after = after
21
+ # @param contents [[Node, String]] See {StringInterpolation#contents}
22
+ # @param type [Symbol] See {StringInterpolation#type}
23
+ def initialize(contents, type = :string)
24
+ @contents = Sass::Util.merge_adjacent_strings(contents)
25
+ @type = type
43
26
  end
44
27
 
45
28
  # @return [String] A human-readable s-expression representation of the interpolation
46
29
  def inspect
47
- "(string_interpolation #{@before.inspect} #{@mid.inspect} #{@after.inspect})"
30
+ "(string_interpolation #{@type.inspect} #{contents.map {|c| c.inspect}.join(', ')})"
48
31
  end
49
32
 
50
33
  # @see Node#to_sass
51
34
  def to_sass(opts = {})
52
- quote = type == :string ? opts[:quote] || quote_for(self) || '"' : :none
35
+ quote = type == :string ? opts[:quote] || detected_quote : :none
53
36
  opts = opts.merge(:quote => quote)
54
37
 
55
38
  res = ""
56
39
  res << quote if quote != :none
57
- res << _to_sass(before, opts)
58
- res << '#{' << @mid.to_sass(opts.merge(:quote => nil)) << '}'
59
- res << _to_sass(after, opts)
40
+ contents.each do |c|
41
+ if c.is_a?(String)
42
+ c = Sass::Script::Value::String.quote(c, opts).slice(1...-1) if quote != :none
43
+ res << c
44
+ else
45
+ res << '#{' << c.to_sass(opts.merge(:quote => nil)) << '}'
46
+ end
47
+ end
60
48
  res << quote if quote != :none
61
49
  res
62
50
  end
63
51
 
64
- # Returns the three components of the interpolation, `before`, `mid`, and `after`.
52
+ # Returns the node contents of this interpolation.
65
53
  #
66
54
  # @return [Array<Node>]
67
55
  # @see #initialize
68
56
  # @see Node#children
69
57
  def children
70
- [@before, @mid, @after].compact
58
+ contents.select {|c| c.is_a?(Sass::Script::Tree::Node)}
71
59
  end
72
60
 
73
61
  # @see Node#deep_copy
74
62
  def deep_copy
75
63
  node = dup
76
- node.instance_variable_set('@before', @before.deep_copy) if @before
77
- node.instance_variable_set('@mid', @mid.deep_copy)
78
- node.instance_variable_set('@after', @after.deep_copy) if @after
64
+ node.instance_variable_set('@contents', contents.map do |c|
65
+ c.is_a?(String) ? c : c.deep_copy
66
+ end)
79
67
  node
80
68
  end
81
69
 
@@ -87,39 +75,30 @@ module Sass::Script::Tree
87
75
  # @return [Sass::Script::Value::String]
88
76
  # The SassScript string that is the value of the interpolation
89
77
  def _perform(environment)
90
- res = ""
91
- before = @before.perform(environment)
92
- res << before.value
93
- mid = @mid.perform(environment)
94
- res << (mid.is_a?(Sass::Script::Value::String) ? mid.value : mid.to_s(:quote => :none))
95
- res << @after.perform(environment).value
96
- opts(Sass::Script::Value::String.new(res, before.type))
78
+ opts(Sass::Script::Value::String.new(contents.map do |c|
79
+ next c if c.is_a?(String)
80
+ value = c.perform(environment)
81
+ value.is_a?(Sass::Script::Value::String) ? value.value : value.to_s(:quote => :none)
82
+ end.join, type))
97
83
  end
98
84
 
99
85
  private
100
86
 
101
- def _to_sass(string_or_interp, opts)
102
- result = string_or_interp.to_sass(opts)
103
- opts[:quote] == :none ? result : result.slice(1...-1)
104
- end
105
-
106
- def quote_for(string_or_interp)
107
- if string_or_interp.is_a?(Sass::Script::Tree::Literal)
108
- return nil if string_or_interp.value.value.empty?
109
- return '"' if string_or_interp.value.value.include?("'")
110
- return "'" if string_or_interp.value.value.include?('"')
111
- return nil
87
+ # Returns the best quote to use for this interpolation.
88
+ #
89
+ # @return [String]
90
+ def detected_quote
91
+ has_double_quote = false
92
+ contents.each do |c|
93
+ next if c.is_a?(Sass::Script::Tree::Node)
94
+
95
+ # Double-quotes take precedence over single quotes, so if any string contains
96
+ # a single quote we'll definitely end up using double quotes.
97
+ return '"' if c.include?("'")
98
+ has_double_quote ||= c.include?('"')
112
99
  end
113
100
 
114
- # Double-quotes take precedence over single quotes.
115
- before_quote = quote_for(string_or_interp.before)
116
- return '"' if before_quote == '"'
117
- after_quote = quote_for(string_or_interp.after)
118
- return '"' if after_quote == '"'
119
-
120
- # Returns "'" if either or both insist on single quotes, and nil
121
- # otherwise.
122
- before_quote || after_quote
101
+ has_double_quote ? "'" : '"'
123
102
  end
124
103
  end
125
104
  end
@@ -14,7 +14,7 @@ module Sass::Script::Tree
14
14
  # @param name [String] See \{#name}
15
15
  def initialize(name)
16
16
  @name = name
17
- @underscored_name = name.tr("-", "_")
17
+ @underscored_name = name.gsub(/-/, "_")
18
18
  super()
19
19
  end
20
20
 
@@ -9,5 +9,3 @@ 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: separator)
20
+ super(value, separator)
21
21
  if keywords.is_a?(Sass::Util::NormalizedMap)
22
22
  @keywords = keywords
23
23
  else
@@ -22,12 +22,11 @@ module Sass::Script::Value
22
22
  def initialize(value = nil)
23
23
  value.freeze unless value.nil? || value == true || value == false
24
24
  @value = value
25
- @options = nil
26
25
  end
27
26
 
28
27
  # Sets the options hash for this node,
29
28
  # as well as for all child nodes.
30
- # See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
29
+ # See {file:SASS_REFERENCE.md#options the Sass options documentation}.
31
30
  #
32
31
  # @param options [{Symbol => Object}] The options
33
32
  attr_writer :options
@@ -88,7 +87,7 @@ MSG
88
87
  # @return [Script::Value::String] A string containing both values
89
88
  # separated by `"="`
90
89
  def single_eq(other)
91
- Sass::Script::Value::String.new("#{self}=#{other}")
90
+ Sass::Script::Value::String.new("#{to_s}=#{other.to_s}")
92
91
  end
93
92
 
94
93
  # The SassScript `+` operation.
@@ -107,7 +106,7 @@ MSG
107
106
  # @return [Script::Value::String] A string containing both values
108
107
  # separated by `"-"`
109
108
  def minus(other)
110
- Sass::Script::Value::String.new("#{self}-#{other}")
109
+ Sass::Script::Value::String.new("#{to_s}-#{other.to_s}")
111
110
  end
112
111
 
113
112
  # The SassScript `/` operation.
@@ -116,7 +115,7 @@ MSG
116
115
  # @return [Script::Value::String] A string containing both values
117
116
  # separated by `"/"`
118
117
  def div(other)
119
- Sass::Script::Value::String.new("#{self}/#{other}")
118
+ Sass::Script::Value::String.new("#{to_s}/#{other.to_s}")
120
119
  end
121
120
 
122
121
  # The SassScript unary `+` operation (e.g. `+$a`).
@@ -125,7 +124,7 @@ MSG
125
124
  # @return [Script::Value::String] A string containing the value
126
125
  # preceded by `"+"`
127
126
  def unary_plus
128
- Sass::Script::Value::String.new("+#{self}")
127
+ Sass::Script::Value::String.new("+#{to_s}")
129
128
  end
130
129
 
131
130
  # The SassScript unary `-` operation (e.g. `-$a`).
@@ -134,7 +133,7 @@ MSG
134
133
  # @return [Script::Value::String] A string containing the value
135
134
  # preceded by `"-"`
136
135
  def unary_minus
137
- Sass::Script::Value::String.new("-#{self}")
136
+ Sass::Script::Value::String.new("-#{to_s}")
138
137
  end
139
138
 
140
139
  # The SassScript unary `/` operation (e.g. `/$a`).
@@ -143,13 +142,13 @@ MSG
143
142
  # @return [Script::Value::String] A string containing the value
144
143
  # preceded by `"/"`
145
144
  def unary_div
146
- Sass::Script::Value::String.new("/#{self}")
145
+ Sass::Script::Value::String.new("/#{to_s}")
147
146
  end
148
147
 
149
148
  # Returns the hash code of this value. Two objects' hash codes should be
150
149
  # equal if the objects are equal.
151
150
  #
152
- # @return [Integer for Ruby 2.4.0+, Fixnum for earlier Ruby versions] The hash code.
151
+ # @return [Fixnum] The hash code.
153
152
  def hash
154
153
  value.hash
155
154
  end
@@ -176,7 +175,7 @@ MSG
176
175
  eq(other).to_bool
177
176
  end
178
177
 
179
- # @return [Integer] The integer value of this value
178
+ # @return [Fixnum] The integer value of this value
180
179
  # @raise [Sass::SyntaxError] if this value isn't an integer
181
180
  def to_i
182
181
  raise Sass::SyntaxError.new("#{inspect} is not an integer.")
@@ -192,12 +191,6 @@ MSG
192
191
  # @return [Symbol]
193
192
  def separator; nil; end
194
193
 
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
-
201
194
  # Returns the value of this value as a list.
202
195
  # Single values are considered the same as single-element lists.
203
196
  #
@@ -234,17 +227,6 @@ MSG
234
227
  false
235
228
  end
236
229
 
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
-
248
230
  protected
249
231
 
250
232
  # Evaluates the value.
@@ -17,16 +17,15 @@ module Sass::Script::Value
17
17
  # @private
18
18
  #
19
19
  # Convert a ruby integer to a rgba components
20
- # @param color [Integer]
21
- # @return [Array<Integer>] Array of 4 numbers representing r,g,b and alpha
20
+ # @param color [Fixnum]
21
+ # @return [Array<Fixnum>] Array of 4 numbers representing r,g,b and alpha
22
22
  def self.int_to_rgba(color)
23
23
  rgba = (0..3).map {|n| color >> (n << 3) & 0xff}.reverse
24
24
  rgba[-1] = rgba[-1] / 255.0
25
25
  rgba
26
26
  end
27
27
 
28
- ALTERNATE_COLOR_NAMES = Sass::Util.map_vals(
29
- {
28
+ ALTERNATE_COLOR_NAMES = Sass::Util.map_vals({
30
29
  'aqua' => 0x00FFFFFF,
31
30
  'darkgrey' => 0xA9A9A9FF,
32
31
  'darkslategrey' => 0x2F4F4FFF,
@@ -36,11 +35,10 @@ module Sass::Script::Value
36
35
  'lightgrey' => 0xD3D3D3FF,
37
36
  'lightslategrey' => 0x778899FF,
38
37
  'slategrey' => 0x708090FF,
39
- }, &method(:int_to_rgba))
38
+ }, &method(:int_to_rgba))
40
39
 
41
40
  # A hash from color names to `[red, green, blue]` value arrays.
42
- COLOR_NAMES = Sass::Util.map_vals(
43
- {
41
+ COLOR_NAMES = Sass::Util.map_vals({
44
42
  'aliceblue' => 0xF0F8FFFF,
45
43
  'antiquewhite' => 0xFAEBD7FF,
46
44
  'aquamarine' => 0x7FFFD4FF,
@@ -181,7 +179,7 @@ module Sass::Script::Value
181
179
  'whitesmoke' => 0xF5F5F5FF,
182
180
  'yellow' => 0xFFFF00FF,
183
181
  'yellowgreen' => 0x9ACD32FF
184
- }, &method(:int_to_rgba))
182
+ }, &method(:int_to_rgba))
185
183
 
186
184
  # A hash from `[red, green, blue, alpha]` value arrays to color names.
187
185
  COLOR_NAMES_REVERSE = COLOR_NAMES.invert.freeze
@@ -239,7 +237,7 @@ module Sass::Script::Value
239
237
  @attrs[:alpha] = attrs[3] ? attrs[3].to_f : 1
240
238
  @representation = representation
241
239
  else
242
- attrs = attrs.reject {|_k, v| v.nil?}
240
+ attrs = attrs.reject {|k, v| v.nil?}
243
241
  hsl = [:hue, :saturation, :lightness] & attrs.keys
244
242
  rgb = [:red, :green, :blue] & attrs.keys
245
243
  if !allow_both_rgb_and_hsl && !hsl.empty? && !rgb.empty?
@@ -277,14 +275,13 @@ module Sass::Script::Value
277
275
  #
278
276
  # @return [Color]
279
277
  def self.from_hex(hex_string, alpha = nil)
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
278
+ unless hex_string =~ /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i ||
279
+ hex_string =~ /^#?([0-9a-f])([0-9a-f])([0-9a-f])$/i
282
280
  raise ArgumentError.new("#{hex_string.inspect} is not a valid hex color.")
283
281
  end
284
282
  red = $1.ljust(2, $1).to_i(16)
285
283
  green = $2.ljust(2, $2).to_i(16)
286
284
  blue = $3.ljust(2, $3).to_i(16)
287
- alpha = $4.ljust(2, $4).to_i(16).to_f / 0xff if $4
288
285
 
289
286
  hex_string = "##{hex_string}" unless hex_string[0] == ?#
290
287
  attrs = {:red => red, :green => green, :blue => blue, :representation => hex_string}
@@ -294,7 +291,7 @@ module Sass::Script::Value
294
291
 
295
292
  # The red component of the color.
296
293
  #
297
- # @return [Integer]
294
+ # @return [Fixnum]
298
295
  def red
299
296
  hsl_to_rgb!
300
297
  @attrs[:red]
@@ -302,7 +299,7 @@ module Sass::Script::Value
302
299
 
303
300
  # The green component of the color.
304
301
  #
305
- # @return [Integer]
302
+ # @return [Fixnum]
306
303
  def green
307
304
  hsl_to_rgb!
308
305
  @attrs[:green]
@@ -310,7 +307,7 @@ module Sass::Script::Value
310
307
 
311
308
  # The blue component of the color.
312
309
  #
313
- # @return [Integer]
310
+ # @return [Fixnum]
314
311
  def blue
315
312
  hsl_to_rgb!
316
313
  @attrs[:blue]
@@ -343,7 +340,7 @@ module Sass::Script::Value
343
340
  # The alpha channel (opacity) of the color.
344
341
  # This is 1 unless otherwise defined.
345
342
  #
346
- # @return [Integer]
343
+ # @return [Fixnum]
347
344
  def alpha
348
345
  @attrs[:alpha].to_f
349
346
  end
@@ -358,7 +355,7 @@ module Sass::Script::Value
358
355
 
359
356
  # Returns the red, green, and blue components of the color.
360
357
  #
361
- # @return [Array<Integer>] A frozen three-element array of the red, green, and blue
358
+ # @return [Array<Fixnum>] A frozen three-element array of the red, green, and blue
362
359
  # values (respectively) of the color
363
360
  def rgb
364
361
  [red, green, blue].freeze
@@ -366,7 +363,7 @@ module Sass::Script::Value
366
363
 
367
364
  # Returns the red, green, blue, and alpha components of the color.
368
365
  #
369
- # @return [Array<Integer>] A frozen four-element array of the red, green,
366
+ # @return [Array<Fixnum>] A frozen four-element array of the red, green,
370
367
  # blue, and alpha values (respectively) of the color
371
368
  def rgba
372
369
  [red, green, blue, alpha].freeze
@@ -374,7 +371,7 @@ module Sass::Script::Value
374
371
 
375
372
  # Returns the hue, saturation, and lightness components of the color.
376
373
  #
377
- # @return [Array<Integer>] A frozen three-element array of the
374
+ # @return [Array<Fixnum>] A frozen three-element array of the
378
375
  # hue, saturation, and lightness values (respectively) of the color
379
376
  def hsl
380
377
  [hue, saturation, lightness].freeze
@@ -382,7 +379,7 @@ module Sass::Script::Value
382
379
 
383
380
  # Returns the hue, saturation, lightness, and alpha components of the color.
384
381
  #
385
- # @return [Array<Integer>] A frozen four-element array of the hue,
382
+ # @return [Array<Fixnum>] A frozen four-element array of the hue,
386
383
  # saturation, lightness, and alpha values (respectively) of the color
387
384
  def hsla
388
385
  [hue, saturation, lightness, alpha].freeze
@@ -424,7 +421,7 @@ module Sass::Script::Value
424
421
  # @return [Color] The new Color object
425
422
  # @raise [ArgumentError] if both RGB and HSL keys are specified
426
423
  def with(attrs)
427
- attrs = attrs.reject {|_k, v| v.nil?}
424
+ attrs = attrs.reject {|k, v| v.nil?}
428
425
  hsl = !([:hue, :saturation, :lightness] & attrs.keys).empty?
429
426
  rgb = !([:red, :green, :blue] & attrs.keys).empty?
430
427
  if hsl && rgb
@@ -564,11 +561,6 @@ module Sass::Script::Value
564
561
  def to_s(opts = {})
565
562
  return smallest if options[:style] == :compressed
566
563
  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)
572
564
  return name if name
573
565
  alpha? ? rgba_str : hex_str
574
566
  end