h2o 0.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +11 -0
- data/.gitignore +1 -0
- data/.project +17 -0
- data/README.md +0 -0
- data/Rakefile +32 -0
- data/TODO.md +5 -0
- data/VERSION +1 -0
- data/benchmark/parser.rb +57 -0
- data/benchmark/source.html +4212 -0
- data/example/h2o/base.html +0 -1
- data/example/h2o/index.html +10 -0
- data/example/h2o/layout.html +11 -0
- data/example/request.html +0 -0
- data/example/server +1 -1
- data/h2o.gemspec +101 -41
- data/init.rb +1 -0
- data/lib/.DS_Store +0 -0
- data/lib/core_ext/object.rb +0 -0
- data/lib/h2o.rb +29 -39
- data/lib/h2o/constants.rb +2 -2
- data/lib/h2o/context.rb +3 -10
- data/lib/h2o/error.rb +9 -0
- data/lib/h2o/filters/default.rb +0 -0
- data/lib/h2o/nodes.rb +5 -1
- data/lib/h2o/tags.rb +1 -6
- data/lib/h2o/tags/block.rb +0 -30
- data/lib/h2o/tags/extends.rb +33 -0
- data/lib/h2o/tags/for.rb +7 -6
- data/lib/h2o/tags/with.rb +0 -0
- data/lib/h2o/template.rb +33 -0
- data/spec/fixtures/_partial.html +0 -0
- data/spec/fixtures/a.html +1 -0
- data/spec/fixtures/b.html +0 -0
- data/spec/fixtures/deep/folder/c.html +0 -0
- data/spec/h2o/context_spec.rb +134 -0
- data/spec/h2o/default.html +93 -0
- data/spec/h2o/file_loader_spec.rb +35 -0
- data/spec/h2o/filters_spec.rb +57 -0
- data/spec/h2o/parser_spec.rb +78 -0
- data/spec/h2o/tags/block_spec.rb +26 -0
- data/spec/h2o/tags/for_spec.rb +65 -0
- data/spec/h2o/tags/if_spec.rb +58 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +24 -0
- metadata +81 -27
- data/lib/h2o/errors.rb +0 -7
- data/lib/h2o/tags/recurse.rb +0 -55
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe H2o::Tags::For do
|
4
|
+
describe "Iterations" do
|
5
|
+
it "should iteration through array" do
|
6
|
+
t = parse("{% for a in list %}{{ a }}{% endfor %}")
|
7
|
+
t.render(:list => [1,2,3]).should == '123'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should iterate through array subclass" do
|
11
|
+
t = parse("{% for i, user in users %}{{ i }}.{{ user }}{% endfor %}")
|
12
|
+
t.render(:users =>%w(PeterIT ManHoodHero)).should == '0.PeterIT1.ManHoodHero'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should iterate through a hash object" do
|
16
|
+
person = {:name => 'taylor', :age => 19 }
|
17
|
+
|
18
|
+
t = parse("{% for a in person %}{{ a }}{% endfor %}")
|
19
|
+
t.render(:person => person).should == 'taylor19'
|
20
|
+
|
21
|
+
t = parse("{%for a, b in person %}{{ a }}{{ b }}{% endfor %}")
|
22
|
+
t.render(:person => person).should == 'nametaylorage19'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "Magic loop variable" do
|
27
|
+
before do
|
28
|
+
@context = {:words=> %w(something else about this person) }
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should correct iteration counters" do
|
32
|
+
fortag('{{ loop.counter }}').render(@context).should == '12345'
|
33
|
+
fortag('{{ loop.counter0 }}').render(@context).should == '01234'
|
34
|
+
|
35
|
+
fortag('{{ loop.revcounter }}').render(@context).should == '54321'
|
36
|
+
fortag('{{ loop.revcounter0 }}').render(@context).should == '43210'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should have .even and .odd iteration flag" do
|
40
|
+
fortag('{% if loop.even %}{{ item }}{% endif %}').render(@context).should == 'elsethis'
|
41
|
+
fortag('{% if loop.odd %}{{ item}}{% endif %}').render(@context).should == 'somethingaboutperson'
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have .first and .last flag to indicate if it's first/last iteration" do
|
45
|
+
fortag('{%if loop.first %}{{ item }}{% endif }').render(@context).should == 'something'
|
46
|
+
fortag('{%if loop.last %}{{ item }}{% endif }').render(@context).should == 'person'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should have parent property pointer to parent loop" do
|
50
|
+
template = fortag '{% for num in numbers %}{{ loop.parent.counter }}-{{ item }}{% endfor %}'
|
51
|
+
expect = '1-something1-something2-else2-else3-about3-about4-this4-this5-person5-person'
|
52
|
+
|
53
|
+
template.render(@context.merge(:numbers=> [6,8])).should == expect
|
54
|
+
|
55
|
+
template = fortag '{% for num in numbers %}{% if loop.parent.first %}{{ num }}-{{ item }}{% endif %}{% endfor %}'
|
56
|
+
expect = '88-something99-something66-something'
|
57
|
+
|
58
|
+
template.render(@context.merge(:numbers=> [88,99,66])).should == expect
|
59
|
+
end
|
60
|
+
|
61
|
+
def fortag(body)
|
62
|
+
parse("{% for item in words %}#{body}{% endfor %}")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe H2o::Tags::If do
|
4
|
+
it "should render if body when expression evaluated as true" do
|
5
|
+
parse('{% if true %}if body{% endif %}').render.should == 'if body'
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should render else body when expression yields false" do
|
9
|
+
parse('{% if !true %}{% else %}else body{% endif %}').render.should == 'else body'
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "Basic type comparisons" do
|
13
|
+
it "should compare numbers" do
|
14
|
+
parse('{% if 3 > 2 %}Yes{% endif %}').render.should == 'Yes'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should compare string" do
|
18
|
+
parse('{% if "z" > "a" %}Y{% endif %}').render.should == 'Y'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should compare variables" do
|
22
|
+
parse('{% if a >= b %}Y{% endif %}').render(:a=>2, :b=>1).should == 'Y'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "logical comparisons" do
|
27
|
+
it "should perform left > right comparison" do
|
28
|
+
parse('{% if 3 > 2 %}Yes{% endif %}').render.should == 'Yes'
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should perform left >= right comparison" do
|
33
|
+
parse('{% if 3 >= 2 %}Y{% endif %}').render.should == 'Y'
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should perform left >= right comparison" do
|
38
|
+
parse('{% if 3 >= 2 %}Y{% endif %}').render.should == 'Y'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "Binary logics" do
|
43
|
+
it "should evaluate a true expression" do
|
44
|
+
parse('{% if true %}truth{% endif %}').render.should == 'truth'
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
it "should negate a expression with not or !" do
|
49
|
+
parse('{% if not false %}truth{% endif %}').render.should == 'truth'
|
50
|
+
|
51
|
+
parse('{% if !false %}truth{% endif %}').render.should == 'truth'
|
52
|
+
|
53
|
+
parse('{% if !page.editable %}Locked{% else %}Editable{% endif %}').render(:page=>{:editable => true}).should == 'Editable'
|
54
|
+
|
55
|
+
parse('{% if ! 2 > 3 %}Y{% endif %}').render.should == 'Y'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
3
|
+
|
4
|
+
require 'h2o'
|
5
|
+
require 'pp'
|
6
|
+
|
7
|
+
def parse(source)
|
8
|
+
H2o::Template.parse(source)
|
9
|
+
end
|
10
|
+
|
11
|
+
class H2o::HashLoader
|
12
|
+
def initialize(stack)
|
13
|
+
@stack = stack
|
14
|
+
end
|
15
|
+
|
16
|
+
def read(file)
|
17
|
+
raise "Template not find" unless exist?(file)
|
18
|
+
@stack[file]
|
19
|
+
end
|
20
|
+
|
21
|
+
def exist?(file)
|
22
|
+
@stack.has_key?(file)
|
23
|
+
end
|
24
|
+
end
|
metadata
CHANGED
@@ -1,20 +1,37 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: h2o
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
version: 0.3.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
|
-
- Taylor
|
12
|
+
- Taylor luk
|
8
13
|
autorequire:
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-08-30 00:00:00 +10:00
|
13
18
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: schacon-git
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
16
33
|
description: h2o is a django inspired template that offers natural template syntax and easy to integrate.
|
17
|
-
email:
|
34
|
+
email: subjective@gmail.com
|
18
35
|
executables: []
|
19
36
|
|
20
37
|
extensions: []
|
@@ -22,61 +39,98 @@ extensions: []
|
|
22
39
|
extra_rdoc_files:
|
23
40
|
- README.md
|
24
41
|
files:
|
42
|
+
- .autotest
|
43
|
+
- .gitignore
|
44
|
+
- .project
|
25
45
|
- README.md
|
46
|
+
- Rakefile
|
47
|
+
- TODO.md
|
48
|
+
- VERSION
|
49
|
+
- benchmark/parser.rb
|
50
|
+
- benchmark/source.html
|
51
|
+
- example/erb/base.html
|
52
|
+
- example/h2o/base.html
|
53
|
+
- example/h2o/index.html
|
54
|
+
- example/h2o/inherit.html
|
55
|
+
- example/h2o/layout.html
|
56
|
+
- example/liquid/base.html
|
57
|
+
- example/request.html
|
58
|
+
- example/run.rb
|
59
|
+
- example/server
|
60
|
+
- example/server.bat
|
61
|
+
- example/server.rb
|
26
62
|
- h2o.gemspec
|
63
|
+
- init.rb
|
64
|
+
- lib/.DS_Store
|
65
|
+
- lib/core_ext/object.rb
|
27
66
|
- lib/h2o.rb
|
28
67
|
- lib/h2o/constants.rb
|
29
68
|
- lib/h2o/context.rb
|
30
69
|
- lib/h2o/datatype.rb
|
31
|
-
- lib/h2o/
|
70
|
+
- lib/h2o/error.rb
|
32
71
|
- lib/h2o/filters.rb
|
33
72
|
- lib/h2o/filters/default.rb
|
34
73
|
- lib/h2o/nodes.rb
|
35
74
|
- lib/h2o/parser.rb
|
36
75
|
- lib/h2o/tags.rb
|
37
76
|
- lib/h2o/tags/block.rb
|
77
|
+
- lib/h2o/tags/extends.rb
|
38
78
|
- lib/h2o/tags/for.rb
|
39
79
|
- lib/h2o/tags/if.rb
|
40
80
|
- lib/h2o/tags/with.rb
|
41
|
-
- lib/h2o/
|
42
|
-
-
|
43
|
-
-
|
44
|
-
-
|
45
|
-
-
|
46
|
-
-
|
47
|
-
-
|
48
|
-
-
|
49
|
-
-
|
50
|
-
-
|
51
|
-
-
|
81
|
+
- lib/h2o/template.rb
|
82
|
+
- spec/fixtures/_partial.html
|
83
|
+
- spec/fixtures/a.html
|
84
|
+
- spec/fixtures/b.html
|
85
|
+
- spec/fixtures/deep/folder/c.html
|
86
|
+
- spec/h2o/context_spec.rb
|
87
|
+
- spec/h2o/default.html
|
88
|
+
- spec/h2o/file_loader_spec.rb
|
89
|
+
- spec/h2o/filters_spec.rb
|
90
|
+
- spec/h2o/parser_spec.rb
|
91
|
+
- spec/h2o/tags/block_spec.rb
|
92
|
+
- spec/h2o/tags/for_spec.rb
|
93
|
+
- spec/h2o/tags/if_spec.rb
|
94
|
+
- spec/spec.opts
|
95
|
+
- spec/spec_helper.rb
|
52
96
|
has_rdoc: true
|
53
|
-
homepage: http://
|
97
|
+
homepage: http://www.h2o-template.org
|
54
98
|
licenses: []
|
55
99
|
|
56
100
|
post_install_message:
|
57
101
|
rdoc_options:
|
58
|
-
- --
|
59
|
-
- README.md
|
102
|
+
- --charset=UTF-8
|
60
103
|
require_paths:
|
61
104
|
- lib
|
62
105
|
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
63
107
|
requirements:
|
64
108
|
- - ">="
|
65
109
|
- !ruby/object:Gem::Version
|
110
|
+
segments:
|
111
|
+
- 0
|
66
112
|
version: "0"
|
67
|
-
version:
|
68
113
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
69
115
|
requirements:
|
70
116
|
- - ">="
|
71
117
|
- !ruby/object:Gem::Version
|
118
|
+
segments:
|
119
|
+
- 0
|
72
120
|
version: "0"
|
73
|
-
version:
|
74
121
|
requirements: []
|
75
122
|
|
76
123
|
rubyforge_project:
|
77
|
-
rubygems_version: 1.3.
|
124
|
+
rubygems_version: 1.3.7
|
78
125
|
signing_key:
|
79
126
|
specification_version: 3
|
80
|
-
summary:
|
81
|
-
test_files:
|
82
|
-
|
127
|
+
summary: h2o is a django inspired template
|
128
|
+
test_files:
|
129
|
+
- spec/h2o/context_spec.rb
|
130
|
+
- spec/h2o/file_loader_spec.rb
|
131
|
+
- spec/h2o/filters_spec.rb
|
132
|
+
- spec/h2o/parser_spec.rb
|
133
|
+
- spec/h2o/tags/block_spec.rb
|
134
|
+
- spec/h2o/tags/for_spec.rb
|
135
|
+
- spec/h2o/tags/if_spec.rb
|
136
|
+
- spec/spec_helper.rb
|
data/lib/h2o/errors.rb
DELETED
data/lib/h2o/tags/recurse.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
module H2o
|
2
|
-
module Tags
|
3
|
-
# Recurse tag allows rendering of tree structures. The template should look something like this:
|
4
|
-
# {% recurse all_categories with children as category %}
|
5
|
-
# <ul>
|
6
|
-
# {% loop %}
|
7
|
-
# <li>
|
8
|
-
# <h{{ level }}>{{ category.title }}</h{{ level }}>
|
9
|
-
# {% children %}
|
10
|
-
# </li>
|
11
|
-
# {% endloop %}
|
12
|
-
# </ul>
|
13
|
-
# {% endrecurse %}
|
14
|
-
class Recurse < Tag
|
15
|
-
|
16
|
-
Syntax = /(#{H2o::NAME_RE})\s+with\s+(#{H2o::IDENTIFIER_RE})\s+as\s+(#{H2o::IDENTIFIER_RE})/
|
17
|
-
|
18
|
-
def initialize(parser, argstring)
|
19
|
-
@body = parser.parse(:loop, :children, :endloop, :endrecurse)
|
20
|
-
@child = parser.parse(:children, :endloop, :endrecurse) if parser.token && parser.token.include?('loop')
|
21
|
-
@enditem = parser.parse(:endloop, :endrecurse) if parser.token && parser.token.include?('children')
|
22
|
-
@end = parser.parse(:endrecurse) if parser.token && parser.token.include?('endloop')
|
23
|
-
if argstring =~ Syntax
|
24
|
-
@collection_id = $1.to_sym
|
25
|
-
@children_method = $2.to_sym
|
26
|
-
@item_id = $3.to_sym
|
27
|
-
else
|
28
|
-
raise SyntaxError, "Invalid recurse syntax "
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def render(context, stream)
|
33
|
-
collection = context.resolve(@collection_id)
|
34
|
-
@body.render(context, stream)
|
35
|
-
context.stack do
|
36
|
-
level = context[:level] || 1
|
37
|
-
collection.each do |item|
|
38
|
-
context[@item_id] = item
|
39
|
-
context[:level] = level
|
40
|
-
@child.render(context, stream)
|
41
|
-
children = item.respond_to?(@children_method) ? item.send(@children_method) : item[@children_method]
|
42
|
-
unless children.empty?
|
43
|
-
stream << self.render(Context.new({@collection_id => children, :level => (level + 1)}), [])
|
44
|
-
end
|
45
|
-
@enditem.render(context, stream)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
@end.render(context, stream)
|
49
|
-
end
|
50
|
-
|
51
|
-
Tags.register(self, :recurse)
|
52
|
-
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|