haml 4.0.7 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/CHANGELOG.md +42 -4
- data/FAQ.md +4 -14
- data/MIT-LICENSE +1 -1
- data/README.md +85 -42
- data/REFERENCE.md +108 -57
- data/Rakefile +46 -54
- data/lib/haml/attribute_builder.rb +163 -0
- data/lib/haml/attribute_compiler.rb +215 -0
- data/lib/haml/attribute_parser.rb +144 -0
- data/lib/haml/buffer.rb +22 -132
- data/lib/haml/compiler.rb +87 -295
- data/lib/haml/engine.rb +25 -41
- data/lib/haml/error.rb +3 -0
- data/lib/haml/escapable.rb +49 -0
- data/lib/haml/exec.rb +33 -19
- data/lib/haml/filters.rb +18 -24
- data/lib/haml/generator.rb +41 -0
- data/lib/haml/helpers/action_view_extensions.rb +3 -2
- data/lib/haml/helpers/action_view_mods.rb +36 -58
- data/lib/haml/helpers/action_view_xss_mods.rb +1 -0
- data/lib/haml/helpers/safe_erubi_template.rb +27 -0
- data/lib/haml/helpers/safe_erubis_template.rb +4 -1
- data/lib/haml/helpers/xss_mods.rb +18 -12
- data/lib/haml/helpers.rb +133 -90
- data/lib/haml/options.rb +38 -47
- data/lib/haml/parser.rb +278 -216
- data/lib/haml/{template/plugin.rb → plugin.rb} +8 -15
- data/lib/haml/railtie.rb +21 -12
- data/lib/haml/sass_rails_filter.rb +17 -4
- data/lib/haml/template/options.rb +12 -2
- data/lib/haml/template.rb +12 -6
- data/lib/haml/temple_engine.rb +120 -0
- data/lib/haml/temple_line_counter.rb +29 -0
- data/lib/haml/util.rb +80 -199
- data/lib/haml/version.rb +2 -1
- data/lib/haml.rb +1 -0
- data/test/attribute_parser_test.rb +101 -0
- data/test/engine_test.rb +287 -176
- data/test/filters_test.rb +32 -19
- data/test/gemfiles/Gemfile.rails-4.0.x +9 -3
- data/test/gemfiles/Gemfile.rails-4.0.x.lock +87 -0
- 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 +224 -112
- data/test/options_test.rb +22 -0
- data/test/parser_test.rb +71 -4
- data/test/results/bemit.xhtml +4 -0
- 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 +24 -56
- data/test/template_test_helper.rb +38 -0
- data/test/templates/bemit.haml +3 -0
- data/test/templates/just_stuff.haml +1 -0
- data/test/templates/standard_ugly.haml +1 -0
- data/test/templates/with_bom.haml +1 -0
- data/test/temple_line_counter_test.rb +40 -0
- data/test/test_helper.rb +26 -8
- data/test/util_test.rb +6 -47
- metadata +53 -43
- data/test/gemfiles/Gemfile.rails-3.0.x +0 -5
- data/test/gemfiles/Gemfile.rails-3.1.x +0 -6
- data/test/gemfiles/Gemfile.rails-3.2.x +0 -5
- data/test/haml-spec/LICENSE +0 -14
- data/test/haml-spec/README.md +0 -106
- data/test/haml-spec/lua_haml_spec.lua +0 -38
- data/test/haml-spec/perl_haml_test.pl +0 -81
- data/test/haml-spec/ruby_haml_test.rb +0 -23
- data/test/haml-spec/tests.json +0 -660
- 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/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,16 +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
|
-
|
48
|
-
if defined?(ActionController::Response)
|
49
|
-
# This is needed for >=3.0.0
|
50
|
-
@base.controller.response = ActionController::Response.new
|
51
|
-
end
|
52
|
-
|
53
|
-
@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))
|
54
37
|
end
|
55
38
|
|
56
39
|
def render(text, options = {})
|
@@ -59,12 +42,29 @@ class HelperTest < MiniTest::Unit::TestCase
|
|
59
42
|
end
|
60
43
|
|
61
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
|
+
|
62
54
|
output = render(<<-HAML, :action_view)
|
63
55
|
- render_something_with_haml_concat
|
64
56
|
- render_something_with_haml_tag_and_concat
|
65
57
|
- render_something_with_haml_concat
|
66
58
|
HAML
|
67
|
-
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))
|
68
68
|
end
|
69
69
|
|
70
70
|
def test_flatten
|
@@ -79,13 +79,13 @@ HAML
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def test_list_of_should_render_correctly
|
82
|
-
assert_equal("<li>1</li>\n<li>2</li
|
83
|
-
assert_equal("<li>[1]</li
|
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
|
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>",
|
85
85
|
render("= list_of(['Fee', 'Fi', 'Fo', 'Fum']) do |title|\n %h1= title\n %p A word!"))
|
86
|
-
assert_equal("<li c='3'>1</li>\n<li c='3'>2</li
|
87
|
-
assert_equal("<li c='3'>[1]</li
|
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
|
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>",
|
89
89
|
render("= list_of(['Fee', 'Fi', 'Fo', 'Fum'], {:c => 3}) do |title|\n %h1= title\n %p A word!"))
|
90
90
|
end
|
91
91
|
|
@@ -95,15 +95,15 @@ HAML
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def test_tabs
|
98
|
-
assert_equal("foo\
|
99
|
-
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"))
|
100
100
|
end
|
101
101
|
|
102
102
|
def test_with_tabs
|
103
103
|
assert_equal(<<HTML, render(<<HAML))
|
104
104
|
Foo
|
105
|
-
|
106
|
-
|
105
|
+
Bar
|
106
|
+
Baz
|
107
107
|
Baz
|
108
108
|
HTML
|
109
109
|
Foo
|
@@ -120,7 +120,7 @@ HAML
|
|
120
120
|
|
121
121
|
begin
|
122
122
|
ActionView::Base.new.render(:inline => "<%= flatten('Foo\\nBar') %>")
|
123
|
-
rescue NoMethodError,
|
123
|
+
rescue NoMethodError, ActionView::Template::Error
|
124
124
|
proper_behavior = true
|
125
125
|
end
|
126
126
|
assert(proper_behavior)
|
@@ -138,18 +138,26 @@ HAML
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def test_form_tag
|
141
|
-
# This is usually provided by ActionController::Base.
|
142
141
|
def @base.protect_against_forgery?; false; end
|
143
|
-
|
144
142
|
rendered = render(<<HAML, :action_view)
|
145
143
|
= form_tag 'foo' do
|
146
|
-
|
147
|
-
|
144
|
+
%p bar
|
145
|
+
%strong baz
|
148
146
|
HAML
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
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
|
159
|
+
HAML
|
160
|
+
assert_match(/<(form|div)[^>]+><input/, rendered)
|
153
161
|
end
|
154
162
|
|
155
163
|
def test_pre
|
@@ -157,56 +165,40 @@ HAML
|
|
157
165
|
render('= content_tag "pre", "Foo bar\n baz"', :action_view))
|
158
166
|
end
|
159
167
|
|
160
|
-
# Rails >= 3.2.3 adds a newline after opening textarea tags.
|
161
|
-
def self.rails_text_area_helpers_emit_a_newline?
|
162
|
-
major, minor, tiny = ActionPack::VERSION::MAJOR, ActionPack::VERSION::MINOR, ActionPack::VERSION::TINY
|
163
|
-
major == 4 || ((major == 3) && (minor >= 2) && (tiny >= 3))
|
164
|
-
end
|
165
|
-
|
166
|
-
def text_area_content_regex
|
167
|
-
@text_area_content_regex ||= if self.class.rails_text_area_helpers_emit_a_newline?
|
168
|
-
/<(textarea)[^>]*>\n(.*?)<\/\1>/im
|
169
|
-
else
|
170
|
-
/<(textarea)[^>]*>(.*?)<\/\1>/im
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
168
|
def test_text_area_tag
|
175
169
|
output = render('= text_area_tag "body", "Foo\nBar\n Baz\n Boom"', :action_view)
|
176
|
-
match_data = output.match(
|
170
|
+
match_data = output.match(TEXT_AREA_CONTENT_REGEX)
|
177
171
|
assert_equal "Foo
Bar
 Baz
 Boom", match_data[2]
|
178
172
|
end
|
179
173
|
|
180
174
|
def test_text_area
|
181
175
|
output = render('= text_area :post, :body', :action_view)
|
182
|
-
match_data = output.match(
|
176
|
+
match_data = output.match(TEXT_AREA_CONTENT_REGEX)
|
183
177
|
assert_equal "Foo bar
baz", match_data[2]
|
184
178
|
end
|
185
179
|
|
186
180
|
def test_partials_should_not_cause_textareas_to_be_indented
|
187
181
|
# non-indentation of textareas rendered inside partials
|
188
|
-
@base.instance_variable_set(
|
182
|
+
@base.instance_variable_set(:@post, Post.new("Foo", nil, PostErrors.new))
|
189
183
|
output = render(".foo\n .bar\n = render '/text_area_helper'", :action_view)
|
190
|
-
match_data = output.match(
|
184
|
+
match_data = output.match(TEXT_AREA_CONTENT_REGEX)
|
191
185
|
assert_equal 'Foo', match_data[2]
|
192
186
|
end
|
193
187
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
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
|
202
195
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
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]
|
210
202
|
end
|
211
203
|
|
212
204
|
def test_capture_haml
|
@@ -306,8 +298,12 @@ HAML
|
|
306
298
|
assert_equal("<p id='foo&bar'>baz</p>\n", render("%p{:id => 'foo&bar'} baz", :escape_html => true))
|
307
299
|
end
|
308
300
|
|
309
|
-
def
|
310
|
-
assert_equal("<br class='foo' />\n", render("- haml_tag :br, :class => 'foo'"))
|
301
|
+
def test_haml_tag_autoclosed_tags_are_closed_xhtml
|
302
|
+
assert_equal("<br class='foo' />\n", render("- haml_tag :br, :class => 'foo'", :format => :xhtml))
|
303
|
+
end
|
304
|
+
|
305
|
+
def test_haml_tag_autoclosed_tags_are_closed_html
|
306
|
+
assert_equal("<br class='foo'>\n", render("- haml_tag :br, :class => 'foo'", :format => :html5))
|
311
307
|
end
|
312
308
|
|
313
309
|
def test_haml_tag_with_class_array
|
@@ -338,7 +334,8 @@ HAML
|
|
338
334
|
end
|
339
335
|
|
340
336
|
def test_haml_tag_flags
|
341
|
-
assert_equal("<p />\n", render("- haml_tag :p, :/"))
|
337
|
+
assert_equal("<p />\n", render("- haml_tag :p, :/", :format => :xhtml))
|
338
|
+
assert_equal("<p>\n", render("- haml_tag :p, :/", :format => :html5))
|
342
339
|
assert_equal("<p>kumquat</p>\n", render("- haml_tag :p, :< do\n kumquat"))
|
343
340
|
|
344
341
|
assert_raises(Haml::Error) { render("- haml_tag :p, 'foo', :/") }
|
@@ -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
|
@@ -385,6 +389,41 @@ HTML
|
|
385
389
|
HAML
|
386
390
|
end
|
387
391
|
|
392
|
+
def test_haml_tag_if_positive
|
393
|
+
assert_equal(<<HTML, render(<<HAML))
|
394
|
+
<div class='conditional'>
|
395
|
+
<p>A para</p>
|
396
|
+
</div>
|
397
|
+
HTML
|
398
|
+
- haml_tag_if true, '.conditional' do
|
399
|
+
%p A para
|
400
|
+
HAML
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_haml_tag_if_positive_with_attributes
|
404
|
+
assert_equal(<<HTML, render(<<HAML))
|
405
|
+
<div class='conditional' foo='bar'>
|
406
|
+
<p>A para</p>
|
407
|
+
</div>
|
408
|
+
HTML
|
409
|
+
- haml_tag_if true, '.conditional', {:foo => 'bar'} do
|
410
|
+
%p A para
|
411
|
+
HAML
|
412
|
+
end
|
413
|
+
|
414
|
+
def test_haml_tag_if_negative
|
415
|
+
assert_equal(<<HTML, render(<<HAML))
|
416
|
+
<p>A para</p>
|
417
|
+
HTML
|
418
|
+
- haml_tag_if false, '.conditional' do
|
419
|
+
%p A para
|
420
|
+
HAML
|
421
|
+
end
|
422
|
+
|
423
|
+
def test_haml_tag_if_error_return
|
424
|
+
assert_raises(Haml::Error) { render("= haml_tag_if false, '.conditional' do\n %p Hello") }
|
425
|
+
end
|
426
|
+
|
388
427
|
def test_is_haml
|
389
428
|
assert(!ActionView::Base.new.is_haml?)
|
390
429
|
assert_equal("true\n", render("= is_haml?"))
|
@@ -406,15 +445,14 @@ HAML
|
|
406
445
|
end
|
407
446
|
|
408
447
|
def test_capture_deals_properly_with_collections
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
end
|
448
|
+
obj = Object.new
|
449
|
+
def obj.trc(collection, &block)
|
450
|
+
collection.each do |record|
|
451
|
+
haml_concat capture_haml(record, &block)
|
414
452
|
end
|
415
453
|
end
|
416
454
|
|
417
|
-
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))
|
418
456
|
end
|
419
457
|
|
420
458
|
def test_capture_with_string_block
|
@@ -422,17 +460,57 @@ HAML
|
|
422
460
|
end
|
423
461
|
|
424
462
|
def test_capture_with_non_string_value_reurns_nil
|
425
|
-
|
426
|
-
|
427
|
-
contents = capture(&block)
|
463
|
+
def @base.check_capture_returns_nil(&block)
|
464
|
+
contents = capture(&block)
|
428
465
|
|
429
|
-
|
430
|
-
end
|
466
|
+
contents << "ERROR" if contents
|
431
467
|
end
|
432
468
|
|
433
469
|
assert_equal("\n", render("= check_capture_returns_nil { 2 }", :action_view))
|
434
470
|
end
|
435
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
|
+
|
436
514
|
def test_find_and_preserve_with_block
|
437
515
|
assert_equal("<pre>Foo
Bar</pre>\nFoo\nBar\n",
|
438
516
|
render("= find_and_preserve do\n %pre\n Foo\n Bar\n Foo\n Bar"))
|
@@ -444,7 +522,7 @@ HAML
|
|
444
522
|
end
|
445
523
|
|
446
524
|
def test_preserve_with_block
|
447
|
-
assert_equal("<pre>Foo
Bar</pre>
Foo
Bar
|
525
|
+
assert_equal("<pre>Foo
Bar</pre>
Foo
Bar",
|
448
526
|
render("= preserve do\n %pre\n Foo\n Bar\n Foo\n Bar"))
|
449
527
|
end
|
450
528
|
|
@@ -481,17 +559,22 @@ MESSAGE
|
|
481
559
|
end
|
482
560
|
|
483
561
|
def test_error_return_line
|
484
|
-
render("%p foo\n= haml_concat
|
562
|
+
render("%p foo\n= haml_concat('foo').to_s\n%p bar")
|
485
563
|
assert false, "Expected Haml::Error"
|
486
564
|
rescue Haml::Error => e
|
487
|
-
assert_equal 2, e.backtrace[
|
565
|
+
assert_equal 2, e.backtrace[0].scan(/:(\d+)/).first.first.to_i
|
488
566
|
end
|
489
567
|
|
490
568
|
def test_error_return_line_in_helper
|
491
|
-
|
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)
|
492
575
|
assert false, "Expected Haml::Error"
|
493
576
|
rescue Haml::Error => e
|
494
|
-
assert_equal
|
577
|
+
assert_equal __LINE__ - 6, e.backtrace[0].scan(/:(\d+)/).first.first.to_i
|
495
578
|
end
|
496
579
|
|
497
580
|
class ActsLikeTag
|
@@ -559,7 +642,7 @@ HAML
|
|
559
642
|
|
560
643
|
def test_escape_once_leaves_numeric_references
|
561
644
|
assert_equal ""><&  ", Haml::Helpers.escape_once('"><&  ') #decimal
|
562
|
-
|
645
|
+
assert_equal ""><&  ", Haml::Helpers.escape_once('"><&  ') #hexadecimal
|
563
646
|
end
|
564
647
|
|
565
648
|
def test_escape_once_encoding
|
@@ -571,6 +654,36 @@ HAML
|
|
571
654
|
$stderr = old_stderr
|
572
655
|
end
|
573
656
|
|
657
|
+
def test_html_attrs_xhtml
|
658
|
+
assert_equal("<html lang='en-US' xml:lang='en-US' xmlns='http://www.w3.org/1999/xhtml'></html>\n",
|
659
|
+
render("%html{html_attrs}", :format => :xhtml))
|
660
|
+
end
|
661
|
+
|
662
|
+
def test_html_attrs_html4
|
663
|
+
assert_equal("<html lang='en-US'></html>\n",
|
664
|
+
render("%html{html_attrs}", :format => :html4))
|
665
|
+
end
|
666
|
+
|
667
|
+
def test_html_attrs_html5
|
668
|
+
assert_equal("<html lang='en-US'></html>\n",
|
669
|
+
render("%html{html_attrs}", :format => :html5))
|
670
|
+
end
|
671
|
+
|
672
|
+
def test_html_attrs_xhtml_other_lang
|
673
|
+
assert_equal("<html lang='es-AR' xml:lang='es-AR' xmlns='http://www.w3.org/1999/xhtml'></html>\n",
|
674
|
+
render("%html{html_attrs('es-AR')}", :format => :xhtml))
|
675
|
+
end
|
676
|
+
|
677
|
+
def test_html_attrs_html4_other_lang
|
678
|
+
assert_equal("<html lang='es-AR'></html>\n",
|
679
|
+
render("%html{html_attrs('es-AR')}", :format => :html4))
|
680
|
+
end
|
681
|
+
|
682
|
+
def test_html_attrs_html5_other_lang
|
683
|
+
assert_equal("<html lang='es-AR'></html>\n",
|
684
|
+
render("%html{html_attrs('es-AR')}", :format => :html5))
|
685
|
+
end
|
686
|
+
|
574
687
|
def test_escape_once_should_work_on_frozen_strings
|
575
688
|
begin
|
576
689
|
Haml::Helpers.escape_once('foo'.freeze)
|
@@ -580,4 +693,3 @@ HAML
|
|
580
693
|
end
|
581
694
|
|
582
695
|
end
|
583
|
-
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Haml
|
4
|
+
class OptionsTest < Haml::TestCase
|
5
|
+
def test_buffer_defaults_have_only_buffer_option_keys
|
6
|
+
assert_equal(
|
7
|
+
Haml::Options.buffer_option_keys.sort,
|
8
|
+
Haml::Options.buffer_defaults.keys.sort,
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_buffer_defaults_values_are_the_same_as_rails_defaults
|
13
|
+
rails_defaults = Haml::Options.defaults.merge(Haml::Template.options)
|
14
|
+
Haml::Options.buffer_option_keys.each do |key|
|
15
|
+
assert_equal(
|
16
|
+
rails_defaults[key],
|
17
|
+
Haml::Options.buffer_defaults[key], "key: #{key}"
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/test/parser_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
module Haml
|
4
|
-
class ParserTest <
|
4
|
+
class ParserTest < Haml::TestCase
|
5
5
|
|
6
6
|
test "should raise error for 'else' at wrong indent level" do
|
7
7
|
begin
|
@@ -94,12 +94,79 @@ module Haml
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
+
test "revealed conditional comments are detected" do
|
98
|
+
text = "some revealed text"
|
99
|
+
cond = "[cond]"
|
100
|
+
|
101
|
+
node = parse("/!#{cond} #{text}").children[0]
|
102
|
+
|
103
|
+
assert_equal text, node.value[:text]
|
104
|
+
assert_equal cond, node.value[:conditional]
|
105
|
+
assert node.value[:revealed]
|
106
|
+
end
|
107
|
+
|
108
|
+
test "hidden conditional comments are detected" do
|
109
|
+
text = "some revealed text"
|
110
|
+
cond = "[cond]"
|
111
|
+
|
112
|
+
node = parse("/#{cond} #{text}").children[0]
|
113
|
+
|
114
|
+
assert_equal text, node.value[:text]
|
115
|
+
assert_equal cond, node.value[:conditional]
|
116
|
+
refute node.value[:revealed]
|
117
|
+
end
|
118
|
+
|
119
|
+
test "only script lines are checked for continuation keywords" do
|
120
|
+
haml = "- if true\n setup\n- else\n else\n"
|
121
|
+
node = parse(haml).children[0]
|
122
|
+
assert_equal(3, node.children.size)
|
123
|
+
end
|
124
|
+
|
125
|
+
# see #830. Strictly speaking the pipe here is not necessary, but there
|
126
|
+
# shouldn't be an error if it is there.
|
127
|
+
test "multiline Ruby with extra trailing pipe doesn't raise error" do
|
128
|
+
haml = "%p= foo bar, |\n baz"
|
129
|
+
begin
|
130
|
+
parse haml
|
131
|
+
rescue Haml::SyntaxError
|
132
|
+
flunk "Should not have raised SyntaxError"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
test "empty filter doesn't hide following lines" do
|
137
|
+
root = parse "%p\n :plain\n %p\n"
|
138
|
+
p_element = root.children[0]
|
139
|
+
assert_equal 2, p_element.children.size
|
140
|
+
assert_equal :filter, p_element.children[0].type
|
141
|
+
assert_equal :tag, p_element.children[1].type
|
142
|
+
end
|
143
|
+
|
144
|
+
# Previously blocks under a haml_comment would be rejected if any line was
|
145
|
+
# indented by a value that wasn't a multiple of the document indentation.
|
146
|
+
test "haml_comment accepts any indentation in content" do
|
147
|
+
begin
|
148
|
+
parse "-\#\n Indented two spaces\n Indented three spaces"
|
149
|
+
rescue Haml::SyntaxError
|
150
|
+
flunk "haml_comment should accept any combination of indentation"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
test "block haml_comment includes text" do
|
155
|
+
root = parse "-#\n Hello\n Hello\n"
|
156
|
+
assert_equal "Hello\n Hello\n", root.children[0].value[:text]
|
157
|
+
end
|
158
|
+
|
159
|
+
test "block haml_comment includes first line if present" do
|
160
|
+
root = parse "-# First line\n Hello\n Hello\n"
|
161
|
+
assert_equal " First line\nHello\n Hello\n", root.children[0].value[:text]
|
162
|
+
end
|
163
|
+
|
97
164
|
private
|
98
165
|
|
99
166
|
def parse(haml, options = nil)
|
100
167
|
options ||= Options.new
|
101
|
-
parser = Parser.new(
|
102
|
-
parser.
|
168
|
+
parser = Parser.new(options)
|
169
|
+
parser.call(haml)
|
103
170
|
end
|
104
171
|
end
|
105
|
-
end
|
172
|
+
end
|