haml 4.1.0.beta.1 → 5.0.0.beta.2
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.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/CHANGELOG.md +36 -6
- data/FAQ.md +4 -14
- data/MIT-LICENSE +1 -1
- data/README.md +81 -48
- data/REFERENCE.md +86 -50
- data/Rakefile +28 -41
- data/lib/haml/attribute_builder.rb +163 -0
- data/lib/haml/attribute_compiler.rb +214 -0
- data/lib/haml/attribute_parser.rb +112 -0
- data/lib/haml/buffer.rb +24 -126
- data/lib/haml/compiler.rb +62 -281
- data/lib/haml/engine.rb +16 -23
- data/lib/haml/error.rb +2 -0
- data/lib/haml/escapable.rb +48 -0
- data/lib/haml/exec.rb +23 -12
- data/lib/haml/filters.rb +3 -4
- data/lib/haml/generator.rb +36 -0
- data/lib/haml/helpers.rb +61 -48
- data/lib/haml/helpers/action_view_extensions.rb +1 -1
- data/lib/haml/helpers/action_view_mods.rb +32 -50
- data/lib/haml/helpers/safe_erubi_template.rb +26 -0
- data/lib/haml/helpers/safe_erubis_template.rb +2 -0
- data/lib/haml/helpers/xss_mods.rb +17 -12
- data/lib/haml/options.rb +32 -36
- data/lib/haml/parser.rb +61 -38
- data/lib/haml/{template/plugin.rb → plugin.rb} +5 -2
- data/lib/haml/railtie.rb +14 -6
- data/lib/haml/template.rb +11 -6
- data/lib/haml/temple_engine.rb +119 -0
- data/lib/haml/temple_line_counter.rb +28 -0
- data/lib/haml/util.rb +17 -112
- data/lib/haml/version.rb +1 -1
- data/test/attribute_parser_test.rb +105 -0
- data/test/engine_test.rb +202 -106
- data/test/filters_test.rb +32 -19
- data/test/gemfiles/Gemfile.rails-4.0.x +7 -1
- data/test/gemfiles/Gemfile.rails-4.0.x.lock +57 -71
- data/test/gemfiles/Gemfile.rails-4.1.x +5 -0
- data/test/gemfiles/Gemfile.rails-4.2.x +5 -0
- data/test/gemfiles/Gemfile.rails-5.0.x +4 -0
- data/test/helper_test.rb +156 -109
- data/test/options_test.rb +21 -0
- data/test/parser_test.rb +49 -4
- data/test/results/eval_suppressed.xhtml +4 -4
- data/test/results/helpers.xhtml +43 -41
- data/test/results/helpful.xhtml +6 -3
- data/test/results/just_stuff.xhtml +21 -20
- data/test/results/list.xhtml +9 -9
- data/test/results/nuke_inner_whitespace.xhtml +22 -22
- data/test/results/nuke_outer_whitespace.xhtml +84 -92
- data/test/results/original_engine.xhtml +17 -17
- data/test/results/partial_layout.xhtml +4 -3
- data/test/results/partial_layout_erb.xhtml +4 -3
- data/test/results/partials.xhtml +11 -10
- data/test/results/silent_script.xhtml +63 -63
- data/test/results/standard.xhtml +156 -159
- data/test/results/tag_parsing.xhtml +19 -19
- data/test/results/very_basic.xhtml +2 -2
- data/test/results/whitespace_handling.xhtml +77 -76
- data/test/template_test.rb +21 -48
- data/test/template_test_helper.rb +38 -0
- data/test/templates/just_stuff.haml +1 -0
- data/test/templates/standard_ugly.haml +1 -0
- data/test/temple_line_counter_test.rb +40 -0
- data/test/test_helper.rb +10 -10
- data/test/util_test.rb +1 -48
- metadata +49 -35
- data/lib/haml/temple.rb +0 -85
- data/test/gemfiles/Gemfile.rails-3.2.x +0 -4
- data/test/templates/_av_partial_1_ugly.haml +0 -9
- data/test/templates/_av_partial_2_ugly.haml +0 -5
- data/test/templates/action_view_ugly.haml +0 -47
- data/test/templates/standard_ugly.haml +0 -43
data/test/engine_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require 'test_helper'
|
3
3
|
|
4
|
-
class EngineTest <
|
4
|
+
class EngineTest < Haml::TestCase
|
5
5
|
# A map of erroneous Haml documents to the error messages they should produce.
|
6
6
|
# The error messages may be arrays;
|
7
7
|
# if so, the second element should be the line number that should be reported for the error.
|
@@ -126,11 +126,11 @@ class EngineTest < MiniTest::Unit::TestCase
|
|
126
126
|
end
|
127
127
|
|
128
128
|
def test_flexible_tabulation
|
129
|
-
assert_equal("<p>\
|
129
|
+
assert_equal("<p>\nfoo\n</p>\n<q>\nbar\n<a>\nbaz\n</a>\n</q>\n",
|
130
130
|
render("%p\n foo\n%q\n bar\n %a\n baz"))
|
131
|
-
assert_equal("<p>\
|
131
|
+
assert_equal("<p>\nfoo\n</p>\n<q>\nbar\n<a>\nbaz\n</a>\n</q>\n",
|
132
132
|
render("%p\n\tfoo\n%q\n\tbar\n\t%a\n\t\tbaz"))
|
133
|
-
assert_equal("<p>\n
|
133
|
+
assert_equal("<p>\n \t \t bar\n baz\n</p>\n",
|
134
134
|
render("%p\n :plain\n \t \t bar\n baz"))
|
135
135
|
end
|
136
136
|
|
@@ -185,7 +185,7 @@ class EngineTest < MiniTest::Unit::TestCase
|
|
185
185
|
def test_dynamic_attributes_with_no_content
|
186
186
|
assert_equal(<<HTML, render(<<HAML))
|
187
187
|
<p>
|
188
|
-
|
188
|
+
<a href='http://haml.info'></a>
|
189
189
|
</p>
|
190
190
|
HTML
|
191
191
|
%p
|
@@ -222,7 +222,7 @@ HAML
|
|
222
222
|
end
|
223
223
|
|
224
224
|
def test_one_liner_with_newline_shouldnt_be_one_line
|
225
|
-
assert_equal("<p
|
225
|
+
assert_equal("<p>foo\nbar</p>", render('%p= "foo\nbar"').chomp)
|
226
226
|
end
|
227
227
|
|
228
228
|
def test_multi_render
|
@@ -233,8 +233,31 @@ HAML
|
|
233
233
|
end
|
234
234
|
|
235
235
|
def test_interpolation
|
236
|
-
assert_equal("<p>Hello World</p>\n", render('%p Hello #{who}', :
|
237
|
-
assert_equal("<p>\
|
236
|
+
assert_equal("<p>Hello World</p>\n", render('%p Hello #{who}', locals: {who: 'World'}, escape_html: false))
|
237
|
+
assert_equal("<p>\nHello World\n</p>\n", render("%p\n Hello \#{who}", locals: {who: 'World'}, escape_html: false))
|
238
|
+
assert_equal("<p>Hello World</p>\n", render('%p Hello #{who}', locals: {who: 'World'}, escape_html: true))
|
239
|
+
assert_equal("<p>\nHello World\n</p>\n", render("%p\n Hello \#{who}", locals: {who: 'World'}, escape_html: true))
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_interpolation_with_instance_var
|
243
|
+
scope = Object.new
|
244
|
+
scope.instance_variable_set(:@who, 'World')
|
245
|
+
|
246
|
+
assert_equal("<p>Hello World</p>\n", render('%p Hello #@who', scope: scope, escape_html: false))
|
247
|
+
assert_equal("<p>\nHello World\n</p>\n", render("%p\n Hello \#@who", scope: scope, escape_html: false))
|
248
|
+
assert_equal("<p>Hello World</p>\n", render('%p Hello #@who', scope: scope, escape_html: true))
|
249
|
+
assert_equal("<p>\nHello World\n</p>\n", render("%p\n Hello \#@who", scope: scope, escape_html: true))
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_interpolation_with_global
|
253
|
+
$global_var_for_testing = 'World'
|
254
|
+
|
255
|
+
assert_equal("<p>Hello World</p>\n", render('%p Hello #$global_var_for_testing', escape_html: false))
|
256
|
+
assert_equal("<p>\nHello World\n</p>\n", render("%p\n Hello \#$global_var_for_testing", escape_html: false))
|
257
|
+
assert_equal("<p>Hello World</p>\n", render('%p Hello #$global_var_for_testing', escape_html: true))
|
258
|
+
assert_equal("<p>\nHello World\n</p>\n", render("%p\n Hello \#$global_var_for_testing", escape_html: true))
|
259
|
+
ensure
|
260
|
+
$global_var_for_testing = nil
|
238
261
|
end
|
239
262
|
|
240
263
|
def test_interpolation_in_the_middle_of_a_string
|
@@ -242,9 +265,43 @@ HAML
|
|
242
265
|
render("\"title '\#{\"Title\"}'. \""))
|
243
266
|
end
|
244
267
|
|
268
|
+
def test_interpolation_with_instance_var_in_the_middle_of_a_string
|
269
|
+
scope = Object.new
|
270
|
+
scope.instance_variable_set(:@title, 'Title')
|
271
|
+
|
272
|
+
assert_equal("\"title 'Title'. \"\n",
|
273
|
+
render("\"title '\#@title'. \"", :scope => scope))
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_interpolation_with_global_in_the_middle_of_a_string
|
277
|
+
$global_var_for_testing = 'Title'
|
278
|
+
|
279
|
+
assert_equal("\"title 'Title'. \"\n",
|
280
|
+
render("\"title '\#$global_var_for_testing'. \""))
|
281
|
+
ensure
|
282
|
+
$global_var_for_testing = nil
|
283
|
+
end
|
284
|
+
|
245
285
|
def test_interpolation_at_the_beginning_of_a_line
|
246
286
|
assert_equal("<p>2</p>\n", render('%p #{1 + 1}'))
|
247
|
-
assert_equal("<p>\
|
287
|
+
assert_equal("<p>\n2\n</p>\n", render("%p\n \#{1 + 1}"))
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_interpolation_with_instance_var_at_the_beginning_of_a_line
|
291
|
+
scope = Object.new
|
292
|
+
scope.instance_variable_set(:@foo, 2)
|
293
|
+
|
294
|
+
assert_equal("<p>2</p>\n", render('%p #@foo', :scope => scope))
|
295
|
+
assert_equal("<p>\n2\n</p>\n", render("%p\n \#@foo", :scope => scope))
|
296
|
+
end
|
297
|
+
|
298
|
+
def test_interpolation_with_global_at_the_beginning_of_a_line
|
299
|
+
$global_var_for_testing = 2
|
300
|
+
|
301
|
+
assert_equal("<p>2</p>\n", render('%p #$global_var_for_testing'))
|
302
|
+
assert_equal("<p>\n2\n</p>\n", render("%p\n \#$global_var_for_testing"))
|
303
|
+
ensure
|
304
|
+
$global_var_for_testing = nil
|
248
305
|
end
|
249
306
|
|
250
307
|
def test_escaped_interpolation
|
@@ -269,7 +326,7 @@ HAML
|
|
269
326
|
|
270
327
|
def test_attribute_hash_with_newlines
|
271
328
|
assert_equal("<p a='b' c='d'>foop</p>\n", render("%p{:a => 'b',\n :c => 'd'} foop"))
|
272
|
-
assert_equal("<p a='b' c='d'>\
|
329
|
+
assert_equal("<p a='b' c='d'>\nfoop\n</p>\n", render("%p{:a => 'b',\n :c => 'd'}\n foop"))
|
273
330
|
assert_equal("<p a='b' c='d'>\n", render("%p{:a => 'b',\n :c => 'd'}/"))
|
274
331
|
assert_equal("<p a='b' c='d' e='f'></p>\n", render("%p{:a => 'b',\n :c => 'd',\n :e => 'f'}"))
|
275
332
|
end
|
@@ -288,8 +345,8 @@ HAML
|
|
288
345
|
assert_equal(hash, {:color => 'red'})
|
289
346
|
end
|
290
347
|
|
291
|
-
def
|
292
|
-
assert_equal(<<HTML, render(<<HAML
|
348
|
+
def test_semi_prerendered_tags
|
349
|
+
assert_equal(<<HTML, render(<<HAML))
|
293
350
|
<p a='2'></p>
|
294
351
|
<p a='2'>foo</p>
|
295
352
|
<p a='2'>
|
@@ -331,7 +388,7 @@ HAML
|
|
331
388
|
assert_equal("<textarea>#{'a' * 100}</textarea>\n",
|
332
389
|
render("%textarea #{'a' * 100}"))
|
333
390
|
|
334
|
-
assert_equal("<p>\n
|
391
|
+
assert_equal("<p>\n<textarea>Foo\nBar\nBaz</textarea>\n</p>\n", render(<<SOURCE))
|
335
392
|
%p
|
336
393
|
%textarea
|
337
394
|
Foo
|
@@ -378,7 +435,7 @@ HAML
|
|
378
435
|
def test_both_whitespace_nukes_work_together
|
379
436
|
assert_equal(<<RESULT, render(<<SOURCE))
|
380
437
|
<p><q>Foo
|
381
|
-
|
438
|
+
Bar</q></p>
|
382
439
|
RESULT
|
383
440
|
%p
|
384
441
|
%q><= "Foo\\nBar"
|
@@ -387,6 +444,7 @@ SOURCE
|
|
387
444
|
|
388
445
|
def test_nil_option
|
389
446
|
assert_equal("<p foo='bar'></p>\n", render('%p{:foo => "bar"}', :attr_wrapper => nil))
|
447
|
+
assert_equal("<p foo='bar'></p>\n", render('%p{foo: "bar"}', :attr_wrapper => nil))
|
390
448
|
end
|
391
449
|
|
392
450
|
def test_comment_with_crazy_nesting
|
@@ -408,11 +466,11 @@ HAML
|
|
408
466
|
def test_indentation_after_dynamic_attr_hash
|
409
467
|
assert_equal(<<HTML, render(<<HAML))
|
410
468
|
<html>
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
469
|
+
<body>
|
470
|
+
<img src='test'>
|
471
|
+
foo
|
472
|
+
bar
|
473
|
+
</body>
|
416
474
|
</html>
|
417
475
|
HTML
|
418
476
|
%html
|
@@ -423,10 +481,12 @@ HAML
|
|
423
481
|
end
|
424
482
|
|
425
483
|
def test_whitespace_nuke_with_both_newlines
|
426
|
-
assert_equal("<p
|
484
|
+
assert_equal("<p>\nfoo\n</p>\n", render('%p<= "\nfoo\n"'))
|
427
485
|
assert_equal(<<HTML, render(<<HAML))
|
428
486
|
<p>
|
429
|
-
|
487
|
+
<p>
|
488
|
+
foo
|
489
|
+
</p>
|
430
490
|
</p>
|
431
491
|
HTML
|
432
492
|
%p
|
@@ -437,7 +497,7 @@ HAML
|
|
437
497
|
def test_whitespace_nuke_with_tags_and_else
|
438
498
|
assert_equal(<<HTML, render(<<HAML))
|
439
499
|
<a>
|
440
|
-
|
500
|
+
<b>foo</b>
|
441
501
|
</a>
|
442
502
|
HTML
|
443
503
|
%a
|
@@ -450,9 +510,9 @@ HAML
|
|
450
510
|
|
451
511
|
assert_equal(<<HTML, render(<<HAML))
|
452
512
|
<a>
|
453
|
-
|
454
|
-
|
455
|
-
|
513
|
+
<b>
|
514
|
+
foo
|
515
|
+
</b>
|
456
516
|
</a>
|
457
517
|
HTML
|
458
518
|
%a
|
@@ -467,7 +527,7 @@ HAML
|
|
467
527
|
def test_outer_whitespace_nuke_with_empty_script
|
468
528
|
assert_equal(<<HTML, render(<<HAML))
|
469
529
|
<p>
|
470
|
-
|
530
|
+
foo <a></a></p>
|
471
531
|
HTML
|
472
532
|
%p
|
473
533
|
foo
|
@@ -479,7 +539,7 @@ HAML
|
|
479
539
|
def test_both_case_indentation_work_with_deeply_nested_code
|
480
540
|
result = <<RESULT
|
481
541
|
<h2>
|
482
|
-
|
542
|
+
other
|
483
543
|
</h2>
|
484
544
|
RESULT
|
485
545
|
assert_equal(result, render(<<HAML))
|
@@ -502,15 +562,15 @@ HAML
|
|
502
562
|
HAML
|
503
563
|
end
|
504
564
|
|
505
|
-
def
|
506
|
-
assert_equal("foo\n", render(<<HAML
|
565
|
+
def test_equals_block
|
566
|
+
assert_equal("foo\n", render(<<HAML))
|
507
567
|
= capture_haml do
|
508
568
|
foo
|
509
569
|
HAML
|
510
570
|
end
|
511
571
|
|
512
|
-
def
|
513
|
-
assert_equal("foo\nbar\n", render(<<HAML
|
572
|
+
def test_plain_equals
|
573
|
+
assert_equal("foo\nbar\n", render(<<HAML))
|
514
574
|
= "foo"
|
515
575
|
bar
|
516
576
|
HAML
|
@@ -528,10 +588,7 @@ HAML
|
|
528
588
|
end
|
529
589
|
|
530
590
|
def test_end_with_method_call
|
531
|
-
assert_equal(
|
532
|
-
2|3|4
|
533
|
-
b-a-r
|
534
|
-
HTML
|
591
|
+
assert_equal("2|3|4b-a-r", render(<<HAML))
|
535
592
|
= [1, 2, 3].map do |i|
|
536
593
|
- i + 1
|
537
594
|
- end.join("|")
|
@@ -545,9 +602,7 @@ HAML
|
|
545
602
|
def test_nested_end_with_method_call
|
546
603
|
assert_equal(<<HTML, render(<<HAML))
|
547
604
|
<p>
|
548
|
-
|
549
|
-
b-a-r
|
550
|
-
</p>
|
605
|
+
2|3|4b-a-r</p>
|
551
606
|
HTML
|
552
607
|
%p
|
553
608
|
= [1, 2, 3].map do |i|
|
@@ -629,7 +684,7 @@ HAML
|
|
629
684
|
def test_escape_attrs_false
|
630
685
|
assert_equal(<<HTML, render(<<HAML, :escape_attrs => false))
|
631
686
|
<div class='<?php echo """ ?>' id='foo'>
|
632
|
-
|
687
|
+
bar
|
633
688
|
</div>
|
634
689
|
HTML
|
635
690
|
#foo{:class => '<?php echo """ ?>'}
|
@@ -638,9 +693,9 @@ HAML
|
|
638
693
|
end
|
639
694
|
|
640
695
|
def test_escape_attrs_always
|
641
|
-
assert_equal(<<HTML, render(<<HAML, :escape_attrs =>
|
642
|
-
<div class='
|
643
|
-
|
696
|
+
assert_equal(<<HTML, render(<<HAML, :escape_attrs => true))
|
697
|
+
<div class='"&lt;&gt;&amp;"' id='foo'>
|
698
|
+
bar
|
644
699
|
</div>
|
645
700
|
HTML
|
646
701
|
#foo{:class => '"<>&"'}
|
@@ -760,7 +815,7 @@ HAML
|
|
760
815
|
assert_equal("<a href='#'>Foo</a>\n",
|
761
816
|
render('%a(href="#") #{"Foo"}'))
|
762
817
|
|
763
|
-
assert_equal("<a href='
|
818
|
+
assert_equal("<a href='#"'></a>\n", render('%a(href="#\\"")'))
|
764
819
|
end
|
765
820
|
|
766
821
|
def test_case_assigned_to_var
|
@@ -889,7 +944,7 @@ HAML
|
|
889
944
|
# HTML escaping tests
|
890
945
|
|
891
946
|
def test_ampersand_equals_should_escape
|
892
|
-
assert_equal("<p>\
|
947
|
+
assert_equal("<p>\nfoo & bar\n</p>\n", render("%p\n &= 'foo & bar'", :escape_html => false))
|
893
948
|
end
|
894
949
|
|
895
950
|
def test_ampersand_equals_inline_should_escape
|
@@ -901,7 +956,7 @@ HAML
|
|
901
956
|
end
|
902
957
|
|
903
958
|
def test_bang_equals_should_not_escape
|
904
|
-
assert_equal("<p>\
|
959
|
+
assert_equal("<p>\nfoo & bar\n</p>\n", render("%p\n != 'foo & bar'", :escape_html => true))
|
905
960
|
end
|
906
961
|
|
907
962
|
def test_bang_equals_inline_should_not_escape
|
@@ -915,8 +970,6 @@ HAML
|
|
915
970
|
render(".atlantis{:style => 'ugly&stupid'} foo"))
|
916
971
|
assert_equal("<p class='atlantis' style='ugly&stupid'>foo</p>\n",
|
917
972
|
render("%p.atlantis{:style => 'ugly&stupid'}= 'foo'"))
|
918
|
-
assert_equal("<p class='atlantis' style='ugly
stupid'></p>\n",
|
919
|
-
render("%p.atlantis{:style => \"ugly\\nstupid\"}"))
|
920
973
|
end
|
921
974
|
|
922
975
|
def test_dynamic_attributes_should_be_escaped
|
@@ -926,8 +979,6 @@ HAML
|
|
926
979
|
render("%p{:width => nil, :src => '&foo.png', :alt => String.new} foo"))
|
927
980
|
assert_equal("<div alt='' src='&foo.png'>foo</div>\n",
|
928
981
|
render("%div{:width => nil, :src => '&foo.png', :alt => String.new}= 'foo'"))
|
929
|
-
assert_equal("<img alt='' src='foo
.png'>\n",
|
930
|
-
render("%img{:width => nil, :src => \"foo\\n.png\", :alt => String.new}"))
|
931
982
|
end
|
932
983
|
|
933
984
|
def test_string_double_equals_should_be_esaped
|
@@ -946,13 +997,13 @@ HAML
|
|
946
997
|
end
|
947
998
|
|
948
999
|
def test_escaped_string_double_equals
|
949
|
-
assert_equal("<p>\
|
950
|
-
assert_equal("<p>\
|
1000
|
+
assert_equal("<p>\n4&<\n</p>\n", render("%p\n &== \#{2+2}&\#{'<'}", :escape_html => true))
|
1001
|
+
assert_equal("<p>\n4&<\n</p>\n", render("%p\n &== \#{2+2}&\#{'<'}", :escape_html => false))
|
951
1002
|
end
|
952
1003
|
|
953
1004
|
def test_unescaped_string_double_equals
|
954
|
-
assert_equal("<p>\
|
955
|
-
assert_equal("<p>\
|
1005
|
+
assert_equal("<p>\n4&<\n</p>\n", render("%p\n !== \#{2+2}&\#{'<'}", :escape_html => true))
|
1006
|
+
assert_equal("<p>\n4&<\n</p>\n", render("%p\n !== \#{2+2}&\#{'<'}", :escape_html => false))
|
956
1007
|
end
|
957
1008
|
|
958
1009
|
def test_string_interpolation_should_be_esaped
|
@@ -971,18 +1022,28 @@ HAML
|
|
971
1022
|
end
|
972
1023
|
|
973
1024
|
def test_escaped_string_interpolation
|
974
|
-
assert_equal("<p>\
|
975
|
-
assert_equal("<p>\
|
1025
|
+
assert_equal("<p>\n4&<\n</p>\n", render("%p\n & \#{2+2}&\#{'<'}", :escape_html => true))
|
1026
|
+
assert_equal("<p>\n4&<\n</p>\n", render("%p\n & \#{2+2}&\#{'<'}", :escape_html => false))
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
def test_escaped_string_interpolation_with_no_space
|
1030
|
+
assert_equal("<br>\n", render('&#{"<br>"}'))
|
1031
|
+
assert_equal("<span><br></span>\n", render('%span&#{"<br>"}'))
|
976
1032
|
end
|
977
1033
|
|
978
1034
|
def test_unescaped_string_interpolation
|
979
|
-
assert_equal("<p>\
|
980
|
-
assert_equal("<p>\
|
1035
|
+
assert_equal("<p>\n4&<\n</p>\n", render("%p\n ! \#{2+2}&\#{'<'}", :escape_html => true))
|
1036
|
+
assert_equal("<p>\n4&<\n</p>\n", render("%p\n ! \#{2+2}&\#{'<'}", :escape_html => false))
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
def test_unescaped_string_interpolation_with_no_space
|
1040
|
+
assert_equal("<br>\n", render('!#{"<br>"}'))
|
1041
|
+
assert_equal("<span><br></span>\n", render('%span!#{"<br>"}'))
|
981
1042
|
end
|
982
1043
|
|
983
1044
|
def test_scripts_should_respect_escape_html_option
|
984
|
-
assert_equal("<p>\
|
985
|
-
assert_equal("<p>\
|
1045
|
+
assert_equal("<p>\nfoo & bar\n</p>\n", render("%p\n = 'foo & bar'", :escape_html => true))
|
1046
|
+
assert_equal("<p>\nfoo & bar\n</p>\n", render("%p\n = 'foo & bar'", :escape_html => false))
|
986
1047
|
end
|
987
1048
|
|
988
1049
|
def test_inline_scripts_should_respect_escape_html_option
|
@@ -1061,9 +1122,9 @@ HAML
|
|
1061
1122
|
|
1062
1123
|
def test_attr_wrapper
|
1063
1124
|
assert_equal("<p strange=*attrs*></p>\n", render("%p{ :strange => 'attrs'}", :attr_wrapper => '*'))
|
1064
|
-
assert_equal("<p escaped
|
1065
|
-
assert_equal("<p escaped=\"quo
|
1066
|
-
assert_equal("<p escaped=\"q
|
1125
|
+
assert_equal("<p escaped=\"quo"te\"></p>\n", render("%p{ :escaped => 'quo\"te'}", :attr_wrapper => '"'))
|
1126
|
+
assert_equal("<p escaped=\"quo'te\"></p>\n", render("%p{ :escaped => 'quo\\'te'}", :attr_wrapper => '"'))
|
1127
|
+
assert_equal("<p escaped=\"q'uo"te\"></p>\n", render("%p{ :escaped => 'q\\'uo\"te'}", :attr_wrapper => '"'))
|
1067
1128
|
assert_equal("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n", render("!!! XML", :attr_wrapper => '"', :format => :xhtml))
|
1068
1129
|
end
|
1069
1130
|
|
@@ -1081,9 +1142,7 @@ HAML
|
|
1081
1142
|
end
|
1082
1143
|
|
1083
1144
|
def test_attrs_parsed_correctly
|
1084
|
-
assert_equal("<p boom=>biddly='bar => baz'></p>\n", render("%p{'boom=>biddly' => 'bar => baz'}"))
|
1085
1145
|
assert_equal("<p foo,bar='baz, qux'></p>\n", render("%p{'foo,bar' => 'baz, qux'}"))
|
1086
|
-
assert_equal("<p escaped='quo
te'></p>\n", render("%p{ :escaped => \"quo\\nte\"}"))
|
1087
1146
|
assert_equal("<p escaped='quo4te'></p>\n", render("%p{ :escaped => \"quo\#{2 + 2}te\"}"))
|
1088
1147
|
end
|
1089
1148
|
|
@@ -1189,10 +1248,10 @@ HAML
|
|
1189
1248
|
def test_compile_error
|
1190
1249
|
render("a\nb\n- fee)\nc")
|
1191
1250
|
rescue Exception => e
|
1192
|
-
assert_match(/\(test_compile_error\):3
|
1251
|
+
assert_match(/\(test_compile_error\):3:/i, e.message)
|
1252
|
+
assert_match(/(syntax error|expecting \$end)/i, e.message)
|
1193
1253
|
else
|
1194
|
-
assert(false,
|
1195
|
-
'"a\nb\n- fee)\nc" doesn\'t produce an exception!')
|
1254
|
+
assert(false, '"a\nb\n- fee)\nc" doesn\'t produce an exception!')
|
1196
1255
|
end
|
1197
1256
|
|
1198
1257
|
def test_unbalanced_brackets
|
@@ -1201,6 +1260,21 @@ HAML
|
|
1201
1260
|
assert_equal(Haml::Error.message(:unbalanced_brackets), e.message)
|
1202
1261
|
end
|
1203
1262
|
|
1263
|
+
def test_single_line_comments_are_interpolated
|
1264
|
+
assert_equal("<!-- Hello 2 -->\n",
|
1265
|
+
render('/ Hello #{1 + 1}'))
|
1266
|
+
end
|
1267
|
+
|
1268
|
+
def test_single_line_comments_are_not_interpolated_with_suppress_eval
|
1269
|
+
assert_equal("<!-- -->\n",
|
1270
|
+
render('/ Hello #{1 + 1}', :suppress_eval => true))
|
1271
|
+
end
|
1272
|
+
|
1273
|
+
def test_single_line_comments_with_interpolation_dont_break_tabulation
|
1274
|
+
assert_equal("<!-- Hello 2 -->\nconcatted\n",
|
1275
|
+
render("/ Hello \#{1 + 1}\n- haml_concat 'concatted'"))
|
1276
|
+
end
|
1277
|
+
|
1204
1278
|
def test_balanced_conditional_comments
|
1205
1279
|
assert_equal("<!--[if !(IE 6)|(IE 7)]> Bracket: ] <![endif]-->\n",
|
1206
1280
|
render("/[if !(IE 6)|(IE 7)] Bracket: ]"))
|
@@ -1212,13 +1286,13 @@ HAML
|
|
1212
1286
|
end
|
1213
1287
|
|
1214
1288
|
def test_downlevel_revealed_conditional_comments_block
|
1215
|
-
assert_equal("<!--[if !IE]><!-->\
|
1289
|
+
assert_equal("<!--[if !IE]><!-->\nA comment\n<!--<![endif]-->\n",
|
1216
1290
|
render("/![if !IE]\n A comment"))
|
1217
1291
|
end
|
1218
1292
|
|
1219
1293
|
def test_local_assigns_dont_modify_class
|
1220
1294
|
assert_equal("bar\n", render("= foo", :locals => {:foo => 'bar'}))
|
1221
|
-
|
1295
|
+
assert_nil(defined?(foo))
|
1222
1296
|
end
|
1223
1297
|
|
1224
1298
|
def test_object_ref_with_nil_id
|
@@ -1253,7 +1327,7 @@ HAML
|
|
1253
1327
|
|
1254
1328
|
def test_render_should_accept_a_binding_as_scope
|
1255
1329
|
string = "This is a string!"
|
1256
|
-
string.instance_variable_set(
|
1330
|
+
string.instance_variable_set(:@var, "Instance variable")
|
1257
1331
|
b = string.instance_eval do
|
1258
1332
|
var = "Local variable"
|
1259
1333
|
# Silence unavoidable warning; Ruby doesn't know we're going to use this
|
@@ -1334,15 +1408,15 @@ HAML
|
|
1334
1408
|
end
|
1335
1409
|
end
|
1336
1410
|
|
1337
|
-
def
|
1411
|
+
def test_spacing_inside_tag
|
1338
1412
|
assert_equal("<div id='outer'>\n<div id='inner'>\n<p>hello world</p>\n</div>\n</div>\n",
|
1339
|
-
render("#outer\n #inner\n %p hello world"
|
1413
|
+
render("#outer\n #inner\n %p hello world"))
|
1340
1414
|
|
1341
1415
|
assert_equal("<p>#{'s' * 75}</p>\n",
|
1342
|
-
render("%p #{'s' * 75}"
|
1416
|
+
render("%p #{'s' * 75}"))
|
1343
1417
|
|
1344
1418
|
assert_equal("<p>#{'s' * 75}</p>\n",
|
1345
|
-
render("%p= 's' * 75"
|
1419
|
+
render("%p= 's' * 75"))
|
1346
1420
|
end
|
1347
1421
|
|
1348
1422
|
def test_remove_whitespace_true
|
@@ -1359,15 +1433,13 @@ HAML
|
|
1359
1433
|
render('%div <span>foo</span> <span>bar</span>', :remove_whitespace => true))
|
1360
1434
|
end
|
1361
1435
|
|
1362
|
-
def
|
1436
|
+
def test_auto_preserve
|
1363
1437
|
assert_equal("<pre>foo
bar</pre>\n", render('%pre="foo\nbar"'))
|
1364
1438
|
assert_equal("<pre>foo\nbar</pre>\n", render("%pre\n foo\n bar"))
|
1365
|
-
assert_equal("<pre>foo\nbar</pre>\n", render('%pre="foo\nbar"', :ugly => true))
|
1366
|
-
assert_equal("<pre>foo\nbar</pre>\n", render("%pre\n foo\n bar", :ugly => true))
|
1367
1439
|
end
|
1368
1440
|
|
1369
1441
|
def test_xhtml_output_option
|
1370
|
-
assert_equal "<p>\n
|
1442
|
+
assert_equal "<p>\n<br />\n</p>\n", render("%p\n %br", :format => :xhtml)
|
1371
1443
|
assert_equal "<a />\n", render("%a/", :format => :xhtml)
|
1372
1444
|
end
|
1373
1445
|
|
@@ -1400,6 +1472,8 @@ HAML
|
|
1400
1472
|
engine = Haml::Engine.new('%a{:b => "a #$global_var_for_testing b"}')
|
1401
1473
|
$global_var_for_testing = 'bar'
|
1402
1474
|
assert_equal("<a b='a bar b'></a>\n", engine.to_html)
|
1475
|
+
ensure
|
1476
|
+
$global_var_for_testing = nil
|
1403
1477
|
end
|
1404
1478
|
|
1405
1479
|
def test_utf8_attrs
|
@@ -1410,7 +1484,7 @@ HAML
|
|
1410
1484
|
# HTML 4.0
|
1411
1485
|
|
1412
1486
|
def test_html_has_no_self_closing_tags
|
1413
|
-
assert_equal "<p>\n
|
1487
|
+
assert_equal "<p>\n<br>\n</p>\n", render("%p\n %br", :format => :html4)
|
1414
1488
|
assert_equal "<br>\n", render("%br/", :format => :html4)
|
1415
1489
|
end
|
1416
1490
|
|
@@ -1454,7 +1528,7 @@ HAML
|
|
1454
1528
|
render("%div{:data => {:one_plus_one => 1+1}}",
|
1455
1529
|
:hyphenate_data_attrs => false))
|
1456
1530
|
|
1457
|
-
assert_equal("<div data-foo='Here&#
|
1531
|
+
assert_equal("<div data-foo='Here's a "quoteful" string.'></div>\n",
|
1458
1532
|
render(%{%div{:data => {:foo => %{Here's a "quoteful" string.}}}},
|
1459
1533
|
:hyphenate_data_attrs => false)) #'
|
1460
1534
|
end
|
@@ -1507,24 +1581,23 @@ HAML
|
|
1507
1581
|
end
|
1508
1582
|
|
1509
1583
|
def test_html5_data_attributes_with_attr_method
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1584
|
+
obj = Object.new
|
1585
|
+
def obj.data_hash
|
1586
|
+
{:data => {:foo => "bar", :baz => "bang"}}
|
1587
|
+
end
|
1514
1588
|
|
1515
|
-
|
1516
|
-
|
1517
|
-
end
|
1589
|
+
def obj.data_val
|
1590
|
+
{:data => "dat"}
|
1518
1591
|
end
|
1519
1592
|
|
1520
1593
|
assert_equal("<div data-baz='bang' data-brat='wurst' data-foo='blip'></div>\n",
|
1521
|
-
render("%div{data_hash, :data => {:foo => 'blip', :brat => 'wurst'}}"))
|
1594
|
+
render("%div{data_hash, :data => {:foo => 'blip', :brat => 'wurst'}}", scope: obj))
|
1522
1595
|
assert_equal("<div data-baz='bang' data-foo='blip'></div>\n",
|
1523
|
-
render("%div{data_hash, 'data-foo' => 'blip'}"))
|
1596
|
+
render("%div{data_hash, 'data-foo' => 'blip'}", scope: obj))
|
1524
1597
|
assert_equal("<div data-baz='bang' data-foo='bar' data='dat'></div>\n",
|
1525
|
-
render("%div{data_hash, :data => 'dat'}"))
|
1598
|
+
render("%div{data_hash, :data => 'dat'}", scope: obj))
|
1526
1599
|
assert_equal("<div data-brat='wurst' data-foo='blip' data='dat'></div>\n",
|
1527
|
-
render("%div{data_val, :data => {:foo => 'blip', :brat => 'wurst'}}"))
|
1600
|
+
render("%div{data_val, :data => {:foo => 'blip', :brat => 'wurst'}}", scope: obj))
|
1528
1601
|
end
|
1529
1602
|
|
1530
1603
|
def test_html5_data_attributes_with_identical_attribute_values
|
@@ -1536,8 +1609,8 @@ HAML
|
|
1536
1609
|
assert_equal(<<XML, render(<<HAML, { :format => :html5, :mime_type => 'text/xml' }))
|
1537
1610
|
<?xml version='1.0' encoding='utf-8' ?>
|
1538
1611
|
<root>
|
1539
|
-
|
1540
|
-
|
1612
|
+
<element />
|
1613
|
+
<hr />
|
1541
1614
|
</root>
|
1542
1615
|
XML
|
1543
1616
|
!!! XML
|
@@ -1551,8 +1624,8 @@ HAML
|
|
1551
1624
|
assert_equal(<<XML, render(<<HAML, { :format => :html4, :mime_type => 'text/xml' }))
|
1552
1625
|
<?xml version='1.0' encoding='utf-8' ?>
|
1553
1626
|
<root>
|
1554
|
-
|
1555
|
-
|
1627
|
+
<element />
|
1628
|
+
<hr />
|
1556
1629
|
</root>
|
1557
1630
|
XML
|
1558
1631
|
!!! XML
|
@@ -1618,10 +1691,10 @@ HAML
|
|
1618
1691
|
|
1619
1692
|
def test_new_attribute_parsing
|
1620
1693
|
assert_equal("<a a2='b2'>bar</a>\n", render("%a(a2=b2) bar", :locals => {:b2 => 'b2'}))
|
1621
|
-
assert_equal(%Q{<a a='foo
|
1622
|
-
assert_equal(%Q{<a a=
|
1623
|
-
assert_equal(%Q{<a a='foo
|
1624
|
-
assert_equal(%Q{<a a=
|
1694
|
+
assert_equal(%Q{<a a='foo"bar'>bar</a>\n}, render(%q{%a(a="#{'foo"bar'}") bar})) #'
|
1695
|
+
assert_equal(%Q{<a a='foo'bar'>bar</a>\n}, render(%q{%a(a="#{"foo'bar"}") bar})) #'
|
1696
|
+
assert_equal(%Q{<a a='foo"bar'>bar</a>\n}, render(%q{%a(a='foo"bar') bar}))
|
1697
|
+
assert_equal(%Q{<a a='foo'bar'>bar</a>\n}, render(%q{%a(a="foo'bar") bar}))
|
1625
1698
|
assert_equal("<a a:b='foo'>bar</a>\n", render("%a(a:b='foo') bar"))
|
1626
1699
|
assert_equal("<a a='foo' b='bar'>bar</a>\n", render("%a(a = 'foo' b = 'bar') bar"))
|
1627
1700
|
assert_equal("<a a='foo' b='bar'>bar</a>\n", render("%a(a = foo b = bar) bar", :locals => {:foo => 'foo', :bar => 'bar'}))
|
@@ -1631,11 +1704,11 @@ HAML
|
|
1631
1704
|
end
|
1632
1705
|
|
1633
1706
|
def test_new_attribute_escaping
|
1634
|
-
assert_equal(%Q{<a a='foo
|
1635
|
-
assert_equal(%Q{<a a='foo
|
1707
|
+
assert_equal(%Q{<a a='foo " bar'>bar</a>\n}, render(%q{%a(a="foo \" bar") bar}))
|
1708
|
+
assert_equal(%Q{<a a='foo \\" bar'>bar</a>\n}, render(%q{%a(a="foo \\\\\" bar") bar}))
|
1636
1709
|
|
1637
|
-
assert_equal(%Q{<a a=
|
1638
|
-
assert_equal(%Q{<a a=
|
1710
|
+
assert_equal(%Q{<a a='foo ' bar'>bar</a>\n}, render(%q{%a(a='foo \' bar') bar}))
|
1711
|
+
assert_equal(%Q{<a a='foo \\' bar'>bar</a>\n}, render(%q{%a(a='foo \\\\\' bar') bar}))
|
1639
1712
|
|
1640
1713
|
assert_equal(%Q{<a a='foo \\ bar'>bar</a>\n}, render(%q{%a(a="foo \\\\ bar") bar}))
|
1641
1714
|
assert_equal(%Q{<a a='foo \#{1 + 1} bar'>bar</a>\n}, render(%q{%a(a="foo \#{1 + 1} bar") bar}))
|
@@ -1664,6 +1737,8 @@ HAML
|
|
1664
1737
|
locals = {:b => 'b', :d => 'd'}
|
1665
1738
|
assert_equal("<p a='b' c='d'></p>\n", render("%p{:a => b}(c=d)", :locals => locals))
|
1666
1739
|
assert_equal("<p a='b' c='d'></p>\n", render("%p(a=b){:c => d}", :locals => locals))
|
1740
|
+
|
1741
|
+
assert_equal("<p id='b_d'></p>\n<p id='b_d'></p>\n", render("%p(id=b){id:d}\n%p(id=b){id:d}", locals: locals))
|
1667
1742
|
end
|
1668
1743
|
|
1669
1744
|
# Ruby Multiline
|
@@ -1763,8 +1838,7 @@ HAML
|
|
1763
1838
|
|
1764
1839
|
def test_loud_ruby_multiline_with_block
|
1765
1840
|
assert_equal(<<HTML, render(<<HAML))
|
1766
|
-
#{%w[far faz fang]}
|
1767
|
-
<p>foo</p>
|
1841
|
+
#{%w[far faz fang]}<p>foo</p>
|
1768
1842
|
<p>bar</p>
|
1769
1843
|
HTML
|
1770
1844
|
= ["bar",
|
@@ -1877,7 +1951,7 @@ HAML
|
|
1877
1951
|
def test_utf_8_bom
|
1878
1952
|
assert_equal <<HTML, render(<<HAML)
|
1879
1953
|
<div class='foo'>
|
1880
|
-
|
1954
|
+
<p>baz</p>
|
1881
1955
|
</div>
|
1882
1956
|
HTML
|
1883
1957
|
\xEF\xBB\xBF.foo
|
@@ -1986,6 +2060,28 @@ HAML
|
|
1986
2060
|
end
|
1987
2061
|
end
|
1988
2062
|
|
2063
|
+
def test_tracing
|
2064
|
+
result = render('%p{:class => "hello"}', :trace => true, :filename => 'foo').strip
|
2065
|
+
assert_equal "<p class='hello' data-trace='foo:1'></p>", result
|
2066
|
+
end
|
2067
|
+
|
2068
|
+
def test_unsafe_dynamic_attribute_name_raises_invalid_attribute_name_error
|
2069
|
+
assert_raises(Haml::InvalidAttributeNameError) do
|
2070
|
+
render(<<-HAML)
|
2071
|
+
- params = { 'x /><script>alert(1);</script><div x' => 'hello' }
|
2072
|
+
%div{ data: params }
|
2073
|
+
HAML
|
2074
|
+
end
|
2075
|
+
end
|
2076
|
+
|
2077
|
+
def test_unsafe_static_attribute_name_raises_invalid_attribute_name_error
|
2078
|
+
assert_raises(Haml::InvalidAttributeNameError) do
|
2079
|
+
render(<<-HAML)
|
2080
|
+
%div{ 'x /><script>alert(1);</script><div x' => 'hello' }
|
2081
|
+
HAML
|
2082
|
+
end
|
2083
|
+
end
|
2084
|
+
|
1989
2085
|
private
|
1990
2086
|
|
1991
2087
|
def assert_valid_encoding_comment(comment)
|