h2o 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +52 -0
- data/example/erb/base.html +56 -0
- data/example/h2o/base.html +85 -0
- data/example/h2o/inherit.html +7 -0
- data/example/liquid/base.html +57 -0
- data/example/request.html +0 -0
- data/example/run.rb +103 -0
- data/example/server +3 -0
- data/example/server.bat +1 -0
- data/example/server.rb +37 -0
- data/h2o.gemspec +43 -0
- data/lib/core_ext/object.rb +13 -0
- data/lib/h2o.rb +43 -0
- data/lib/h2o/constants.rb +40 -0
- data/lib/h2o/context.rb +158 -0
- data/lib/h2o/datatype.rb +11 -0
- data/lib/h2o/errors.rb +7 -0
- data/lib/h2o/filters.rb +49 -0
- data/lib/h2o/filters/default.rb +47 -0
- data/lib/h2o/nodes.rb +68 -0
- data/lib/h2o/parser.rb +225 -0
- data/lib/h2o/tags.rb +22 -0
- data/lib/h2o/tags/block.rb +64 -0
- data/lib/h2o/tags/for.rb +76 -0
- data/lib/h2o/tags/if.rb +77 -0
- data/lib/h2o/tags/recurse.rb +55 -0
- data/lib/h2o/tags/with.rb +28 -0
- metadata +82 -0
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
H2O template markup
|
2
|
+
========================
|
3
|
+
Being a martial art fan, I burrow a quote.
|
4
|
+
|
5
|
+
>Empty your mind, be formless. Shapeless, like water. If you put water into a cup, it becomes the cup. You put water into a bottle and it becomes the bottle. You put it in a teapot it becomes the teapot. Now, water can flow or it can crash. **Be water my friend**. -- Bruce Lee
|
6
|
+
|
7
|
+
H2o template
|
8
|
+
------------------------
|
9
|
+
H2O is markup language for Ruby :) that taken a lot of inspiration from django.
|
10
|
+
|
11
|
+
* Readable and human friendly syntax.
|
12
|
+
* Easy to use and maintain
|
13
|
+
* Encourage reuse in templates by template inclusion and inheritance.
|
14
|
+
* highly extensible through filters, tags and template extensions.
|
15
|
+
* ruby 1.9 compatible
|
16
|
+
|
17
|
+
|
18
|
+
Install
|
19
|
+
|
20
|
+
`gem install speedmax-h2o --source=http://gems.github.com`
|
21
|
+
|
22
|
+
as Rails Gem dependencies
|
23
|
+
|
24
|
+
`config.gem 'speedmax-h2o', :lib => 'h2o', :source=> 'http://gems.github.com'`
|
25
|
+
|
26
|
+
as Rails Plugin
|
27
|
+
|
28
|
+
`script/plugin install git://github.com/speedmax/h2o.git`
|
29
|
+
|
30
|
+
With Git
|
31
|
+
|
32
|
+
`git clone http://github.com/speedmax/h2o.git`
|
33
|
+
|
34
|
+
Download
|
35
|
+
|
36
|
+
[<img src="http://github.com/images/modules/download/zip.png">](http://github.com/speedmax/h2o/zipball/master)
|
37
|
+
|
38
|
+
|
39
|
+
Quick start
|
40
|
+
-----------------------
|
41
|
+
|
42
|
+
Your ruby script
|
43
|
+
|
44
|
+
require 'h2o'
|
45
|
+
person = { :name => 'taylor luk', :age => 27 }
|
46
|
+
puts H2o::template.parse('{{ person.name }}').render(:person => person)
|
47
|
+
|
48
|
+
|
49
|
+
Documentation
|
50
|
+
------------------------
|
51
|
+
|
52
|
+
Currently ruby version is still work in progress, please refer to h2o-php's [documentation](http://wiki.github.com/speedmax/h2o-php)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
6
|
+
<title>something {{ page.title | capitalize }}</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
|
10
|
+
<%= context['callable'] %>
|
11
|
+
{{ callable }}
|
12
|
+
|
13
|
+
<h3>try this loop thingy - bitches on the run </h3>
|
14
|
+
|
15
|
+
<h3>Normal:</h3>
|
16
|
+
<ul>
|
17
|
+
<%= context['links'].first %>
|
18
|
+
<% for item in context['links'] %>
|
19
|
+
<li><%= item %></li>
|
20
|
+
<% end %>
|
21
|
+
</ul>
|
22
|
+
|
23
|
+
<h3>Reverse:</h3>
|
24
|
+
<ul>
|
25
|
+
<% context['links'].reverse.each_with_index do |item, index| %>
|
26
|
+
<li <% if index % 2 == 0 %>style="background:green"<% end %>>
|
27
|
+
<%= (context['links'].length - index == 0) %> <%= index %> - <%= item %>
|
28
|
+
|
29
|
+
<% context['links'].each_with_index do |shit, index| %>
|
30
|
+
<%= index %>
|
31
|
+
<% end %>
|
32
|
+
</li>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
</ul>
|
36
|
+
|
37
|
+
<h3>Empty:</h3>
|
38
|
+
<% for ass in [] %>
|
39
|
+
<% defined? ass %>
|
40
|
+
<% end %>
|
41
|
+
|
42
|
+
<h3>Nested: TODO</h3>
|
43
|
+
|
44
|
+
<h3>Conditions</h3>
|
45
|
+
|
46
|
+
<% if context['page']['title'] %>
|
47
|
+
this is a page title
|
48
|
+
<% else %>
|
49
|
+
test - else block
|
50
|
+
<% end %>
|
51
|
+
|
52
|
+
<h1><%= context['page']['title'].capitalize %></h1>
|
53
|
+
<small><%= context['page']['description'] %></small>
|
54
|
+
<p><%= context['page']['body'] %></p>
|
55
|
+
</body>
|
56
|
+
</html>
|
@@ -0,0 +1,85 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
6
|
+
<title>something {{ page.title | capitalize }}</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
|
10
|
+
{% if 1 > 2 %}
|
11
|
+
1 > 2
|
12
|
+
{% else %}
|
13
|
+
2 > 1
|
14
|
+
{% endif %}
|
15
|
+
|
16
|
+
{% if true == true %}
|
17
|
+
Truth
|
18
|
+
{% endif %}
|
19
|
+
|
20
|
+
{% if nil == nil %}
|
21
|
+
devel exists
|
22
|
+
{% endif %}
|
23
|
+
|
24
|
+
{% if 2.3 > 2 %}
|
25
|
+
biggie
|
26
|
+
{% endif %}
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
{{ links.length }}
|
31
|
+
|
32
|
+
{% if page.title == "this is a title" %}
|
33
|
+
haha
|
34
|
+
{% else %}
|
35
|
+
ohoh
|
36
|
+
{% endif %}
|
37
|
+
|
38
|
+
{{ callable }}
|
39
|
+
|
40
|
+
<h3>try this loop thingy - bitches on the run </h3>
|
41
|
+
|
42
|
+
<h3>Normal:</h3>
|
43
|
+
<ul>
|
44
|
+
{{ links.first }}
|
45
|
+
{% for item in links %}
|
46
|
+
<li>{{ item }} </li>
|
47
|
+
{% endfor %}
|
48
|
+
</ul>
|
49
|
+
|
50
|
+
<h3>Reverse:</h3>
|
51
|
+
<ul>
|
52
|
+
{% for item in links reverse %}
|
53
|
+
<li {% if loop.even %}style="background:green"{% endif %}>
|
54
|
+
{{ loop.last }} {{ loop.counter }} - {{ item }}
|
55
|
+
|
56
|
+
{% for shit in links %}
|
57
|
+
{{ loop.counter }}
|
58
|
+
{% endfor %}
|
59
|
+
</li>
|
60
|
+
{% endfor %}
|
61
|
+
</ul>
|
62
|
+
|
63
|
+
<h3>Empty:</h3>
|
64
|
+
{% for ass in asses %}
|
65
|
+
{{ ass }}
|
66
|
+
{% endfor %}
|
67
|
+
|
68
|
+
<h3>Nested: TODO</h3>
|
69
|
+
<h3>Conditions</h3>
|
70
|
+
|
71
|
+
{% if page.title %}
|
72
|
+
this is a page title
|
73
|
+
{% else %}
|
74
|
+
test - else block
|
75
|
+
{% endif %}
|
76
|
+
|
77
|
+
{% block body %}
|
78
|
+
{% block.super %}
|
79
|
+
something here
|
80
|
+
<h1>{{ page.title | test "", adsf }}</h1>
|
81
|
+
<small> {{ page.description }} </small>
|
82
|
+
<p>{{ page.body }}</p>
|
83
|
+
{% endblock %}
|
84
|
+
</body>
|
85
|
+
</html>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
6
|
+
<title>something {{ page.title | capitalize }}</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
|
10
|
+
{{ callable }}
|
11
|
+
|
12
|
+
<h3>try this loop thingy - bitches on the run </h3>
|
13
|
+
|
14
|
+
<h3>Normal:</h3>
|
15
|
+
<ul>
|
16
|
+
{{ links.first }}
|
17
|
+
{% for item in links %}
|
18
|
+
<li>{{ item }} </li>
|
19
|
+
{% endfor %}
|
20
|
+
</ul>
|
21
|
+
|
22
|
+
<h3>Reverse:</h3>
|
23
|
+
<ul>
|
24
|
+
{% for item in links reverse %}
|
25
|
+
|
26
|
+
|
27
|
+
<li {% if loop.even %}style="background:green"{% endif %}>
|
28
|
+
{{ forloop.last }} {{ forloop.index }} - {{ item }}
|
29
|
+
|
30
|
+
{% for shit in links %}
|
31
|
+
{{ forloop.index }}
|
32
|
+
{% endfor %}
|
33
|
+
</li>
|
34
|
+
{% endfor %}
|
35
|
+
</ul>
|
36
|
+
|
37
|
+
<h3>Empty:</h3>
|
38
|
+
{% for ass in asses %}
|
39
|
+
{{ ass }}
|
40
|
+
{% endfor %}
|
41
|
+
|
42
|
+
<h3>Nested: TODO</h3>
|
43
|
+
|
44
|
+
<h3>Conditions</h3>
|
45
|
+
|
46
|
+
{% if page.title %}
|
47
|
+
this is a page title
|
48
|
+
{% else %}
|
49
|
+
test - else block
|
50
|
+
{% endif %}
|
51
|
+
|
52
|
+
<h1>{{ page.title | test "", adsf }}</h1>
|
53
|
+
<small> {{ page.description }} </small>
|
54
|
+
<p>{{ page.body }}</p>
|
55
|
+
|
56
|
+
</body>
|
57
|
+
</html>
|
File without changes
|
data/example/run.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'server'
|
3
|
+
require 'benchmark'
|
4
|
+
|
5
|
+
# Hack require to force reload
|
6
|
+
alias :old_require :require
|
7
|
+
def require file
|
8
|
+
begin; load(File.dirname(__FILE__) + "/../lib/#{file}.rb");rescue Exception => e;old_require(file);end
|
9
|
+
end
|
10
|
+
|
11
|
+
def profile mode
|
12
|
+
raise "please give me a block" unless block_given?
|
13
|
+
require 'ruby-prof' unless defined?(RubyProf)
|
14
|
+
|
15
|
+
modes = {
|
16
|
+
:memory => RubyProf::MEMORY ,
|
17
|
+
:cpu => RubyProf::CPU_TIME ,
|
18
|
+
:time => RubyProf::WALL_TIME,
|
19
|
+
:allocation => RubyProf::ALLOCATIONS
|
20
|
+
}
|
21
|
+
|
22
|
+
RubyProf.measure_mode if mode = modes[mode]
|
23
|
+
|
24
|
+
begin
|
25
|
+
RubyProf.start
|
26
|
+
yield
|
27
|
+
ensure
|
28
|
+
result = RubyProf.stop
|
29
|
+
end
|
30
|
+
|
31
|
+
# Print a graph profile to text
|
32
|
+
|
33
|
+
printer = RubyProf::FlatPrinter.new(result)
|
34
|
+
File.open('request.html', 'w') do |file|
|
35
|
+
printer.print(STDOUT, {:min_percent => 1, :print_file => true})
|
36
|
+
end
|
37
|
+
|
38
|
+
printer = RubyProf::CallTreePrinter.new(result)
|
39
|
+
File.open('cachegrind.out.1', 'w') do |file|
|
40
|
+
printer.print(file, {:min_percent => 1, :print_file => true})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Context
|
45
|
+
context = {
|
46
|
+
'page' => {
|
47
|
+
'title' => 'this is a title',
|
48
|
+
'description' => 'page description',
|
49
|
+
'body' =>'page body'
|
50
|
+
},
|
51
|
+
#:callable => Proc.new { "my ass"; a = 2/0 },
|
52
|
+
'links' => ["http://google.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com", "http://yahoo.com"]
|
53
|
+
}
|
54
|
+
|
55
|
+
# require 'liquid'
|
56
|
+
# require 'pathname'
|
57
|
+
# require 'erb'
|
58
|
+
#
|
59
|
+
# class ErbTemplate
|
60
|
+
# def initialize(file)
|
61
|
+
# @template = ERB.new(Pathname.new(file).read)
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# def render context
|
65
|
+
# @template.result binding
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
|
69
|
+
|
70
|
+
address= "localhost:#{(ARGV[0]||80)}"
|
71
|
+
|
72
|
+
|
73
|
+
# Start server and run template
|
74
|
+
Server.start address do |s|
|
75
|
+
Object.class_eval do
|
76
|
+
remove_const 'H2o' if const_defined? 'H2o'
|
77
|
+
end
|
78
|
+
|
79
|
+
require 'h2o'
|
80
|
+
|
81
|
+
# liquid = Liquid::Template.parse(Pathname.new('liquid/base.html').read)
|
82
|
+
# erb = ErbTemplate.new('erb/base.html')
|
83
|
+
#
|
84
|
+
Benchmark.bm do|b|
|
85
|
+
|
86
|
+
b.report('H2o time :') {
|
87
|
+
h2o = H2o::Template.new('../benchmark/source.html')
|
88
|
+
|
89
|
+
s.print h2o.render(context)
|
90
|
+
}
|
91
|
+
#
|
92
|
+
# s.print 'liquid rendering result<hr>'
|
93
|
+
# b.report("Liquid time :") { s.print liquid.render(context) }
|
94
|
+
#
|
95
|
+
# s.print 'erb rendering result<hr>'
|
96
|
+
# b.report("erb time :") { s.print erb.render(context) }
|
97
|
+
end
|
98
|
+
#
|
99
|
+
# profile :memory do
|
100
|
+
# s.print h2o.render(context)
|
101
|
+
# end
|
102
|
+
end
|
103
|
+
|
data/example/server
ADDED
data/example/server.bat
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby ./run.rb 888
|
data/example/server.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
class Server
|
5
|
+
attr_reader :server
|
6
|
+
def initialize ip, port
|
7
|
+
raise "Please supply a valid ip and port" unless ip && port
|
8
|
+
|
9
|
+
puts "Listening to request #{ip}:#{port}"
|
10
|
+
puts "-----------------------------------"
|
11
|
+
@server = TCPServer.new(ip, port.to_i)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.start(address = 'localhost:80')
|
15
|
+
ip, port = address.split(':')
|
16
|
+
instance = new(ip, port)
|
17
|
+
|
18
|
+
raise "Please give a block to run" unless block_given?
|
19
|
+
|
20
|
+
while s = instance.server.accept do
|
21
|
+
Thread.start do
|
22
|
+
s.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
|
23
|
+
|
24
|
+
begin
|
25
|
+
yield(s)
|
26
|
+
rescue Exception => e
|
27
|
+
s.print "<pre>Error: #{(e.inspect)}</pre>"
|
28
|
+
s.print "<pre>stack: #{e.backtrace.join("\n")}</pre>"
|
29
|
+
ensure
|
30
|
+
s.print "\r\n"
|
31
|
+
s.close
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
data/h2o.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "h2o"
|
3
|
+
s.version = "0.2"
|
4
|
+
s.date = "2008-09-5"
|
5
|
+
s.summary = "Django inspired template markup"
|
6
|
+
s.email = "taylor.luk@idealian.net"
|
7
|
+
s.homepage = "http://github.com/speedmax/h2o"
|
8
|
+
s.description = "h2o is a django inspired template that offers natural template syntax and easy to integrate."
|
9
|
+
s.has_rdoc = true
|
10
|
+
s.authors = ["Taylor Luk"]
|
11
|
+
s.files = ["README.md",
|
12
|
+
"h2o.gemspec",
|
13
|
+
"lib/h2o.rb",
|
14
|
+
"lib/h2o/",
|
15
|
+
"lib/h2o/constants.rb",
|
16
|
+
"lib/h2o/context.rb",
|
17
|
+
"lib/h2o/datatype.rb",
|
18
|
+
"lib/h2o/errors.rb",
|
19
|
+
"lib/h2o/filters.rb",
|
20
|
+
"lib/h2o/filters/default.rb",
|
21
|
+
"lib/h2o/nodes.rb",
|
22
|
+
"lib/h2o/parser.rb",
|
23
|
+
"lib/h2o/tags.rb",
|
24
|
+
"lib/h2o/tags/block.rb",
|
25
|
+
"lib/h2o/tags/for.rb",
|
26
|
+
"lib/h2o/tags/if.rb",
|
27
|
+
"lib/h2o/tags/with.rb",
|
28
|
+
"lib/h2o/tags/recurse.rb",
|
29
|
+
"lib/core_ext/object.rb",
|
30
|
+
"example/server.rb",
|
31
|
+
"example/run.rb",
|
32
|
+
"example/server",
|
33
|
+
"example/server.bat",
|
34
|
+
"example/request.html",
|
35
|
+
"example/erb/base.html",
|
36
|
+
"example/h2o/base.html",
|
37
|
+
"example/h2o/inherit.html",
|
38
|
+
"example/liquid/base.html",
|
39
|
+
]
|
40
|
+
s.test_files = []
|
41
|
+
s.rdoc_options = ["--main", "README.md"]
|
42
|
+
s.extra_rdoc_files = ["README.md"]
|
43
|
+
end
|