haml-edge 2.3.179 → 2.3.180

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/README.md +88 -149
  3. data/VERSION +1 -1
  4. data/bin/css2sass +7 -1
  5. data/bin/sass-convert +7 -0
  6. data/lib/haml/exec.rb +95 -22
  7. data/lib/haml/template.rb +1 -1
  8. data/lib/haml/util.rb +50 -0
  9. data/lib/sass.rb +1 -1
  10. data/lib/sass/css.rb +38 -210
  11. data/lib/sass/engine.rb +121 -47
  12. data/lib/sass/files.rb +28 -19
  13. data/lib/sass/plugin.rb +32 -43
  14. data/lib/sass/repl.rb +1 -1
  15. data/lib/sass/script.rb +25 -6
  16. data/lib/sass/script/bool.rb +1 -0
  17. data/lib/sass/script/color.rb +2 -2
  18. data/lib/sass/script/css_lexer.rb +22 -0
  19. data/lib/sass/script/css_parser.rb +28 -0
  20. data/lib/sass/script/funcall.rb +17 -9
  21. data/lib/sass/script/functions.rb +46 -1
  22. data/lib/sass/script/interpolation.rb +42 -0
  23. data/lib/sass/script/lexer.rb +142 -34
  24. data/lib/sass/script/literal.rb +28 -12
  25. data/lib/sass/script/node.rb +57 -1
  26. data/lib/sass/script/number.rb +18 -3
  27. data/lib/sass/script/operation.rb +44 -8
  28. data/lib/sass/script/parser.rb +149 -24
  29. data/lib/sass/script/string.rb +50 -2
  30. data/lib/sass/script/unary_operation.rb +25 -10
  31. data/lib/sass/script/variable.rb +20 -11
  32. data/lib/sass/scss.rb +14 -0
  33. data/lib/sass/scss/css_parser.rb +39 -0
  34. data/lib/sass/scss/parser.rb +683 -0
  35. data/lib/sass/scss/rx.rb +112 -0
  36. data/lib/sass/scss/script_lexer.rb +13 -0
  37. data/lib/sass/scss/script_parser.rb +25 -0
  38. data/lib/sass/tree/comment_node.rb +58 -16
  39. data/lib/sass/tree/debug_node.rb +7 -2
  40. data/lib/sass/tree/directive_node.rb +38 -34
  41. data/lib/sass/tree/for_node.rb +6 -0
  42. data/lib/sass/tree/if_node.rb +13 -0
  43. data/lib/sass/tree/import_node.rb +26 -7
  44. data/lib/sass/tree/mixin_def_node.rb +18 -0
  45. data/lib/sass/tree/mixin_node.rb +16 -1
  46. data/lib/sass/tree/node.rb +98 -27
  47. data/lib/sass/tree/prop_node.rb +97 -20
  48. data/lib/sass/tree/root_node.rb +37 -0
  49. data/lib/sass/tree/rule_node.rb +88 -60
  50. data/lib/sass/tree/variable_node.rb +9 -5
  51. data/lib/sass/tree/while_node.rb +4 -0
  52. data/test/haml/results/filters.xhtml +1 -1
  53. data/test/haml/util_test.rb +28 -0
  54. data/test/sass/conversion_test.rb +884 -0
  55. data/test/sass/css2sass_test.rb +46 -21
  56. data/test/sass/engine_test.rb +680 -160
  57. data/test/sass/functions_test.rb +27 -0
  58. data/test/sass/more_results/more_import.css +1 -1
  59. data/test/sass/more_templates/more_import.sass +3 -3
  60. data/test/sass/plugin_test.rb +28 -8
  61. data/test/sass/results/compact.css +1 -1
  62. data/test/sass/results/complex.css +5 -5
  63. data/test/sass/results/compressed.css +1 -1
  64. data/test/sass/results/expanded.css +1 -1
  65. data/test/sass/results/import.css +3 -1
  66. data/test/sass/results/mixins.css +12 -12
  67. data/test/sass/results/nested.css +1 -1
  68. data/test/sass/results/parent_ref.css +4 -4
  69. data/test/sass/results/script.css +3 -3
  70. data/test/sass/results/scss_import.css +15 -0
  71. data/test/sass/results/scss_importee.css +2 -0
  72. data/test/sass/script_conversion_test.rb +153 -0
  73. data/test/sass/script_test.rb +44 -54
  74. data/test/sass/scss/css_test.rb +811 -0
  75. data/test/sass/scss/rx_test.rb +156 -0
  76. data/test/sass/scss/scss_test.rb +871 -0
  77. data/test/sass/scss/test_helper.rb +37 -0
  78. data/test/sass/templates/alt.sass +2 -2
  79. data/test/sass/templates/bork1.sass +1 -1
  80. data/test/sass/templates/import.sass +4 -4
  81. data/test/sass/templates/importee.sass +3 -3
  82. data/test/sass/templates/line_numbers.sass +1 -1
  83. data/test/sass/templates/mixins.sass +2 -2
  84. data/test/sass/templates/nested_mixin_bork.sass +1 -1
  85. data/test/sass/templates/options.sass +1 -1
  86. data/test/sass/templates/parent_ref.sass +2 -2
  87. data/test/sass/templates/script.sass +69 -69
  88. data/test/sass/templates/scss_import.scss +10 -0
  89. data/test/sass/templates/scss_importee.scss +1 -0
  90. data/test/sass/templates/units.sass +10 -10
  91. data/test/test_helper.rb +4 -4
  92. metadata +27 -2
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require File.dirname(__FILE__) + '/../../test_helper'
4
+ require 'sass/engine'
5
+
6
+ class ScssRxTest < Test::Unit::TestCase
7
+ include Sass::SCSS::RX
8
+
9
+ def test_identifiers
10
+ assert_match IDENT, "foo"
11
+ assert_match IDENT, "\xC3\xBFoo" # Initial char can be nonascii
12
+ assert_match IDENT, "\\123abcoo" # Initial char can be unicode escape
13
+ assert_match IDENT, "\\f oo" # Unicode escapes can be followed by whitespace
14
+ assert_match IDENT, "\\fa\too"
15
+ assert_match IDENT, "\\ff2\roo"
16
+ assert_match IDENT, "\\f13a\foo"
17
+ assert_match IDENT, "\\f13abcoo"
18
+ assert_match IDENT, "\\ oo" # Initial char can be a plain escape as well
19
+ assert_match IDENT, "\\~oo"
20
+ assert_match IDENT, "\\\\oo"
21
+ assert_match IDENT, "\\{oo"
22
+ assert_match IDENT, "\\\xC3\xBFoo"
23
+ assert_match IDENT, "-foo" # Can put a - before anything
24
+ assert_match IDENT, "-\xC3\xBFoo"
25
+ assert_match IDENT, "-\\f oo"
26
+ assert_match IDENT, "_foo" # Can put a _ before anything
27
+ assert_match IDENT, "_\xC3\xBFoo"
28
+ assert_match IDENT, "_\\f oo"
29
+
30
+ assert_match IDENT, "foo-bar"
31
+ assert_match IDENT, "f012-23"
32
+ assert_match IDENT, "foo_-_bar"
33
+ assert_match IDENT, "f012_23"
34
+
35
+ # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-003.xht
36
+ assert_match IDENT, "c\\lass"
37
+ # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-004.xht
38
+ assert_match IDENT, "c\\00006Cas\\000073"
39
+ # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-001.xht
40
+ assert_match IDENT, "IdE6n-3t0_6"
41
+ # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-006.xht
42
+ assert_match IDENT, "\\6000ident"
43
+ # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-007.xht
44
+ assert_match IDENT, "iden\\6000t\\6000"
45
+ # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-013.xht
46
+ assert_match IDENT, "\\-ident"
47
+ end
48
+
49
+ def test_underscores_in_identifiers
50
+ assert_match IDENT, "foo_bar"
51
+ assert_match IDENT, "_\xC3\xBFfoo"
52
+ end
53
+
54
+ def test_invalid_identifiers
55
+ assert_no_match IDENT, ""
56
+ assert_no_match IDENT, "1foo"
57
+ assert_no_match IDENT, "-1foo"
58
+ assert_no_match IDENT, "--foo"
59
+ assert_no_match IDENT, "_1foo"
60
+ assert_no_match IDENT, "__foo"
61
+ assert_no_match IDENT, "-_foo"
62
+ assert_no_match IDENT, "_-foo"
63
+ assert_no_match IDENT, "foo bar"
64
+ assert_no_match IDENT, "foo~bar"
65
+
66
+ # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-008.xht
67
+ assert_no_match IDENT, "c\\06C ass"
68
+ assert_no_match IDENT, "back\\67\n round"
69
+ end
70
+
71
+ def test_double_quote_strings
72
+ assert_match STRING, '"foo bar"'
73
+ assert_match STRING, '"foo\\\nbar"'
74
+ assert_match STRING, "\"\\\"\""
75
+ assert_match STRING, '"\t !#$%&(-~()*+,-./0123456789~"'
76
+ end
77
+
78
+ def test_single_quote_strings
79
+ assert_match STRING, "'foo bar'"
80
+ assert_match STRING, "'foo\\\nbar'"
81
+ assert_match STRING, "'\\''"
82
+ assert_match STRING, "'\t !#\$%&(-~()*+,-./0123456789~'"
83
+ end
84
+
85
+ def test_invalid_strings
86
+ assert_no_match STRING, "\"foo\nbar\""
87
+ assert_no_match STRING, "\"foo\"bar\""
88
+ assert_no_match STRING, "'foo\nbar'"
89
+ assert_no_match STRING, "'foo'bar'"
90
+ end
91
+
92
+ def test_uri
93
+ assert_match URI, 'url("foo bar)")'
94
+ assert_match URI, "url('foo bar)')"
95
+ assert_match URI, 'url( "foo bar)" )'
96
+ assert_match URI, "url(!#\$%&**+,-./0123456789~)"
97
+ end
98
+
99
+ def test_invalid_uri
100
+ assert_no_match URI, 'url(foo)bar)'
101
+ end
102
+
103
+ def test_unicode_range
104
+ assert_match UNICODERANGE, 'U+00-Ff'
105
+ assert_match UNICODERANGE, 'u+980-9FF'
106
+ assert_match UNICODERANGE, 'U+9aF??'
107
+ assert_match UNICODERANGE, 'U+??'
108
+ end
109
+
110
+ def test_escape_empty_ident
111
+ assert_equal "", Sass::SCSS::RX.escape_ident("")
112
+ end
113
+
114
+ def test_escape_just_prefix_ident
115
+ assert_equal "\\-", Sass::SCSS::RX.escape_ident("-")
116
+ assert_equal "\\_", Sass::SCSS::RX.escape_ident("_")
117
+ end
118
+
119
+ def test_escape_plain_ident
120
+ assert_equal "foo", Sass::SCSS::RX.escape_ident("foo")
121
+ assert_equal "foo-1bar", Sass::SCSS::RX.escape_ident("foo-1bar")
122
+ assert_equal "-foo-bar", Sass::SCSS::RX.escape_ident("-foo-bar")
123
+ assert_equal "f2oo_bar", Sass::SCSS::RX.escape_ident("f2oo_bar")
124
+ assert_equal "_foo_bar", Sass::SCSS::RX.escape_ident("_foo_bar")
125
+ end
126
+
127
+ def test_escape_initial_funky_ident
128
+ assert_equal "\\000035foo", Sass::SCSS::RX.escape_ident("5foo")
129
+ assert_equal "-\\000035foo", Sass::SCSS::RX.escape_ident("-5foo")
130
+ assert_equal "_\\000035foo", Sass::SCSS::RX.escape_ident("_5foo")
131
+
132
+ assert_equal "\\&foo", Sass::SCSS::RX.escape_ident("&foo")
133
+ assert_equal "-\\&foo", Sass::SCSS::RX.escape_ident("-&foo")
134
+
135
+ assert_equal "-\\ foo", Sass::SCSS::RX.escape_ident("- foo")
136
+ end
137
+
138
+ def test_escape_mid_funky_ident
139
+ assert_equal "foo\\&bar", Sass::SCSS::RX.escape_ident("foo&bar")
140
+ assert_equal "foo\\ \\ bar", Sass::SCSS::RX.escape_ident("foo bar")
141
+ assert_equal "foo\\00007fbar", Sass::SCSS::RX.escape_ident("foo\177bar")
142
+ end
143
+
144
+ private
145
+
146
+ def assert_match(rx, str)
147
+ assert_not_nil(match = rx.match(str))
148
+ assert_equal str.size, match[0].size
149
+ end
150
+
151
+ def assert_no_match(rx, str)
152
+ match = rx.match(str)
153
+ assert_not_equal str.size, match && match[0].size
154
+ end
155
+
156
+ end
@@ -0,0 +1,871 @@
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: foobar;
91
+ c: 12px; }
92
+ CSS
93
+ foo {
94
+ a: 1 + 2;
95
+ b: foo + bar;
96
+ c: floor(12.3px); }
97
+ SCSS
98
+ end
99
+
100
+ def test_debug_directive
101
+ assert_warning "test_debug_directive_inline.scss:2 DEBUG: hello world!" do
102
+ assert_equal <<CSS, render(<<SCSS)
103
+ foo {
104
+ a: b; }
105
+
106
+ bar {
107
+ c: d; }
108
+ CSS
109
+ foo {a: b}
110
+ @debug "hello world!";
111
+ bar {c: d}
112
+ SCSS
113
+ end
114
+ end
115
+
116
+ def test_for_directive
117
+ assert_equal <<CSS, render(<<SCSS)
118
+ .foo {
119
+ a: 1;
120
+ a: 2;
121
+ a: 3;
122
+ a: 4; }
123
+ CSS
124
+ .foo {
125
+ @for $var from 1 to 5 {a: $var;}
126
+ }
127
+ SCSS
128
+
129
+ assert_equal <<CSS, render(<<SCSS)
130
+ .foo {
131
+ a: 1;
132
+ a: 2;
133
+ a: 3;
134
+ a: 4;
135
+ a: 5; }
136
+ CSS
137
+ .foo {
138
+ @for $var from 1 through 5 {a: $var;}
139
+ }
140
+ SCSS
141
+ end
142
+
143
+ def test_if_directive
144
+ assert_equal <<CSS, render(<<SCSS)
145
+ foo {
146
+ a: b; }
147
+ CSS
148
+ @if "foo" == "foo" {foo {a: b}}
149
+ @if "foo" != "foo" {bar {a: b}}
150
+ SCSS
151
+
152
+ assert_equal <<CSS, render(<<SCSS)
153
+ bar {
154
+ a: b; }
155
+ CSS
156
+ @if "foo" != "foo" {foo {a: b}}
157
+ @else if "foo" == "foo" {bar {a: b}}
158
+ @else if true {baz {a: b}}
159
+ SCSS
160
+
161
+ assert_equal <<CSS, render(<<SCSS)
162
+ bar {
163
+ a: b; }
164
+ CSS
165
+ @if "foo" != "foo" {foo {a: b}}
166
+ @else {bar {a: b}}
167
+ SCSS
168
+ end
169
+
170
+ def test_while_directive
171
+ assert_equal <<CSS, render(<<SCSS)
172
+ .foo {
173
+ a: 1;
174
+ a: 2;
175
+ a: 3;
176
+ a: 4; }
177
+ CSS
178
+ $i: 1;
179
+
180
+ .foo {
181
+ @while $i != 5 {
182
+ a: $i;
183
+ $i: $i + 1;
184
+ }
185
+ }
186
+ SCSS
187
+ end
188
+
189
+ def test_css_import_directive
190
+ assert_equal "@import url(foo.css);\n", render('@import "foo.css";')
191
+ assert_equal "@import url(foo.css);\n", render("@import 'foo.css';")
192
+ assert_equal "@import url(foo.css);\n", render('@import url("foo.css");')
193
+ assert_equal "@import url(foo.css);\n", render("@import url('foo.css');")
194
+ assert_equal "@import url(foo.css);\n", render('@import url(foo.css);')
195
+ end
196
+
197
+ def test_block_comment_in_script
198
+ assert_equal <<CSS, render(<<SCSS)
199
+ foo {
200
+ a: 1bar; }
201
+ CSS
202
+ foo {a: 1 + /* flang */ bar}
203
+ SCSS
204
+ end
205
+
206
+ def test_line_comment_in_script
207
+ assert_equal <<CSS, render(<<SCSS)
208
+ foo {
209
+ a: 1blang; }
210
+ CSS
211
+ foo {a: 1 + // flang }
212
+ blang }
213
+ SCSS
214
+ end
215
+
216
+ ## Nested Rules
217
+
218
+ def test_nested_rules
219
+ assert_equal <<CSS, render(<<SCSS)
220
+ foo bar {
221
+ a: b; }
222
+ CSS
223
+ foo {bar {a: b}}
224
+ SCSS
225
+ assert_equal <<CSS, render(<<SCSS)
226
+ foo bar {
227
+ a: b; }
228
+ foo baz {
229
+ b: c; }
230
+ CSS
231
+ foo {
232
+ bar {a: b}
233
+ baz {b: c}}
234
+ SCSS
235
+ assert_equal <<CSS, render(<<SCSS)
236
+ foo bar baz {
237
+ a: b; }
238
+ foo bang bip {
239
+ a: b; }
240
+ CSS
241
+ foo {
242
+ bar {baz {a: b}}
243
+ bang {bip {a: b}}}
244
+ SCSS
245
+ end
246
+
247
+ def test_nested_rules_with_declarations
248
+ assert_equal <<CSS, render(<<SCSS)
249
+ foo {
250
+ a: b; }
251
+ foo bar {
252
+ c: d; }
253
+ CSS
254
+ foo {
255
+ a: b;
256
+ bar {c: d}}
257
+ SCSS
258
+ assert_equal <<CSS, render(<<SCSS)
259
+ foo {
260
+ a: b; }
261
+ foo bar {
262
+ c: d; }
263
+ CSS
264
+ foo {
265
+ bar {c: d}
266
+ a: b}
267
+ SCSS
268
+ assert_equal <<CSS, render(<<SCSS)
269
+ foo {
270
+ ump: nump;
271
+ grump: clump; }
272
+ foo bar {
273
+ blat: bang;
274
+ habit: rabbit; }
275
+ foo bar baz {
276
+ a: b; }
277
+ foo bar bip {
278
+ c: d; }
279
+ foo bibble bap {
280
+ e: f; }
281
+ CSS
282
+ foo {
283
+ ump: nump;
284
+ grump: clump;
285
+ bar {
286
+ blat: bang;
287
+ habit: rabbit;
288
+ baz {a: b}
289
+ bip {c: d}}
290
+ bibble {
291
+ bap {e: f}}}
292
+ SCSS
293
+ end
294
+
295
+ def test_nested_rules_with_fancy_selectors
296
+ assert_equal <<CSS, render(<<SCSS)
297
+ foo .bar {
298
+ a: b; }
299
+ foo :baz {
300
+ c: d; }
301
+ foo bang:bop {
302
+ e: f; }
303
+ CSS
304
+ foo {
305
+ .bar {a: b}
306
+ :baz {c: d}
307
+ bang:bop {e: f}}
308
+ SCSS
309
+ end
310
+
311
+ def test_almost_ambiguous_nested_rules_and_declarations
312
+ assert_equal <<CSS, render(<<SCSS)
313
+ foo {
314
+ bar: baz bang bop biddle woo look at all these elems; }
315
+ foo bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {
316
+ a: b; }
317
+ foo bar:baz bang bop biddle woo look at all these elems {
318
+ a: b; }
319
+ CSS
320
+ foo {
321
+ bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {a: b};
322
+ bar:baz bang bop biddle woo look at all these elems {a: b};
323
+ bar:baz bang bop biddle woo look at all these elems; }
324
+ SCSS
325
+ end
326
+
327
+ def test_newlines_in_selectors
328
+ assert_equal <<CSS, render(<<SCSS)
329
+ foo
330
+ bar {
331
+ a: b; }
332
+ CSS
333
+ foo
334
+ bar {a: b}
335
+ SCSS
336
+
337
+ assert_equal <<CSS, render(<<SCSS)
338
+ foo baz,
339
+ foo bang,
340
+ bar baz,
341
+ bar bang {
342
+ a: b; }
343
+ CSS
344
+ foo,
345
+ bar {
346
+ baz,
347
+ bang {a: b}}
348
+ SCSS
349
+
350
+ assert_equal <<CSS, render(<<SCSS)
351
+ foo
352
+ bar baz
353
+ bang {
354
+ a: b; }
355
+ foo
356
+ bar bip bop {
357
+ c: d; }
358
+ CSS
359
+ foo
360
+ bar {
361
+ baz
362
+ bang {a: b}
363
+
364
+ bip bop {c: d}}
365
+ SCSS
366
+
367
+ assert_equal <<CSS, render(<<SCSS)
368
+ foo bang, foo bip
369
+ bop, bar
370
+ baz bang, bar
371
+ baz bip
372
+ bop {
373
+ a: b; }
374
+ CSS
375
+ foo, bar
376
+ baz {
377
+ bang, bip
378
+ bop {a: b}}
379
+ SCSS
380
+ end
381
+
382
+ def test_parent_selectors
383
+ assert_equal <<CSS, render(<<SCSS)
384
+ foo:hover {
385
+ a: b; }
386
+ bar foo.baz {
387
+ c: d; }
388
+ CSS
389
+ foo {
390
+ &:hover {a: b}
391
+ bar &.baz {c: d}}
392
+ SCSS
393
+ end
394
+
395
+ ## Namespace Properties
396
+
397
+ def test_namespace_properties
398
+ assert_equal <<CSS, render(<<SCSS)
399
+ foo {
400
+ bar: baz;
401
+ bang-bip: 1px;
402
+ bang-bop: bar; }
403
+ CSS
404
+ foo {
405
+ bar: baz;
406
+ bang: {
407
+ bip: 1px;
408
+ bop: bar;}}
409
+ SCSS
410
+ end
411
+
412
+ def test_nested_namespace_properties
413
+ assert_equal <<CSS, render(<<SCSS)
414
+ foo {
415
+ bar: baz;
416
+ bang-bip: 1px;
417
+ bang-bop: bar;
418
+ bang-blat-baf: bort; }
419
+ CSS
420
+ foo {
421
+ bar: baz;
422
+ bang: {
423
+ bip: 1px;
424
+ bop: bar;
425
+ blat:{baf:bort}}}
426
+ SCSS
427
+ end
428
+
429
+ def test_namespace_properties_with_value
430
+ assert_equal <<CSS, render(<<SCSS)
431
+ foo {
432
+ bar: baz;
433
+ bar-bip: bop;
434
+ bar-bing: bop; }
435
+ CSS
436
+ foo {
437
+ bar: baz {
438
+ bip: bop;
439
+ bing: bop; }}
440
+ SCSS
441
+ end
442
+
443
+ def test_namespace_properties_with_script_value
444
+ assert_equal <<CSS, render(<<SCSS)
445
+ foo {
446
+ bar: bazbang;
447
+ bar-bip: bop;
448
+ bar-bing: bop; }
449
+ CSS
450
+ foo {
451
+ bar: baz + bang {
452
+ bip: bop;
453
+ bing: bop; }}
454
+ SCSS
455
+ end
456
+
457
+ def test_no_namespace_properties_without_space
458
+ assert_equal <<CSS, render(<<SCSS)
459
+ foo bar:baz {
460
+ bip: bop; }
461
+ CSS
462
+ foo {
463
+ bar:baz {
464
+ bip: bop }}
465
+ SCSS
466
+ end
467
+
468
+ def test_no_namespace_properties_without_space_even_when_its_unambiguous
469
+ render(<<SCSS)
470
+ foo {
471
+ bar:1px {
472
+ bip: bop }}
473
+ SCSS
474
+ assert(false, "Expected syntax error")
475
+ rescue Sass::SyntaxError => e
476
+ assert_equal <<MESSAGE, e.message
477
+ Invalid CSS: a space is required between a property and its definition
478
+ when it has other properties nested beneath it.
479
+ MESSAGE
480
+ assert_equal 2, e.sass_line
481
+ end
482
+
483
+ ## Mixins
484
+
485
+ def test_basic_mixins
486
+ assert_equal <<CSS, render(<<SCSS)
487
+ .foo {
488
+ a: b; }
489
+ CSS
490
+ @mixin foo {
491
+ .foo {a: b}}
492
+
493
+ @include foo;
494
+ SCSS
495
+
496
+ assert_equal <<CSS, render(<<SCSS)
497
+ bar {
498
+ c: d; }
499
+ bar .foo {
500
+ a: b; }
501
+ CSS
502
+ @mixin foo {
503
+ .foo {a: b}}
504
+
505
+ bar {
506
+ @include foo;
507
+ c: d; }
508
+ SCSS
509
+
510
+ assert_equal <<CSS, render(<<SCSS)
511
+ bar {
512
+ a: b;
513
+ c: d; }
514
+ CSS
515
+ @mixin foo {a: b}
516
+
517
+ bar {
518
+ @include foo;
519
+ c: d; }
520
+ SCSS
521
+ end
522
+
523
+ def test_mixins_with_empty_args
524
+ assert_equal <<CSS, render(<<SCSS)
525
+ .foo {
526
+ a: b; }
527
+ CSS
528
+ @mixin foo() {a: b}
529
+
530
+ .foo {@include foo();}
531
+ SCSS
532
+
533
+ assert_equal <<CSS, render(<<SCSS)
534
+ .foo {
535
+ a: b; }
536
+ CSS
537
+ @mixin foo() {a: b}
538
+
539
+ .foo {@include foo;}
540
+ SCSS
541
+
542
+ assert_equal <<CSS, render(<<SCSS)
543
+ .foo {
544
+ a: b; }
545
+ CSS
546
+ @mixin foo {a: b}
547
+
548
+ .foo {@include foo();}
549
+ SCSS
550
+ end
551
+
552
+ def test_mixins_with_args
553
+ assert_equal <<CSS, render(<<SCSS)
554
+ .foo {
555
+ a: bar; }
556
+ CSS
557
+ @mixin foo($a) {a: $a}
558
+
559
+ .foo {@include foo(bar)}
560
+ SCSS
561
+
562
+ assert_equal <<CSS, render(<<SCSS)
563
+ .foo {
564
+ a: bar;
565
+ b: 12px; }
566
+ CSS
567
+ @mixin foo($a, $b) {
568
+ a: $a;
569
+ b: $b; }
570
+
571
+ .foo {@include foo(bar, 12px)}
572
+ SCSS
573
+ end
574
+
575
+ ## Interpolation
576
+
577
+ def test_basic_selector_interpolation
578
+ assert_equal <<CSS, render(<<SCSS)
579
+ foo 3 baz {
580
+ a: b; }
581
+ CSS
582
+ foo \#{1 + 2} baz {a: b}
583
+ SCSS
584
+ assert_equal <<CSS, render(<<SCSS)
585
+ foo.bar baz {
586
+ a: b; }
587
+ CSS
588
+ foo\#{".bar"} baz {a: b}
589
+ SCSS
590
+ assert_equal <<CSS, render(<<SCSS)
591
+ foo.bar baz {
592
+ a: b; }
593
+ CSS
594
+ \#{"foo"}.bar baz {a: b}
595
+ SCSS
596
+ end
597
+
598
+ def test_selector_only_interpolation
599
+ assert_equal <<CSS, render(<<SCSS)
600
+ foo bar {
601
+ a: b; }
602
+ CSS
603
+ \#{"foo" + " bar"} {a: b}
604
+ SCSS
605
+ end
606
+
607
+ def test_selector_interpolation_before_element_name
608
+ assert_equal <<CSS, render(<<SCSS)
609
+ foo barbaz {
610
+ a: b; }
611
+ CSS
612
+ \#{"foo" + " bar"}baz {a: b}
613
+ SCSS
614
+ end
615
+
616
+ def test_selector_interpolation_in_string
617
+ assert_equal <<CSS, render(<<SCSS)
618
+ foo[val="bar foo bar baz"] {
619
+ a: b; }
620
+ CSS
621
+ foo[val="bar \#{"foo" + " bar"} baz"] {a: b}
622
+ SCSS
623
+ end
624
+
625
+ def test_selector_interpolation_in_pseudoclass
626
+ assert_equal <<CSS, render(<<SCSS)
627
+ foo:nth-child(5n) {
628
+ a: b; }
629
+ CSS
630
+ foo:nth-child(\#{5 + "n"}) {a: b}
631
+ SCSS
632
+ end
633
+
634
+ def test_basic_prop_val_interpolation
635
+ assert_equal <<CSS, render(<<SCSS)
636
+ foo {
637
+ bar: foo 3 baz; }
638
+ CSS
639
+ foo {bar: foo \#{1 + 2} baz}
640
+ SCSS
641
+ assert_equal <<CSS, render(<<SCSS)
642
+ foo {
643
+ bar: foo3 baz; }
644
+ CSS
645
+ foo {bar: foo\#{1 + 2} baz}
646
+ SCSS
647
+ assert_equal <<CSS, render(<<SCSS)
648
+ foo {
649
+ bar: foo 3, baz; }
650
+ CSS
651
+ foo {bar: foo \#{1 + 2},baz}
652
+ SCSS
653
+ end
654
+
655
+ def test_prop_val_only_interpolation
656
+ assert_equal <<CSS, render(<<SCSS)
657
+ foo {
658
+ bar: bazbang; }
659
+ CSS
660
+ foo {bar: \#{"baz" + "bang"}}
661
+ SCSS
662
+ end
663
+
664
+ def test_prop_val_interpolation_in_string
665
+ assert_equal <<CSS, render(<<SCSS)
666
+ foo {
667
+ bar: "bizzle bazbang bop"; }
668
+ CSS
669
+ foo {bar: "bizzle \#{"baz" + "bang"} bop"}
670
+ SCSS
671
+ end
672
+
673
+ def test_prop_val_interpolation_in_function
674
+ assert_equal <<CSS, render(<<SCSS)
675
+ foo {
676
+ bar: flabnabbit(1foo); }
677
+ CSS
678
+ foo {bar: flabnabbit(\#{1 + "foo"})}
679
+ SCSS
680
+ end
681
+
682
+ def test_basic_prop_name_interpolation
683
+ assert_equal <<CSS, render(<<SCSS)
684
+ foo {
685
+ barbazbang: blip; }
686
+ CSS
687
+ foo {bar\#{"baz" + "bang"}: blip}
688
+ SCSS
689
+ assert_equal <<CSS, render(<<SCSS)
690
+ foo {
691
+ bar3: blip; }
692
+ CSS
693
+ foo {bar\#{1 + 2}: blip}
694
+ SCSS
695
+ end
696
+
697
+ def test_prop_name_only_interpolation
698
+ assert_equal <<CSS, render(<<SCSS)
699
+ foo {
700
+ bazbang: blip; }
701
+ CSS
702
+ foo {\#{"baz" + "bang"}: blip}
703
+ SCSS
704
+ end
705
+
706
+ ## Errors
707
+
708
+ def test_mixin_defs_only_at_toplevel
709
+ render <<SCSS
710
+ foo {
711
+ @mixin bar {a: b}}
712
+ SCSS
713
+ assert(false, "Expected syntax error")
714
+ rescue Sass::SyntaxError => e
715
+ assert_equal "Mixins may only be defined at the root of a document.", e.message
716
+ assert_equal 2, e.sass_line
717
+ end
718
+
719
+ def test_imports_only_at_toplevel
720
+ render <<SCSS
721
+ foo {
722
+ @import "foo.scss";}
723
+ SCSS
724
+ assert(false, "Expected syntax error")
725
+ rescue Sass::SyntaxError => e
726
+ assert_equal "Import directives may only be used at the root of a document.", e.message
727
+ assert_equal 2, e.sass_line
728
+ end
729
+
730
+ def test_rules_beneath_properties
731
+ render <<SCSS
732
+ foo {
733
+ bar: {
734
+ baz {
735
+ bang: bop }}}
736
+ SCSS
737
+ assert(false, "Expected syntax error")
738
+ rescue Sass::SyntaxError => e
739
+ assert_equal 'Illegal nesting: Only properties may be nested beneath properties.', e.message
740
+ assert_equal 3, e.sass_line
741
+ end
742
+
743
+ def test_uses_property_exception_with_star_hack
744
+ render <<SCSS
745
+ foo {
746
+ *bar:baz [fail]; }
747
+ SCSS
748
+ assert(false, "Expected syntax error")
749
+ rescue Sass::SyntaxError => e
750
+ assert_equal 'Invalid CSS after " *bar:baz ": expected ";", was "[fail]; }"', e.message
751
+ assert_equal 2, e.sass_line
752
+ end
753
+
754
+ def test_uses_property_exception_with_colon_hack
755
+ render <<SCSS
756
+ foo {
757
+ :bar:baz [fail]; }
758
+ SCSS
759
+ assert(false, "Expected syntax error")
760
+ rescue Sass::SyntaxError => e
761
+ assert_equal 'Invalid CSS after " :bar:baz ": expected ";", was "[fail]; }"', e.message
762
+ assert_equal 2, e.sass_line
763
+ end
764
+
765
+ def test_uses_rule_exception_with_dot_hack
766
+ render <<SCSS
767
+ foo {
768
+ .bar:baz <fail>; }
769
+ SCSS
770
+ assert(false, "Expected syntax error")
771
+ rescue Sass::SyntaxError => e
772
+ assert_equal 'Invalid CSS after " .bar:baz ": expected "{", was "<fail>; }"', e.message
773
+ assert_equal 2, e.sass_line
774
+ end
775
+
776
+ def test_uses_property_exception_with_space_after_name
777
+ render <<SCSS
778
+ foo {
779
+ bar: baz [fail]; }
780
+ SCSS
781
+ assert(false, "Expected syntax error")
782
+ rescue Sass::SyntaxError => e
783
+ assert_equal 'Invalid CSS after " bar: baz ": expected ";", was "[fail]; }"', e.message
784
+ assert_equal 2, e.sass_line
785
+ end
786
+
787
+ def test_uses_property_exception_with_non_identifier_after_name
788
+ render <<SCSS
789
+ foo {
790
+ bar:1px [fail]; }
791
+ SCSS
792
+ assert(false, "Expected syntax error")
793
+ rescue Sass::SyntaxError => e
794
+ assert_equal 'Invalid CSS after " bar:1px ": expected ";", was "[fail]; }"', e.message
795
+ assert_equal 2, e.sass_line
796
+ end
797
+
798
+ def test_uses_property_exception_when_followed_by_open_bracket
799
+ render <<SCSS
800
+ foo {
801
+ bar:{baz: .fail} }
802
+ SCSS
803
+ assert(false, "Expected syntax error")
804
+ rescue Sass::SyntaxError => e
805
+ assert_equal 'Invalid CSS after " bar:{baz: ": expected expression (e.g. 1px, bold), was ".fail} }"', e.message
806
+ assert_equal 2, e.sass_line
807
+ end
808
+
809
+ def test_script_error
810
+ render <<SCSS
811
+ foo {
812
+ bar: "baz" * * }
813
+ SCSS
814
+ assert(false, "Expected syntax error")
815
+ rescue Sass::SyntaxError => e
816
+ assert_equal 'Invalid CSS after " bar: "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message
817
+ assert_equal 2, e.sass_line
818
+ end
819
+
820
+ def test_multiline_script_syntax_error
821
+ render <<SCSS
822
+ foo {
823
+ bar:
824
+ "baz" * * }
825
+ SCSS
826
+ assert(false, "Expected syntax error")
827
+ rescue Sass::SyntaxError => e
828
+ assert_equal 'Invalid CSS after " "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message
829
+ assert_equal 3, e.sass_line
830
+ end
831
+
832
+ def test_multiline_script_runtime_error
833
+ render <<SCSS
834
+ foo {
835
+ bar: "baz" +
836
+ "bar" +
837
+ $bang }
838
+ SCSS
839
+ assert(false, "Expected syntax error")
840
+ rescue Sass::SyntaxError => e
841
+ assert_equal "Undefined variable: \"$bang\".", e.message
842
+ assert_equal 4, e.sass_line
843
+ end
844
+
845
+ def test_post_multiline_script_runtime_error
846
+ render <<SCSS
847
+ foo {
848
+ bar: "baz" +
849
+ "bar" +
850
+ "baz";
851
+ bip: $bop; }
852
+ SCSS
853
+ assert(false, "Expected syntax error")
854
+ rescue Sass::SyntaxError => e
855
+ assert_equal "Undefined variable: \"$bop\".", e.message
856
+ assert_equal 5, e.sass_line
857
+ end
858
+
859
+ def test_multiline_property_runtime_error
860
+ render <<SCSS
861
+ foo {
862
+ bar: baz
863
+ bar
864
+ \#{$bang} }
865
+ SCSS
866
+ assert(false, "Expected syntax error")
867
+ rescue Sass::SyntaxError => e
868
+ assert_equal "Undefined variable: \"$bang\".", e.message
869
+ assert_equal 4, e.sass_line
870
+ end
871
+ end