sass 3.5.2 → 3.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) 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/extra/sass-spec-ref.sh +9 -1
  8. data/lib/sass/engine.rb +1 -9
  9. data/lib/sass/exec/base.rb +0 -2
  10. data/lib/sass/exec/sass_scss.rb +1 -5
  11. data/lib/sass/importers/filesystem.rb +4 -2
  12. data/lib/sass/logger/base.rb +11 -0
  13. data/lib/sass/script/css_parser.rb +4 -1
  14. data/lib/sass/script/functions.rb +76 -41
  15. data/lib/sass/script/lexer.rb +62 -19
  16. data/lib/sass/script/parser.rb +260 -93
  17. data/lib/sass/script/tree/funcall.rb +0 -4
  18. data/lib/sass/script/tree/interpolation.rb +0 -3
  19. data/lib/sass/script/tree/operation.rb +1 -1
  20. data/lib/sass/script/value/color.rb +3 -2
  21. data/lib/sass/script/value/helpers.rb +8 -2
  22. data/lib/sass/script/value/number.rb +2 -1
  23. data/lib/sass/scss/css_parser.rb +6 -1
  24. data/lib/sass/scss/parser.rb +48 -18
  25. data/lib/sass/scss/rx.rb +1 -1
  26. data/lib/sass/scss/static_parser.rb +15 -18
  27. data/lib/sass/selector/comma_sequence.rb +2 -1
  28. data/lib/sass/selector/pseudo.rb +1 -1
  29. data/lib/sass/selector/sequence.rb +0 -4
  30. data/lib/sass/source/map.rb +0 -4
  31. data/lib/sass/tree/rule_node.rb +3 -6
  32. data/lib/sass/tree/visitors/perform.rb +2 -6
  33. data/lib/sass/tree/visitors/to_css.rb +4 -11
  34. data/lib/sass/util.rb +60 -20
  35. data/lib/sass/version.rb +0 -2
  36. metadata +38 -162
  37. data/Rakefile +0 -338
  38. data/lib/test.css +0 -4
  39. data/lib/test.css.map +0 -7
  40. data/test/sass-spec.yml +0 -3
  41. data/test/sass/cache_test.rb +0 -130
  42. data/test/sass/callbacks_test.rb +0 -60
  43. data/test/sass/compiler_test.rb +0 -225
  44. data/test/sass/conversion_test.rb +0 -2138
  45. data/test/sass/css2sass_test.rb +0 -523
  46. data/test/sass/css_variable_test.rb +0 -237
  47. data/test/sass/data/hsl-rgb.txt +0 -319
  48. data/test/sass/encoding_test.rb +0 -188
  49. data/test/sass/engine_test.rb +0 -3499
  50. data/test/sass/exec_test.rb +0 -95
  51. data/test/sass/extend_test.rb +0 -1678
  52. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  53. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  54. data/test/sass/functions_test.rb +0 -2021
  55. data/test/sass/importer_test.rb +0 -420
  56. data/test/sass/logger_test.rb +0 -57
  57. data/test/sass/mock_importer.rb +0 -49
  58. data/test/sass/more_results/more1.css +0 -9
  59. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  60. data/test/sass/more_results/more_import.css +0 -29
  61. data/test/sass/more_templates/_more_partial.sass +0 -2
  62. data/test/sass/more_templates/more1.sass +0 -23
  63. data/test/sass/more_templates/more_import.sass +0 -11
  64. data/test/sass/plugin_test.rb +0 -552
  65. data/test/sass/results/alt.css +0 -4
  66. data/test/sass/results/basic.css +0 -9
  67. data/test/sass/results/cached_import_option.css +0 -3
  68. data/test/sass/results/compact.css +0 -5
  69. data/test/sass/results/complex.css +0 -86
  70. data/test/sass/results/compressed.css +0 -1
  71. data/test/sass/results/expanded.css +0 -19
  72. data/test/sass/results/filename_fn.css +0 -3
  73. data/test/sass/results/if.css +0 -3
  74. data/test/sass/results/import.css +0 -31
  75. data/test/sass/results/import_charset.css +0 -5
  76. data/test/sass/results/import_charset_ibm866.css +0 -5
  77. data/test/sass/results/import_content.css +0 -1
  78. data/test/sass/results/line_numbers.css +0 -49
  79. data/test/sass/results/mixins.css +0 -95
  80. data/test/sass/results/multiline.css +0 -24
  81. data/test/sass/results/nested.css +0 -22
  82. data/test/sass/results/options.css +0 -1
  83. data/test/sass/results/parent_ref.css +0 -13
  84. data/test/sass/results/script.css +0 -16
  85. data/test/sass/results/scss_import.css +0 -31
  86. data/test/sass/results/scss_importee.css +0 -2
  87. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  88. data/test/sass/results/subdir/subdir.css +0 -3
  89. data/test/sass/results/units.css +0 -11
  90. data/test/sass/results/warn.css +0 -0
  91. data/test/sass/results/warn_imported.css +0 -0
  92. data/test/sass/script_conversion_test.rb +0 -365
  93. data/test/sass/script_test.rb +0 -1429
  94. data/test/sass/scss/css_test.rb +0 -1266
  95. data/test/sass/scss/rx_test.rb +0 -159
  96. data/test/sass/scss/scss_test.rb +0 -4238
  97. data/test/sass/scss/test_helper.rb +0 -37
  98. data/test/sass/source_map_test.rb +0 -1052
  99. data/test/sass/superselector_test.rb +0 -209
  100. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  101. data/test/sass/templates/_double_import_loop2.sass +0 -1
  102. data/test/sass/templates/_filename_fn_import.scss +0 -11
  103. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  104. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  105. data/test/sass/templates/_imported_content.sass +0 -3
  106. data/test/sass/templates/_partial.sass +0 -2
  107. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  108. data/test/sass/templates/alt.sass +0 -16
  109. data/test/sass/templates/basic.sass +0 -23
  110. data/test/sass/templates/bork1.sass +0 -2
  111. data/test/sass/templates/bork2.sass +0 -2
  112. data/test/sass/templates/bork3.sass +0 -2
  113. data/test/sass/templates/bork4.sass +0 -2
  114. data/test/sass/templates/bork5.sass +0 -3
  115. data/test/sass/templates/cached_import_option.scss +0 -3
  116. data/test/sass/templates/compact.sass +0 -17
  117. data/test/sass/templates/complex.sass +0 -305
  118. data/test/sass/templates/compressed.sass +0 -15
  119. data/test/sass/templates/double_import_loop1.sass +0 -1
  120. data/test/sass/templates/expanded.sass +0 -17
  121. data/test/sass/templates/filename_fn.scss +0 -18
  122. data/test/sass/templates/if.sass +0 -11
  123. data/test/sass/templates/import.sass +0 -12
  124. data/test/sass/templates/import_charset.sass +0 -9
  125. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  126. data/test/sass/templates/import_content.sass +0 -4
  127. data/test/sass/templates/importee.less +0 -2
  128. data/test/sass/templates/importee.sass +0 -19
  129. data/test/sass/templates/line_numbers.sass +0 -13
  130. data/test/sass/templates/mixin_bork.sass +0 -5
  131. data/test/sass/templates/mixins.sass +0 -76
  132. data/test/sass/templates/multiline.sass +0 -20
  133. data/test/sass/templates/nested.sass +0 -25
  134. data/test/sass/templates/nested_bork1.sass +0 -2
  135. data/test/sass/templates/nested_bork2.sass +0 -2
  136. data/test/sass/templates/nested_bork3.sass +0 -2
  137. data/test/sass/templates/nested_bork4.sass +0 -2
  138. data/test/sass/templates/nested_import.sass +0 -2
  139. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  140. data/test/sass/templates/options.sass +0 -2
  141. data/test/sass/templates/parent_ref.sass +0 -25
  142. data/test/sass/templates/same_name_different_ext.sass +0 -2
  143. data/test/sass/templates/same_name_different_ext.scss +0 -1
  144. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  145. data/test/sass/templates/script.sass +0 -101
  146. data/test/sass/templates/scss_import.scss +0 -12
  147. data/test/sass/templates/scss_importee.scss +0 -1
  148. data/test/sass/templates/single_import_loop.sass +0 -1
  149. data/test/sass/templates/subdir/import_up1.scss +0 -1
  150. data/test/sass/templates/subdir/import_up2.scss +0 -1
  151. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  152. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  153. data/test/sass/templates/subdir/subdir.sass +0 -6
  154. data/test/sass/templates/units.sass +0 -11
  155. data/test/sass/templates/warn.sass +0 -3
  156. data/test/sass/templates/warn_imported.sass +0 -4
  157. data/test/sass/test_helper.rb +0 -8
  158. data/test/sass/util/multibyte_string_scanner_test.rb +0 -152
  159. data/test/sass/util/normalized_map_test.rb +0 -50
  160. data/test/sass/util/subset_map_test.rb +0 -90
  161. data/test/sass/util_test.rb +0 -403
  162. data/test/sass/value_helpers_test.rb +0 -178
  163. data/test/test_helper.rb +0 -149
@@ -1,2 +0,0 @@
1
- scss {
2
- imported: yes; }
@@ -1 +0,0 @@
1
- #pi { width: 314px; }
@@ -1,3 +0,0 @@
1
- #nested { relative: true; }
2
-
3
- #subdir { font-size: 20px; font-weight: bold; }
@@ -1,11 +0,0 @@
1
- b {
2
- foo: 5px;
3
- bar: 24px;
4
- baz: 66.6666666667%;
5
- many-units: 32em;
6
- mm: 15mm;
7
- pc: 2pc;
8
- pt: -72pt;
9
- inches: 2in;
10
- more-inches: 3.5in;
11
- mixed: 2.0416666667in; }
File without changes
File without changes
@@ -1,365 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require File.dirname(__FILE__) + '/../test_helper'
3
- require 'sass/engine'
4
-
5
- class SassScriptConversionTest < MiniTest::Test
6
- def test_bool
7
- assert_renders "true"
8
- assert_renders "false"
9
- end
10
-
11
- def test_color
12
- assert_renders "#abcdef"
13
- assert_renders "blue"
14
- assert_renders "rgba(0, 1, 2, 0.2)"
15
- assert_renders "#abc"
16
- assert_renders "#0000ff"
17
- end
18
-
19
- def test_number
20
- assert_renders "10"
21
- assert_renders "10.35"
22
- assert_renders "12px"
23
- assert_renders "12.45px"
24
-
25
- assert_equal "12.3456789013", render("12.34567890129")
26
- end
27
-
28
- def test_string
29
- assert_renders '"foo"'
30
- assert_renders '"bar baz"'
31
- assert_equal '"baz bang"', render("'baz bang'")
32
- end
33
-
34
- def test_string_quotes
35
- assert_equal "'quote\"quote'", render('"quote\\"quote"')
36
- assert_equal '"quote\'quote"', render("'quote\\'quote'")
37
- assert_renders '"quote\'quote\\"quote"'
38
- assert_equal '"quote\'quote\\"quote"', render("'quote\\'quote\"quote'")
39
- end
40
-
41
- def test_string_escapes
42
- assert_renders '"foo\\\\bar"'
43
- end
44
-
45
- def test_funcall
46
- assert_renders "foo(true, blue)"
47
- assert_renders "hsla(20deg, 30%, 50%, 0.3)"
48
- assert_renders "blam()"
49
-
50
- assert_renders "-\xC3\xBFoo(12px)"
51
- assert_renders "-foo(12px)"
52
- end
53
-
54
- def test_funcall_with_keyword_args
55
- assert_renders "foo(arg1, arg2, $karg1: val, $karg2: val2)"
56
- assert_renders "foo($karg1: val, $karg2: val2)"
57
- end
58
-
59
- def test_funcall_with_hyphen_conversion_keyword_arg
60
- assert_renders "foo($a-b_c: val)"
61
- end
62
-
63
- def test_url
64
- assert_renders "url(foo.gif)"
65
- assert_renders "url($var)"
66
- assert_renders "url(\#{$var}/flip.gif)"
67
- end
68
-
69
- def test_variable
70
- assert_renders "$foo-bar"
71
- assert_renders "$flaznicate"
72
- end
73
-
74
- def test_null
75
- assert_renders "null"
76
- end
77
-
78
- def test_space_list
79
- assert_renders "foo bar baz"
80
- assert_renders "foo (bar baz) bip"
81
- assert_renders "foo (bar, baz) bip"
82
- end
83
-
84
- def test_comma_list
85
- assert_renders "foo, bar, baz"
86
- assert_renders "foo, (bar, baz), bip"
87
- assert_renders "foo, bar baz, bip"
88
- end
89
-
90
- def test_space_list_adds_parens_for_clarity
91
- assert_renders "(1 + 1) (2 / 4) (3 * 5)"
92
- end
93
-
94
- def test_comma_list_doesnt_add_parens
95
- assert_renders "1 + 1, 2 / 4, 3 * 5"
96
- end
97
-
98
- def test_empty_list
99
- assert_renders "()"
100
- end
101
-
102
- def test_list_in_args
103
- assert_renders "foo((a, b, c))"
104
- assert_renders "foo($arg: (a, b, c))"
105
- assert_renders "foo(a, b, (a, b, c)...)"
106
- end
107
-
108
- def test_singleton_list
109
- assert_renders "(1,)"
110
- assert_renders "(1 2 3,)"
111
- assert_renders "((1, 2, 3),)"
112
- end
113
-
114
- def test_map
115
- assert_renders "(foo: bar)"
116
- assert_renders "(foo: bar, baz: bip)"
117
- assert_renders "(foo: bar, baz: (bip: bap))"
118
- end
119
-
120
- def test_map_in_list
121
- assert_renders "(foo: bar) baz"
122
- assert_renders "(foo: bar), (baz: bip)"
123
- end
124
-
125
- def test_list_in_map
126
- assert_renders "(foo: bar baz)"
127
- assert_renders "(foo: (bar, baz), bip: bop)"
128
- end
129
-
130
- def test_selector
131
- assert_renders "&"
132
- end
133
-
134
- def self.test_precedence(outer, inner)
135
- op_outer = Sass::Script::Lexer::OPERATORS_REVERSE[outer]
136
- op_inner = Sass::Script::Lexer::OPERATORS_REVERSE[inner]
137
- class_eval <<RUBY
138
- def test_precedence_#{outer}_#{inner}
139
- assert_renders "$foo #{op_outer} $bar #{op_inner} $baz"
140
- assert_renders "$foo #{op_inner} $bar #{op_outer} $baz"
141
-
142
- assert_renders "($foo #{op_outer} $bar) #{op_inner} $baz"
143
- assert_renders "$foo #{op_inner} ($bar #{op_outer} $baz)"
144
-
145
- assert_equal "$foo #{op_outer} $bar #{op_inner} $baz",
146
- render("$foo #{op_outer} ($bar #{op_inner} $baz)")
147
- assert_equal "$foo #{op_inner} $bar #{op_outer} $baz",
148
- render("($foo #{op_inner} $bar) #{op_outer} $baz")
149
- end
150
- RUBY
151
- end
152
-
153
- def self.assert_associative(op_name, sibling_name)
154
- op = separator_for(op_name)
155
- sibling = separator_for(sibling_name)
156
- class_eval <<RUBY
157
- def test_associative_#{op_name}_#{sibling_name}
158
- assert_renders "$foo#{op}$bar#{op}$baz"
159
-
160
- assert_equal "$foo#{op}$bar#{op}$baz",
161
- render("$foo#{op}($bar#{op}$baz)")
162
- assert_equal "$foo#{op}$bar#{op}$baz",
163
- render("($foo#{op}$bar)#{op}$baz")
164
-
165
- assert_equal "$foo#{op}$bar#{sibling}$baz",
166
- render("$foo#{op}($bar#{sibling}$baz)")
167
- assert_equal "$foo#{sibling}$bar#{op}$baz",
168
- render("($foo#{sibling}$bar)#{op}$baz")
169
- end
170
- RUBY
171
- end
172
-
173
- def self.separator_for(op_name)
174
- case op_name
175
- when :comma; ", "
176
- when :space; " "
177
- else; " #{Sass::Script::Lexer::OPERATORS_REVERSE[op_name]} "
178
- end
179
- end
180
-
181
- def self.assert_non_associative(op_name, sibling_name)
182
- op = Sass::Script::Lexer::OPERATORS_REVERSE[op_name]
183
- sibling = Sass::Script::Lexer::OPERATORS_REVERSE[sibling_name]
184
- class_eval <<RUBY
185
- def test_non_associative_#{op_name}_#{sibling_name}
186
- assert_renders "$foo #{op} $bar #{op} $baz"
187
-
188
- assert_renders "$foo #{op} ($bar #{op} $baz)"
189
- assert_equal "$foo #{op} $bar #{op} $baz",
190
- render("($foo #{op} $bar) #{op} $baz")
191
-
192
- assert_renders "$foo #{op} ($bar #{sibling} $baz)"
193
- assert_equal "$foo #{sibling} $bar #{op} $baz",
194
- render("($foo #{sibling} $bar) #{op} $baz")
195
- end
196
- RUBY
197
- end
198
-
199
- test_precedence :or, :and
200
- test_precedence :and, :eq
201
- test_precedence :and, :neq
202
- test_precedence :eq, :gt
203
- test_precedence :eq, :gte
204
- test_precedence :eq, :lt
205
- test_precedence :eq, :lte
206
- test_precedence :gt, :plus
207
- test_precedence :gt, :minus
208
- test_precedence :plus, :times
209
- test_precedence :plus, :div
210
- test_precedence :plus, :mod
211
-
212
- assert_associative :plus, :minus
213
- assert_associative :times, :div
214
- assert_associative :times, :mod
215
-
216
- assert_non_associative :minus, :plus
217
- assert_non_associative :div, :times
218
- assert_non_associative :mod, :times
219
- assert_non_associative :gt, :gte
220
- assert_non_associative :gte, :lt
221
- assert_non_associative :lt, :lte
222
- assert_non_associative :lte, :gt
223
-
224
- def test_comma_precedence
225
- assert_renders "$foo, $bar, $baz"
226
-
227
- assert_renders "$foo ($bar, $baz)"
228
- assert_renders "($foo, $bar) $baz"
229
-
230
- assert_equal "$foo, $bar $baz", render("$foo, ($bar $baz)")
231
- assert_equal "$foo $bar, $baz", render("($foo $bar), $baz")
232
-
233
- assert_equal "$foo, ($bar, $baz)", render("$foo, ($bar, $baz)")
234
- assert_equal "($foo, $bar), $baz", render("($foo, $bar), $baz")
235
- end
236
-
237
- def test_space_precedence
238
- assert_renders "$foo $bar $baz"
239
-
240
- assert_renders "$foo or ($bar $baz)"
241
- assert_renders "($foo $bar) or $baz"
242
-
243
- assert_renders "$foo ($bar or $baz)"
244
- assert_renders "($foo or $bar) $baz"
245
-
246
- assert_equal "$foo ($bar $baz)", render("$foo ($bar $baz)")
247
- assert_equal "($foo $bar) $baz", render("($foo $bar) $baz")
248
- end
249
-
250
- def test_unary_op
251
- assert_renders "-12px"
252
- assert_renders '/"foo"'
253
- assert_renders 'not true'
254
-
255
- assert_renders "-(foo(12px))"
256
- assert_renders "-(-foo(12px))"
257
- assert_renders "-(_foo(12px))"
258
- assert_renders "-(\xC3\xBFoo(12px))"
259
- assert_renders "-(blue)"
260
-
261
- assert_equal 'not true or false', render('(not true) or false')
262
- assert_equal 'not (true or false)', render('not (true or false)')
263
- end
264
-
265
- def test_interpolation
266
- assert_equal 'unquote("#{$foo}#{$bar}#{$baz}")', render("$foo\#{$bar}$baz")
267
- assert_equal 'unquote("#{$foo}#{$bar} #{$baz}")', render("$foo\#{$bar} $baz")
268
- assert_equal 'unquote("#{$foo} #{$bar}#{$baz}")', render("$foo \#{$bar}$baz")
269
- assert_renders "$foo \#{$bar} $baz"
270
- assert_renders "$foo \#{$bar}\#{$bang} $baz"
271
- assert_renders "$foo \#{$bar} \#{$bang} $baz"
272
- assert_equal 'unquote("#{$bar}#{$baz}")', render("\#{$bar}$baz")
273
- assert_equal 'unquote("#{$foo}#{$bar}")', render("$foo\#{$bar}")
274
- assert_renders "\#{$bar}"
275
- end
276
-
277
- def test_interpolation_in_function
278
- assert_renders 'flabnabbit(#{1 + "foo"})'
279
- assert_equal 'flabnabbit(unquote("#{$foo} #{1 + "foo"}#{$baz}"))',
280
- render('flabnabbit($foo #{1 + "foo"}$baz)')
281
- assert_renders 'flabnabbit($foo #{1 + "foo"}#{2 + "bar"} $baz)'
282
- end
283
-
284
- def test_interpolation_in_string_function
285
- assert_renders 'calc(#{1 + "foo"})'
286
- assert_renders 'calc(foo#{1 + "foo"}baz)'
287
- end
288
-
289
- def test_interpolation_near_operators
290
- assert_renders '#{1 + 2} , #{3 + 4}'
291
- assert_renders '#{1 + 2}, #{3 + 4}'
292
- assert_renders '#{1 + 2} ,#{3 + 4}'
293
- assert_renders '#{1 + 2},#{3 + 4}'
294
- assert_renders '#{1 + 2}, #{3 + 4}, #{5 + 6}'
295
- assert_renders '3, #{3 + 4}, 11'
296
-
297
- assert_renders '3 / #{3 + 4}'
298
- assert_renders '3 /#{3 + 4}'
299
- assert_renders '3/ #{3 + 4}'
300
- assert_renders '3/#{3 + 4}'
301
-
302
- assert_equal 'unquote("#{1 + 2} * 7")', render('#{1 + 2} * 7')
303
- assert_equal 'unquote("#{1 + 2}* 7")', render('#{1 + 2}* 7')
304
- assert_equal 'unquote("#{1 + 2} *7")', render('#{1 + 2} *7')
305
- assert_equal 'unquote("#{1 + 2}*7")', render('#{1 + 2}*7')
306
-
307
- assert_renders '-#{1 + 2}'
308
- assert_equal 'unquote("- #{1 + 2}")', render('- #{1 + 2}')
309
-
310
- assert_equal 'unquote("5 + #{1 + 2} * #{3 + 4}")', render('5 + #{1 + 2} * #{3 + 4}')
311
- assert_equal 'unquote("5 +#{1 + 2} * #{3 + 4}")', render('5 +#{1 + 2} * #{3 + 4}')
312
- assert_equal 'unquote("5+#{1 + 2} * #{3 + 4}")', render('5+#{1 + 2} * #{3 + 4}')
313
- assert_equal 'unquote("#{1 + 2} * #{3 + 4} + 5")', render('#{1 + 2} * #{3 + 4} + 5')
314
- assert_equal 'unquote("#{1 + 2} * #{3 + 4}+ 5")', render('#{1 + 2} * #{3 + 4}+ 5')
315
- assert_equal 'unquote("#{1 + 2} * #{3 + 4}+5")', render('#{1 + 2} * #{3 + 4}+5')
316
-
317
- assert_equal '5 / unquote("#{1 + 2} + #{3 + 4}")', render('5 / (#{1 + 2} + #{3 + 4})')
318
- assert_equal '5 / unquote("#{1 + 2} + #{3 + 4}")', render('5 /(#{1 + 2} + #{3 + 4})')
319
- assert_equal '5 / unquote("#{1 + 2} + #{3 + 4}")', render('5 /( #{1 + 2} + #{3 + 4} )')
320
- assert_equal 'unquote("#{1 + 2} + #{3 + 4}") / 5', render('(#{1 + 2} + #{3 + 4}) / 5')
321
- assert_equal 'unquote("#{1 + 2} + #{3 + 4}") / 5', render('(#{1 + 2} + #{3 + 4})/ 5')
322
- assert_equal 'unquote("#{1 + 2} + #{3 + 4}") / 5', render('( #{1 + 2} + #{3 + 4} )/ 5')
323
-
324
- assert_equal 'unquote("#{1 + 2} + #{2 + 3}")', render('#{1 + 2} + 2 + 3')
325
- assert_equal 'unquote("#{1 + 2} +#{2 + 3}")', render('#{1 + 2} +2 + 3')
326
- end
327
-
328
- def test_string_interpolation
329
- assert_renders '"foo#{$bar}baz"'
330
- assert_renders '"foo #{$bar}baz"'
331
- assert_renders '"foo#{$bar} baz"'
332
- assert_renders '"foo #{$bar} baz"'
333
- assert_renders '"foo #{$bar}#{$bang} baz"'
334
- assert_renders '"foo #{$bar} #{$bang} baz"'
335
- assert_renders '"#{$bar}baz"'
336
- assert_renders '"foo#{$bar}"'
337
- assert_renders '"#{$bar}"'
338
-
339
- assert_renders "'\"\#{\"bar\"}\"'"
340
- assert_renders '"\#{bar}"'
341
-
342
- assert_equal '"foo#{$bar}baz"', render("'foo\#{$bar}baz'")
343
- end
344
-
345
- def test_bracketed_lists
346
- assert_renders("[]")
347
- assert_renders("[foo, bar]")
348
- assert_renders("[[foo]]")
349
- assert_renders("[(foo bar)]")
350
- assert_renders("[foo bar,]")
351
- assert_renders("[(foo,)]")
352
- end
353
-
354
- private
355
-
356
- def assert_renders(script, options = {})
357
- assert_equal(script, render(script, options))
358
- end
359
-
360
- def render(script, options = {})
361
- munge_filename(options)
362
- node = Sass::Script.parse(script, 1, 0, options.merge(:_convert => true))
363
- node.to_sass
364
- end
365
- end
@@ -1,1429 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require File.dirname(__FILE__) + '/../test_helper'
3
- require 'sass/engine'
4
-
5
- module Sass::Script::Functions::UserFunctions
6
- def assert_options(val)
7
- val.options[:foo]
8
- Sass::Script::Value::String.new("Options defined!")
9
- end
10
-
11
- def arg_error
12
- assert_options
13
- end
14
- end
15
-
16
- module Sass::Script::Functions
17
- include Sass::Script::Functions::UserFunctions
18
- end
19
-
20
- class SassScriptTest < MiniTest::Test
21
- include Sass::Script
22
-
23
- def test_color_clamps_input
24
- assert_equal 0, Sass::Script::Value::Color.new([1, 2, -1]).blue
25
- assert_equal 255, Sass::Script::Value::Color.new([256, 2, 3]).red
26
- end
27
-
28
- def test_color_clamps_rgba_input
29
- assert_equal 1, Sass::Script::Value::Color.new([1, 2, 3, 1.1]).alpha
30
- assert_equal 0, Sass::Script::Value::Color.new([1, 2, 3, -0.1]).alpha
31
- end
32
-
33
- def test_color_from_hex
34
- assert_equal Sass::Script::Value::Color.new([0,0,0]), Sass::Script::Value::Color.from_hex('000000')
35
- assert_equal Sass::Script::Value::Color.new([0,0,0]), Sass::Script::Value::Color.from_hex('#000000')
36
- end
37
-
38
- def test_string_escapes
39
- assert_equal "'", resolve("\"'\"")
40
- assert_equal '"', resolve("\"\\\"\"")
41
- assert_equal "\\", resolve("\"\\\\\"")
42
- assert_equal "☃", resolve("\"\\2603\"")
43
- assert_equal "☃f", resolve("\"\\2603 f\"")
44
- assert_equal "☃x", resolve("\"\\2603x\"")
45
- assert_equal "\\2603", resolve("\"\\\\2603\"")
46
- assert_equal "\#{foo}", resolve("\"\\\#{foo}\"")
47
-
48
- # U+FFFD is the replacement character, "�".
49
- assert_equal [0xFFFD].pack("U"), resolve("\"\\0\"")
50
- assert_equal [0xFFFD].pack("U"), resolve("\"\\FFFFFF\"")
51
- assert_equal [0xFFFD].pack("U"), resolve("\"\\D800\"")
52
- assert_equal [0xD7FF].pack("U"), resolve("\"\\D7FF\"")
53
- assert_equal [0xFFFD].pack("U"), resolve("\"\\DFFF\"")
54
- assert_equal [0xE000].pack("U"), resolve("\"\\E000\"")
55
- end
56
-
57
- def test_string_escapes_are_resolved_before_operators
58
- assert_equal "true", resolve('"abc" == "\61\62\63"')
59
- end
60
-
61
- def test_string_quote
62
- assert_equal '"foo"', resolve_quoted('"foo"')
63
- assert_equal "'f\"oo'", resolve_quoted('"f\"oo"')
64
- assert_equal "\"f'oo\"", resolve_quoted("'f\\'oo'")
65
- assert_equal "\"f'o\\\"o\"", resolve_quoted("'f\\'o\"o'")
66
- assert_equal '"foo bar"', resolve_quoted('"foo\20 bar"')
67
- assert_equal '"foo\a bar"', resolve_quoted('"foo\a bar"')
68
- assert_equal '"x\ay"', resolve_quoted('"x\a y"')
69
- assert_equal '"\a "', resolve_quoted('"\a\20"')
70
- assert_equal '"\a abcdef"', resolve_quoted('"\a abcdef"')
71
- assert_equal '"☃abcdef"', resolve_quoted('"\2603 abcdef"')
72
- assert_equal '"\\\\"', resolve_quoted('"\\\\"')
73
- assert_equal '"foobar"', resolve_quoted("\"foo\\\nbar\"")
74
- assert_equal '"#{foo}"', resolve_quoted("\"\\\#{foo}\"")
75
- end
76
-
77
- def test_color_names
78
- assert_equal "white", resolve("white")
79
- assert_equal "#ffffff", resolve("#ffffff")
80
- silence_warnings {assert_equal "#fffffe", resolve("white - #000001")}
81
- assert_equal "transparent", resolve("transparent")
82
- assert_equal "rgba(0, 0, 0, 0)", resolve("rgba(0, 0, 0, 0)")
83
- end
84
-
85
- def test_rgba_color_literals
86
- assert_equal Sass::Script::Value::Color.new([1, 2, 3, 0.75]), eval("rgba(1, 2, 3, 0.75)")
87
- assert_equal "rgba(1, 2, 3, 0.75)", resolve("rgba(1, 2, 3, 0.75)")
88
-
89
- assert_equal Sass::Script::Value::Color.new([1, 2, 3, 0]), eval("rgba(1, 2, 3, 0)")
90
- assert_equal "rgba(1, 2, 3, 0)", resolve("rgba(1, 2, 3, 0)")
91
-
92
- assert_equal Sass::Script::Value::Color.new([1, 2, 3]), eval("rgba(1, 2, 3, 1)")
93
- assert_equal Sass::Script::Value::Color.new([1, 2, 3, 1]), eval("rgba(1, 2, 3, 1)")
94
- assert_equal "#010203", resolve("rgba(1, 2, 3, 1)")
95
- assert_equal "white", resolve("rgba(255, 255, 255, 1)")
96
- end
97
-
98
- def test_rgba_color_math
99
- silence_warnings {assert_equal "rgba(50, 50, 100, 0.35)", resolve("rgba(1, 1, 2, 0.35) * rgba(50, 50, 50, 0.35)")}
100
- silence_warnings {assert_equal "rgba(52, 52, 52, 0.25)", resolve("rgba(2, 2, 2, 0.25) + rgba(50, 50, 50, 0.25)")}
101
-
102
- assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: rgba(1, 2, 3, 0.15) + rgba(50, 50, 50, 0.75)") do
103
- silence_warnings {resolve("rgba(1, 2, 3, 0.15) + rgba(50, 50, 50, 0.75)")}
104
- end
105
- assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: #123456 * rgba(50, 50, 50, 0.75)") do
106
- silence_warnings {resolve("#123456 * rgba(50, 50, 50, 0.75)")}
107
- end
108
- assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: rgba(50, 50, 50, 0.75) / #123456") do
109
- silence_warnings {resolve("rgba(50, 50, 50, 0.75) / #123456")}
110
- end
111
- end
112
-
113
- def test_rgba_number_math
114
- silence_warnings {assert_equal "rgba(49, 49, 49, 0.75)", resolve("rgba(50, 50, 50, 0.75) - 1")}
115
- silence_warnings {assert_equal "rgba(100, 100, 100, 0.75)", resolve("rgba(50, 50, 50, 0.75) * 2")}
116
- end
117
-
118
- def test_rgba_rounding
119
- assert_equal "rgba(10, 1, 0, 0.1234567892)", resolve("rgba(10.0, 1.23456789, 0.0, 0.12345678919)")
120
- end
121
-
122
- def test_rgb_calc
123
- assert_equal "rgb(calc(255 - 5), 0, 0)", resolve("rgb(calc(255 - 5), 0, 0)")
124
- end
125
-
126
- def test_rgba_calc
127
- assert_equal "rgba(calc(255 - 5), 0, 0, 0.1)",
128
- resolve("rgba(calc(255 - 5), 0, 0, 0.1)")
129
- assert_equal "rgba(127, 0, 0, calc(0.1 + 0.5))",
130
- resolve("rgba(127, 0, 0, calc(0.1 + 0.5))")
131
- end
132
-
133
- def test_rgba_shorthand_calc
134
- assert_equal "rgba(255, 0, 0, calc(0.1 + 0.5))",
135
- resolve("rgba(red, calc(0.1 + 0.5))")
136
- end
137
-
138
- def test_hsl_calc
139
- assert_equal "hsl(calc(360 * 5 / 6), 50%, 50%)", resolve("hsl(calc(360 * 5 / 6), 50%, 50%)")
140
- end
141
-
142
- def test_hsla_calc
143
- assert_equal "hsla(calc(360 * 5 / 6), 50%, 50%, 0.1)",
144
- resolve("hsla(calc(360 * 5 / 6), 50%, 50%, 0.1)")
145
- assert_equal "hsla(270, 50%, 50%, calc(0.1 + 0.1))",
146
- resolve("hsla(270, 50%, 50%, calc(0.1 + 0.1))")
147
- end
148
-
149
- def test_compressed_colors
150
- assert_equal "#123456", resolve("#123456", :style => :compressed)
151
- assert_equal "rgba(1,2,3,0.5)", resolve("rgba(1, 2, 3, 0.5)", :style => :compressed)
152
- assert_equal "#123", resolve("#112233", :style => :compressed)
153
- assert_equal "#000", resolve("black", :style => :compressed)
154
- assert_equal "red", resolve("#f00", :style => :compressed)
155
- assert_equal "blue", resolve("blue", :style => :compressed)
156
- assert_equal "navy", resolve("#000080", :style => :compressed)
157
- assert_equal "navy #fff", resolve("#000080 white", :style => :compressed)
158
- assert_equal "This color is #fff", resolve('"This color is #{ white }"', :style => :compressed)
159
- assert_equal "transparent", resolve("rgba(0, 0, 0, 0)", :style => :compressed)
160
- end
161
-
162
- def test_compressed_comma
163
- # assert_equal "foo,bar,baz", resolve("foo, bar, baz", :style => :compressed)
164
- # assert_equal "foo,#baf,baz", resolve("foo, #baf, baz", :style => :compressed)
165
- assert_equal "foo,#baf,red", resolve("foo, #baf, #f00", :style => :compressed)
166
- end
167
-
168
- def test_implicit_strings
169
- assert_equal Sass::Script::Value::String.new("foo"), eval("foo")
170
- assert_equal Sass::Script::Value::String.new("foo/bar"), eval("foo/bar")
171
- end
172
-
173
- def test_basic_interpolation
174
- assert_equal "foo3bar", resolve("foo\#{1 + 2}bar")
175
- assert_equal "foo3 bar", resolve("foo\#{1 + 2} bar")
176
- assert_equal "foo 3bar", resolve("foo \#{1 + 2}bar")
177
- assert_equal "foo 3 bar", resolve("foo \#{1 + 2} bar")
178
- assert_equal "foo 35 bar", resolve("foo \#{1 + 2}\#{2 + 3} bar")
179
- assert_equal "foo 3 5 bar", resolve("foo \#{1 + 2} \#{2 + 3} bar")
180
- assert_equal "3bar", resolve("\#{1 + 2}bar")
181
- assert_equal "foo3", resolve("foo\#{1 + 2}")
182
- assert_equal "3", resolve("\#{1 + 2}")
183
- end
184
-
185
- def test_interpolation_in_function
186
- assert_equal 'flabnabbit(1foo)', resolve('flabnabbit(#{1 + "foo"})')
187
- assert_equal 'flabnabbit(foo 1foobaz)', resolve('flabnabbit(foo #{1 + "foo"}baz)')
188
- assert_equal('flabnabbit(foo 1foo2bar baz)',
189
- resolve('flabnabbit(foo #{1 + "foo"}#{2 + "bar"} baz)'))
190
- end
191
-
192
- def test_interpolation_near_operators
193
- silence_warnings do
194
- assert_equal '3 , 7', resolve('#{1 + 2} , #{3 + 4}')
195
- assert_equal '3, 7', resolve('#{1 + 2}, #{3 + 4}')
196
- assert_equal '3 ,7', resolve('#{1 + 2} ,#{3 + 4}')
197
- assert_equal '3,7', resolve('#{1 + 2},#{3 + 4}')
198
- assert_equal '3, 7, 11', resolve('#{1 + 2}, #{3 + 4}, #{5 + 6}')
199
- assert_equal '3, 7, 11', resolve('3, #{3 + 4}, 11')
200
- assert_equal '3, 7, 11', resolve('3, 7, #{5 + 6}')
201
-
202
- assert_equal '3 / 7', resolve('3 / #{3 + 4}')
203
- assert_equal '3 /7', resolve('3 /#{3 + 4}')
204
- assert_equal '3/ 7', resolve('3/ #{3 + 4}')
205
- assert_equal '3/7', resolve('3/#{3 + 4}')
206
-
207
- assert_equal '3 * 7', resolve('#{1 + 2} * 7')
208
- assert_equal '3* 7', resolve('#{1 + 2}* 7')
209
- assert_equal '3 *7', resolve('#{1 + 2} *7')
210
- assert_equal '3*7', resolve('#{1 + 2}*7')
211
-
212
- assert_equal '-3', resolve('-#{1 + 2}')
213
- assert_equal '- 3', resolve('- #{1 + 2}')
214
-
215
- assert_equal '5 + 3 * 7', resolve('5 + #{1 + 2} * #{3 + 4}')
216
- assert_equal '5 +3 * 7', resolve('5 +#{1 + 2} * #{3 + 4}')
217
- assert_equal '5+3 * 7', resolve('5+#{1 + 2} * #{3 + 4}')
218
- assert_equal '3 * 7 + 5', resolve('#{1 + 2} * #{3 + 4} + 5')
219
- assert_equal '3 * 7+ 5', resolve('#{1 + 2} * #{3 + 4}+ 5')
220
- assert_equal '3 * 7+5', resolve('#{1 + 2} * #{3 + 4}+5')
221
-
222
- assert_equal '5/3 + 7', resolve('5 / (#{1 + 2} + #{3 + 4})')
223
- assert_equal '5/3 + 7', resolve('5 /(#{1 + 2} + #{3 + 4})')
224
- assert_equal '5/3 + 7', resolve('5 /( #{1 + 2} + #{3 + 4} )')
225
- assert_equal '3 + 7/5', resolve('(#{1 + 2} + #{3 + 4}) / 5')
226
- assert_equal '3 + 7/5', resolve('(#{1 + 2} + #{3 + 4})/ 5')
227
- assert_equal '3 + 7/5', resolve('( #{1 + 2} + #{3 + 4} )/ 5')
228
-
229
- assert_equal '3 + 5', resolve('#{1 + 2} + 2 + 3')
230
- assert_equal '3 +5', resolve('#{1 + 2} +2 + 3')
231
- end
232
- end
233
-
234
- def test_string_interpolation
235
- assert_equal "foo bar, baz bang", resolve('"foo #{"bar"}, #{"baz"} bang"')
236
- assert_equal "foo bar baz bang", resolve('"foo #{"#{"ba" + "r"} baz"} bang"')
237
- assert_equal 'foo #{bar baz} bang', resolve('"foo \#{#{"ba" + "r"} baz} bang"')
238
- assert_equal 'foo #{baz bang', resolve('"foo #{"\#{" + "baz"} bang"')
239
- assert_equal "foo2bar", resolve('\'foo#{1 + 1}bar\'')
240
- assert_equal "foo2bar", resolve('"foo#{1 + 1}bar"')
241
- assert_equal "foo1bar5baz4bang", resolve('\'foo#{1 + "bar#{2 + 3}baz" + 4}bang\'')
242
- end
243
-
244
- def test_interpolation_in_interpolation
245
- assert_equal 'foo', resolve('#{#{foo}}')
246
- assert_equal 'foo', resolve('"#{#{foo}}"')
247
- assert_equal 'foo', resolve('#{"#{foo}"}')
248
- assert_equal 'foo', resolve('"#{"#{foo}"}"')
249
- end
250
-
251
- def test_interpolation_with_newline
252
- assert_equal "\nbang", resolve('"#{"\a "}bang"')
253
- assert_equal "\n\nbang", resolve('"#{"\a "}\a bang"')
254
- end
255
-
256
- def test_rule_interpolation
257
- assert_equal(<<CSS, render(<<SASS))
258
- foo bar baz bang {
259
- a: b; }
260
- CSS
261
- foo \#{"\#{"ba" + "r"} baz"} bang
262
- a: b
263
- SASS
264
- assert_equal(<<CSS, render(<<SASS))
265
- foo [bar="\#{bar baz}"] bang {
266
- a: b; }
267
- CSS
268
- foo [bar="\\\#{\#{"ba" + "r"} baz}"] bang
269
- a: b
270
- SASS
271
- assert_equal(<<CSS, render(<<SASS))
272
- foo [bar="\#{baz"] bang {
273
- a: b; }
274
- CSS
275
- foo [bar="\#{"\\\#{" + "baz"}"] bang
276
- a: b
277
- SASS
278
- end
279
-
280
- def test_inaccessible_functions
281
- assert_equal "send(to_s)", resolve("send(to_s)", :line => 2)
282
- assert_equal "public_instance_methods()", resolve("public_instance_methods()")
283
- end
284
-
285
- def test_adding_functions_directly_to_functions_module
286
- assert !Functions.callable?('nonexistent')
287
- Functions.class_eval { def nonexistent; end }
288
- assert Functions.callable?('nonexistent')
289
- Functions.send :remove_method, :nonexistent
290
- end
291
-
292
- def test_default_functions
293
- assert_equal "url(12)", resolve("url(12)")
294
- assert_equal 'blam("foo")', resolve('blam("foo")')
295
- end
296
-
297
- def test_function_results_have_options
298
- assert_equal "Options defined!", resolve("assert_options(abs(1))")
299
- assert_equal "Options defined!", resolve("assert_options(round(1.2))")
300
- end
301
-
302
- def test_funcall_requires_no_whitespace_before_lparen
303
- assert_equal "no-repeat 15px", resolve("no-repeat (7px + 8px)")
304
- assert_equal "no-repeat(15px)", resolve("no-repeat(7px + 8px)")
305
- end
306
-
307
- def test_dynamic_url
308
- assert_equal "url(foo-bar)", resolve("url($foo)", {}, env('foo' => Sass::Script::Value::String.new("foo-bar")))
309
- assert_equal "url(foo-bar baz)", resolve("url($foo $bar)", {}, env('foo' => Sass::Script::Value::String.new("foo-bar"), 'bar' => Sass::Script::Value::String.new("baz")))
310
- assert_equal "url(foo baz)", resolve("url(foo $bar)", {}, env('bar' => Sass::Script::Value::String.new("baz")))
311
- assert_equal "url(foo bar)", resolve("url(foo bar)")
312
- end
313
-
314
- def test_url_with_interpolation
315
- assert_equal "url(http://sass-lang.com/images/foo-bar)", resolve("url(http://sass-lang.com/images/\#{foo-bar})")
316
- assert_equal 'url("http://sass-lang.com/images/foo-bar")', resolve("url('http://sass-lang.com/images/\#{foo-bar}')")
317
- assert_equal 'url("http://sass-lang.com/images/foo-bar")', resolve('url("http://sass-lang.com/images/#{foo-bar}")')
318
- assert_unquoted "url(http://sass-lang.com/images/\#{foo-bar})"
319
- end
320
-
321
- def test_hyphenated_variables
322
- assert_equal("a-b", resolve("$a-b", {}, env("a-b" => Sass::Script::Value::String.new("a-b"))))
323
- end
324
-
325
- def test_ruby_equality
326
- assert_equal eval('"foo"'), eval('"foo"')
327
- assert_equal eval('1'), eval('1.0')
328
- assert_equal eval('1 2 3.0'), eval('1 2 3')
329
- assert_equal eval('1, 2, 3.0'), eval('1, 2, 3')
330
- assert_equal eval('(1 2), (3, 4), (5 6)'), eval('(1 2), (3, 4), (5 6)')
331
- refute_equal eval('1, 2, 3'), eval('1 2 3')
332
- refute_equal eval('1'), eval('"1"')
333
- end
334
-
335
- def test_booleans
336
- assert_equal "true", resolve("true")
337
- assert_equal "false", resolve("false")
338
- end
339
-
340
- def test_null
341
- assert_equal "", resolve("null")
342
- end
343
-
344
- def test_boolean_ops
345
- assert_equal "true", resolve("true and true")
346
- assert_equal "true", resolve("false or true")
347
- assert_equal "true", resolve("true or false")
348
- assert_equal "true", resolve("true or true")
349
- assert_equal "false", resolve("false or false")
350
- assert_equal "false", resolve("false and true")
351
- assert_equal "false", resolve("true and false")
352
- assert_equal "false", resolve("false and false")
353
-
354
- assert_equal "true", resolve("not false")
355
- assert_equal "false", resolve("not true")
356
- assert_equal "true", resolve("not not true")
357
-
358
- assert_equal "1", resolve("false or 1")
359
- assert_equal "false", resolve("false and 1")
360
- assert_equal "2", resolve("2 or 3")
361
- assert_equal "3", resolve("2 and 3")
362
-
363
- assert_equal "true", resolve("null or true")
364
- assert_equal "true", resolve("true or null")
365
- assert_equal "", resolve("null or null")
366
- assert_equal "", resolve("null and true")
367
- assert_equal "", resolve("true and null")
368
- assert_equal "", resolve("null and null")
369
-
370
- assert_equal "true", resolve("not null")
371
-
372
- assert_equal "1", resolve("null or 1")
373
- assert_equal "", resolve("null and 1")
374
- end
375
-
376
- def test_arithmetic_ops
377
- assert_equal "2", resolve("1 + 1")
378
- assert_equal "0", resolve("1 - 1")
379
- assert_equal "8", resolve("2 * 4")
380
- assert_equal "0.5", resolve("(2 / 4)")
381
- assert_equal "2", resolve("(4 / 2)")
382
-
383
- assert_equal "-1", resolve("-1")
384
- end
385
-
386
- def test_subtraction_vs_minus_vs_identifier
387
- assert_equal "0.25em", resolve("1em-.75")
388
- assert_equal "0.25em", resolve("1em-0.75")
389
- assert_equal "1em -0.75", resolve("1em -.75")
390
- assert_equal "1em -0.75", resolve("1em -0.75")
391
- assert_equal "1em- 0.75", resolve("1em- .75")
392
- assert_equal "1em- 0.75", resolve("1em- 0.75")
393
- assert_equal "0.25em", resolve("1em - .75")
394
- assert_equal "0.25em", resolve("1em - 0.75")
395
- end
396
-
397
- def test_string_ops
398
- assert_equal '"foo" "bar"', resolve('"foo" "bar"')
399
- assert_equal "true 1", resolve('true 1')
400
- assert_equal '"foo", "bar"', resolve("'foo' , 'bar'")
401
- assert_equal "true, 1", resolve('true , 1')
402
- assert_equal "foobar", resolve('"foo" + "bar"')
403
- assert_equal "\nfoo\nxyz", resolve('"\a foo" + "\axyz"')
404
- assert_equal "true1", resolve('true + 1')
405
- assert_equal '"foo"-"bar"', resolve("'foo' - 'bar'")
406
- assert_equal "true-1", resolve('true - 1')
407
- assert_equal '"foo"/"bar"', resolve('"foo" / "bar"')
408
- assert_equal "true/1", resolve('true / 1')
409
-
410
- assert_equal '-"bar"', resolve("- 'bar'")
411
- assert_equal "-true", resolve('- true')
412
- assert_equal '/"bar"', resolve('/ "bar"')
413
- assert_equal "/true", resolve('/ true')
414
- end
415
-
416
- def test_relational_ops
417
- assert_equal "false", resolve("1 > 2")
418
- assert_equal "false", resolve("2 > 2")
419
- assert_equal "true", resolve("3 > 2")
420
- assert_equal "false", resolve("1 >= 2")
421
- assert_equal "true", resolve("2 >= 2")
422
- assert_equal "true", resolve("3 >= 2")
423
- assert_equal "true", resolve("1 < 2")
424
- assert_equal "false", resolve("2 < 2")
425
- assert_equal "false", resolve("3 < 2")
426
- assert_equal "true", resolve("1 <= 2")
427
- assert_equal "true", resolve("2 <= 2")
428
- assert_equal "false", resolve("3 <= 2")
429
- end
430
-
431
- def test_null_ops
432
- assert_raise_message(Sass::SyntaxError,
433
- 'Invalid null operation: "null plus 1".') {eval("null + 1")}
434
- assert_raise_message(Sass::SyntaxError,
435
- 'Invalid null operation: "null minus 1".') {eval("null - 1")}
436
- assert_raise_message(Sass::SyntaxError,
437
- 'Invalid null operation: "null times 1".') {eval("null * 1")}
438
- assert_raise_message(Sass::SyntaxError,
439
- 'Invalid null operation: "null div 1".') {eval("null / 1")}
440
- assert_raise_message(Sass::SyntaxError,
441
- 'Invalid null operation: "null mod 1".') {eval("null % 1")}
442
- assert_raise_message(Sass::SyntaxError,
443
- 'Invalid null operation: "1 plus null".') {eval("1 + null")}
444
- assert_raise_message(Sass::SyntaxError,
445
- 'Invalid null operation: "1 minus null".') {eval("1 - null")}
446
- assert_raise_message(Sass::SyntaxError,
447
- 'Invalid null operation: "1 times null".') {eval("1 * null")}
448
- assert_raise_message(Sass::SyntaxError,
449
- 'Invalid null operation: "1 div null".') {eval("1 / null")}
450
- assert_raise_message(Sass::SyntaxError,
451
- 'Invalid null operation: "1 mod null".') {eval("1 % null")}
452
- assert_raise_message(Sass::SyntaxError,
453
- 'Invalid null operation: "1 gt null".') {eval("1 > null")}
454
- assert_raise_message(Sass::SyntaxError,
455
- 'Invalid null operation: "null lt 1".') {eval("null < 1")}
456
- assert_raise_message(Sass::SyntaxError,
457
- 'Invalid null operation: "null plus null".') {eval("null + null")}
458
- assert_raise_message(Sass::SyntaxError,
459
- 'Invalid null operation: ""foo" plus null".') {eval("foo + null")}
460
- end
461
-
462
- def test_equals
463
- assert_equal("true", resolve('"foo" == $foo', {},
464
- env("foo" => Sass::Script::Value::String.new("foo"))))
465
- assert_equal "true", resolve("1 == 1.0")
466
- assert_equal "true", resolve("false != true")
467
- assert_equal "false", resolve("1em == 1px")
468
- assert_equal "false", resolve("12 != 12")
469
- assert_equal "true", resolve("(foo bar baz) == (foo bar baz)")
470
- assert_equal "true", resolve("(foo, bar, baz) == (foo, bar, baz)")
471
- assert_equal "true", resolve('((1 2), (3, 4), (5 6)) == ((1 2), (3, 4), (5 6))')
472
- assert_equal "true", resolve('((1 2), (3 4)) == (1 2, 3 4)')
473
- assert_equal "false", resolve('((1 2) 3) == (1 2 3)')
474
- assert_equal "false", resolve('(1 (2 3)) == (1 2 3)')
475
- assert_equal "false", resolve('((1, 2) (3, 4)) == (1, 2 3, 4)')
476
- assert_equal "false", resolve('(1 2 3) == (1, 2, 3)')
477
-
478
- assert_equal "true", resolve('null == null')
479
- assert_equal "false", resolve('"null" == null')
480
- assert_equal "false", resolve('0 == null')
481
- assert_equal "false", resolve('() == null')
482
-
483
- assert_equal "false", resolve('null != null')
484
- assert_equal "true", resolve('"null" != null')
485
- assert_equal "true", resolve('0 != null')
486
- assert_equal "true", resolve('() != null')
487
- end
488
-
489
- def test_mod
490
- assert_equal "5", resolve("29 % 12")
491
- assert_equal "5px", resolve("29px % 12")
492
- assert_equal "5px", resolve("29px % 12px")
493
- end
494
-
495
- def test_operation_precedence
496
- assert_equal "false true", resolve("true and false false or true")
497
- assert_equal "true", resolve("false and true or true and true")
498
- assert_equal "true", resolve("1 == 2 or 3 == 3")
499
- assert_equal "true", resolve("1 < 2 == 3 >= 3")
500
- assert_equal "true", resolve("1 + 3 > 4 - 2")
501
- assert_equal "11", resolve("1 + 2 * 3 + 4")
502
- end
503
-
504
- def test_functions
505
- assert_equal "#80ff80", resolve("hsl(120, 100%, 75%)")
506
- silence_warnings {assert_equal "#81ff81", resolve("hsl(120, 100%, 75%) + #010001")}
507
- end
508
-
509
- def test_operator_unit_conversion
510
- assert_equal "1.1cm", resolve("1cm + 1mm")
511
- assert_equal "8q", resolve("4q + 1mm")
512
- assert_equal "40.025cm", resolve("40cm + 1q")
513
- assert_equal "2in", resolve("1in + 96px")
514
- assert_equal "true", resolve("2mm < 1cm")
515
- assert_equal "true", resolve("10mm == 1cm")
516
- assert_equal "true", resolve("1.1cm == 11mm")
517
- assert_equal "true", resolve("2mm == 8q")
518
- assert_equal "false", resolve("2px > 3q")
519
-
520
- Sass::Deprecation.allow_double_warnings do
521
- assert_warning(<<WARNING) {assert_equal "true", resolve("1 == 1cm")}
522
- DEPRECATION WARNING on line 1 of test_operator_unit_conversion_inline.sass:
523
- The result of `1 == 1cm` will be `false` in future releases of Sass.
524
- Unitless numbers will no longer be equal to the same numbers with units.
525
- WARNING
526
-
527
- assert_warning(<<WARNING) {assert_equal "false", resolve("1 != 1cm")}
528
- DEPRECATION WARNING on line 1 of test_operator_unit_conversion_inline.sass:
529
- The result of `1 != 1cm` will be `true` in future releases of Sass.
530
- Unitless numbers will no longer be equal to the same numbers with units.
531
- WARNING
532
- end
533
- end
534
-
535
- def test_length_units
536
- assert_equal "2.54", resolve("(1in/1cm)")
537
- assert_equal "2.3622047244", resolve("(1cm/1pc)")
538
- assert_equal "4.2333333333", resolve("(1pc/1mm)")
539
- assert_equal "2.8346456693", resolve("(1mm/1pt)")
540
- assert_equal "1.3333333333", resolve("(1pt/1px)")
541
- assert_equal "0.0104166667", resolve("(1px/1in)")
542
- assert_equal "1.0583333333", resolve("(1px/1q)")
543
- assert_equal "0.0590551181", resolve("(1q/1pc)")
544
- end
545
-
546
- def test_angle_units
547
- assert_equal "1.1111111111", resolve("(1deg/1grad)")
548
- assert_equal "0.0157079633", resolve("(1grad/1rad)")
549
- assert_equal "0.1591549431", resolve("(1rad/1turn)")
550
- assert_equal "360", resolve("(1turn/1deg)")
551
- end
552
-
553
- def test_time_units
554
- assert_equal "1000", resolve("(1s/1ms)")
555
- end
556
-
557
- def test_frequency_units
558
- assert_equal "0.001", resolve("(1Hz/1kHz)")
559
- end
560
-
561
- def test_resolution_units
562
- assert_equal "0.3937007874", resolve("(1dpi/1dpcm)")
563
- assert_equal "0.0264583333", resolve("(1dpcm/1dppx)")
564
- assert_equal "96", resolve("(1dppx/1dpi)")
565
- end
566
-
567
- def test_operations_have_options
568
- assert_equal "Options defined!", resolve("assert_options(1 + 1)")
569
- assert_equal "Options defined!", resolve("assert_options('bar' + 'baz')")
570
- end
571
-
572
- def test_slash_compiles_literally_when_left_alone
573
- assert_equal "1px/2px", resolve("1px/2px")
574
- assert_equal "1px/2px/3px/4px", resolve("1px/2px/3px/4px")
575
-
576
- assert_equal "1px/2px redpx bluepx", resolve("1px/2px redpx bluepx")
577
- assert_equal "foo 1px/2px/3px bar", resolve("foo 1px/2px/3px bar")
578
- end
579
-
580
- def test_slash_divides_with_parens
581
- assert_equal "0.5", resolve("(1px/2px)")
582
- assert_equal "0.5", resolve("(1px)/2px")
583
- assert_equal "0.5", resolve("1px/(2px)")
584
- end
585
-
586
- def test_slash_divides_with_other_arithmetic
587
- assert_equal "0.5px", resolve("1px*1px/2px")
588
- assert_equal "0.5px", resolve("1px/2px*1px")
589
- assert_equal "0.5", resolve("0+1px/2px")
590
- assert_equal "0.5", resolve("1px/2px+0")
591
- end
592
-
593
- def test_slash_divides_with_variable
594
- assert_equal "0.5", resolve("$var/2px", {}, env("var" => eval("1px")))
595
- assert_equal "0.5", resolve("1px/$var", {}, env("var" => eval("2px")))
596
- assert_equal "0.5", resolve("$var", {}, env("var" => eval("1px/2px")))
597
- end
598
-
599
- # Regression test for issue 1786.
600
- def test_slash_division_within_list
601
- assert_equal "1 1/2 1/2", resolve("(1 1/2 1/2)")
602
- assert_equal "1/2 1/2", resolve("(1/2 1/2)")
603
- assert_equal "1/2", resolve("(1/2,)")
604
- end
605
-
606
- def test_non_ident_colors_with_wrong_number_of_digits
607
- assert_raise_message(Sass::SyntaxError,
608
- 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#1"') {eval("#1")}
609
- assert_raise_message(Sass::SyntaxError,
610
- 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#12"') {eval("#12")}
611
- assert_raise_message(Sass::SyntaxError,
612
- 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#1234"') {eval("#1234")}
613
- assert_raise_message(Sass::SyntaxError,
614
- 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#12345"') {eval("#12345")}
615
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "": expected expression (e.g. ' \
616
- '1px, bold), was "#1234567"') {eval("#1234567")}
617
- end
618
-
619
- def test_case_insensitive_color_names
620
- assert_equal "BLUE", resolve("BLUE")
621
- assert_equal "rEd", resolve("rEd")
622
- assert_equal "#804000", resolve("mix(GrEeN, ReD)")
623
- end
624
-
625
- def test_empty_list
626
- assert_equal "1 2 3", resolve("1 2 () 3")
627
- assert_equal "1 2 3", resolve("1 2 3 ()")
628
- assert_equal "1 2 3", resolve("() 1 2 3")
629
- assert_raise_message(Sass::SyntaxError, "() isn't a valid CSS value.") {resolve("()")}
630
- assert_raise_message(Sass::SyntaxError, "() isn't a valid CSS value.") {resolve("nth(append((), ()), 1)")}
631
- end
632
-
633
- def test_list_with_nulls
634
- assert_equal "1, 2, 3", resolve("1, 2, null, 3")
635
- assert_equal "1 2 3", resolve("1 2 null 3")
636
- assert_equal "1, 2, 3", resolve("1, 2, 3, null")
637
- assert_equal "1 2 3", resolve("1 2 3 null")
638
- assert_equal "1, 2, 3", resolve("null, 1, 2, 3")
639
- assert_equal "1 2 3", resolve("null 1 2 3")
640
- end
641
-
642
- def test_map_can_have_trailing_comma
643
- assert_equal("(foo: 1, bar: 2)", eval("(foo: 1, bar: 2,)").to_sass)
644
- end
645
-
646
- def test_list_can_have_trailing_comma
647
- assert_equal("1, 2, 3", resolve("1, 2, 3,"))
648
- end
649
-
650
- def test_trailing_comma_defines_singleton_list
651
- assert_equal("1 2 3", resolve("nth((1 2 3,), 1)"))
652
- end
653
-
654
- def test_map_cannot_have_duplicate_keys
655
- assert_raise_message(Sass::SyntaxError, 'Duplicate key "foo" in map (foo: bar, foo: baz).') do
656
- eval("(foo: bar, foo: baz)")
657
- end
658
- assert_raise_message(Sass::SyntaxError, 'Duplicate key "foo" in map (foo: bar, fo + o: baz).') do
659
- eval("(foo: bar, fo + o: baz)")
660
- end
661
- assert_raise_message(Sass::SyntaxError, 'Duplicate key "foo" in map (foo: bar, "foo": baz).') do
662
- eval("(foo: bar, 'foo': baz)")
663
- end
664
- assert_raise_message(Sass::SyntaxError, 'Duplicate key 2px in map (2px: bar, 1px + 1px: baz).') do
665
- eval("(2px: bar, 1px + 1px: baz)")
666
- end
667
- assert_raise_message(Sass::SyntaxError, 'Duplicate key #0000ff in map (blue: bar, #00f: baz).') do
668
- eval("(blue: bar, #00f: baz)")
669
- end
670
- end
671
-
672
- def test_non_duplicate_map_keys
673
- # These shouldn't throw errors
674
- eval("(foo: foo, bar: bar)")
675
- eval("(2px: foo, 2: bar)")
676
- eval("(2px: foo, 2em: bar)")
677
- eval("('2px': foo, 2px: bar)")
678
- end
679
-
680
- def test_map_syntax_errors
681
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "(foo:": expected expression (e.g. 1px, bold), was ")"') do
682
- eval("(foo:)")
683
- end
684
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "(": expected ")", was ":bar)"') do
685
- eval("(:bar)")
686
- end
687
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "(foo, bar": expected ")", was ": baz)"') do
688
- eval("(foo, bar: baz)")
689
- end
690
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "(foo: bar, baz": expected ":", was ")"') do
691
- eval("(foo: bar, baz)")
692
- end
693
- end
694
-
695
- def test_deep_argument_error_not_unwrapped
696
- # JRuby (as of 1.6.7.2) offers no way of distinguishing between
697
- # argument errors caused by programming errors in a function and
698
- # argument errors explicitly thrown within that function.
699
- return if RUBY_PLATFORM =~ /java/
700
-
701
- # Don't validate the message; it's different on Rubinius.
702
- assert_raises(ArgumentError) {resolve("arg-error()")}
703
- end
704
-
705
- def test_shallow_argument_error_unwrapped
706
- assert_raise_message(Sass::SyntaxError, "wrong number of arguments (1 for 0) for `arg-error'") {resolve("arg-error(1)")}
707
- end
708
-
709
- def test_boolean_ops_short_circuit
710
- assert_equal "false", resolve("$ie and $ie <= 7", {}, env('ie' => Sass::Script::Value::Bool.new(false)))
711
- assert_equal "true", resolve("$ie or $undef", {}, env('ie' => Sass::Script::Value::Bool.new(true)))
712
- end
713
-
714
- def test_selector
715
- env = Sass::Environment.new
716
- assert_equal "true", resolve("& == null", {}, env)
717
-
718
- env.selector = selector('.foo.bar .baz.bang, .bip.bop')
719
- assert_equal ".foo.bar .baz.bang, .bip.bop", resolve("&", {}, env)
720
- assert_equal ".foo.bar .baz.bang", resolve("nth(&, 1)", {}, env)
721
- assert_equal ".bip.bop", resolve("nth(&, 2)", {}, env)
722
- assert_equal ".foo.bar", resolve("nth(nth(&, 1), 1)", {}, env)
723
- assert_equal ".baz.bang", resolve("nth(nth(&, 1), 2)", {}, env)
724
- assert_equal ".bip.bop", resolve("nth(nth(&, 2), 1)", {}, env)
725
- assert_equal "string", resolve("type-of(nth(nth(&, 1), 1))", {}, env)
726
-
727
- env.selector = selector('.foo > .bar')
728
- assert_equal ".foo > .bar", resolve("&", {}, env)
729
- assert_equal ".foo > .bar", resolve("nth(&, 1)", {}, env)
730
- assert_equal ".foo", resolve("nth(nth(&, 1), 1)", {}, env)
731
- assert_equal ">", resolve("nth(nth(&, 1), 2)", {}, env)
732
- assert_equal ".bar", resolve("nth(nth(&, 1), 3)", {}, env)
733
- end
734
-
735
- def test_selector_with_newlines
736
- env = Sass::Environment.new
737
- env.selector = selector(".foo.bar\n.baz.bang,\n\n.bip.bop")
738
- assert_equal ".foo.bar .baz.bang, .bip.bop", resolve("&", {}, env)
739
- assert_equal ".foo.bar .baz.bang", resolve("nth(&, 1)", {}, env)
740
- assert_equal ".bip.bop", resolve("nth(&, 2)", {}, env)
741
- assert_equal ".foo.bar", resolve("nth(nth(&, 1), 1)", {}, env)
742
- assert_equal ".baz.bang", resolve("nth(nth(&, 1), 2)", {}, env)
743
- assert_equal ".bip.bop", resolve("nth(nth(&, 2), 1)", {}, env)
744
- assert_equal "string", resolve("type-of(nth(nth(&, 1), 1))", {}, env)
745
- end
746
-
747
- def test_setting_global_variable_globally
748
- assert_no_warning {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
749
- .foo {
750
- a: 1; }
751
-
752
- .bar {
753
- b: 2; }
754
- CSS
755
- $var: 1;
756
-
757
- .foo {
758
- a: $var;
759
- }
760
-
761
- $var: 2;
762
-
763
- .bar {
764
- b: $var;
765
- }
766
- SCSS
767
- end
768
-
769
- def test_setting_global_variable_locally
770
- assert_no_warning {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
771
- .bar {
772
- a: x;
773
- b: y;
774
- c: z; }
775
- CSS
776
- $var1: 1;
777
- $var3: 3;
778
-
779
- .foo {
780
- $var1: x !global;
781
- $var2: y !global;
782
- @each $var3 in _ {
783
- $var3: z !global;
784
- }
785
- }
786
-
787
- .bar {
788
- a: $var1;
789
- b: $var2;
790
- c: $var3;
791
- }
792
- SCSS
793
- end
794
-
795
- def test_setting_global_variable_locally_with_default
796
- assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
797
- .bar {
798
- a: 1;
799
- b: y;
800
- c: z; }
801
- CSS
802
- $var1: 1;
803
-
804
- .foo {
805
- $var1: x !global !default;
806
- $var2: y !global !default;
807
- @each $var3 in _ {
808
- $var3: z !global !default;
809
- }
810
- }
811
-
812
- .bar {
813
- a: $var1;
814
- b: $var2;
815
- c: $var3;
816
- }
817
- SCSS
818
- end
819
-
820
- def test_setting_local_variable
821
- assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
822
- .a {
823
- value: inside; }
824
-
825
- .b {
826
- value: outside; }
827
- CSS
828
- $var: outside;
829
-
830
- .a {
831
- $var: inside;
832
- value: $var;
833
- }
834
-
835
- .b {
836
- value: $var;
837
- }
838
- SCSS
839
- end
840
-
841
- def test_setting_local_variable_from_inner_scope
842
- assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
843
- .a .b {
844
- value: inside; }
845
- .a .c {
846
- value: inside; }
847
- CSS
848
- .a {
849
- $var: outside;
850
-
851
- .b {
852
- $var: inside;
853
- value: $var;
854
- }
855
-
856
- .c {
857
- value: $var;
858
- }
859
- }
860
- SCSS
861
- end
862
-
863
- def test_if_can_assign_to_global_variables
864
- assert_equal <<CSS, render(<<SCSS, :syntax => :scss)
865
- .a {
866
- b: 2; }
867
- CSS
868
- $var: 1;
869
- @if true {$var: 2}
870
- .a {b: $var}
871
- SCSS
872
- end
873
-
874
- def test_else_can_assign_to_global_variables
875
- assert_equal <<CSS, render(<<SCSS, :syntax => :scss)
876
- .a {
877
- b: 2; }
878
- CSS
879
- $var: 1;
880
- @if false {}
881
- @else {$var: 2}
882
- .a {b: $var}
883
- SCSS
884
- end
885
-
886
- def test_for_can_assign_to_global_variables
887
- assert_equal <<CSS, render(<<SCSS, :syntax => :scss)
888
- .a {
889
- b: 2; }
890
- CSS
891
- $var: 1;
892
- @for $i from 1 to 2 {$var: 2}
893
- .a {b: $var}
894
- SCSS
895
- end
896
-
897
- def test_each_can_assign_to_global_variables
898
- assert_equal <<CSS, render(<<SCSS, :syntax => :scss)
899
- .a {
900
- b: 2; }
901
- CSS
902
- $var: 1;
903
- @each $a in 1 {$var: 2}
904
- .a {b: $var}
905
- SCSS
906
- end
907
-
908
- def test_while_can_assign_to_global_variables
909
- assert_equal <<CSS, render(<<SCSS, :syntax => :scss)
910
- .a {
911
- b: 2; }
912
- CSS
913
- $var: 1;
914
- @while $var != 2 {$var: 2}
915
- .a {b: $var}
916
- SCSS
917
- end
918
-
919
- def test_if_doesnt_leak_local_variables
920
- assert_raise_message(Sass::SyntaxError, 'Undefined variable: "$var".') do
921
- render(<<SCSS, :syntax => :scss)
922
- @if true {$var: 1}
923
- .a {b: $var}
924
- SCSS
925
- end
926
- end
927
-
928
- def test_else_doesnt_leak_local_variables
929
- assert_raise_message(Sass::SyntaxError, 'Undefined variable: "$var".') do
930
- render(<<SCSS, :syntax => :scss)
931
- @if false {}
932
- @else {$var: 1}
933
- .a {b: $var}
934
- SCSS
935
- end
936
- end
937
-
938
- def test_for_doesnt_leak_local_variables
939
- assert_raise_message(Sass::SyntaxError, 'Undefined variable: "$var".') do
940
- render(<<SCSS, :syntax => :scss)
941
- @for $i from 1 to 2 {$var: 1}
942
- .a {b: $var}
943
- SCSS
944
- end
945
- end
946
-
947
- def test_each_doesnt_leak_local_variables
948
- assert_raise_message(Sass::SyntaxError, 'Undefined variable: "$var".') do
949
- render(<<SCSS, :syntax => :scss)
950
- @each $a in 1 {$var: 1}
951
- .a {b: $var}
952
- SCSS
953
- end
954
- end
955
-
956
- def test_while_doesnt_leak_local_variables
957
- assert_raise_message(Sass::SyntaxError, 'Undefined variable: "$var".') do
958
- render(<<SCSS, :syntax => :scss)
959
- $iter: true;
960
- @while $iter {
961
- $var: 1;
962
- $iter: false;
963
- }
964
- .a {b: $var}
965
- SCSS
966
- end
967
- end
968
-
969
- def test_color_format_is_preserved_by_default
970
- assert_equal "blue", resolve("blue")
971
- assert_equal "bLuE", resolve("bLuE")
972
- assert_equal "#00f", resolve("#00f")
973
- assert_equal "blue #00F", resolve("blue #00F")
974
- assert_equal "blue", resolve("nth(blue #00F, 1)")
975
- assert_equal "#00F", resolve("nth(blue #00F, 2)")
976
- end
977
-
978
- def test_color_format_isnt_always_preserved_in_compressed_style
979
- assert_equal "red", resolve("red", :style => :compressed)
980
- assert_equal "red", resolve("#f00", :style => :compressed)
981
- assert_equal "red red", resolve("red #f00", :style => :compressed)
982
- assert_equal "red", resolve("nth(red #f00, 2)", :style => :compressed)
983
- end
984
-
985
- def test_color_format_is_sometimes_preserved_in_compressed_style
986
- assert_equal "ReD", resolve("ReD", :style => :compressed)
987
- assert_equal "blue", resolve("blue", :style => :compressed)
988
- assert_equal "#00f", resolve("#00f", :style => :compressed)
989
- end
990
-
991
- def test_color_format_isnt_preserved_when_modified
992
- assert_equal "magenta", resolve("change-color(#f00, $blue: 255)")
993
- end
994
-
995
- def test_ids
996
- assert_equal "#foo", resolve("#foo")
997
- assert_equal "#abcd", resolve("#abcd")
998
- assert_equal "#abc-def", resolve("#abc-def")
999
- assert_equal "#abc_def", resolve("#abc_def")
1000
- assert_equal "#uvw-xyz", resolve("#uvw-xyz")
1001
- assert_equal "#uvw_xyz", resolve("#uvw_xyz")
1002
- assert_equal "#uvwxyz", resolve("#uvw + xyz")
1003
- end
1004
-
1005
- def test_scientific_notation
1006
- assert_equal "2000", resolve("2e3")
1007
- assert_equal "2000", resolve("2E3")
1008
- assert_equal "2000", resolve("2e+3")
1009
- assert_equal "2000em", resolve("2e3em")
1010
- assert_equal "25000000000", resolve("2.5e10")
1011
- assert_equal "0.1234", resolve("1234e-4")
1012
- assert_equal "12.34", resolve("1.234e1")
1013
- end
1014
-
1015
- def test_identifier_units
1016
- assert_equal "5-foo", resolve("2-foo + 3-foo")
1017
- assert_equal "5-foo-", resolve("2-foo- + 3-foo-")
1018
- assert_equal "5-\\u2603", resolve("2-\\u2603 + 3-\\u2603")
1019
- end
1020
-
1021
- def test_backslash_newline_in_string
1022
- assert_equal 'foobar', resolve("\"foo\\\nbar\"")
1023
- assert_equal 'foobar', resolve("'foo\\\nbar'")
1024
- end
1025
-
1026
- def test_unclosed_special_fun
1027
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(foo()": expected ")", was ""') do
1028
- resolve("calc(foo()")
1029
- end
1030
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(#{\')\'}": expected ")", was ""') do
1031
- resolve("calc(\#{')'}")
1032
- end
1033
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(#{foo": expected "}", was ""') do
1034
- resolve("calc(\#{foo")
1035
- end
1036
- end
1037
-
1038
- def test_special_fun_with_interpolation
1039
- assert_equal "calc())", resolve("calc(\#{')'})")
1040
- assert_equal "calc(# {foo})", resolve("calc(# {foo})")
1041
- end
1042
-
1043
- # Regression Tests
1044
-
1045
- def test_interpolation_after_string
1046
- assert_equal '"foobar" 2', resolve('"foobar" #{2}')
1047
- assert_equal "calc(1 + 2) 3", resolve('calc(1 + 2) #{3}')
1048
- end
1049
-
1050
- def test_repeatedly_modified_color
1051
- assert_equal(<<CSS, render(<<SASS))
1052
- a {
1053
- link-color: #161C14;
1054
- link-color-hover: black;
1055
- link-color-tap: rgba(22, 28, 20, 0.3); }
1056
- CSS
1057
- $green: #161C14
1058
- $link-color: $green
1059
- $link-color-hover: darken($link-color, 10%)
1060
- $link-color-tap: rgba($green, 0.3)
1061
-
1062
- a
1063
- link-color: $link-color
1064
- link-color-hover: $link-color-hover
1065
- link-color-tap: $link-color-tap
1066
- SASS
1067
- end
1068
-
1069
- def test_inspect_divided_numbers
1070
- assert_equal "1px/2px", resolve("inspect(1px/2px)")
1071
- assert_equal "0.5", resolve("inspect((1px/2px))")
1072
- end
1073
-
1074
- def test_minus_without_whitespace
1075
- assert_equal "5px", resolve("15px-10px")
1076
- assert_equal "5px-", resolve("15px--10px-")
1077
- end
1078
-
1079
- def test_minus_preceded_by_comment
1080
- assert_equal "15px -10px", resolve("15px/**/-10px")
1081
- end
1082
-
1083
- def test_user_defined_function_forces_division
1084
- assert_equal(<<CSS, render(<<SASS))
1085
- a {
1086
- b: 10px; }
1087
- CSS
1088
- @function foo()
1089
- @return 20px
1090
-
1091
- a
1092
- b: (foo() / 2)
1093
- SASS
1094
-
1095
- assert_equal(<<CSS, render(<<SASS))
1096
- a {
1097
- b: 10px; }
1098
- CSS
1099
- @function foo()
1100
- @return 20px
1101
-
1102
- a
1103
- b: foo() / 2
1104
- SASS
1105
- end
1106
-
1107
- def test_funcall_has_higher_precedence_than_color_name
1108
- assert_equal "teal(12)", resolve("teal(12)")
1109
- assert_equal "tealbang(12)", resolve("tealbang(12)")
1110
- assert_equal "teal-bang(12)", resolve("teal-bang(12)")
1111
- assert_equal "teal\\+bang(12)", resolve("teal\\+bang(12)")
1112
- end
1113
-
1114
- def test_funcall_has_higher_precedence_than_true_false_null
1115
- assert_equal "teal(12)", resolve("teal(12)")
1116
- assert_equal "tealbang(12)", resolve("tealbang(12)")
1117
- assert_equal "teal-bang(12)", resolve("teal-bang(12)")
1118
- assert_equal "teal\\+bang(12)", resolve("teal\\+bang(12)")
1119
- end
1120
-
1121
- def test_and_or_not_disallowed_as_function_names
1122
- %w[and or not].each do |name|
1123
- assert_raise_message(Sass::SyntaxError, "Invalid function name \"#{name}\".") do
1124
- render(<<SASS)
1125
- @function #{name}()
1126
- @return null
1127
- SASS
1128
- end
1129
- end
1130
- end
1131
-
1132
- def test_interpolation_after_hash
1133
- assert_equal "#2", resolve('"##{1 + 1}"')
1134
- end
1135
-
1136
- def test_func_call_arglist_trailing_comma
1137
- assert_equal eval('foo(bar)'), eval('foo(bar, )')
1138
- end
1139
-
1140
- def test_color_prefixed_identifier
1141
- assert_equal "tealbang", resolve("tealbang")
1142
- assert_equal "teal-bang", resolve("teal-bang")
1143
- end
1144
-
1145
- def test_op_prefixed_identifier
1146
- assert_equal "notbang", resolve("notbang")
1147
- assert_equal "not-bang", resolve("not-bang")
1148
- assert_equal "or-bang", resolve("or-bang")
1149
- assert_equal "and-bang", resolve("and-bang")
1150
- end
1151
-
1152
- def test_number_initialization
1153
- assert_equal Sass::Script::Value::Number.new(10, ["px"]), Sass::Script::Value::Number.new(10, "px")
1154
- assert_equal Sass::Script::Value::Number.new(10, ["px"], ["em"]), Sass::Script::Value::Number.new(10, "px", "em")
1155
- end
1156
-
1157
- def test_is_unit
1158
- assert Sass::Script::Value::Number.new(10, "px").is_unit?("px")
1159
- assert Sass::Script::Value::Number.new(10).is_unit?(nil)
1160
- assert !Sass::Script::Value::Number.new(10, "px", "em").is_unit?("px")
1161
- assert !Sass::Script::Value::Number.new(10, [], "em").is_unit?("em")
1162
- assert !Sass::Script::Value::Number.new(10, ["px", "em"]).is_unit?("px")
1163
- end
1164
-
1165
- def test_rename_redirect
1166
- assert_no_warning do
1167
- assert_equal Sass::Script::Value::Base, Sass::Script::Literal
1168
- assert_equal Sass::Script::Tree::Node, Sass::Script::Node
1169
- assert_equal Sass::Script::Tree::Operation, Sass::Script::Operation
1170
- assert_equal Sass::Script::Value::String, Sass::Script::String
1171
- end
1172
- end
1173
-
1174
- def test_number_printing
1175
- assert_equal "1", resolve("1")
1176
- assert_equal "1", resolve("1.0")
1177
- assert_equal "1000000000", resolve("1000000000")
1178
- assert_equal "0.00001", resolve("0.00001")
1179
- assert_equal "1.1212121212", resolve("1.12121212124")
1180
- assert_equal "1.1212121213", resolve("1.12121212125")
1181
- assert_equal "Infinity", resolve("(1.0/0.0)")
1182
- assert_equal "-Infinity", resolve("(-1.0/0.0)")
1183
- assert_equal "NaN", resolve("(0.0/0.0)")
1184
- end
1185
-
1186
- def test_equality_uses_an_epsilon
1187
- # At least on my machine, this calculation introduces a floating point error:
1188
- # 29.0 / 7 * 7
1189
- # => 29.000000000000004
1190
- assert_equal "true", resolve("29 == (29 / 7 * 7)")
1191
- end
1192
-
1193
- def test_compressed_output_of_numbers_with_leading_zeros
1194
- assert_equal "1.5", resolve("1.5", :style => :compressed)
1195
- assert_equal ".5", resolve("0.5", :style => :compressed)
1196
- assert_equal "-.5", resolve("-0.5", :style => :compressed)
1197
- assert_equal "0.5", resolve("0.5", :style => :compact)
1198
- end
1199
-
1200
- def test_interpolation_without_deprecation_warning
1201
- assert_no_warning {assert_equal "a", resolve('#{a}')}
1202
- assert_no_warning {assert_equal "abc", resolve('a#{b}c')}
1203
- assert_no_warning {assert_equal "+ a", resolve('+ #{a}')}
1204
- assert_no_warning {assert_equal "/ a", resolve('/ #{a}')}
1205
- assert_no_warning {assert_equal "1 / a", resolve('1 / #{a}')}
1206
- assert_no_warning {assert_equal "a / b", resolve('#{a} / #{b}')}
1207
- assert_no_warning {assert_equal "foo(1 = a)", resolve('foo(1 = #{a})')}
1208
- assert_no_warning {assert_equal "foo(a = b)", resolve('foo(#{a} = #{b})')}
1209
- assert_no_warning {assert_equal "-a", resolve('-#{a}')}
1210
- assert_no_warning {assert_equal "1-a", resolve('1-#{a}')}
1211
- assert_no_warning {assert_equal "a- 1", resolve('#{a}- 1')}
1212
- assert_no_warning {assert_equal "a-1", resolve('#{a}-1')}
1213
- assert_no_warning {assert_equal "a-b", resolve('#{a}-#{b}')}
1214
- assert_no_warning {assert_equal "a1", resolve('#{a}1')}
1215
- assert_no_warning {assert_equal "ab", resolve('#{a}b')}
1216
- assert_no_warning {assert_equal "1a", resolve('1#{a}')}
1217
- assert_no_warning {assert_equal "ba", resolve('b#{a}')}
1218
- end
1219
-
1220
- def test_leading_interpolation_with_deprecation_warning
1221
- assert_equal "ab == 1", resolve_with_interp_warning('#{a + b} == 1')
1222
- assert_equal "ab != 1", resolve_with_interp_warning('#{a + b} != 1')
1223
- assert_equal "ab > 1", resolve_with_interp_warning('#{a + b} > 1')
1224
- assert_equal "ab >= 1", resolve_with_interp_warning('#{a + b} >= 1')
1225
- assert_equal "ab < 1", resolve_with_interp_warning('#{a + b} < 1')
1226
- assert_equal "ab <= 1", resolve_with_interp_warning('#{a + b} <= 1')
1227
- assert_equal "ab + 1", resolve_with_interp_warning('#{a + b} + 1')
1228
- assert_equal "ab * 1", resolve_with_interp_warning('#{a + b} * 1')
1229
- assert_equal "ab - 1", resolve_with_interp_warning('#{a + b} - 1')
1230
- assert_equal "ab % 1", resolve_with_interp_warning('#{a + b} % 1')
1231
- assert_equal(
1232
- "abvar",
1233
- resolve_with_interp_warning(
1234
- '#{a + b}$var', '"#{a + b}#{$var}"',
1235
- env('var' => Sass::Script::Value::String.new("var"))))
1236
- assert_equal(
1237
- "varab",
1238
- resolve_with_interp_warning(
1239
- '$var#{a + b}', '"#{$var}#{a + b}"',
1240
- env('var' => Sass::Script::Value::String.new("var"))))
1241
- assert_equal "ab1", resolve_with_interp_warning('#{a + b}(1)', '"#{a + b}1"')
1242
- assert_equal "1ab", resolve_with_interp_warning('(1)#{a + b}', '"1#{a + b}"')
1243
- end
1244
-
1245
- def test_trailing_interpolation_with_deprecation_warning
1246
- assert_equal "not ab", resolve_with_interp_warning('not #{a + b}')
1247
- assert_equal "1 and ab", resolve_with_interp_warning('1 and #{a + b}')
1248
- assert_equal "1 or ab", resolve_with_interp_warning('1 or #{a + b}')
1249
- assert_equal "1 == ab", resolve_with_interp_warning('1 == #{a + b}')
1250
- assert_equal "1 != ab", resolve_with_interp_warning('1 != #{a + b}')
1251
- assert_equal "1 > ab", resolve_with_interp_warning('1 > #{a + b}')
1252
- assert_equal "1 >= ab", resolve_with_interp_warning('1 >= #{a + b}')
1253
- assert_equal "1 < ab", resolve_with_interp_warning('1 < #{a + b}')
1254
- assert_equal "1 <= ab", resolve_with_interp_warning('1 <= #{a + b}')
1255
- assert_equal "1 + ab", resolve_with_interp_warning('1 + #{a + b}')
1256
- assert_equal "1 * ab", resolve_with_interp_warning('1 * #{a + b}')
1257
- assert_equal "1 - ab", resolve_with_interp_warning('1 - #{a + b}')
1258
- assert_equal "1 % ab", resolve_with_interp_warning('1 % #{a + b}')
1259
- assert_equal "- ab", resolve_with_interp_warning('- #{a + b}')
1260
- assert_equal "1- ab", resolve_with_interp_warning('1- #{a + b}')
1261
- assert_equal "- ab 2 3", resolve_with_interp_warning('- #{a + b} 2 3', '"- #{a + b} #{2 3}"')
1262
- end
1263
-
1264
- def test_brackteing_interpolation_with_deprecation_warning
1265
- assert_equal "ab == cd", resolve_with_interp_warning('#{a + b} == #{c + d}')
1266
- assert_equal "ab != cd", resolve_with_interp_warning('#{a + b} != #{c + d}')
1267
- assert_equal "ab > cd", resolve_with_interp_warning('#{a + b} > #{c + d}')
1268
- assert_equal "ab >= cd", resolve_with_interp_warning('#{a + b} >= #{c + d}')
1269
- assert_equal "ab < cd", resolve_with_interp_warning('#{a + b} < #{c + d}')
1270
- assert_equal "ab <= cd", resolve_with_interp_warning('#{a + b} <= #{c + d}')
1271
- assert_equal "ab + cd", resolve_with_interp_warning('#{a + b} + #{c + d}')
1272
- assert_equal "ab * cd", resolve_with_interp_warning('#{a + b} * #{c + d}')
1273
- assert_equal "ab - cd", resolve_with_interp_warning('#{a + b} - #{c + d}')
1274
- assert_equal "ab % cd", resolve_with_interp_warning('#{a + b} % #{c + d}')
1275
- end
1276
-
1277
- def test_interp_warning_formatting
1278
- resolve_with_interp_warning('#{1} + 1', '"1 + 1"')
1279
- resolve_with_interp_warning('#{1} + "foo"', '\'1 + "foo"\'')
1280
- resolve_with_interp_warning('#{1} + \'foo\'', '\'1 + "foo"\'')
1281
-
1282
- resolve_with_interp_warning('#{1} + "#{a + b}"', '\'1 + "#{a + b}"\'')
1283
- resolve_with_interp_warning('"#{a + b}" + #{1}', '\'"#{a + b}" + 1\'')
1284
- resolve_with_interp_warning('"#{a + b}" + #{1} + "#{c + d}"', '\'"#{a + b}" + 1 + "#{c + d}"\'')
1285
-
1286
- resolve_with_interp_warning('#{1} + "\'"', '"1 + \\"\'\\""')
1287
- resolve_with_interp_warning('#{1} + \'"\'', '"1 + \'\\"\'"')
1288
- resolve_with_interp_warning('#{1} + "\'\\""', '"1 + \\"\'\\\\\\"\\""')
1289
- end
1290
-
1291
- def test_inactive_lazy_interpolation_deprecation_warning
1292
- assert_equal '1, 2, 3', assert_no_warning {resolve('1, #{2}, 3')}
1293
- assert_equal '1, 2, 3', assert_no_warning {resolve('1, 2, #{3}')}
1294
- assert_equal '1,2,3', assert_no_warning {resolve('1,#{2},3')}
1295
- assert_equal '1 2 3', assert_no_warning {resolve('#{1} 2 3')}
1296
- assert_equal '1 2 3', assert_no_warning {resolve('1 #{2} 3')}
1297
- assert_equal '1 2 3', assert_no_warning {resolve('1 2 #{3}')}
1298
-
1299
- assert_equal '+1 2 3', assert_no_warning {resolve('+#{1} 2 3')}
1300
- assert_equal '-1 2 3', assert_no_warning {resolve('-#{1} 2 3')}
1301
- assert_equal '/1 2 3', assert_no_warning {resolve('/#{1} 2 3')}
1302
-
1303
- assert_equal '1, 2, 31', assert_no_warning {resolve('(1, #{2}, 3) + 1')}
1304
- assert_equal '11, 2, 3', assert_no_warning {resolve('1 + (1, #{2}, 3)')}
1305
-
1306
- assert_equal 'a, b, c', assert_no_warning {resolve('selector-parse((a, #{b}, c))')}
1307
- end
1308
-
1309
- def test_active_lazy_interpolation_deprecation_warning
1310
- Sass::Deprecation.allow_double_warnings do
1311
- assert_equal "1, 2, 3", resolve_with_lazy_interp_warning('quote((1, #{2}, 3))', '"1, 2, 3"')
1312
- assert_equal "1", resolve_with_lazy_interp_warning('length((1, #{2}, 3))', '"1, 2, 3"')
1313
- assert_equal "1, 2, 3", resolve_with_lazy_interp_warning('inspect((1, #{2}, 3))', '"1, 2, 3"')
1314
- assert_equal "string", resolve_with_lazy_interp_warning('type-of((1, #{2}, 3))', '"1, 2, 3"')
1315
-
1316
- assert_equal "+1 2 3", resolve_with_lazy_interp_warning('quote((+#{1} 2 3))', '"+1 #{2 3}"')
1317
- assert_equal "/1 2 3", resolve_with_lazy_interp_warning('quote((/#{1} 2 3))', '"/1 #{2 3}"')
1318
- assert_equal "-1 2 3", resolve_with_lazy_interp_warning('quote((-#{1} 2 3))', '"-1 #{2 3}"')
1319
- end
1320
- end
1321
-
1322
- def test_comparison_of_complex_units
1323
- # Tests for issue #1960
1324
- Sass::Deprecation.allow_double_warnings do
1325
- assert_warning(<<WARNING) do
1326
- DEPRECATION WARNING on line 1 of test_comparison_of_complex_units_inline.sass:
1327
- The result of `10 == 10px` will be `false` in future releases of Sass.
1328
- Unitless numbers will no longer be equal to the same numbers with units.
1329
- WARNING
1330
- assert_equal "true", resolve("10 == 2 * 5px")
1331
- end
1332
- assert_warning(<<WARNING) do
1333
- DEPRECATION WARNING on line 1 of test_comparison_of_complex_units_inline.sass:
1334
- The result of `10 == 10px*px` will be `false` in future releases of Sass.
1335
- Unitless numbers will no longer be equal to the same numbers with units.
1336
- WARNING
1337
- assert_equal "true", resolve("10 == 2px * 5px")
1338
- end
1339
- end
1340
-
1341
- assert_equal "true", resolve("10px * 1px == 2px * 5px")
1342
- assert_equal "true", resolve("5px * 1px < 2px * 5px")
1343
- end
1344
-
1345
- private
1346
-
1347
- def resolve_with_lazy_interp_warning(str, contents = nil, environment = env)
1348
- contents ||= "\"#{str}\""
1349
- result = assert_warning(<<WARNING) {resolve(str, {}, environment)}
1350
- DEPRECATION WARNING on line 1 of #{filename_for_test}:
1351
- \#{} interpolation near operators will be simplified in a future version of Sass.
1352
- To preserve the current behavior, use quotes:
1353
-
1354
- unquote(#{contents})
1355
- WARNING
1356
- $_sass_deprecated_interp_warnings = nil
1357
- result
1358
- end
1359
-
1360
- def resolve_with_interp_warning(str, contents = nil, environment = env)
1361
- contents ||= "\"#{str}\""
1362
- assert_warning(<<WARNING) {resolve(str, {}, environment)}
1363
- DEPRECATION WARNING on line 1 of #{filename_for_test}:
1364
- \#{} interpolation near operators will be simplified in a future version of Sass.
1365
- To preserve the current behavior, use quotes:
1366
-
1367
- unquote(#{contents})
1368
-
1369
- You can use the sass-convert command to automatically fix most cases.
1370
- WARNING
1371
- end
1372
-
1373
- def resolve(str, opts = {}, environment = env)
1374
- munge_filename opts
1375
- val = eval(str, opts, environment)
1376
- assert_kind_of Sass::Script::Value::Base, val
1377
- val.options = opts
1378
- val.is_a?(Sass::Script::Value::String) ? val.value : val.to_s
1379
- end
1380
-
1381
- def resolve_quoted(str, opts = {}, environment = env)
1382
- munge_filename opts
1383
- val = eval(str, opts, environment)
1384
- assert_kind_of Sass::Script::Value::Base, val
1385
- val.to_s
1386
- end
1387
-
1388
- def assert_unquoted(str, opts = {}, environment = env)
1389
- munge_filename opts
1390
- val = eval(str, opts, environment)
1391
- assert_kind_of Sass::Script::Value::String, val
1392
- assert_equal :identifier, val.type
1393
- end
1394
-
1395
- def assert_quoted(str, opts = {}, environment = env)
1396
- munge_filename opts
1397
- val = eval(str, opts, environment)
1398
- assert_kind_of Sass::Script::Value::String, val
1399
- assert_equal :string, val.type
1400
- end
1401
-
1402
- def eval(str, opts = {}, environment = env)
1403
- munge_filename opts
1404
- Sass::Script.parse(str, opts.delete(:line) || 1,
1405
- opts.delete(:offset) || 0, opts).
1406
- perform(Sass::Environment.new(environment, opts))
1407
- end
1408
-
1409
- def render(sass, options = {})
1410
- munge_filename options
1411
- Sass::Engine.new(sass, options).render
1412
- end
1413
-
1414
- def env(hash = {})
1415
- env = Sass::Environment.new
1416
- hash.each {|k, v| env.set_var(k, v)}
1417
- env
1418
- end
1419
-
1420
- def selector(str)
1421
- parser = Sass::SCSS::StaticParser.new(
1422
- str, filename_for_test, Sass::Importers::Filesystem.new('.'))
1423
- parser.parse_selector
1424
- end
1425
-
1426
- def test_null_is_a_singleton
1427
- assert_same Sass::Script::Value::Null.new, Sass::Script::Value::Null.new
1428
- end
1429
- end