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.

Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +36 -6
  4. data/FAQ.md +4 -14
  5. data/MIT-LICENSE +1 -1
  6. data/README.md +81 -48
  7. data/REFERENCE.md +86 -50
  8. data/Rakefile +28 -41
  9. data/lib/haml/attribute_builder.rb +163 -0
  10. data/lib/haml/attribute_compiler.rb +214 -0
  11. data/lib/haml/attribute_parser.rb +112 -0
  12. data/lib/haml/buffer.rb +24 -126
  13. data/lib/haml/compiler.rb +62 -281
  14. data/lib/haml/engine.rb +16 -23
  15. data/lib/haml/error.rb +2 -0
  16. data/lib/haml/escapable.rb +48 -0
  17. data/lib/haml/exec.rb +23 -12
  18. data/lib/haml/filters.rb +3 -4
  19. data/lib/haml/generator.rb +36 -0
  20. data/lib/haml/helpers.rb +61 -48
  21. data/lib/haml/helpers/action_view_extensions.rb +1 -1
  22. data/lib/haml/helpers/action_view_mods.rb +32 -50
  23. data/lib/haml/helpers/safe_erubi_template.rb +26 -0
  24. data/lib/haml/helpers/safe_erubis_template.rb +2 -0
  25. data/lib/haml/helpers/xss_mods.rb +17 -12
  26. data/lib/haml/options.rb +32 -36
  27. data/lib/haml/parser.rb +61 -38
  28. data/lib/haml/{template/plugin.rb → plugin.rb} +5 -2
  29. data/lib/haml/railtie.rb +14 -6
  30. data/lib/haml/template.rb +11 -6
  31. data/lib/haml/temple_engine.rb +119 -0
  32. data/lib/haml/temple_line_counter.rb +28 -0
  33. data/lib/haml/util.rb +17 -112
  34. data/lib/haml/version.rb +1 -1
  35. data/test/attribute_parser_test.rb +105 -0
  36. data/test/engine_test.rb +202 -106
  37. data/test/filters_test.rb +32 -19
  38. data/test/gemfiles/Gemfile.rails-4.0.x +7 -1
  39. data/test/gemfiles/Gemfile.rails-4.0.x.lock +57 -71
  40. data/test/gemfiles/Gemfile.rails-4.1.x +5 -0
  41. data/test/gemfiles/Gemfile.rails-4.2.x +5 -0
  42. data/test/gemfiles/Gemfile.rails-5.0.x +4 -0
  43. data/test/helper_test.rb +156 -109
  44. data/test/options_test.rb +21 -0
  45. data/test/parser_test.rb +49 -4
  46. data/test/results/eval_suppressed.xhtml +4 -4
  47. data/test/results/helpers.xhtml +43 -41
  48. data/test/results/helpful.xhtml +6 -3
  49. data/test/results/just_stuff.xhtml +21 -20
  50. data/test/results/list.xhtml +9 -9
  51. data/test/results/nuke_inner_whitespace.xhtml +22 -22
  52. data/test/results/nuke_outer_whitespace.xhtml +84 -92
  53. data/test/results/original_engine.xhtml +17 -17
  54. data/test/results/partial_layout.xhtml +4 -3
  55. data/test/results/partial_layout_erb.xhtml +4 -3
  56. data/test/results/partials.xhtml +11 -10
  57. data/test/results/silent_script.xhtml +63 -63
  58. data/test/results/standard.xhtml +156 -159
  59. data/test/results/tag_parsing.xhtml +19 -19
  60. data/test/results/very_basic.xhtml +2 -2
  61. data/test/results/whitespace_handling.xhtml +77 -76
  62. data/test/template_test.rb +21 -48
  63. data/test/template_test_helper.rb +38 -0
  64. data/test/templates/just_stuff.haml +1 -0
  65. data/test/templates/standard_ugly.haml +1 -0
  66. data/test/temple_line_counter_test.rb +40 -0
  67. data/test/test_helper.rb +10 -10
  68. data/test/util_test.rb +1 -48
  69. metadata +49 -35
  70. data/lib/haml/temple.rb +0 -85
  71. data/test/gemfiles/Gemfile.rails-3.2.x +0 -4
  72. data/test/templates/_av_partial_1_ugly.haml +0 -9
  73. data/test/templates/_av_partial_2_ugly.haml +0 -5
  74. data/test/templates/action_view_ugly.haml +0 -47
  75. data/test/templates/standard_ugly.haml +0 -43
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class FiltersTest < MiniTest::Unit::TestCase
3
+ class FiltersTest < Haml::TestCase
4
4
  test "should be registered as filters when including Haml::Filters::Base" do
5
5
  begin
6
6
  refute Haml::Filters.defined.has_key? "bar"
@@ -26,8 +26,11 @@ class FiltersTest < MiniTest::Unit::TestCase
26
26
  test "should raise error when a Tilt filters dependencies are unavailable for extension" do
27
27
  begin
28
28
  assert_raises Haml::Error do
29
- Haml::Filters.register_tilt_filter "Textile"
30
- Haml::Filters.defined["textile"].template_class
29
+ # ignore warnings from Tilt
30
+ silence_warnings do
31
+ Haml::Filters.register_tilt_filter "Textile"
32
+ Haml::Filters.defined["textile"].template_class
33
+ end
31
34
  end
32
35
  ensure
33
36
  Haml::Filters.remove_filter "Textile"
@@ -64,7 +67,7 @@ class FiltersTest < MiniTest::Unit::TestCase
64
67
  end
65
68
 
66
69
  test "should respect escaped newlines and interpolation" do
67
- html = "\\n\n"
70
+ html = "\\n\n\n"
68
71
  haml = ":plain\n \\n\#{""}"
69
72
  assert_equal(html, render(haml))
70
73
  end
@@ -73,16 +76,21 @@ class FiltersTest < MiniTest::Unit::TestCase
73
76
  assert_equal("\n", render(':plain'))
74
77
  end
75
78
 
76
- test "should be compatible with ugly mode" do
79
+ test ":plain with content" do
77
80
  expectation = "foo\n"
78
- assert_equal(expectation, render(":plain\n foo", :ugly => true))
81
+ assert_equal(expectation, render(":plain\n foo"))
79
82
  end
80
83
 
81
84
  test "should pass options to Tilt filters that precompile" do
82
- haml = ":erb\n <%= 'foo' %>"
83
- refute_match('TEST_VAR', Haml::Engine.new(haml).compiler.precompiled)
84
- Haml::Filters::Erb.options = {:outvar => 'TEST_VAR'}
85
- assert_match('TEST_VAR', Haml::Engine.new(haml).compiler.precompiled)
85
+ begin
86
+ orig_erb_opts = Haml::Filters::Erb.options
87
+ haml = ":erb\n <%= 'foo' %>"
88
+ refute_match('test_var', Haml::Engine.new(haml).compiler.precompiled)
89
+ Haml::Filters::Erb.options = {:outvar => 'test_var'}
90
+ assert_match('test_var', Haml::Engine.new(haml).compiler.precompiled)
91
+ ensure
92
+ Haml::Filters::Erb.options = orig_erb_opts
93
+ end
86
94
  end
87
95
 
88
96
  test "should pass options to Tilt filters that don't precompile" do
@@ -109,9 +117,14 @@ class FiltersTest < MiniTest::Unit::TestCase
109
117
  end
110
118
  end
111
119
 
120
+ test "interpolated code should be escaped if escape_html is set" do
121
+ assert_equal "&lt;script&gt;evil&lt;/script&gt;\n\n",
122
+ render(":plain\n \#{'<script>evil</script>'}", :escape_html => true)
123
+ end
124
+
112
125
  end
113
126
 
114
- class ErbFilterTest < MiniTest::Unit::TestCase
127
+ class ErbFilterTest < Haml::TestCase
115
128
  test "multiline expressions should work" do
116
129
  html = "foobarbaz\n"
117
130
  haml = %Q{:erb\n <%= "foo" +\n "bar" +\n "baz" %>}
@@ -132,7 +145,7 @@ class ErbFilterTest < MiniTest::Unit::TestCase
132
145
 
133
146
  end
134
147
 
135
- class JavascriptFilterTest < MiniTest::Unit::TestCase
148
+ class JavascriptFilterTest < Haml::TestCase
136
149
  test "should interpolate" do
137
150
  scope = Object.new.instance_eval {foo = "bar"; nil if foo; binding}
138
151
  haml = ":javascript\n \#{foo}"
@@ -140,8 +153,8 @@ class JavascriptFilterTest < MiniTest::Unit::TestCase
140
153
  assert_match(/bar/, html)
141
154
  end
142
155
 
143
- test "should never HTML-escape ampersands" do
144
- html = "<script>\n & < > &\n</script>\n"
156
+ test "should never HTML-escape non-interpolated ampersands" do
157
+ html = "<script>\n & < > &amp;\n</script>\n"
145
158
  haml = %Q{:javascript\n & < > \#{"&"}}
146
159
  assert_equal(html, render(haml, :escape_html => true))
147
160
  end
@@ -178,7 +191,7 @@ class JavascriptFilterTest < MiniTest::Unit::TestCase
178
191
  end
179
192
  end
180
193
 
181
- class CSSFilterTest < MiniTest::Unit::TestCase
194
+ class CSSFilterTest < Haml::TestCase
182
195
  test "should wrap output in CDATA and a CSS tag when output is XHTML" do
183
196
  html = "<style type='text/css'>\n /*<![CDATA[*/\n foo\n /*]]>*/\n</style>\n"
184
197
  haml = ":css\n foo"
@@ -217,7 +230,7 @@ class CSSFilterTest < MiniTest::Unit::TestCase
217
230
  end
218
231
  end
219
232
 
220
- class CDATAFilterTest < MiniTest::Unit::TestCase
233
+ class CDATAFilterTest < Haml::TestCase
221
234
  test "should wrap output in CDATA tag" do
222
235
  html = "<![CDATA[\n foo\n]]>\n"
223
236
  haml = ":cdata\n foo"
@@ -225,7 +238,7 @@ class CDATAFilterTest < MiniTest::Unit::TestCase
225
238
  end
226
239
  end
227
240
 
228
- class EscapedFilterTest < MiniTest::Unit::TestCase
241
+ class EscapedFilterTest < Haml::TestCase
229
242
  test "should escape ampersands" do
230
243
  html = "&amp;\n"
231
244
  haml = ":escaped\n &"
@@ -233,7 +246,7 @@ class EscapedFilterTest < MiniTest::Unit::TestCase
233
246
  end
234
247
  end
235
248
 
236
- class RubyFilterTest < MiniTest::Unit::TestCase
249
+ class RubyFilterTest < Haml::TestCase
237
250
  test "can write to haml_io" do
238
251
  haml = ":ruby\n haml_io.puts 'hello'\n"
239
252
  html = "hello\n"
@@ -251,4 +264,4 @@ class RubyFilterTest < MiniTest::Unit::TestCase
251
264
  html = "7\n"
252
265
  assert_equal(html, render(haml))
253
266
  end
254
- end
267
+ end
@@ -1,5 +1,11 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'coveralls', require: false
3
+ if ENV['TRAVIS']
4
+ platform :mri_21 do
5
+ gem 'coveralls', require: false
6
+ end
7
+ end
8
+
4
9
  gem 'rails', '~> 4.0.0'
10
+ gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7'
5
11
  gemspec :path => '../..'
@@ -1,101 +1,87 @@
1
1
  PATH
2
- remote: ../../..
2
+ remote: ../..
3
3
  specs:
4
- rails (4.0.0.beta1)
5
- actionmailer (= 4.0.0.beta1)
6
- actionpack (= 4.0.0.beta1)
7
- activerecord (= 4.0.0.beta1)
8
- activesupport (= 4.0.0.beta1)
9
- bundler (>= 1.3.0, < 2.0)
10
- railties (= 4.0.0.beta1)
11
- sprockets-rails (~> 2.0.0.rc4)
12
-
13
- PATH
14
- remote: /Users/norman/work/haml
15
- specs:
16
- haml (4.0.3)
4
+ haml (4.0.7)
17
5
  tilt
18
6
 
19
7
  GEM
20
8
  remote: http://rubygems.org/
21
9
  specs:
22
- actionmailer (4.0.0.beta1)
23
- actionpack (= 4.0.0.beta1)
24
- mail (~> 2.5.3)
25
- actionpack (4.0.0.beta1)
26
- activesupport (= 4.0.0.beta1)
10
+ actionmailer (4.0.13)
11
+ actionpack (= 4.0.13)
12
+ mail (~> 2.5, >= 2.5.4)
13
+ actionpack (4.0.13)
14
+ activesupport (= 4.0.13)
27
15
  builder (~> 3.1.0)
28
16
  erubis (~> 2.7.0)
29
17
  rack (~> 1.5.2)
30
18
  rack-test (~> 0.6.2)
31
- activemodel (4.0.0.beta1)
32
- activesupport (= 4.0.0.beta1)
19
+ activemodel (4.0.13)
20
+ activesupport (= 4.0.13)
33
21
  builder (~> 3.1.0)
34
- activerecord (4.0.0.beta1)
35
- activemodel (= 4.0.0.beta1)
36
- activerecord-deprecated_finders (~> 0.0.3)
37
- activesupport (= 4.0.0.beta1)
38
- arel (~> 4.0.0.beta1)
39
- activerecord-deprecated_finders (0.0.3)
40
- activesupport (4.0.0.beta1)
41
- i18n (~> 0.6.2)
22
+ activerecord (4.0.13)
23
+ activemodel (= 4.0.13)
24
+ activerecord-deprecated_finders (~> 1.0.2)
25
+ activesupport (= 4.0.13)
26
+ arel (~> 4.0.0)
27
+ activerecord-deprecated_finders (1.0.4)
28
+ activesupport (4.0.13)
29
+ i18n (~> 0.6, >= 0.6.9)
42
30
  minitest (~> 4.2)
43
31
  multi_json (~> 1.3)
44
32
  thread_safe (~> 0.1)
45
- tzinfo (~> 0.3.33)
46
- arel (4.0.0)
47
- atomic (1.1.9)
33
+ tzinfo (~> 0.3.37)
34
+ arel (4.0.2)
48
35
  builder (3.1.4)
36
+ concurrent-ruby (1.0.2)
49
37
  erubis (2.7.0)
50
- hike (1.2.2)
51
- i18n (0.6.4)
52
- json (1.8.0)
53
- mail (2.5.4)
54
- mime-types (~> 1.16)
55
- treetop (~> 1.4.8)
56
- mime-types (1.23)
57
- minitest (4.7.4)
58
- multi_json (1.7.3)
59
- nokogiri (1.5.9)
60
- polyglot (0.3.3)
61
- rack (1.5.2)
62
- rack-test (0.6.2)
38
+ i18n (0.7.0)
39
+ mail (2.6.4)
40
+ mime-types (>= 1.16, < 4)
41
+ mime-types (2.99.2)
42
+ minitest (4.7.5)
43
+ multi_json (1.12.1)
44
+ nokogiri (1.5.11)
45
+ rack (1.5.5)
46
+ rack-test (0.6.3)
63
47
  rack (>= 1.0)
64
- railties (4.0.0.beta1)
65
- actionpack (= 4.0.0.beta1)
66
- activesupport (= 4.0.0.beta1)
48
+ rails (4.0.13)
49
+ actionmailer (= 4.0.13)
50
+ actionpack (= 4.0.13)
51
+ activerecord (= 4.0.13)
52
+ activesupport (= 4.0.13)
53
+ bundler (>= 1.3.0, < 2.0)
54
+ railties (= 4.0.13)
55
+ sprockets-rails (~> 2.0)
56
+ railties (4.0.13)
57
+ actionpack (= 4.0.13)
58
+ activesupport (= 4.0.13)
67
59
  rake (>= 0.8.7)
68
- rdoc (~> 3.4)
69
- thor (>= 0.17.0, < 2.0)
70
- rake (10.0.4)
60
+ thor (>= 0.18.1, < 2.0)
61
+ rake (11.2.2)
71
62
  rbench (0.2.3)
72
- rdoc (3.12.2)
73
- json (~> 1.4)
74
- sprockets (2.9.3)
75
- hike (~> 1.2)
76
- multi_json (~> 1.0)
77
- rack (~> 1.0)
78
- tilt (~> 1.1, != 1.3.0)
79
- sprockets-rails (2.0.0.rc4)
63
+ sprockets (3.7.0)
64
+ concurrent-ruby (~> 1.0)
65
+ rack (> 1, < 3)
66
+ sprockets-rails (2.3.3)
80
67
  actionpack (>= 3.0)
81
68
  activesupport (>= 3.0)
82
- sprockets (~> 2.8)
83
- thor (0.18.1)
84
- thread_safe (0.1.0)
85
- atomic
86
- tilt (1.4.1)
87
- treetop (1.4.12)
88
- polyglot
89
- polyglot (>= 0.3.1)
90
- tzinfo (0.3.37)
69
+ sprockets (>= 2.8, < 4.0)
70
+ thor (0.19.1)
71
+ thread_safe (0.3.5)
72
+ tilt (2.0.5)
73
+ tzinfo (0.3.51)
91
74
 
92
75
  PLATFORMS
93
76
  ruby
94
77
 
95
78
  DEPENDENCIES
96
- bundler (~> 1.3.0)
97
79
  haml!
80
+ mime-types (< 3)
98
81
  minitest
99
- nokogiri
100
- rails (~> 4.0.0.beta1)!
82
+ nokogiri (~> 1.5.10)
83
+ rails (~> 4.0.0)
101
84
  rbench
85
+
86
+ BUNDLED WITH
87
+ 1.12.5
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'rails', '~> 4.1.0'
4
+ gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7'
5
+ gemspec :path => '../..'
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'rails', '~> 4.2.0'
4
+ gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7'
5
+ gemspec :path => '../..'
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'rails', '~> 5.0.0'
4
+ gemspec :path => '../..'
@@ -1,32 +1,13 @@
1
1
  require 'test_helper'
2
+ require "active_model/naming"
2
3
 
3
- class ActionView::Base
4
- def nested_tag
5
- content_tag(:span) {content_tag(:div) {"something"}}
6
- end
7
-
8
- def wacky_form
9
- form_tag("/foo") {"bar"}
10
- end
4
+ class FormModel
5
+ extend ActiveModel::Naming
11
6
  end
12
7
 
13
- module Haml::Helpers
14
- def something_that_uses_haml_concat
15
- haml_concat('foo').to_s
16
- end
17
-
18
- def render_something_with_haml_concat
19
- haml_concat "<p>"
20
- end
21
-
22
- def render_something_with_haml_tag_and_concat
23
- haml_tag 'p' do
24
- haml_concat '<foo>'
25
- end
26
- end
27
- end
8
+ class HelperTest < Haml::TestCase
9
+ TEXT_AREA_CONTENT_REGEX = /<(textarea)[^>]*>\n(.*?)<\/\1>/im
28
10
 
29
- class HelperTest < MiniTest::Unit::TestCase
30
11
  Post = Struct.new('Post', :body, :error_field, :errors)
31
12
  class PostErrors
32
13
  def on(name)
@@ -41,10 +22,18 @@ class HelperTest < MiniTest::Unit::TestCase
41
22
  end
42
23
 
43
24
  def setup
44
- @base = ActionView::Base.new
25
+ @base = Class.new(ActionView::Base) {
26
+ def nested_tag
27
+ content_tag(:span) {content_tag(:div) {"something"}}
28
+ end
29
+
30
+ def wacky_form
31
+ form_tag("/foo") {"bar"}
32
+ end
33
+ }.new
45
34
  @base.controller = ActionController::Base.new
46
35
  @base.view_paths << File.expand_path("../templates", __FILE__)
47
- @base.instance_variable_set('@post', Post.new("Foo bar\nbaz", nil, PostErrors.new))
36
+ @base.instance_variable_set(:@post, Post.new("Foo bar\nbaz", nil, PostErrors.new))
48
37
  end
49
38
 
50
39
  def render(text, options = {})
@@ -53,12 +42,29 @@ class HelperTest < MiniTest::Unit::TestCase
53
42
  end
54
43
 
55
44
  def test_rendering_with_escapes
45
+ def @base.render_something_with_haml_concat
46
+ haml_concat "<p>"
47
+ end
48
+ def @base.render_something_with_haml_tag_and_concat
49
+ haml_tag 'p' do
50
+ haml_concat '<foo>'
51
+ end
52
+ end
53
+
56
54
  output = render(<<-HAML, :action_view)
57
55
  - render_something_with_haml_concat
58
56
  - render_something_with_haml_tag_and_concat
59
57
  - render_something_with_haml_concat
60
58
  HAML
61
- assert_equal("&lt;p&gt;\n<p>\n <foo>\n</p>\n&lt;p&gt;\n", output)
59
+ assert_equal("&lt;p&gt;\n<p>\n &lt;foo&gt;\n</p>\n&lt;p&gt;\n", output)
60
+ end
61
+
62
+ def test_with_raw_haml_concat
63
+ haml = <<HAML
64
+ - with_raw_haml_concat do
65
+ - haml_concat "<>&"
66
+ HAML
67
+ assert_equal("<>&\n", render(haml, :action_view))
62
68
  end
63
69
 
64
70
  def test_flatten
@@ -73,13 +79,13 @@ HAML
73
79
  end
74
80
 
75
81
  def test_list_of_should_render_correctly
76
- assert_equal("<li>1</li>\n<li>2</li>\n", render("= list_of([1, 2]) do |i|\n = i"))
77
- assert_equal("<li>[1]</li>\n", render("= list_of([[1]]) do |i|\n = i.inspect"))
78
- assert_equal("<li>\n <h1>Fee</h1>\n <p>A word!</p>\n</li>\n<li>\n <h1>Fi</h1>\n <p>A word!</p>\n</li>\n<li>\n <h1>Fo</h1>\n <p>A word!</p>\n</li>\n<li>\n <h1>Fum</h1>\n <p>A word!</p>\n</li>\n",
82
+ assert_equal("<li>1</li>\n<li>2</li>", render("= list_of([1, 2]) do |i|\n = i"))
83
+ assert_equal("<li>[1]</li>", render("= list_of([[1]]) do |i|\n = i.inspect"))
84
+ assert_equal("<li>\n <h1>Fee</h1>\n <p>A word!</p>\n</li>\n<li>\n <h1>Fi</h1>\n <p>A word!</p>\n</li>\n<li>\n <h1>Fo</h1>\n <p>A word!</p>\n</li>\n<li>\n <h1>Fum</h1>\n <p>A word!</p>\n</li>",
79
85
  render("= list_of(['Fee', 'Fi', 'Fo', 'Fum']) do |title|\n %h1= title\n %p A word!"))
80
- assert_equal("<li c='3'>1</li>\n<li c='3'>2</li>\n", render("= list_of([1, 2], {:c => 3}) do |i|\n = i"))
81
- assert_equal("<li c='3'>[1]</li>\n", render("= list_of([[1]], {:c => 3}) do |i|\n = i.inspect"))
82
- assert_equal("<li c='3'>\n <h1>Fee</h1>\n <p>A word!</p>\n</li>\n<li c='3'>\n <h1>Fi</h1>\n <p>A word!</p>\n</li>\n<li c='3'>\n <h1>Fo</h1>\n <p>A word!</p>\n</li>\n<li c='3'>\n <h1>Fum</h1>\n <p>A word!</p>\n</li>\n",
86
+ assert_equal("<li c='3'>1</li>\n<li c='3'>2</li>", render("= list_of([1, 2], {:c => 3}) do |i|\n = i"))
87
+ assert_equal("<li c='3'>[1]</li>", render("= list_of([[1]], {:c => 3}) do |i|\n = i.inspect"))
88
+ assert_equal("<li c='3'>\n <h1>Fee</h1>\n <p>A word!</p>\n</li>\n<li c='3'>\n <h1>Fi</h1>\n <p>A word!</p>\n</li>\n<li c='3'>\n <h1>Fo</h1>\n <p>A word!</p>\n</li>\n<li c='3'>\n <h1>Fum</h1>\n <p>A word!</p>\n</li>",
83
89
  render("= list_of(['Fee', 'Fi', 'Fo', 'Fum'], {:c => 3}) do |title|\n %h1= title\n %p A word!"))
84
90
  end
85
91
 
@@ -89,15 +95,15 @@ HAML
89
95
  end
90
96
 
91
97
  def test_tabs
92
- assert_equal("foo\n bar\nbaz\n", render("foo\n- tab_up\nbar\n- tab_down\nbaz"))
93
- assert_equal(" <p>tabbed</p>\n", render("- buffer.tabulation=5\n%p tabbed"))
98
+ assert_equal("foo\nbar\nbaz\n", render("foo\n- tab_up\nbar\n- tab_down\nbaz"))
99
+ assert_equal("<p>tabbed</p>\n", render("- buffer.tabulation=5\n%p tabbed"))
94
100
  end
95
101
 
96
102
  def test_with_tabs
97
103
  assert_equal(<<HTML, render(<<HAML))
98
104
  Foo
99
- Bar
100
- Baz
105
+ Bar
106
+ Baz
101
107
  Baz
102
108
  HTML
103
109
  Foo
@@ -132,18 +138,26 @@ HAML
132
138
  end
133
139
 
134
140
  def test_form_tag
135
- # This is usually provided by ActionController::Base.
136
141
  def @base.protect_against_forgery?; false; end
137
- assert_equal(<<HTML, render(<<HAML, :action_view))
138
- <form accept-charset="UTF-8" action="foo" method="post">#{rails_form_opener}
139
- <p>bar</p>
140
- <strong>baz</strong>
141
- </form>
142
- HTML
142
+ rendered = render(<<HAML, :action_view)
143
143
  = form_tag 'foo' do
144
- %p bar
145
- %strong baz
144
+ %p bar
145
+ %strong baz
146
+ HAML
147
+ fragment = Nokogiri::HTML.fragment(rendered)
148
+ assert_equal 'foo', fragment.css('form').first.attributes['action'].to_s
149
+ assert_equal 'bar', fragment.css('form p').first.text.strip
150
+ assert_equal 'baz', fragment.css('form strong').first.text.strip
151
+ end
152
+
153
+ def test_form_for
154
+ # FIXME: current HAML doesn't do proper indentation with form_for (it's the capture { output } in #form_for).
155
+ def @base.protect_against_forgery?; false; end
156
+ rendered = render(<<HAML, :action_view)
157
+ = form_for OpenStruct.new, url: 'foo', as: :post do |f|
158
+ = f.text_field :name
146
159
  HAML
160
+ assert_match(/<(form|div)[^>]+><input/, rendered)
147
161
  end
148
162
 
149
163
  def test_pre
@@ -151,56 +165,40 @@ HAML
151
165
  render('= content_tag "pre", "Foo bar\n baz"', :action_view))
152
166
  end
153
167
 
154
- # Rails >= 3.2.3 adds a newline after opening textarea tags.
155
- def self.rails_text_area_helpers_emit_a_newline?
156
- major, minor, tiny = ActionPack::VERSION::MAJOR, ActionPack::VERSION::MINOR, ActionPack::VERSION::TINY
157
- major == 4 || ((major == 3) && (minor >= 2) && (tiny >= 3))
158
- end
159
-
160
- def text_area_content_regex
161
- @text_area_content_regex ||= if self.class.rails_text_area_helpers_emit_a_newline?
162
- /<(textarea)[^>]*>\n(.*?)<\/\1>/im
163
- else
164
- /<(textarea)[^>]*>(.*?)<\/\1>/im
165
- end
166
- end
167
-
168
168
  def test_text_area_tag
169
169
  output = render('= text_area_tag "body", "Foo\nBar\n Baz\n Boom"', :action_view)
170
- match_data = output.match(text_area_content_regex)
170
+ match_data = output.match(TEXT_AREA_CONTENT_REGEX)
171
171
  assert_equal "Foo&#x000A;Bar&#x000A; Baz&#x000A; Boom", match_data[2]
172
172
  end
173
173
 
174
174
  def test_text_area
175
175
  output = render('= text_area :post, :body', :action_view)
176
- match_data = output.match(text_area_content_regex)
176
+ match_data = output.match(TEXT_AREA_CONTENT_REGEX)
177
177
  assert_equal "Foo bar&#x000A;baz", match_data[2]
178
178
  end
179
179
 
180
180
  def test_partials_should_not_cause_textareas_to_be_indented
181
181
  # non-indentation of textareas rendered inside partials
182
- @base.instance_variable_set('@post', Post.new("Foo", nil, PostErrors.new))
182
+ @base.instance_variable_set(:@post, Post.new("Foo", nil, PostErrors.new))
183
183
  output = render(".foo\n .bar\n = render '/text_area_helper'", :action_view)
184
- match_data = output.match(text_area_content_regex)
184
+ match_data = output.match(TEXT_AREA_CONTENT_REGEX)
185
185
  assert_equal 'Foo', match_data[2]
186
186
  end
187
187
 
188
- if rails_text_area_helpers_emit_a_newline?
189
- def test_textareas_should_prerve_leading_whitespace
190
- # leading whitespace preservation
191
- @base.instance_variable_set('@post', Post.new(" Foo", nil, PostErrors.new))
192
- output = render(".foo\n = text_area :post, :body", :action_view)
193
- match_data = output.match(text_area_content_regex)
194
- assert_equal '&#x0020; Foo', match_data[2]
195
- end
188
+ def test_textareas_should_preserve_leading_whitespace
189
+ # leading whitespace preservation
190
+ @base.instance_variable_set(:@post, Post.new(" Foo", nil, PostErrors.new))
191
+ output = render(".foo\n = text_area :post, :body", :action_view)
192
+ match_data = output.match(TEXT_AREA_CONTENT_REGEX)
193
+ assert_equal '&#x0020; Foo', match_data[2]
194
+ end
196
195
 
197
- def test_textareas_should_prerve_leading_whitespace_in_partials
198
- # leading whitespace in textareas rendered inside partials
199
- @base.instance_variable_set('@post', Post.new(" Foo", nil, PostErrors.new))
200
- output = render(".foo\n .bar\n = render '/text_area_helper'", :action_view)
201
- match_data = output.match(text_area_content_regex)
202
- assert_equal '&#x0020; Foo', match_data[2]
203
- end
196
+ def test_textareas_should_preserve_leading_whitespace_in_partials
197
+ # leading whitespace in textareas rendered inside partials
198
+ @base.instance_variable_set(:@post, Post.new(" Foo", nil, PostErrors.new))
199
+ output = render(".foo\n .bar\n = render '/text_area_helper'", :action_view)
200
+ match_data = output.match(TEXT_AREA_CONTENT_REGEX)
201
+ assert_equal '&#x0020; Foo', match_data[2]
204
202
  end
205
203
 
206
204
  def test_capture_haml
@@ -238,11 +236,10 @@ HAML
238
236
 
239
237
  def test_form_tag_in_helper_with_string_block
240
238
  def @base.protect_against_forgery?; false; end
241
- assert_equal(<<HTML, render(<<HAML, :action_view))
242
- <form accept-charset="UTF-8" action="/foo" method="post">#{rails_form_opener}bar</form>
243
- HTML
244
- = wacky_form
245
- HAML
239
+ rendered = render('= wacky_form', :action_view)
240
+ fragment = Nokogiri::HTML.fragment(rendered)
241
+ assert_equal 'bar', fragment.text.strip
242
+ assert_equal '/foo', fragment.css('form').first.attributes['action'].to_s
246
243
  end
247
244
 
248
245
  def test_haml_tag_name_attribute_with_id
@@ -361,12 +358,19 @@ HTML
361
358
  HAML
362
359
  end
363
360
 
361
+ def test_haml_concat_inside_haml_tag_escaped_with_xss
362
+ assert_equal("<p>\n &lt;&gt;&amp;\n</p>\n", render(<<HAML, :action_view))
363
+ - haml_tag :p do
364
+ - haml_concat "<>&"
365
+ HAML
366
+ end
367
+
364
368
  def test_haml_concat_with_multiline_string
365
369
  assert_equal(<<HTML, render(<<HAML))
366
370
  <p>
367
- foo
368
- bar
369
- baz
371
+ foo
372
+ bar
373
+ baz
370
374
  </p>
371
375
  HTML
372
376
  %p
@@ -374,10 +378,10 @@ HTML
374
378
  HAML
375
379
  end
376
380
 
377
- def test_haml_tag_with_ugly
378
- assert_equal(<<HTML, render(<<HAML, :ugly => true))
381
+ def test_haml_tag
382
+ assert_equal(<<HTML, render(<<HAML))
379
383
  <p>
380
- <strong>Hi!</strong>
384
+ <strong>Hi!</strong>
381
385
  </p>
382
386
  HTML
383
387
  - haml_tag :p do
@@ -388,7 +392,7 @@ HAML
388
392
  def test_haml_tag_if_positive
389
393
  assert_equal(<<HTML, render(<<HAML))
390
394
  <div class='conditional'>
391
- <p>A para</p>
395
+ <p>A para</p>
392
396
  </div>
393
397
  HTML
394
398
  - haml_tag_if true, '.conditional' do
@@ -399,7 +403,7 @@ HAML
399
403
  def test_haml_tag_if_positive_with_attributes
400
404
  assert_equal(<<HTML, render(<<HAML))
401
405
  <div class='conditional' foo='bar'>
402
- <p>A para</p>
406
+ <p>A para</p>
403
407
  </div>
404
408
  HTML
405
409
  - haml_tag_if true, '.conditional', {:foo => 'bar'} do
@@ -441,15 +445,14 @@ HAML
441
445
  end
442
446
 
443
447
  def test_capture_deals_properly_with_collections
444
- Haml::Helpers.module_eval do
445
- def trc(collection, &block)
446
- collection.each do |record|
447
- haml_concat capture_haml(record, &block)
448
- end
448
+ obj = Object.new
449
+ def obj.trc(collection, &block)
450
+ collection.each do |record|
451
+ haml_concat capture_haml(record, &block)
449
452
  end
450
453
  end
451
454
 
452
- assert_equal("1\n\n2\n\n3\n\n", render("- trc([1, 2, 3]) do |i|\n = i.inspect"))
455
+ assert_equal("1\n\n2\n\n3\n\n", render("- trc([1, 2, 3]) do |i|\n = i.inspect", scope: obj))
453
456
  end
454
457
 
455
458
  def test_capture_with_string_block
@@ -457,17 +460,57 @@ HAML
457
460
  end
458
461
 
459
462
  def test_capture_with_non_string_value_reurns_nil
460
- Haml::Helpers.module_eval do
461
- def check_capture_returns_nil(&block)
462
- contents = capture(&block)
463
+ def @base.check_capture_returns_nil(&block)
464
+ contents = capture(&block)
463
465
 
464
- contents << "ERROR" if contents
465
- end
466
+ contents << "ERROR" if contents
466
467
  end
467
468
 
468
469
  assert_equal("\n", render("= check_capture_returns_nil { 2 }", :action_view))
469
470
  end
470
471
 
472
+
473
+ class HomemadeViewContext
474
+ include ActionView::Context
475
+ include ActionView::Helpers::FormHelper
476
+
477
+ def initialize
478
+ _prepare_context
479
+ end
480
+
481
+ def url_for(*)
482
+ "/"
483
+ end
484
+
485
+ def dom_class(*)
486
+ end
487
+
488
+ def dom_id(*)
489
+ end
490
+
491
+ def m # I have to inject the model into the view using an instance method, using locals doesn't work.
492
+ FormModel.new
493
+ end
494
+
495
+ def protect_against_forgery?
496
+ end
497
+
498
+ # def capture(*args, &block)
499
+ # capture_haml(*args, &block)
500
+ # end
501
+ end
502
+
503
+ def test_form_for_with_homemade_view_context
504
+ handler = ActionView::Template.handler_for_extension("haml")
505
+ template = ActionView::Template.new(<<HAML, "inline template", handler, {})
506
+ = form_for(m, :url => "/") do
507
+ %b Bold!
508
+ HAML
509
+
510
+ # see if Bold is within form tags:
511
+ assert_match(/<form.*>.*<b>Bold!<\/b>.*<\/form>/m, template.render(HomemadeViewContext.new, {}))
512
+ end
513
+
471
514
  def test_find_and_preserve_with_block
472
515
  assert_equal("<pre>Foo&#x000A;Bar</pre>\nFoo\nBar\n",
473
516
  render("= find_and_preserve do\n %pre\n Foo\n Bar\n Foo\n Bar"))
@@ -479,7 +522,7 @@ HAML
479
522
  end
480
523
 
481
524
  def test_preserve_with_block
482
- assert_equal("<pre>Foo&#x000A;Bar</pre>&#x000A;Foo&#x000A;Bar\n",
525
+ assert_equal("<pre>Foo&#x000A;Bar</pre>&#x000A;Foo&#x000A;Bar",
483
526
  render("= preserve do\n %pre\n Foo\n Bar\n Foo\n Bar"))
484
527
  end
485
528
 
@@ -516,17 +559,22 @@ MESSAGE
516
559
  end
517
560
 
518
561
  def test_error_return_line
519
- render("%p foo\n= haml_concat 'foo'\n%p bar")
562
+ render("%p foo\n= haml_concat('foo').to_s\n%p bar")
520
563
  assert false, "Expected Haml::Error"
521
564
  rescue Haml::Error => e
522
- assert_equal 2, e.backtrace[1].scan(/:(\d+)/).first.first.to_i
565
+ assert_equal 2, e.backtrace[0].scan(/:(\d+)/).first.first.to_i
523
566
  end
524
567
 
525
568
  def test_error_return_line_in_helper
526
- render("- something_that_uses_haml_concat")
569
+ obj = Object.new
570
+ def obj.something_that_uses_haml_concat
571
+ haml_concat('foo').to_s
572
+ end
573
+
574
+ render("- something_that_uses_haml_concat", scope: obj)
527
575
  assert false, "Expected Haml::Error"
528
576
  rescue Haml::Error => e
529
- assert_equal 15, e.backtrace[0].scan(/:(\d+)/).first.first.to_i
577
+ assert_equal __LINE__ - 6, e.backtrace[0].scan(/:(\d+)/).first.first.to_i
530
578
  end
531
579
 
532
580
  class ActsLikeTag
@@ -645,4 +693,3 @@ HAML
645
693
  end
646
694
 
647
695
  end
648
-