temple 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +7 -0
- data/EXPRESSIONS.md +7 -0
- data/README.md +2 -0
- data/lib/temple/engine.rb +1 -13
- data/lib/temple/filters/dynamic_inliner.rb +1 -1
- data/lib/temple/filters/static_merger.rb +2 -3
- data/lib/temple/generators.rb +28 -3
- data/lib/temple/grammar.rb +1 -0
- data/lib/temple/html/dispatcher.rb +4 -0
- data/lib/temple/html/fast.rb +7 -0
- data/lib/temple/html/pretty.rb +1 -1
- data/lib/temple/mixins/dispatcher.rb +13 -30
- data/lib/temple/mixins/engine_dsl.rb +56 -38
- data/lib/temple/mixins/grammar_dsl.rb +1 -1
- data/lib/temple/mixins/template.rb +17 -0
- data/lib/temple/templates.rb +1 -5
- data/lib/temple/templates/tilt.rb +4 -0
- data/lib/temple/version.rb +1 -1
- data/test/filters/test_dynamic_inliner.rb +8 -13
- data/test/filters/test_static_merger.rb +1 -3
- data/test/mixins/test_dispatcher.rb +17 -4
- data/test/test_engine.rb +18 -15
- data/test/test_generator.rb +13 -4
- metadata +25 -9
data/CHANGES
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
0.4.1
|
2
|
+
|
3
|
+
* Generators: produce optimized code
|
4
|
+
* remove deprecated method EngineDSL#wildcard
|
5
|
+
* Set tilt template default_mime_type to text/html
|
6
|
+
* HTML: Support conditional comments [:html, :condcomment, ...]
|
7
|
+
|
1
8
|
0.4.0
|
2
9
|
|
3
10
|
* Split Temple::HTML::AttributeMerger in AttributeSorter,
|
data/EXPRESSIONS.md
CHANGED
@@ -210,6 +210,13 @@ Example:
|
|
210
210
|
generates:
|
211
211
|
<!--comment-->
|
212
212
|
|
213
|
+
### [:html, :condcomment, condition, sexp]
|
214
|
+
|
215
|
+
Example:
|
216
|
+
[:html, :condcomment, 'IE', [:static, 'comment']]
|
217
|
+
generates:
|
218
|
+
<!--[if IE]>comment<![endif]-->
|
219
|
+
|
213
220
|
### [:html, :tag, identifier, attributes, optional-sexp]
|
214
221
|
|
215
222
|
HTML tag abstraction. Identifier can be a String or a Symbol. If the optional content Sexp is omitted
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
Temple
|
2
2
|
======
|
3
3
|
|
4
|
+
[![Build Status](https://secure.travis-ci.org/judofyr/temple.png?branch=master)](http://travis-ci.org/judofyr/temple) [![Dependency Status](https://gemnasium.com/judofyr/temple.png?travis)](https://gemnasium.com/judofyr/temple) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/judofyr/temple)
|
5
|
+
|
4
6
|
Temple is an abstraction and a framework for compiling templates to pure Ruby.
|
5
7
|
It's all about making it easier to experiment, implement and optimize template
|
6
8
|
languages. If you're interested in implementing your own template language, or
|
data/lib/temple/engine.rb
CHANGED
@@ -56,19 +56,7 @@ module Temple
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def call_chain
|
59
|
-
@call_chain ||= @chain.map
|
60
|
-
name, filter, option_filter, local_options = e
|
61
|
-
case filter
|
62
|
-
when Class
|
63
|
-
filtered_options = Hash[*option_filter.select {|k| options.include?(k) }.map {|k| [k, options[k]] }.flatten]
|
64
|
-
filter.new(ImmutableHash.new(local_options, filtered_options))
|
65
|
-
when UnboundMethod
|
66
|
-
filter = filter.bind(self)
|
67
|
-
filter.arity == 1 ? filter : filter.call
|
68
|
-
else
|
69
|
-
filter
|
70
|
-
end
|
71
|
-
end.compact
|
59
|
+
@call_chain ||= @chain.map {|name, constructor| constructor.call(self) }.compact
|
72
60
|
end
|
73
61
|
end
|
74
62
|
end
|
@@ -8,8 +8,7 @@ module Temple
|
|
8
8
|
#
|
9
9
|
# Compiles to:
|
10
10
|
#
|
11
|
-
# [:
|
12
|
-
# [:static, "Hello World!"]]
|
11
|
+
# [:static, "Hello World!"]
|
13
12
|
#
|
14
13
|
# @api public
|
15
14
|
class StaticMerger < Filter
|
@@ -31,7 +30,7 @@ module Temple
|
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
34
|
-
result
|
33
|
+
result.size == 2 ? result[1] : result
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|
data/lib/temple/generators.rb
CHANGED
@@ -65,7 +65,7 @@ module Temple
|
|
65
65
|
# _buf = []
|
66
66
|
# _buf << "static"
|
67
67
|
# _buf << dynamic
|
68
|
-
# _buf
|
68
|
+
# _buf
|
69
69
|
#
|
70
70
|
# @api public
|
71
71
|
class Array < Generator
|
@@ -79,8 +79,25 @@ module Temple
|
|
79
79
|
end
|
80
80
|
|
81
81
|
# Just like Array, but calls #join on the array.
|
82
|
+
#
|
83
|
+
# _buf = []
|
84
|
+
# _buf << "static"
|
85
|
+
# _buf << dynamic
|
86
|
+
# _buf.join
|
87
|
+
#
|
82
88
|
# @api public
|
83
89
|
class ArrayBuffer < Array
|
90
|
+
def call(exp)
|
91
|
+
case exp.first
|
92
|
+
when :static
|
93
|
+
"#{buffer} = #{exp.last.inspect}"
|
94
|
+
when :dynamic
|
95
|
+
"#{buffer} = (#{exp.last}).to_s"
|
96
|
+
else
|
97
|
+
super
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
84
101
|
def postamble
|
85
102
|
"#{buffer} = #{buffer}.join"
|
86
103
|
end
|
@@ -94,11 +111,15 @@ module Temple
|
|
94
111
|
# _buf
|
95
112
|
#
|
96
113
|
# @api public
|
97
|
-
class StringBuffer <
|
114
|
+
class StringBuffer < ArrayBuffer
|
98
115
|
def preamble
|
99
116
|
"#{buffer} = ''"
|
100
117
|
end
|
101
118
|
|
119
|
+
def postamble
|
120
|
+
buffer
|
121
|
+
end
|
122
|
+
|
102
123
|
def on_dynamic(code)
|
103
124
|
concat("(#{code}).to_s")
|
104
125
|
end
|
@@ -106,7 +127,7 @@ module Temple
|
|
106
127
|
|
107
128
|
# Implements a rails output buffer.
|
108
129
|
#
|
109
|
-
# @output_buffer = ActionView::
|
130
|
+
# @output_buffer = ActionView::SafeBuffer
|
110
131
|
# @output_buffer.safe_concat "static"
|
111
132
|
# @output_buffer.safe_concat dynamic.to_s
|
112
133
|
# @output_buffer
|
@@ -118,6 +139,10 @@ module Temple
|
|
118
139
|
# output_buffer is needed for Rails 3.1 Streaming support
|
119
140
|
:capture_generator => RailsOutputBuffer
|
120
141
|
|
142
|
+
def call(exp)
|
143
|
+
[preamble, compile(exp), postamble].join('; ')
|
144
|
+
end
|
145
|
+
|
121
146
|
def preamble
|
122
147
|
if options[:streaming] && options[:buffer] == '@output_buffer'
|
123
148
|
"#{buffer} = output_buffer || #{options[:buffer_class]}.new"
|
data/lib/temple/grammar.rb
CHANGED
@@ -14,6 +14,10 @@ module Temple
|
|
14
14
|
[:html, :comment, compile(content)]
|
15
15
|
end
|
16
16
|
|
17
|
+
def on_html_condcomment(condition, content)
|
18
|
+
[:html, :condcomment, condition, compile(content)]
|
19
|
+
end
|
20
|
+
|
17
21
|
def on_html_tag(name, attrs, content = nil)
|
18
22
|
result = [:html, :tag, name, compile(attrs)]
|
19
23
|
content ? (result << compile(content)) : result
|
data/lib/temple/html/fast.rb
CHANGED
@@ -65,6 +65,13 @@ module Temple
|
|
65
65
|
[:static, '-->']]
|
66
66
|
end
|
67
67
|
|
68
|
+
def on_html_condcomment(condition, content)
|
69
|
+
on_html_comment [:multi,
|
70
|
+
[:static, "[#{condition}]>"],
|
71
|
+
content,
|
72
|
+
[:static, '<![endif]']]
|
73
|
+
end
|
74
|
+
|
68
75
|
def on_html_tag(name, attrs, content = nil)
|
69
76
|
name = name.to_s
|
70
77
|
closed = !content || (empty_exp?(content) && options[:autoclose].include?(name))
|
data/lib/temple/html/pretty.rb
CHANGED
@@ -6,7 +6,7 @@ module Temple
|
|
6
6
|
:pretty => true,
|
7
7
|
:indent_tags => %w(article aside audio base body datalist dd div dl dt
|
8
8
|
fieldset figure footer form head h1 h2 h3 h4 h5 h6
|
9
|
-
header hgroup hr html
|
9
|
+
header hgroup hr html li link meta nav ol p
|
10
10
|
rp rt ruby section script style table tbody td tfoot
|
11
11
|
th thead title tr ul video).freeze,
|
12
12
|
:pre_tags => %w(code pre textarea).freeze
|
@@ -60,15 +60,10 @@ module Temple
|
|
60
60
|
dispatched_methods.each do |method|
|
61
61
|
method.split('_')[1..-1].inject(tree) {|node, type| node[type.to_sym] }.method = method
|
62
62
|
end
|
63
|
-
self.class.class_eval %{
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
else
|
68
|
-
replace_dispatcher(exp)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
}
|
63
|
+
self.class.class_eval %{def dispatcher(exp)
|
64
|
+
return replace_dispatcher(exp) if self.class != #{self.class}
|
65
|
+
#{tree.compile.gsub("\n", "\n ")}
|
66
|
+
end}
|
72
67
|
dispatcher(exp)
|
73
68
|
end
|
74
69
|
|
@@ -86,31 +81,19 @@ module Temple
|
|
86
81
|
@method = nil
|
87
82
|
end
|
88
83
|
|
89
|
-
def compile(level = 0,
|
84
|
+
def compile(level = 0, call_parent = nil)
|
85
|
+
call_method = method ? (level == 0 ? "#{method}(*exp)" :
|
86
|
+
"#{method}(*exp[#{level}..-1])") : call_parent
|
90
87
|
if empty?
|
91
|
-
|
92
|
-
|
93
|
-
elsif !parent
|
94
|
-
'exp'
|
95
|
-
else
|
96
|
-
raise 'Invalid dispatcher node'
|
97
|
-
end
|
88
|
+
raise 'Invalid dispatcher node' unless method
|
89
|
+
call_method
|
98
90
|
else
|
99
|
-
code =
|
91
|
+
code = "case(exp[#{level}])\n"
|
100
92
|
each do |key, child|
|
101
|
-
code <<
|
102
|
-
|
103
|
-
end
|
104
|
-
if method || !parent
|
105
|
-
code << (' ' * level) + "else"
|
106
|
-
if method
|
107
|
-
code << (' ' * level) + " #{method}(*exp[#{level}..-1])"
|
108
|
-
else
|
109
|
-
code << (' ' * level) + " exp"
|
110
|
-
end
|
93
|
+
code << "when #{key.inspect}\n " <<
|
94
|
+
child.compile(level + 1, call_method).gsub("\n", "\n ") << "\n"
|
111
95
|
end
|
112
|
-
code << ('
|
113
|
-
code.join("\n")
|
96
|
+
code << "else\n " << (call_method || 'exp') << "\nend"
|
114
97
|
end
|
115
98
|
end
|
116
99
|
end
|
@@ -6,21 +6,24 @@ module Temple
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def append(*args, &block)
|
9
|
-
chain <<
|
9
|
+
chain << chain_element(args, block)
|
10
10
|
chain_modified!
|
11
11
|
end
|
12
12
|
|
13
13
|
def prepend(*args, &block)
|
14
|
-
chain.unshift(
|
14
|
+
chain.unshift(chain_element(args, block))
|
15
15
|
chain_modified!
|
16
16
|
end
|
17
17
|
|
18
18
|
def remove(name)
|
19
|
+
name = chain_name(name)
|
19
20
|
found = false
|
20
21
|
chain.reject! do |i|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
if i.first == name
|
23
|
+
found = true
|
24
|
+
else
|
25
|
+
false
|
26
|
+
end
|
24
27
|
end
|
25
28
|
raise "#{name} not found" unless found
|
26
29
|
chain_modified!
|
@@ -28,20 +31,9 @@ module Temple
|
|
28
31
|
|
29
32
|
alias use append
|
30
33
|
|
31
|
-
# DEPRECATED!
|
32
|
-
#
|
33
|
-
# wildcard(:FilterName) { FilterClass.new(options) }
|
34
|
-
#
|
35
|
-
# is replaced by
|
36
|
-
#
|
37
|
-
# use(:FilterName) { FilterClass.new(options) }
|
38
|
-
#
|
39
|
-
alias wildcard use
|
40
|
-
|
41
34
|
def before(name, *args, &block)
|
42
|
-
name =
|
43
|
-
|
44
|
-
e = element(args, block)
|
35
|
+
name = chain_name(name)
|
36
|
+
e = chain_element(args, block)
|
45
37
|
found, i = false, 0
|
46
38
|
while i < chain.size
|
47
39
|
if chain[i].first == name
|
@@ -57,9 +49,8 @@ module Temple
|
|
57
49
|
end
|
58
50
|
|
59
51
|
def after(name, *args, &block)
|
60
|
-
name =
|
61
|
-
|
62
|
-
e = element(args, block)
|
52
|
+
name = chain_name(name)
|
53
|
+
e = chain_element(args, block)
|
63
54
|
found, i = false, 0
|
64
55
|
while i < chain.size
|
65
56
|
if chain[i].first == name
|
@@ -74,9 +65,8 @@ module Temple
|
|
74
65
|
end
|
75
66
|
|
76
67
|
def replace(name, *args, &block)
|
77
|
-
name =
|
78
|
-
|
79
|
-
e = element(args, block)
|
68
|
+
name = chain_name(name)
|
69
|
+
e = chain_element(args, block)
|
80
70
|
found = false
|
81
71
|
chain.each_with_index do |c, i|
|
82
72
|
if c.first == name
|
@@ -99,23 +89,55 @@ module Temple
|
|
99
89
|
|
100
90
|
private
|
101
91
|
|
102
|
-
def
|
92
|
+
def chain_name(name)
|
93
|
+
name = Class === name ? name.name.to_sym : name
|
94
|
+
raise(ArgumentError, 'Name argument must be Class or Symbol') unless Symbol === name
|
95
|
+
name
|
96
|
+
end
|
97
|
+
|
98
|
+
def chain_class_constructor(filter, option_filter)
|
99
|
+
local_options = Hash === option_filter.last ? option_filter.pop : nil
|
100
|
+
raise(ArgumentError, 'Only symbols allowed in option filter') unless option_filter.all? {|o| Symbol === o }
|
101
|
+
proc do |engine|
|
102
|
+
filtered_options = Hash[*option_filter.select {|k| engine.options.include?(k) }.map {|k| [k, engine.options[k]] }.flatten]
|
103
|
+
filter.new(ImmutableHash.new(local_options, filtered_options))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def chain_proc_constructor(name, filter)
|
108
|
+
raise(ArgumentError, 'Proc or blocks must have arity 0 or 1') if filter.arity > 1
|
109
|
+
method_name = "FILTER #{name}"
|
103
110
|
if Class === self
|
104
|
-
define_method(
|
105
|
-
instance_method(
|
111
|
+
define_method(method_name, &filter)
|
112
|
+
filter = instance_method(method_name)
|
113
|
+
if filter.arity == 1
|
114
|
+
proc {|engine| filter.bind(engine) }
|
115
|
+
else
|
116
|
+
proc do |engine|
|
117
|
+
f = filter.bind(engine).call
|
118
|
+
raise 'Constructor must return callable object' unless f.respond_to?(:call)
|
119
|
+
f
|
120
|
+
end
|
121
|
+
end
|
106
122
|
else
|
107
|
-
(class << self; self; end).class_eval { define_method(
|
108
|
-
method(
|
123
|
+
(class << self; self; end).class_eval { define_method(method_name, &filter) }
|
124
|
+
filter = method(method_name)
|
125
|
+
proc {|engine| filter }
|
109
126
|
end
|
110
127
|
end
|
111
128
|
|
112
|
-
def
|
129
|
+
def chain_callable_constructor(filter)
|
130
|
+
raise(ArgumentError, 'Class or callable argument is required') unless filter.respond_to?(:call)
|
131
|
+
proc {|engine| filter }
|
132
|
+
end
|
133
|
+
|
134
|
+
def chain_element(args, block)
|
113
135
|
name = args.shift
|
114
136
|
if Class === name
|
115
137
|
filter = name
|
116
138
|
name = filter.name.to_sym
|
117
139
|
else
|
118
|
-
raise(ArgumentError, '
|
140
|
+
raise(ArgumentError, 'Name argument must be Class or Symbol') unless Symbol === name
|
119
141
|
end
|
120
142
|
|
121
143
|
if block
|
@@ -131,20 +153,16 @@ module Temple
|
|
131
153
|
# The proc is converted to a method of the engine class.
|
132
154
|
# The proc can then access the option hash of the engine.
|
133
155
|
raise(ArgumentError, 'Too many arguments') unless args.empty?
|
134
|
-
|
135
|
-
[name, define_chain_method("FILTER #{name}", filter)]
|
156
|
+
[name, chain_proc_constructor(name, filter)]
|
136
157
|
when Class
|
137
158
|
# Class argument (e.g Filter class)
|
138
159
|
# The options are passed to the classes constructor.
|
139
|
-
|
140
|
-
raise(ArgumentError, 'Only symbols allowed in option filter') unless args.all? {|o| Symbol === o }
|
141
|
-
[name, filter, args, local_options]
|
160
|
+
[name, chain_class_constructor(filter, args)]
|
142
161
|
else
|
143
162
|
# Other callable argument (e.g. Object of class which implements #call or Method)
|
144
163
|
# The callable has no access to the option hash of the engine.
|
145
164
|
raise(ArgumentError, 'Too many arguments') unless args.empty?
|
146
|
-
|
147
|
-
[name, filter]
|
165
|
+
[name, chain_callable_constructor(filter)]
|
148
166
|
end
|
149
167
|
end
|
150
168
|
end
|
@@ -33,7 +33,7 @@ module Temple
|
|
33
33
|
|
34
34
|
def match(exp, unmatched)
|
35
35
|
tmp = []
|
36
|
-
@children.any? {|rule| rule.match(exp, tmp) } || (unmatched.
|
36
|
+
@children.any? {|rule| rule.match(exp, tmp) } || (unmatched.concat(tmp) && false)
|
37
37
|
end
|
38
38
|
|
39
39
|
def after_copy(source)
|
@@ -9,6 +9,23 @@ module Temple
|
|
9
9
|
default_options[:engine]
|
10
10
|
end
|
11
11
|
|
12
|
+
def init
|
13
|
+
# Overwrite this for class initialization
|
14
|
+
end
|
15
|
+
|
16
|
+
def register_as(name)
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
def create(engine, options)
|
21
|
+
template = Class.new(self)
|
22
|
+
template.default_options[:engine] = engine
|
23
|
+
template.default_options.update(options)
|
24
|
+
template.init
|
25
|
+
template.register_as(options[:register_as]) if options[:register_as]
|
26
|
+
template
|
27
|
+
end
|
28
|
+
|
12
29
|
def build_engine(*options)
|
13
30
|
raise 'No engine configured' unless engine
|
14
31
|
options << default_options
|
data/lib/temple/templates.rb
CHANGED
@@ -5,11 +5,7 @@ module Temple
|
|
5
5
|
autoload :Rails, 'temple/templates/rails'
|
6
6
|
|
7
7
|
def self.method_missing(name, engine, options = {})
|
8
|
-
|
9
|
-
template.default_options[:engine] = engine
|
10
|
-
template.default_options.update(options)
|
11
|
-
template.register_as(options[:register_as]) if options[:register_as]
|
12
|
-
template
|
8
|
+
const_get(name).create(engine, options)
|
13
9
|
end
|
14
10
|
end
|
15
11
|
end
|
data/lib/temple/version.rb
CHANGED
@@ -10,7 +10,7 @@ describe Temple::Filters::DynamicInliner do
|
|
10
10
|
[:static, "Hello "],
|
11
11
|
[:static, "World\n "],
|
12
12
|
[:static, "Have a nice day"]
|
13
|
-
]).should.equal [:
|
13
|
+
]).should.equal [:dynamic, '"Hello World\n Have a nice day"']
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'should compile several dynamics into dynamic' do
|
@@ -18,7 +18,7 @@ describe Temple::Filters::DynamicInliner do
|
|
18
18
|
[:dynamic, "@hello"],
|
19
19
|
[:dynamic, "@world"],
|
20
20
|
[:dynamic, "@yeah"]
|
21
|
-
]).should.equal [:
|
21
|
+
]).should.equal [:dynamic, '"#{@hello}#{@world}#{@yeah}"']
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'should compile static and dynamic into dynamic' do
|
@@ -27,7 +27,7 @@ describe Temple::Filters::DynamicInliner do
|
|
27
27
|
[:dynamic, "@world"],
|
28
28
|
[:dynamic, "@yeah"],
|
29
29
|
[:static, "Nice"]
|
30
|
-
]).should.equal [:
|
30
|
+
]).should.equal [:dynamic, '"Hello#{@world}#{@yeah}Nice"']
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'should merge statics and dynamics around a code' do
|
@@ -45,18 +45,15 @@ describe Temple::Filters::DynamicInliner do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'should keep codes intact' do
|
48
|
-
|
49
|
-
@filter.call(exp).should.equal exp
|
48
|
+
@filter.call([:multi, [:code, 'foo']]).should.equal [:code, 'foo']
|
50
49
|
end
|
51
50
|
|
52
51
|
it 'should keep single statics intact' do
|
53
|
-
|
54
|
-
@filter.call(exp).should.equal exp
|
52
|
+
@filter.call([:multi, [:static, 'foo']]).should.equal [:static, 'foo']
|
55
53
|
end
|
56
54
|
|
57
55
|
it 'should keep single dynamic intact' do
|
58
|
-
|
59
|
-
@filter.call(exp).should.equal exp
|
56
|
+
@filter.call([:multi, [:dynamic, 'foo']]).should.equal [:dynamic, 'foo']
|
60
57
|
end
|
61
58
|
|
62
59
|
it 'should inline inside multi' do
|
@@ -70,7 +67,7 @@ describe Temple::Filters::DynamicInliner do
|
|
70
67
|
[:dynamic, "@world"]
|
71
68
|
]).should.equal [:multi,
|
72
69
|
[:dynamic, '"Hello #{@world}"'],
|
73
|
-
[:
|
70
|
+
[:dynamic, '"Hello #{@world}"'],
|
74
71
|
[:dynamic, '"Hello #{@world}"']
|
75
72
|
]
|
76
73
|
end
|
@@ -81,9 +78,7 @@ describe Temple::Filters::DynamicInliner do
|
|
81
78
|
[:newline],
|
82
79
|
[:dynamic, "@world"],
|
83
80
|
[:newline]
|
84
|
-
]).should.equal [:
|
85
|
-
[:dynamic, ['"Hello \n"', '"#{@world}"', '""'].join("\\\n")]
|
86
|
-
]
|
81
|
+
]).should.equal [:dynamic, ['"Hello \n"', '"#{@world}"', '""'].join("\\\n")]
|
87
82
|
end
|
88
83
|
|
89
84
|
it 'should compile static followed by newline' do
|
@@ -10,9 +10,7 @@ describe Temple::Filters::StaticMerger do
|
|
10
10
|
[:static, "Hello "],
|
11
11
|
[:static, "World, "],
|
12
12
|
[:static, "Good night"]
|
13
|
-
]).should.equal [:
|
14
|
-
[:static, "Hello World, Good night"]
|
15
|
-
]
|
13
|
+
]).should.equal [:static, "Hello World, Good night"]
|
16
14
|
end
|
17
15
|
|
18
16
|
it 'should merge serveral statics around code' do
|
@@ -15,8 +15,16 @@ class FilterWithDispatcherMixin
|
|
15
15
|
[:on_second_test, arg]
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
[:
|
18
|
+
def on_a_b(*arg)
|
19
|
+
[:on_ab, *arg]
|
20
|
+
end
|
21
|
+
|
22
|
+
def on_a_b_test(arg)
|
23
|
+
[:on_ab_test, arg]
|
24
|
+
end
|
25
|
+
|
26
|
+
def on_a_b_c_d_test(arg)
|
27
|
+
[:on_abcd_test, arg]
|
20
28
|
end
|
21
29
|
end
|
22
30
|
|
@@ -47,8 +55,13 @@ describe Temple::Mixins::Dispatcher do
|
|
47
55
|
@filter.call([:test, :check, 42]).should.equal [:on_check, 42]
|
48
56
|
end
|
49
57
|
|
50
|
-
it 'should dispatch
|
51
|
-
@filter.call([:
|
58
|
+
it 'should dispatch parent level' do
|
59
|
+
@filter.call([:a, 42]).should == [:a, 42]
|
60
|
+
@filter.call([:a, :b, 42]).should == [:on_ab, 42]
|
61
|
+
@filter.call([:a, :b, :test, 42]).should == [:on_ab_test, 42]
|
62
|
+
@filter.call([:a, :b, :c, 42]).should == [:on_ab, :c, 42]
|
63
|
+
@filter.call([:a, :b, :c, :d, 42]).should == [:on_ab, :c, :d, 42]
|
64
|
+
@filter.call([:a, :b, :c, :d, :test, 42]).should == [:on_abcd_test, 42]
|
52
65
|
end
|
53
66
|
|
54
67
|
it 'should dispatch zero level' do
|
data/test/test_engine.rb
CHANGED
@@ -32,32 +32,35 @@ describe Temple::Engine do
|
|
32
32
|
|
33
33
|
TestEngine.chain[0].first.should.equal :Parser
|
34
34
|
TestEngine.chain[0].size.should.equal 2
|
35
|
-
TestEngine.chain[0].last.should.be.instance_of
|
35
|
+
TestEngine.chain[0].last.should.be.instance_of Proc
|
36
36
|
|
37
37
|
TestEngine.chain[1].first.should.equal :MyFilter1
|
38
38
|
TestEngine.chain[1].size.should.equal 2
|
39
|
-
TestEngine.chain[1].last.should.be.instance_of
|
39
|
+
TestEngine.chain[1].last.should.be.instance_of Proc
|
40
40
|
|
41
41
|
TestEngine.chain[2].first.should.equal :MyFilter2
|
42
42
|
TestEngine.chain[2].size.should.equal 2
|
43
|
-
TestEngine.chain[2].last.should.be.instance_of
|
43
|
+
TestEngine.chain[2].last.should.be.instance_of Proc
|
44
44
|
|
45
|
-
TestEngine.chain[3].
|
46
|
-
TestEngine.chain[3].should.equal
|
45
|
+
TestEngine.chain[3].first.should.equal :'Temple::HTML::Pretty'
|
46
|
+
TestEngine.chain[3].size.should.equal 2
|
47
|
+
TestEngine.chain[3].last.should.be.instance_of Proc
|
47
48
|
|
48
|
-
TestEngine.chain[4].
|
49
|
-
TestEngine.chain[4].should.equal
|
49
|
+
TestEngine.chain[4].first.should.equal :MultiFlattener
|
50
|
+
TestEngine.chain[4].size.should.equal 2
|
51
|
+
TestEngine.chain[4].last.should.be.instance_of Proc
|
50
52
|
|
51
|
-
TestEngine.chain[5].
|
52
|
-
TestEngine.chain[5].should.equal
|
53
|
+
TestEngine.chain[5].first.should.equal :ArrayBuffer
|
54
|
+
TestEngine.chain[5].size.should.equal 2
|
55
|
+
TestEngine.chain[5].last.should.be.instance_of Proc
|
53
56
|
|
57
|
+
TestEngine.chain[6].first.should.equal :BeforeLast
|
54
58
|
TestEngine.chain[6].size.should.equal 2
|
55
|
-
TestEngine.chain[6]
|
56
|
-
TestEngine.chain[6][1].should.be.instance_of Callable1
|
59
|
+
TestEngine.chain[6].last.should.be.instance_of Proc
|
57
60
|
|
61
|
+
TestEngine.chain[7].first.should.equal :Last
|
58
62
|
TestEngine.chain[7].size.should.equal 2
|
59
|
-
TestEngine.chain[7]
|
60
|
-
TestEngine.chain[7][1].should.be.instance_of UnboundMethod
|
63
|
+
TestEngine.chain[7].last.should.be.instance_of Proc
|
61
64
|
end
|
62
65
|
|
63
66
|
it 'should instantiate chain' do
|
@@ -85,7 +88,7 @@ describe Temple::Engine do
|
|
85
88
|
engine.chain.size.should.equal 9
|
86
89
|
engine.chain[8].first.should.equal :MyFilter3
|
87
90
|
engine.chain[8].size.should.equal 2
|
88
|
-
engine.chain[8].last.should.be.instance_of
|
91
|
+
engine.chain[8].last.should.be.instance_of Proc
|
89
92
|
|
90
93
|
call_chain = engine.send(:call_chain)
|
91
94
|
call_chain.size.should.equal 9
|
@@ -105,7 +108,7 @@ describe Temple::Engine do
|
|
105
108
|
engine.chain.size.should.equal 9
|
106
109
|
engine.chain[0].first.should.equal :MyFilter0
|
107
110
|
engine.chain[0].size.should.equal 2
|
108
|
-
engine.chain[0].last.should.be.instance_of
|
111
|
+
engine.chain[0].last.should.be.instance_of Proc
|
109
112
|
engine.chain[1].first.should.equal :Parser
|
110
113
|
|
111
114
|
call_chain = engine.send(:call_chain)
|
data/test/test_generator.rb
CHANGED
@@ -81,24 +81,33 @@ describe Temple::Generators::Array do
|
|
81
81
|
gen.call([:static, 'test']).should.equal '_buf = []; _buf << ("test"); _buf'
|
82
82
|
gen.call([:dynamic, 'test']).should.equal '_buf = []; _buf << (test); _buf'
|
83
83
|
gen.call([:code, 'test']).should.equal '_buf = []; test; _buf'
|
84
|
+
|
85
|
+
gen.call([:multi, [:static, 'a'], [:static, 'b']]).should.equal '_buf = []; _buf << ("a"); _buf << ("b"); _buf'
|
86
|
+
gen.call([:multi, [:static, 'a'], [:dynamic, 'b']]).should.equal '_buf = []; _buf << ("a"); _buf << (b); _buf'
|
84
87
|
end
|
85
88
|
end
|
86
89
|
|
87
90
|
describe Temple::Generators::ArrayBuffer do
|
88
91
|
it 'should compile simple expressions' do
|
89
92
|
gen = Temple::Generators::ArrayBuffer.new
|
90
|
-
gen.call([:static, 'test']).should.equal '_buf =
|
91
|
-
gen.call([:dynamic, 'test']).should.equal '_buf =
|
93
|
+
gen.call([:static, 'test']).should.equal '_buf = "test"'
|
94
|
+
gen.call([:dynamic, 'test']).should.equal '_buf = (test).to_s'
|
92
95
|
gen.call([:code, 'test']).should.equal '_buf = []; test; _buf = _buf.join'
|
96
|
+
|
97
|
+
gen.call([:multi, [:static, 'a'], [:static, 'b']]).should.equal '_buf = []; _buf << ("a"); _buf << ("b"); _buf = _buf.join'
|
98
|
+
gen.call([:multi, [:static, 'a'], [:dynamic, 'b']]).should.equal '_buf = []; _buf << ("a"); _buf << (b); _buf = _buf.join'
|
93
99
|
end
|
94
100
|
end
|
95
101
|
|
96
102
|
describe Temple::Generators::StringBuffer do
|
97
103
|
it 'should compile simple expressions' do
|
98
104
|
gen = Temple::Generators::StringBuffer.new
|
99
|
-
gen.call([:static, 'test']).should.equal '_buf =
|
100
|
-
gen.call([:dynamic, 'test']).should.equal '_buf =
|
105
|
+
gen.call([:static, 'test']).should.equal '_buf = "test"'
|
106
|
+
gen.call([:dynamic, 'test']).should.equal '_buf = (test).to_s'
|
101
107
|
gen.call([:code, 'test']).should.equal '_buf = \'\'; test; _buf'
|
108
|
+
|
109
|
+
gen.call([:multi, [:static, 'a'], [:static, 'b']]).should.equal '_buf = \'\'; _buf << ("a"); _buf << ("b"); _buf'
|
110
|
+
gen.call([:multi, [:static, 'a'], [:dynamic, 'b']]).should.equal '_buf = \'\'; _buf << ("a"); _buf << ((b).to_s); _buf'
|
102
111
|
end
|
103
112
|
end
|
104
113
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: temple
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-09-04 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: tilt
|
17
|
-
requirement:
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,15 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements:
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
26
31
|
- !ruby/object:Gem::Dependency
|
27
32
|
name: bacon
|
28
|
-
requirement:
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
29
34
|
none: false
|
30
35
|
requirements:
|
31
36
|
- - ! '>='
|
@@ -33,10 +38,15 @@ dependencies:
|
|
33
38
|
version: '0'
|
34
39
|
type: :development
|
35
40
|
prerelease: false
|
36
|
-
version_requirements:
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
37
47
|
- !ruby/object:Gem::Dependency
|
38
48
|
name: rake
|
39
|
-
requirement:
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
40
50
|
none: false
|
41
51
|
requirements:
|
42
52
|
- - ! '>='
|
@@ -44,7 +54,12 @@ dependencies:
|
|
44
54
|
version: '0'
|
45
55
|
type: :development
|
46
56
|
prerelease: false
|
47
|
-
version_requirements:
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
48
63
|
description:
|
49
64
|
email:
|
50
65
|
- judofyr@gmail.com
|
@@ -138,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
153
|
version: '0'
|
139
154
|
requirements: []
|
140
155
|
rubyforge_project:
|
141
|
-
rubygems_version: 1.8.
|
156
|
+
rubygems_version: 1.8.24
|
142
157
|
signing_key:
|
143
158
|
specification_version: 3
|
144
159
|
summary: Template compilation framework in Ruby
|
@@ -164,3 +179,4 @@ test_files:
|
|
164
179
|
- test/test_grammar.rb
|
165
180
|
- test/test_hash.rb
|
166
181
|
- test/test_utils.rb
|
182
|
+
has_rdoc:
|