cerubis 0.0.1
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/.gitignore +10 -0
- data/.travis.yml +14 -0
- data/Gemfile +15 -0
- data/README.md +111 -0
- data/Rakefile +15 -0
- data/TODO.md +31 -0
- data/cerubis.gemspec +22 -0
- data/examples/blocks.rb +20 -0
- data/examples/full/blocks/script_block.rb +8 -0
- data/examples/full/config.rb +14 -0
- data/examples/full/example.rb +25 -0
- data/examples/full/helpers/html_helpers.rb +13 -0
- data/examples/full/helpers/include_helper.rb +15 -0
- data/examples/full/models/page.rb +17 -0
- data/examples/full/models/site.rb +13 -0
- data/examples/full/templates/_footer.cerubis +1 -0
- data/examples/full/templates/_header.cerubis +1 -0
- data/examples/full/templates/main.cerubis +31 -0
- data/examples/helpers.rb +22 -0
- data/examples/html.rb +18 -0
- data/examples/variables.rb +10 -0
- data/lib/cerubis.rb +55 -0
- data/lib/cerubis/block.rb +27 -0
- data/lib/cerubis/block_node.rb +37 -0
- data/lib/cerubis/blocks/if.rb +8 -0
- data/lib/cerubis/blocks/loop.rb +20 -0
- data/lib/cerubis/blocks/unless.rb +9 -0
- data/lib/cerubis/condition.rb +59 -0
- data/lib/cerubis/context.rb +30 -0
- data/lib/cerubis/helper.rb +12 -0
- data/lib/cerubis/matcher.rb +19 -0
- data/lib/cerubis/method.rb +19 -0
- data/lib/cerubis/node.rb +27 -0
- data/lib/cerubis/objects/array.rb +4 -0
- data/lib/cerubis/objects/fixnum.rb +4 -0
- data/lib/cerubis/objects/float.rb +4 -0
- data/lib/cerubis/objects/hash.rb +4 -0
- data/lib/cerubis/objects/string.rb +4 -0
- data/lib/cerubis/parser.rb +125 -0
- data/lib/cerubis/syntax_error.rb +4 -0
- data/lib/cerubis/template.rb +21 -0
- data/lib/cerubis/text_node.rb +10 -0
- data/lib/cerubis/variable_replacement.rb +34 -0
- data/lib/cerubis/version.rb +3 -0
- data/test/all.rb +3 -0
- data/test/cerubis/block_node_test.rb +36 -0
- data/test/cerubis/blocks/if_test.rb +24 -0
- data/test/cerubis/blocks/loop_test.rb +25 -0
- data/test/cerubis/blocks/unless_test.rb +25 -0
- data/test/cerubis/condition_test.rb +142 -0
- data/test/cerubis/context_test.rb +33 -0
- data/test/cerubis/helper_test.rb +17 -0
- data/test/cerubis/matcher_test.rb +20 -0
- data/test/cerubis/method_test.rb +60 -0
- data/test/cerubis/parser_test.rb +48 -0
- data/test/cerubis/template_test.rb +38 -0
- data/test/cerubis/text_node_test.rb +16 -0
- data/test/cerubis_test.rb +31 -0
- data/test/matchers/test_block_name.rb +25 -0
- data/test/matchers/test_close_block.rb +25 -0
- data/test/matchers/test_conditions.rb +21 -0
- data/test/matchers/test_helpers.rb +21 -0
- data/test/matchers/test_object_method.rb +37 -0
- data/test/matchers/test_open_block.rb +57 -0
- data/test/matchers/test_operators.rb +29 -0
- data/test/matchers/test_variable.rb +37 -0
- data/test/methods/test_array_methods.rb +21 -0
- data/test/methods/test_fixnum_methods.rb +6 -0
- data/test/methods/test_float_methods.rb +6 -0
- data/test/methods/test_hash_methods.rb +11 -0
- data/test/methods/test_string_methods.rb +11 -0
- data/test/nodes/test_node_defaults.rb +30 -0
- data/test/rendered_test.rb +159 -0
- data/test/test_helper.rb +34 -0
- metadata +149 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
class Cerubis
|
2
|
+
class Template
|
3
|
+
attr :content
|
4
|
+
attr :context
|
5
|
+
attr :nodes
|
6
|
+
|
7
|
+
def initialize(content, context={})
|
8
|
+
@content = content
|
9
|
+
@context = Context.new(context)
|
10
|
+
@nodes = Parser.new(@content, :parent => self).nodes
|
11
|
+
end
|
12
|
+
|
13
|
+
def compile
|
14
|
+
@template ||= nodes.map(&:render).join
|
15
|
+
end
|
16
|
+
|
17
|
+
alias :to_html :compile
|
18
|
+
alias :to_text :compile
|
19
|
+
alias :to_s :compile
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Cerubis
|
2
|
+
module VariableReplacement
|
3
|
+
def replace_variables(str, ctx=context)
|
4
|
+
str.gsub(Matcher::Variable) do |variable|
|
5
|
+
match_var = variable.match(Matcher::Variable)[1]
|
6
|
+
if match = match_var.match(Matcher::Helpers)
|
7
|
+
helper_method = match[1]
|
8
|
+
helper_args = match[2].to_s.split(Matcher::CommaOutsideQuote).map do |arg|
|
9
|
+
ctx.get(arg.strip)
|
10
|
+
end
|
11
|
+
|
12
|
+
begin
|
13
|
+
if helper_mod = Cerubis.helpers[helper_method.to_sym] || Cerubis.helpers[helper_method]
|
14
|
+
helper = Helper.new(ctx)
|
15
|
+
helper.extend helper_mod
|
16
|
+
|
17
|
+
if has_public_method?(helper, helper_method)
|
18
|
+
helper.send(helper_method, *helper_args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
rescue ArgumentError
|
22
|
+
raise SyntaxError, "A wrong number of arguments were passed to '#{helper_method}'"
|
23
|
+
end
|
24
|
+
else
|
25
|
+
ctx.get(match_var)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_public_method?(obj, meth)
|
31
|
+
obj.public_methods.include?(meth) || obj.public_methods.include?(meth.to_sym)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/test/all.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'nodes/test_node_defaults'
|
3
|
+
|
4
|
+
class Cerubis::BlockNodeTest < MiniTest::Unit::TestCase
|
5
|
+
include TestNodeDefaults
|
6
|
+
|
7
|
+
def test_open_and_close_block_text_removed_on_render
|
8
|
+
content = <<-STR
|
9
|
+
{{#if true}}
|
10
|
+
Foo Content
|
11
|
+
{{/if}}
|
12
|
+
STR
|
13
|
+
|
14
|
+
node = Cerubis::BlockNode.new(content, :parent => StubObject.new)
|
15
|
+
refute_match /\{\{/, node.render
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_variable_replacement
|
19
|
+
content = <<-STR
|
20
|
+
{{#if true}}
|
21
|
+
<h1>{{title}}</h1>
|
22
|
+
{{/if}}
|
23
|
+
STR
|
24
|
+
|
25
|
+
node = Cerubis::BlockNode.new(content, options)
|
26
|
+
html = Capybara::Node::Simple.new(node.render)
|
27
|
+
|
28
|
+
assert html.has_selector?('h1', :text => 'Foo Title')
|
29
|
+
refute_match /\{\{/, node.render
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def class_name
|
34
|
+
Cerubis::BlockNode
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Cerubis::Blocks::IfTest < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
parent = StubObject.new
|
6
|
+
content = <<-STR
|
7
|
+
{{#if true}}
|
8
|
+
Foo Content
|
9
|
+
{{/if}}
|
10
|
+
STR
|
11
|
+
|
12
|
+
node = Cerubis::BlockNode.new(content, :parent => parent)
|
13
|
+
@output = node.render
|
14
|
+
@block = node.block
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_block_is_instance_of_if_block_class
|
18
|
+
assert_instance_of Cerubis::Blocks::If, @block
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_block_condition_is_true
|
22
|
+
assert @block.true?
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Cerubis::Blocks::LoopTest < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
context = Cerubis::Context.new(:items => [1,2,3])
|
6
|
+
parent = StubObject.new(:context => context)
|
7
|
+
content = <<-STR
|
8
|
+
{{#loop item in items}}
|
9
|
+
<p>{{ item }}</p>
|
10
|
+
{{/loop}}
|
11
|
+
STR
|
12
|
+
|
13
|
+
node = Cerubis::BlockNode.new(content, :parent => parent)
|
14
|
+
@output = node.render
|
15
|
+
@block = node.block
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_block_is_instance_of_loop_block_class
|
19
|
+
assert_instance_of Cerubis::Blocks::Loop, @block
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_block_condition_is_true
|
23
|
+
assert @block.true?
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Cerubis::Blocks::UnlessTest < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
context = Cerubis::Context.new
|
6
|
+
parent = StubObject.new(:context => context)
|
7
|
+
content = <<-STR
|
8
|
+
{{#unless false}}
|
9
|
+
Foo Content
|
10
|
+
{{/unless}}
|
11
|
+
STR
|
12
|
+
|
13
|
+
node = Cerubis::BlockNode.new(content, :parent => parent)
|
14
|
+
@output = node.render
|
15
|
+
@block = node.block
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_block_is_instance_of_unless_block_class
|
19
|
+
assert_instance_of Cerubis::Blocks::Unless, @block
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_block_condition_is_true
|
23
|
+
assert @block.true?
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Cerubis::ConditionTest < MiniTest::Unit::TestCase
|
4
|
+
def test_context_objects
|
5
|
+
condition_str = '2 > 1'
|
6
|
+
context = Cerubis::Context.new
|
7
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
8
|
+
|
9
|
+
assert condition.true?
|
10
|
+
assert_equal ['2', '>', '1'], condition.parsed_content
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_parsed_content
|
14
|
+
condition_str = 'item > item2'
|
15
|
+
context = Cerubis::Context.new(:item => 2, :item2 => 1)
|
16
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
17
|
+
|
18
|
+
assert condition.true?
|
19
|
+
assert_equal 2, condition.context_objects.first
|
20
|
+
assert_equal 1, condition.context_objects.last
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_if_true_condition
|
24
|
+
condition_str = 'true'
|
25
|
+
context = Cerubis::Context.new
|
26
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
27
|
+
|
28
|
+
assert condition.true?
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_if_2_greater_than_1
|
32
|
+
condition_str = '2 > 1'
|
33
|
+
context = Cerubis::Context.new
|
34
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
35
|
+
|
36
|
+
assert condition.true?
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_if_object_method
|
40
|
+
condition_str = 'item.empty?'
|
41
|
+
item = StubObject.new(:empty? => true)
|
42
|
+
context = Cerubis::Context.new(:item => item)
|
43
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
44
|
+
|
45
|
+
assert condition.true?
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_if_1_greater_than_2_fails
|
49
|
+
condition_str = '1 > 2'
|
50
|
+
context = Cerubis::Context.new
|
51
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
52
|
+
|
53
|
+
refute condition.true?
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_in_operator_used_in_if_block
|
57
|
+
assert_raises Cerubis::SyntaxError do
|
58
|
+
condition_str = 'item in items'
|
59
|
+
context = Cerubis::Context.new
|
60
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
61
|
+
condition.true?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_loop_in_block_true
|
66
|
+
condition_str = 'item in items'
|
67
|
+
context = Cerubis::Context.new(:items => [1,2,3,4])
|
68
|
+
condition = Cerubis::Condition.new(condition_str, :type => :loop, :context => context)
|
69
|
+
assert condition.true?
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_loop_in_block_false
|
73
|
+
condition_str = 'item in items'
|
74
|
+
context = Cerubis::Context.new(:items => [])
|
75
|
+
condition = Cerubis::Condition.new(condition_str, :type => :loop, :context => context)
|
76
|
+
refute condition.true?
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_double_equals_operator
|
80
|
+
condition_str = '1 == 1'
|
81
|
+
context = Cerubis::Context.new
|
82
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
83
|
+
|
84
|
+
assert condition.true?
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_triple_equals_operator
|
88
|
+
condition_str = 'foo === foo'
|
89
|
+
context = Cerubis::Context.new(:foo => 'foo str')
|
90
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
91
|
+
|
92
|
+
assert condition.true?
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_not_equals_operator
|
96
|
+
condition_str = 'foo != bar'
|
97
|
+
context = Cerubis::Context.new(:foo => 'foo str', :bar => 'bar str')
|
98
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
99
|
+
|
100
|
+
assert condition.true?
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_less_than_operator
|
104
|
+
condition_str = '1 < 2'
|
105
|
+
context = Cerubis::Context.new
|
106
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
107
|
+
|
108
|
+
assert condition.true?
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_greater_than_operator
|
112
|
+
condition_str = '2 > 1'
|
113
|
+
context = Cerubis::Context.new
|
114
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
115
|
+
|
116
|
+
assert condition.true?
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_less_than_or_equals_operator
|
120
|
+
context = Cerubis::Context.new
|
121
|
+
|
122
|
+
condition_str = '1 <= 2'
|
123
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
124
|
+
assert condition.true?
|
125
|
+
|
126
|
+
condition_str = '2 <= 2'
|
127
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
128
|
+
assert condition.true?
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_greater_than_or_equals_operator
|
132
|
+
context = Cerubis::Context.new
|
133
|
+
|
134
|
+
condition_str = '2 >= 1'
|
135
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
136
|
+
assert condition.true?
|
137
|
+
|
138
|
+
condition_str = '2 >= 2'
|
139
|
+
condition = Cerubis::Condition.new(condition_str, :type => :if, :context => context)
|
140
|
+
assert condition.true?
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Cerubis::ContextTest < MiniTest::Unit::TestCase
|
4
|
+
def test_context_returns_true
|
5
|
+
context = Cerubis::Context.new
|
6
|
+
assert_equal true, context.get('true')
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_context_returns_false
|
10
|
+
context = Cerubis::Context.new
|
11
|
+
assert_equal false, context.get('false')
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_context_returns_integer
|
15
|
+
context = Cerubis::Context.new
|
16
|
+
assert_equal 1, context.get('1')
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_context_returns_float
|
20
|
+
context = Cerubis::Context.new
|
21
|
+
assert_equal 1.5, context.get('1.5')
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_context_returns_item_from_context
|
25
|
+
context = Cerubis::Context.new(:item => :foo)
|
26
|
+
assert_equal :foo, context.get('item')
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_context_returns_string_without_single_quotes
|
30
|
+
context = Cerubis::Context.new
|
31
|
+
assert_equal 'foo', context.get("'foo'")
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Cerubis::HelperTest < MiniTest::Unit::TestCase
|
4
|
+
def test_helper_can_access_context
|
5
|
+
context = Cerubis::Context.new(:bar => 'bar str')
|
6
|
+
helper = Cerubis::Helper.new(context)
|
7
|
+
helper.extend FooHelper
|
8
|
+
|
9
|
+
assert_equal 'bar str', helper.foo_helper('bar')
|
10
|
+
end
|
11
|
+
|
12
|
+
module FooHelper
|
13
|
+
def foo_helper(obj)
|
14
|
+
"#{context[obj.to_sym]}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'matchers/test_operators'
|
3
|
+
require 'matchers/test_block_name'
|
4
|
+
require 'matchers/test_object_method'
|
5
|
+
require 'matchers/test_open_block'
|
6
|
+
require 'matchers/test_close_block'
|
7
|
+
require 'matchers/test_conditions'
|
8
|
+
require 'matchers/test_variable'
|
9
|
+
require 'matchers/test_helpers'
|
10
|
+
|
11
|
+
class Cerubis::MatcherTest < MiniTest::Unit::TestCase
|
12
|
+
include TestOperators
|
13
|
+
include TestBlockName
|
14
|
+
include TestObjectMethod
|
15
|
+
include TestOpenBlock
|
16
|
+
include TestCloseBlock
|
17
|
+
include TestConditions
|
18
|
+
include TestVariable
|
19
|
+
include TestHelpers
|
20
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'methods/test_array_methods'
|
3
|
+
require 'methods/test_string_methods'
|
4
|
+
require 'methods/test_float_methods'
|
5
|
+
require 'methods/test_fixnum_methods'
|
6
|
+
require 'methods/test_hash_methods'
|
7
|
+
|
8
|
+
class Cerubis::MethodTest < MiniTest::Unit::TestCase
|
9
|
+
include TestArrayMethods
|
10
|
+
include TestStringMethods
|
11
|
+
include TestFloatMethods
|
12
|
+
include TestFixnumMethods
|
13
|
+
include TestHashMethods
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@obj = FooObj.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_method_is_allowed
|
20
|
+
assert @obj.cerubis_respond_to?(:foo)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_nested_method_is_allowed
|
24
|
+
assert @obj.foo.cerubis_respond_to?(:baz)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_method_is_not_allowed
|
28
|
+
refute @obj.cerubis_respond_to?(:bar)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_nested_method_is_not_allowed
|
32
|
+
refute @obj.foo.cerubis_respond_to?(:cux)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class FooObj
|
37
|
+
include Cerubis::Method
|
38
|
+
cerubis_method :foo
|
39
|
+
|
40
|
+
def foo
|
41
|
+
BazObj.new
|
42
|
+
end
|
43
|
+
|
44
|
+
def bar
|
45
|
+
"Not Allowed"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class BazObj
|
50
|
+
include Cerubis::Method
|
51
|
+
cerubis_method :baz
|
52
|
+
|
53
|
+
def baz
|
54
|
+
"Allowed"
|
55
|
+
end
|
56
|
+
|
57
|
+
def cux
|
58
|
+
"Not Allowed"
|
59
|
+
end
|
60
|
+
end
|