haml 1.0.0
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.
- data/MIT-LICENSE +20 -0
- data/REFERENCE +662 -0
- data/Rakefile +167 -0
- data/VERSION +1 -0
- data/bin/haml +18 -0
- data/lib/haml/buffer.rb +224 -0
- data/lib/haml/engine.rb +551 -0
- data/lib/haml/helpers.rb +220 -0
- data/lib/haml/helpers/action_view_mods.rb +53 -0
- data/lib/haml/template.rb +138 -0
- data/test/benchmark.rb +62 -0
- data/test/engine_test.rb +93 -0
- data/test/helper_test.rb +105 -0
- data/test/mocks/article.rb +6 -0
- data/test/profile.rb +45 -0
- data/test/results/content_for_layout.xhtml +16 -0
- data/test/results/eval_suppressed.xhtml +2 -0
- data/test/results/helpers.xhtml +50 -0
- data/test/results/helpful.xhtml +5 -0
- data/test/results/just_stuff.xhtml +36 -0
- data/test/results/list.xhtml +12 -0
- data/test/results/original_engine.xhtml +24 -0
- data/test/results/partials.xhtml +20 -0
- data/test/results/silent_script.xhtml +74 -0
- data/test/results/standard.xhtml +42 -0
- data/test/results/tag_parsing.xhtml +28 -0
- data/test/results/very_basic.xhtml +7 -0
- data/test/results/whitespace_handling.xhtml +51 -0
- data/test/rhtml/standard.rhtml +51 -0
- data/test/runner.rb +15 -0
- data/test/template_test.rb +137 -0
- data/test/templates/_partial.haml +7 -0
- data/test/templates/_text_area.haml +3 -0
- data/test/templates/content_for_layout.haml +10 -0
- data/test/templates/eval_suppressed.haml +5 -0
- data/test/templates/helpers.haml +39 -0
- data/test/templates/helpful.haml +6 -0
- data/test/templates/just_stuff.haml +29 -0
- data/test/templates/list.haml +12 -0
- data/test/templates/original_engine.haml +17 -0
- data/test/templates/partialize.haml +1 -0
- data/test/templates/partials.haml +12 -0
- data/test/templates/silent_script.haml +40 -0
- data/test/templates/standard.haml +40 -0
- data/test/templates/tag_parsing.haml +24 -0
- data/test/templates/very_basic.haml +4 -0
- data/test/templates/whitespace_handling.haml +66 -0
- metadata +108 -0
data/test/engine_test.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require File.dirname(__FILE__) + '/../lib/haml/engine'
|
5
|
+
|
6
|
+
class EngineTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def render(text, options = {})
|
9
|
+
Haml::Engine.new(text, options).to_html
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_empty_render_should_remain_empty
|
13
|
+
assert_equal('', render(''))
|
14
|
+
end
|
15
|
+
|
16
|
+
# This is ugly because Hashes are unordered; we don't always know the order
|
17
|
+
# in which attributes will be returned.
|
18
|
+
# There is probably a better way to do this.
|
19
|
+
def test_attributes_should_render_correctly
|
20
|
+
assert_equal("<div class='atlantis' style='ugly'>\n</div>", render(".atlantis{:style => 'ugly'}").chomp)
|
21
|
+
rescue
|
22
|
+
assert_equal("<div style='ugly' class='atlantis'>\n</div>", render(".atlantis{:style => 'ugly'}").chomp)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_ruby_code_should_work_inside_attributes
|
26
|
+
author = 'hcatlin'
|
27
|
+
assert_equal("<p class='3'>foo</p>", render("%p{:class => 1+2} foo").chomp)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_nil_should_render_empty_tag
|
31
|
+
assert_equal("<div class='no_attributes'>\n</div>",
|
32
|
+
render(".no_attributes{:nil => nil}").chomp)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_strings_should_get_stripped_inside_tags
|
36
|
+
assert_equal("<div class='stripped'>This should have no spaces in front of it</div>",
|
37
|
+
render(".stripped This should have no spaces in front of it").chomp)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_one_liner_should_be_one_line
|
41
|
+
assert_equal("<p>Hello</p>", render('%p Hello').chomp)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_long_liner_should_not_print_on_one_line
|
45
|
+
assert_equal("<div>\n #{'x' * 51}\n</div>", render("%div #{'x' * 51}").chomp)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_multi_render
|
49
|
+
engine = Haml::Engine.new("%strong Hi there!")
|
50
|
+
assert_equal("<strong>Hi there!</strong>\n", engine.to_html)
|
51
|
+
assert_equal("<strong>Hi there!</strong>\n", engine.to_html)
|
52
|
+
assert_equal("<strong>Hi there!</strong>\n", engine.to_html)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Options tests
|
56
|
+
|
57
|
+
def test_stop_eval
|
58
|
+
assert_equal("", render("= 'Hello'", :suppress_eval => true))
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_attr_wrapper
|
62
|
+
assert_equal("<p strange=*attrs*>\n</p>\n", render("%p{ :strange => 'attrs'}", :attr_wrapper => '*'))
|
63
|
+
assert_equal("<p escaped='quo\"te'>\n</p>\n", render("%p{ :escaped => 'quo\"te'}", :attr_wrapper => '"'))
|
64
|
+
assert_equal("<p escaped=\"q'uo"te\">\n</p>\n", render("%p{ :escaped => 'q\\'uo\"te'}", :attr_wrapper => '"'))
|
65
|
+
assert_equal("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n", render("!!! XML", :attr_wrapper => '"'))
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_locals
|
69
|
+
assert_equal("<p>Paragraph!</p>\n", render("%p= text", :locals => { :text => "Paragraph!" }))
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_precompiled
|
73
|
+
precompiled = <<-END
|
74
|
+
def _haml_render
|
75
|
+
_hamlout = @haml_stack[-1]
|
76
|
+
_erbout = _hamlout.buffer
|
77
|
+
|
78
|
+
_hamlout.open_tag("p", 0, nil, true, "", nil, nil, false)
|
79
|
+
@haml_lineno = 1
|
80
|
+
haml_temp = "Haml Rocks Socks"
|
81
|
+
haml_temp = _hamlout.push_script(haml_temp, 1, false)
|
82
|
+
_hamlout.close_tag("p", 0)
|
83
|
+
end
|
84
|
+
END
|
85
|
+
|
86
|
+
assert_equal("<p>Haml Rocks Socks</p>\n", render("%h1 I shall not be rendered", :precompiled => precompiled))
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_comps
|
90
|
+
assert_equal(-1, "foo" <=> nil)
|
91
|
+
assert_equal(1, nil <=> "foo")
|
92
|
+
end
|
93
|
+
end
|
data/test/helper_test.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require File.dirname(__FILE__) + '/../lib/haml/template'
|
5
|
+
|
6
|
+
class HelperTest < Test::Unit::TestCase
|
7
|
+
include Haml::Helpers
|
8
|
+
|
9
|
+
def setup
|
10
|
+
ActionView::Base.register_template_handler("haml", Haml::Template)
|
11
|
+
@base = ActionView::Base.new
|
12
|
+
@base.controller = ActionController::Base.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def render(text, options = {})
|
16
|
+
if options == :action_view
|
17
|
+
@base.render :inline => text, :type => :haml
|
18
|
+
else
|
19
|
+
Haml::Engine.new(text, options).to_html
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_flatten
|
24
|
+
assert_equal(flatten("FooBar"), "FooBar")
|
25
|
+
|
26
|
+
assert_equal(flatten("Foo\rBar"), "FooBar")
|
27
|
+
|
28
|
+
assert_equal(flatten("Foo\nBar"), "Foo
Bar")
|
29
|
+
|
30
|
+
assert_equal(flatten("Hello\nWorld!\nYOU ARE \rFLAT?\n\rOMGZ!"),
|
31
|
+
"Hello
World!
YOU ARE FLAT?
OMGZ!")
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_list_of_should_render_correctly
|
35
|
+
assert_equal("<li>1</li>\n<li>2</li>\n", render("= list_of([1, 2]) do |i|\n = i"))
|
36
|
+
assert_equal("<li>1</li>\n", render("= list_of([[1]]) do |i|\n = i.first"))
|
37
|
+
assert_equal("<li>\n <h1>Fee</h1>\n <p>A word!</p>\n</li>\n<li>\n <h1>Fi</h1>\n <p>A word!</p>\n</li>\n<li>\n <h1>Fo</h1>\n <p>A word!</p>\n</li>\n<li>\n <h1>Fum</h1>\n <p>A word!</p>\n</li>\n",
|
38
|
+
render("= list_of(['Fee', 'Fi', 'Fo', 'Fum']) do |title|\n %h1= title\n %p A word!"))
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_buffer_access
|
42
|
+
assert(render("= buffer") =~ /#<Haml::Buffer:0x[a-z0-9]+>/)
|
43
|
+
assert_equal(render("= (buffer == _hamlout)"), "true\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_tabs
|
47
|
+
assert_equal(render("foo\n- tab_up\nbar\n- tab_down\nbaz"), "foo\n bar\nbaz\n")
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_helpers_dont_leak
|
51
|
+
# Haml helpers shouldn't be accessible from ERB
|
52
|
+
render("foo")
|
53
|
+
proper_behavior = false
|
54
|
+
|
55
|
+
begin
|
56
|
+
ActionView::Base.new.render(:inline => "<%= flatten('Foo\\nBar') %>")
|
57
|
+
rescue NoMethodError
|
58
|
+
proper_behavior = true
|
59
|
+
end
|
60
|
+
assert(proper_behavior)
|
61
|
+
|
62
|
+
begin
|
63
|
+
ActionView::Base.new.render(:inline => "<%= concat('foo') %>")
|
64
|
+
rescue ArgumentError
|
65
|
+
proper_behavior = true
|
66
|
+
end
|
67
|
+
assert(proper_behavior)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_action_view_included
|
71
|
+
assert(Haml::Helpers.action_view?)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_action_view_not_included
|
75
|
+
#This is for 100% rcov, rather than any real testing purposes.
|
76
|
+
Kernel.module_eval do
|
77
|
+
alias_method :old_require, :require
|
78
|
+
def require(string)
|
79
|
+
raise LoadError if string == "action_view"
|
80
|
+
old_require string
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
load File.dirname(__FILE__) + '/../lib/haml/helpers/action_view_mods.rb'
|
85
|
+
|
86
|
+
Kernel.module_eval do
|
87
|
+
alias_method :require, :old_require
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_form_tag
|
92
|
+
# Until the next Rails is released, form_tag with a block can have one of
|
93
|
+
# two behaviors.
|
94
|
+
|
95
|
+
result = render("- form_tag 'foo' do\n %p bar\n %strong baz", :action_view)
|
96
|
+
new_rails = "<form action=\"foo\" method=\"post\">\n <p>foo</p>\n</form>\n"
|
97
|
+
old_rails = ""
|
98
|
+
assert(result == new_rails || result == old_rails)
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_capture_haml
|
102
|
+
assert_equal("\"<p>13</p>\\n\"\n", render("- foo = capture_haml(13) do |a|\n %p= a\n= foo.dump"))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
data/test/profile.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/haml/template'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'active_support'
|
4
|
+
require 'action_view'
|
5
|
+
require 'profiler'
|
6
|
+
require 'stringio'
|
7
|
+
|
8
|
+
module Haml
|
9
|
+
# A profiler for HAML, mostly for development use. This simply implements
|
10
|
+
# the Ruby profiler for profiling HAML code.
|
11
|
+
class Profiler
|
12
|
+
|
13
|
+
# Creates a new profiler that looks for templates in the base
|
14
|
+
# directory.
|
15
|
+
def initialize(base = File.join(File.dirname(__FILE__), 'templates'))
|
16
|
+
ActionView::Base.register_template_handler("haml", Haml::Template)
|
17
|
+
unless base.class == ActionView::Base
|
18
|
+
@base = ActionView::Base.new(base)
|
19
|
+
else
|
20
|
+
@base = base
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Profiles HAML on the given template with the given number of runs.
|
25
|
+
# The template name shouldn't have a file extension; this will
|
26
|
+
# automatically look for a HAML template.
|
27
|
+
#
|
28
|
+
# Returns the results of the profiling as a string.
|
29
|
+
def profile(runs = 100, template_name = 'standard')
|
30
|
+
# Runs the profiler, collects information
|
31
|
+
Profiler__::start_profile
|
32
|
+
runs.times { @base.render template_name }
|
33
|
+
Profiler__::stop_profile
|
34
|
+
|
35
|
+
# Outputs information to a StringIO, returns result
|
36
|
+
io = StringIO.new
|
37
|
+
Profiler__::print_profile(io)
|
38
|
+
io.pos = 0
|
39
|
+
result = io.read
|
40
|
+
io.close
|
41
|
+
return result
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
</head>
|
5
|
+
<body>
|
6
|
+
<div id='content'>
|
7
|
+
Lorem ipsum dolor sit amet
|
8
|
+
</div>
|
9
|
+
<div id='yieldy'>
|
10
|
+
Lorem ipsum dolor sit amet
|
11
|
+
</div>
|
12
|
+
<div id='nosym'>
|
13
|
+
Lorem ipsum dolor sit amet
|
14
|
+
</div>
|
15
|
+
</body>
|
16
|
+
</html>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
&&&&&&&&&&&
|
2
|
+
<div>
|
3
|
+
<p class='title'>Title</p>
|
4
|
+
<p class='text'>
|
5
|
+
Woah this is really crazy
|
6
|
+
I mean wow,
|
7
|
+
man.
|
8
|
+
</p>
|
9
|
+
</div>
|
10
|
+
<div>
|
11
|
+
<p class='title'>Title</p>
|
12
|
+
<p class='text'>
|
13
|
+
Woah this is really crazy
|
14
|
+
I mean wow,
|
15
|
+
man.
|
16
|
+
</p>
|
17
|
+
</div>
|
18
|
+
<div>
|
19
|
+
<p class='title'>Title</p>
|
20
|
+
<p class='text'>
|
21
|
+
Woah this is really crazy
|
22
|
+
I mean wow,
|
23
|
+
man.
|
24
|
+
</p>
|
25
|
+
</div>
|
26
|
+
<p>foo</p>
|
27
|
+
<p>
|
28
|
+
reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally loooooooooooooooooong
|
29
|
+
</p>
|
30
|
+
<div class='woah'>
|
31
|
+
<div id='funky'>
|
32
|
+
<div>
|
33
|
+
<h1>Big!</h1>
|
34
|
+
<p>Small</p>
|
35
|
+
<!-- Invisible -->
|
36
|
+
</div>
|
37
|
+
<div class='dilly'>
|
38
|
+
<p>foo</p>
|
39
|
+
<h1>bar</h1>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
(<strong>parentheses!</strong>)
|
43
|
+
</div>
|
44
|
+
*<span class='small'>Not really</span>
|
45
|
+
click
|
46
|
+
<a href='thing'>here</a>.
|
47
|
+
<p>baz</p>
|
48
|
+
<p>boom</p>
|
49
|
+
foo
|
50
|
+
<li><a href='http://www.google.com'>google</a></li>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<?xml version='1.0' encoding='utf-8' ?>
|
2
|
+
<?xml version='1.0' encoding='iso-8859-1' ?>
|
3
|
+
<?xml version='1.0' encoding='utf-8' ?>
|
4
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
6
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
7
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
8
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
|
9
|
+
<strong apos="Foo's bar!">Boo!</strong>
|
10
|
+
<div class='render'><em>wow!</em></div>
|
11
|
+
<p>
|
12
|
+
Escape
|
13
|
+
- character
|
14
|
+
%p foo
|
15
|
+
yee\ha
|
16
|
+
</p>
|
17
|
+
<!-- Short comment -->
|
18
|
+
<!--
|
19
|
+
This is a really long comment look how long it is it should be on a line of its own don't you think?
|
20
|
+
-->
|
21
|
+
<!--
|
22
|
+
This is a block comment
|
23
|
+
cool, huh?
|
24
|
+
<strong>there can even be sub-tags!</strong>
|
25
|
+
Or script!
|
26
|
+
-->
|
27
|
+
<!--[if lte IE6]> conditional comment! <![endif]-->
|
28
|
+
<!--[if gte IE7]>
|
29
|
+
<p>Block conditional comment</p>
|
30
|
+
<div>
|
31
|
+
<h1>Cool, eh?</h1>
|
32
|
+
</div>
|
33
|
+
<![endif]-->
|
34
|
+
<!--[if gte IE5.2]>
|
35
|
+
Woah a period.
|
36
|
+
<![endif]-->
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Stop. HAML time</title>
|
5
|
+
<div id='content'>
|
6
|
+
<h1>This is a title!</h1>
|
7
|
+
<p>
|
8
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit
|
9
|
+
</p>
|
10
|
+
<p class='foo'>Cigarettes!</p>
|
11
|
+
<h2>Man alive!</h2>
|
12
|
+
<ul class='things'>
|
13
|
+
<li>Slippers</li>
|
14
|
+
<li>Shoes</li>
|
15
|
+
<li>Bathrobe</li>
|
16
|
+
<li>Coffee</li>
|
17
|
+
</ul>
|
18
|
+
<pre>
|
19
|
+
This is some text that's in a pre block!
|
20
|
+
Let's see what happens when it's rendered! What about now, since we're on a new line?
|
21
|
+
</pre>
|
22
|
+
</div>
|
23
|
+
</head>
|
24
|
+
</html>
|
@@ -0,0 +1,74 @@
|
|
1
|
+
<div>
|
2
|
+
<h1>I can count!</h1>
|
3
|
+
1
|
4
|
+
2
|
5
|
+
3
|
6
|
+
4
|
7
|
+
5
|
8
|
+
6
|
9
|
+
7
|
10
|
+
8
|
11
|
+
9
|
12
|
+
10
|
13
|
+
11
|
14
|
+
12
|
15
|
+
13
|
16
|
+
14
|
17
|
+
15
|
18
|
+
16
|
19
|
+
17
|
20
|
+
18
|
21
|
+
19
|
22
|
+
20
|
23
|
+
<h1>I know my ABCs!</h1>
|
24
|
+
<ul>
|
25
|
+
<li>a</li>
|
26
|
+
<li>b</li>
|
27
|
+
<li>c</li>
|
28
|
+
<li>d</li>
|
29
|
+
<li>e</li>
|
30
|
+
<li>f</li>
|
31
|
+
<li>g</li>
|
32
|
+
<li>h</li>
|
33
|
+
<li>i</li>
|
34
|
+
<li>j</li>
|
35
|
+
<li>k</li>
|
36
|
+
<li>l</li>
|
37
|
+
<li>m</li>
|
38
|
+
<li>n</li>
|
39
|
+
<li>o</li>
|
40
|
+
<li>p</li>
|
41
|
+
<li>q</li>
|
42
|
+
<li>r</li>
|
43
|
+
<li>s</li>
|
44
|
+
<li>t</li>
|
45
|
+
<li>u</li>
|
46
|
+
<li>v</li>
|
47
|
+
<li>w</li>
|
48
|
+
<li>x</li>
|
49
|
+
<li>y</li>
|
50
|
+
<li>z</li>
|
51
|
+
</ul>
|
52
|
+
<h1>I can catch errors!</h1>
|
53
|
+
Oh no! "uninitialized constant Foo" happened!
|
54
|
+
<p>
|
55
|
+
"false" is:
|
56
|
+
false
|
57
|
+
</p>
|
58
|
+
Even!
|
59
|
+
Odd!
|
60
|
+
Even!
|
61
|
+
Odd!
|
62
|
+
Even!
|
63
|
+
</div>
|
64
|
+
<div class='foo'>
|
65
|
+
<strong>foobar</strong>
|
66
|
+
</div>
|
67
|
+
<strong>0</strong>
|
68
|
+
<strong>1</strong>
|
69
|
+
<strong>2</strong>
|
70
|
+
<strong>3</strong>
|
71
|
+
<strong>4</strong>
|
72
|
+
<div class='test'>
|
73
|
+
<p>boom</p>
|
74
|
+
</div>
|