haml 4.0.7 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|