haml 4.0.7 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +42 -4
  4. data/FAQ.md +4 -14
  5. data/MIT-LICENSE +1 -1
  6. data/README.md +85 -42
  7. data/REFERENCE.md +108 -57
  8. data/Rakefile +46 -54
  9. data/lib/haml/attribute_builder.rb +163 -0
  10. data/lib/haml/attribute_compiler.rb +215 -0
  11. data/lib/haml/attribute_parser.rb +144 -0
  12. data/lib/haml/buffer.rb +22 -132
  13. data/lib/haml/compiler.rb +87 -295
  14. data/lib/haml/engine.rb +25 -41
  15. data/lib/haml/error.rb +3 -0
  16. data/lib/haml/escapable.rb +49 -0
  17. data/lib/haml/exec.rb +33 -19
  18. data/lib/haml/filters.rb +18 -24
  19. data/lib/haml/generator.rb +41 -0
  20. data/lib/haml/helpers/action_view_extensions.rb +3 -2
  21. data/lib/haml/helpers/action_view_mods.rb +36 -58
  22. data/lib/haml/helpers/action_view_xss_mods.rb +1 -0
  23. data/lib/haml/helpers/safe_erubi_template.rb +27 -0
  24. data/lib/haml/helpers/safe_erubis_template.rb +4 -1
  25. data/lib/haml/helpers/xss_mods.rb +18 -12
  26. data/lib/haml/helpers.rb +133 -90
  27. data/lib/haml/options.rb +38 -47
  28. data/lib/haml/parser.rb +278 -216
  29. data/lib/haml/{template/plugin.rb → plugin.rb} +8 -15
  30. data/lib/haml/railtie.rb +21 -12
  31. data/lib/haml/sass_rails_filter.rb +17 -4
  32. data/lib/haml/template/options.rb +12 -2
  33. data/lib/haml/template.rb +12 -6
  34. data/lib/haml/temple_engine.rb +120 -0
  35. data/lib/haml/temple_line_counter.rb +29 -0
  36. data/lib/haml/util.rb +80 -199
  37. data/lib/haml/version.rb +2 -1
  38. data/lib/haml.rb +1 -0
  39. data/test/attribute_parser_test.rb +101 -0
  40. data/test/engine_test.rb +287 -176
  41. data/test/filters_test.rb +32 -19
  42. data/test/gemfiles/Gemfile.rails-4.0.x +9 -3
  43. data/test/gemfiles/Gemfile.rails-4.0.x.lock +87 -0
  44. data/test/gemfiles/Gemfile.rails-4.1.x +5 -0
  45. data/test/gemfiles/Gemfile.rails-4.2.x +5 -0
  46. data/test/gemfiles/Gemfile.rails-5.0.x +4 -0
  47. data/test/helper_test.rb +224 -112
  48. data/test/options_test.rb +22 -0
  49. data/test/parser_test.rb +71 -4
  50. data/test/results/bemit.xhtml +4 -0
  51. data/test/results/eval_suppressed.xhtml +4 -4
  52. data/test/results/helpers.xhtml +43 -41
  53. data/test/results/helpful.xhtml +6 -3
  54. data/test/results/just_stuff.xhtml +21 -20
  55. data/test/results/list.xhtml +9 -9
  56. data/test/results/nuke_inner_whitespace.xhtml +22 -22
  57. data/test/results/nuke_outer_whitespace.xhtml +84 -92
  58. data/test/results/original_engine.xhtml +17 -17
  59. data/test/results/partial_layout.xhtml +4 -3
  60. data/test/results/partial_layout_erb.xhtml +4 -3
  61. data/test/results/partials.xhtml +11 -10
  62. data/test/results/silent_script.xhtml +63 -63
  63. data/test/results/standard.xhtml +156 -159
  64. data/test/results/tag_parsing.xhtml +19 -19
  65. data/test/results/very_basic.xhtml +2 -2
  66. data/test/results/whitespace_handling.xhtml +77 -76
  67. data/test/template_test.rb +24 -56
  68. data/test/template_test_helper.rb +38 -0
  69. data/test/templates/bemit.haml +3 -0
  70. data/test/templates/just_stuff.haml +1 -0
  71. data/test/templates/standard_ugly.haml +1 -0
  72. data/test/templates/with_bom.haml +1 -0
  73. data/test/temple_line_counter_test.rb +40 -0
  74. data/test/test_helper.rb +26 -8
  75. data/test/util_test.rb +6 -47
  76. metadata +53 -43
  77. data/test/gemfiles/Gemfile.rails-3.0.x +0 -5
  78. data/test/gemfiles/Gemfile.rails-3.1.x +0 -6
  79. data/test/gemfiles/Gemfile.rails-3.2.x +0 -5
  80. data/test/haml-spec/LICENSE +0 -14
  81. data/test/haml-spec/README.md +0 -106
  82. data/test/haml-spec/lua_haml_spec.lua +0 -38
  83. data/test/haml-spec/perl_haml_test.pl +0 -81
  84. data/test/haml-spec/ruby_haml_test.rb +0 -23
  85. data/test/haml-spec/tests.json +0 -660
  86. data/test/templates/_av_partial_1_ugly.haml +0 -9
  87. data/test/templates/_av_partial_2_ugly.haml +0 -5
  88. data/test/templates/action_view_ugly.haml +0 -47
  89. 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 < MiniTest::Unit::TestCase
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.
@@ -113,13 +113,11 @@ class EngineTest < MiniTest::Unit::TestCase
113
113
  end
114
114
 
115
115
  def setup
116
- return if RUBY_VERSION < "1.9"
117
116
  @old_default_internal = Encoding.default_internal
118
117
  silence_warnings{Encoding.default_internal = nil}
119
118
  end
120
119
 
121
120
  def teardown
122
- return if RUBY_VERSION < "1.9"
123
121
  silence_warnings{Encoding.default_internal = @old_default_internal}
124
122
  end
125
123
 
@@ -128,11 +126,11 @@ class EngineTest < MiniTest::Unit::TestCase
128
126
  end
129
127
 
130
128
  def test_flexible_tabulation
131
- assert_equal("<p>\n foo\n</p>\n<q>\n bar\n <a>\n baz\n </a>\n</q>\n",
129
+ assert_equal("<p>\nfoo\n</p>\n<q>\nbar\n<a>\nbaz\n</a>\n</q>\n",
132
130
  render("%p\n foo\n%q\n bar\n %a\n baz"))
133
- assert_equal("<p>\n foo\n</p>\n<q>\n bar\n <a>\n baz\n </a>\n</q>\n",
131
+ assert_equal("<p>\nfoo\n</p>\n<q>\nbar\n<a>\nbaz\n</a>\n</q>\n",
134
132
  render("%p\n\tfoo\n%q\n\tbar\n\t%a\n\t\tbaz"))
135
- assert_equal("<p>\n \t \t bar\n baz\n</p>\n",
133
+ assert_equal("<p>\n \t \t bar\n baz\n</p>\n",
136
134
  render("%p\n :plain\n \t \t bar\n baz"))
137
135
  end
138
136
 
@@ -187,7 +185,7 @@ class EngineTest < MiniTest::Unit::TestCase
187
185
  def test_dynamic_attributes_with_no_content
188
186
  assert_equal(<<HTML, render(<<HAML))
189
187
  <p>
190
- <a href='http://haml.info'></a>
188
+ <a href='http://haml.info'></a>
191
189
  </p>
192
190
  HTML
193
191
  %p
@@ -224,7 +222,7 @@ HAML
224
222
  end
225
223
 
226
224
  def test_one_liner_with_newline_shouldnt_be_one_line
227
- assert_equal("<p>\n foo\n bar\n</p>", render('%p= "foo\nbar"').chomp)
225
+ assert_equal("<p>foo\nbar</p>", render('%p= "foo\nbar"').chomp)
228
226
  end
229
227
 
230
228
  def test_multi_render
@@ -235,8 +233,31 @@ HAML
235
233
  end
236
234
 
237
235
  def test_interpolation
238
- assert_equal("<p>Hello World</p>\n", render('%p Hello #{who}', :locals => {:who => 'World'}))
239
- assert_equal("<p>\n Hello World\n</p>\n", render("%p\n Hello \#{who}", :locals => {:who => 'World'}))
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
240
261
  end
241
262
 
242
263
  def test_interpolation_in_the_middle_of_a_string
@@ -244,9 +265,43 @@ HAML
244
265
  render("\"title '\#{\"Title\"}'. \""))
245
266
  end
246
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
+
247
285
  def test_interpolation_at_the_beginning_of_a_line
248
286
  assert_equal("<p>2</p>\n", render('%p #{1 + 1}'))
249
- assert_equal("<p>\n 2\n</p>\n", render("%p\n \#{1 + 1}"))
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
250
305
  end
251
306
 
252
307
  def test_escaped_interpolation
@@ -271,7 +326,7 @@ HAML
271
326
 
272
327
  def test_attribute_hash_with_newlines
273
328
  assert_equal("<p a='b' c='d'>foop</p>\n", render("%p{:a => 'b',\n :c => 'd'} foop"))
274
- assert_equal("<p a='b' c='d'>\n foop\n</p>\n", render("%p{:a => 'b',\n :c => 'd'}\n foop"))
329
+ assert_equal("<p a='b' c='d'>\nfoop\n</p>\n", render("%p{:a => 'b',\n :c => 'd'}\n foop"))
275
330
  assert_equal("<p a='b' c='d'>\n", render("%p{:a => 'b',\n :c => 'd'}/"))
276
331
  assert_equal("<p a='b' c='d' e='f'></p>\n", render("%p{:a => 'b',\n :c => 'd',\n :e => 'f'}"))
277
332
  end
@@ -290,8 +345,8 @@ HAML
290
345
  assert_equal(hash, {:color => 'red'})
291
346
  end
292
347
 
293
- def test_ugly_semi_prerendered_tags
294
- assert_equal(<<HTML, render(<<HAML, :ugly => true))
348
+ def test_semi_prerendered_tags
349
+ assert_equal(<<HTML, render(<<HAML))
295
350
  <p a='2'></p>
296
351
  <p a='2'>foo</p>
297
352
  <p a='2'>
@@ -333,7 +388,7 @@ HAML
333
388
  assert_equal("<textarea>#{'a' * 100}</textarea>\n",
334
389
  render("%textarea #{'a' * 100}"))
335
390
 
336
- assert_equal("<p>\n <textarea>Foo\n Bar\n Baz</textarea>\n</p>\n", render(<<SOURCE))
391
+ assert_equal("<p>\n<textarea>Foo\nBar\nBaz</textarea>\n</p>\n", render(<<SOURCE))
337
392
  %p
338
393
  %textarea
339
394
  Foo
@@ -380,7 +435,7 @@ HAML
380
435
  def test_both_whitespace_nukes_work_together
381
436
  assert_equal(<<RESULT, render(<<SOURCE))
382
437
  <p><q>Foo
383
- Bar</q></p>
438
+ Bar</q></p>
384
439
  RESULT
385
440
  %p
386
441
  %q><= "Foo\\nBar"
@@ -389,6 +444,7 @@ SOURCE
389
444
 
390
445
  def test_nil_option
391
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))
392
448
  end
393
449
 
394
450
  def test_comment_with_crazy_nesting
@@ -407,15 +463,14 @@ HAML
407
463
 
408
464
  # Regression tests
409
465
 
410
- unless RUBY_VERSION < "1.9"
411
- def test_indentation_after_dynamic_attr_hash
412
- assert_equal(<<HTML, render(<<HAML))
466
+ def test_indentation_after_dynamic_attr_hash
467
+ assert_equal(<<HTML, render(<<HAML))
413
468
  <html>
414
- <body>
415
- <img src='test'>
416
- foo
417
- bar
418
- </body>
469
+ <body>
470
+ <img src='test'>
471
+ foo
472
+ bar
473
+ </body>
419
474
  </html>
420
475
  HTML
421
476
  %html
@@ -423,14 +478,15 @@ HTML
423
478
  %img{:src => 'te'+'st'}
424
479
  = "foo\\nbar"
425
480
  HAML
426
- end
427
481
  end
428
482
 
429
483
  def test_whitespace_nuke_with_both_newlines
430
- assert_equal("<p>foo</p>\n", render('%p<= "\nfoo\n"'))
484
+ assert_equal("<p>\nfoo\n</p>\n", render('%p<= "\nfoo\n"'))
431
485
  assert_equal(<<HTML, render(<<HAML))
432
486
  <p>
433
- <p>foo</p>
487
+ <p>
488
+ foo
489
+ </p>
434
490
  </p>
435
491
  HTML
436
492
  %p
@@ -441,7 +497,7 @@ HAML
441
497
  def test_whitespace_nuke_with_tags_and_else
442
498
  assert_equal(<<HTML, render(<<HAML))
443
499
  <a>
444
- <b>foo</b>
500
+ <b>foo</b>
445
501
  </a>
446
502
  HTML
447
503
  %a
@@ -454,9 +510,9 @@ HAML
454
510
 
455
511
  assert_equal(<<HTML, render(<<HAML))
456
512
  <a>
457
- <b>
458
- foo
459
- </b>
513
+ <b>
514
+ foo
515
+ </b>
460
516
  </a>
461
517
  HTML
462
518
  %a
@@ -471,7 +527,7 @@ HAML
471
527
  def test_outer_whitespace_nuke_with_empty_script
472
528
  assert_equal(<<HTML, render(<<HAML))
473
529
  <p>
474
- foo<a></a></p>
530
+ foo <a></a></p>
475
531
  HTML
476
532
  %p
477
533
  foo
@@ -483,7 +539,7 @@ HAML
483
539
  def test_both_case_indentation_work_with_deeply_nested_code
484
540
  result = <<RESULT
485
541
  <h2>
486
- other
542
+ other
487
543
  </h2>
488
544
  RESULT
489
545
  assert_equal(result, render(<<HAML))
@@ -506,15 +562,15 @@ HAML
506
562
  HAML
507
563
  end
508
564
 
509
- def test_equals_block_with_ugly
510
- assert_equal("foo\n", render(<<HAML, :ugly => true))
565
+ def test_equals_block
566
+ assert_equal("foo\n", render(<<HAML))
511
567
  = capture_haml do
512
568
  foo
513
569
  HAML
514
570
  end
515
571
 
516
- def test_plain_equals_with_ugly
517
- assert_equal("foo\nbar\n", render(<<HAML, :ugly => true))
572
+ def test_plain_equals
573
+ assert_equal("foo\nbar\n", render(<<HAML))
518
574
  = "foo"
519
575
  bar
520
576
  HAML
@@ -532,10 +588,7 @@ HAML
532
588
  end
533
589
 
534
590
  def test_end_with_method_call
535
- assert_equal(<<HTML, render(<<HAML))
536
- 2|3|4
537
- b-a-r
538
- HTML
591
+ assert_equal("2|3|4b-a-r", render(<<HAML))
539
592
  = [1, 2, 3].map do |i|
540
593
  - i + 1
541
594
  - end.join("|")
@@ -549,9 +602,7 @@ HAML
549
602
  def test_nested_end_with_method_call
550
603
  assert_equal(<<HTML, render(<<HAML))
551
604
  <p>
552
- 2|3|4
553
- b-a-r
554
- </p>
605
+ 2|3|4b-a-r</p>
555
606
  HTML
556
607
  %p
557
608
  = [1, 2, 3].map do |i|
@@ -633,7 +684,7 @@ HAML
633
684
  def test_escape_attrs_false
634
685
  assert_equal(<<HTML, render(<<HAML, :escape_attrs => false))
635
686
  <div class='<?php echo "&quot;" ?>' id='foo'>
636
- bar
687
+ bar
637
688
  </div>
638
689
  HTML
639
690
  #foo{:class => '<?php echo "&quot;" ?>'}
@@ -642,9 +693,9 @@ HAML
642
693
  end
643
694
 
644
695
  def test_escape_attrs_always
645
- assert_equal(<<HTML, render(<<HAML, :escape_attrs => :always))
646
- <div class='"&amp;lt;&amp;gt;&amp;amp;"' id='foo'>
647
- bar
696
+ assert_equal(<<HTML, render(<<HAML, :escape_attrs => true))
697
+ <div class='&quot;&amp;lt;&amp;gt;&amp;amp;&quot;' id='foo'>
698
+ bar
648
699
  </div>
649
700
  HTML
650
701
  #foo{:class => '"&lt;&gt;&amp;"'}
@@ -764,7 +815,7 @@ HAML
764
815
  assert_equal("<a href='#'>Foo</a>\n",
765
816
  render('%a(href="#") #{"Foo"}'))
766
817
 
767
- assert_equal("<a href='#\"'></a>\n", render('%a(href="#\\"")'))
818
+ assert_equal("<a href='#&quot;'></a>\n", render('%a(href="#\\"")'))
768
819
  end
769
820
 
770
821
  def test_case_assigned_to_var
@@ -893,7 +944,7 @@ HAML
893
944
  # HTML escaping tests
894
945
 
895
946
  def test_ampersand_equals_should_escape
896
- assert_equal("<p>\n foo &amp; bar\n</p>\n", render("%p\n &= 'foo & bar'", :escape_html => false))
947
+ assert_equal("<p>\nfoo &amp; bar\n</p>\n", render("%p\n &= 'foo & bar'", :escape_html => false))
897
948
  end
898
949
 
899
950
  def test_ampersand_equals_inline_should_escape
@@ -905,7 +956,7 @@ HAML
905
956
  end
906
957
 
907
958
  def test_bang_equals_should_not_escape
908
- assert_equal("<p>\n foo & bar\n</p>\n", render("%p\n != 'foo & bar'", :escape_html => true))
959
+ assert_equal("<p>\nfoo & bar\n</p>\n", render("%p\n != 'foo & bar'", :escape_html => true))
909
960
  end
910
961
 
911
962
  def test_bang_equals_inline_should_not_escape
@@ -919,8 +970,6 @@ HAML
919
970
  render(".atlantis{:style => 'ugly&stupid'} foo"))
920
971
  assert_equal("<p class='atlantis' style='ugly&amp;stupid'>foo</p>\n",
921
972
  render("%p.atlantis{:style => 'ugly&stupid'}= 'foo'"))
922
- assert_equal("<p class='atlantis' style='ugly&#x000A;stupid'></p>\n",
923
- render("%p.atlantis{:style => \"ugly\\nstupid\"}"))
924
973
  end
925
974
 
926
975
  def test_dynamic_attributes_should_be_escaped
@@ -930,8 +979,6 @@ HAML
930
979
  render("%p{:width => nil, :src => '&foo.png', :alt => String.new} foo"))
931
980
  assert_equal("<div alt='' src='&amp;foo.png'>foo</div>\n",
932
981
  render("%div{:width => nil, :src => '&foo.png', :alt => String.new}= 'foo'"))
933
- assert_equal("<img alt='' src='foo&#x000A;.png'>\n",
934
- render("%img{:width => nil, :src => \"foo\\n.png\", :alt => String.new}"))
935
982
  end
936
983
 
937
984
  def test_string_double_equals_should_be_esaped
@@ -950,13 +997,13 @@ HAML
950
997
  end
951
998
 
952
999
  def test_escaped_string_double_equals
953
- assert_equal("<p>\n 4&&lt;\n</p>\n", render("%p\n &== \#{2+2}&\#{'<'}", :escape_html => true))
954
- assert_equal("<p>\n 4&&lt;\n</p>\n", render("%p\n &== \#{2+2}&\#{'<'}", :escape_html => false))
1000
+ assert_equal("<p>\n4&&lt;\n</p>\n", render("%p\n &== \#{2+2}&\#{'<'}", :escape_html => true))
1001
+ assert_equal("<p>\n4&&lt;\n</p>\n", render("%p\n &== \#{2+2}&\#{'<'}", :escape_html => false))
955
1002
  end
956
1003
 
957
1004
  def test_unescaped_string_double_equals
958
- assert_equal("<p>\n 4&<\n</p>\n", render("%p\n !== \#{2+2}&\#{'<'}", :escape_html => true))
959
- assert_equal("<p>\n 4&<\n</p>\n", render("%p\n !== \#{2+2}&\#{'<'}", :escape_html => false))
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))
960
1007
  end
961
1008
 
962
1009
  def test_string_interpolation_should_be_esaped
@@ -975,18 +1022,28 @@ HAML
975
1022
  end
976
1023
 
977
1024
  def test_escaped_string_interpolation
978
- assert_equal("<p>\n 4&&lt;\n</p>\n", render("%p\n & \#{2+2}&\#{'<'}", :escape_html => true))
979
- assert_equal("<p>\n 4&&lt;\n</p>\n", render("%p\n & \#{2+2}&\#{'<'}", :escape_html => false))
1025
+ assert_equal("<p>\n4&&lt;\n</p>\n", render("%p\n & \#{2+2}&\#{'<'}", :escape_html => true))
1026
+ assert_equal("<p>\n4&&lt;\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("&lt;br&gt;\n", render('&#{"<br>"}'))
1031
+ assert_equal("<span>&lt;br&gt;</span>\n", render('%span&#{"<br>"}'))
980
1032
  end
981
1033
 
982
1034
  def test_unescaped_string_interpolation
983
- assert_equal("<p>\n 4&<\n</p>\n", render("%p\n ! \#{2+2}&\#{'<'}", :escape_html => true))
984
- assert_equal("<p>\n 4&<\n</p>\n", render("%p\n ! \#{2+2}&\#{'<'}", :escape_html => false))
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>"}'))
985
1042
  end
986
1043
 
987
1044
  def test_scripts_should_respect_escape_html_option
988
- assert_equal("<p>\n foo &amp; bar\n</p>\n", render("%p\n = 'foo & bar'", :escape_html => true))
989
- assert_equal("<p>\n foo & bar\n</p>\n", render("%p\n = 'foo & bar'", :escape_html => false))
1045
+ assert_equal("<p>\nfoo &amp; 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))
990
1047
  end
991
1048
 
992
1049
  def test_inline_scripts_should_respect_escape_html_option
@@ -1065,9 +1122,9 @@ HAML
1065
1122
 
1066
1123
  def test_attr_wrapper
1067
1124
  assert_equal("<p strange=*attrs*></p>\n", render("%p{ :strange => 'attrs'}", :attr_wrapper => '*'))
1068
- assert_equal("<p escaped='quo\"te'></p>\n", render("%p{ :escaped => 'quo\"te'}", :attr_wrapper => '"'))
1069
- assert_equal("<p escaped=\"quo'te\"></p>\n", render("%p{ :escaped => 'quo\\'te'}", :attr_wrapper => '"'))
1070
- assert_equal("<p escaped=\"q'uo&#x0022;te\"></p>\n", render("%p{ :escaped => 'q\\'uo\"te'}", :attr_wrapper => '"'))
1125
+ assert_equal("<p escaped=\"quo&quot;te\"></p>\n", render("%p{ :escaped => 'quo\"te'}", :attr_wrapper => '"'))
1126
+ assert_equal("<p escaped=\"quo&#39;te\"></p>\n", render("%p{ :escaped => 'quo\\'te'}", :attr_wrapper => '"'))
1127
+ assert_equal("<p escaped=\"q&#39;uo&quot;te\"></p>\n", render("%p{ :escaped => 'q\\'uo\"te'}", :attr_wrapper => '"'))
1071
1128
  assert_equal("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n", render("!!! XML", :attr_wrapper => '"', :format => :xhtml))
1072
1129
  end
1073
1130
 
@@ -1085,9 +1142,7 @@ HAML
1085
1142
  end
1086
1143
 
1087
1144
  def test_attrs_parsed_correctly
1088
- assert_equal("<p boom=>biddly='bar =&gt; baz'></p>\n", render("%p{'boom=>biddly' => 'bar => baz'}"))
1089
1145
  assert_equal("<p foo,bar='baz, qux'></p>\n", render("%p{'foo,bar' => 'baz, qux'}"))
1090
- assert_equal("<p escaped='quo&#x000A;te'></p>\n", render("%p{ :escaped => \"quo\\nte\"}"))
1091
1146
  assert_equal("<p escaped='quo4te'></p>\n", render("%p{ :escaped => \"quo\#{2 + 2}te\"}"))
1092
1147
  end
1093
1148
 
@@ -1193,10 +1248,10 @@ HAML
1193
1248
  def test_compile_error
1194
1249
  render("a\nb\n- fee)\nc")
1195
1250
  rescue Exception => e
1196
- assert_match(/\(test_compile_error\):3: (syntax error|expecting \$end)/i, e.message)
1251
+ assert_match(/\(test_compile_error\):3:/i, e.message)
1252
+ assert_match(/(syntax error|expecting \$end)/i, e.message)
1197
1253
  else
1198
- assert(false,
1199
- '"a\nb\n- fee)\nc" doesn\'t produce an exception!')
1254
+ assert(false, '"a\nb\n- fee)\nc" doesn\'t produce an exception!')
1200
1255
  end
1201
1256
 
1202
1257
  def test_unbalanced_brackets
@@ -1205,14 +1260,39 @@ HAML
1205
1260
  assert_equal(Haml::Error.message(:unbalanced_brackets), e.message)
1206
1261
  end
1207
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
+
1208
1278
  def test_balanced_conditional_comments
1209
1279
  assert_equal("<!--[if !(IE 6)|(IE 7)]> Bracket: ] <![endif]-->\n",
1210
1280
  render("/[if !(IE 6)|(IE 7)] Bracket: ]"))
1211
1281
  end
1212
1282
 
1283
+ def test_downlevel_revealed_conditional_comments
1284
+ assert_equal("<!--[if !IE]><!--> A comment <!--<![endif]-->\n",
1285
+ render("/![if !IE] A comment"))
1286
+ end
1287
+
1288
+ def test_downlevel_revealed_conditional_comments_block
1289
+ assert_equal("<!--[if !IE]><!-->\nA comment\n<!--<![endif]-->\n",
1290
+ render("/![if !IE]\n A comment"))
1291
+ end
1292
+
1213
1293
  def test_local_assigns_dont_modify_class
1214
1294
  assert_equal("bar\n", render("= foo", :locals => {:foo => 'bar'}))
1215
- assert_equal(nil, defined?(foo))
1295
+ assert_nil(defined?(foo))
1216
1296
  end
1217
1297
 
1218
1298
  def test_object_ref_with_nil_id
@@ -1247,7 +1327,7 @@ HAML
1247
1327
 
1248
1328
  def test_render_should_accept_a_binding_as_scope
1249
1329
  string = "This is a string!"
1250
- string.instance_variable_set("@var", "Instance variable")
1330
+ string.instance_variable_set(:@var, "Instance variable")
1251
1331
  b = string.instance_eval do
1252
1332
  var = "Local variable"
1253
1333
  # Silence unavoidable warning; Ruby doesn't know we're going to use this
@@ -1328,15 +1408,15 @@ HAML
1328
1408
  end
1329
1409
  end
1330
1410
 
1331
- def test_ugly_true
1411
+ def test_spacing_inside_tag
1332
1412
  assert_equal("<div id='outer'>\n<div id='inner'>\n<p>hello world</p>\n</div>\n</div>\n",
1333
- render("#outer\n #inner\n %p hello world", :ugly => true))
1413
+ render("#outer\n #inner\n %p hello world"))
1334
1414
 
1335
1415
  assert_equal("<p>#{'s' * 75}</p>\n",
1336
- render("%p #{'s' * 75}", :ugly => true))
1416
+ render("%p #{'s' * 75}"))
1337
1417
 
1338
1418
  assert_equal("<p>#{'s' * 75}</p>\n",
1339
- render("%p= 's' * 75", :ugly => true))
1419
+ render("%p= 's' * 75"))
1340
1420
  end
1341
1421
 
1342
1422
  def test_remove_whitespace_true
@@ -1353,15 +1433,13 @@ HAML
1353
1433
  render('%div <span>foo</span> <span>bar</span>', :remove_whitespace => true))
1354
1434
  end
1355
1435
 
1356
- def test_auto_preserve_unless_ugly
1436
+ def test_auto_preserve
1357
1437
  assert_equal("<pre>foo&#x000A;bar</pre>\n", render('%pre="foo\nbar"'))
1358
1438
  assert_equal("<pre>foo\nbar</pre>\n", render("%pre\n foo\n bar"))
1359
- assert_equal("<pre>foo\nbar</pre>\n", render('%pre="foo\nbar"', :ugly => true))
1360
- assert_equal("<pre>foo\nbar</pre>\n", render("%pre\n foo\n bar", :ugly => true))
1361
1439
  end
1362
1440
 
1363
1441
  def test_xhtml_output_option
1364
- assert_equal "<p>\n <br />\n</p>\n", render("%p\n %br", :format => :xhtml)
1442
+ assert_equal "<p>\n<br />\n</p>\n", render("%p\n %br", :format => :xhtml)
1365
1443
  assert_equal "<a />\n", render("%a/", :format => :xhtml)
1366
1444
  end
1367
1445
 
@@ -1394,6 +1472,8 @@ HAML
1394
1472
  engine = Haml::Engine.new('%a{:b => "a #$global_var_for_testing b"}')
1395
1473
  $global_var_for_testing = 'bar'
1396
1474
  assert_equal("<a b='a bar b'></a>\n", engine.to_html)
1475
+ ensure
1476
+ $global_var_for_testing = nil
1397
1477
  end
1398
1478
 
1399
1479
  def test_utf8_attrs
@@ -1404,7 +1484,7 @@ HAML
1404
1484
  # HTML 4.0
1405
1485
 
1406
1486
  def test_html_has_no_self_closing_tags
1407
- assert_equal "<p>\n <br>\n</p>\n", render("%p\n %br", :format => :html4)
1487
+ assert_equal "<p>\n<br>\n</p>\n", render("%p\n %br", :format => :html4)
1408
1488
  assert_equal "<br>\n", render("%br/", :format => :html4)
1409
1489
  end
1410
1490
 
@@ -1448,7 +1528,7 @@ HAML
1448
1528
  render("%div{:data => {:one_plus_one => 1+1}}",
1449
1529
  :hyphenate_data_attrs => false))
1450
1530
 
1451
- assert_equal("<div data-foo='Here&#x0027;s a \"quoteful\" string.'></div>\n",
1531
+ assert_equal("<div data-foo='Here&#39;s a &quot;quoteful&quot; string.'></div>\n",
1452
1532
  render(%{%div{:data => {:foo => %{Here's a "quoteful" string.}}}},
1453
1533
  :hyphenate_data_attrs => false)) #'
1454
1534
  end
@@ -1467,6 +1547,21 @@ HAML
1467
1547
  render("%div{:foo => {:baz => 'bang'}}"))
1468
1548
  end
1469
1549
 
1550
+ def test_arbitrary_attribute_hash_merging
1551
+ assert_equal(%Q{<a aria-baz='qux' aria-foo='bar'></a>\n}, render(<<-HAML))
1552
+ - h1 = {:aria => {:foo => :bar}}
1553
+ - h2 = {:baz => :qux}
1554
+ %a{h1, :aria => h2}
1555
+ HAML
1556
+ end
1557
+
1558
+ def test_hash_method_call_in_attributes
1559
+ assert_equal(%Q{<a foo='bar' hoge='fuga'></a>\n}, render(<<-HAML))
1560
+ - hash = {:hoge => :fuga}
1561
+ %a{{foo: 'bar'}.merge(hash)}
1562
+ HAML
1563
+ end
1564
+
1470
1565
  def test_html5_data_attributes_with_nested_hash
1471
1566
  assert_equal("<div data-a-b='c'></div>\n", render(<<-HAML))
1472
1567
  - hash = {:a => {:b => 'c'}}
@@ -1492,24 +1587,23 @@ HAML
1492
1587
  end
1493
1588
 
1494
1589
  def test_html5_data_attributes_with_attr_method
1495
- Haml::Helpers.module_eval do
1496
- def data_hash
1497
- {:data => {:foo => "bar", :baz => "bang"}}
1498
- end
1590
+ obj = Object.new
1591
+ def obj.data_hash
1592
+ {:data => {:foo => "bar", :baz => "bang"}}
1593
+ end
1499
1594
 
1500
- def data_val
1501
- {:data => "dat"}
1502
- end
1595
+ def obj.data_val
1596
+ {:data => "dat"}
1503
1597
  end
1504
1598
 
1505
1599
  assert_equal("<div data-baz='bang' data-brat='wurst' data-foo='blip'></div>\n",
1506
- render("%div{data_hash, :data => {:foo => 'blip', :brat => 'wurst'}}"))
1600
+ render("%div{data_hash, :data => {:foo => 'blip', :brat => 'wurst'}}", scope: obj))
1507
1601
  assert_equal("<div data-baz='bang' data-foo='blip'></div>\n",
1508
- render("%div{data_hash, 'data-foo' => 'blip'}"))
1602
+ render("%div{data_hash, 'data-foo' => 'blip'}", scope: obj))
1509
1603
  assert_equal("<div data-baz='bang' data-foo='bar' data='dat'></div>\n",
1510
- render("%div{data_hash, :data => 'dat'}"))
1604
+ render("%div{data_hash, :data => 'dat'}", scope: obj))
1511
1605
  assert_equal("<div data-brat='wurst' data-foo='blip' data='dat'></div>\n",
1512
- render("%div{data_val, :data => {:foo => 'blip', :brat => 'wurst'}}"))
1606
+ render("%div{data_val, :data => {:foo => 'blip', :brat => 'wurst'}}", scope: obj))
1513
1607
  end
1514
1608
 
1515
1609
  def test_html5_data_attributes_with_identical_attribute_values
@@ -1521,8 +1615,8 @@ HAML
1521
1615
  assert_equal(<<XML, render(<<HAML, { :format => :html5, :mime_type => 'text/xml' }))
1522
1616
  <?xml version='1.0' encoding='utf-8' ?>
1523
1617
  <root>
1524
- <element />
1525
- <hr />
1618
+ <element />
1619
+ <hr />
1526
1620
  </root>
1527
1621
  XML
1528
1622
  !!! XML
@@ -1536,8 +1630,8 @@ HAML
1536
1630
  assert_equal(<<XML, render(<<HAML, { :format => :html4, :mime_type => 'text/xml' }))
1537
1631
  <?xml version='1.0' encoding='utf-8' ?>
1538
1632
  <root>
1539
- <element />
1540
- <hr />
1633
+ <element />
1634
+ <hr />
1541
1635
  </root>
1542
1636
  XML
1543
1637
  !!! XML
@@ -1603,10 +1697,10 @@ HAML
1603
1697
 
1604
1698
  def test_new_attribute_parsing
1605
1699
  assert_equal("<a a2='b2'>bar</a>\n", render("%a(a2=b2) bar", :locals => {:b2 => 'b2'}))
1606
- assert_equal(%Q{<a a='foo"bar'>bar</a>\n}, render(%q{%a(a="#{'foo"bar'}") bar})) #'
1607
- assert_equal(%Q{<a a="foo'bar">bar</a>\n}, render(%q{%a(a="#{"foo'bar"}") bar})) #'
1608
- assert_equal(%Q{<a a='foo"bar'>bar</a>\n}, render(%q{%a(a='foo"bar') bar}))
1609
- assert_equal(%Q{<a a="foo'bar">bar</a>\n}, render(%q{%a(a="foo'bar") bar}))
1700
+ assert_equal(%Q{<a a='foo&quot;bar'>bar</a>\n}, render(%q{%a(a="#{'foo"bar'}") bar})) #'
1701
+ assert_equal(%Q{<a a='foo&#39;bar'>bar</a>\n}, render(%q{%a(a="#{"foo'bar"}") bar})) #'
1702
+ assert_equal(%Q{<a a='foo&quot;bar'>bar</a>\n}, render(%q{%a(a='foo"bar') bar}))
1703
+ assert_equal(%Q{<a a='foo&#39;bar'>bar</a>\n}, render(%q{%a(a="foo'bar") bar}))
1610
1704
  assert_equal("<a a:b='foo'>bar</a>\n", render("%a(a:b='foo') bar"))
1611
1705
  assert_equal("<a a='foo' b='bar'>bar</a>\n", render("%a(a = 'foo' b = 'bar') bar"))
1612
1706
  assert_equal("<a a='foo' b='bar'>bar</a>\n", render("%a(a = foo b = bar) bar", :locals => {:foo => 'foo', :bar => 'bar'}))
@@ -1616,11 +1710,11 @@ HAML
1616
1710
  end
1617
1711
 
1618
1712
  def test_new_attribute_escaping
1619
- assert_equal(%Q{<a a='foo " bar'>bar</a>\n}, render(%q{%a(a="foo \" bar") bar}))
1620
- assert_equal(%Q{<a a='foo \\" bar'>bar</a>\n}, render(%q{%a(a="foo \\\\\" bar") bar}))
1713
+ assert_equal(%Q{<a a='foo &quot; bar'>bar</a>\n}, render(%q{%a(a="foo \" bar") bar}))
1714
+ assert_equal(%Q{<a a='foo \\&quot; bar'>bar</a>\n}, render(%q{%a(a="foo \\\\\" bar") bar}))
1621
1715
 
1622
- assert_equal(%Q{<a a="foo ' bar">bar</a>\n}, render(%q{%a(a='foo \' bar') bar}))
1623
- assert_equal(%Q{<a a="foo \\' bar">bar</a>\n}, render(%q{%a(a='foo \\\\\' bar') bar}))
1716
+ assert_equal(%Q{<a a='foo &#39; bar'>bar</a>\n}, render(%q{%a(a='foo \' bar') bar}))
1717
+ assert_equal(%Q{<a a='foo \\&#39; bar'>bar</a>\n}, render(%q{%a(a='foo \\\\\' bar') bar}))
1624
1718
 
1625
1719
  assert_equal(%Q{<a a='foo \\ bar'>bar</a>\n}, render(%q{%a(a="foo \\\\ bar") bar}))
1626
1720
  assert_equal(%Q{<a a='foo \#{1 + 1} bar'>bar</a>\n}, render(%q{%a(a="foo \#{1 + 1} bar") bar}))
@@ -1649,6 +1743,8 @@ HAML
1649
1743
  locals = {:b => 'b', :d => 'd'}
1650
1744
  assert_equal("<p a='b' c='d'></p>\n", render("%p{:a => b}(c=d)", :locals => locals))
1651
1745
  assert_equal("<p a='b' c='d'></p>\n", render("%p(a=b){:c => d}", :locals => locals))
1746
+
1747
+ 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))
1652
1748
  end
1653
1749
 
1654
1750
  # Ruby Multiline
@@ -1696,11 +1792,7 @@ HAML
1696
1792
  end
1697
1793
 
1698
1794
  def test_ruby_character_literals_are_not_continuation
1699
- html = if RUBY_VERSION < "1.9"
1700
- "44\n44\n<p>foo</p>\n"
1701
- else
1702
- ",\n,\n<p>foo</p>\n"
1703
- end
1795
+ html = ",\n,\n<p>foo</p>\n"
1704
1796
  assert_equal(html, render(<<HAML))
1705
1797
  = ?,
1706
1798
  = ?\,
@@ -1752,8 +1844,7 @@ HAML
1752
1844
 
1753
1845
  def test_loud_ruby_multiline_with_block
1754
1846
  assert_equal(<<HTML, render(<<HAML))
1755
- #{%w[far faz fang]}
1756
- <p>foo</p>
1847
+ #{%w[far faz fang]}<p>foo</p>
1757
1848
  <p>bar</p>
1758
1849
  HTML
1759
1850
  = ["bar",
@@ -1866,7 +1957,7 @@ HAML
1866
1957
  def test_utf_8_bom
1867
1958
  assert_equal <<HTML, render(<<HAML)
1868
1959
  <div class='foo'>
1869
- <p>baz</p>
1960
+ <p>baz</p>
1870
1961
  </div>
1871
1962
  HTML
1872
1963
  \xEF\xBB\xBF.foo
@@ -1874,60 +1965,59 @@ HTML
1874
1965
  HAML
1875
1966
  end
1876
1967
 
1877
- unless RUBY_VERSION < "1.9"
1878
- def test_default_encoding
1879
- assert_equal(Encoding.find("utf-8"), render(<<HAML.encode("us-ascii")).encoding)
1968
+ def test_default_encoding
1969
+ assert_equal(Encoding.find("utf-8"), render(<<HAML.encode("us-ascii")).encoding)
1880
1970
  %p bar
1881
1971
  %p foo
1882
1972
  HAML
1883
- end
1973
+ end
1884
1974
 
1885
- def test_fake_ascii_encoding
1886
- assert_encoded_equal(<<HTML.force_encoding("ascii-8bit"), render(<<HAML, :encoding => "ascii-8bit"))
1975
+ def test_fake_ascii_encoding
1976
+ assert_encoded_equal(<<HTML.force_encoding("ascii-8bit"), render(<<HAML, :encoding => "ascii-8bit"))
1887
1977
  <p>bâr</p>
1888
1978
  <p>föö</p>
1889
1979
  HTML
1890
1980
  %p bâr
1891
1981
  %p föö
1892
1982
  HAML
1893
- end
1983
+ end
1894
1984
 
1895
- def test_convert_template_render_proc
1896
- assert_converts_template_properly {|e| e.render_proc.call}
1897
- end
1985
+ def test_convert_template_render_proc
1986
+ assert_converts_template_properly {|e| e.render_proc.call}
1987
+ end
1898
1988
 
1899
- def test_convert_template_render
1900
- assert_converts_template_properly {|e| e.render}
1901
- end
1989
+ def test_convert_template_render
1990
+ assert_converts_template_properly {|e| e.render}
1991
+ end
1902
1992
 
1903
- def test_convert_template_def_method
1904
- assert_converts_template_properly do |e|
1905
- o = Object.new
1906
- e.def_method(o, :render)
1907
- o.render
1908
- end
1993
+ def test_convert_template_def_method
1994
+ assert_converts_template_properly do |e|
1995
+ o = Object.new
1996
+ e.def_method(o, :render)
1997
+ o.render
1909
1998
  end
1999
+ end
1910
2000
 
1911
- def test_encoding_error
1912
- render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
1913
- assert(false, "Expected exception")
1914
- rescue Haml::Error => e
1915
- assert_equal(3, e.line)
1916
- assert_match(/Invalid .* character/, e.message)
1917
- end
2001
+ def test_encoding_error
2002
+ render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
2003
+ assert(false, "Expected exception")
2004
+ rescue Haml::Error => e
2005
+ assert_equal(3, e.line)
2006
+ assert_match(/Invalid .* character/, e.message)
2007
+ end
1918
2008
 
1919
- def test_ascii_incompatible_encoding_error
1920
- template = "foo\nbar\nb_z".encode("utf-16le")
1921
- template[9] = "\xFE".force_encoding("utf-16le")
1922
- render(template)
1923
- assert(false, "Expected exception")
1924
- rescue Haml::Error => e
1925
- assert_equal(3, e.line)
1926
- assert_match(/Invalid .* character/, e.message)
1927
- end
2009
+ def test_ascii_incompatible_encoding_error
2010
+ template = "foo\nbar\nb_z".encode("utf-16le")
2011
+ template[9] = "\xFE".force_encoding("utf-16le")
2012
+ render(template)
2013
+ assert(false, "Expected exception")
2014
+ rescue Haml::Error => e
2015
+ assert_equal(3, e.line)
2016
+ assert_match(/Invalid .* character/, e.message)
2017
+ end
1928
2018
 
1929
- def test_same_coding_comment_as_encoding
1930
- assert_renders_encoded(<<HTML, <<HAML)
2019
+ def test_same_coding_comment_as_encoding
2020
+ assert_renders_encoded(<<HTML, <<HAML)
1931
2021
  <p>bâr</p>
1932
2022
  <p>föö</p>
1933
2023
  HTML
@@ -1935,34 +2025,33 @@ HTML
1935
2025
  %p bâr
1936
2026
  %p föö
1937
2027
  HAML
1938
- end
1939
-
1940
- def test_coding_comments
1941
- assert_valid_encoding_comment("-# coding: ibm866")
1942
- assert_valid_encoding_comment("-# CodINg: IbM866")
1943
- assert_valid_encoding_comment("-#coding:ibm866")
1944
- assert_valid_encoding_comment("-# CodINg= ibm866")
1945
- assert_valid_encoding_comment("-# foo BAR FAOJcoding: ibm866")
1946
- assert_valid_encoding_comment("-# coding: ibm866 ASFJ (&(&#!$")
1947
- assert_valid_encoding_comment("-# -*- coding: ibm866")
1948
- assert_valid_encoding_comment("-# coding: ibm866 -*- coding: blah")
1949
- assert_valid_encoding_comment("-# -*- coding: ibm866 -*-")
1950
- assert_valid_encoding_comment("-# -*- encoding: ibm866 -*-")
1951
- assert_valid_encoding_comment('-# -*- coding: "ibm866" -*-')
1952
- assert_valid_encoding_comment("-#-*-coding:ibm866-*-")
1953
- assert_valid_encoding_comment("-#-*-coding:ibm866-*-")
1954
- assert_valid_encoding_comment("-# -*- foo: bar; coding: ibm866; baz: bang -*-")
1955
- assert_valid_encoding_comment("-# foo bar coding: baz -*- coding: ibm866 -*-")
1956
- assert_valid_encoding_comment("-# -*- coding: ibm866 -*- foo bar coding: baz")
1957
- end
2028
+ end
1958
2029
 
1959
- def test_different_coding_than_system
1960
- assert_renders_encoded(<<HTML.encode("IBM866"), <<HAML.encode("IBM866"))
2030
+ def test_coding_comments
2031
+ assert_valid_encoding_comment("-# coding: ibm866")
2032
+ assert_valid_encoding_comment("-# CodINg: IbM866")
2033
+ assert_valid_encoding_comment("-#coding:ibm866")
2034
+ assert_valid_encoding_comment("-# CodINg= ibm866")
2035
+ assert_valid_encoding_comment("-# foo BAR FAOJcoding: ibm866")
2036
+ assert_valid_encoding_comment("-# coding: ibm866 ASFJ (&(&#!$")
2037
+ assert_valid_encoding_comment("-# -*- coding: ibm866")
2038
+ assert_valid_encoding_comment("-# coding: ibm866 -*- coding: blah")
2039
+ assert_valid_encoding_comment("-# -*- coding: ibm866 -*-")
2040
+ assert_valid_encoding_comment("-# -*- encoding: ibm866 -*-")
2041
+ assert_valid_encoding_comment('-# -*- coding: "ibm866" -*-')
2042
+ assert_valid_encoding_comment("-#-*-coding:ibm866-*-")
2043
+ assert_valid_encoding_comment("-#-*-coding:ibm866-*-")
2044
+ assert_valid_encoding_comment("-# -*- foo: bar; coding: ibm866; baz: bang -*-")
2045
+ assert_valid_encoding_comment("-# foo bar coding: baz -*- coding: ibm866 -*-")
2046
+ assert_valid_encoding_comment("-# -*- coding: ibm866 -*- foo bar coding: baz")
2047
+ end
2048
+
2049
+ def test_different_coding_than_system
2050
+ assert_renders_encoded(<<HTML.encode("IBM866"), <<HAML.encode("IBM866"))
1961
2051
  <p>тАЬ</p>
1962
2052
  HTML
1963
2053
  %p тАЬ
1964
2054
  HAML
1965
- end
1966
2055
  end
1967
2056
 
1968
2057
  def test_block_spacing
@@ -1977,6 +2066,28 @@ HAML
1977
2066
  end
1978
2067
  end
1979
2068
 
2069
+ def test_tracing
2070
+ result = render('%p{:class => "hello"}', :trace => true, :filename => 'foo').strip
2071
+ assert_equal "<p class='hello' data-trace='foo:1'></p>", result
2072
+ end
2073
+
2074
+ def test_unsafe_dynamic_attribute_name_raises_invalid_attribute_name_error
2075
+ assert_raises(Haml::InvalidAttributeNameError) do
2076
+ render(<<-HAML)
2077
+ - params = { 'x /><script>alert(1);</script><div x' => 'hello' }
2078
+ %div{ data: params }
2079
+ HAML
2080
+ end
2081
+ end
2082
+
2083
+ def test_unsafe_static_attribute_name_raises_invalid_attribute_name_error
2084
+ assert_raises(Haml::InvalidAttributeNameError) do
2085
+ render(<<-HAML)
2086
+ %div{ 'x /><script>alert(1);</script><div x' => 'hello' }
2087
+ HAML
2088
+ end
2089
+ end
2090
+
1980
2091
  private
1981
2092
 
1982
2093
  def assert_valid_encoding_comment(comment)