haml 2.2.24 → 3.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of haml might be problematic. Click here for more details.

Files changed (168) hide show
  1. data/.yardopts +0 -1
  2. data/README.md +91 -151
  3. data/REMEMBER +11 -1
  4. data/Rakefile +73 -55
  5. data/VERSION +1 -1
  6. data/VERSION_NAME +1 -1
  7. data/bin/css2sass +7 -1
  8. data/bin/sass-convert +7 -0
  9. data/extra/haml-mode.el +2 -1
  10. data/lib/haml/buffer.rb +22 -4
  11. data/lib/haml/engine.rb +5 -1
  12. data/lib/haml/exec.rb +231 -46
  13. data/lib/haml/filters.rb +19 -8
  14. data/lib/haml/helpers.rb +47 -20
  15. data/lib/haml/helpers/action_view_extensions.rb +2 -4
  16. data/lib/haml/helpers/action_view_mods.rb +11 -8
  17. data/lib/haml/helpers/xss_mods.rb +13 -2
  18. data/lib/haml/html.rb +179 -48
  19. data/lib/haml/html/erb.rb +141 -0
  20. data/lib/haml/precompiler.rb +40 -15
  21. data/lib/haml/railtie.rb +1 -5
  22. data/lib/haml/root.rb +3 -0
  23. data/lib/haml/template.rb +4 -14
  24. data/lib/haml/util.rb +120 -30
  25. data/lib/haml/version.rb +25 -2
  26. data/lib/sass.rb +5 -1
  27. data/lib/sass/callbacks.rb +50 -0
  28. data/lib/sass/css.rb +40 -191
  29. data/lib/sass/engine.rb +170 -74
  30. data/lib/sass/environment.rb +8 -2
  31. data/lib/sass/error.rb +163 -25
  32. data/lib/sass/files.rb +31 -28
  33. data/lib/sass/plugin.rb +268 -87
  34. data/lib/sass/plugin/rails.rb +9 -4
  35. data/lib/sass/repl.rb +1 -1
  36. data/lib/sass/script.rb +31 -29
  37. data/lib/sass/script/bool.rb +1 -0
  38. data/lib/sass/script/color.rb +290 -23
  39. data/lib/sass/script/css_lexer.rb +22 -0
  40. data/lib/sass/script/css_parser.rb +28 -0
  41. data/lib/sass/script/funcall.rb +22 -3
  42. data/lib/sass/script/functions.rb +523 -33
  43. data/lib/sass/script/interpolation.rb +42 -0
  44. data/lib/sass/script/lexer.rb +169 -52
  45. data/lib/sass/script/literal.rb +58 -9
  46. data/lib/sass/script/node.rb +79 -1
  47. data/lib/sass/script/number.rb +20 -5
  48. data/lib/sass/script/operation.rb +49 -3
  49. data/lib/sass/script/parser.rb +162 -28
  50. data/lib/sass/script/string.rb +50 -2
  51. data/lib/sass/script/unary_operation.rb +25 -2
  52. data/lib/sass/script/variable.rb +21 -4
  53. data/lib/sass/scss.rb +14 -0
  54. data/lib/sass/scss/css_parser.rb +39 -0
  55. data/lib/sass/scss/parser.rb +683 -0
  56. data/lib/sass/scss/rx.rb +112 -0
  57. data/lib/sass/scss/script_lexer.rb +13 -0
  58. data/lib/sass/scss/script_parser.rb +25 -0
  59. data/lib/sass/tree/comment_node.rb +69 -27
  60. data/lib/sass/tree/debug_node.rb +7 -2
  61. data/lib/sass/tree/directive_node.rb +41 -35
  62. data/lib/sass/tree/for_node.rb +6 -0
  63. data/lib/sass/tree/if_node.rb +13 -1
  64. data/lib/sass/tree/import_node.rb +52 -27
  65. data/lib/sass/tree/mixin_def_node.rb +18 -0
  66. data/lib/sass/tree/mixin_node.rb +41 -6
  67. data/lib/sass/tree/node.rb +197 -70
  68. data/lib/sass/tree/prop_node.rb +152 -57
  69. data/lib/sass/tree/root_node.rb +118 -0
  70. data/lib/sass/tree/rule_node.rb +193 -96
  71. data/lib/sass/tree/variable_node.rb +9 -5
  72. data/lib/sass/tree/while_node.rb +4 -0
  73. data/test/benchmark.rb +5 -5
  74. data/test/haml/engine_test.rb +147 -10
  75. data/test/haml/{rhtml/_av_partial_1.rhtml → erb/_av_partial_1.erb} +1 -1
  76. data/test/haml/{rhtml/_av_partial_2.rhtml → erb/_av_partial_2.erb} +1 -1
  77. data/test/haml/{rhtml/action_view.rhtml → erb/action_view.erb} +1 -1
  78. data/test/haml/{rhtml/standard.rhtml → erb/standard.erb} +0 -0
  79. data/test/haml/helper_test.rb +91 -24
  80. data/test/haml/html2haml/erb_tests.rb +410 -0
  81. data/test/haml/html2haml_test.rb +210 -66
  82. data/test/haml/results/filters.xhtml +1 -1
  83. data/test/haml/results/just_stuff.xhtml +2 -0
  84. data/test/haml/spec_test.rb +44 -0
  85. data/test/haml/template_test.rb +22 -2
  86. data/test/haml/templates/helpers.haml +0 -13
  87. data/test/haml/templates/just_stuff.haml +2 -0
  88. data/test/haml/util_test.rb +48 -0
  89. data/test/sass/callbacks_test.rb +61 -0
  90. data/test/sass/conversion_test.rb +884 -0
  91. data/test/sass/css2sass_test.rb +99 -18
  92. data/test/sass/data/hsl-rgb.txt +319 -0
  93. data/test/sass/engine_test.rb +1049 -131
  94. data/test/sass/functions_test.rb +398 -47
  95. data/test/sass/more_results/more_import.css +1 -1
  96. data/test/sass/more_templates/more_import.sass +3 -3
  97. data/test/sass/plugin_test.rb +184 -10
  98. data/test/sass/results/compact.css +1 -1
  99. data/test/sass/results/complex.css +5 -5
  100. data/test/sass/results/compressed.css +1 -1
  101. data/test/sass/results/expanded.css +1 -1
  102. data/test/sass/results/import.css +3 -1
  103. data/test/sass/results/mixins.css +12 -12
  104. data/test/sass/results/nested.css +1 -1
  105. data/test/sass/results/options.css +1 -0
  106. data/test/sass/results/parent_ref.css +4 -4
  107. data/test/sass/results/script.css +3 -3
  108. data/test/sass/results/scss_import.css +15 -0
  109. data/test/sass/results/scss_importee.css +2 -0
  110. data/test/sass/script_conversion_test.rb +153 -0
  111. data/test/sass/script_test.rb +137 -70
  112. data/test/sass/scss/css_test.rb +811 -0
  113. data/test/sass/scss/rx_test.rb +156 -0
  114. data/test/sass/scss/scss_test.rb +871 -0
  115. data/test/sass/scss/test_helper.rb +37 -0
  116. data/test/sass/templates/alt.sass +2 -2
  117. data/test/sass/templates/bork1.sass +2 -0
  118. data/test/sass/templates/bork3.sass +2 -0
  119. data/test/sass/templates/bork4.sass +2 -0
  120. data/test/sass/templates/import.sass +4 -4
  121. data/test/sass/templates/importee.sass +3 -3
  122. data/test/sass/templates/line_numbers.sass +1 -1
  123. data/test/sass/templates/mixin_bork.sass +5 -0
  124. data/test/sass/templates/mixins.sass +2 -2
  125. data/test/sass/templates/nested_bork1.sass +2 -0
  126. data/test/sass/templates/nested_bork2.sass +2 -0
  127. data/test/sass/templates/nested_bork3.sass +2 -0
  128. data/test/sass/templates/nested_bork4.sass +2 -0
  129. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  130. data/test/sass/templates/options.sass +2 -0
  131. data/test/sass/templates/parent_ref.sass +2 -2
  132. data/test/sass/templates/script.sass +69 -69
  133. data/test/sass/templates/scss_import.scss +10 -0
  134. data/test/sass/templates/scss_importee.scss +1 -0
  135. data/test/sass/templates/units.sass +10 -10
  136. data/test/test_helper.rb +20 -8
  137. data/vendor/fssm/LICENSE +20 -0
  138. data/vendor/fssm/README.markdown +55 -0
  139. data/vendor/fssm/Rakefile +59 -0
  140. data/vendor/fssm/VERSION.yml +5 -0
  141. data/vendor/fssm/example.rb +9 -0
  142. data/vendor/fssm/fssm.gemspec +77 -0
  143. data/vendor/fssm/lib/fssm.rb +33 -0
  144. data/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  145. data/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  146. data/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  147. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  148. data/vendor/fssm/lib/fssm/monitor.rb +26 -0
  149. data/vendor/fssm/lib/fssm/path.rb +91 -0
  150. data/vendor/fssm/lib/fssm/pathname.rb +502 -0
  151. data/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  152. data/vendor/fssm/lib/fssm/state/file.rb +24 -0
  153. data/vendor/fssm/lib/fssm/support.rb +63 -0
  154. data/vendor/fssm/lib/fssm/tree.rb +176 -0
  155. data/vendor/fssm/profile/prof-cache.rb +40 -0
  156. data/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  157. data/vendor/fssm/profile/prof-pathname.rb +68 -0
  158. data/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  159. data/vendor/fssm/profile/prof.html +2379 -0
  160. data/vendor/fssm/spec/path_spec.rb +75 -0
  161. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  162. data/vendor/fssm/spec/root/file.css +0 -0
  163. data/vendor/fssm/spec/root/file.rb +0 -0
  164. data/vendor/fssm/spec/root/file.yml +0 -0
  165. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  166. data/vendor/fssm/spec/spec_helper.rb +14 -0
  167. metadata +94 -14
  168. data/test/sass/templates/bork.sass +0 -2
@@ -0,0 +1,811 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require File.dirname(__FILE__) + '/test_helper'
4
+ require 'sass/scss/css_parser'
5
+
6
+ # These tests just test the parsing of CSS
7
+ # (both standard and any hacks we intend to support).
8
+ # Tests of SCSS-specific behavior go in scss_test.rb.
9
+ class ScssCssTest < Test::Unit::TestCase
10
+ include ScssTestHelper
11
+
12
+ def test_basic_scss
13
+ assert_parses <<SCSS
14
+ selector {
15
+ property: value;
16
+ property2: value; }
17
+ SCSS
18
+
19
+ assert_equal <<CSS, render('sel{p:v}')
20
+ sel {
21
+ p: v; }
22
+ CSS
23
+ end
24
+
25
+ def test_empty_rule
26
+ assert_equal "", render("#foo .bar {}")
27
+ assert_equal "", render(<<SCSS)
28
+ #foo .bar {
29
+ }
30
+ SCSS
31
+ end
32
+
33
+ def test_cdo_and_cdc_ignored_at_toplevel
34
+ assert_equal <<CSS, render(<<SCSS)
35
+ foo {
36
+ bar: baz; }
37
+
38
+ bar {
39
+ bar: baz; }
40
+
41
+ baz {
42
+ bar: baz; }
43
+ CSS
44
+ foo {bar: baz}
45
+ <!--
46
+ bar {bar: baz}
47
+ -->
48
+ baz {bar: baz}
49
+ SCSS
50
+ end
51
+
52
+ def test_unicode
53
+ assert_parses <<SCSS
54
+ foo {
55
+ bar: föö bâr; }
56
+ SCSS
57
+ end
58
+
59
+ def test_invisible_comments
60
+ assert_equal <<CSS, render(<<SCSS)
61
+ foo {
62
+ a: d; }
63
+ CSS
64
+ foo {a: /* b; c: */ d}
65
+ SCSS
66
+ assert_equal <<CSS, render(<<SCSS)
67
+ foo {
68
+ a: d; }
69
+ CSS
70
+ foo {a /*: b; c */: d}
71
+ SCSS
72
+ end
73
+
74
+ def test_crazy_comments
75
+ # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/t040109-c17-comments-00-b.xht
76
+ assert_equal <<CSS, render(<<SCSS)
77
+ /* This is a CSS comment. */
78
+ .one {
79
+ color: green; }
80
+
81
+ /* Another comment */
82
+ /* The following should not be used:
83
+ .two {color: red;} */
84
+ .three {
85
+ color: green;
86
+ /* color: red; */ }
87
+
88
+ /**
89
+ .four {color: red;} */
90
+ .five {
91
+ color: green; }
92
+
93
+ /**/
94
+ .six {
95
+ color: green; }
96
+
97
+ /*********/
98
+ .seven {
99
+ color: green; }
100
+
101
+ /* a comment **/
102
+ .eight {
103
+ color: green; }
104
+ CSS
105
+ /* This is a CSS comment. */
106
+ .one {color: green;} /* Another comment */
107
+ /* The following should not be used:
108
+ .two {color: red;} */
109
+ .three {color: green; /* color: red; */}
110
+ /**
111
+ .four {color: red;} */
112
+ .five {color: green;}
113
+ /**/
114
+ .six {color: green;}
115
+ /*********/
116
+ .seven {color: green;}
117
+ /* a comment **/
118
+ .eight {color: green;}
119
+ SCSS
120
+ end
121
+
122
+ def test_rule_comments
123
+ assert_parses <<SCSS
124
+ /* Foo */
125
+ .foo {
126
+ a: b; }
127
+ SCSS
128
+ assert_equal <<CSS, render(<<SCSS)
129
+ /* Foo
130
+ * Bar */
131
+ .foo {
132
+ a: b; }
133
+ CSS
134
+ /* Foo
135
+ * Bar */.foo {
136
+ a: b; }
137
+ SCSS
138
+ end
139
+
140
+ def test_property_comments
141
+ assert_parses <<SCSS
142
+ .foo {
143
+ /* Foo */
144
+ a: b; }
145
+ SCSS
146
+ assert_equal <<CSS, render(<<SCSS)
147
+ .foo {
148
+ /* Foo
149
+ * Bar */
150
+ a: b; }
151
+ CSS
152
+ .foo {
153
+ /* Foo
154
+ * Bar */a: b; }
155
+ SCSS
156
+ end
157
+
158
+ def test_selector_comments
159
+ assert_equal <<CSS, render(<<SCSS)
160
+ .foo #bar:baz( bip) {
161
+ a: b; }
162
+ CSS
163
+ .foo /* .a #foo */ #bar:baz(/* bang )*/ bip) {
164
+ a: b; }
165
+ SCSS
166
+ end
167
+
168
+ def test_lonely_comments
169
+ assert_parses <<SCSS
170
+ /* Foo
171
+ * Bar */
172
+ SCSS
173
+ assert_parses <<SCSS
174
+ .foo {
175
+ /* Foo
176
+ * Bar */ }
177
+ SCSS
178
+ end
179
+
180
+ def test_multiple_comments
181
+ assert_parses <<SCSS
182
+ /* Foo
183
+ * Bar */
184
+ /* Baz
185
+ * Bang */
186
+ SCSS
187
+ assert_parses <<SCSS
188
+ .foo {
189
+ /* Foo
190
+ * Bar */
191
+ /* Baz
192
+ * Bang */ }
193
+ SCSS
194
+ assert_equal <<CSS, render(<<SCSS)
195
+ .foo {
196
+ /* Foo Bar */
197
+ /* Baz Bang */ }
198
+ CSS
199
+ .foo {
200
+ /* Foo Bar *//* Baz Bang */ }
201
+ SCSS
202
+ end
203
+
204
+ def test_bizarrely_formatted_comments
205
+ assert_parses <<SCSS
206
+ .foo {
207
+ /* Foo
208
+ Bar
209
+ Baz */
210
+ a: b; }
211
+ SCSS
212
+ assert_parses <<SCSS
213
+ .foo {
214
+ /* Foo
215
+ Bar
216
+ Baz */
217
+ a: b; }
218
+ SCSS
219
+ assert_equal <<CSS, render(<<SCSS)
220
+ .foo {
221
+ /* Foo
222
+ Bar */
223
+ a: b; }
224
+ CSS
225
+ .foo {/* Foo
226
+ Bar */
227
+ a: b; }
228
+ SCSS
229
+ assert_equal <<CSS, render(<<SCSS)
230
+ .foo {
231
+ /* Foo
232
+ Bar
233
+ Baz */
234
+ a: b; }
235
+ CSS
236
+ .foo {/* Foo
237
+ Bar
238
+ Baz */
239
+ a: b; }
240
+ SCSS
241
+ end
242
+
243
+ ## Declarations
244
+
245
+ def test_vendor_properties
246
+ assert_parses <<SCSS
247
+ foo {
248
+ -moz-foo-bar: blat;
249
+ -o-flat-blang: wibble; }
250
+ SCSS
251
+ end
252
+
253
+ def test_empty_declarations
254
+ assert_equal <<CSS, render(<<SCSS)
255
+ foo {
256
+ bar: baz; }
257
+ CSS
258
+ foo {;;;;
259
+ bar: baz;;;;
260
+ ;;}
261
+ SCSS
262
+ end
263
+
264
+ def test_basic_property_types
265
+ assert_parses <<SCSS
266
+ foo {
267
+ a: 2;
268
+ b: 2.3em;
269
+ c: 50%;
270
+ d: "fraz bran";
271
+ e: flanny-blanny-blan;
272
+ f: url(http://sass-lang.com);
273
+ g: U+ffa?;
274
+ h: #aabbcc; }
275
+ SCSS
276
+ end
277
+
278
+ def test_functions
279
+ assert_parses <<SCSS
280
+ foo {
281
+ a: foo-bar(12);
282
+ b: -foo-bar-baz(13, 14 15); }
283
+ SCSS
284
+ end
285
+
286
+ def test_unary_minus
287
+ assert_parses <<SCSS
288
+ foo {
289
+ a: -2;
290
+ b: -2.3em;
291
+ c: -50%;
292
+ d: -foo(bar baz); }
293
+ SCSS
294
+ end
295
+
296
+ def test_operators
297
+ assert_parses <<SCSS
298
+ foo {
299
+ a: foo bar baz;
300
+ b: foo, #aabbcc, -12;
301
+ c: 1px/2px/-3px;
302
+ d: foo bar, baz/bang; }
303
+ SCSS
304
+ end
305
+
306
+ def test_important
307
+ assert_parses <<SCSS
308
+ foo {
309
+ a: foo !important;
310
+ b: foo bar !important;
311
+ b: foo, bar !important; }
312
+ SCSS
313
+ end
314
+
315
+ def test_initial_hyphen
316
+ assert_parses <<SCSS
317
+ foo {
318
+ a: -moz-bar-baz;
319
+ b: foo -o-bar-baz; }
320
+ SCSS
321
+ end
322
+
323
+ def test_ms_filter_syntax
324
+ assert_equal <<CSS, render(<<SCSS)
325
+ foo {
326
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000);
327
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); }
328
+ CSS
329
+ foo {
330
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000);
331
+ filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); }
332
+ SCSS
333
+ end
334
+
335
+ def test_declaration_hacks
336
+ assert_parses <<SCSS
337
+ foo {
338
+ _name: val;
339
+ *name: val;
340
+ :name: val;
341
+ .name: val;
342
+ name: val; }
343
+ SCSS
344
+ end
345
+
346
+ def test_zero_arg_functions
347
+ assert_parses <<SCSS
348
+ foo {
349
+ a: foo();
350
+ b: bar baz-bang() bip; }
351
+ SCSS
352
+ end
353
+
354
+ def test_expression_function
355
+ assert_parses <<SCSS
356
+ foo {
357
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
358
+ SCSS
359
+ end
360
+
361
+ def test_calc_function
362
+ assert_parses <<SCSS
363
+ foo {
364
+ a: 12px calc(100%/3 - 2*1em - 2*1px); }
365
+ SCSS
366
+ end
367
+
368
+ def test_unary_ops
369
+ assert_equal <<CSS, render(<<SCSS)
370
+ foo {
371
+ a: -0.5em;
372
+ b: 0.5em;
373
+ c: -foo(12px);
374
+ d: +foo(12px); }
375
+ CSS
376
+ foo {
377
+ a: -0.5em;
378
+ b: +0.5em;
379
+ c: -foo(12px);
380
+ d: +foo(12px); }
381
+ SCSS
382
+ end
383
+
384
+ ## Directives
385
+
386
+ def test_charset_directive
387
+ assert_parses '@charset "utf-8";'
388
+ end
389
+
390
+ def test_namespace_directive
391
+ assert_parses '@namespace "http://www.w3.org/Profiles/xhtml1-strict";'
392
+ assert_parses '@namespace url(http://www.w3.org/Profiles/xhtml1-strict);'
393
+ assert_parses '@namespace html url("http://www.w3.org/Profiles/xhtml1-strict");'
394
+ end
395
+
396
+ def test_media_directive
397
+ assert_parses <<SCSS
398
+ @media all {
399
+ rule1 {
400
+ prop: val; }
401
+
402
+ rule2 {
403
+ prop: val; } }
404
+ SCSS
405
+ assert_parses <<SCSS
406
+ @media screen, print {
407
+ rule1 {
408
+ prop: val; }
409
+
410
+ rule2 {
411
+ prop: val; } }
412
+ SCSS
413
+ end
414
+
415
+ def test_media_directive_with_keywords
416
+ assert_parses <<SCSS
417
+ @media screen and (-webkit-min-device-pixel-ratio:0) {
418
+ a: b; }
419
+ SCSS
420
+ assert_parses <<SCSS
421
+ @media only screen, print and (foo: 0px) and (bar: flam(12px solid)) {
422
+ a: b; }
423
+ SCSS
424
+ end
425
+
426
+ def test_import_directive
427
+ assert_parses '@import "foo.css";'
428
+ assert_parses "@import 'foo.css';"
429
+ assert_parses '@import url("foo.css");'
430
+ assert_parses "@import url('foo.css');"
431
+ assert_parses '@import url(foo.css);'
432
+ end
433
+
434
+ def test_import_directive_with_media
435
+ assert_parses '@import "foo.css" screen;'
436
+ assert_parses '@import "foo.css" screen, print;'
437
+ assert_parses '@import "foo.css" screen, print and (foo: 0);'
438
+ assert_parses '@import "foo.css" screen, only print, screen and (foo: 0);'
439
+ end
440
+
441
+ def test_page_directive
442
+ assert_parses <<SCSS
443
+ @page {
444
+ prop1: val;
445
+ prop2: val; }
446
+ SCSS
447
+ assert_parses <<SCSS
448
+ @page flap {
449
+ prop1: val;
450
+ prop2: val; }
451
+ SCSS
452
+ assert_parses <<SCSS
453
+ @page :first {
454
+ prop1: val;
455
+ prop2: val; }
456
+ SCSS
457
+ assert_parses <<SCSS
458
+ @page flap:first {
459
+ prop1: val;
460
+ prop2: val; }
461
+ SCSS
462
+ end
463
+
464
+ def test_blockless_directive_without_semicolon
465
+ assert_equal "@charset \"utf-8\";\n", render('@charset "utf-8"')
466
+ end
467
+
468
+ def test_directive_with_lots_of_whitespace
469
+ assert_equal "@charset \"utf-16\";\n", render('@charset "utf-16" ;')
470
+ end
471
+
472
+ def test_empty_blockless_directive
473
+ assert_parses "@foo;"
474
+ end
475
+
476
+ def test_multiple_blockless_directives
477
+ assert_parses <<SCSS
478
+ @foo bar;
479
+ @bar baz;
480
+ SCSS
481
+ end
482
+
483
+ def test_empty_block_directive
484
+ assert_parses "@foo {}"
485
+ assert_equal "@foo {}\n", render(<<SCSS)
486
+ @foo {
487
+ }
488
+ SCSS
489
+ end
490
+
491
+ def test_multiple_block_directives
492
+ assert_parses <<SCSS
493
+ @foo bar {
494
+ a: b; }
495
+
496
+ @bar baz {
497
+ c: d; }
498
+ SCSS
499
+ end
500
+
501
+ def test_block_directive_with_rule_and_property
502
+ assert_parses <<SCSS
503
+ @foo {
504
+ rule {
505
+ a: b; }
506
+
507
+ a: b; }
508
+ SCSS
509
+ end
510
+
511
+ def test_block_directive_with_semicolon
512
+ assert_equal <<CSS, render(<<SCSS)
513
+ @foo {
514
+ a: b; }
515
+
516
+ @bar {
517
+ a: b; }
518
+ CSS
519
+ @foo {a:b};
520
+ @bar {a:b};
521
+ SCSS
522
+ end
523
+
524
+ ## Selectors
525
+
526
+ # Taken from http://www.w3.org/TR/css3-selectors/#selectors
527
+ def test_summarized_selectors
528
+ assert_selector_parses('*')
529
+ assert_selector_parses('E')
530
+ assert_selector_parses('E[foo]')
531
+ assert_selector_parses('E[foo="bar"]')
532
+ assert_selector_parses('E[foo~="bar"]')
533
+ assert_selector_parses('E[foo^="bar"]')
534
+ assert_selector_parses('E[foo$="bar"]')
535
+ assert_selector_parses('E[foo*="bar"]')
536
+ assert_selector_parses('E[foo|="en"]')
537
+ assert_selector_parses('E:root')
538
+ assert_selector_parses('E:nth-child(n)')
539
+ assert_selector_parses('E:nth-last-child(n)')
540
+ assert_selector_parses('E:nth-of-type(n)')
541
+ assert_selector_parses('E:nth-last-of-type(n)')
542
+ assert_selector_parses('E:first-child')
543
+ assert_selector_parses('E:last-child')
544
+ assert_selector_parses('E:first-of-type')
545
+ assert_selector_parses('E:last-of-type')
546
+ assert_selector_parses('E:only-child')
547
+ assert_selector_parses('E:only-of-type')
548
+ assert_selector_parses('E:empty')
549
+ assert_selector_parses('E:link')
550
+ assert_selector_parses('E:visited')
551
+ assert_selector_parses('E:active')
552
+ assert_selector_parses('E:hover')
553
+ assert_selector_parses('E:focus')
554
+ assert_selector_parses('E:target')
555
+ assert_selector_parses('E:lang(fr)')
556
+ assert_selector_parses('E:enabled')
557
+ assert_selector_parses('E:disabled')
558
+ assert_selector_parses('E:checked')
559
+ assert_selector_parses('E::first-line')
560
+ assert_selector_parses('E::first-letter')
561
+ assert_selector_parses('E::before')
562
+ assert_selector_parses('E::after')
563
+ assert_selector_parses('E.warning')
564
+ assert_selector_parses('E#myid')
565
+ assert_selector_parses('E:not(s)')
566
+ assert_selector_parses('E F')
567
+ assert_selector_parses('E > F')
568
+ assert_selector_parses('E + F')
569
+ assert_selector_parses('E ~ F')
570
+ end
571
+
572
+ # Taken from http://www.w3.org/TR/css3-selectors/#selectors,
573
+ # but without the element names
574
+ def test_lonely_selectors
575
+ assert_selector_parses('[foo]')
576
+ assert_selector_parses('[foo="bar"]')
577
+ assert_selector_parses('[foo~="bar"]')
578
+ assert_selector_parses('[foo^="bar"]')
579
+ assert_selector_parses('[foo$="bar"]')
580
+ assert_selector_parses('[foo*="bar"]')
581
+ assert_selector_parses('[foo|="en"]')
582
+ assert_selector_parses(':root')
583
+ assert_selector_parses(':nth-child(n)')
584
+ assert_selector_parses(':nth-last-child(n)')
585
+ assert_selector_parses(':nth-of-type(n)')
586
+ assert_selector_parses(':nth-last-of-type(n)')
587
+ assert_selector_parses(':first-child')
588
+ assert_selector_parses(':last-child')
589
+ assert_selector_parses(':first-of-type')
590
+ assert_selector_parses(':last-of-type')
591
+ assert_selector_parses(':only-child')
592
+ assert_selector_parses(':only-of-type')
593
+ assert_selector_parses(':empty')
594
+ assert_selector_parses(':link')
595
+ assert_selector_parses(':visited')
596
+ assert_selector_parses(':active')
597
+ assert_selector_parses(':hover')
598
+ assert_selector_parses(':focus')
599
+ assert_selector_parses(':target')
600
+ assert_selector_parses(':lang(fr)')
601
+ assert_selector_parses(':enabled')
602
+ assert_selector_parses(':disabled')
603
+ assert_selector_parses(':checked')
604
+ assert_selector_parses('::first-line')
605
+ assert_selector_parses('::first-letter')
606
+ assert_selector_parses('::before')
607
+ assert_selector_parses('::after')
608
+ assert_selector_parses('.warning')
609
+ assert_selector_parses('#myid')
610
+ assert_selector_parses(':not(s)')
611
+ end
612
+
613
+ def test_attribute_selectors_with_identifiers
614
+ assert_selector_parses('[foo~=bar]')
615
+ assert_selector_parses('[foo^=bar]')
616
+ assert_selector_parses('[foo$=bar]')
617
+ assert_selector_parses('[foo*=bar]')
618
+ assert_selector_parses('[foo|=en]')
619
+ end
620
+
621
+ def test_nth_selectors
622
+ assert_selector_parses(':nth-child(-n)')
623
+ assert_selector_parses(':nth-child(+n)')
624
+
625
+ assert_selector_parses(':nth-child(even)')
626
+ assert_selector_parses(':nth-child(odd)')
627
+
628
+ assert_selector_parses(':nth-child(50)')
629
+ assert_selector_parses(':nth-child(-50)')
630
+ assert_selector_parses(':nth-child(+50)')
631
+
632
+ assert_selector_parses(':nth-child(2n+3)')
633
+ assert_selector_parses(':nth-child(2n-3)')
634
+ assert_selector_parses(':nth-child(+2n-3)')
635
+ assert_selector_parses(':nth-child(-2n+3)')
636
+ assert_selector_parses(':nth-child(-2n+ 3)')
637
+ assert_selector_parses(':nth-child( 2n + 3 )')
638
+ end
639
+
640
+ def test_negation_selectors
641
+ assert_selector_parses(':not(foo|bar)')
642
+ assert_selector_parses(':not(*|bar)')
643
+
644
+ assert_selector_parses(':not(foo|*)')
645
+ assert_selector_parses(':not(*|*)')
646
+
647
+ assert_selector_parses(':not(#blah)')
648
+ assert_selector_parses(':not(.blah)')
649
+
650
+ assert_selector_parses(':not([foo])')
651
+ assert_selector_parses(':not([foo^="bar"])')
652
+ assert_selector_parses(':not([baz|foo~="bar"])')
653
+
654
+ assert_selector_parses(':not(:hover)')
655
+ assert_selector_parses(':not(:nth-child(2n + 3))')
656
+ end
657
+
658
+ def test_namespaced_selectors
659
+ assert_selector_parses('foo|E')
660
+ assert_selector_parses('*|E')
661
+ assert_selector_parses('foo|*')
662
+ assert_selector_parses('*|*')
663
+ end
664
+
665
+ def test_namespaced_attribute_selectors
666
+ assert_selector_parses('[foo|bar=baz]')
667
+ assert_selector_parses('[*|bar=baz]')
668
+ assert_selector_parses('[foo|bar|=baz]')
669
+ end
670
+
671
+ def test_comma_selectors
672
+ assert_selector_parses('E, F')
673
+ assert_selector_parses('E F, G H')
674
+ assert_selector_parses('E > F, G > H')
675
+ end
676
+
677
+ def test_selectors_with_newlines
678
+ assert_selector_parses("E,\nF")
679
+ assert_selector_parses("E\nF")
680
+ assert_selector_parses("E, F\nG, H")
681
+ end
682
+
683
+ def test_expression_fallback_selectors
684
+ assert_selector_parses('0%')
685
+ assert_selector_parses('60%')
686
+ assert_selector_parses('100%')
687
+ assert_selector_parses('12px')
688
+ assert_selector_parses('"foo"')
689
+ end
690
+
691
+ def test_functional_pseudo_selectors
692
+ assert_selector_parses(':foo("bar")')
693
+ assert_selector_parses(':foo(bar)')
694
+ assert_selector_parses(':foo(12px)')
695
+ assert_selector_parses(':foo(+)')
696
+ assert_selector_parses(':foo(-)')
697
+ assert_selector_parses(':foo(+"bar")')
698
+ assert_selector_parses(':foo(-++--baz-"bar"12px)')
699
+ end
700
+
701
+ def test_selector_hacks
702
+ assert_selector_parses('> E')
703
+ assert_selector_parses('+ E')
704
+ assert_selector_parses('~ E')
705
+ assert_selector_parses('>> E')
706
+
707
+ assert_selector_parses('E*')
708
+ assert_selector_parses('E*.foo')
709
+ assert_selector_parses('E*:hover')
710
+ end
711
+
712
+ ## Errors
713
+
714
+ def test_invalid_directives
715
+ assert_not_parses("identifier", '@<err> import "foo";')
716
+ assert_not_parses("identifier", '@<err>12 "foo";')
717
+ end
718
+
719
+ def test_invalid_classes
720
+ assert_not_parses("identifier", 'p.<err> foo {a: b}')
721
+ assert_not_parses("identifier", 'p.<err>1foo {a: b}')
722
+ end
723
+
724
+ def test_invalid_ids
725
+ assert_not_parses('"{"', 'p<err># foo {a: b}')
726
+ end
727
+
728
+ def test_no_properties_at_toplevel
729
+ assert_not_parses('pseudoclass or pseudoelement', 'a:<err> b;')
730
+ end
731
+
732
+ def test_no_scss_directives
733
+ assert_parses('@import "foo.sass";')
734
+ assert_parses <<SCSS
735
+ @mixin foo {
736
+ a: b; }
737
+ SCSS
738
+ end
739
+
740
+ def test_no_variables
741
+ assert_not_parses("selector or at-rule", "<err>$var = 12;")
742
+ assert_not_parses('"}"', "foo { <err>!var = 12; }")
743
+ end
744
+
745
+ def test_no_parent_selectors
746
+ assert_not_parses('"{"', "foo <err>&.bar {a: b}")
747
+ end
748
+
749
+ def test_no_selector_interpolation
750
+ assert_not_parses('"{"', 'foo <err>#{"bar"}.baz {a: b}')
751
+ end
752
+
753
+ def test_no_prop_name_interpolation
754
+ assert_not_parses('":"', 'foo {a<err>#{"bar"}baz: b}')
755
+ end
756
+
757
+ def test_no_prop_val_interpolation
758
+ assert_not_parses('"}"', 'foo {a: b <err>#{"bar"} c}')
759
+ end
760
+
761
+ def test_no_string_interpolation
762
+ assert_parses <<SCSS
763
+ foo {
764
+ a: "bang \#{1 + " bar "} bip"; }
765
+ SCSS
766
+ end
767
+
768
+ def test_no_sass_script_values
769
+ assert_not_parses('"}"', 'foo {a: b <err>* c}')
770
+ end
771
+
772
+ def test_no_nested_rules
773
+ assert_not_parses('":"', 'foo {bar <err>{a: b}}')
774
+ assert_not_parses('"}"', 'foo {<err>#bar {a: b}}')
775
+ end
776
+
777
+ def test_no_nested_properties
778
+ assert_not_parses('expression (e.g. 1px, bold)', 'foo {bar: <err>{a: b}}')
779
+ assert_not_parses('expression (e.g. 1px, bold)', 'foo {bar: bang <err>{a: b}}')
780
+ end
781
+
782
+ def test_no_nested_directives
783
+ assert_not_parses('"}"', 'foo {<err>@bar {a: b}}')
784
+ end
785
+
786
+ def test_error_with_windows_newlines
787
+ render <<SCSS
788
+ foo {bar}\r
789
+ baz {a: b}
790
+ SCSS
791
+ assert(false, "Expected syntax error")
792
+ rescue Sass::SyntaxError => e
793
+ assert_equal 'Invalid CSS after "foo {bar": expected ":", was "}"', e.message
794
+ assert_equal 1, e.sass_line
795
+ end
796
+
797
+ private
798
+
799
+ def assert_selector_parses(selector)
800
+ assert_parses <<SCSS
801
+ #{selector} {
802
+ a: b; }
803
+ SCSS
804
+ end
805
+
806
+ def render(scss, options = {})
807
+ tree = Sass::SCSS::CssParser.new(scss).parse
808
+ tree.options = Sass::Engine::DEFAULT_OPTIONS.merge(options)
809
+ tree.render
810
+ end
811
+ end