haml 4.0.0 → 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 +7 -0
- data/.yardopts +1 -1
- data/CHANGELOG.md +117 -5
- data/FAQ.md +7 -17
- data/MIT-LICENSE +1 -1
- data/README.md +85 -42
- data/REFERENCE.md +181 -86
- data/Rakefile +47 -51
- 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 +38 -128
- data/lib/haml/compiler.rb +88 -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 +20 -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 +44 -66
- 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 +16 -4
- data/lib/haml/helpers/xss_mods.rb +18 -12
- data/lib/haml/helpers.rb +122 -58
- data/lib/haml/options.rb +39 -46
- data/lib/haml/parser.rb +278 -217
- data/lib/haml/{template/plugin.rb → plugin.rb} +8 -15
- data/lib/haml/railtie.rb +21 -11
- 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 +2 -1
- data/test/attribute_parser_test.rb +101 -0
- data/test/engine_test.rb +306 -176
- data/test/filters_test.rb +32 -19
- data/test/gemfiles/Gemfile.rails-4.0.x +11 -0
- 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 +282 -96
- 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 +56 -50
- data/test/template_test.rb +44 -53
- data/test/template_test_helper.rb +38 -0
- data/test/templates/_text_area_helper.html.haml +4 -0
- data/test/templates/bemit.haml +3 -0
- data/test/templates/just_stuff.haml +1 -0
- data/test/templates/partial_layout_erb.erb +1 -1
- 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 -12
- data/test/util_test.rb +6 -47
- metadata +88 -106
- data/lib/haml/helpers/rails_323_textarea_fix.rb +0 -24
- 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/gemfiles/Gemfile.rails-master +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/template_test.rb
CHANGED
@@ -2,48 +2,13 @@ require 'test_helper'
|
|
2
2
|
require 'mocks/article'
|
3
3
|
|
4
4
|
require 'action_pack/version'
|
5
|
+
require 'template_test_helper'
|
5
6
|
|
6
|
-
|
7
|
-
include Haml::Filters::Base
|
8
|
-
|
9
|
-
def render(text)
|
10
|
-
"TESTING HAHAHAHA!"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
module Haml::Helpers
|
15
|
-
def test_partial(name, locals = {})
|
16
|
-
Haml::Engine.new(File.read(File.join(TemplateTest::TEMPLATE_PATH, "_#{name}.haml"))).render(self, locals)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class Egocentic
|
21
|
-
def method_missing(*args)
|
22
|
-
self
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class DummyController
|
27
|
-
attr_accessor :logger
|
28
|
-
def initialize
|
29
|
-
@logger = Egocentic.new
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.controller_path
|
33
|
-
''
|
34
|
-
end
|
35
|
-
|
36
|
-
def controller_path
|
37
|
-
''
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
class TemplateTest < MiniTest::Unit::TestCase
|
42
|
-
TEMPLATE_PATH = File.join(File.dirname(__FILE__), "templates")
|
7
|
+
class TemplateTest < Haml::TestCase
|
43
8
|
TEMPLATES = %w{ very_basic standard helpers
|
44
9
|
whitespace_handling original_engine list helpful
|
45
10
|
silent_script tag_parsing just_stuff partials
|
46
|
-
nuke_outer_whitespace nuke_inner_whitespace
|
11
|
+
nuke_outer_whitespace nuke_inner_whitespace bemit
|
47
12
|
render_layout partial_layout partial_layout_erb}
|
48
13
|
|
49
14
|
def setup
|
@@ -56,10 +21,10 @@ class TemplateTest < MiniTest::Unit::TestCase
|
|
56
21
|
def create_base
|
57
22
|
vars = { 'article' => Article.new, 'foo' => 'value one' }
|
58
23
|
|
59
|
-
base = ActionView::Base.new(TEMPLATE_PATH, vars)
|
24
|
+
base = ActionView::Base.new(TemplateTestHelper::TEMPLATE_PATH, vars)
|
60
25
|
|
61
26
|
# This is needed by RJS in (at least) Rails 3
|
62
|
-
base.instance_variable_set(
|
27
|
+
base.instance_variable_set(:@template, base)
|
63
28
|
|
64
29
|
# This is used by form_for.
|
65
30
|
# It's usually provided by ActionController::Base.
|
@@ -83,12 +48,7 @@ class TemplateTest < MiniTest::Unit::TestCase
|
|
83
48
|
def assert_renders_correctly(name, &render_method)
|
84
49
|
old_options = Haml::Template.options.dup
|
85
50
|
Haml::Template.options[:escape_html] = false
|
86
|
-
|
87
|
-
(ActionPack::VERSION::MAJOR == 2 && ActionPack::VERSION::MINOR < 2)
|
88
|
-
render_method ||= proc { |n| @base.render(n) }
|
89
|
-
else
|
90
|
-
render_method ||= proc { |n| @base.render(:file => n) }
|
91
|
-
end
|
51
|
+
render_method ||= proc { |n| @base.render(:file => n) }
|
92
52
|
|
93
53
|
silence_warnings do
|
94
54
|
load_result(name).split("\n").zip(render_method[name].split("\n")).each_with_index do |pair, line|
|
@@ -96,7 +56,7 @@ class TemplateTest < MiniTest::Unit::TestCase
|
|
96
56
|
assert_equal(pair.first, pair.last, message)
|
97
57
|
end
|
98
58
|
end
|
99
|
-
rescue
|
59
|
+
rescue ActionView::Template::Error => e
|
100
60
|
if e.message =~ /Can't run [\w:]+ filter; required (one of|file) ((?:'\w+'(?: or )?)+)(, but none were found| not found)/
|
101
61
|
puts "\nCouldn't require #{$2}; skipping a test."
|
102
62
|
else
|
@@ -111,28 +71,51 @@ class TemplateTest < MiniTest::Unit::TestCase
|
|
111
71
|
end
|
112
72
|
|
113
73
|
TEMPLATES.each do |template|
|
114
|
-
define_method "test_template_should_render_correctly [template: #{template}]
|
74
|
+
define_method "test_template_should_render_correctly [template: #{template}]" do
|
115
75
|
assert_renders_correctly template
|
116
76
|
end
|
117
77
|
end
|
118
78
|
|
79
|
+
def test_render_method_returning_null
|
80
|
+
@base.instance_eval do
|
81
|
+
def empty
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
def render_something(&block)
|
85
|
+
capture(self, &block)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
content_to_render = "%h1 This is part of the broken view.\n= render_something do |thing|\n = thing.empty do\n = 'test'"
|
90
|
+
result = render(content_to_render)
|
91
|
+
expected_result = "<h1>This is part of the broken view.</h1>\n"
|
92
|
+
assert_equal(expected_result, result)
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_simple_rendering
|
96
|
+
content_to_render = "%p test\n= capture { 'foo' }"
|
97
|
+
result = render(content_to_render)
|
98
|
+
expected_result = "<p>test</p>\nfoo\n"
|
99
|
+
assert_equal(expected_result, result)
|
100
|
+
end
|
101
|
+
|
119
102
|
def test_templates_should_render_correctly_with_render_proc
|
120
103
|
assert_renders_correctly("standard") do |name|
|
121
|
-
engine = Haml::Engine.new(File.read(File.dirname(__FILE__) + "/templates/#{name}.haml"), :
|
104
|
+
engine = Haml::Engine.new(File.read(File.dirname(__FILE__) + "/templates/#{name}.haml"), format: :xhtml)
|
122
105
|
engine.render_proc(@base).call
|
123
106
|
end
|
124
107
|
end
|
125
108
|
|
126
109
|
def test_templates_should_render_correctly_with_def_method
|
127
110
|
assert_renders_correctly("standard") do |name|
|
128
|
-
engine = Haml::Engine.new(File.read(File.dirname(__FILE__) + "/templates/#{name}.haml"), :
|
111
|
+
engine = Haml::Engine.new(File.read(File.dirname(__FILE__) + "/templates/#{name}.haml"), format: :xhtml)
|
129
112
|
engine.def_method(@base, "render_standard")
|
130
113
|
@base.render_standard
|
131
114
|
end
|
132
115
|
end
|
133
116
|
|
134
117
|
def test_instance_variables_should_work_inside_templates
|
135
|
-
@base.instance_variable_set(
|
118
|
+
@base.instance_variable_set(:@content_for_layout, 'something')
|
136
119
|
assert_equal("<p>something</p>", render("%p= @content_for_layout").chomp)
|
137
120
|
|
138
121
|
@base.instance_eval("@author = 'Hampton Catlin'")
|
@@ -164,8 +147,8 @@ class TemplateTest < MiniTest::Unit::TestCase
|
|
164
147
|
Haml::Template.options = old_options
|
165
148
|
end
|
166
149
|
|
167
|
-
def
|
168
|
-
assert_equal(<<HTML, render(<<HAML
|
150
|
+
def test_with_output_buffer
|
151
|
+
assert_equal(<<HTML, render(<<HAML))
|
169
152
|
<p>
|
170
153
|
foo
|
171
154
|
baz
|
@@ -328,4 +311,12 @@ HTML
|
|
328
311
|
Test
|
329
312
|
HAML
|
330
313
|
end
|
314
|
+
|
315
|
+
class ::TosUnsafeObject; def to_s; '<hr>'; end; end
|
316
|
+
class ::TosSafeObject; def to_s; '<hr>'.html_safe; end; end
|
317
|
+
|
318
|
+
def test_object_that_returns_safe_buffer
|
319
|
+
assert_equal("<hr>\n", render('= ::TosSafeObject.new', escape_html: true))
|
320
|
+
assert_equal("<hr>\n", render('= ::TosUnsafeObject.new', escape_html: true))
|
321
|
+
end
|
331
322
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module TemplateTestHelper
|
2
|
+
TEMPLATE_PATH = File.join(__dir__, "templates")
|
3
|
+
end
|
4
|
+
|
5
|
+
module Haml::Filters::Test
|
6
|
+
include Haml::Filters::Base
|
7
|
+
|
8
|
+
def render(text)
|
9
|
+
"TESTING HAHAHAHA!"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Haml::Helpers
|
14
|
+
def test_partial(name, locals = {})
|
15
|
+
Haml::Engine.new(File.read(File.join(TemplateTestHelper::TEMPLATE_PATH, "_#{name}.haml")), Haml::Template.options).render(self, locals)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Egocentic
|
20
|
+
def method_missing(*args)
|
21
|
+
self
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class DummyController
|
26
|
+
attr_accessor :logger
|
27
|
+
def initialize
|
28
|
+
@logger = Egocentic.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.controller_path
|
32
|
+
''
|
33
|
+
end
|
34
|
+
|
35
|
+
def controller_path
|
36
|
+
''
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
test/templates/standard.haml
|
@@ -0,0 +1 @@
|
|
1
|
+
BOMG
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TempleLineCounterTest < Haml::TestCase
|
4
|
+
TESTED_TEMPLES = [
|
5
|
+
[:multi,
|
6
|
+
[:code, "foo"],
|
7
|
+
[:static, "bar"],
|
8
|
+
[:dynamic, "baz"],
|
9
|
+
],
|
10
|
+
[:multi,
|
11
|
+
[:code, "foo\nbar\nbaz"],
|
12
|
+
[:static, "foo\nbar\nbaz"],
|
13
|
+
[:dynamic, "foo\nbar\nbaz"],
|
14
|
+
],
|
15
|
+
[:case,
|
16
|
+
["'a\nb', false", [:static, "hello\n"]],
|
17
|
+
[:else, [:code, "raise 'error\n'"]],
|
18
|
+
],
|
19
|
+
[:escape, true, [:dynamic, "foo\nbar"]],
|
20
|
+
[:escape, :once, [:dynamic, "foo\nbar"]],
|
21
|
+
[:escape, false, [:dynamic, "foo\nbar"]],
|
22
|
+
[:escape, true, [:static, "foo\nbar"]],
|
23
|
+
[:escape, :once, [:static, "foo\nbar"]],
|
24
|
+
[:escape, false, [:dynamic, "foo\nbar"]],
|
25
|
+
]
|
26
|
+
|
27
|
+
def test_count_lines
|
28
|
+
TESTED_TEMPLES.each do |temple|
|
29
|
+
code = Haml::TempleEngine.chain.inject(temple) do |exp, (symbol, filter)|
|
30
|
+
case symbol
|
31
|
+
when :Parser, :Compiler
|
32
|
+
exp
|
33
|
+
else
|
34
|
+
filter.call(Haml::TempleEngine).call(exp)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
assert_equal code.count("\n"), Haml::TempleLineCounter.count_lines(temple)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,19 +1,32 @@
|
|
1
|
+
begin
|
2
|
+
if ENV['TRAVIS'] && RUBY_VERSION == '2.1.2' && !defined?(Rubinius)
|
3
|
+
require 'coveralls'
|
4
|
+
Coveralls.wear!
|
5
|
+
end
|
6
|
+
rescue LoadError
|
7
|
+
# ignore error for other test Gemfiles
|
8
|
+
end
|
9
|
+
|
1
10
|
if ENV["COVERAGE"]
|
2
11
|
require "simplecov"
|
3
12
|
SimpleCov.start
|
4
13
|
end
|
5
14
|
|
6
|
-
require 'rubygems'
|
7
|
-
gem "minitest"
|
8
15
|
require 'bundler/setup'
|
9
16
|
require 'minitest/autorun'
|
10
17
|
require 'action_pack'
|
11
18
|
require 'action_controller'
|
12
19
|
require 'action_view'
|
20
|
+
require 'action_view/base'
|
13
21
|
require 'nokogiri'
|
14
|
-
|
15
22
|
require 'rails'
|
23
|
+
|
24
|
+
if defined?(I18n.enforce_available_locales)
|
25
|
+
I18n.enforce_available_locales = true
|
26
|
+
end
|
27
|
+
|
16
28
|
class TestApp < Rails::Application
|
29
|
+
config.eager_load = false
|
17
30
|
config.root = ""
|
18
31
|
end
|
19
32
|
Rails.application = TestApp
|
@@ -27,17 +40,23 @@ $VERBOSE = true
|
|
27
40
|
require 'haml'
|
28
41
|
require 'haml/template'
|
29
42
|
|
30
|
-
|
43
|
+
TestApp.initialize!
|
44
|
+
|
31
45
|
Haml::Template.options[:format] = :xhtml
|
32
46
|
|
47
|
+
BASE_TEST_CLASS = if defined?(Minitest::Test)
|
48
|
+
Minitest::Test
|
49
|
+
else
|
50
|
+
MiniTest::Unit::TestCase
|
51
|
+
end
|
52
|
+
|
33
53
|
module Declarative
|
34
54
|
def test(name, &block)
|
35
|
-
define_method("
|
55
|
+
define_method("test_ #{name}", &block)
|
36
56
|
end
|
37
57
|
end
|
38
58
|
|
39
|
-
class
|
40
|
-
|
59
|
+
class Haml::TestCase < BASE_TEST_CLASS
|
41
60
|
extend Declarative
|
42
61
|
|
43
62
|
def render(text, options = {}, base = nil, &block)
|
@@ -65,10 +84,6 @@ class MiniTest::Unit::TestCase
|
|
65
84
|
Haml::Util.silence_warnings(&block)
|
66
85
|
end
|
67
86
|
|
68
|
-
def rails_form_opener
|
69
|
-
'<div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div>'
|
70
|
-
end
|
71
|
-
|
72
87
|
def assert_raises_message(klass, message)
|
73
88
|
yield
|
74
89
|
rescue Exception => e
|
@@ -81,5 +96,4 @@ class MiniTest::Unit::TestCase
|
|
81
96
|
def self.error(*args)
|
82
97
|
Haml::Error.message(*args)
|
83
98
|
end
|
84
|
-
|
85
99
|
end
|
data/test/util_test.rb
CHANGED
@@ -1,21 +1,8 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class UtilTest <
|
3
|
+
class UtilTest < Haml::TestCase
|
4
4
|
include Haml::Util
|
5
5
|
|
6
|
-
def test_powerset
|
7
|
-
return unless Set[Set[]] == Set[Set[]] # There's a bug in Ruby 1.8.6 that breaks nested set equality
|
8
|
-
assert_equal([[].to_set].to_set,
|
9
|
-
powerset([]))
|
10
|
-
assert_equal([[].to_set, [1].to_set].to_set,
|
11
|
-
powerset([1]))
|
12
|
-
assert_equal([[].to_set, [1].to_set, [2].to_set, [1, 2].to_set].to_set,
|
13
|
-
powerset([1, 2]))
|
14
|
-
assert_equal([[].to_set, [1].to_set, [2].to_set, [3].to_set,
|
15
|
-
[1, 2].to_set, [2, 3].to_set, [1, 3].to_set, [1, 2, 3].to_set].to_set,
|
16
|
-
powerset([1, 2, 3]))
|
17
|
-
end
|
18
|
-
|
19
6
|
def test_silence_warnings
|
20
7
|
old_stderr, $stderr = $stderr, StringIO.new
|
21
8
|
warn "Out"
|
@@ -26,38 +13,10 @@ class UtilTest < MiniTest::Unit::TestCase
|
|
26
13
|
$stderr = old_stderr
|
27
14
|
end
|
28
15
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
assert_equal(
|
34
|
-
assert_equal(["/tmp/foo.rb", -12, "fizzle"], caller_info("/tmp/foo.rb:-12: in `fizzle'"))
|
35
|
-
assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle {}'"))
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_def_static_method
|
39
|
-
klass = Class.new
|
40
|
-
def_static_method(klass, :static_method, [:arg1, :arg2],
|
41
|
-
:sarg1, :sarg2, <<RUBY)
|
42
|
-
s = "Always " + arg1
|
43
|
-
s << " <% if sarg1 %>and<% else %>but never<% end %> " << arg2
|
44
|
-
|
45
|
-
<% if sarg2 %>
|
46
|
-
s << "."
|
47
|
-
<% end %>
|
48
|
-
RUBY
|
49
|
-
c = klass.new
|
50
|
-
assert_equal("Always brush your teeth and comb your hair.",
|
51
|
-
c.send(static_method_name(:static_method, true, true),
|
52
|
-
"brush your teeth", "comb your hair"))
|
53
|
-
assert_equal("Always brush your teeth and comb your hair",
|
54
|
-
c.send(static_method_name(:static_method, true, false),
|
55
|
-
"brush your teeth", "comb your hair"))
|
56
|
-
assert_equal("Always brush your teeth but never play with fire.",
|
57
|
-
c.send(static_method_name(:static_method, false, true),
|
58
|
-
"brush your teeth", "play with fire"))
|
59
|
-
assert_equal("Always brush your teeth but never play with fire",
|
60
|
-
c.send(static_method_name(:static_method, false, false),
|
61
|
-
"brush your teeth", "play with fire"))
|
16
|
+
def test_check_encoding_does_not_destoy_the_given_string
|
17
|
+
string_with_bom = File.read(File.dirname(__FILE__) + '/templates/with_bom.haml', :encoding => Encoding::UTF_8)
|
18
|
+
original = string_with_bom.dup
|
19
|
+
check_encoding(string_with_bom)
|
20
|
+
assert_equal(original, string_with_bom)
|
62
21
|
end
|
63
22
|
end
|