haml 3.0.0.beta.3 → 3.0.0.rc.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.
- data/.yardopts +2 -0
- data/REMEMBER +4 -11
- data/Rakefile +24 -2
- data/VERSION +1 -1
- data/lib/haml.rb +5 -2
- data/lib/haml/exec.rb +11 -4
- data/lib/haml/filters.rb +3 -0
- data/lib/haml/helpers.rb +2 -10
- data/lib/haml/helpers/action_view_extensions.rb +4 -2
- data/lib/haml/helpers/action_view_mods.rb +6 -4
- data/lib/haml/html.rb +0 -1
- data/lib/haml/precompiler.rb +37 -30
- data/lib/haml/railtie.rb +6 -2
- data/lib/haml/root.rb +4 -0
- data/lib/haml/template.rb +2 -0
- data/lib/haml/util.rb +74 -0
- data/lib/haml/util/subset_map.rb +101 -0
- data/lib/sass.rb +1 -0
- data/lib/sass/engine.rb +36 -31
- data/lib/sass/files.rb +1 -1
- data/lib/sass/plugin.rb +21 -0
- data/lib/sass/plugin/staleness_checker.rb +9 -9
- data/lib/sass/script.rb +1 -2
- data/lib/sass/script/color.rb +4 -3
- data/lib/sass/script/css_lexer.rb +11 -1
- data/lib/sass/script/css_parser.rb +4 -1
- data/lib/sass/script/funcall.rb +9 -0
- data/lib/sass/script/interpolation.rb +21 -0
- data/lib/sass/script/lexer.rb +30 -13
- data/lib/sass/script/node.rb +1 -1
- data/lib/sass/script/number.rb +4 -5
- data/lib/sass/script/parser.rb +13 -14
- data/lib/sass/script/string.rb +8 -2
- data/lib/sass/script/string_interpolation.rb +27 -4
- data/lib/sass/scss.rb +3 -0
- data/lib/sass/scss/css_parser.rb +5 -3
- data/lib/sass/scss/parser.rb +146 -64
- data/lib/sass/scss/rx.rb +9 -1
- data/lib/sass/scss/sass_parser.rb +11 -0
- data/lib/sass/scss/script_lexer.rb +2 -0
- data/lib/sass/scss/static_parser.rb +48 -0
- data/lib/sass/selector.rb +353 -0
- data/lib/sass/selector/abstract_sequence.rb +40 -0
- data/lib/sass/selector/comma_sequence.rb +80 -0
- data/lib/sass/selector/sequence.rb +194 -0
- data/lib/sass/selector/simple.rb +107 -0
- data/lib/sass/selector/simple_sequence.rb +161 -0
- data/lib/sass/tree/comment_node.rb +1 -0
- data/lib/sass/tree/debug_node.rb +1 -0
- data/lib/sass/tree/directive_node.rb +1 -0
- data/lib/sass/tree/extend_node.rb +60 -0
- data/lib/sass/tree/for_node.rb +1 -0
- data/lib/sass/tree/if_node.rb +2 -0
- data/lib/sass/tree/import_node.rb +2 -0
- data/lib/sass/tree/mixin_def_node.rb +1 -0
- data/lib/sass/tree/mixin_node.rb +21 -5
- data/lib/sass/tree/node.rb +59 -12
- data/lib/sass/tree/prop_node.rb +20 -21
- data/lib/sass/tree/root_node.rb +8 -17
- data/lib/sass/tree/rule_node.rb +49 -100
- data/lib/sass/tree/variable_node.rb +1 -0
- data/lib/sass/tree/warn_node.rb +1 -0
- data/lib/sass/tree/while_node.rb +1 -0
- data/test/haml/engine_test.rb +185 -3
- data/test/haml/helper_test.rb +25 -2
- data/test/haml/template_test.rb +2 -2
- data/test/haml/templates/helpers.haml +13 -0
- data/test/haml/util/subset_map_test.rb +91 -0
- data/test/haml/util_test.rb +25 -0
- data/test/sass/conversion_test.rb +23 -3
- data/test/sass/engine_test.rb +50 -7
- data/test/sass/extend_test.rb +1045 -0
- data/test/sass/results/complex.css +0 -1
- data/test/sass/results/script.css +1 -1
- data/test/sass/script_conversion_test.rb +16 -0
- data/test/sass/script_test.rb +37 -4
- data/test/sass/scss/css_test.rb +17 -3
- data/test/sass/scss/rx_test.rb +1 -1
- data/test/sass/scss/scss_test.rb +30 -0
- data/test/sass/templates/complex.sass +0 -2
- data/test/test_helper.rb +5 -0
- metadata +18 -4
data/lib/sass/tree/rule_node.rb
CHANGED
@@ -7,7 +7,6 @@ module Sass::Tree
|
|
7
7
|
# @see Sass::Tree
|
8
8
|
class RuleNode < Node
|
9
9
|
# The character used to include the parent selector
|
10
|
-
# @private
|
11
10
|
PARENT = '&'
|
12
11
|
|
13
12
|
# The CSS selector for this rule,
|
@@ -18,44 +17,19 @@ module Sass::Tree
|
|
18
17
|
# @return [Array<String, Sass::Script::Node>]
|
19
18
|
attr_accessor :rule
|
20
19
|
|
21
|
-
# The CSS
|
22
|
-
#
|
20
|
+
# The CSS selector for this rule,
|
21
|
+
# without any unresolved interpolation
|
22
|
+
# but with parent references still intact.
|
23
23
|
# It's only set once {Tree::Node#perform} has been called.
|
24
24
|
#
|
25
|
-
#
|
26
|
-
# The first level of arrays comma-separated selectors;
|
27
|
-
# the second represents structure within those selectors,
|
28
|
-
# currently only parent-refs (represented by `:parent`).
|
29
|
-
# Newlines are represented as literal `\n` characters in the strings.
|
30
|
-
# For example,
|
31
|
-
#
|
32
|
-
# &.foo, bar, baz,
|
33
|
-
# bip, &.bop, bup
|
34
|
-
#
|
35
|
-
# would be
|
36
|
-
#
|
37
|
-
# [[:parent, ".foo"], ["bar"], ["baz"],
|
38
|
-
# ["\nbip"], [:parent, ".bop"], ["bup"]]
|
39
|
-
#
|
40
|
-
# @return [Array<Array<String, Symbol>>]
|
25
|
+
# @return [Selector::CommaSequence]
|
41
26
|
attr_accessor :parsed_rules
|
42
27
|
|
43
|
-
# The CSS
|
44
|
-
#
|
28
|
+
# The CSS selector for this rule,
|
29
|
+
# without any unresolved interpolation or parent references.
|
45
30
|
# It's only set once {Tree::Node#cssize} has been called.
|
46
31
|
#
|
47
|
-
#
|
48
|
-
# Newlines are represented as literal `\n` characters in the strings.
|
49
|
-
# For example,
|
50
|
-
#
|
51
|
-
# foo bar, baz,
|
52
|
-
# bang, bip bop, blip
|
53
|
-
#
|
54
|
-
# would be
|
55
|
-
#
|
56
|
-
# ["foo bar", "baz", "\nbang", "bip bop", "blip"]
|
57
|
-
#
|
58
|
-
# @return [Array<String>]
|
32
|
+
# @return [Selector::CommaSequence]
|
59
33
|
attr_accessor :resolved_rules
|
60
34
|
|
61
35
|
# How deep this rule is indented
|
@@ -121,6 +95,7 @@ module Sass::Tree
|
|
121
95
|
name.gsub(/^/, ' ' * tabs) + children_to_src(tabs, opts, :sass)
|
122
96
|
end
|
123
97
|
|
98
|
+
# @see Node#to_scss
|
124
99
|
def to_scss(tabs, opts = {})
|
125
100
|
name = rule.map {|r| r.is_a?(String) ? r : "\#{#{r.to_sass(opts)}}"}.
|
126
101
|
join.gsub(/^[ \t]*/, ' ' * tabs)
|
@@ -135,6 +110,15 @@ module Sass::Tree
|
|
135
110
|
res
|
136
111
|
end
|
137
112
|
|
113
|
+
# Extends this Rule's selector with the given `extends`.
|
114
|
+
#
|
115
|
+
# @see Node#do_extend
|
116
|
+
def do_extend(extends)
|
117
|
+
node = dup
|
118
|
+
node.resolved_rules = resolved_rules.do_extend(extends)
|
119
|
+
node
|
120
|
+
end
|
121
|
+
|
138
122
|
protected
|
139
123
|
|
140
124
|
# Computes the CSS for the rule.
|
@@ -154,7 +138,9 @@ module Sass::Tree
|
|
154
138
|
rule_indent = ' ' * (tabs - 1)
|
155
139
|
per_rule_indent, total_indent = [:nested, :expanded].include?(style) ? [rule_indent, ''] : ['', rule_indent]
|
156
140
|
|
157
|
-
total_rule = total_indent + resolved_rules.
|
141
|
+
total_rule = total_indent + resolved_rules.members.
|
142
|
+
map {|seq| seq.to_a.join}.
|
143
|
+
join(rule_separator).split("\n").map do |line|
|
158
144
|
per_rule_indent + line.strip
|
159
145
|
end.join(line_separator)
|
160
146
|
|
@@ -199,21 +185,24 @@ module Sass::Tree
|
|
199
185
|
to_return
|
200
186
|
end
|
201
187
|
|
202
|
-
# Runs
|
203
|
-
# and parses the
|
188
|
+
# Runs SassScript interpolation in the selector,
|
189
|
+
# and then parses the result into a {Sass::Selector::CommaSequence}.
|
204
190
|
#
|
205
191
|
# @param environment [Sass::Environment] The lexical environment containing
|
206
192
|
# variable and mixin values
|
207
193
|
def perform!(environment)
|
208
|
-
@parsed_rules =
|
194
|
+
@parsed_rules = Sass::SCSS::StaticParser.new(run_interp(@rule, environment)).
|
195
|
+
parse_selector(self.line, self.filename)
|
209
196
|
super
|
210
197
|
end
|
211
198
|
|
212
199
|
# Converts nested rules into a flat list of rules.
|
213
200
|
#
|
201
|
+
# @param extends [Haml::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
|
202
|
+
# The extensions defined for this tree
|
214
203
|
# @param parent [RuleNode, nil] The parent node of this node,
|
215
204
|
# or nil if the parent isn't a {RuleNode}
|
216
|
-
def _cssize(parent)
|
205
|
+
def _cssize(extends, parent)
|
217
206
|
node = super
|
218
207
|
rules = node.children.select {|c| c.is_a?(RuleNode)}
|
219
208
|
props = node.children.reject {|c| c.is_a?(RuleNode) || c.invisible?}
|
@@ -232,14 +221,28 @@ module Sass::Tree
|
|
232
221
|
# Resolves parent references and nested selectors,
|
233
222
|
# and updates the indentation based on the parent's indentation.
|
234
223
|
#
|
224
|
+
# @param extends [Haml::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
|
225
|
+
# The extensions defined for this tree
|
235
226
|
# @param parent [RuleNode, nil] The parent node of this node,
|
236
227
|
# or nil if the parent isn't a {RuleNode}
|
237
228
|
# @raise [Sass::SyntaxError] if the rule has no parents but uses `&`
|
238
|
-
def cssize!(parent)
|
239
|
-
self.resolved_rules = resolve_parent_refs(parent && parent.resolved_rules)
|
229
|
+
def cssize!(extends, parent)
|
230
|
+
self.resolved_rules = @parsed_rules.resolve_parent_refs(parent && parent.resolved_rules)
|
240
231
|
super
|
241
232
|
end
|
242
233
|
|
234
|
+
# Returns an error message if the given child node is invalid,
|
235
|
+
# and false otherwise.
|
236
|
+
#
|
237
|
+
# {ExtendNode}s are valid within {RuleNode}s.
|
238
|
+
#
|
239
|
+
# @param child [Tree::Node] A potential child nodecompact.
|
240
|
+
# @return [Boolean, String] Whether or not the child node is valid,
|
241
|
+
# as well as the error message to display if it is invalid
|
242
|
+
def invalid_child?(child)
|
243
|
+
super unless child.is_a?(ExtendNode)
|
244
|
+
end
|
245
|
+
|
243
246
|
# A hash that will be associated with this rule in the CSS document
|
244
247
|
# if the {file:SASS_REFERENCE.md#debug_info-option `:debug_info` option} is enabled.
|
245
248
|
# This data is used by e.g. [the FireSass Firebug extension](https://addons.mozilla.org/en-US/firefox/addon/103988).
|
@@ -252,70 +255,16 @@ module Sass::Tree
|
|
252
255
|
|
253
256
|
private
|
254
257
|
|
255
|
-
def resolve_parent_refs(super_rules)
|
256
|
-
if super_rules.nil?
|
257
|
-
return @parsed_rules.map do |rule|
|
258
|
-
if rule.include?(:parent)
|
259
|
-
raise Sass::SyntaxError.new("Base-level rules cannot contain the parent-selector-referencing character '#{PARENT}'.")
|
260
|
-
end
|
261
|
-
|
262
|
-
rule.join
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
new_rules = []
|
267
|
-
super_rules.each do |super_rule|
|
268
|
-
@parsed_rules.each do |rule|
|
269
|
-
new_rules << []
|
270
|
-
|
271
|
-
# An initial newline of the child rule
|
272
|
-
# should be moved to the beginning of the entire rule
|
273
|
-
rule.first.slice!(0) if nl = (rule.first.is_a?(String) && rule.first[0] == ?\n)
|
274
|
-
rule = [nl ? "\n" : "", :parent, " ", *rule] unless rule.include?(:parent)
|
275
|
-
|
276
|
-
new_rules.last << rule.map do |segment|
|
277
|
-
next segment unless segment == :parent
|
278
|
-
super_rule
|
279
|
-
end.join
|
280
|
-
end
|
281
|
-
end
|
282
|
-
new_rules
|
283
|
-
end
|
284
|
-
|
285
|
-
def parse_selector(text)
|
286
|
-
scanner = StringScanner.new(text)
|
287
|
-
rules = [[]]
|
288
|
-
|
289
|
-
while scanner.rest?
|
290
|
-
rules.last << scanner.scan(/[^",&]*/)
|
291
|
-
case scanner.scan(/./)
|
292
|
-
when '&'; rules.last << :parent
|
293
|
-
when ','
|
294
|
-
scanner.scan(/\s*/)
|
295
|
-
if scanner.rest?
|
296
|
-
rules << []
|
297
|
-
rules.last << "\n" if scanner.matched.include?("\n")
|
298
|
-
end
|
299
|
-
when '"'
|
300
|
-
rules.last << '"' << scanner.scan(/([^"\\]|\\.)*/)
|
301
|
-
# We don't want to enforce that strings are closed,
|
302
|
-
# but we do want to consume quotes or trailing backslashes.
|
303
|
-
rules.last << scanner.scan(/./) if scanner.rest?
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
rules.map! do |l|
|
308
|
-
Haml::Util.merge_adjacent_strings(l).reject {|r| r.is_a?(String) && r.empty?}
|
309
|
-
end
|
310
|
-
|
311
|
-
rules
|
312
|
-
end
|
313
|
-
|
314
258
|
def debug_info_rule
|
315
259
|
node = DirectiveNode.new("@media -sass-debug-info")
|
316
260
|
debug_info.map {|k, v| [k.to_s, v.to_s]}.sort.each do |k, v|
|
317
261
|
rule = RuleNode.new([""])
|
318
|
-
rule.resolved_rules =
|
262
|
+
rule.resolved_rules = Sass::Selector::CommaSequence.new(
|
263
|
+
[Sass::Selector::Sequence.new(
|
264
|
+
[Sass::Selector::SimpleSequence.new(
|
265
|
+
[Sass::Selector::Element.new(k.to_s.gsub(/[^\w-]/, "\\\\\\0"), nil)])
|
266
|
+
])
|
267
|
+
])
|
319
268
|
prop = PropNode.new([""], "", :new)
|
320
269
|
prop.resolved_name = "font-family"
|
321
270
|
prop.resolved_value = Sass::SCSS::RX.escape_ident(v.to_s)
|
data/lib/sass/tree/warn_node.rb
CHANGED
data/lib/sass/tree/while_node.rb
CHANGED
data/test/haml/engine_test.rb
CHANGED
@@ -1348,17 +1348,199 @@ SASS
|
|
1348
1348
|
render("%a{:a => 'b',\n:b => 'c'}(c='d'\nd='e') bar"))
|
1349
1349
|
end
|
1350
1350
|
|
1351
|
+
# Ruby Multiline
|
1352
|
+
|
1353
|
+
def test_silent_ruby_multiline
|
1354
|
+
assert_equal(<<HTML, render(<<HAML))
|
1355
|
+
bar, baz, bang
|
1356
|
+
<p>foo</p>
|
1357
|
+
HTML
|
1358
|
+
- foo = ["bar",
|
1359
|
+
"baz",
|
1360
|
+
"bang"]
|
1361
|
+
= foo.join(", ")
|
1362
|
+
%p foo
|
1363
|
+
HAML
|
1364
|
+
end
|
1365
|
+
|
1366
|
+
def test_loud_ruby_multiline
|
1367
|
+
assert_equal(<<HTML, render(<<HAML))
|
1368
|
+
bar, baz, bang
|
1369
|
+
<p>foo</p>
|
1370
|
+
<p>bar</p>
|
1371
|
+
HTML
|
1372
|
+
= ["bar",
|
1373
|
+
"baz",
|
1374
|
+
"bang"].join(", ")
|
1375
|
+
%p foo
|
1376
|
+
%p bar
|
1377
|
+
HAML
|
1378
|
+
end
|
1379
|
+
|
1380
|
+
def test_escaped_loud_ruby_multiline
|
1381
|
+
assert_equal(<<HTML, render(<<HAML))
|
1382
|
+
bar<, baz, bang
|
1383
|
+
<p>foo</p>
|
1384
|
+
<p>bar</p>
|
1385
|
+
HTML
|
1386
|
+
&= ["bar<",
|
1387
|
+
"baz",
|
1388
|
+
"bang"].join(", ")
|
1389
|
+
%p foo
|
1390
|
+
%p bar
|
1391
|
+
HAML
|
1392
|
+
end
|
1393
|
+
|
1394
|
+
def test_unescaped_loud_ruby_multiline
|
1395
|
+
assert_equal(<<HTML, render(<<HAML, :escape_html => true))
|
1396
|
+
bar<, baz, bang
|
1397
|
+
<p>foo</p>
|
1398
|
+
<p>bar</p>
|
1399
|
+
HTML
|
1400
|
+
!= ["bar<",
|
1401
|
+
"baz",
|
1402
|
+
"bang"].join(", ")
|
1403
|
+
%p foo
|
1404
|
+
%p bar
|
1405
|
+
HAML
|
1406
|
+
end
|
1407
|
+
|
1408
|
+
def test_flattened_loud_ruby_multiline
|
1409
|
+
assert_equal(<<HTML, render(<<HAML))
|
1410
|
+
<pre>bar
baz
bang</pre>
|
1411
|
+
<p>foo</p>
|
1412
|
+
<p>bar</p>
|
1413
|
+
HTML
|
1414
|
+
~ "<pre>" + ["bar",
|
1415
|
+
"baz",
|
1416
|
+
"bang"].join("\\n") + "</pre>"
|
1417
|
+
%p foo
|
1418
|
+
%p bar
|
1419
|
+
HAML
|
1420
|
+
end
|
1421
|
+
|
1422
|
+
def test_loud_ruby_multiline_with_block
|
1423
|
+
assert_equal(<<HTML, render(<<HAML))
|
1424
|
+
farfazfang
|
1425
|
+
<p>foo</p>
|
1426
|
+
<p>bar</p>
|
1427
|
+
HTML
|
1428
|
+
= ["bar",
|
1429
|
+
"baz",
|
1430
|
+
"bang"].map do |str|
|
1431
|
+
- str.gsub("ba",
|
1432
|
+
"fa")
|
1433
|
+
%p foo
|
1434
|
+
%p bar
|
1435
|
+
HAML
|
1436
|
+
end
|
1437
|
+
|
1438
|
+
def test_silent_ruby_multiline_with_block
|
1439
|
+
assert_equal(<<HTML, render(<<HAML))
|
1440
|
+
far
|
1441
|
+
faz
|
1442
|
+
fang
|
1443
|
+
<p>foo</p>
|
1444
|
+
<p>bar</p>
|
1445
|
+
HTML
|
1446
|
+
- ["bar",
|
1447
|
+
"baz",
|
1448
|
+
"bang"].map do |str|
|
1449
|
+
= str.gsub("ba",
|
1450
|
+
"fa")
|
1451
|
+
%p foo
|
1452
|
+
%p bar
|
1453
|
+
HAML
|
1454
|
+
end
|
1455
|
+
|
1456
|
+
def test_ruby_multiline_in_tag
|
1457
|
+
assert_equal(<<HTML, render(<<HAML))
|
1458
|
+
<p>foo, bar, baz</p>
|
1459
|
+
<p>foo</p>
|
1460
|
+
<p>bar</p>
|
1461
|
+
HTML
|
1462
|
+
%p= ["foo",
|
1463
|
+
"bar",
|
1464
|
+
"baz"].join(", ")
|
1465
|
+
%p foo
|
1466
|
+
%p bar
|
1467
|
+
HAML
|
1468
|
+
end
|
1469
|
+
|
1470
|
+
def test_escaped_ruby_multiline_in_tag
|
1471
|
+
assert_equal(<<HTML, render(<<HAML))
|
1472
|
+
<p>foo<, bar, baz</p>
|
1473
|
+
<p>foo</p>
|
1474
|
+
<p>bar</p>
|
1475
|
+
HTML
|
1476
|
+
%p&= ["foo<",
|
1477
|
+
"bar",
|
1478
|
+
"baz"].join(", ")
|
1479
|
+
%p foo
|
1480
|
+
%p bar
|
1481
|
+
HAML
|
1482
|
+
end
|
1483
|
+
|
1484
|
+
def test_unescaped_ruby_multiline_in_tag
|
1485
|
+
assert_equal(<<HTML, render(<<HAML, :escape_html => true))
|
1486
|
+
<p>foo<, bar, baz</p>
|
1487
|
+
<p>foo</p>
|
1488
|
+
<p>bar</p>
|
1489
|
+
HTML
|
1490
|
+
%p!= ["foo<",
|
1491
|
+
"bar",
|
1492
|
+
"baz"].join(", ")
|
1493
|
+
%p foo
|
1494
|
+
%p bar
|
1495
|
+
HAML
|
1496
|
+
end
|
1497
|
+
|
1498
|
+
def test_ruby_multiline_with_normal_multiline
|
1499
|
+
assert_equal(<<HTML, render(<<HAML))
|
1500
|
+
foobarbar, baz, bang
|
1501
|
+
<p>foo</p>
|
1502
|
+
<p>bar</p>
|
1503
|
+
HTML
|
1504
|
+
= "foo" + |
|
1505
|
+
"bar" + |
|
1506
|
+
["bar", |
|
1507
|
+
"baz",
|
1508
|
+
"bang"].join(", ")
|
1509
|
+
%p foo
|
1510
|
+
%p bar
|
1511
|
+
HAML
|
1512
|
+
end
|
1513
|
+
|
1514
|
+
def test_ruby_multiline_after_filter
|
1515
|
+
assert_equal(<<HTML, render(<<HAML))
|
1516
|
+
foo
|
1517
|
+
bar
|
1518
|
+
bar, baz, bang
|
1519
|
+
<p>foo</p>
|
1520
|
+
<p>bar</p>
|
1521
|
+
HTML
|
1522
|
+
:plain
|
1523
|
+
foo
|
1524
|
+
bar
|
1525
|
+
= ["bar",
|
1526
|
+
"baz",
|
1527
|
+
"bang"].join(", ")
|
1528
|
+
%p foo
|
1529
|
+
%p bar
|
1530
|
+
HAML
|
1531
|
+
end
|
1532
|
+
|
1351
1533
|
# Encodings
|
1352
1534
|
|
1353
1535
|
def test_utf_8_bom
|
1354
|
-
assert_equal <<
|
1536
|
+
assert_equal <<HTML, render(<<HAML)
|
1355
1537
|
<div class='foo'>
|
1356
1538
|
<p>baz</p>
|
1357
1539
|
</div>
|
1358
|
-
|
1540
|
+
HTML
|
1359
1541
|
\xEF\xBB\xBF.foo
|
1360
1542
|
%p baz
|
1361
|
-
|
1543
|
+
HAML
|
1362
1544
|
end
|
1363
1545
|
|
1364
1546
|
unless Haml::Util.ruby1_8?
|