xass 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (242) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +11 -0
  3. data/CONTRIBUTING +3 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +201 -0
  6. data/Rakefile +349 -0
  7. data/VERSION +1 -0
  8. data/VERSION_NAME +1 -0
  9. data/bin/push +13 -0
  10. data/bin/sass +13 -0
  11. data/bin/sass-convert +12 -0
  12. data/bin/scss +13 -0
  13. data/extra/update_watch.rb +13 -0
  14. data/init.rb +18 -0
  15. data/lib/sass/cache_stores/base.rb +88 -0
  16. data/lib/sass/cache_stores/chain.rb +33 -0
  17. data/lib/sass/cache_stores/filesystem.rb +64 -0
  18. data/lib/sass/cache_stores/memory.rb +47 -0
  19. data/lib/sass/cache_stores/null.rb +25 -0
  20. data/lib/sass/cache_stores.rb +15 -0
  21. data/lib/sass/callbacks.rb +66 -0
  22. data/lib/sass/css.rb +409 -0
  23. data/lib/sass/engine.rb +930 -0
  24. data/lib/sass/environment.rb +101 -0
  25. data/lib/sass/error.rb +201 -0
  26. data/lib/sass/exec.rb +707 -0
  27. data/lib/sass/importers/base.rb +139 -0
  28. data/lib/sass/importers/filesystem.rb +186 -0
  29. data/lib/sass/importers.rb +22 -0
  30. data/lib/sass/logger/base.rb +32 -0
  31. data/lib/sass/logger/log_level.rb +49 -0
  32. data/lib/sass/logger.rb +15 -0
  33. data/lib/sass/media.rb +213 -0
  34. data/lib/sass/plugin/compiler.rb +406 -0
  35. data/lib/sass/plugin/configuration.rb +123 -0
  36. data/lib/sass/plugin/generic.rb +15 -0
  37. data/lib/sass/plugin/merb.rb +48 -0
  38. data/lib/sass/plugin/rack.rb +60 -0
  39. data/lib/sass/plugin/rails.rb +47 -0
  40. data/lib/sass/plugin/staleness_checker.rb +199 -0
  41. data/lib/sass/plugin.rb +133 -0
  42. data/lib/sass/railtie.rb +10 -0
  43. data/lib/sass/repl.rb +57 -0
  44. data/lib/sass/root.rb +7 -0
  45. data/lib/sass/script/arg_list.rb +52 -0
  46. data/lib/sass/script/bool.rb +18 -0
  47. data/lib/sass/script/color.rb +606 -0
  48. data/lib/sass/script/css_lexer.rb +29 -0
  49. data/lib/sass/script/css_parser.rb +31 -0
  50. data/lib/sass/script/funcall.rb +245 -0
  51. data/lib/sass/script/functions.rb +1543 -0
  52. data/lib/sass/script/interpolation.rb +79 -0
  53. data/lib/sass/script/lexer.rb +345 -0
  54. data/lib/sass/script/list.rb +85 -0
  55. data/lib/sass/script/literal.rb +221 -0
  56. data/lib/sass/script/node.rb +99 -0
  57. data/lib/sass/script/null.rb +37 -0
  58. data/lib/sass/script/number.rb +453 -0
  59. data/lib/sass/script/operation.rb +110 -0
  60. data/lib/sass/script/parser.rb +502 -0
  61. data/lib/sass/script/string.rb +51 -0
  62. data/lib/sass/script/string_interpolation.rb +103 -0
  63. data/lib/sass/script/unary_operation.rb +69 -0
  64. data/lib/sass/script/variable.rb +58 -0
  65. data/lib/sass/script.rb +39 -0
  66. data/lib/sass/scss/css_parser.rb +36 -0
  67. data/lib/sass/scss/parser.rb +1180 -0
  68. data/lib/sass/scss/rx.rb +133 -0
  69. data/lib/sass/scss/script_lexer.rb +15 -0
  70. data/lib/sass/scss/script_parser.rb +25 -0
  71. data/lib/sass/scss/static_parser.rb +54 -0
  72. data/lib/sass/scss.rb +16 -0
  73. data/lib/sass/selector/abstract_sequence.rb +94 -0
  74. data/lib/sass/selector/comma_sequence.rb +92 -0
  75. data/lib/sass/selector/sequence.rb +507 -0
  76. data/lib/sass/selector/simple.rb +119 -0
  77. data/lib/sass/selector/simple_sequence.rb +215 -0
  78. data/lib/sass/selector.rb +452 -0
  79. data/lib/sass/shared.rb +76 -0
  80. data/lib/sass/supports.rb +229 -0
  81. data/lib/sass/tree/charset_node.rb +22 -0
  82. data/lib/sass/tree/comment_node.rb +82 -0
  83. data/lib/sass/tree/content_node.rb +9 -0
  84. data/lib/sass/tree/css_import_node.rb +60 -0
  85. data/lib/sass/tree/debug_node.rb +18 -0
  86. data/lib/sass/tree/directive_node.rb +42 -0
  87. data/lib/sass/tree/each_node.rb +24 -0
  88. data/lib/sass/tree/extend_node.rb +36 -0
  89. data/lib/sass/tree/for_node.rb +36 -0
  90. data/lib/sass/tree/function_node.rb +34 -0
  91. data/lib/sass/tree/if_node.rb +52 -0
  92. data/lib/sass/tree/import_node.rb +75 -0
  93. data/lib/sass/tree/media_node.rb +58 -0
  94. data/lib/sass/tree/mixin_def_node.rb +38 -0
  95. data/lib/sass/tree/mixin_node.rb +39 -0
  96. data/lib/sass/tree/node.rb +196 -0
  97. data/lib/sass/tree/prop_node.rb +152 -0
  98. data/lib/sass/tree/return_node.rb +18 -0
  99. data/lib/sass/tree/root_node.rb +78 -0
  100. data/lib/sass/tree/rule_node.rb +132 -0
  101. data/lib/sass/tree/supports_node.rb +51 -0
  102. data/lib/sass/tree/trace_node.rb +32 -0
  103. data/lib/sass/tree/variable_node.rb +30 -0
  104. data/lib/sass/tree/visitors/base.rb +75 -0
  105. data/lib/sass/tree/visitors/check_nesting.rb +147 -0
  106. data/lib/sass/tree/visitors/convert.rb +316 -0
  107. data/lib/sass/tree/visitors/cssize.rb +241 -0
  108. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  109. data/lib/sass/tree/visitors/extend.rb +68 -0
  110. data/lib/sass/tree/visitors/perform.rb +446 -0
  111. data/lib/sass/tree/visitors/set_options.rb +125 -0
  112. data/lib/sass/tree/visitors/to_css.rb +228 -0
  113. data/lib/sass/tree/warn_node.rb +18 -0
  114. data/lib/sass/tree/while_node.rb +18 -0
  115. data/lib/sass/util/multibyte_string_scanner.rb +155 -0
  116. data/lib/sass/util/subset_map.rb +109 -0
  117. data/lib/sass/util/test.rb +10 -0
  118. data/lib/sass/util.rb +948 -0
  119. data/lib/sass/version.rb +126 -0
  120. data/lib/sass.rb +95 -0
  121. data/rails/init.rb +1 -0
  122. data/test/Gemfile +3 -0
  123. data/test/Gemfile.lock +10 -0
  124. data/test/sass/cache_test.rb +89 -0
  125. data/test/sass/callbacks_test.rb +61 -0
  126. data/test/sass/conversion_test.rb +1760 -0
  127. data/test/sass/css2sass_test.rb +458 -0
  128. data/test/sass/data/hsl-rgb.txt +319 -0
  129. data/test/sass/engine_test.rb +3244 -0
  130. data/test/sass/exec_test.rb +86 -0
  131. data/test/sass/extend_test.rb +1482 -0
  132. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  133. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  134. data/test/sass/functions_test.rb +1139 -0
  135. data/test/sass/importer_test.rb +192 -0
  136. data/test/sass/logger_test.rb +58 -0
  137. data/test/sass/mock_importer.rb +49 -0
  138. data/test/sass/more_results/more1.css +9 -0
  139. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  140. data/test/sass/more_results/more_import.css +29 -0
  141. data/test/sass/more_templates/_more_partial.sass +2 -0
  142. data/test/sass/more_templates/more1.sass +23 -0
  143. data/test/sass/more_templates/more_import.sass +11 -0
  144. data/test/sass/plugin_test.rb +564 -0
  145. data/test/sass/results/alt.css +4 -0
  146. data/test/sass/results/basic.css +9 -0
  147. data/test/sass/results/cached_import_option.css +3 -0
  148. data/test/sass/results/compact.css +5 -0
  149. data/test/sass/results/complex.css +86 -0
  150. data/test/sass/results/compressed.css +1 -0
  151. data/test/sass/results/expanded.css +19 -0
  152. data/test/sass/results/filename_fn.css +3 -0
  153. data/test/sass/results/if.css +3 -0
  154. data/test/sass/results/import.css +31 -0
  155. data/test/sass/results/import_charset.css +5 -0
  156. data/test/sass/results/import_charset_1_8.css +5 -0
  157. data/test/sass/results/import_charset_ibm866.css +5 -0
  158. data/test/sass/results/import_content.css +1 -0
  159. data/test/sass/results/line_numbers.css +49 -0
  160. data/test/sass/results/mixins.css +95 -0
  161. data/test/sass/results/multiline.css +24 -0
  162. data/test/sass/results/nested.css +22 -0
  163. data/test/sass/results/options.css +1 -0
  164. data/test/sass/results/parent_ref.css +13 -0
  165. data/test/sass/results/script.css +16 -0
  166. data/test/sass/results/scss_import.css +31 -0
  167. data/test/sass/results/scss_importee.css +2 -0
  168. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  169. data/test/sass/results/subdir/subdir.css +3 -0
  170. data/test/sass/results/units.css +11 -0
  171. data/test/sass/results/warn.css +0 -0
  172. data/test/sass/results/warn_imported.css +0 -0
  173. data/test/sass/script_conversion_test.rb +299 -0
  174. data/test/sass/script_test.rb +622 -0
  175. data/test/sass/scss/css_test.rb +1100 -0
  176. data/test/sass/scss/rx_test.rb +156 -0
  177. data/test/sass/scss/scss_test.rb +2106 -0
  178. data/test/sass/scss/test_helper.rb +37 -0
  179. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  180. data/test/sass/templates/_double_import_loop2.sass +1 -0
  181. data/test/sass/templates/_filename_fn_import.scss +11 -0
  182. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  183. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  184. data/test/sass/templates/_imported_content.sass +3 -0
  185. data/test/sass/templates/_partial.sass +2 -0
  186. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  187. data/test/sass/templates/alt.sass +16 -0
  188. data/test/sass/templates/basic.sass +23 -0
  189. data/test/sass/templates/bork1.sass +2 -0
  190. data/test/sass/templates/bork2.sass +2 -0
  191. data/test/sass/templates/bork3.sass +2 -0
  192. data/test/sass/templates/bork4.sass +2 -0
  193. data/test/sass/templates/bork5.sass +3 -0
  194. data/test/sass/templates/cached_import_option.scss +3 -0
  195. data/test/sass/templates/compact.sass +17 -0
  196. data/test/sass/templates/complex.sass +305 -0
  197. data/test/sass/templates/compressed.sass +15 -0
  198. data/test/sass/templates/double_import_loop1.sass +1 -0
  199. data/test/sass/templates/expanded.sass +17 -0
  200. data/test/sass/templates/filename_fn.scss +18 -0
  201. data/test/sass/templates/if.sass +11 -0
  202. data/test/sass/templates/import.sass +12 -0
  203. data/test/sass/templates/import_charset.sass +9 -0
  204. data/test/sass/templates/import_charset_1_8.sass +6 -0
  205. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  206. data/test/sass/templates/import_content.sass +4 -0
  207. data/test/sass/templates/importee.less +2 -0
  208. data/test/sass/templates/importee.sass +19 -0
  209. data/test/sass/templates/line_numbers.sass +13 -0
  210. data/test/sass/templates/mixin_bork.sass +5 -0
  211. data/test/sass/templates/mixins.sass +76 -0
  212. data/test/sass/templates/multiline.sass +20 -0
  213. data/test/sass/templates/nested.sass +25 -0
  214. data/test/sass/templates/nested_bork1.sass +2 -0
  215. data/test/sass/templates/nested_bork2.sass +2 -0
  216. data/test/sass/templates/nested_bork3.sass +2 -0
  217. data/test/sass/templates/nested_bork4.sass +2 -0
  218. data/test/sass/templates/nested_import.sass +2 -0
  219. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  220. data/test/sass/templates/options.sass +2 -0
  221. data/test/sass/templates/parent_ref.sass +25 -0
  222. data/test/sass/templates/same_name_different_ext.sass +2 -0
  223. data/test/sass/templates/same_name_different_ext.scss +1 -0
  224. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  225. data/test/sass/templates/script.sass +101 -0
  226. data/test/sass/templates/scss_import.scss +11 -0
  227. data/test/sass/templates/scss_importee.scss +1 -0
  228. data/test/sass/templates/single_import_loop.sass +1 -0
  229. data/test/sass/templates/subdir/import_up1.scss +1 -0
  230. data/test/sass/templates/subdir/import_up2.scss +1 -0
  231. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  232. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  233. data/test/sass/templates/subdir/subdir.sass +6 -0
  234. data/test/sass/templates/units.sass +11 -0
  235. data/test/sass/templates/warn.sass +3 -0
  236. data/test/sass/templates/warn_imported.sass +4 -0
  237. data/test/sass/test_helper.rb +8 -0
  238. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  239. data/test/sass/util/subset_map_test.rb +91 -0
  240. data/test/sass/util_test.rb +382 -0
  241. data/test/test_helper.rb +80 -0
  242. metadata +354 -0
@@ -0,0 +1,2106 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require File.dirname(__FILE__) + '/test_helper'
4
+
5
+ class ScssTest < Test::Unit::TestCase
6
+ include ScssTestHelper
7
+
8
+ ## One-Line Comments
9
+
10
+ def test_one_line_comments
11
+ assert_equal <<CSS, render(<<SCSS)
12
+ .foo {
13
+ baz: bang; }
14
+ CSS
15
+ .foo {// bar: baz;}
16
+ baz: bang; //}
17
+ }
18
+ SCSS
19
+ assert_equal <<CSS, render(<<SCSS)
20
+ .foo bar[val="//"] {
21
+ baz: bang; }
22
+ CSS
23
+ .foo bar[val="//"] {
24
+ baz: bang; //}
25
+ }
26
+ SCSS
27
+ end
28
+
29
+ ## Script
30
+
31
+ def test_variables
32
+ assert_equal <<CSS, render(<<SCSS)
33
+ blat {
34
+ a: foo; }
35
+ CSS
36
+ $var: foo;
37
+
38
+ blat {a: $var}
39
+ SCSS
40
+
41
+ assert_equal <<CSS, render(<<SCSS)
42
+ foo {
43
+ a: 2;
44
+ b: 6; }
45
+ CSS
46
+ foo {
47
+ $var: 2;
48
+ $another-var: 4;
49
+ a: $var;
50
+ b: $var + $another-var;}
51
+ SCSS
52
+ end
53
+
54
+ def test_unicode_variables
55
+ assert_equal <<CSS, render(<<SCSS)
56
+ blat {
57
+ a: foo; }
58
+ CSS
59
+ $vär: foo;
60
+
61
+ blat {a: $vär}
62
+ SCSS
63
+ end
64
+
65
+ def test_guard_assign
66
+ assert_equal <<CSS, render(<<SCSS)
67
+ foo {
68
+ a: 1; }
69
+ CSS
70
+ $var: 1;
71
+ $var: 2 !default;
72
+
73
+ foo {a: $var}
74
+ SCSS
75
+
76
+ assert_equal <<CSS, render(<<SCSS)
77
+ foo {
78
+ a: 2; }
79
+ CSS
80
+ $var: 2 !default;
81
+
82
+ foo {a: $var}
83
+ SCSS
84
+ end
85
+
86
+ def test_sass_script
87
+ assert_equal <<CSS, render(<<SCSS)
88
+ foo {
89
+ a: 3;
90
+ b: -1;
91
+ c: foobar;
92
+ d: 12px; }
93
+ CSS
94
+ foo {
95
+ a: 1 + 2;
96
+ b: 1 - 2;
97
+ c: foo + bar;
98
+ d: floor(12.3px); }
99
+ SCSS
100
+ end
101
+
102
+ def test_debug_directive
103
+ assert_warning "test_debug_directive_inline.scss:2 DEBUG: hello world!" do
104
+ assert_equal <<CSS, render(<<SCSS)
105
+ foo {
106
+ a: b; }
107
+
108
+ bar {
109
+ c: d; }
110
+ CSS
111
+ foo {a: b}
112
+ @debug "hello world!";
113
+ bar {c: d}
114
+ SCSS
115
+ end
116
+ end
117
+
118
+ def test_warn_directive
119
+ expected_warning = <<EXPECTATION
120
+ WARNING: this is a warning
121
+ on line 2 of test_warn_directive_inline.scss
122
+
123
+ WARNING: this is a mixin
124
+ on line 1 of test_warn_directive_inline.scss, in `foo'
125
+ from line 3 of test_warn_directive_inline.scss
126
+ EXPECTATION
127
+ assert_warning expected_warning do
128
+ assert_equal <<CSS, render(<<SCSS)
129
+ bar {
130
+ c: d; }
131
+ CSS
132
+ @mixin foo { @warn "this is a mixin";}
133
+ @warn "this is a warning";
134
+ bar {c: d; @include foo;}
135
+ SCSS
136
+ end
137
+ end
138
+
139
+ def test_for_directive
140
+ assert_equal <<CSS, render(<<SCSS)
141
+ .foo {
142
+ a: 1;
143
+ a: 2;
144
+ a: 3;
145
+ a: 4; }
146
+ CSS
147
+ .foo {
148
+ @for $var from 1 to 5 {a: $var;}
149
+ }
150
+ SCSS
151
+
152
+ assert_equal <<CSS, render(<<SCSS)
153
+ .foo {
154
+ a: 1;
155
+ a: 2;
156
+ a: 3;
157
+ a: 4;
158
+ a: 5; }
159
+ CSS
160
+ .foo {
161
+ @for $var from 1 through 5 {a: $var;}
162
+ }
163
+ SCSS
164
+ end
165
+
166
+ def test_if_directive
167
+ assert_equal <<CSS, render(<<SCSS)
168
+ foo {
169
+ a: b; }
170
+ CSS
171
+ @if "foo" == "foo" {foo {a: b}}
172
+ @if "foo" != "foo" {bar {a: b}}
173
+ SCSS
174
+
175
+ assert_equal <<CSS, render(<<SCSS)
176
+ bar {
177
+ a: b; }
178
+ CSS
179
+ @if "foo" != "foo" {foo {a: b}}
180
+ @else if "foo" == "foo" {bar {a: b}}
181
+ @else if true {baz {a: b}}
182
+ SCSS
183
+
184
+ assert_equal <<CSS, render(<<SCSS)
185
+ bar {
186
+ a: b; }
187
+ CSS
188
+ @if "foo" != "foo" {foo {a: b}}
189
+ @else {bar {a: b}}
190
+ SCSS
191
+ end
192
+
193
+ def test_comment_after_if_directive
194
+ assert_equal <<CSS, render(<<SCSS)
195
+ foo {
196
+ a: b;
197
+ /* This is a comment */
198
+ c: d; }
199
+ CSS
200
+ foo {
201
+ @if true {a: b}
202
+ /* This is a comment */
203
+ c: d }
204
+ SCSS
205
+ assert_equal <<CSS, render(<<SCSS)
206
+ foo {
207
+ a: b;
208
+ /* This is a comment */
209
+ c: d; }
210
+ CSS
211
+ foo {
212
+ @if true {a: b}
213
+ @else {x: y}
214
+ /* This is a comment */
215
+ c: d }
216
+ SCSS
217
+ end
218
+
219
+ def test_while_directive
220
+ assert_equal <<CSS, render(<<SCSS)
221
+ .foo {
222
+ a: 1;
223
+ a: 2;
224
+ a: 3;
225
+ a: 4; }
226
+ CSS
227
+ $i: 1;
228
+
229
+ .foo {
230
+ @while $i != 5 {
231
+ a: $i;
232
+ $i: $i + 1;
233
+ }
234
+ }
235
+ SCSS
236
+ end
237
+
238
+ def test_each_directive
239
+ assert_equal <<CSS, render(<<SCSS)
240
+ a {
241
+ b: 1px;
242
+ b: 2px;
243
+ b: 3px;
244
+ b: 4px; }
245
+
246
+ c {
247
+ d: foo;
248
+ d: bar;
249
+ d: baz;
250
+ d: bang; }
251
+ CSS
252
+ a {
253
+ @each $number in 1px 2px 3px 4px {
254
+ b: $number;
255
+ }
256
+ }
257
+ c {
258
+ @each $str in foo, bar, baz, bang {
259
+ d: $str;
260
+ }
261
+ }
262
+ SCSS
263
+ end
264
+
265
+ def test_css_import_directive
266
+ assert_equal "@import url(foo.css);\n", render('@import "foo.css";')
267
+ assert_equal "@import url(foo.css);\n", render("@import 'foo.css';")
268
+ assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
269
+ assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
270
+ assert_equal "@import url(foo.css);\n", render('@import url(foo.css);')
271
+ end
272
+
273
+ def test_css_string_import_directive_with_media
274
+ assert_parses '@import "foo.css" screen;'
275
+ assert_parses '@import "foo.css" screen, print;'
276
+ assert_parses '@import "foo.css" screen, print and (foo: 0);'
277
+ assert_parses '@import "foo.css" screen, only print, screen and (foo: 0);'
278
+ end
279
+
280
+ def test_css_url_import_directive_with_media
281
+ assert_parses '@import url("foo.css") screen;'
282
+ assert_parses '@import url("foo.css") screen, print;'
283
+ assert_parses '@import url("foo.css") screen, print and (foo: 0);'
284
+ assert_parses '@import url("foo.css") screen, only print, screen and (foo: 0);'
285
+ end
286
+
287
+ def test_media_import
288
+ assert_equal("@import \"./fonts.sass\" all;\n", render("@import \"./fonts.sass\" all;"))
289
+ end
290
+
291
+ def test_dynamic_media_import
292
+ assert_equal(<<CSS, render(<<SCSS))
293
+ @import "foo" print and (-webkit-min-device-pixel-ratio-foo: 25);
294
+ CSS
295
+ $media: print;
296
+ $key: -webkit-min-device-pixel-ratio;
297
+ $value: 20;
298
+ @import "foo" \#{$media} and ($key + "-foo": $value + 5);
299
+ SCSS
300
+ end
301
+
302
+ def test_http_import
303
+ assert_equal("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";\n",
304
+ render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";"))
305
+ end
306
+
307
+ def test_protocol_relative_import
308
+ assert_equal("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";\n",
309
+ render("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";"))
310
+ end
311
+
312
+ def test_import_with_interpolation
313
+ assert_equal <<CSS, render(<<SCSS)
314
+ @import url("http://fonts.googleapis.com/css?family=Droid+Sans");
315
+ CSS
316
+ $family: unquote("Droid+Sans");
317
+ @import url("http://fonts.googleapis.com/css?family=\#{$family}");
318
+ SCSS
319
+ end
320
+
321
+ def test_url_import
322
+ assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass);"))
323
+ end
324
+
325
+ def test_css_import_doesnt_move_through_comments
326
+ assert_equal <<CSS, render(<<SCSS)
327
+ /* Comment 1 */
328
+ @import url("foo.css");
329
+ /* Comment 2 */
330
+ @import url("bar.css");
331
+ CSS
332
+ /* Comment 1 */
333
+ @import url("foo.css");
334
+
335
+ /* Comment 2 */
336
+ @import url("bar.css");
337
+ SCSS
338
+ end
339
+
340
+ def test_css_import_movement_stops_at_comments
341
+ assert_equal <<CSS, render(<<SCSS)
342
+ /* Comment 1 */
343
+ @import url("foo.css");
344
+ /* Comment 2 */
345
+ @import url("bar.css");
346
+ .foo {
347
+ a: b; }
348
+
349
+ /* Comment 3 */
350
+ CSS
351
+ /* Comment 1 */
352
+ @import url("foo.css");
353
+
354
+ /* Comment 2 */
355
+
356
+ .foo {a: b}
357
+
358
+ /* Comment 3 */
359
+ @import url("bar.css");
360
+ SCSS
361
+ end
362
+
363
+ def test_block_comment_in_script
364
+ assert_equal <<CSS, render(<<SCSS)
365
+ foo {
366
+ a: 1bar; }
367
+ CSS
368
+ foo {a: 1 + /* flang */ bar}
369
+ SCSS
370
+ end
371
+
372
+ def test_line_comment_in_script
373
+ assert_equal <<CSS, render(<<SCSS)
374
+ foo {
375
+ a: 1blang; }
376
+ CSS
377
+ foo {a: 1 + // flang }
378
+ blang }
379
+ SCSS
380
+ end
381
+
382
+ ## Nested Rules
383
+
384
+ def test_nested_rules
385
+ assert_equal <<CSS, render(<<SCSS)
386
+ foo bar {
387
+ a: b; }
388
+ CSS
389
+ foo {bar {a: b}}
390
+ SCSS
391
+ assert_equal <<CSS, render(<<SCSS)
392
+ foo bar {
393
+ a: b; }
394
+ foo baz {
395
+ b: c; }
396
+ CSS
397
+ foo {
398
+ bar {a: b}
399
+ baz {b: c}}
400
+ SCSS
401
+ assert_equal <<CSS, render(<<SCSS)
402
+ foo bar baz {
403
+ a: b; }
404
+ foo bang bip {
405
+ a: b; }
406
+ CSS
407
+ foo {
408
+ bar {baz {a: b}}
409
+ bang {bip {a: b}}}
410
+ SCSS
411
+ end
412
+
413
+ def test_nested_rules_with_declarations
414
+ assert_equal <<CSS, render(<<SCSS)
415
+ foo {
416
+ a: b; }
417
+ foo bar {
418
+ c: d; }
419
+ CSS
420
+ foo {
421
+ a: b;
422
+ bar {c: d}}
423
+ SCSS
424
+ assert_equal <<CSS, render(<<SCSS)
425
+ foo {
426
+ a: b; }
427
+ foo bar {
428
+ c: d; }
429
+ CSS
430
+ foo {
431
+ bar {c: d}
432
+ a: b}
433
+ SCSS
434
+ assert_equal <<CSS, render(<<SCSS)
435
+ foo {
436
+ ump: nump;
437
+ grump: clump; }
438
+ foo bar {
439
+ blat: bang;
440
+ habit: rabbit; }
441
+ foo bar baz {
442
+ a: b; }
443
+ foo bar bip {
444
+ c: d; }
445
+ foo bibble bap {
446
+ e: f; }
447
+ CSS
448
+ foo {
449
+ ump: nump;
450
+ grump: clump;
451
+ bar {
452
+ blat: bang;
453
+ habit: rabbit;
454
+ baz {a: b}
455
+ bip {c: d}}
456
+ bibble {
457
+ bap {e: f}}}
458
+ SCSS
459
+ end
460
+
461
+ def test_nested_rules_with_fancy_selectors
462
+ assert_equal <<CSS, render(<<SCSS)
463
+ foo .bar {
464
+ a: b; }
465
+ foo :baz {
466
+ c: d; }
467
+ foo bang:bop {
468
+ e: f; }
469
+ CSS
470
+ foo {
471
+ .bar {a: b}
472
+ :baz {c: d}
473
+ bang:bop {e: f}}
474
+ SCSS
475
+ end
476
+
477
+ def test_almost_ambiguous_nested_rules_and_declarations
478
+ assert_equal <<CSS, render(<<SCSS)
479
+ foo {
480
+ bar: baz bang bop biddle woo look at all these elems; }
481
+ foo bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {
482
+ a: b; }
483
+ foo bar:baz bang bop biddle woo look at all these elems {
484
+ a: b; }
485
+ CSS
486
+ foo {
487
+ bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {a: b};
488
+ bar:baz bang bop biddle woo look at all these elems {a: b};
489
+ bar:baz bang bop biddle woo look at all these elems; }
490
+ SCSS
491
+ end
492
+
493
+ def test_newlines_in_selectors
494
+ assert_equal <<CSS, render(<<SCSS)
495
+ foo
496
+ bar {
497
+ a: b; }
498
+ CSS
499
+ foo
500
+ bar {a: b}
501
+ SCSS
502
+
503
+ assert_equal <<CSS, render(<<SCSS)
504
+ foo baz,
505
+ foo bang,
506
+ bar baz,
507
+ bar bang {
508
+ a: b; }
509
+ CSS
510
+ foo,
511
+ bar {
512
+ baz,
513
+ bang {a: b}}
514
+ SCSS
515
+
516
+ assert_equal <<CSS, render(<<SCSS)
517
+ foo
518
+ bar baz
519
+ bang {
520
+ a: b; }
521
+ foo
522
+ bar bip bop {
523
+ c: d; }
524
+ CSS
525
+ foo
526
+ bar {
527
+ baz
528
+ bang {a: b}
529
+
530
+ bip bop {c: d}}
531
+ SCSS
532
+
533
+ assert_equal <<CSS, render(<<SCSS)
534
+ foo bang, foo bip
535
+ bop, bar
536
+ baz bang, bar
537
+ baz bip
538
+ bop {
539
+ a: b; }
540
+ CSS
541
+ foo, bar
542
+ baz {
543
+ bang, bip
544
+ bop {a: b}}
545
+ SCSS
546
+ end
547
+
548
+ def test_trailing_comma_in_selector
549
+ assert_equal <<CSS, render(<<SCSS)
550
+ #foo #bar,
551
+ #baz #boom {
552
+ a: b; }
553
+
554
+ #bip #bop {
555
+ c: d; }
556
+ CSS
557
+ #foo #bar,,
558
+ ,#baz #boom, {a: b}
559
+
560
+ #bip #bop, ,, {c: d}
561
+ SCSS
562
+ end
563
+
564
+ def test_parent_selectors
565
+ assert_equal <<CSS, render(<<SCSS)
566
+ foo:hover {
567
+ a: b; }
568
+ bar foo.baz {
569
+ c: d; }
570
+ CSS
571
+ foo {
572
+ &:hover {a: b}
573
+ bar &.baz {c: d}}
574
+ SCSS
575
+ end
576
+
577
+ def test_parent_selector_with_subject
578
+ assert_equal <<CSS, render(<<SCSS)
579
+ bar foo.baz! .bip {
580
+ a: b; }
581
+
582
+ bar foo bar.baz! .bip {
583
+ c: d; }
584
+ CSS
585
+ foo {
586
+ bar &.baz! .bip {a: b}}
587
+
588
+ foo bar {
589
+ bar &.baz! .bip {c: d}}
590
+ SCSS
591
+ end
592
+
593
+ ## Namespace Properties
594
+
595
+ def test_namespace_properties
596
+ assert_equal <<CSS, render(<<SCSS)
597
+ foo {
598
+ bar: baz;
599
+ bang-bip: 1px;
600
+ bang-bop: bar; }
601
+ CSS
602
+ foo {
603
+ bar: baz;
604
+ bang: {
605
+ bip: 1px;
606
+ bop: bar;}}
607
+ SCSS
608
+ end
609
+
610
+ def test_several_namespace_properties
611
+ assert_equal <<CSS, render(<<SCSS)
612
+ foo {
613
+ bar: baz;
614
+ bang-bip: 1px;
615
+ bang-bop: bar;
616
+ buzz-fram: "foo";
617
+ buzz-frum: moo; }
618
+ CSS
619
+ foo {
620
+ bar: baz;
621
+ bang: {
622
+ bip: 1px;
623
+ bop: bar;}
624
+ buzz: {
625
+ fram: "foo";
626
+ frum: moo;
627
+ }
628
+ }
629
+ SCSS
630
+ end
631
+
632
+ def test_nested_namespace_properties
633
+ assert_equal <<CSS, render(<<SCSS)
634
+ foo {
635
+ bar: baz;
636
+ bang-bip: 1px;
637
+ bang-bop: bar;
638
+ bang-blat-baf: bort; }
639
+ CSS
640
+ foo {
641
+ bar: baz;
642
+ bang: {
643
+ bip: 1px;
644
+ bop: bar;
645
+ blat:{baf:bort}}}
646
+ SCSS
647
+ end
648
+
649
+ def test_namespace_properties_with_value
650
+ assert_equal <<CSS, render(<<SCSS)
651
+ foo {
652
+ bar: baz;
653
+ bar-bip: bop;
654
+ bar-bing: bop; }
655
+ CSS
656
+ foo {
657
+ bar: baz {
658
+ bip: bop;
659
+ bing: bop; }}
660
+ SCSS
661
+ end
662
+
663
+ def test_namespace_properties_with_script_value
664
+ assert_equal <<CSS, render(<<SCSS)
665
+ foo {
666
+ bar: bazbang;
667
+ bar-bip: bop;
668
+ bar-bing: bop; }
669
+ CSS
670
+ foo {
671
+ bar: baz + bang {
672
+ bip: bop;
673
+ bing: bop; }}
674
+ SCSS
675
+ end
676
+
677
+ def test_no_namespace_properties_without_space
678
+ assert_equal <<CSS, render(<<SCSS)
679
+ foo bar:baz {
680
+ bip: bop; }
681
+ CSS
682
+ foo {
683
+ bar:baz {
684
+ bip: bop }}
685
+ SCSS
686
+ end
687
+
688
+ def test_no_namespace_properties_without_space_even_when_its_unambiguous
689
+ render(<<SCSS)
690
+ foo {
691
+ bar:1px {
692
+ bip: bop }}
693
+ SCSS
694
+ assert(false, "Expected syntax error")
695
+ rescue Sass::SyntaxError => e
696
+ assert_equal <<MESSAGE, e.message
697
+ Invalid CSS: a space is required between a property and its definition
698
+ when it has other properties nested beneath it.
699
+ MESSAGE
700
+ assert_equal 2, e.sass_line
701
+ end
702
+
703
+ ## Mixins
704
+
705
+ def test_basic_mixins
706
+ assert_equal <<CSS, render(<<SCSS)
707
+ .foo {
708
+ a: b; }
709
+ CSS
710
+ @mixin foo {
711
+ .foo {a: b}}
712
+
713
+ @include foo;
714
+ SCSS
715
+
716
+ assert_equal <<CSS, render(<<SCSS)
717
+ bar {
718
+ c: d; }
719
+ bar .foo {
720
+ a: b; }
721
+ CSS
722
+ @mixin foo {
723
+ .foo {a: b}}
724
+
725
+ bar {
726
+ @include foo;
727
+ c: d; }
728
+ SCSS
729
+
730
+ assert_equal <<CSS, render(<<SCSS)
731
+ bar {
732
+ a: b;
733
+ c: d; }
734
+ CSS
735
+ @mixin foo {a: b}
736
+
737
+ bar {
738
+ @include foo;
739
+ c: d; }
740
+ SCSS
741
+ end
742
+
743
+ def test_mixins_with_empty_args
744
+ assert_equal <<CSS, render(<<SCSS)
745
+ .foo {
746
+ a: b; }
747
+ CSS
748
+ @mixin foo() {a: b}
749
+
750
+ .foo {@include foo();}
751
+ SCSS
752
+
753
+ assert_equal <<CSS, render(<<SCSS)
754
+ .foo {
755
+ a: b; }
756
+ CSS
757
+ @mixin foo() {a: b}
758
+
759
+ .foo {@include foo;}
760
+ SCSS
761
+
762
+ assert_equal <<CSS, render(<<SCSS)
763
+ .foo {
764
+ a: b; }
765
+ CSS
766
+ @mixin foo {a: b}
767
+
768
+ .foo {@include foo();}
769
+ SCSS
770
+ end
771
+
772
+ def test_mixins_with_args
773
+ assert_equal <<CSS, render(<<SCSS)
774
+ .foo {
775
+ a: bar; }
776
+ CSS
777
+ @mixin foo($a) {a: $a}
778
+
779
+ .foo {@include foo(bar)}
780
+ SCSS
781
+
782
+ assert_equal <<CSS, render(<<SCSS)
783
+ .foo {
784
+ a: bar;
785
+ b: 12px; }
786
+ CSS
787
+ @mixin foo($a, $b) {
788
+ a: $a;
789
+ b: $b; }
790
+
791
+ .foo {@include foo(bar, 12px)}
792
+ SCSS
793
+ end
794
+
795
+ ## Functions
796
+
797
+ def test_basic_function
798
+ assert_equal(<<CSS, render(<<SASS))
799
+ bar {
800
+ a: 3; }
801
+ CSS
802
+ @function foo() {
803
+ @return 1 + 2;
804
+ }
805
+
806
+ bar {
807
+ a: foo();
808
+ }
809
+ SASS
810
+ end
811
+
812
+ def test_function_args
813
+ assert_equal(<<CSS, render(<<SASS))
814
+ bar {
815
+ a: 3; }
816
+ CSS
817
+ @function plus($var1, $var2) {
818
+ @return $var1 + $var2;
819
+ }
820
+
821
+ bar {
822
+ a: plus(1, 2);
823
+ }
824
+ SASS
825
+ end
826
+
827
+ ## Var Args
828
+
829
+ def test_mixin_var_args
830
+ assert_equal <<CSS, render(<<SCSS)
831
+ .foo {
832
+ a: 1;
833
+ b: 2, 3, 4; }
834
+ CSS
835
+ @mixin foo($a, $b...) {
836
+ a: $a;
837
+ b: $b;
838
+ }
839
+
840
+ .foo {@include foo(1, 2, 3, 4)}
841
+ SCSS
842
+ end
843
+
844
+ def test_mixin_empty_var_args
845
+ assert_equal <<CSS, render(<<SCSS)
846
+ .foo {
847
+ a: 1;
848
+ b: 0; }
849
+ CSS
850
+ @mixin foo($a, $b...) {
851
+ a: $a;
852
+ b: length($b);
853
+ }
854
+
855
+ .foo {@include foo(1)}
856
+ SCSS
857
+ end
858
+
859
+ def test_mixin_var_args_act_like_list
860
+ assert_equal <<CSS, render(<<SCSS)
861
+ .foo {
862
+ a: 3;
863
+ b: 3; }
864
+ CSS
865
+ @mixin foo($a, $b...) {
866
+ a: length($b);
867
+ b: nth($b, 2);
868
+ }
869
+
870
+ .foo {@include foo(1, 2, 3, 4)}
871
+ SCSS
872
+ end
873
+
874
+ def test_mixin_splat_args
875
+ assert_equal <<CSS, render(<<SCSS)
876
+ .foo {
877
+ a: 1;
878
+ b: 2;
879
+ c: 3;
880
+ d: 4; }
881
+ CSS
882
+ @mixin foo($a, $b, $c, $d) {
883
+ a: $a;
884
+ b: $b;
885
+ c: $c;
886
+ d: $d;
887
+ }
888
+
889
+ $list: 2, 3, 4;
890
+ .foo {@include foo(1, $list...)}
891
+ SCSS
892
+ end
893
+
894
+ def test_mixin_splat_expression
895
+ assert_equal <<CSS, render(<<SCSS)
896
+ .foo {
897
+ a: 1;
898
+ b: 2;
899
+ c: 3;
900
+ d: 4; }
901
+ CSS
902
+ @mixin foo($a, $b, $c, $d) {
903
+ a: $a;
904
+ b: $b;
905
+ c: $c;
906
+ d: $d;
907
+ }
908
+
909
+ .foo {@include foo(1, (2, 3, 4)...)}
910
+ SCSS
911
+ end
912
+
913
+ def test_mixin_splat_args_with_var_args
914
+ assert_equal <<CSS, render(<<SCSS)
915
+ .foo {
916
+ a: 1;
917
+ b: 2, 3, 4; }
918
+ CSS
919
+ @mixin foo($a, $b...) {
920
+ a: $a;
921
+ b: $b;
922
+ }
923
+
924
+ $list: 2, 3, 4;
925
+ .foo {@include foo(1, $list...)}
926
+ SCSS
927
+ end
928
+
929
+ def test_mixin_splat_args_with_var_args_and_normal_args
930
+ assert_equal <<CSS, render(<<SCSS)
931
+ .foo {
932
+ a: 1;
933
+ b: 2;
934
+ c: 3, 4; }
935
+ CSS
936
+ @mixin foo($a, $b, $c...) {
937
+ a: $a;
938
+ b: $b;
939
+ c: $c;
940
+ }
941
+
942
+ $list: 2, 3, 4;
943
+ .foo {@include foo(1, $list...)}
944
+ SCSS
945
+ end
946
+
947
+ def test_mixin_splat_args_with_var_args_preserves_separator
948
+ assert_equal <<CSS, render(<<SCSS)
949
+ .foo {
950
+ a: 1;
951
+ b: 2 3 4 5; }
952
+ CSS
953
+ @mixin foo($a, $b...) {
954
+ a: $a;
955
+ b: $b;
956
+ }
957
+
958
+ $list: 3 4 5;
959
+ .foo {@include foo(1, 2, $list...)}
960
+ SCSS
961
+ end
962
+
963
+ def test_mixin_var_and_splat_args_pass_through_keywords
964
+ assert_equal <<CSS, render(<<SCSS)
965
+ .foo {
966
+ a: 3;
967
+ b: 1;
968
+ c: 2; }
969
+ CSS
970
+ @mixin foo($a...) {
971
+ @include bar($a...);
972
+ }
973
+
974
+ @mixin bar($b, $c, $a) {
975
+ a: $a;
976
+ b: $b;
977
+ c: $c;
978
+ }
979
+
980
+ .foo {@include foo(1, $c: 2, $a: 3)}
981
+ SCSS
982
+ end
983
+
984
+ def test_mixin_var_args_with_keyword
985
+ assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
986
+ @mixin foo($a, $b...) {
987
+ a: $a;
988
+ b: $b;
989
+ }
990
+
991
+ .foo {@include foo($a: 1, 2, 3, 4)}
992
+ SCSS
993
+ end
994
+
995
+ def test_mixin_keyword_for_var_arg
996
+ assert_raise_message(Sass::SyntaxError, "Argument $b of mixin foo cannot be used as a named argument.") {render <<SCSS}
997
+ @mixin foo($a, $b...) {
998
+ a: $a;
999
+ b: $b;
1000
+ }
1001
+
1002
+ .foo {@include foo(1, $b: 2 3 4)}
1003
+ SCSS
1004
+ end
1005
+
1006
+ def test_mixin_keyword_for_unknown_arg_with_var_args
1007
+ assert_raise_message(Sass::SyntaxError, "Mixin foo doesn't have an argument named $c.") {render <<SCSS}
1008
+ @mixin foo($a, $b...) {
1009
+ a: $a;
1010
+ b: $b;
1011
+ }
1012
+
1013
+ .foo {@include foo(1, $c: 2 3 4)}
1014
+ SCSS
1015
+ end
1016
+
1017
+ def test_function_var_args
1018
+ assert_equal <<CSS, render(<<SCSS)
1019
+ .foo {
1020
+ val: "a: 1, b: 2, 3, 4"; }
1021
+ CSS
1022
+ @function foo($a, $b...) {
1023
+ @return "a: \#{$a}, b: \#{$b}";
1024
+ }
1025
+
1026
+ .foo {val: foo(1, 2, 3, 4)}
1027
+ SCSS
1028
+ end
1029
+
1030
+ def test_function_empty_var_args
1031
+ assert_equal <<CSS, render(<<SCSS)
1032
+ .foo {
1033
+ val: "a: 1, b: 0"; }
1034
+ CSS
1035
+ @function foo($a, $b...) {
1036
+ @return "a: \#{$a}, b: \#{length($b)}";
1037
+ }
1038
+
1039
+ .foo {val: foo(1)}
1040
+ SCSS
1041
+ end
1042
+
1043
+ def test_function_var_args_act_like_list
1044
+ assert_equal <<CSS, render(<<SCSS)
1045
+ .foo {
1046
+ val: "a: 3, b: 3"; }
1047
+ CSS
1048
+ @function foo($a, $b...) {
1049
+ @return "a: \#{length($b)}, b: \#{nth($b, 2)}";
1050
+ }
1051
+
1052
+ .foo {val: foo(1, 2, 3, 4)}
1053
+ SCSS
1054
+ end
1055
+
1056
+ def test_function_splat_args
1057
+ assert_equal <<CSS, render(<<SCSS)
1058
+ .foo {
1059
+ val: "a: 1, b: 2, c: 3, d: 4"; }
1060
+ CSS
1061
+ @function foo($a, $b, $c, $d) {
1062
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
1063
+ }
1064
+
1065
+ $list: 2, 3, 4;
1066
+ .foo {val: foo(1, $list...)}
1067
+ SCSS
1068
+ end
1069
+
1070
+ def test_function_splat_expression
1071
+ assert_equal <<CSS, render(<<SCSS)
1072
+ .foo {
1073
+ val: "a: 1, b: 2, c: 3, d: 4"; }
1074
+ CSS
1075
+ @function foo($a, $b, $c, $d) {
1076
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
1077
+ }
1078
+
1079
+ .foo {val: foo(1, (2, 3, 4)...)}
1080
+ SCSS
1081
+ end
1082
+
1083
+ def test_function_splat_args_with_var_args
1084
+ assert_equal <<CSS, render(<<SCSS)
1085
+ .foo {
1086
+ val: "a: 1, b: 2, 3, 4"; }
1087
+ CSS
1088
+ @function foo($a, $b...) {
1089
+ @return "a: \#{$a}, b: \#{$b}";
1090
+ }
1091
+
1092
+ $list: 2, 3, 4;
1093
+ .foo {val: foo(1, $list...)}
1094
+ SCSS
1095
+ end
1096
+
1097
+ def test_function_splat_args_with_var_args_and_normal_args
1098
+ assert_equal <<CSS, render(<<SCSS)
1099
+ .foo {
1100
+ val: "a: 1, b: 2, c: 3, 4"; }
1101
+ CSS
1102
+ @function foo($a, $b, $c...) {
1103
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1104
+ }
1105
+
1106
+ $list: 2, 3, 4;
1107
+ .foo {val: foo(1, $list...)}
1108
+ SCSS
1109
+ end
1110
+
1111
+ def test_function_splat_args_with_var_args_preserves_separator
1112
+ assert_equal <<CSS, render(<<SCSS)
1113
+ .foo {
1114
+ val: "a: 1, b: 2 3 4 5"; }
1115
+ CSS
1116
+ @function foo($a, $b...) {
1117
+ @return "a: \#{$a}, b: \#{$b}";
1118
+ }
1119
+
1120
+ $list: 3 4 5;
1121
+ .foo {val: foo(1, 2, $list...)}
1122
+ SCSS
1123
+ end
1124
+
1125
+ def test_function_var_and_splat_args_pass_through_keywords
1126
+ assert_equal <<CSS, render(<<SCSS)
1127
+ .foo {
1128
+ val: "a: 3, b: 1, c: 2"; }
1129
+ CSS
1130
+ @function foo($a...) {
1131
+ @return bar($a...);
1132
+ }
1133
+
1134
+ @function bar($b, $c, $a) {
1135
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1136
+ }
1137
+
1138
+ .foo {val: foo(1, $c: 2, $a: 3)}
1139
+ SCSS
1140
+ end
1141
+
1142
+ def test_function_var_args_with_keyword
1143
+ assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
1144
+ @function foo($a, $b...) {
1145
+ @return "a: \#{$a}, b: $b";
1146
+ }
1147
+
1148
+ .foo {val: foo($a: 1, 2, 3, 4)}
1149
+ SCSS
1150
+ end
1151
+
1152
+ def test_function_keyword_for_var_arg
1153
+ assert_raise_message(Sass::SyntaxError, "Argument $b of function foo cannot be used as a named argument.") {render <<SCSS}
1154
+ @function foo($a, $b...) {
1155
+ @return "a: \#{$a}, b: \#{$b}";
1156
+ }
1157
+
1158
+ .foo {val: foo(1, $b: 2 3 4)}
1159
+ SCSS
1160
+ end
1161
+
1162
+ def test_function_keyword_for_unknown_arg_with_var_args
1163
+ assert_raise_message(Sass::SyntaxError, "Function foo doesn't have an argument named $c.") {render <<SCSS}
1164
+ @function foo($a, $b...) {
1165
+ @return "a: \#{$a}, b: \#{$b}";
1166
+ }
1167
+
1168
+ .foo {val: foo(1, $c: 2 3 4)}
1169
+ SCSS
1170
+ end
1171
+
1172
+ def test_function_var_args_passed_to_native
1173
+ assert_equal <<CSS, render(<<SCSS)
1174
+ .foo {
1175
+ val: #102035; }
1176
+ CSS
1177
+ @function foo($args...) {
1178
+ @return adjust-color($args...);
1179
+ }
1180
+
1181
+ .foo {val: foo(#102030, $blue: 5)}
1182
+ SCSS
1183
+ end
1184
+
1185
+ ## Interpolation
1186
+
1187
+ def test_basic_selector_interpolation
1188
+ assert_equal <<CSS, render(<<SCSS)
1189
+ foo 3 baz {
1190
+ a: b; }
1191
+ CSS
1192
+ foo \#{1 + 2} baz {a: b}
1193
+ SCSS
1194
+ assert_equal <<CSS, render(<<SCSS)
1195
+ foo.bar baz {
1196
+ a: b; }
1197
+ CSS
1198
+ foo\#{".bar"} baz {a: b}
1199
+ SCSS
1200
+ assert_equal <<CSS, render(<<SCSS)
1201
+ foo.bar baz {
1202
+ a: b; }
1203
+ CSS
1204
+ \#{"foo"}.bar baz {a: b}
1205
+ SCSS
1206
+ end
1207
+
1208
+ def test_selector_only_interpolation
1209
+ assert_equal <<CSS, render(<<SCSS)
1210
+ foo bar {
1211
+ a: b; }
1212
+ CSS
1213
+ \#{"foo" + " bar"} {a: b}
1214
+ SCSS
1215
+ end
1216
+
1217
+ def test_selector_interpolation_before_element_name
1218
+ assert_equal <<CSS, render(<<SCSS)
1219
+ foo barbaz {
1220
+ a: b; }
1221
+ CSS
1222
+ \#{"foo" + " bar"}baz {a: b}
1223
+ SCSS
1224
+ end
1225
+
1226
+ def test_selector_interpolation_in_string
1227
+ assert_equal <<CSS, render(<<SCSS)
1228
+ foo[val="bar foo bar baz"] {
1229
+ a: b; }
1230
+ CSS
1231
+ foo[val="bar \#{"foo" + " bar"} baz"] {a: b}
1232
+ SCSS
1233
+ end
1234
+
1235
+ def test_selector_interpolation_in_pseudoclass
1236
+ assert_equal <<CSS, render(<<SCSS)
1237
+ foo:nth-child(5n) {
1238
+ a: b; }
1239
+ CSS
1240
+ foo:nth-child(\#{5 + "n"}) {a: b}
1241
+ SCSS
1242
+ end
1243
+
1244
+ def test_selector_interpolation_at_class_begininng
1245
+ assert_equal <<CSS, render(<<SCSS)
1246
+ .zzz {
1247
+ a: b; }
1248
+ CSS
1249
+ $zzz: zzz;
1250
+ .\#{$zzz} { a: b; }
1251
+ SCSS
1252
+ end
1253
+
1254
+ def test_selector_interpolation_at_id_begininng
1255
+ assert_equal <<CSS, render(<<SCSS)
1256
+ #zzz {
1257
+ a: b; }
1258
+ CSS
1259
+ $zzz: zzz;
1260
+ #\#{$zzz} { a: b; }
1261
+ SCSS
1262
+ end
1263
+
1264
+ def test_selector_interpolation_at_pseudo_begininng
1265
+ assert_equal <<CSS, render(<<SCSS)
1266
+ :zzz::zzz {
1267
+ a: b; }
1268
+ CSS
1269
+ $zzz: zzz;
1270
+ :\#{$zzz}::\#{$zzz} { a: b; }
1271
+ SCSS
1272
+ end
1273
+
1274
+ def test_selector_interpolation_at_attr_beginning
1275
+ assert_equal <<CSS, render(<<SCSS)
1276
+ [zzz=foo] {
1277
+ a: b; }
1278
+ CSS
1279
+ $zzz: zzz;
1280
+ [\#{$zzz}=foo] { a: b; }
1281
+ SCSS
1282
+ end
1283
+
1284
+ def test_selector_interpolation_at_attr_end
1285
+ assert_equal <<CSS, render(<<SCSS)
1286
+ [foo=zzz] {
1287
+ a: b; }
1288
+ CSS
1289
+ $zzz: zzz;
1290
+ [foo=\#{$zzz}] { a: b; }
1291
+ SCSS
1292
+ end
1293
+
1294
+ def test_selector_interpolation_at_dashes
1295
+ assert_equal <<CSS, render(<<SCSS)
1296
+ div {
1297
+ -foo-a-b-foo: foo; }
1298
+ CSS
1299
+ $a : a;
1300
+ $b : b;
1301
+ div { -foo-\#{$a}-\#{$b}-foo: foo }
1302
+ SCSS
1303
+ end
1304
+
1305
+ def test_selector_interpolation_in_reference_combinator
1306
+ assert_equal <<CSS, render(<<SCSS)
1307
+ .foo /a/ .bar /b|c/ .baz {
1308
+ a: b; }
1309
+ CSS
1310
+ $a: a;
1311
+ $b: b;
1312
+ $c: c;
1313
+ .foo /\#{$a}/ .bar /\#{$b}|\#{$c}/ .baz {a: b}
1314
+ SCSS
1315
+ end
1316
+
1317
+ def test_parent_selector_with_parent_and_subject
1318
+ assert_equal <<CSS, render(<<SCSS)
1319
+ bar foo.baz! .bip {
1320
+ c: d; }
1321
+ CSS
1322
+ $subject: "!";
1323
+ foo {
1324
+ bar &.baz\#{$subject} .bip {c: d}}
1325
+ SCSS
1326
+ end
1327
+
1328
+ def test_basic_prop_name_interpolation
1329
+ assert_equal <<CSS, render(<<SCSS)
1330
+ foo {
1331
+ barbazbang: blip; }
1332
+ CSS
1333
+ foo {bar\#{"baz" + "bang"}: blip}
1334
+ SCSS
1335
+ assert_equal <<CSS, render(<<SCSS)
1336
+ foo {
1337
+ bar3: blip; }
1338
+ CSS
1339
+ foo {bar\#{1 + 2}: blip}
1340
+ SCSS
1341
+ end
1342
+
1343
+ def test_prop_name_only_interpolation
1344
+ assert_equal <<CSS, render(<<SCSS)
1345
+ foo {
1346
+ bazbang: blip; }
1347
+ CSS
1348
+ foo {\#{"baz" + "bang"}: blip}
1349
+ SCSS
1350
+ end
1351
+
1352
+ def test_directive_interpolation
1353
+ assert_equal <<CSS, render(<<SCSS)
1354
+ @foo bar12 qux {
1355
+ a: b; }
1356
+ CSS
1357
+ $baz: 12;
1358
+ @foo bar\#{$baz} qux {a: b}
1359
+ SCSS
1360
+ end
1361
+
1362
+ def test_media_interpolation
1363
+ assert_equal <<CSS, render(<<SCSS)
1364
+ @media bar12 {
1365
+ a: b; }
1366
+ CSS
1367
+ $baz: 12;
1368
+ @media bar\#{$baz} {a: b}
1369
+ SCSS
1370
+ end
1371
+
1372
+ def test_script_in_media
1373
+ assert_equal <<CSS, render(<<SCSS)
1374
+ @media screen and (-webkit-min-device-pixel-ratio: 20), only print {
1375
+ a: b; }
1376
+ CSS
1377
+ $media1: screen;
1378
+ $media2: print;
1379
+ $var: -webkit-min-device-pixel-ratio;
1380
+ $val: 20;
1381
+ @media \#{$media1} and ($var: $val), only \#{$media2} {a: b}
1382
+ SCSS
1383
+
1384
+ assert_equal <<CSS, render(<<SCSS)
1385
+ @media screen and (-webkit-min-device-pixel-ratio: 13) {
1386
+ a: b; }
1387
+ CSS
1388
+ $vals: 1 2 3;
1389
+ @media screen and (-webkit-min-device-pixel-ratio: 5 + 6 + nth($vals, 2)) {a: b}
1390
+ SCSS
1391
+ end
1392
+
1393
+ def test_media_interpolation_with_reparse
1394
+ assert_equal <<CSS, render(<<SCSS)
1395
+ @media screen and (max-width: 300px) {
1396
+ a: b; }
1397
+ @media screen and (max-width: 300px) {
1398
+ a: b; }
1399
+ @media screen and (max-width: 300px) {
1400
+ a: b; }
1401
+ @media screen and (max-width: 300px), print and (max-width: 300px) {
1402
+ a: b; }
1403
+ CSS
1404
+ $constraint: "(max-width: 300px)";
1405
+ $fragment: "nd \#{$constraint}";
1406
+ $comma: "een, pri";
1407
+ @media screen and \#{$constraint} {a: b}
1408
+ @media screen {
1409
+ @media \#{$constraint} {a: b}
1410
+ }
1411
+ @media screen a\#{$fragment} {a: b}
1412
+ @media scr\#{$comma}nt {
1413
+ @media \#{$constraint} {a: b}
1414
+ }
1415
+ SCSS
1416
+ end
1417
+
1418
+ def test_moz_document_interpolation
1419
+ assert_equal <<CSS, render(<<SCSS)
1420
+ @-moz-document url(http://sass-lang.com/),
1421
+ url-prefix(http://sass-lang.com/docs),
1422
+ domain(sass-lang.com),
1423
+ domain("sass-lang.com") {
1424
+ .foo {
1425
+ a: b; } }
1426
+ CSS
1427
+ $domain: "sass-lang.com";
1428
+ @-moz-document url(http://\#{$domain}/),
1429
+ url-prefix(http://\#{$domain}/docs),
1430
+ domain(\#{$domain}),
1431
+ \#{domain($domain)} {
1432
+ .foo {a: b}
1433
+ }
1434
+ SCSS
1435
+ end
1436
+
1437
+ def test_supports_with_expressions
1438
+ assert_equal <<CSS, render(<<SCSS)
1439
+ @supports (feature1: val) and (feature2: val) or (not (feature23: val4)) {
1440
+ foo {
1441
+ a: b; } }
1442
+ CSS
1443
+ $query: "(feature1: val)";
1444
+ $feature: feature2;
1445
+ $val: val;
1446
+ @supports \#{$query} and ($feature: $val) or (not ($feature + 3: $val + 4)) {
1447
+ foo {a: b}
1448
+ }
1449
+ SCSS
1450
+ end
1451
+
1452
+ def test_supports_bubbling
1453
+ assert_equal <<CSS, render(<<SCSS)
1454
+ @supports (foo: bar) {
1455
+ a {
1456
+ b: c; }
1457
+ @supports (baz: bang) {
1458
+ a {
1459
+ d: e; } } }
1460
+ CSS
1461
+ a {
1462
+ @supports (foo: bar) {
1463
+ b: c;
1464
+ @supports (baz: bang) {
1465
+ d: e;
1466
+ }
1467
+ }
1468
+ }
1469
+ SCSS
1470
+ end
1471
+
1472
+ def test_random_directive_interpolation
1473
+ assert_equal <<CSS, render(<<SCSS)
1474
+ @foo url(http://sass-lang.com/),
1475
+ domain("sass-lang.com"),
1476
+ "foobarbaz",
1477
+ foobarbaz {
1478
+ .foo {
1479
+ a: b; } }
1480
+ CSS
1481
+ $domain: "sass-lang.com";
1482
+ @foo url(http://\#{$domain}/),
1483
+ \#{domain($domain)},
1484
+ "foo\#{'ba' + 'r'}baz",
1485
+ foo\#{'ba' + 'r'}baz {
1486
+ .foo {a: b}
1487
+ }
1488
+ SCSS
1489
+ end
1490
+
1491
+ def test_nested_mixin_def
1492
+ assert_equal <<CSS, render(<<SCSS)
1493
+ foo {
1494
+ a: b; }
1495
+ CSS
1496
+ foo {
1497
+ @mixin bar {a: b}
1498
+ @include bar; }
1499
+ SCSS
1500
+ end
1501
+
1502
+ def test_nested_mixin_shadow
1503
+ assert_equal <<CSS, render(<<SCSS)
1504
+ foo {
1505
+ c: d; }
1506
+
1507
+ baz {
1508
+ a: b; }
1509
+ CSS
1510
+ @mixin bar {a: b}
1511
+
1512
+ foo {
1513
+ @mixin bar {c: d}
1514
+ @include bar;
1515
+ }
1516
+
1517
+ baz {@include bar}
1518
+ SCSS
1519
+ end
1520
+
1521
+ def test_nested_function_def
1522
+ assert_equal <<CSS, render(<<SCSS)
1523
+ foo {
1524
+ a: 1; }
1525
+
1526
+ bar {
1527
+ b: foo(); }
1528
+ CSS
1529
+ foo {
1530
+ @function foo() {@return 1}
1531
+ a: foo(); }
1532
+
1533
+ bar {b: foo()}
1534
+ SCSS
1535
+ end
1536
+
1537
+ def test_nested_function_shadow
1538
+ assert_equal <<CSS, render(<<SCSS)
1539
+ foo {
1540
+ a: 2; }
1541
+
1542
+ baz {
1543
+ b: 1; }
1544
+ CSS
1545
+ @function foo() {@return 1}
1546
+
1547
+ foo {
1548
+ @function foo() {@return 2}
1549
+ a: foo();
1550
+ }
1551
+
1552
+ baz {b: foo()}
1553
+ SCSS
1554
+ end
1555
+
1556
+ ## Errors
1557
+
1558
+ def test_nested_mixin_def_is_scoped
1559
+ render <<SCSS
1560
+ foo {
1561
+ @mixin bar {a: b}}
1562
+ bar {@include bar}
1563
+ SCSS
1564
+ assert(false, "Expected syntax error")
1565
+ rescue Sass::SyntaxError => e
1566
+ assert_equal "Undefined mixin 'bar'.", e.message
1567
+ assert_equal 3, e.sass_line
1568
+ end
1569
+
1570
+ def test_rules_beneath_properties
1571
+ render <<SCSS
1572
+ foo {
1573
+ bar: {
1574
+ baz {
1575
+ bang: bop }}}
1576
+ SCSS
1577
+ assert(false, "Expected syntax error")
1578
+ rescue Sass::SyntaxError => e
1579
+ assert_equal 'Illegal nesting: Only properties may be nested beneath properties.', e.message
1580
+ assert_equal 3, e.sass_line
1581
+ end
1582
+
1583
+ def test_uses_property_exception_with_star_hack
1584
+ render <<SCSS
1585
+ foo {
1586
+ *bar:baz [fail]; }
1587
+ SCSS
1588
+ assert(false, "Expected syntax error")
1589
+ rescue Sass::SyntaxError => e
1590
+ assert_equal 'Invalid CSS after " *bar:baz ": expected ";", was "[fail]; }"', e.message
1591
+ assert_equal 2, e.sass_line
1592
+ end
1593
+
1594
+ def test_uses_property_exception_with_colon_hack
1595
+ render <<SCSS
1596
+ foo {
1597
+ :bar:baz [fail]; }
1598
+ SCSS
1599
+ assert(false, "Expected syntax error")
1600
+ rescue Sass::SyntaxError => e
1601
+ assert_equal 'Invalid CSS after " :bar:baz ": expected ";", was "[fail]; }"', e.message
1602
+ assert_equal 2, e.sass_line
1603
+ end
1604
+
1605
+ def test_uses_rule_exception_with_dot_hack
1606
+ render <<SCSS
1607
+ foo {
1608
+ .bar:baz <fail>; }
1609
+ SCSS
1610
+ assert(false, "Expected syntax error")
1611
+ rescue Sass::SyntaxError => e
1612
+ assert_equal 'Invalid CSS after " .bar:baz ": expected "{", was "<fail>; }"', e.message
1613
+ assert_equal 2, e.sass_line
1614
+ end
1615
+
1616
+ def test_uses_property_exception_with_space_after_name
1617
+ render <<SCSS
1618
+ foo {
1619
+ bar: baz [fail]; }
1620
+ SCSS
1621
+ assert(false, "Expected syntax error")
1622
+ rescue Sass::SyntaxError => e
1623
+ assert_equal 'Invalid CSS after " bar: baz ": expected ";", was "[fail]; }"', e.message
1624
+ assert_equal 2, e.sass_line
1625
+ end
1626
+
1627
+ def test_uses_property_exception_with_non_identifier_after_name
1628
+ render <<SCSS
1629
+ foo {
1630
+ bar:1px [fail]; }
1631
+ SCSS
1632
+ assert(false, "Expected syntax error")
1633
+ rescue Sass::SyntaxError => e
1634
+ assert_equal 'Invalid CSS after " bar:1px ": expected ";", was "[fail]; }"', e.message
1635
+ assert_equal 2, e.sass_line
1636
+ end
1637
+
1638
+ def test_uses_property_exception_when_followed_by_open_bracket
1639
+ render <<SCSS
1640
+ foo {
1641
+ bar:{baz: .fail} }
1642
+ SCSS
1643
+ assert(false, "Expected syntax error")
1644
+ rescue Sass::SyntaxError => e
1645
+ assert_equal 'Invalid CSS after " bar:{baz: ": expected expression (e.g. 1px, bold), was ".fail} }"', e.message
1646
+ assert_equal 2, e.sass_line
1647
+ end
1648
+
1649
+ def test_script_error
1650
+ render <<SCSS
1651
+ foo {
1652
+ bar: "baz" * * }
1653
+ SCSS
1654
+ assert(false, "Expected syntax error")
1655
+ rescue Sass::SyntaxError => e
1656
+ assert_equal 'Invalid CSS after " bar: "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message
1657
+ assert_equal 2, e.sass_line
1658
+ end
1659
+
1660
+ def test_multiline_script_syntax_error
1661
+ render <<SCSS
1662
+ foo {
1663
+ bar:
1664
+ "baz" * * }
1665
+ SCSS
1666
+ assert(false, "Expected syntax error")
1667
+ rescue Sass::SyntaxError => e
1668
+ assert_equal 'Invalid CSS after " "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message
1669
+ assert_equal 3, e.sass_line
1670
+ end
1671
+
1672
+ def test_multiline_script_runtime_error
1673
+ render <<SCSS
1674
+ foo {
1675
+ bar: "baz" +
1676
+ "bar" +
1677
+ $bang }
1678
+ SCSS
1679
+ assert(false, "Expected syntax error")
1680
+ rescue Sass::SyntaxError => e
1681
+ assert_equal "Undefined variable: \"$bang\".", e.message
1682
+ assert_equal 4, e.sass_line
1683
+ end
1684
+
1685
+ def test_post_multiline_script_runtime_error
1686
+ render <<SCSS
1687
+ foo {
1688
+ bar: "baz" +
1689
+ "bar" +
1690
+ "baz";
1691
+ bip: $bop; }
1692
+ SCSS
1693
+ assert(false, "Expected syntax error")
1694
+ rescue Sass::SyntaxError => e
1695
+ assert_equal "Undefined variable: \"$bop\".", e.message
1696
+ assert_equal 5, e.sass_line
1697
+ end
1698
+
1699
+ def test_multiline_property_runtime_error
1700
+ render <<SCSS
1701
+ foo {
1702
+ bar: baz
1703
+ bar
1704
+ \#{$bang} }
1705
+ SCSS
1706
+ assert(false, "Expected syntax error")
1707
+ rescue Sass::SyntaxError => e
1708
+ assert_equal "Undefined variable: \"$bang\".", e.message
1709
+ assert_equal 4, e.sass_line
1710
+ end
1711
+
1712
+ def test_post_resolution_selector_error
1713
+ render "\n\nfoo \#{\") bar\"} {a: b}"
1714
+ assert(false, "Expected syntax error")
1715
+ rescue Sass::SyntaxError => e
1716
+ assert_equal 'Invalid CSS after "foo ": expected selector, was ") bar"', e.message
1717
+ assert_equal 3, e.sass_line
1718
+ end
1719
+
1720
+ def test_parent_in_mid_selector_error
1721
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1722
+ Invalid CSS after " .foo": expected "{", was "&.bar {a: b}"
1723
+
1724
+ "&.bar" may only be used at the beginning of a compound selector.
1725
+ MESSAGE
1726
+ flim {
1727
+ .foo&.bar {a: b}
1728
+ }
1729
+ SCSS
1730
+ end
1731
+
1732
+ def test_parent_after_selector_error
1733
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1734
+ Invalid CSS after " .foo.bar": expected "{", was "& {a: b}"
1735
+
1736
+ "&" may only be used at the beginning of a compound selector.
1737
+ MESSAGE
1738
+ flim {
1739
+ .foo.bar& {a: b}
1740
+ }
1741
+ SCSS
1742
+ end
1743
+
1744
+ def test_double_parent_selector_error
1745
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1746
+ Invalid CSS after " &": expected "{", was "& {a: b}"
1747
+
1748
+ "&" may only be used at the beginning of a compound selector.
1749
+ MESSAGE
1750
+ flim {
1751
+ && {a: b}
1752
+ }
1753
+ SCSS
1754
+ end
1755
+
1756
+ def test_no_lonely_else
1757
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1758
+ Invalid CSS: @else must come after @if
1759
+ MESSAGE
1760
+ @else {foo: bar}
1761
+ SCSS
1762
+ end
1763
+
1764
+ # Regression
1765
+
1766
+ def test_parent_ref_with_newline
1767
+ assert_equal(<<CSS, render(<<SCSS))
1768
+ a.c
1769
+ , b.c {
1770
+ x: y; }
1771
+ CSS
1772
+ a
1773
+ , b {&.c {x: y}}
1774
+ SCSS
1775
+ end
1776
+
1777
+ def test_loud_comment_in_compressed_mode
1778
+ assert_equal(<<CSS, render(<<SCSS))
1779
+ /*! foo */
1780
+ CSS
1781
+ /*! foo */
1782
+ SCSS
1783
+ end
1784
+
1785
+ def test_parsing_decimals_followed_by_comments_doesnt_take_forever
1786
+ assert_equal(<<CSS, render(<<SCSS))
1787
+ .foo {
1788
+ padding: 4.21053% 4.21053% 5.63158%; }
1789
+ CSS
1790
+ .foo {
1791
+ padding: 4.21052631578947% 4.21052631578947% 5.631578947368421% /**/
1792
+ }
1793
+ SCSS
1794
+ end
1795
+
1796
+ def test_parsing_many_numbers_doesnt_take_forever
1797
+ values = ["80% 90%"] * 1000
1798
+ assert_equal(<<CSS, render(<<SCSS))
1799
+ .foo {
1800
+ padding: #{values.join(', ')}; }
1801
+ CSS
1802
+ .foo {
1803
+ padding: #{values.join(', ')};
1804
+ }
1805
+ SCSS
1806
+ end
1807
+
1808
+ def test_import_comments_in_imports
1809
+ assert_equal(<<CSS, render(<<SCSS))
1810
+ @import url(foo.css);
1811
+ @import url(bar.css);
1812
+ @import url(baz.css);
1813
+ CSS
1814
+ @import "foo.css", // this is a comment
1815
+ "bar.css", /* this is another comment */
1816
+ "baz.css"; // this is a third comment
1817
+ SCSS
1818
+ end
1819
+
1820
+ def test_reference_combinator_with_parent_ref
1821
+ assert_equal <<CSS, render(<<SCSS)
1822
+ a /foo/ b {
1823
+ c: d; }
1824
+ CSS
1825
+ a {& /foo/ b {c: d}}
1826
+ SCSS
1827
+ end
1828
+
1829
+ def test_newline_selector_rendered_multiple_times
1830
+ assert_equal <<CSS, render(<<SCSS)
1831
+ form input,
1832
+ form select {
1833
+ color: white; }
1834
+
1835
+ form input,
1836
+ form select {
1837
+ color: white; }
1838
+ CSS
1839
+ @for $i from 1 through 2 {
1840
+ form {
1841
+ input,
1842
+ select {
1843
+ color: white;
1844
+ }
1845
+ }
1846
+ }
1847
+ SCSS
1848
+ end
1849
+
1850
+ def test_prop_name_interpolation_after_hyphen
1851
+ assert_equal <<CSS, render(<<SCSS)
1852
+ a {
1853
+ -foo-bar: b; }
1854
+ CSS
1855
+ a { -\#{"foo"}-bar: b; }
1856
+ SCSS
1857
+ end
1858
+
1859
+ def test_star_plus_and_parent
1860
+ assert_equal <<CSS, render(<<SCSS)
1861
+ * + html foo {
1862
+ a: b; }
1863
+ CSS
1864
+ foo {*+html & {a: b}}
1865
+ SCSS
1866
+ end
1867
+
1868
+ def test_weird_added_space
1869
+ assert_equal <<CSS, render(<<SCSS)
1870
+ foo {
1871
+ bar: -moz-bip; }
1872
+ CSS
1873
+ $value : bip;
1874
+
1875
+ foo {
1876
+ bar: -moz-\#{$value};
1877
+ }
1878
+ SCSS
1879
+ end
1880
+
1881
+ def test_interpolation_with_bracket_on_next_line
1882
+ assert_equal <<CSS, render(<<SCSS)
1883
+ a.foo b {
1884
+ color: red; }
1885
+ CSS
1886
+ a.\#{"foo"} b
1887
+ {color: red}
1888
+ SCSS
1889
+ end
1890
+
1891
+ def test_extra_comma_in_mixin_arglist_error
1892
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1893
+ Invalid CSS after "...clude foo(bar, ": expected mixin argument, was ");"
1894
+ MESSAGE
1895
+ @mixin foo($a1, $a2) {
1896
+ baz: $a1 $a2;
1897
+ }
1898
+
1899
+ .bar {
1900
+ @include foo(bar, );
1901
+ }
1902
+ SCSS
1903
+ end
1904
+
1905
+ def test_interpolation
1906
+ assert_equal <<CSS, render(<<SCSS)
1907
+ ul li#foo a span.label {
1908
+ foo: bar; }
1909
+ CSS
1910
+ $bar : "#foo";
1911
+ ul li\#{$bar} a span.label { foo: bar; }
1912
+ SCSS
1913
+ end
1914
+
1915
+ def test_mixin_with_keyword_args
1916
+ assert_equal <<CSS, render(<<SCSS)
1917
+ .mixed {
1918
+ required: foo;
1919
+ arg1: default-val1;
1920
+ arg2: non-default-val2; }
1921
+ CSS
1922
+ @mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
1923
+ required: $required;
1924
+ arg1: $arg1;
1925
+ arg2: $arg2;
1926
+ }
1927
+ .mixed { @include a-mixin(foo, $arg2: non-default-val2); }
1928
+ SCSS
1929
+ end
1930
+
1931
+ def test_passing_required_args_as_a_keyword_arg
1932
+ assert_equal <<CSS, render(<<SCSS)
1933
+ .mixed {
1934
+ required: foo;
1935
+ arg1: default-val1;
1936
+ arg2: default-val2; }
1937
+ CSS
1938
+ @mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
1939
+ required: $required;
1940
+ arg1: $arg1;
1941
+ arg2: $arg2; }
1942
+ .mixed { @include a-mixin($required: foo); }
1943
+ SCSS
1944
+ end
1945
+
1946
+ def test_passing_all_as_keyword_args_in_opposite_order
1947
+ assert_equal <<CSS, render(<<SCSS)
1948
+ .mixed {
1949
+ required: foo;
1950
+ arg1: non-default-val1;
1951
+ arg2: non-default-val2; }
1952
+ CSS
1953
+ @mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
1954
+ required: $required;
1955
+ arg1: $arg1;
1956
+ arg2: $arg2; }
1957
+ .mixed { @include a-mixin($arg2: non-default-val2, $arg1: non-default-val1, $required: foo); }
1958
+ SCSS
1959
+ end
1960
+
1961
+ def test_keyword_args_in_functions
1962
+ assert_equal <<CSS, render(<<SCSS)
1963
+ .keyed {
1964
+ color: rgba(170, 119, 204, 0.4); }
1965
+ CSS
1966
+ .keyed { color: rgba($color: #a7c, $alpha: 0.4) }
1967
+ SCSS
1968
+ end
1969
+
1970
+ def test_unknown_keyword_arg_raises_error
1971
+ assert_raise_message(Sass::SyntaxError, "Mixin a doesn't have an argument named $c.") {render <<SCSS}
1972
+ @mixin a($b: 1) { a: $b; }
1973
+ div { @include a(1, $c: 3); }
1974
+ SCSS
1975
+ end
1976
+
1977
+
1978
+ def test_newlines_removed_from_selectors_when_compressed
1979
+ assert_equal <<CSS, render(<<SCSS, :style => :compressed)
1980
+ z a,z b{display:block}
1981
+ CSS
1982
+ a
1983
+ , b {
1984
+ z & {
1985
+ display: block;
1986
+ }
1987
+ }
1988
+ SCSS
1989
+ end
1990
+
1991
+ def test_if_error_line
1992
+ assert_raise_line(2) {render(<<SCSS)}
1993
+ @if true {foo: bar}
1994
+ }
1995
+ SCSS
1996
+ end
1997
+
1998
+ def test_multiline_var
1999
+ assert_equal <<CSS, render(<<SCSS)
2000
+ foo {
2001
+ a: 3;
2002
+ b: false;
2003
+ c: a b c; }
2004
+ CSS
2005
+ foo {
2006
+ $var1: 1 +
2007
+ 2;
2008
+ $var2: true and
2009
+ false;
2010
+ $var3: a b
2011
+ c;
2012
+ a: $var1;
2013
+ b: $var2;
2014
+ c: $var3; }
2015
+ SCSS
2016
+ end
2017
+
2018
+ def test_mixin_content
2019
+ assert_equal <<CSS, render(<<SASS)
2020
+ .parent {
2021
+ background-color: red;
2022
+ border-color: red; }
2023
+ .parent .child {
2024
+ background-color: yellow;
2025
+ color: blue;
2026
+ border-color: yellow; }
2027
+ CSS
2028
+ $color: blue;
2029
+ @mixin context($class, $color: red) {
2030
+ .\#{$class} {
2031
+ background-color: $color;
2032
+ @content;
2033
+ border-color: $color;
2034
+ }
2035
+ }
2036
+ @include context(parent) {
2037
+ @include context(child, $color: yellow) {
2038
+ color: $color;
2039
+ }
2040
+ }
2041
+ SASS
2042
+ end
2043
+
2044
+ def test_empty_content
2045
+ assert_equal <<CSS, render(<<SCSS)
2046
+ a {
2047
+ b: c; }
2048
+ CSS
2049
+ @mixin foo { @content }
2050
+ a { b: c; @include foo {} }
2051
+ SCSS
2052
+ end
2053
+
2054
+ def test_options_passed_to_script
2055
+ assert_equal <<CSS, render(<<SCSS, :style => :compressed)
2056
+ foo{color:#000}
2057
+ CSS
2058
+ foo {color: darken(black, 10%)}
2059
+ SCSS
2060
+ end
2061
+
2062
+ # ref: https://github.com/nex3/sass/issues/104
2063
+ def test_no_buffer_overflow
2064
+ template = render <<SCSS
2065
+ .aaa {
2066
+ background-color: white;
2067
+ }
2068
+ .aaa .aaa .aaa {
2069
+ background-color: black;
2070
+ }
2071
+ .bbb {
2072
+ @extend .aaa;
2073
+ }
2074
+ .xxx {
2075
+ @extend .bbb;
2076
+ }
2077
+ .yyy {
2078
+ @extend .bbb;
2079
+ }
2080
+ .zzz {
2081
+ @extend .bbb;
2082
+ }
2083
+ SCSS
2084
+ Sass::SCSS::Parser.new(template, "test.scss").parse
2085
+ end
2086
+
2087
+ def test_extend_in_media_in_rule
2088
+ assert_equal(<<CSS, render(<<SCSS))
2089
+ @media screen {
2090
+ .foo {
2091
+ a: b; } }
2092
+ CSS
2093
+ .foo {
2094
+ @media screen {
2095
+ @extend %bar;
2096
+ }
2097
+ }
2098
+
2099
+ @media screen {
2100
+ %bar {
2101
+ a: b;
2102
+ }
2103
+ }
2104
+ SCSS
2105
+ end
2106
+ end