h2o 0.2 → 0.3.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.
- 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
|