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 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,
@@ -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
@@ -56,19 +56,7 @@ module Temple
56
56
  end
57
57
 
58
58
  def call_chain
59
- @call_chain ||= @chain.map do |e|
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
@@ -64,7 +64,7 @@ module Temple
64
64
  result.concat(prev) if state == :single
65
65
  end
66
66
 
67
- result
67
+ result.size == 2 ? result[1] : result
68
68
  end
69
69
  end
70
70
  end
@@ -8,8 +8,7 @@ module Temple
8
8
  #
9
9
  # Compiles to:
10
10
  #
11
- # [:multi,
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
@@ -65,7 +65,7 @@ module Temple
65
65
  # _buf = []
66
66
  # _buf << "static"
67
67
  # _buf << dynamic
68
- # _buf.join
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 < Array
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::OutputBuffer
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"
@@ -29,6 +29,7 @@ module Temple
29
29
  # HTML abstraction
30
30
  [:html, :doctype, String] |
31
31
  [:html, :comment, Expression] |
32
+ [:html, :condcomment, String, Expression]|
32
33
  [:html, :tag, HTMLIdentifier, Expression, 'Expression?'] |
33
34
  [:html, :attrs, 'HTMLAttr*'] |
34
35
  HTMLAttr
@@ -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
@@ -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))
@@ -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 input li link meta nav ol p
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
- def dispatcher(exp)
65
- if self.class == #{self.class}
66
- #{tree.compile}
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, parent = nil)
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
- if method
92
- (' ' * level) + "#{method}(*exp[#{level}..-1])"
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 = [(' ' * level) + "case(exp[#{level}])"]
91
+ code = "case(exp[#{level}])\n"
100
92
  each do |key, child|
101
- code << (' ' * level) + "when #{key.inspect}"
102
- code << child.compile(level + 1, parent || method)
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 << (' ' * level) + "end"
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 << element(args, block)
9
+ chain << chain_element(args, block)
10
10
  chain_modified!
11
11
  end
12
12
 
13
13
  def prepend(*args, &block)
14
- chain.unshift(element(args, block))
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
- equal = i.first == name
22
- found = true if equal
23
- equal
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 = Class === name ? name.name.to_sym : name
43
- raise(ArgumentError, 'First argument must be Class or Symbol') unless Symbol === name
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 = Class === name ? name.name.to_sym : name
61
- raise(ArgumentError, 'First argument must be Class or Symbol') unless Symbol === name
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 = Class === name ? name.name.to_sym : name
78
- raise(ArgumentError, 'First argument must be Class or Symbol') unless Symbol === name
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 define_chain_method(name, proc)
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(name, &proc)
105
- instance_method(name)
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(name, &proc) }
108
- method(name)
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 element(args, block)
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, 'First argument must be Class or Symbol') unless Symbol === name
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
- raise(ArgumentError, 'Proc or blocks must have arity 0 or 1') if filter.arity > 1
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
- local_options = Hash === args.last ? args.pop : nil
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
- raise(ArgumentError, 'Class or callable argument is required') unless filter.respond_to?(:call)
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.push(*tmp) && false)
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
@@ -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
- template = Class.new(const_get(name))
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
@@ -23,6 +23,10 @@ module Temple
23
23
  @src
24
24
  end
25
25
 
26
+ def self.init
27
+ self.default_mime_type = default_options[:mime_type] || 'text/html'
28
+ end
29
+
26
30
  def self.register_as(name)
27
31
  ::Tilt.register name.to_s, self
28
32
  end
@@ -1,3 +1,3 @@
1
1
  module Temple
2
- VERSION = '0.4.0'
2
+ VERSION = '0.4.1'
3
3
  end
@@ -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 [:multi, [:dynamic, '"Hello World\n Have a nice day"']]
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 [:multi, [:dynamic, '"#{@hello}#{@world}#{@yeah}"']]
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 [:multi, [:dynamic, '"Hello#{@world}#{@yeah}Nice"']]
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
- exp = [:multi, [:code, 'foo']]
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
- exp = [:multi, [:static, 'foo']]
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
- exp = [:multi, [:dynamic, 'foo']]
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
- [:multi, [:dynamic, '"Hello #{@world}"']],
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 [:multi,
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 [:multi,
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 on_seventh_level_level_level_level_level_test(arg)
19
- [:on_seventh_test, arg]
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 seventh level' do
51
- @filter.call([:seventh, :level, :level, :level, :level, :level, :test, 42]).should == [:on_seventh_test, 42]
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
@@ -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 UnboundMethod
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 UnboundMethod
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 UnboundMethod
43
+ TestEngine.chain[2].last.should.be.instance_of Proc
44
44
 
45
- TestEngine.chain[3].size.should.equal 4
46
- TestEngine.chain[3].should.equal [:'Temple::HTML::Pretty', Temple::HTML::Pretty, [:format], {:pretty => true}]
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].size.should.equal 4
49
- TestEngine.chain[4].should.equal [:MultiFlattener, Temple::Filters::MultiFlattener, [], nil]
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].size.should.equal 4
52
- TestEngine.chain[5].should.equal [:ArrayBuffer, Temple::Generators::ArrayBuffer, [], nil]
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][0].should.equal :BeforeLast
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][0].should.equal :Last
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 Method
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 Method
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)
@@ -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 = []; _buf << ("test"); _buf = _buf.join'
91
- gen.call([:dynamic, 'test']).should.equal '_buf = []; _buf << (test); _buf = _buf.join'
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 = \'\'; _buf << ("test"); _buf'
100
- gen.call([:dynamic, 'test']).should.equal '_buf = \'\'; _buf << ((test).to_s); _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.0
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-02-26 00:00:00.000000000 Z
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: &18003800 !ruby/object:Gem::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: *18003800
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: &18002180 !ruby/object:Gem::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: *18002180
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: &18000780 !ruby/object:Gem::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: *18000780
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.15
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: