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.

Files changed (48) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/REFERENCE +662 -0
  3. data/Rakefile +167 -0
  4. data/VERSION +1 -0
  5. data/bin/haml +18 -0
  6. data/lib/haml/buffer.rb +224 -0
  7. data/lib/haml/engine.rb +551 -0
  8. data/lib/haml/helpers.rb +220 -0
  9. data/lib/haml/helpers/action_view_mods.rb +53 -0
  10. data/lib/haml/template.rb +138 -0
  11. data/test/benchmark.rb +62 -0
  12. data/test/engine_test.rb +93 -0
  13. data/test/helper_test.rb +105 -0
  14. data/test/mocks/article.rb +6 -0
  15. data/test/profile.rb +45 -0
  16. data/test/results/content_for_layout.xhtml +16 -0
  17. data/test/results/eval_suppressed.xhtml +2 -0
  18. data/test/results/helpers.xhtml +50 -0
  19. data/test/results/helpful.xhtml +5 -0
  20. data/test/results/just_stuff.xhtml +36 -0
  21. data/test/results/list.xhtml +12 -0
  22. data/test/results/original_engine.xhtml +24 -0
  23. data/test/results/partials.xhtml +20 -0
  24. data/test/results/silent_script.xhtml +74 -0
  25. data/test/results/standard.xhtml +42 -0
  26. data/test/results/tag_parsing.xhtml +28 -0
  27. data/test/results/very_basic.xhtml +7 -0
  28. data/test/results/whitespace_handling.xhtml +51 -0
  29. data/test/rhtml/standard.rhtml +51 -0
  30. data/test/runner.rb +15 -0
  31. data/test/template_test.rb +137 -0
  32. data/test/templates/_partial.haml +7 -0
  33. data/test/templates/_text_area.haml +3 -0
  34. data/test/templates/content_for_layout.haml +10 -0
  35. data/test/templates/eval_suppressed.haml +5 -0
  36. data/test/templates/helpers.haml +39 -0
  37. data/test/templates/helpful.haml +6 -0
  38. data/test/templates/just_stuff.haml +29 -0
  39. data/test/templates/list.haml +12 -0
  40. data/test/templates/original_engine.haml +17 -0
  41. data/test/templates/partialize.haml +1 -0
  42. data/test/templates/partials.haml +12 -0
  43. data/test/templates/silent_script.haml +40 -0
  44. data/test/templates/standard.haml +40 -0
  45. data/test/templates/tag_parsing.haml +24 -0
  46. data/test/templates/very_basic.haml +4 -0
  47. data/test/templates/whitespace_handling.haml +66 -0
  48. metadata +108 -0
@@ -0,0 +1,42 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xml-lang='en-US'>
3
+ <head>
4
+ <title>Hampton Catlin Is Totally Awesome</title>
5
+ <meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
6
+ </head>
7
+ <body>
8
+ <!-- You're In my house now! -->
9
+ <div class='header'>
10
+ Yes, ladies and gentileman. He is just that egotistical.
11
+ Fantastic! This should be multi-line output
12
+ The question is if this would translate! Ahah!
13
+ 20
14
+ </div>
15
+ <div id='body'> Quotes should be loved! Just like people!</div>
16
+ Wow.|
17
+ <p>
18
+ Holy cow multiline tags! A pipe (|) even!
19
+ PipesIgnored|PipesIgnored|PipesIgnored|
20
+ 1|2|3
21
+ </p>
22
+ <div class='silent'>
23
+ this shouldn't evaluate but now it should!
24
+ </div>
25
+ <ul class='really cool'>
26
+ <li>a</li>
27
+ <li>b</li>
28
+ <li>c</li>
29
+ <li>d</li>
30
+ <li>e</li>
31
+ <li>f</li>
32
+ </ul>
33
+ <div class='of_divs_with_underscore' id='combo'>with this text</div>
34
+ hello
35
+ <div class='footer'>
36
+ <strong class='shout'>
37
+ This is a really long ruby quote. It should be loved and wrapped because its more than 50 characters. This value may change in the future and this test may look stupid.
38
+ So, I'm just making it *really* long. God, I hope this works
39
+ </strong>
40
+ </div>
41
+ </body>
42
+ </html>
@@ -0,0 +1,28 @@
1
+ <div class='tags'>
2
+ <foo>1</foo>
3
+ <FOO>2</FOO>
4
+ <fooBAR>3</fooBAR>
5
+ <fooBar>4</fooBar>
6
+ <foo_bar>5</foo_bar>
7
+ <foo-bar>6</foo-bar>
8
+ <foo:bar>7</foo:bar>
9
+ <foo class='bar'>8</foo>
10
+ <fooBAr_baz:boom_bar>9</fooBAr_baz:boom_bar>
11
+ <foo13>10</foo13>
12
+ <foo2u>11</foo2u>
13
+ </div>
14
+ <div class='classes'>
15
+ <p class='foo bar' id='boom'>
16
+ </p>
17
+ <div class='fooBar'>a</div>
18
+ <div class='foo-bar'>b</div>
19
+ <div class='foo_bar'>c</div>
20
+ <div class='FOOBAR'>d</div>
21
+ <div class='foo16'>e</div>
22
+ <div class='123'>f</div>
23
+ <div class='foo2u'>g</div>
24
+ </div>
25
+ <div class='broken'>
26
+ <foo><{ :a => :b }</foo>
27
+ <div class='foo'>>{ :c => :d }</div>
28
+ </div>
@@ -0,0 +1,7 @@
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
+ </body>
7
+ </html>
@@ -0,0 +1,51 @@
1
+ <div id='whitespace_test'>
2
+ <div class='text_area_test_area'>
3
+ <textarea>Oneline</textarea>
4
+ </div>
5
+ <textarea>BLAH
6
+ </textarea>
7
+ <div class='text_area_test_area'>
8
+ <textarea>Two&#x000A;lines</textarea>
9
+ </div>
10
+ <textarea>BLAH
11
+ </textarea>
12
+ <div class='text_area_test_area'>
13
+ <textarea>Oneline</textarea>
14
+ </div>
15
+ <textarea>BLAH&#x000A;</textarea>
16
+ <div class='text_area_test_area'>
17
+ <textarea>Two&#x000A;lines</textarea>
18
+ </div>
19
+ <textarea>BLAH&#x000A;</textarea>
20
+ <div id='flattened'>
21
+ <div class='text_area_test_area'>
22
+ <textarea>Two&#x000A;lines</textarea>
23
+ </div>
24
+ <textarea>BLAH&#x000A;</textarea>
25
+ </div>
26
+ </div>
27
+ <div class='hithere'>
28
+ Foo bar
29
+ <pre>foo bar</pre>
30
+ <pre>foo&#x000A;bar</pre>
31
+ <p><pre>foo&#x000A;bar</pre></p>
32
+ <p>
33
+ foo
34
+ bar
35
+ </p>
36
+ <pre>&#x000A; ___&#x000A; ,o88888&#x000A; ,o8888888'&#x000A; ,:o:o:oooo. ,8O88Pd8888"&#x000A; ,.::.::o:ooooOoOoO. ,oO8O8Pd888'"&#x000A; ,.:.::o:ooOoOoOO8O8OOo.8OOPd8O8O"&#x000A; , ..:.::o:ooOoOOOO8OOOOo.FdO8O8"&#x000A; , ..:.::o:ooOoOO8O888O8O,COCOO"&#x000A; , . ..:.::o:ooOoOOOO8OOOOCOCO"&#x000A; . ..:.::o:ooOoOoOO8O8OCCCC"o&#x000A; . ..:.::o:ooooOoCoCCC"o:o&#x000A; . ..:.::o:o:,cooooCo"oo:o:&#x000A; ` . . ..:.:cocoooo"'o:o:::'&#x000A; .` . ..::ccccoc"'o:o:o:::'&#x000A; :.:. ,c:cccc"':.:.:.:.:.'&#x000A; ..:.:"'`::::c:"'..:.:.:.:.:.' http://www.chris.com/ASCII/&#x000A; ...:.'.:.::::"' . . . . .'&#x000A; .. . ....:."' ` . . . ''&#x000A; . . . ...."'&#x000A; .. . ."' -hrr-&#x000A; .&#x000A;&#x000A;&#x000A; It's a planet!&#x000A;%strong This shouldn't be bold!&#x000A;</pre>
37
+ <strong>This should!</strong>
38
+ <textarea>
39
+ ___ ___ ___ ___&#x000A; /\__\ /\ \ /\__\ /\__\&#x000A; /:/ / /::\ \ /::| | /:/ /&#x000A; /:/__/ /:/\:\ \ /:|:| | /:/ /&#x000A; /::\ \ ___ /::\~\:\ \ /:/|:|__|__ /:/ /&#x000A; /:/\:\ /\__\ /:/\:\ \:\__\ /:/ |::::\__\ /:/__/&#x000A; \/__\:\/:/ / \/__\:\/:/ / \/__/~~/:/ / \:\ \&#x000A; \::/ / \::/ / /:/ / \:\ \&#x000A; /:/ / /:/ / /:/ / \:\ \&#x000A; /:/ / /:/ / /:/ / \:\__\&#x000A; \/__/ \/__/ \/__/ \/__/&#x000A; &#x000A; Many&#x000A; thanks&#x000A; to&#x000A; http://www.network-science.de/ascii/&#x000A;
40
+ <strong>indeed!</strong>
41
+ </textarea>
42
+ </div>
43
+ <div class='foo'>
44
+ 13
45
+ <textarea>&#x000A;a&#x000A;</textarea><textarea>&#x000A;b&#x000A;</textarea><textarea>&#x000A;c&#x000A;</textarea>
46
+ </div>
47
+ <pre>
48
+ foo&#x000A;
49
+ bar
50
+ </pre>
51
+
@@ -0,0 +1,51 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xml-lang='en-US'>
3
+ <head>
4
+ <title>Hampton Catlin Is Totally Awesome</title>
5
+ <meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
6
+ </head>
7
+ <body>
8
+ <!-- You're In my house now! -->
9
+ <div class='header'>
10
+ Yes, ladies and gentileman. He is just that egotistical.
11
+ Fantastic! This should be multi-line output
12
+ The question is if this would translate! Ahah!
13
+ <%= 1 + 9 + 8 + 2 %>
14
+ <%# numbers should work and this should be ignored %>
15
+ </div>
16
+ <div id='body'><%= " Quotes should be loved! Just like people!" %></div>
17
+ Wow.
18
+ <p>
19
+ <%= "Holy cow " +
20
+ "multiline " +
21
+ "tags! " +
22
+ "A pipe (|) even!" %>
23
+ <%= [1, 2, 3].collect { |n| "PipesIgnored|" } %>
24
+ <%= [1, 2, 3].collect { |n|
25
+ n.to_s
26
+ }.join("|") %>
27
+ </p>
28
+ <div class='silent'>
29
+ <% foo = String.new
30
+ foo << "this"
31
+ foo << " shouldn't"
32
+ foo << " evaluate" %>
33
+ <%= foo + "but now it should!" %>
34
+ <%# Woah crap a comment! %>
35
+ </div>
36
+ <ul class='really cool'>
37
+ <% ('a'..'f').each do |a|%>
38
+ <li><%= a %>
39
+ <% end %>
40
+ <div class='of_divs_with_underscore' id='combo'><%= @should_eval = "with this text" %></div>
41
+ <%= [ 104, 101, 108, 108, 111 ].map do |byte|
42
+ byte.chr
43
+ end %>
44
+ <div class='footer'>
45
+ <strong class='shout'>
46
+ <%= "This is a really long ruby quote. It should be loved and wrapped because its more than 50 characters. This value may change in the future and this test may look stupid.\n" +
47
+ " So, I'm just making it *really* long. God, I hope this works" %>
48
+ </strong>
49
+ </div>
50
+ </body>
51
+ </html>
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'action_view'
4
+ require '../lib/haml/template'
5
+ require 'fileutils'
6
+
7
+ haml_template_engine = Haml::Template.new(ActionView::Base.new)
8
+ haml_template_engine.render(File.dirname(__FILE__) + '/templates/standard.haml')
9
+
10
+ begin
11
+ eval(File.read("template_test.rb"))
12
+ rescue StandardError => e
13
+ puts e.backtrace
14
+ puts e.inspect
15
+ end
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'rubygems'
5
+ require 'active_support'
6
+ require 'action_view'
7
+
8
+ require File.dirname(__FILE__) + '/../lib/haml/template'
9
+ require File.dirname(__FILE__) + '/mocks/article'
10
+
11
+ class TemplateTest < Test::Unit::TestCase
12
+ @@templates = %w{ very_basic standard helpers
13
+ whitespace_handling original_engine list helpful
14
+ silent_script tag_parsing just_stuff partials }
15
+
16
+ def setup
17
+ ActionView::Base.register_template_handler("haml", Haml::Template)
18
+ @base = ActionView::Base.new(File.dirname(__FILE__) + "/../test/templates/")
19
+ @base.instance_variable_set("@article", Article.new)
20
+ @base.instance_variable_set("@foo", 'value one')
21
+ end
22
+
23
+ def render(text)
24
+ Haml::Engine.new(text).to_html(@base)
25
+ end
26
+
27
+ def load_result(name)
28
+ @result = ''
29
+ File.new(File.dirname(__FILE__) + "/results/#{name}.xhtml").each_line { |l| @result += l }
30
+ @result
31
+ end
32
+
33
+ def assert_renders_correctly(name)
34
+ test = Proc.new do |rendered|
35
+ load_result(name).split("\n").zip(rendered.split("\n")).each_with_index do |pair, line|
36
+ message = "template: #{name}\nline: #{line}"
37
+ assert_equal(pair.first, pair.last, message)
38
+ end
39
+ end
40
+ test.call(@base.render(name))
41
+ test.call(@base.render(:file => "partialize", :locals => { :name => name }))
42
+ end
43
+
44
+ def test_empty_render_should_remain_empty
45
+ assert_equal('', render(''))
46
+ end
47
+
48
+ def test_templates_should_render_correctly
49
+ @@templates.each do |template|
50
+ assert_renders_correctly template
51
+ end
52
+ end
53
+
54
+ def test_action_view_templates_render_correctly
55
+ @base.instance_variable_set("@content_for_layout", 'Lorem ipsum dolor sit amet')
56
+ assert_renders_correctly 'content_for_layout'
57
+ end
58
+
59
+ def test_instance_variables_should_work_inside_templates
60
+ @base.instance_variable_set("@content_for_layout", 'something')
61
+ assert_equal("<p>something</p>", render("%p= @content_for_layout").chomp)
62
+
63
+ @base.instance_eval("@author = 'Hampton Catlin'")
64
+ assert_equal("<div class='author'>Hampton Catlin</div>", render(".author= @author").chomp)
65
+
66
+ @base.instance_eval("@author = 'Hampton'")
67
+ assert_equal("Hampton", render("= @author").chomp)
68
+
69
+ @base.instance_eval("@author = 'Catlin'")
70
+ assert_equal("Catlin", render("= @author").chomp)
71
+ end
72
+
73
+ def test_instance_variables_should_work_inside_attributes
74
+ @base.instance_eval("@author = 'hcatlin'")
75
+ assert_equal("<p class='hcatlin'>foo</p>", render("%p{:class => @author} foo").chomp)
76
+ end
77
+
78
+ def test_template_renders_should_eval
79
+ assert_equal("2\n", render("= 1+1"))
80
+ end
81
+
82
+ def test_rhtml_still_renders
83
+ res = @base.render("../rhtml/standard")
84
+ assert !(res.nil? || res.empty?)
85
+ end
86
+
87
+ def test_haml_options
88
+ Haml::Template.options = { :suppress_eval => true }
89
+ assert_equal({ :suppress_eval => true }, Haml::Template.options)
90
+ assert_renders_correctly("eval_suppressed")
91
+ Haml::Template.options = {}
92
+ end
93
+
94
+ def test_exceptions_should_work_correctly
95
+ template = <<END
96
+ %p
97
+ %h1 Hello!
98
+ = "lots of lines"
99
+ - raise "Oh no!"
100
+ %p
101
+ this is after the exception
102
+ %strong yes it is!
103
+ ho ho ho.
104
+ END
105
+ @base.haml_filename = "(test)"
106
+ begin
107
+ render(template.chomp)
108
+ rescue Exception => e
109
+ assert_equal("(test).haml:4", e.backtrace[0])
110
+ end
111
+
112
+ @base.haml_filename = nil
113
+ begin
114
+ render(template.chomp)
115
+ rescue Exception => e
116
+ assert_equal("(haml):4", e.backtrace[0])
117
+ end
118
+
119
+ template = <<END
120
+ %p
121
+ %h1 Hello!
122
+ = "lots of lines"
123
+ = "even more!"
124
+ - compile_error(
125
+ %p
126
+ this is after the exception
127
+ %strong yes it is!
128
+ ho ho ho.
129
+ END
130
+
131
+ begin
132
+ render(template.chomp)
133
+ rescue Exception => e
134
+ assert_equal("(haml):5", e.backtrace[0])
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,7 @@
1
+ %p
2
+ @foo =
3
+ = @foo
4
+ - @foo = 'value three'
5
+ %p
6
+ @foo =
7
+ = @foo
@@ -0,0 +1,3 @@
1
+ .text_area_test_area
2
+ ~ "<textarea>" + value + "</textarea>"
3
+ = "<textarea>BLAH\n</textarea>"
@@ -0,0 +1,10 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %body
5
+ #content
6
+ = @content_for_layout
7
+ #yieldy
8
+ = yield :layout
9
+ #nosym
10
+ = yield
@@ -0,0 +1,5 @@
1
+ = "not me!"
2
+ = "nor me!"
3
+ - foo = "not even me!"
4
+ %p= foo
5
+ %h1 Me!
@@ -0,0 +1,39 @@
1
+ = h("&&&&&&&&&&&") # This is an ActionView Helper... should load
2
+ - foo = capture do # This ActionView Helper is designed for ERB, but should work with HAML
3
+ %div
4
+ %p.title Title
5
+ %p.text
6
+ Woah this is really crazy
7
+ I mean wow,
8
+ man.
9
+ - 3.times do
10
+ = foo
11
+ %p foo
12
+ - tab_up
13
+ %p reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally loooooooooooooooooong
14
+ - tab_down
15
+ .woah
16
+ #funky
17
+ = capture_haml do
18
+ %div
19
+ %h1 Big!
20
+ %p Small
21
+ / Invisible
22
+ = capture do
23
+ .dilly
24
+ %p foo
25
+ %h1 bar
26
+ = surround '(', ')' do
27
+ %strong parentheses!
28
+ = precede '*' do
29
+ %span.small Not really
30
+ click
31
+ = succeed '.' do
32
+ %a{:href=>"thing"} here
33
+ %p baz
34
+ - buffer.tabulation = 10
35
+ %p boom
36
+ - concat "foo\n"
37
+ - buffer.tabulation = 0
38
+ = list_of({:google => 'http://www.google.com'}) do |name, link|
39
+ %a{ :href => link }= name
@@ -0,0 +1,6 @@
1
+ %div[@article]
2
+ %h1= @article.title
3
+ %div= @article.body
4
+ %div{:class => "article full"}[@article]= "boo"
5
+ %span[@not_a_real_variable_and_will_be_nil]
6
+ Boo
@@ -0,0 +1,29 @@
1
+ !!! XML
2
+ !!! XML ISO-8859-1
3
+ !!! XML UtF-8 Foo bar
4
+ !!!
5
+ !!! 1.1
6
+ !!! 1.1 Strict
7
+ !!! Strict foo bar
8
+ !!! FRAMESET
9
+ %strong{:apos => "Foo's bar!"} Boo!
10
+ .render= render :inline => "%em= 'wow!'", :type => :haml
11
+ %p
12
+ \Escape
13
+ \- character
14
+ \%p foo
15
+ \yee\ha
16
+ / Short comment
17
+ / This is a really long comment look how long it is it should be on a line of its own don't you think?
18
+ /
19
+ This is a block comment
20
+ cool, huh?
21
+ %strong there can even be sub-tags!
22
+ = "Or script!"
23
+ /[if lte IE6] conditional comment!
24
+ /[if gte IE7]
25
+ %p Block conditional comment
26
+ %div
27
+ %h1 Cool, eh?
28
+ /[if gte IE5.2]
29
+ Woah a period.