haml 2.0.10 → 2.2.0
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/.yardopts +5 -0
- data/MIT-LICENSE +1 -1
- data/README.md +347 -0
- data/Rakefile +124 -19
- data/VERSION +1 -1
- data/VERSION_NAME +1 -0
- data/extra/haml-mode.el +397 -78
- data/extra/sass-mode.el +148 -36
- data/extra/update_watch.rb +13 -0
- data/lib/haml.rb +15 -993
- data/lib/haml/buffer.rb +131 -84
- data/lib/haml/engine.rb +129 -97
- data/lib/haml/error.rb +7 -7
- data/lib/haml/exec.rb +127 -42
- data/lib/haml/filters.rb +107 -42
- data/lib/haml/helpers.rb +210 -156
- data/lib/haml/helpers/action_view_extensions.rb +34 -39
- data/lib/haml/helpers/action_view_mods.rb +132 -139
- data/lib/haml/html.rb +77 -65
- data/lib/haml/precompiler.rb +404 -213
- data/lib/haml/shared.rb +78 -0
- data/lib/haml/template.rb +14 -14
- data/lib/haml/template/patch.rb +2 -2
- data/lib/haml/template/plugin.rb +2 -3
- data/lib/haml/util.rb +211 -6
- data/lib/haml/version.rb +30 -13
- data/lib/sass.rb +7 -856
- data/lib/sass/css.rb +169 -161
- data/lib/sass/engine.rb +344 -328
- data/lib/sass/environment.rb +79 -0
- data/lib/sass/error.rb +33 -11
- data/lib/sass/files.rb +139 -0
- data/lib/sass/plugin.rb +160 -117
- data/lib/sass/plugin/merb.rb +7 -6
- data/lib/sass/plugin/rails.rb +5 -6
- data/lib/sass/repl.rb +58 -0
- data/lib/sass/script.rb +59 -0
- data/lib/sass/script/bool.rb +17 -0
- data/lib/sass/script/color.rb +183 -0
- data/lib/sass/script/funcall.rb +50 -0
- data/lib/sass/script/functions.rb +198 -0
- data/lib/sass/script/lexer.rb +178 -0
- data/lib/sass/script/literal.rb +177 -0
- data/lib/sass/script/node.rb +14 -0
- data/lib/sass/script/number.rb +381 -0
- data/lib/sass/script/operation.rb +45 -0
- data/lib/sass/script/parser.rb +172 -0
- data/lib/sass/script/string.rb +12 -0
- data/lib/sass/script/unary_operation.rb +34 -0
- data/lib/sass/script/variable.rb +31 -0
- data/lib/sass/tree/comment_node.rb +73 -10
- data/lib/sass/tree/debug_node.rb +30 -0
- data/lib/sass/tree/directive_node.rb +42 -17
- data/lib/sass/tree/file_node.rb +41 -0
- data/lib/sass/tree/for_node.rb +48 -0
- data/lib/sass/tree/if_node.rb +54 -0
- data/lib/sass/tree/mixin_def_node.rb +29 -0
- data/lib/sass/tree/mixin_node.rb +48 -0
- data/lib/sass/tree/node.rb +214 -11
- data/lib/sass/tree/prop_node.rb +109 -0
- data/lib/sass/tree/rule_node.rb +178 -51
- data/lib/sass/tree/variable_node.rb +34 -0
- data/lib/sass/tree/while_node.rb +31 -0
- data/test/haml/engine_test.rb +331 -36
- data/test/haml/helper_test.rb +12 -1
- data/test/haml/results/content_for_layout.xhtml +0 -3
- data/test/haml/results/filters.xhtml +2 -0
- data/test/haml/results/list.xhtml +1 -1
- data/test/haml/template_test.rb +7 -2
- data/test/haml/templates/content_for_layout.haml +0 -2
- data/test/haml/templates/list.haml +1 -1
- data/test/haml/util_test.rb +92 -0
- data/test/sass/css2sass_test.rb +69 -24
- data/test/sass/engine_test.rb +586 -64
- data/test/sass/functions_test.rb +125 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +81 -28
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/{constants.css → script.css} +4 -4
- data/test/sass/results/subdir/subdir.css +2 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/script_test.rb +258 -0
- data/test/sass/templates/import.sass +1 -1
- data/test/sass/templates/importee.sass +7 -2
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/{constants.sass → script.sass} +11 -10
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/subdir.sass +2 -2
- data/test/sass/templates/units.sass +11 -0
- data/test/test_helper.rb +14 -0
- metadata +77 -19
- data/FAQ +0 -138
- data/README.rdoc +0 -319
- data/lib/sass/constant.rb +0 -216
- data/lib/sass/constant/color.rb +0 -101
- data/lib/sass/constant/literal.rb +0 -54
- data/lib/sass/constant/nil.rb +0 -9
- data/lib/sass/constant/number.rb +0 -87
- data/lib/sass/constant/operation.rb +0 -30
- data/lib/sass/constant/string.rb +0 -22
- data/lib/sass/tree/attr_node.rb +0 -57
- data/lib/sass/tree/value_node.rb +0 -20
data/test/haml/helper_test.rb
CHANGED
@@ -14,6 +14,12 @@ class HelperTest < Test::Unit::TestCase
|
|
14
14
|
def setup
|
15
15
|
@base = ActionView::Base.new
|
16
16
|
@base.controller = ActionController::Base.new
|
17
|
+
|
18
|
+
if defined?(ActionController::Response)
|
19
|
+
# This is needed for >=3.0.0
|
20
|
+
@base.controller.response = ActionController::Response.new
|
21
|
+
end
|
22
|
+
|
17
23
|
@base.instance_variable_set('@post', Post.new("Foo bar\nbaz"))
|
18
24
|
end
|
19
25
|
|
@@ -61,7 +67,7 @@ class HelperTest < Test::Unit::TestCase
|
|
61
67
|
|
62
68
|
begin
|
63
69
|
ActionView::Base.new.render(:inline => "<%= flatten('Foo\\nBar') %>")
|
64
|
-
rescue NoMethodError
|
70
|
+
rescue NoMethodError, ActionView::TemplateError
|
65
71
|
proper_behavior = true
|
66
72
|
end
|
67
73
|
assert(proper_behavior)
|
@@ -182,6 +188,11 @@ HAML
|
|
182
188
|
render("= find_and_preserve do\n %pre\n Foo\n Bar\n Foo\n Bar"))
|
183
189
|
end
|
184
190
|
|
191
|
+
def test_find_and_preserve_with_block_and_tags
|
192
|
+
assert_equal("<pre>Foo\nBar</pre>\nFoo\nBar\n",
|
193
|
+
render("= find_and_preserve([]) do\n %pre\n Foo\n Bar\n Foo\n Bar"))
|
194
|
+
end
|
195
|
+
|
185
196
|
def test_preserve_with_block
|
186
197
|
assert_equal("<pre>Foo
Bar</pre>
Foo
Bar\n",
|
187
198
|
render("= preserve do\n %pre\n Foo\n Bar\n Foo\n Bar"))
|
data/test/haml/template_test.rb
CHANGED
@@ -35,6 +35,10 @@ class DummyController
|
|
35
35
|
def self.controller_path
|
36
36
|
''
|
37
37
|
end
|
38
|
+
|
39
|
+
def controller_path
|
40
|
+
''
|
41
|
+
end
|
38
42
|
end
|
39
43
|
|
40
44
|
class TemplateTest < Test::Unit::TestCase
|
@@ -91,7 +95,8 @@ class TemplateTest < Test::Unit::TestCase
|
|
91
95
|
end
|
92
96
|
|
93
97
|
def assert_renders_correctly(name, &render_method)
|
94
|
-
if ActionPack::VERSION::MAJOR < 2 ||
|
98
|
+
if ActionPack::VERSION::MAJOR < 2 ||
|
99
|
+
(ActionPack::VERSION::MAJOR == 2 && ActionPack::VERSION::MINOR < 2)
|
95
100
|
render_method ||= proc { |name| @base.render(name) }
|
96
101
|
else
|
97
102
|
render_method ||= proc { |name| @base.render(:file => name) }
|
@@ -135,7 +140,7 @@ class TemplateTest < Test::Unit::TestCase
|
|
135
140
|
end
|
136
141
|
|
137
142
|
def test_action_view_templates_render_correctly
|
138
|
-
@base.
|
143
|
+
@base.content_for(:layout) {'Lorem ipsum dolor sit amet'}
|
139
144
|
assert_renders_correctly 'content_for_layout'
|
140
145
|
end
|
141
146
|
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
class UtilTest < Test::Unit::TestCase
|
6
|
+
include Haml::Util
|
7
|
+
|
8
|
+
def test_scope
|
9
|
+
assert(File.exist?(scope("Rakefile")))
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_to_hash
|
13
|
+
assert_equal({
|
14
|
+
:foo => 1,
|
15
|
+
:bar => 2,
|
16
|
+
:baz => 3
|
17
|
+
}, to_hash([[:foo, 1], [:bar, 2], [:baz, 3]]))
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_map_keys
|
21
|
+
assert_equal({
|
22
|
+
"foo" => 1,
|
23
|
+
"bar" => 2,
|
24
|
+
"baz" => 3
|
25
|
+
}, map_keys({:foo => 1, :bar => 2, :baz => 3}) {|k| k.to_s})
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_map_vals
|
29
|
+
assert_equal({
|
30
|
+
:foo => "1",
|
31
|
+
:bar => "2",
|
32
|
+
:baz => "3"
|
33
|
+
}, map_vals({:foo => 1, :bar => 2, :baz => 3}) {|k| k.to_s})
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_map_hash
|
37
|
+
assert_equal({
|
38
|
+
"foo" => "1",
|
39
|
+
"bar" => "2",
|
40
|
+
"baz" => "3"
|
41
|
+
}, map_hash({:foo => 1, :bar => 2, :baz => 3}) {|k, v| [k.to_s, v.to_s]})
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_powerset
|
45
|
+
return unless Set[Set[]] == Set[Set[]] # There's a bug in Ruby 1.8.6 that breaks nested set equality
|
46
|
+
assert_equal([[].to_set].to_set,
|
47
|
+
powerset([]))
|
48
|
+
assert_equal([[].to_set, [1].to_set].to_set,
|
49
|
+
powerset([1]))
|
50
|
+
assert_equal([[].to_set, [1].to_set, [2].to_set, [1, 2].to_set].to_set,
|
51
|
+
powerset([1, 2]))
|
52
|
+
assert_equal([[].to_set, [1].to_set, [2].to_set, [3].to_set,
|
53
|
+
[1, 2].to_set, [2, 3].to_set, [1, 3].to_set, [1, 2, 3].to_set].to_set,
|
54
|
+
powerset([1, 2, 3]))
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_has
|
58
|
+
assert(has?(:instance_method, String, :chomp!))
|
59
|
+
assert(has?(:private_instance_method, Haml::Engine, :set_locals))
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_enum_with_index
|
63
|
+
assert_equal(%w[foo0 bar1 baz2],
|
64
|
+
enum_with_index(%w[foo bar baz]).map {|s, i| "#{s}#{i}"})
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_def_static_method
|
68
|
+
klass = Class.new
|
69
|
+
def_static_method(klass, :static_method, [:arg1, :arg2],
|
70
|
+
:sarg1, :sarg2, <<RUBY)
|
71
|
+
s = "Always " + arg1
|
72
|
+
s << " <% if sarg1 %>and<% else %>but never<% end %> " << arg2
|
73
|
+
|
74
|
+
<% if sarg2 %>
|
75
|
+
s << "."
|
76
|
+
<% end %>
|
77
|
+
RUBY
|
78
|
+
c = klass.new
|
79
|
+
assert_equal("Always brush your teeth and comb your hair.",
|
80
|
+
c.send(static_method_name(:static_method, true, true),
|
81
|
+
"brush your teeth", "comb your hair"))
|
82
|
+
assert_equal("Always brush your teeth and comb your hair",
|
83
|
+
c.send(static_method_name(:static_method, true, false),
|
84
|
+
"brush your teeth", "comb your hair"))
|
85
|
+
assert_equal("Always brush your teeth but never play with fire.",
|
86
|
+
c.send(static_method_name(:static_method, false, true),
|
87
|
+
"brush your teeth", "play with fire"))
|
88
|
+
assert_equal("Always brush your teeth but never play with fire",
|
89
|
+
c.send(static_method_name(:static_method, false, false),
|
90
|
+
"brush your teeth", "play with fire"))
|
91
|
+
end
|
92
|
+
end
|
data/test/sass/css2sass_test.rb
CHANGED
@@ -11,27 +11,27 @@ h1 {
|
|
11
11
|
CSS
|
12
12
|
assert_equal(<<SASS, css2sass(css))
|
13
13
|
h1
|
14
|
-
:
|
14
|
+
color: red
|
15
15
|
SASS
|
16
|
-
assert_equal(<<SASS, css2sass(css, :
|
16
|
+
assert_equal(<<SASS, css2sass(css, :old => true))
|
17
17
|
h1
|
18
|
-
color
|
18
|
+
:color red
|
19
19
|
SASS
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_nesting
|
23
23
|
assert_equal(<<SASS, css2sass(<<CSS))
|
24
24
|
li
|
25
|
-
:
|
25
|
+
display: none
|
26
26
|
|
27
27
|
a
|
28
|
-
|
28
|
+
text-decoration: none
|
29
29
|
|
30
30
|
span
|
31
|
-
:
|
31
|
+
color: yellow
|
32
32
|
|
33
33
|
&:hover
|
34
|
-
|
34
|
+
text-decoration: underline
|
35
35
|
SASS
|
36
36
|
li {
|
37
37
|
display: none;
|
@@ -51,6 +51,28 @@ li a:hover {
|
|
51
51
|
CSS
|
52
52
|
end
|
53
53
|
|
54
|
+
def test_no_nesting_around_rules
|
55
|
+
assert_equal(<<SASS, css2sass(<<CSS))
|
56
|
+
div .warning
|
57
|
+
color: #d21a19
|
58
|
+
|
59
|
+
|
60
|
+
span .debug
|
61
|
+
cursor: crosshair
|
62
|
+
|
63
|
+
|
64
|
+
div .debug
|
65
|
+
cursor: default
|
66
|
+
SASS
|
67
|
+
div .warning {
|
68
|
+
color: #d21a19; }
|
69
|
+
span .debug {
|
70
|
+
cursor: crosshair;}
|
71
|
+
div .debug {
|
72
|
+
cursor: default; }
|
73
|
+
CSS
|
74
|
+
end
|
75
|
+
|
54
76
|
def test_comments_multiline
|
55
77
|
css = <<CSS
|
56
78
|
/* comment */
|
@@ -82,24 +104,24 @@ span.turkey {
|
|
82
104
|
CSS
|
83
105
|
sass = <<SASS
|
84
106
|
elephant.rawr
|
85
|
-
:
|
107
|
+
rampages: excessively
|
86
108
|
|
87
109
|
|
88
110
|
span.turkey
|
89
|
-
:
|
111
|
+
isdinner: true
|
90
112
|
|
91
113
|
|
92
114
|
.turducken
|
93
|
-
:
|
115
|
+
chimera: not_really
|
94
116
|
|
95
117
|
|
96
118
|
#overhere
|
97
|
-
:
|
98
|
-
:
|
119
|
+
bored: sorta
|
120
|
+
better_than: thread_pools
|
99
121
|
|
100
122
|
|
101
123
|
#one_more
|
102
|
-
:
|
124
|
+
finally: srsly
|
103
125
|
SASS
|
104
126
|
assert_equal(css2sass(css), sass)
|
105
127
|
end
|
@@ -108,7 +130,7 @@ SASS
|
|
108
130
|
assert_equal(<<SASS, css2sass(<<CSS))
|
109
131
|
li
|
110
132
|
.one, .two
|
111
|
-
:
|
133
|
+
color: red
|
112
134
|
SASS
|
113
135
|
li .one {
|
114
136
|
color: red;
|
@@ -120,16 +142,16 @@ CSS
|
|
120
142
|
|
121
143
|
assert_equal(<<SASS, css2sass(<<CSS))
|
122
144
|
.one
|
123
|
-
:
|
145
|
+
color: green
|
124
146
|
|
125
147
|
|
126
148
|
.two
|
127
|
-
:
|
128
|
-
:
|
149
|
+
color: green
|
150
|
+
color: red
|
129
151
|
|
130
152
|
|
131
153
|
.three
|
132
|
-
:
|
154
|
+
color: red
|
133
155
|
SASS
|
134
156
|
.one, .two {
|
135
157
|
color: green;
|
@@ -144,23 +166,23 @@ CSS
|
|
144
166
|
def test_bad_formatting
|
145
167
|
assert_equal(<<SASS, css2sass(<<CSS))
|
146
168
|
hello
|
147
|
-
:
|
169
|
+
parent: true
|
148
170
|
|
149
171
|
there
|
150
|
-
:
|
172
|
+
parent: false
|
151
173
|
|
152
174
|
who
|
153
|
-
:
|
175
|
+
hoo: false
|
154
176
|
|
155
177
|
why
|
156
|
-
:
|
178
|
+
y: true
|
157
179
|
|
158
180
|
when
|
159
|
-
:
|
181
|
+
wen: nao
|
160
182
|
|
161
183
|
|
162
184
|
down_here
|
163
|
-
:
|
185
|
+
yeah: true
|
164
186
|
SASS
|
165
187
|
hello {
|
166
188
|
parent: true;
|
@@ -185,6 +207,29 @@ down_here { yeah: true; }
|
|
185
207
|
CSS
|
186
208
|
end
|
187
209
|
|
210
|
+
def test_comments_in_selectors
|
211
|
+
assert_equal(<<SASS, css2sass(<<CSS))
|
212
|
+
.js
|
213
|
+
#location-navigation-form .form-submit, #business-listing-form .form-submit, #detailTabs ul, #detailsEnhanced #addTags, #locationSearchList, #moreHoods
|
214
|
+
display: none
|
215
|
+
|
216
|
+
|
217
|
+
#navListLeft
|
218
|
+
display: none
|
219
|
+
SASS
|
220
|
+
.js #location-navigation-form .form-submit,
|
221
|
+
.js #business-listing-form .form-submit,
|
222
|
+
.js #detailTabs ul,
|
223
|
+
/* .js #addReview, */
|
224
|
+
/* .js #addTags, */
|
225
|
+
.js #detailsEnhanced #addTags,
|
226
|
+
.js #locationSearchList,
|
227
|
+
.js #moreHoods,
|
228
|
+
#navListLeft
|
229
|
+
{ display: none; }
|
230
|
+
CSS
|
231
|
+
end
|
232
|
+
|
188
233
|
private
|
189
234
|
|
190
235
|
def css2sass(string, opts={})
|
data/test/sass/engine_test.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require File.dirname(__FILE__) + '/../test_helper'
|
3
3
|
require 'sass/engine'
|
4
|
+
require 'stringio'
|
4
5
|
|
5
6
|
class SassEngineTest < Test::Unit::TestCase
|
6
7
|
# A map of erroneous Sass documents to the error messages they should produce.
|
@@ -8,68 +9,104 @@ class SassEngineTest < Test::Unit::TestCase
|
|
8
9
|
# if so, the second element should be the line number that should be reported for the error.
|
9
10
|
# If this isn't provided, the tests will assume the line number should be the last line of the document.
|
10
11
|
EXCEPTION_MAP = {
|
11
|
-
"!a = 1 + " => '
|
12
|
-
"!a = 1 + 2 +" => '
|
13
|
-
"!a =
|
14
|
-
"!a =
|
15
|
-
"!a =
|
16
|
-
"!a =
|
17
|
-
"
|
18
|
-
"
|
19
|
-
"
|
20
|
-
"
|
21
|
-
"
|
22
|
-
":" => 'Invalid
|
23
|
-
":
|
24
|
-
"
|
25
|
-
"a\n :b" => 'Invalid
|
26
|
-
"a\n
|
27
|
-
"a\n
|
28
|
-
"a\n
|
29
|
-
"a
|
30
|
-
"
|
31
|
-
"a
|
32
|
-
"
|
33
|
-
"!" => 'Invalid
|
34
|
-
"!a" =>
|
35
|
-
"!
|
36
|
-
"!a
|
37
|
-
"a
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
"a
|
42
|
-
"a
|
43
|
-
"a\n :b c\n !d = 3" => "Constants may only be declared at the root of a document.",
|
44
|
-
"!a = 1b + 2c" => "Incompatible units: b and c.",
|
12
|
+
"!a = 1 + " => 'Expected expression, was end of text.',
|
13
|
+
"!a = 1 + 2 +" => 'Expected expression, was end of text.',
|
14
|
+
"!a = 1 + 2 + %" => 'Expected expression, was mod token.',
|
15
|
+
"!a = foo(\"bar\"" => 'Expected rparen token, was end of text.',
|
16
|
+
"!a = 1 }" => 'Unexpected end_interpolation token.',
|
17
|
+
"!a = 1 }foo\"" => 'Unexpected end_interpolation token.',
|
18
|
+
":" => 'Invalid property: ":".',
|
19
|
+
": a" => 'Invalid property: ": a".',
|
20
|
+
":= a" => 'Invalid property: ":= a".',
|
21
|
+
"a\n :b" => 'Invalid property: ":b " (no value).',
|
22
|
+
"a\n b:" => 'Invalid property: "b: " (no value).',
|
23
|
+
"a\n :b: c" => 'Invalid property: ":b: c".',
|
24
|
+
"a\n :b:c d" => 'Invalid property: ":b:c d".',
|
25
|
+
"a\n :b=c d" => 'Invalid property: ":b=c d".',
|
26
|
+
"a\n :b c;" => 'Invalid property: ":b c;" (no ";" required at end-of-line).',
|
27
|
+
"a\n b: c;" => 'Invalid property: "b: c;" (no ";" required at end-of-line).',
|
28
|
+
"a\n b : c" => 'Invalid property: "b : c".',
|
29
|
+
"a\n b=c: d" => 'Invalid property: "b=c: d".',
|
30
|
+
":a" => 'Properties aren\'t allowed at the root of a document.',
|
31
|
+
"!" => 'Invalid variable: "!".',
|
32
|
+
"!a" => 'Invalid variable: "!a".',
|
33
|
+
"! a" => 'Invalid variable: "! a".',
|
34
|
+
"!a b" => 'Invalid variable: "!a b".',
|
35
|
+
"!a = 1b + 2c" => "Incompatible units: 'c' and 'b'.",
|
36
|
+
"!a = 1b < 2c" => "Incompatible units: 'c' and 'b'.",
|
37
|
+
"!a = 1b > 2c" => "Incompatible units: 'c' and 'b'.",
|
38
|
+
"!a = 1b <= 2c" => "Incompatible units: 'c' and 'b'.",
|
39
|
+
"!a = 1b >= 2c" => "Incompatible units: 'c' and 'b'.",
|
40
|
+
"a\n :b= 1b * 2c" => "2b*c isn't a valid CSS value.",
|
41
|
+
"a\n :b= 1b % 2c" => "Cannot modulo by a number with units: 2c.",
|
42
|
+
"!a = 2px + #ccc" => "Cannot add a number with units (2px) to a color (#cccccc).",
|
43
|
+
"!a = #ccc + 2px" => "Cannot add a number with units (2px) to a color (#cccccc).",
|
45
44
|
"& a\n :b c" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
|
46
|
-
"a\n :b\n c" => "Illegal nesting: Only
|
47
|
-
"a,\n :b c" => "Rules can\'t end in commas.",
|
45
|
+
"a\n :b\n c" => "Illegal nesting: Only properties may be nested beneath properties.",
|
46
|
+
"a,\n :b c" => ["Rules can\'t end in commas.", 1],
|
48
47
|
"a," => "Rules can\'t end in commas.",
|
49
|
-
"a,\n!b =
|
50
|
-
"!a = b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath
|
48
|
+
"a,\n!b = 1" => ["Rules can\'t end in commas.", 1],
|
49
|
+
"!a = b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.",
|
51
50
|
"@import foo.sass" => "File to import not found or unreadable: foo.sass.",
|
52
51
|
"@import templates/basic\n foo" => "Illegal nesting: Nothing may be nested beneath import directives.",
|
53
52
|
"foo\n @import templates/basic" => "Import directives may only be used at the root of a document.",
|
54
53
|
"foo\n @import #{File.dirname(__FILE__)}/templates/basic" => "Import directives may only be used at the root of a document.",
|
55
|
-
|
56
|
-
"!foo = !(foo)" => "Invalid constant.",
|
54
|
+
%Q{!foo = "bar" "baz" !} => %Q{Syntax error in '"bar" "baz" !' at character 20.},
|
57
55
|
"=foo\n :color red\n.bar\n +bang" => "Undefined mixin 'bang'.",
|
58
|
-
".bar\n =foo\n :color red\n" => "Mixins may only be defined at the root of a document.",
|
56
|
+
".bar\n =foo\n :color red\n" => ["Mixins may only be defined at the root of a document.", 2],
|
59
57
|
"=foo\n :color red\n.bar\n +foo\n :color red" => "Illegal nesting: Nothing may be nested beneath mixin directives.",
|
60
58
|
" a\n b: c" => ["Indenting at the beginning of the document is illegal.", 1],
|
61
59
|
" \n \n\t\n a\n b: c" => ["Indenting at the beginning of the document is illegal.", 4],
|
60
|
+
"a\n b: c\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 3],
|
61
|
+
"a\n b: c\na\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 4],
|
62
|
+
"a\n\t\tb: c\n\tb: c" => ["Inconsistent indentation: 1 tab was used for indentation, but the rest of the document was indented using 2 tabs.", 3],
|
63
|
+
"a\n b: c\n b: c" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces.", 3],
|
64
|
+
"a\n b: c\n a\n d: e" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces.", 4],
|
65
|
+
"a\n b: c\na\n d: e" => ["The line was indented 2 levels deeper than the previous line.", 4],
|
66
|
+
"a\n b: c\n a\n d: e" => ["The line was indented 3 levels deeper than the previous line.", 4],
|
67
|
+
"a\n \tb: c" => ["Indentation can't use both tabs and spaces.", 2],
|
68
|
+
"=a(" => 'Invalid mixin "a(".',
|
69
|
+
"=a(b)" => 'Mixin argument "b" must begin with an exclamation point (!).',
|
70
|
+
"=a(,)" => "Mixin arguments can't be empty.",
|
71
|
+
"=a(!)" => "Mixin arguments can't be empty.",
|
72
|
+
"=a(!foo bar)" => "Invalid variable \"!foo bar\".",
|
73
|
+
"=foo\n bar: baz\n+foo" => ["Properties aren't allowed at the root of a document.", 2],
|
74
|
+
"a-\#{!b\n c: d" => ["Expected end_interpolation token, was end of text.", 1],
|
75
|
+
"=a(!b = 1, !c)" => "Required arguments must not follow optional arguments \"!c\".",
|
76
|
+
"=a(!b = 1)\n :a= !b\ndiv\n +a(1,2)" => "Mixin a takes 1 argument but 2 were passed.",
|
77
|
+
"=a(!b)\n :a= !b\ndiv\n +a" => "Mixin a is missing parameter !b.",
|
78
|
+
"@else\n a\n b: c" => ["@else must come after @if.", 1],
|
79
|
+
"@if false\n@else foo" => "Invalid else directive '@else foo': expected 'if <expr>'.",
|
80
|
+
"@if false\n@else if " => "Invalid else directive '@else if': expected 'if <expr>'.",
|
81
|
+
"a\n !b = 12\nc\n d = !b" => 'Undefined variable: "!b".',
|
82
|
+
"=foo\n !b = 12\nc\n +foo\n d = !b" => 'Undefined variable: "!b".',
|
83
|
+
'@for !a from "foo" to 1' => '"foo" is not an integer.',
|
84
|
+
'@for !a from 1 to "2"' => '"2" is not an integer.',
|
85
|
+
'@for !a from 1 to "foo"' => '"foo" is not an integer.',
|
86
|
+
'@for !a from 1 to 1.232323' => '1.232 is not an integer.',
|
87
|
+
'@for !a from 1px to 3em' => "Incompatible units: 'em' and 'px'.",
|
88
|
+
'@if' => "Invalid if directive '@if': expected expression.",
|
89
|
+
'@while' => "Invalid while directive '@while': expected expression.",
|
90
|
+
'@debug' => "Invalid debug directive '@debug': expected expression.",
|
62
91
|
|
63
92
|
# Regression tests
|
64
|
-
"a\n b:\n c\n d" => ["Illegal nesting: Only
|
93
|
+
"a\n b:\n c\n d" => ["Illegal nesting: Only properties may be nested beneath properties.", 3],
|
65
94
|
"& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
|
66
95
|
"a\n b: c\n& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 3],
|
67
96
|
}
|
68
|
-
|
97
|
+
|
98
|
+
def teardown
|
99
|
+
clean_up_sassc
|
100
|
+
end
|
101
|
+
|
69
102
|
def test_basic_render
|
70
103
|
renders_correctly "basic", { :style => :compact }
|
71
104
|
end
|
72
105
|
|
106
|
+
def test_empty_render
|
107
|
+
assert_equal "", render("")
|
108
|
+
end
|
109
|
+
|
73
110
|
def test_multiple_calls_to_render
|
74
111
|
sass = Sass::Engine.new("a\n b: c")
|
75
112
|
assert_equal sass.render, sass.render
|
@@ -82,16 +119,25 @@ END
|
|
82
119
|
renders_correctly "compressed", { :style => :compressed }
|
83
120
|
end
|
84
121
|
|
122
|
+
def test_flexible_tabulation
|
123
|
+
assert_equal("p {\n a: b; }\n p q {\n c: d; }\n",
|
124
|
+
render("p\n a: b\n q\n c: d\n"))
|
125
|
+
assert_equal("p {\n a: b; }\n p q {\n c: d; }\n",
|
126
|
+
render("p\n\ta: b\n\tq\n\t\tc: d\n"))
|
127
|
+
end
|
128
|
+
|
85
129
|
def test_exceptions
|
86
130
|
EXCEPTION_MAP.each do |key, value|
|
131
|
+
line = 10
|
87
132
|
begin
|
88
|
-
Sass::Engine.new(key).render
|
133
|
+
Sass::Engine.new(key, :filename => __FILE__, :line => line).render
|
89
134
|
rescue Sass::SyntaxError => err
|
90
135
|
value = [value] unless value.is_a?(Array)
|
91
136
|
|
92
137
|
assert_equal(value.first, err.message, "Line: #{key}")
|
93
|
-
assert_equal(
|
94
|
-
|
138
|
+
assert_equal(__FILE__, err.sass_filename)
|
139
|
+
assert_equal((value[1] || key.split("\n").length) + line - 1, err.sass_line, "Line: #{key}")
|
140
|
+
assert_match(/#{Regexp.escape(__FILE__)}:[0-9]+/, err.backtrace[0], "Line: #{key}")
|
95
141
|
else
|
96
142
|
assert(false, "Exception not raised for\n#{key}")
|
97
143
|
end
|
@@ -101,7 +147,7 @@ END
|
|
101
147
|
def test_exception_line
|
102
148
|
to_render = <<SASS
|
103
149
|
rule
|
104
|
-
:
|
150
|
+
:prop val
|
105
151
|
// comment!
|
106
152
|
|
107
153
|
:broken
|
@@ -115,9 +161,26 @@ SASS
|
|
115
161
|
end
|
116
162
|
end
|
117
163
|
|
164
|
+
def test_exception_location
|
165
|
+
to_render = <<SASS
|
166
|
+
rule
|
167
|
+
:prop val
|
168
|
+
// comment!
|
169
|
+
|
170
|
+
:broken
|
171
|
+
SASS
|
172
|
+
begin
|
173
|
+
Sass::Engine.new(to_render, :filename => __FILE__, :line => (__LINE__-7)).render
|
174
|
+
rescue Sass::SyntaxError => err
|
175
|
+
assert_equal(__FILE__, err.sass_filename)
|
176
|
+
assert_equal((__LINE__-6), err.sass_line)
|
177
|
+
else
|
178
|
+
assert(false, "Exception not raised for '#{to_render}'!")
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
118
182
|
def test_imported_exception
|
119
|
-
[
|
120
|
-
i = nil if i == 1
|
183
|
+
[nil, 2].each do |i|
|
121
184
|
begin
|
122
185
|
Sass::Engine.new("@import bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
|
123
186
|
rescue Sass::SyntaxError => err
|
@@ -130,19 +193,44 @@ SASS
|
|
130
193
|
end
|
131
194
|
|
132
195
|
def test_css_import
|
133
|
-
assert_equal("@import url(./fonts.css) screen
|
134
|
-
assert_equal("@import \"./fonts.css\" screen
|
196
|
+
assert_equal("@import url(./fonts.css) screen;\n", render("@import url(./fonts.css) screen"))
|
197
|
+
assert_equal("@import \"./fonts.css\" screen;\n", render("@import \"./fonts.css\" screen"))
|
135
198
|
end
|
136
199
|
|
137
200
|
def test_sass_import
|
201
|
+
assert !File.exists?(sassc_path("importee"))
|
138
202
|
renders_correctly "import", { :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"] }
|
203
|
+
assert File.exists?(sassc_path("importee"))
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_no_cache
|
207
|
+
assert !File.exists?(sassc_path("importee"))
|
208
|
+
renders_correctly("import", {
|
209
|
+
:style => :compact, :cache => false,
|
210
|
+
:load_paths => [File.dirname(__FILE__) + "/templates"],
|
211
|
+
})
|
212
|
+
assert !File.exists?(sassc_path("importee"))
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_units
|
216
|
+
renders_correctly "units"
|
139
217
|
end
|
140
218
|
|
141
219
|
def test_default_function
|
142
|
-
assert_equal("foo {\n bar: url(foo.png); }\n", render(
|
220
|
+
assert_equal("foo {\n bar: url(foo.png); }\n", render(%Q{foo\n bar = url("foo.png")\n}));
|
143
221
|
assert_equal("foo {\n bar: url(); }\n", render("foo\n bar = url()\n"));
|
144
222
|
end
|
145
223
|
|
224
|
+
def test_string_minus
|
225
|
+
assert_equal("foo {\n bar: baz-boom-bat; }\n", render(%Q{foo\n bar = "baz"-"boom"-"bat"}))
|
226
|
+
assert_equal("foo {\n bar: -baz-boom; }\n", render(%Q{foo\n bar = -"baz"-"boom"}))
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_string_div
|
230
|
+
assert_equal("foo {\n bar: baz/boom/bat; }\n", render(%Q{foo\n bar = "baz"/"boom"/"bat"}))
|
231
|
+
assert_equal("foo {\n bar: /baz/boom; }\n", render(%Q{foo\n bar = /"baz"/"boom"}))
|
232
|
+
end
|
233
|
+
|
146
234
|
def test_basic_multiline_selector
|
147
235
|
assert_equal("#foo #bar,\n#baz #boom {\n foo: bar; }\n",
|
148
236
|
render("#foo #bar,\n#baz #boom\n :foo bar"))
|
@@ -163,21 +251,21 @@ SASS
|
|
163
251
|
|
164
252
|
def test_colon_only
|
165
253
|
begin
|
166
|
-
render("a\n b: c", :
|
254
|
+
render("a\n b: c", :property_syntax => :old)
|
167
255
|
rescue Sass::SyntaxError => e
|
168
|
-
assert_equal("Illegal
|
256
|
+
assert_equal("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.",
|
169
257
|
e.message)
|
170
258
|
else
|
171
|
-
assert(false, "SyntaxError not raised for :
|
259
|
+
assert(false, "SyntaxError not raised for :property_syntax => :old")
|
172
260
|
end
|
173
261
|
|
174
262
|
begin
|
175
|
-
render("a\n :b c", :
|
263
|
+
render("a\n :b c", :property_syntax => :new)
|
176
264
|
rescue Sass::SyntaxError => e
|
177
|
-
assert_equal("Illegal
|
265
|
+
assert_equal("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.",
|
178
266
|
e.message)
|
179
267
|
else
|
180
|
-
assert(false, "SyntaxError not raised for :
|
268
|
+
assert(false, "SyntaxError not raised for :property_syntax => :new")
|
181
269
|
end
|
182
270
|
end
|
183
271
|
|
@@ -192,7 +280,7 @@ SASS
|
|
192
280
|
end
|
193
281
|
|
194
282
|
def test_directive
|
195
|
-
assert_equal("@a b
|
283
|
+
assert_equal("@a b;\n", render("@a b"))
|
196
284
|
|
197
285
|
assert_equal("@a {\n b: c; }\n", render("@a\n :b c"))
|
198
286
|
assert_equal("@a { b: c; }\n", render("@a\n :b c", :style => :compact))
|
@@ -252,6 +340,54 @@ END
|
|
252
340
|
assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed))
|
253
341
|
end
|
254
342
|
|
343
|
+
def test_line_annotations
|
344
|
+
assert_equal(<<CSS, render(<<SASS, :line_comments => true, :style => :compact))
|
345
|
+
/* line 2, test_line_annotations_inline.sass */
|
346
|
+
foo bar { foo: bar; }
|
347
|
+
/* line 5, test_line_annotations_inline.sass */
|
348
|
+
foo baz { blip: blop; }
|
349
|
+
|
350
|
+
/* line 9, test_line_annotations_inline.sass */
|
351
|
+
floodle { flop: blop; }
|
352
|
+
|
353
|
+
/* line 18, test_line_annotations_inline.sass */
|
354
|
+
bup { mix: on; }
|
355
|
+
/* line 15, test_line_annotations_inline.sass */
|
356
|
+
bup mixin { moop: mup; }
|
357
|
+
|
358
|
+
/* line 22, test_line_annotations_inline.sass */
|
359
|
+
bip hop, skip hop { a: b; }
|
360
|
+
CSS
|
361
|
+
foo
|
362
|
+
bar
|
363
|
+
foo: bar
|
364
|
+
|
365
|
+
baz
|
366
|
+
blip: blop
|
367
|
+
|
368
|
+
|
369
|
+
floodle
|
370
|
+
|
371
|
+
flop: blop
|
372
|
+
|
373
|
+
=mxn
|
374
|
+
mix: on
|
375
|
+
mixin
|
376
|
+
moop: mup
|
377
|
+
|
378
|
+
bup
|
379
|
+
+mxn
|
380
|
+
|
381
|
+
bip, skip
|
382
|
+
hop
|
383
|
+
a: b
|
384
|
+
SASS
|
385
|
+
end
|
386
|
+
|
387
|
+
def test_line_annotations_with_filename
|
388
|
+
renders_correctly "line_numbers", :line_comments => true, :load_paths => [File.dirname(__FILE__) + "/templates"]
|
389
|
+
end
|
390
|
+
|
255
391
|
def test_empty_first_line
|
256
392
|
assert_equal("#a {\n b: c; }\n", render("#a\n\n b: c"))
|
257
393
|
end
|
@@ -266,8 +402,8 @@ END
|
|
266
402
|
end
|
267
403
|
|
268
404
|
def test_or_eq
|
269
|
-
assert_equal("foo {\n a: b; }\n", render(
|
270
|
-
assert_equal("foo {\n a: b; }\n", render(
|
405
|
+
assert_equal("foo {\n a: b; }\n", render(%Q{!foo = "b"\n!foo ||= "c"\nfoo\n a = !foo}))
|
406
|
+
assert_equal("foo {\n a: b; }\n", render(%Q{!foo ||= "b"\nfoo\n a = !foo}))
|
271
407
|
end
|
272
408
|
|
273
409
|
def test_mixins
|
@@ -275,27 +411,413 @@ END
|
|
275
411
|
end
|
276
412
|
|
277
413
|
def test_mixins_dont_interfere_with_sibling_combinator
|
278
|
-
assert_equal("foo + bar {\n a: b; }\n", render("foo\n + bar\n a: b"))
|
279
414
|
assert_equal("foo + bar {\n a: b; }\nfoo + baz {\n c: d; }\n",
|
280
415
|
render("foo\n +\n bar\n a: b\n baz\n c: d"))
|
281
416
|
end
|
282
417
|
|
283
|
-
|
418
|
+
def test_mixin_args
|
419
|
+
assert_equal("blat {\n baz: hi; }\n", render(<<SASS))
|
420
|
+
=foo(!bar)
|
421
|
+
baz = !bar
|
422
|
+
blat
|
423
|
+
+foo(\"hi\")
|
424
|
+
SASS
|
425
|
+
assert_equal("blat {\n baz: 3; }\n", render(<<SASS))
|
426
|
+
=foo(!a, !b)
|
427
|
+
baz = !a + !b
|
428
|
+
blat
|
429
|
+
+foo(1, 2)
|
430
|
+
SASS
|
431
|
+
assert_equal("blat {\n baz: 4;\n baz: 3;\n baz: 5;\n bang: 3; }\n", render(<<SASS))
|
432
|
+
=foo(!c = (6 + 4) / 2)
|
433
|
+
baz = !c
|
434
|
+
!c = 3
|
435
|
+
blat
|
436
|
+
+foo(!c + 1)
|
437
|
+
+foo((!c + 3)/2)
|
438
|
+
+foo
|
439
|
+
bang = !c
|
440
|
+
SASS
|
441
|
+
end
|
442
|
+
|
443
|
+
def test_default_values_for_mixin_arguments
|
444
|
+
assert_equal("white {\n color: white; }\n\nblack {\n color: black; }\n", render(<<SASS))
|
445
|
+
=foo(!a = #FFF)
|
446
|
+
:color= !a
|
447
|
+
white
|
448
|
+
+foo
|
449
|
+
black
|
450
|
+
+foo(#000)
|
451
|
+
SASS
|
452
|
+
assert_equal(<<CSS, render(<<SASS))
|
453
|
+
one {
|
454
|
+
color: white;
|
455
|
+
padding: 1px;
|
456
|
+
margin: 4px; }
|
457
|
+
|
458
|
+
two {
|
459
|
+
color: white;
|
460
|
+
padding: 2px;
|
461
|
+
margin: 5px; }
|
462
|
+
|
463
|
+
three {
|
464
|
+
color: white;
|
465
|
+
padding: 2px;
|
466
|
+
margin: 3px; }
|
467
|
+
CSS
|
468
|
+
!a = 5px
|
469
|
+
=foo(!a, !b = 1px, !c = 3px + !b)
|
470
|
+
:color= !a
|
471
|
+
:padding= !b
|
472
|
+
:margin= !c
|
473
|
+
one
|
474
|
+
+foo(#fff)
|
475
|
+
two
|
476
|
+
+foo(#fff, 2px)
|
477
|
+
three
|
478
|
+
+foo(#fff, 2px, 3px)
|
479
|
+
SASS
|
480
|
+
end
|
481
|
+
|
482
|
+
def test_interpolation
|
483
|
+
assert_equal("a-1 {\n b-2-3: c-3; }\n", render(<<SASS))
|
484
|
+
!a = 1
|
485
|
+
!b = 2
|
486
|
+
!c = 3
|
487
|
+
a-\#{!a}
|
488
|
+
b-\#{!b}-\#{!c}: c-\#{!a + !b}
|
489
|
+
SASS
|
490
|
+
end
|
491
|
+
|
492
|
+
def test_if_directive
|
493
|
+
assert_equal("a {\n b: 1; }\n", render(<<SASS))
|
494
|
+
!var = true
|
495
|
+
a
|
496
|
+
@if !var
|
497
|
+
b: 1
|
498
|
+
@if not !var
|
499
|
+
b: 2
|
500
|
+
SASS
|
501
|
+
end
|
502
|
+
|
503
|
+
def test_for
|
504
|
+
assert_equal(<<CSS, render(<<SASS))
|
505
|
+
a-0 {
|
506
|
+
2i: 0; }
|
507
|
+
|
508
|
+
a-1 {
|
509
|
+
2i: 2; }
|
510
|
+
|
511
|
+
a-2 {
|
512
|
+
2i: 4; }
|
513
|
+
|
514
|
+
a-3 {
|
515
|
+
2i: 6; }
|
516
|
+
|
517
|
+
b-1 {
|
518
|
+
j-1: 0; }
|
519
|
+
|
520
|
+
b-2 {
|
521
|
+
j-1: 1; }
|
522
|
+
|
523
|
+
b-3 {
|
524
|
+
j-1: 2; }
|
525
|
+
|
526
|
+
b-4 {
|
527
|
+
j-1: 3; }
|
528
|
+
CSS
|
529
|
+
!a = 3
|
530
|
+
@for !i from 0 to !a + 1
|
531
|
+
a-\#{!i}
|
532
|
+
2i = 2 * !i
|
533
|
+
|
534
|
+
@for !j from 1 through 4
|
535
|
+
b-\#{!j}
|
536
|
+
j-1 = !j - 1
|
537
|
+
SASS
|
538
|
+
end
|
539
|
+
|
540
|
+
def test_while
|
541
|
+
assert_equal(<<CSS, render(<<SASS))
|
542
|
+
a-5 {
|
543
|
+
blooble: gloop; }
|
544
|
+
|
545
|
+
a-4 {
|
546
|
+
blooble: gloop; }
|
284
547
|
|
548
|
+
a-3 {
|
549
|
+
blooble: gloop; }
|
550
|
+
|
551
|
+
a-2 {
|
552
|
+
blooble: gloop; }
|
553
|
+
|
554
|
+
a-1 {
|
555
|
+
blooble: gloop; }
|
556
|
+
CSS
|
557
|
+
!a = 5
|
558
|
+
@while !a != 0
|
559
|
+
a-\#{!a}
|
560
|
+
blooble: gloop
|
561
|
+
!a = !a - 1
|
562
|
+
SASS
|
563
|
+
end
|
564
|
+
|
565
|
+
def test_else
|
566
|
+
assert_equal(<<CSS, render(<<SASS))
|
567
|
+
a {
|
568
|
+
t1: t;
|
569
|
+
t2: t;
|
570
|
+
t3: t;
|
571
|
+
t4: t; }
|
572
|
+
CSS
|
573
|
+
a
|
574
|
+
@if true
|
575
|
+
t1: t
|
576
|
+
@else
|
577
|
+
f1: f
|
578
|
+
|
579
|
+
@if false
|
580
|
+
f2: f
|
581
|
+
@else
|
582
|
+
t2: t
|
583
|
+
|
584
|
+
@if false
|
585
|
+
f3: f1
|
586
|
+
@else if 1 + 1 == 3
|
587
|
+
f3: f2
|
588
|
+
@else
|
589
|
+
t3: t
|
590
|
+
|
591
|
+
@if false
|
592
|
+
f4: f1
|
593
|
+
@else if 1 + 1 == 2
|
594
|
+
t4: t
|
595
|
+
@else
|
596
|
+
f4: f2
|
597
|
+
|
598
|
+
@if false
|
599
|
+
f5: f1
|
600
|
+
@else if false
|
601
|
+
f5: f2
|
602
|
+
SASS
|
603
|
+
end
|
604
|
+
|
605
|
+
def test_variable_reassignment
|
606
|
+
assert_equal(<<CSS, render(<<SASS))
|
607
|
+
a {
|
608
|
+
b: 1;
|
609
|
+
c: 2; }
|
610
|
+
CSS
|
611
|
+
!a = 1
|
612
|
+
a
|
613
|
+
b = !a
|
614
|
+
!a = 2
|
615
|
+
c = !a
|
616
|
+
SASS
|
617
|
+
end
|
618
|
+
|
619
|
+
def test_variable_scope
|
620
|
+
assert_equal(<<CSS, render(<<SASS))
|
621
|
+
a {
|
622
|
+
b-1: c;
|
623
|
+
b-2: c;
|
624
|
+
d: 12; }
|
625
|
+
|
626
|
+
b {
|
627
|
+
d: 17; }
|
628
|
+
CSS
|
629
|
+
!i = 12
|
630
|
+
a
|
631
|
+
@for !i from 1 through 2
|
632
|
+
b-\#{!i}: c
|
633
|
+
d = !i
|
634
|
+
|
635
|
+
=foo
|
636
|
+
!i = 17
|
637
|
+
|
638
|
+
b
|
639
|
+
+foo
|
640
|
+
d = !i
|
641
|
+
SASS
|
642
|
+
end
|
643
|
+
|
644
|
+
def test_argument_error
|
645
|
+
assert_raise(Sass::SyntaxError) { render("a\n b = hsl(1)") }
|
646
|
+
end
|
647
|
+
|
648
|
+
def test_comments_at_the_top_of_a_document
|
649
|
+
render(<<SASS)
|
650
|
+
//
|
651
|
+
This is a comment that
|
652
|
+
continues to the second line.
|
653
|
+
foo
|
654
|
+
bar: baz
|
655
|
+
SASS
|
656
|
+
end
|
657
|
+
|
658
|
+
def test_loud_comments_containing_a_comment_close
|
659
|
+
actual_css = render(<<SASS)
|
660
|
+
/*
|
661
|
+
This is a comment that
|
662
|
+
continues to the second line. */
|
663
|
+
foo
|
664
|
+
bar: baz
|
665
|
+
SASS
|
666
|
+
assert_equal(<<CSS, actual_css)
|
667
|
+
/* This is a comment that
|
668
|
+
* continues to the second line. */
|
669
|
+
foo {
|
670
|
+
bar: baz; }
|
671
|
+
CSS
|
672
|
+
end
|
673
|
+
|
674
|
+
def test_quoted_colon
|
675
|
+
assert_equal(<<CSS, render(<<SASS))
|
676
|
+
a b[foo="bar: baz"] {
|
677
|
+
c: d; }
|
678
|
+
CSS
|
679
|
+
a
|
680
|
+
b[foo="bar: baz"]
|
681
|
+
c: d
|
682
|
+
SASS
|
683
|
+
end
|
684
|
+
|
685
|
+
def test_quoted_comma
|
686
|
+
assert_equal(<<CSS, render(<<SASS))
|
687
|
+
a b[foo="bar, baz"] {
|
688
|
+
c: d; }
|
689
|
+
CSS
|
690
|
+
a
|
691
|
+
b[foo="bar, baz"]
|
692
|
+
c: d
|
693
|
+
SASS
|
694
|
+
end
|
695
|
+
|
696
|
+
def test_quoted_ampersand
|
697
|
+
assert_equal(<<CSS, render(<<SASS))
|
698
|
+
a b[foo="bar & baz"] {
|
699
|
+
c: d; }
|
700
|
+
CSS
|
701
|
+
a
|
702
|
+
b[foo="bar & baz"]
|
703
|
+
c: d
|
704
|
+
SASS
|
705
|
+
end
|
706
|
+
|
707
|
+
# Regression tests
|
708
|
+
|
709
|
+
def test_comment_beneath_prop
|
710
|
+
assert_equal(<<RESULT, render(<<SOURCE))
|
711
|
+
.box {
|
712
|
+
border-style: solid; }
|
713
|
+
RESULT
|
714
|
+
.box
|
715
|
+
:border
|
716
|
+
//:color black
|
717
|
+
:style solid
|
718
|
+
SOURCE
|
719
|
+
|
720
|
+
assert_equal(<<RESULT, render(<<SOURCE))
|
721
|
+
.box {
|
722
|
+
/* :color black */
|
723
|
+
border-style: solid; }
|
724
|
+
RESULT
|
725
|
+
.box
|
726
|
+
:border
|
727
|
+
/*:color black
|
728
|
+
:style solid
|
729
|
+
SOURCE
|
730
|
+
|
731
|
+
assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
|
732
|
+
.box{border-style:solid}
|
733
|
+
RESULT
|
734
|
+
.box
|
735
|
+
:border
|
736
|
+
/*:color black
|
737
|
+
:style solid
|
738
|
+
SOURCE
|
739
|
+
end
|
740
|
+
|
741
|
+
def test_compressed_comment_beneath_directive
|
742
|
+
assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
|
743
|
+
@foo{a:b}
|
744
|
+
RESULT
|
745
|
+
@foo
|
746
|
+
a: b
|
747
|
+
/*b: c
|
748
|
+
SOURCE
|
749
|
+
end
|
750
|
+
|
751
|
+
def test_comment_with_crazy_indentation
|
752
|
+
assert_equal(<<CSS, render(<<SASS))
|
753
|
+
/* This is a loud comment:
|
754
|
+
* Where the indentation is wonky. */
|
755
|
+
.comment {
|
756
|
+
width: 1px; }
|
757
|
+
CSS
|
758
|
+
/*
|
759
|
+
This is a loud comment:
|
760
|
+
Where the indentation is wonky.
|
761
|
+
//
|
762
|
+
This is a silent comment:
|
763
|
+
Where the indentation is wonky.
|
764
|
+
.comment
|
765
|
+
width: 1px
|
766
|
+
SASS
|
767
|
+
end
|
768
|
+
|
769
|
+
def test_plus_with_space
|
770
|
+
assert_equal(<<CSS, render(<<SASS))
|
771
|
+
a + b {
|
772
|
+
color: green; }
|
773
|
+
CSS
|
774
|
+
a
|
775
|
+
+ b
|
776
|
+
color: green
|
777
|
+
SASS
|
778
|
+
end
|
779
|
+
|
780
|
+
def test_empty_line_comment
|
781
|
+
assert_equal(<<CSS, render(<<SASS))
|
782
|
+
/* Foo
|
783
|
+
*
|
784
|
+
* Bar */
|
785
|
+
CSS
|
786
|
+
/*
|
787
|
+
Foo
|
788
|
+
|
789
|
+
Bar
|
790
|
+
SASS
|
791
|
+
end
|
792
|
+
|
793
|
+
private
|
794
|
+
|
285
795
|
def render(sass, options = {})
|
796
|
+
munge_filename options
|
286
797
|
Sass::Engine.new(sass, options).render
|
287
798
|
end
|
288
799
|
|
289
800
|
def renders_correctly(name, options={})
|
290
801
|
sass_file = load_file(name, "sass")
|
291
802
|
css_file = load_file(name, "css")
|
803
|
+
options[:filename] ||= filename(name, "sass")
|
804
|
+
options[:css_filename] ||= filename(name, "css")
|
292
805
|
css_result = Sass::Engine.new(sass_file, options).render
|
293
806
|
assert_equal css_file, css_result
|
294
807
|
end
|
295
808
|
|
296
809
|
def load_file(name, type = "sass")
|
297
810
|
@result = ''
|
298
|
-
File.new(
|
811
|
+
File.new(filename(name, type)).each_line { |l| @result += l }
|
299
812
|
@result
|
300
813
|
end
|
814
|
+
|
815
|
+
def filename(name, type)
|
816
|
+
File.dirname(__FILE__) + "/#{type == 'sass' ? 'templates' : 'results'}/#{name}.#{type}"
|
817
|
+
end
|
818
|
+
|
819
|
+
def sassc_path(template)
|
820
|
+
sassc_path = File.join(File.dirname(__FILE__) + "/templates/#{template}.sass")
|
821
|
+
Sass::Files.send(:sassc_filename, sassc_path, Sass::Engine::DEFAULT_OPTIONS)
|
822
|
+
end
|
301
823
|
end
|