haml 3.0.0.rc.3 → 3.0.0.rc.4
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.
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/haml/exec.rb +36 -12
- data/lib/haml/helpers/action_view_mods.rb +16 -0
- data/lib/haml/railtie.rb +1 -0
- data/lib/haml/template.rb +1 -9
- data/lib/haml/template/options.rb +16 -0
- data/lib/sass/less.rb +363 -0
- data/lib/sass/plugin/rails.rb +1 -1
- data/lib/sass/tree/for_node.rb +12 -0
- data/lib/sass/tree/if_node.rb +12 -0
- data/lib/sass/tree/root_node.rb +2 -1
- data/lib/sass/tree/while_node.rb +12 -0
- data/test/haml/template_test.rb +11 -0
- data/test/sass/conversion_test.rb +18 -0
- data/test/sass/extend_test.rb +67 -0
- data/test/sass/less_conversion_test.rb +625 -0
- data/test/sass/templates/importee.less +2 -0
- metadata +8 -3
data/lib/sass/plugin/rails.rb
CHANGED
@@ -4,7 +4,7 @@ unless defined?(Sass::RAILS_LOADED)
|
|
4
4
|
Sass::Plugin.options.merge!(:template_location => Haml::Util.rails_root + '/public/stylesheets/sass',
|
5
5
|
:css_location => Haml::Util.rails_root + '/public/stylesheets',
|
6
6
|
:cache_location => Haml::Util.rails_root + '/tmp/sass-cache',
|
7
|
-
:always_check => Haml::Util.rails_env
|
7
|
+
:always_check => Haml::Util.rails_env == "development",
|
8
8
|
:quiet => Haml::Util.rails_env != "production",
|
9
9
|
:full_exception => Haml::Util.rails_env != "production")
|
10
10
|
|
data/lib/sass/tree/for_node.rb
CHANGED
@@ -51,5 +51,17 @@ module Sass::Tree
|
|
51
51
|
end
|
52
52
|
children
|
53
53
|
end
|
54
|
+
|
55
|
+
# Returns an error message if the given child node is invalid,
|
56
|
+
# and false otherwise.
|
57
|
+
#
|
58
|
+
# {ExtendNode}s are valid within {ForNode}s.
|
59
|
+
#
|
60
|
+
# @param child [Tree::Node] A potential child node.
|
61
|
+
# @return [Boolean, String] Whether or not the child node is valid,
|
62
|
+
# as well as the error message to display if it is invalid
|
63
|
+
def invalid_child?(child)
|
64
|
+
super unless child.is_a?(ExtendNode)
|
65
|
+
end
|
54
66
|
end
|
55
67
|
end
|
data/lib/sass/tree/if_node.rb
CHANGED
@@ -65,5 +65,17 @@ module Sass::Tree
|
|
65
65
|
return @else.perform(environment) if @else
|
66
66
|
[]
|
67
67
|
end
|
68
|
+
|
69
|
+
# Returns an error message if the given child node is invalid,
|
70
|
+
# and false otherwise.
|
71
|
+
#
|
72
|
+
# {ExtendNode}s are valid within {IfNode}s.
|
73
|
+
#
|
74
|
+
# @param child [Tree::Node] A potential child node.
|
75
|
+
# @return [Boolean, String] Whether or not the child node is valid,
|
76
|
+
# as well as the error message to display if it is invalid
|
77
|
+
def invalid_child?(child)
|
78
|
+
super unless child.is_a?(ExtendNode)
|
79
|
+
end
|
68
80
|
end
|
69
81
|
end
|
data/lib/sass/tree/root_node.rb
CHANGED
@@ -68,7 +68,8 @@ module Sass
|
|
68
68
|
child.send("to_#{fmt}", 0, opts) +
|
69
69
|
if nxt &&
|
70
70
|
(child.is_a?(CommentNode) && child.line + child.value.count("\n") + 1 == nxt.line) ||
|
71
|
-
(child.is_a?(ImportNode) && nxt.is_a?(ImportNode) && child.line + 1 == nxt.line)
|
71
|
+
(child.is_a?(ImportNode) && nxt.is_a?(ImportNode) && child.line + 1 == nxt.line) ||
|
72
|
+
(child.is_a?(VariableNode) && nxt.is_a?(VariableNode) && child.line + 1 == nxt.line)
|
72
73
|
""
|
73
74
|
else
|
74
75
|
"\n"
|
data/lib/sass/tree/while_node.rb
CHANGED
@@ -32,5 +32,17 @@ module Sass::Tree
|
|
32
32
|
end
|
33
33
|
children
|
34
34
|
end
|
35
|
+
|
36
|
+
# Returns an error message if the given child node is invalid,
|
37
|
+
# and false otherwise.
|
38
|
+
#
|
39
|
+
# {ExtendNode}s are valid within {WhileNode}s.
|
40
|
+
#
|
41
|
+
# @param child [Tree::Node] A potential child node.
|
42
|
+
# @return [Boolean, String] Whether or not the child node is valid,
|
43
|
+
# as well as the error message to display if it is invalid
|
44
|
+
def invalid_child?(child)
|
45
|
+
super unless child.is_a?(ExtendNode)
|
46
|
+
end
|
35
47
|
end
|
36
48
|
end
|
data/test/haml/template_test.rb
CHANGED
@@ -401,6 +401,17 @@ window.location.reload();
|
|
401
401
|
HTML
|
402
402
|
= update_page do |p|
|
403
403
|
- p.reload
|
404
|
+
HAML
|
405
|
+
end
|
406
|
+
|
407
|
+
def test_cache
|
408
|
+
@base.controller = ActionController::Base.new
|
409
|
+
@base.controller.perform_caching = false
|
410
|
+
assert_equal(<<HTML, render(<<HAML, :action_view))
|
411
|
+
Test
|
412
|
+
HTML
|
413
|
+
- cache do
|
414
|
+
Test
|
404
415
|
HAML
|
405
416
|
end
|
406
417
|
end
|
@@ -888,6 +888,24 @@ SCSS
|
|
888
888
|
assert_sass_to_scss '$var: 12px $bar baz !default;', '$var ||= 12px $bar "baz"'
|
889
889
|
end
|
890
890
|
|
891
|
+
def test_multiple_variable_definitions
|
892
|
+
assert_renders <<SASS, <<SCSS
|
893
|
+
$var1: foo
|
894
|
+
$var2: bar
|
895
|
+
$var3: baz
|
896
|
+
|
897
|
+
$var4: bip
|
898
|
+
$var5: bap
|
899
|
+
SASS
|
900
|
+
$var1: foo;
|
901
|
+
$var2: bar;
|
902
|
+
$var3: baz;
|
903
|
+
|
904
|
+
$var4: bip;
|
905
|
+
$var5: bap;
|
906
|
+
SCSS
|
907
|
+
end
|
908
|
+
|
891
909
|
def test_division_asserted_with_parens
|
892
910
|
assert_renders <<SASS, <<SCSS
|
893
911
|
foo
|
data/test/sass/extend_test.rb
CHANGED
@@ -1165,6 +1165,73 @@ a.bar.baz {a: b}
|
|
1165
1165
|
SCSS
|
1166
1166
|
end
|
1167
1167
|
|
1168
|
+
def test_control_flow_if
|
1169
|
+
assert_equal <<CSS, render(<<SCSS)
|
1170
|
+
.true, .also-true {
|
1171
|
+
color: green; }
|
1172
|
+
|
1173
|
+
.false, .also-false {
|
1174
|
+
color: red; }
|
1175
|
+
CSS
|
1176
|
+
.true { color: green; }
|
1177
|
+
.false { color: red; }
|
1178
|
+
.also-true {
|
1179
|
+
@if true { @extend .true; }
|
1180
|
+
@else { @extend .false; }
|
1181
|
+
}
|
1182
|
+
.also-false {
|
1183
|
+
@if false { @extend .true; }
|
1184
|
+
@else { @extend .false; }
|
1185
|
+
}
|
1186
|
+
SCSS
|
1187
|
+
end
|
1188
|
+
|
1189
|
+
def test_control_flow_for
|
1190
|
+
assert_equal <<CSS, render(<<SCSS)
|
1191
|
+
.base-0, .added {
|
1192
|
+
color: green; }
|
1193
|
+
|
1194
|
+
.base-1, .added {
|
1195
|
+
display: block; }
|
1196
|
+
|
1197
|
+
.base-2, .added {
|
1198
|
+
border: 1px solid blue; }
|
1199
|
+
CSS
|
1200
|
+
.base-0 { color: green; }
|
1201
|
+
.base-1 { display: block; }
|
1202
|
+
.base-2 { border: 1px solid blue; }
|
1203
|
+
.added {
|
1204
|
+
@for $i from 0 to 3 {
|
1205
|
+
@extend .base-\#{$i};
|
1206
|
+
}
|
1207
|
+
}
|
1208
|
+
SCSS
|
1209
|
+
end
|
1210
|
+
|
1211
|
+
def test_control_flow_while
|
1212
|
+
assert_equal <<CSS, render(<<SCSS)
|
1213
|
+
.base-0, .added {
|
1214
|
+
color: green; }
|
1215
|
+
|
1216
|
+
.base-1, .added {
|
1217
|
+
display: block; }
|
1218
|
+
|
1219
|
+
.base-2, .added {
|
1220
|
+
border: 1px solid blue; }
|
1221
|
+
CSS
|
1222
|
+
.base-0 { color: green; }
|
1223
|
+
.base-1 { display: block; }
|
1224
|
+
.base-2 { border: 1px solid blue; }
|
1225
|
+
.added {
|
1226
|
+
$i : 0;
|
1227
|
+
@while $i < 3 {
|
1228
|
+
@extend .base-\#{$i};
|
1229
|
+
$i : $i + 1;
|
1230
|
+
}
|
1231
|
+
}
|
1232
|
+
SCSS
|
1233
|
+
end
|
1234
|
+
|
1168
1235
|
private
|
1169
1236
|
|
1170
1237
|
def render(sass, options = {})
|
@@ -0,0 +1,625 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'sass/less'
|
6
|
+
|
7
|
+
class LessConversionTest < Test::Unit::TestCase
|
8
|
+
def test_variable_declarations
|
9
|
+
assert_renders <<SCSS, <<LESS
|
10
|
+
$var1: 2px 3px;
|
11
|
+
$var2: $var1 + 7px;
|
12
|
+
|
13
|
+
$var3: fizz;
|
14
|
+
|
15
|
+
foo {
|
16
|
+
prop: $var1 $var2 $var3; }
|
17
|
+
SCSS
|
18
|
+
@var1: 2px 3px;
|
19
|
+
@var2: @var1 + 7px;
|
20
|
+
|
21
|
+
@var3: fizz;
|
22
|
+
|
23
|
+
foo {prop: @var1 @var2 @var3}
|
24
|
+
LESS
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_nested_variable_declarations
|
28
|
+
assert_renders <<SCSS, <<LESS
|
29
|
+
.foo {
|
30
|
+
$var: 2px;
|
31
|
+
prop: $var; }
|
32
|
+
SCSS
|
33
|
+
.foo {
|
34
|
+
@var: 2px;
|
35
|
+
prop: @var; }
|
36
|
+
LESS
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_import
|
40
|
+
path = File.dirname(__FILE__) + "/templates/importee.less"
|
41
|
+
resolved_path = File.dirname(__FILE__) + "/templates/importee"
|
42
|
+
assert_renders <<SCSS, <<LESS
|
43
|
+
@import "#{resolved_path}";
|
44
|
+
@import "#{resolved_path}";
|
45
|
+
|
46
|
+
@import "#{resolved_path}";
|
47
|
+
@import "#{resolved_path}";
|
48
|
+
@import "#{resolved_path}";
|
49
|
+
SCSS
|
50
|
+
@import url(#{path});
|
51
|
+
@import url("#{path}");
|
52
|
+
|
53
|
+
@import url('#{path}');
|
54
|
+
@import '#{path}';
|
55
|
+
@import "#{path}";
|
56
|
+
LESS
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_mixins_found_through_import
|
60
|
+
path = File.dirname(__FILE__) + "/templates/importee.less"
|
61
|
+
resolved_path = File.dirname(__FILE__) + "/templates/importee"
|
62
|
+
assert_renders <<SCSS, <<LESS
|
63
|
+
@import "#{resolved_path}";
|
64
|
+
|
65
|
+
.baz {
|
66
|
+
@extend .foo;
|
67
|
+
@include bar; }
|
68
|
+
SCSS
|
69
|
+
@import "#{path}";
|
70
|
+
|
71
|
+
.baz {.foo; .bar;}
|
72
|
+
LESS
|
73
|
+
end
|
74
|
+
|
75
|
+
# Selectors
|
76
|
+
|
77
|
+
def test_element_selector
|
78
|
+
assert_renders <<SCSS, <<LESS
|
79
|
+
foo {
|
80
|
+
a: b; }
|
81
|
+
SCSS
|
82
|
+
foo {a: b}
|
83
|
+
LESS
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_class_selector
|
87
|
+
assert_renders <<SCSS, <<LESS
|
88
|
+
.foo {
|
89
|
+
a: b; }
|
90
|
+
SCSS
|
91
|
+
.foo {a: b}
|
92
|
+
LESS
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_id_selector
|
96
|
+
assert_renders <<SCSS, <<LESS
|
97
|
+
#foo {
|
98
|
+
a: b; }
|
99
|
+
SCSS
|
100
|
+
#foo {a: b}
|
101
|
+
LESS
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_pseudoclass_selector
|
105
|
+
assert_renders <<SCSS, <<LESS
|
106
|
+
:foo {
|
107
|
+
a: b; }
|
108
|
+
SCSS
|
109
|
+
:foo {a: b}
|
110
|
+
LESS
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_pseudoelement_selector
|
114
|
+
assert_renders <<SCSS, <<LESS
|
115
|
+
::foo {
|
116
|
+
a: b; }
|
117
|
+
SCSS
|
118
|
+
::foo {a: b}
|
119
|
+
LESS
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_comma_selector
|
123
|
+
assert_renders <<SCSS, <<LESS
|
124
|
+
foo, .bar .baz, :bang {
|
125
|
+
a: b; }
|
126
|
+
SCSS
|
127
|
+
foo, .bar .baz, :bang {a: b}
|
128
|
+
LESS
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_nested_comma_selector
|
132
|
+
assert_renders <<SCSS, <<LESS
|
133
|
+
foo bar, .baz {
|
134
|
+
.bang, &:bip bap {
|
135
|
+
a: b; } }
|
136
|
+
SCSS
|
137
|
+
foo bar, .baz {
|
138
|
+
.bang, :bip bap {a: b} }
|
139
|
+
LESS
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_simple_selector_sequence
|
143
|
+
assert_renders <<SCSS, <<LESS
|
144
|
+
a.foo#bar[attr=val] {
|
145
|
+
a: b; }
|
146
|
+
SCSS
|
147
|
+
a.foo#bar[attr=val] {a: b}
|
148
|
+
LESS
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_descendant_selector
|
152
|
+
assert_renders <<SCSS, <<LESS
|
153
|
+
.foo .bar {
|
154
|
+
a: b; }
|
155
|
+
SCSS
|
156
|
+
.foo .bar {a: b}
|
157
|
+
LESS
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_child_selector
|
161
|
+
assert_renders <<SCSS, <<LESS
|
162
|
+
.foo > .bar {
|
163
|
+
a: b; }
|
164
|
+
SCSS
|
165
|
+
.foo > .bar {a: b}
|
166
|
+
LESS
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_adjacent_selector
|
170
|
+
assert_renders <<SCSS, <<LESS
|
171
|
+
.foo + .bar {
|
172
|
+
a: b; }
|
173
|
+
SCSS
|
174
|
+
.foo + .bar {a: b}
|
175
|
+
LESS
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_pseudoclass_in_sequence
|
179
|
+
assert_renders <<SCSS, <<LESS
|
180
|
+
.foo:bar {
|
181
|
+
a: b; }
|
182
|
+
SCSS
|
183
|
+
.foo:bar {a: b}
|
184
|
+
LESS
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_pseudoelement_in_sequence
|
188
|
+
assert_renders <<SCSS, <<LESS
|
189
|
+
.foo::bar {
|
190
|
+
a: b; }
|
191
|
+
SCSS
|
192
|
+
.foo::bar {a: b}
|
193
|
+
LESS
|
194
|
+
end
|
195
|
+
|
196
|
+
# Properties
|
197
|
+
|
198
|
+
def test_space_separated_props
|
199
|
+
assert_renders <<SCSS, <<LESS
|
200
|
+
foo {
|
201
|
+
a: foo bar baz; }
|
202
|
+
SCSS
|
203
|
+
foo {a: foo bar baz}
|
204
|
+
LESS
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_comma_separated_props
|
208
|
+
assert_renders <<SCSS, <<LESS
|
209
|
+
foo {
|
210
|
+
a: foo, bar, baz; }
|
211
|
+
SCSS
|
212
|
+
foo {a: foo, bar, baz}
|
213
|
+
LESS
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_numbers
|
217
|
+
assert_renders <<SCSS, <<LESS
|
218
|
+
foo {
|
219
|
+
a: 1 2.3 -8 5px 3%; }
|
220
|
+
SCSS
|
221
|
+
foo {a: 1 2.3 -8 5px 3%}
|
222
|
+
LESS
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_colors
|
226
|
+
assert_renders <<SCSS, <<LESS
|
227
|
+
foo {
|
228
|
+
a: red #abcdef blue; }
|
229
|
+
SCSS
|
230
|
+
foo {a: #f00 #abcdef blue}
|
231
|
+
LESS
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_strings
|
235
|
+
assert_renders <<SCSS, <<LESS
|
236
|
+
foo {
|
237
|
+
a: "foo @var bar" "baz bang" "quote'quote" 'quote"quote'; }
|
238
|
+
SCSS
|
239
|
+
foo {a: "foo @var bar" 'baz bang' "quote'quote" 'quote"quote'}
|
240
|
+
LESS
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_slash
|
244
|
+
assert_renders <<SCSS, <<LESS
|
245
|
+
foo {
|
246
|
+
a: small/8px 7em/8px;
|
247
|
+
b: 8/4;
|
248
|
+
c: (8 / 4); }
|
249
|
+
SCSS
|
250
|
+
foo {
|
251
|
+
a: small/8px 7em/8px;
|
252
|
+
b: 8/4;
|
253
|
+
c: 8 / 4; }
|
254
|
+
LESS
|
255
|
+
end
|
256
|
+
|
257
|
+
def test_url
|
258
|
+
assert_renders <<SCSS, <<LESS
|
259
|
+
foo {
|
260
|
+
a: url("http://foobar.com/fizzle.html?foo=bar&bar=baz");
|
261
|
+
b: url("http://foobar.com/fizzle.html?foo=bar&bar=baz");
|
262
|
+
c: url("http://foobar.com/fizzle.html?foo=bar&bar=baz"); }
|
263
|
+
SCSS
|
264
|
+
foo {
|
265
|
+
a: url(http://foobar.com/fizzle.html?foo=bar&bar=baz);
|
266
|
+
b: url("http://foobar.com/fizzle.html?foo=bar&bar=baz");
|
267
|
+
c: url('http://foobar.com/fizzle.html?foo=bar&bar=baz'); }
|
268
|
+
LESS
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_functions
|
272
|
+
assert_renders <<SCSS, <<LESS
|
273
|
+
foo {
|
274
|
+
a: baz(12px) rgba(80, 70 120, 0.76);
|
275
|
+
b: faz(1px + 3px) bang($var, #aaaaaa * 3); }
|
276
|
+
SCSS
|
277
|
+
foo {
|
278
|
+
a: baz(12px) rgba(80, 70 120, 0.76);
|
279
|
+
b: faz(1px + 3px) bang(@var, #aaa * 3); }
|
280
|
+
LESS
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_alpha_function
|
284
|
+
assert_renders <<SCSS, <<LESS
|
285
|
+
foo {
|
286
|
+
a: alpha(opacity=2px);
|
287
|
+
b: alpha(opacity = $var); }
|
288
|
+
SCSS
|
289
|
+
foo {
|
290
|
+
a: alpha(opacity=2px);
|
291
|
+
b: alpha(opacity=@var); }
|
292
|
+
LESS
|
293
|
+
end
|
294
|
+
|
295
|
+
def test_variables
|
296
|
+
assert_renders <<SCSS, <<LESS
|
297
|
+
foo {
|
298
|
+
a: $var1 $var-foo; }
|
299
|
+
SCSS
|
300
|
+
foo {a: @var1 @var-foo}
|
301
|
+
LESS
|
302
|
+
end
|
303
|
+
|
304
|
+
def test_operators
|
305
|
+
assert_renders <<SCSS, <<LESS
|
306
|
+
foo {
|
307
|
+
a: 1px + 2px;
|
308
|
+
b: #bbaa88 - #aa1122;
|
309
|
+
c: 5 * 3;
|
310
|
+
d: (8 / 4); }
|
311
|
+
SCSS
|
312
|
+
foo {
|
313
|
+
a: 1px + 2px;
|
314
|
+
b: #ba8 - #a12;
|
315
|
+
c: 5 * 3;
|
316
|
+
d: 8 / 4; }
|
317
|
+
LESS
|
318
|
+
end
|
319
|
+
|
320
|
+
def test_operator_precedence
|
321
|
+
assert_renders <<SCSS, <<LESS
|
322
|
+
foo {
|
323
|
+
a: 1 + 2 * 3 + 4;
|
324
|
+
b: 1 * 2 + 3 * 4;
|
325
|
+
c: 1 - 2 + 2 - 4;
|
326
|
+
d: 1 + 2 - 3 + 4;
|
327
|
+
e: 1 / 2 - 3 / 4;
|
328
|
+
f: 1 - 2 / 3 - 4;
|
329
|
+
g: 1 / 2 * 3 / 4; }
|
330
|
+
SCSS
|
331
|
+
foo {
|
332
|
+
a: 1 + 2 * 3 + 4;
|
333
|
+
b: 1 * 2 + 3 * 4;
|
334
|
+
c: 1 - 2 + 2 - 4;
|
335
|
+
d: 1 + 2 - 3 + 4;
|
336
|
+
e: 1 / 2 - 3 / 4;
|
337
|
+
f: 1 - 2 / 3 - 4;
|
338
|
+
g: 1 / 2 * 3 / 4; }
|
339
|
+
LESS
|
340
|
+
end
|
341
|
+
|
342
|
+
def test_operators_with_parens
|
343
|
+
assert_renders <<SCSS, <<LESS
|
344
|
+
foo {
|
345
|
+
a: 1px + 2px * 3;
|
346
|
+
b: (1px - 2px) / 3; }
|
347
|
+
SCSS
|
348
|
+
foo {
|
349
|
+
a: 1px + (2px * 3);
|
350
|
+
b: (1px - (2px)) / 3; }
|
351
|
+
LESS
|
352
|
+
end
|
353
|
+
|
354
|
+
def test_unary_minus
|
355
|
+
assert_renders <<SCSS, <<LESS
|
356
|
+
foo {
|
357
|
+
a: 1px + -3px; }
|
358
|
+
SCSS
|
359
|
+
foo {a: 1px + (- 3px)}
|
360
|
+
LESS
|
361
|
+
end
|
362
|
+
|
363
|
+
# Nested Rules
|
364
|
+
|
365
|
+
def test_single_nested_rule
|
366
|
+
assert_renders <<SCSS, <<LESS
|
367
|
+
foo bar {
|
368
|
+
a: b; }
|
369
|
+
SCSS
|
370
|
+
foo {bar {a: b}}
|
371
|
+
LESS
|
372
|
+
end
|
373
|
+
|
374
|
+
def test_single_nested_rule_with_props
|
375
|
+
assert_renders <<SCSS, <<LESS
|
376
|
+
foo {
|
377
|
+
bar {
|
378
|
+
a: b; }
|
379
|
+
c: d;
|
380
|
+
e: f; }
|
381
|
+
SCSS
|
382
|
+
foo {
|
383
|
+
bar {a: b}
|
384
|
+
c: d;
|
385
|
+
e: f; }
|
386
|
+
LESS
|
387
|
+
end
|
388
|
+
|
389
|
+
def test_two_nested_rules
|
390
|
+
assert_renders <<SCSS, <<LESS
|
391
|
+
foo {
|
392
|
+
bar {
|
393
|
+
a: b; }
|
394
|
+
baz {
|
395
|
+
c: d; } }
|
396
|
+
SCSS
|
397
|
+
foo {
|
398
|
+
bar {a: b}
|
399
|
+
baz {c: d} }
|
400
|
+
LESS
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_two_nested_rules_with_props
|
404
|
+
assert_renders <<SCSS, <<LESS
|
405
|
+
foo {
|
406
|
+
bar {
|
407
|
+
a: b; }
|
408
|
+
baz {
|
409
|
+
c: d; }
|
410
|
+
e: f;
|
411
|
+
g: h; }
|
412
|
+
SCSS
|
413
|
+
foo {
|
414
|
+
bar {a: b}
|
415
|
+
baz {c: d}
|
416
|
+
e: f;
|
417
|
+
g: h; }
|
418
|
+
LESS
|
419
|
+
end
|
420
|
+
|
421
|
+
def test_nested_rules_with_combinators
|
422
|
+
assert_renders <<SCSS, <<LESS
|
423
|
+
foo {
|
424
|
+
> bar {
|
425
|
+
a: b; }
|
426
|
+
+ baz {
|
427
|
+
c: d; } }
|
428
|
+
SCSS
|
429
|
+
foo {
|
430
|
+
> bar {a: b}
|
431
|
+
+ baz {c: d} }
|
432
|
+
LESS
|
433
|
+
end
|
434
|
+
|
435
|
+
def test_nested_pseudo_rules
|
436
|
+
assert_renders <<SCSS, <<LESS
|
437
|
+
foo {
|
438
|
+
&:bar {
|
439
|
+
a: b; }
|
440
|
+
&::baz {
|
441
|
+
c: d; } }
|
442
|
+
SCSS
|
443
|
+
foo {
|
444
|
+
:bar {a: b}
|
445
|
+
::baz {c: d} }
|
446
|
+
LESS
|
447
|
+
end
|
448
|
+
|
449
|
+
# Mixins
|
450
|
+
|
451
|
+
def test_class_inheritance
|
452
|
+
assert_renders <<SCSS, <<LESS
|
453
|
+
.foo {
|
454
|
+
a: b; }
|
455
|
+
|
456
|
+
.bar {
|
457
|
+
@extend .foo; }
|
458
|
+
SCSS
|
459
|
+
.foo {a: b}
|
460
|
+
.bar {.foo;}
|
461
|
+
LESS
|
462
|
+
end
|
463
|
+
|
464
|
+
def test_multiple_class_inheritance
|
465
|
+
assert_renders <<SCSS, <<LESS
|
466
|
+
.foo {
|
467
|
+
a: b; }
|
468
|
+
|
469
|
+
.bar {
|
470
|
+
c: d; }
|
471
|
+
|
472
|
+
.baz {
|
473
|
+
@extend .foo;
|
474
|
+
@extend .bar; }
|
475
|
+
SCSS
|
476
|
+
.foo {a: b}
|
477
|
+
.bar {c: d}
|
478
|
+
.baz {.foo, .bar;}
|
479
|
+
LESS
|
480
|
+
end
|
481
|
+
|
482
|
+
def test_pseudoclass_inheritance
|
483
|
+
assert_renders <<SCSS, <<LESS
|
484
|
+
:foo {
|
485
|
+
a: b; }
|
486
|
+
|
487
|
+
:bar {
|
488
|
+
@extend :foo; }
|
489
|
+
SCSS
|
490
|
+
:foo {a: b}
|
491
|
+
:bar {:foo;}
|
492
|
+
LESS
|
493
|
+
end
|
494
|
+
|
495
|
+
def test_multiple_pseudoclass_inheritance
|
496
|
+
assert_renders <<SCSS, <<LESS
|
497
|
+
:foo:bar {
|
498
|
+
a: b; }
|
499
|
+
|
500
|
+
:baz {
|
501
|
+
@extend :foo:bar; }
|
502
|
+
SCSS
|
503
|
+
:foo:bar {a: b}
|
504
|
+
:baz {:foo:bar;}
|
505
|
+
LESS
|
506
|
+
end
|
507
|
+
|
508
|
+
def test_abstract_mixin
|
509
|
+
assert_renders <<SCSS, <<LESS
|
510
|
+
@mixin foo {
|
511
|
+
a: b; }
|
512
|
+
|
513
|
+
.bar {
|
514
|
+
@include foo; }
|
515
|
+
SCSS
|
516
|
+
.foo() {a: b}
|
517
|
+
.bar {.foo;}
|
518
|
+
LESS
|
519
|
+
end
|
520
|
+
|
521
|
+
def test_mixin_with_args
|
522
|
+
assert_renders <<SCSS, <<LESS
|
523
|
+
@mixin foo($a: 2px, $b: red) {
|
524
|
+
a: $a; }
|
525
|
+
|
526
|
+
.bar {
|
527
|
+
@include foo; }
|
528
|
+
SCSS
|
529
|
+
.foo(@a: 2px, @b: #f00) {a: @a}
|
530
|
+
.bar {.foo;}
|
531
|
+
LESS
|
532
|
+
|
533
|
+
assert_renders <<SCSS, <<LESS
|
534
|
+
@mixin foo($a: 2px + 3px, $b: red) {
|
535
|
+
a: $a; }
|
536
|
+
|
537
|
+
.bar {
|
538
|
+
@include foo(5px); }
|
539
|
+
SCSS
|
540
|
+
.foo(@a: 2px + 3px, @b: #f00) {a: @a}
|
541
|
+
.bar {.foo(5px);}
|
542
|
+
LESS
|
543
|
+
end
|
544
|
+
|
545
|
+
## Disallowed Mixins
|
546
|
+
|
547
|
+
def test_nested_mixin
|
548
|
+
assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
|
549
|
+
WARNING: Sass doesn't support mixing in selector sequences.
|
550
|
+
Replacing ".foo .bar" with "@extend .bar"
|
551
|
+
WARN
|
552
|
+
.foo .bar {
|
553
|
+
a: b; }
|
554
|
+
|
555
|
+
.bar {
|
556
|
+
// .foo .bar;
|
557
|
+
@extend .bar; }
|
558
|
+
SCSS
|
559
|
+
.foo .bar {a: b}
|
560
|
+
.bar {.foo .bar;}
|
561
|
+
LESS
|
562
|
+
end
|
563
|
+
|
564
|
+
def test_child_selector_mixin
|
565
|
+
assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
|
566
|
+
WARNING: Sass doesn't support mixing in selector sequences.
|
567
|
+
Replacing "> .bar" with "@extend .bar"
|
568
|
+
WARN
|
569
|
+
.foo > .bar {
|
570
|
+
a: b; }
|
571
|
+
|
572
|
+
.bar {
|
573
|
+
// > .bar;
|
574
|
+
@extend .bar; }
|
575
|
+
SCSS
|
576
|
+
.foo > .bar {a: b}
|
577
|
+
.bar {> .bar;}
|
578
|
+
LESS
|
579
|
+
end
|
580
|
+
|
581
|
+
# Accessors
|
582
|
+
|
583
|
+
def test_property_accessor
|
584
|
+
assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
|
585
|
+
WARNING: Sass doesn't support attribute accessors.
|
586
|
+
Ignoring .magic-box['content']
|
587
|
+
WARN
|
588
|
+
.magic-box {
|
589
|
+
content: "gold"; }
|
590
|
+
|
591
|
+
.foo {
|
592
|
+
content: /* .magic-box['content'] */; }
|
593
|
+
SCSS
|
594
|
+
.magic-box {content: "gold"}
|
595
|
+
.foo {content: .magic-box['content']}
|
596
|
+
LESS
|
597
|
+
end
|
598
|
+
|
599
|
+
def test_variable_accessor
|
600
|
+
assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
|
601
|
+
WARNING: Sass doesn't support attribute accessors.
|
602
|
+
Ignoring .magic-box[@content]
|
603
|
+
WARN
|
604
|
+
.magic-box {
|
605
|
+
$content: "gold";
|
606
|
+
content: $content; }
|
607
|
+
|
608
|
+
.foo {
|
609
|
+
content: /* .magic-box[@content] */; }
|
610
|
+
SCSS
|
611
|
+
.magic-box {@content: "gold"; content: @content}
|
612
|
+
.foo {content: .magic-box[@content]}
|
613
|
+
LESS
|
614
|
+
end
|
615
|
+
|
616
|
+
private
|
617
|
+
|
618
|
+
def assert_renders(scss, less)
|
619
|
+
assert_equal(scss, Less::Engine.new(less).to_tree.to_sass_tree.to_scss)
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
rescue LoadError => e
|
624
|
+
puts "\nCouldn't require less, skipping some tests."
|
625
|
+
end
|