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/filters_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class FiltersTest <
|
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
|
-
|
30
|
-
|
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 "
|
79
|
+
test ":plain with content" do
|
77
80
|
expectation = "foo\n"
|
78
|
-
assert_equal(expectation, render(":plain\n foo"
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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 "<script>evil</script>\n\n",
|
122
|
+
render(":plain\n \#{'<script>evil</script>'}", :escape_html => true)
|
123
|
+
end
|
124
|
+
|
112
125
|
end
|
113
126
|
|
114
|
-
class ErbFilterTest <
|
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 <
|
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 & < >
|
156
|
+
test "should never HTML-escape non-interpolated ampersands" do
|
157
|
+
html = "<script>\n & < > &\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 <
|
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 <
|
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 <
|
241
|
+
class EscapedFilterTest < Haml::TestCase
|
229
242
|
test "should escape ampersands" do
|
230
243
|
html = "&\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 <
|
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
|
-
|
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
|
-
|
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.
|
23
|
-
actionpack (= 4.0.
|
24
|
-
mail (~> 2.5.
|
25
|
-
actionpack (4.0.
|
26
|
-
activesupport (= 4.0.
|
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.
|
32
|
-
activesupport (= 4.0.
|
19
|
+
activemodel (4.0.13)
|
20
|
+
activesupport (= 4.0.13)
|
33
21
|
builder (~> 3.1.0)
|
34
|
-
activerecord (4.0.
|
35
|
-
activemodel (= 4.0.
|
36
|
-
activerecord-deprecated_finders (~>
|
37
|
-
activesupport (= 4.0.
|
38
|
-
arel (~> 4.0.0
|
39
|
-
activerecord-deprecated_finders (
|
40
|
-
activesupport (4.0.
|
41
|
-
i18n (~> 0.6.
|
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.
|
46
|
-
arel (4.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
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
65
|
-
|
66
|
-
|
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
|
-
|
69
|
-
|
70
|
-
rake (10.0.4)
|
60
|
+
thor (>= 0.18.1, < 2.0)
|
61
|
+
rake (11.2.2)
|
71
62
|
rbench (0.2.3)
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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 (
|
83
|
-
thor (0.
|
84
|
-
thread_safe (0.
|
85
|
-
|
86
|
-
|
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
|
82
|
+
nokogiri (~> 1.5.10)
|
83
|
+
rails (~> 4.0.0)
|
101
84
|
rbench
|
85
|
+
|
86
|
+
BUNDLED WITH
|
87
|
+
1.12.5
|
data/test/helper_test.rb
CHANGED
@@ -1,32 +1,13 @@
|
|
1
1
|
require 'test_helper'
|
2
|
+
require "active_model/naming"
|
2
3
|
|
3
|
-
class
|
4
|
-
|
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
|
-
|
14
|
-
|
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
|
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(
|
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("<p>\n<p>\n
|
59
|
+
assert_equal("<p>\n<p>\n <foo>\n</p>\n<p>\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
|
77
|
-
assert_equal("<li>[1]</li
|
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
|
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
|
81
|
-
assert_equal("<li c='3'>[1]</li
|
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
|
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\
|
93
|
-
assert_equal("
|
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
|
-
|
100
|
-
|
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
|
-
|
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
|
-
|
145
|
-
|
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(
|
170
|
+
match_data = output.match(TEXT_AREA_CONTENT_REGEX)
|
171
171
|
assert_equal "Foo
Bar
 Baz
 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(
|
176
|
+
match_data = output.match(TEXT_AREA_CONTENT_REGEX)
|
177
177
|
assert_equal "Foo bar
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(
|
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(
|
184
|
+
match_data = output.match(TEXT_AREA_CONTENT_REGEX)
|
185
185
|
assert_equal 'Foo', match_data[2]
|
186
186
|
end
|
187
187
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
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 '  Foo', match_data[2]
|
194
|
+
end
|
196
195
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
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 '  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
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
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 <>&\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
|
-
|
368
|
-
|
369
|
-
|
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
|
378
|
-
assert_equal(<<HTML, render(<<HAML
|
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
|
-
|
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
|
-
|
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
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
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
|
-
|
461
|
-
|
462
|
-
contents = capture(&block)
|
463
|
+
def @base.check_capture_returns_nil(&block)
|
464
|
+
contents = capture(&block)
|
463
465
|
|
464
|
-
|
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
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
Bar</pre>
Foo
Bar
|
525
|
+
assert_equal("<pre>Foo
Bar</pre>
Foo
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
|
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[
|
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
|
-
|
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
|
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
|
-
|