handlebar 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
data/handlebar.gemspec ADDED
@@ -0,0 +1,62 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{handlebar}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Scott Tadman"]
12
+ s.date = %q{2011-06-30}
13
+ s.description = %q{A simple text templating system}
14
+ s.email = %q{github@tadman.ca}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "handlebar.gemspec",
28
+ "lib/handlebar.rb",
29
+ "lib/handlebar/support.rb",
30
+ "lib/handlebar/template.rb",
31
+ "notes/example.hb",
32
+ "test/helper.rb",
33
+ "test/test_handlebar.rb",
34
+ "test/test_handlebar_template.rb"
35
+ ]
36
+ s.homepage = %q{http://github.com/twg/handlebar}
37
+ s.licenses = ["MIT"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.5.3}
40
+ s.summary = %q{Simple text tempating system}
41
+ s.test_files = [
42
+ "test/helper.rb",
43
+ "test/test_handlebar.rb",
44
+ "test/test_handlebar_template.rb"
45
+ ]
46
+
47
+ if s.respond_to? :specification_version then
48
+ s.specification_version = 3
49
+
50
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
51
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
52
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
53
+ else
54
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
55
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
56
+ end
57
+ else
58
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
59
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
60
+ end
61
+ end
62
+
@@ -4,6 +4,18 @@ class Handlebar::Template
4
4
  TOKEN_REGEXP = /((?:[^\{]|\{[^\{]|\{\{\{)+)|\{\{\s*([\&\%\$\.\:\?\*\/\=])?([^\}]*)\}\}/.freeze
5
5
  TOKEN_TRIGGER = /\{\{/.freeze
6
6
 
7
+ # == Utility Classes ======================================================
8
+
9
+ class TemplateHash < Hash; end
10
+
11
+ class VariableTracker < Hash
12
+ def initialize
13
+ super do |h, k|
14
+ h[k] = h.length
15
+ end
16
+ end
17
+ end
18
+
7
19
  # == Exceptions ===========================================================
8
20
 
9
21
  class ParseError < Exception ; end
@@ -15,8 +27,20 @@ class Handlebar::Template
15
27
 
16
28
  # == Instance Methods =====================================================
17
29
 
18
- def initialize(content, context = nil)
19
- @context = context
30
+ def initialize(content, options = nil)
31
+ if (options)
32
+ if (source = options[:escape])
33
+ case (source.to_sym)
34
+ when :html, :html_escape
35
+ @escape_method = :html_escape
36
+ when :text, nil
37
+ # Default, ignored
38
+ else
39
+ raise ArgumentError, "Unknown escape source #{source}"
40
+ end
41
+ end
42
+ end
43
+
20
44
  @content =
21
45
  case (content)
22
46
  when IO
@@ -25,102 +49,18 @@ class Handlebar::Template
25
49
  content.to_s
26
50
  end
27
51
  end
28
-
52
+
29
53
  def to_proc
30
- @proc ||= begin
31
- method = ''
32
- variables = nil
33
- stack = [ [ :base, nil, 0 ] ]
34
- h = Handlebar::Support
35
-
36
- @content.scan(TOKEN_REGEXP).each do |text, tag_type, tag|
37
- if (text)
38
- text = text.sub(/\{(\{\{+)/, '\1').sub(/\}(\}\}+)/, '\1')
39
-
40
- method << "r<<#{text.inspect};"
41
- else
42
- tag = tag.strip
43
-
44
- case (tag_type)
45
- when ?&
46
- # HTML escaped
47
- method << "v&&r<<h.html_escape(v[#{tag.to_sym.inspect}].to_s);"
48
- when ?%
49
- # URI escaped
50
- method << "v&&r<<h.uri_escape(v[#{tag.to_sym.inspect}].to_s);"
51
- when ?$
52
- # JavaScript escaped
53
- method << "v&&r<<h.js_escape(v[#{tag.to_sym.inspect}].to_s);"
54
- when ?.
55
- # CSS escaped
56
- method << "v&&r<<h.css_escape(v[#{tag.to_sym.inspect}].to_s);"
57
- when ?:
58
- # Defines start of a :section
59
- variables ||= 's=[];'
60
- stack << [ :section, tag, 0 ]
61
- method << "if(v);s<<v;v=v.is_a?(Hash)&&v[#{tag.to_sym.inspect}];"
62
- method << "h.iterate(v){|v|;v=h.cast_as_vars(v, s);"
63
- when ??
64
- # Defines start of a ?conditional
65
- stack << [ :conditional, tag ]
66
- method << "if(v&&v.is_a?(Hash)&&v[#{tag.to_sym.inspect}]);"
67
- when ?*
68
- method << "_t=t&&t[#{tag.to_sym.inspect}];r<<(_t.respond_to?(:call)?_t.call(v,t):_t.to_s);"
69
- when ?/
70
- # Closes out a section or conditional
71
- closed = stack.pop
72
-
73
- case (closed[0])
74
- when :section
75
- unless (tag == closed[1] or tag.empty?)
76
- raise ParseError, "Template contains unexpected {{#{tag}}}, expected {{#{closed[1]}}}"
77
- end
54
+ @_proc ||= begin
55
+ source = ''
78
56
 
79
- method << "};v=s.pop;end;"
80
- when :conditional
81
- method << "end;"
82
- when :base
83
- raise ParseError, "Unexpected {{#{tag}}}, too many tags closed"
84
- end
85
- when ?=
86
- # Literal insertion
87
- method << "v&&r<<(v.is_a?(Array)?v[#{stack[-1][2]}]:v[#{tag.to_sym.inspect}]).to_s;"
88
-
89
- stack[-1][2] += 1
90
- else
91
- # Contextual insertion
92
- subst = "v.is_a?(Array)?v[#{stack[-1][2]}]:v[#{tag.to_sym.inspect}]"
93
-
94
- if (@context)
95
- method << "v&&r<<h.#{@context}_escape(#{subst}.to_s);"
96
- else
97
- method << "v&&r<<(#{subst}).to_s;"
98
- end
99
-
100
- stack[-1][2] += 1
101
- end
102
- end
103
- end
104
-
105
- unless (stack.length == 1)
106
- case (stack[1][0])
107
- when :section
108
- raise ParseError, "Unclosed {{:#{stack[1][1]}}} in template"
109
- when :conditional
110
- raise ParseError, "Unclosed {{?#{stack[1][1]}}} in template"
111
- else
112
- raise ParseError, "Unclosed {{#{stack[1][1]}}} in template"
113
- end
114
- end
115
-
116
- c = false
117
- source = "lambda{|v,t|raise RecursionError if(c);c=true;#{variables}r='';#{method}c=false;r}"
57
+ self.compile(:source => source, :escape_method => @escape_method)
118
58
 
119
59
  eval(source)
120
60
  end
121
61
  end
122
62
 
123
- def interpret(variables = nil, templates = nil)
63
+ def render(variables = nil, templates = nil, parents = nil)
124
64
  variables =
125
65
  case (variables)
126
66
  when Array
@@ -132,24 +72,205 @@ class Handlebar::Template
132
72
  end
133
73
 
134
74
  if (templates)
135
- templates = Hash[
136
- templates.collect do |k, v|
137
- [
138
- k,
139
- case (v)
140
- when Handlebar::Template, Proc
141
- v
142
- when TOKEN_TRIGGER
143
- self.class.new(v)
144
- else
145
- v.to_s
75
+ # Unless the template options have already been processed, mapping
76
+ # will need to be performed.
77
+ unless (templates.is_a?(TemplateHash))
78
+ templates = TemplateHash[
79
+ templates.collect do |k, v|
80
+ [
81
+ k,
82
+ case (v)
83
+ when Handlebar::Template, Proc, Array
84
+ v
85
+ when TOKEN_TRIGGER
86
+ self.class.new(v, :escape => @escape_method)
87
+ else
88
+ v.to_s
89
+ end
90
+ ]
91
+ end
92
+ ]
93
+ end
94
+ else
95
+ templates = TemplateHash.new
96
+ end
97
+
98
+ if (parents)
99
+ case (parents)
100
+ when Array
101
+ _parents = parents.dup
102
+ _parent = _parents.shift
103
+ _parent.render(
104
+ variables,
105
+ templates.merge(
106
+ nil => self.to_proc.call(variables, templates)
107
+ ),
108
+ _parents.empty? ? nil : _parents
109
+ )
110
+ when Handlebar::Template, Proc
111
+ parents.render(
112
+ variables,
113
+ templates.merge(
114
+ nil => self.to_proc.call(variables, templates)
115
+ )
116
+ )
117
+ end
118
+ else
119
+ self.to_proc.call(variables, templates)
120
+ end
121
+ end
122
+ alias_method :call, :render
123
+
124
+ def compile(options)
125
+ escape_method = options[:escape_method]
126
+ sections = options[:sections]
127
+ templates = options[:templates]
128
+ variables = options[:variables]
129
+ source = options[:source]
130
+
131
+ stack = [ [ :base, nil, VariableTracker.new ] ]
132
+ stack_variables = nil
133
+
134
+ @content.scan(TOKEN_REGEXP).each do |text, tag_type, tag|
135
+ if (text)
136
+ text = text.sub(/\{(\{\{+)/, '\1').sub(/\}(\}\}+)/, '\1')
137
+
138
+ source and source << "r<<#{text.inspect};"
139
+ else
140
+ tag = tag.strip
141
+ tag = tag.empty? ? nil : tag.to_sym
142
+
143
+ case (tag_type)
144
+ when ?&
145
+ # HTML escaped
146
+ index = stack[-1][2][tag.inspect]
147
+
148
+ source and source << "v&&r<<h.html_escape(v[#{tag.inspect}].to_s);"
149
+
150
+ variables and variables[tag] = true
151
+
152
+ when ?%
153
+ # URI escaped
154
+ index = stack[-1][2][tag.inspect]
155
+
156
+ source and source << "v&&r<<h.uri_escape(v.is_a?(Array)?v[#{index}]:v[#{tag.inspect}]);"
157
+
158
+ variables and variables[tag] = true
159
+ when ?$
160
+ # JavaScript escaped
161
+ index = stack[-1][2][tag.inspect]
162
+
163
+ source and source << "v&&r<<h.js_escape(v.is_a?(Array)?v[#{index}]:v[#{tag.inspect}]);"
164
+
165
+ variables and variables[tag] = true
166
+ when ?.
167
+ # CSS escaped
168
+ index = stack[-1][2][tag.inspect]
169
+
170
+ source and source << "v&&r<<h.css_escape(v.is_a?(Array)?v[#{index}]:v[#{tag.inspect}]);"
171
+
172
+ variables and variables[tag] = true
173
+ when ?:
174
+ # Defines start of a :section
175
+ index = stack[-1][2][tag.inspect]
176
+
177
+ stack_variables ||= 's=[];'
178
+ stack << [ :section, tag, VariableTracker.new ]
179
+
180
+ source and source << "if(v);s<<v;v=v.is_a?(Array)?v[#{index}]:(v.is_a?(Hash)&&v[#{tag.inspect}]);"
181
+ source and source << "h.iterate(v){|v|;v=h.cast_as_vars(v, s);"
182
+
183
+ sections and sections[tag] = true
184
+ when ??
185
+ # Defines start of a ?conditional
186
+
187
+ stack[-1][2][tag.inspect]
188
+
189
+ # The stack will inherit the variable assignment locations from the
190
+ # existing stack layer.
191
+ stack << [ :conditional, tag, stack[-1][2] ]
192
+ source and source << "if(v&&v.is_a?(Hash)&&v[#{tag.inspect}]);"
193
+
194
+ variables and variables[tag] = true
195
+ when ?*
196
+ source and source << "_t=t&&t[#{tag.inspect}];r<<(_t.respond_to?(:call)?_t.call(v,t):_t.to_s);"
197
+
198
+ templates and templates[tag] = true
199
+ when ?/
200
+ # Closes out a section or conditional
201
+ closed = stack.pop
202
+
203
+ case (closed[0])
204
+ when :section
205
+ if (tag and tag != closed[1])
206
+ raise ParseError, "Template contains unexpected {{#{tag}}}, expected {{#{closed[1]}}}"
146
207
  end
147
- ]
208
+
209
+ source and source << "};v=s.pop;end;"
210
+ when :conditional
211
+ source and source << "end;"
212
+ when :base
213
+ raise ParseError, "Unexpected {{#{tag}}}, too many tags closed"
214
+ end
215
+ when ?=
216
+ # Literal insertion
217
+ index = stack[-1][2][tag.inspect]
218
+
219
+ source and source << "v&&r<<(v.is_a?(Array)?v[#{index}]:v[#{tag.inspect}]).to_s;"
220
+
221
+ variables and variables[tag] = true
222
+ else
223
+ # Contextual insertion
224
+ index = stack[-1][2][tag.inspect]
225
+
226
+ subst = "v.is_a?(Array)?v[#{stack[-1][2][tag.inspect]}]:v[#{tag.inspect}]"
227
+
228
+ if (escape_method)
229
+ source and source << "v&&r<<h.#{escape_method}(#{subst}.to_s);"
230
+ else
231
+ source and source << "v&&r<<(#{subst}).to_s;"
232
+ end
233
+
234
+ variables and variables[tag] = true
148
235
  end
149
- ]
236
+ end
237
+ end
238
+
239
+ unless (stack.length == 1)
240
+ case (stack[1][0])
241
+ when :section
242
+ raise ParseError, "Unclosed {{:#{stack[1][1]}}} in template"
243
+ when :conditional
244
+ raise ParseError, "Unclosed {{?#{stack[1][1]}}} in template"
245
+ else
246
+ raise ParseError, "Unclosed {{#{stack[1][1]}}} in template"
247
+ end
248
+ end
249
+
250
+ if (source)
251
+ source.replace("begin;c=false;h=Handlebar::Support;lambda{|v,t|raise RecursionError if(c);c=true;#{stack_variables}r='';#{source}c=false;r};end")
150
252
  end
151
253
 
152
- self.to_proc.call(variables, templates)
254
+ true
255
+ end
256
+
257
+ def to_yaml(dump)
258
+ _proc, @_proc = @_proc, nil
259
+
260
+ super(dump)
261
+
262
+ @_proc = _proc
263
+
264
+ dump
265
+ end
266
+
267
+ def marshal_dump
268
+ [ @content, { :escape => @escape_method } ]
269
+ end
270
+
271
+ def marshal_load(dump)
272
+ @content, options = dump
273
+
274
+ @escape_method = options[:escape]
153
275
  end
154
- alias_method :call, :interpret
155
276
  end
@@ -1,85 +1,179 @@
1
1
  require 'helper'
2
2
 
3
+ require 'yaml'
4
+
3
5
  class TestHandlebarTemplate < Test::Unit::TestCase
4
6
  def test_empty_template
5
7
  template = Handlebar::Template.new('')
6
8
 
7
- assert_equal '', template.interpret
9
+ assert_equal '', template.render
8
10
  end
9
11
 
10
12
  def test_simple_templates
11
13
  template = Handlebar::Template.new('example')
12
14
 
13
- assert_equal 'example', template.interpret
15
+ assert_equal 'example', template.render
14
16
 
15
17
  template = Handlebar::Template.new('{{{example}}}')
16
18
 
17
- assert_equal '{{example}}', template.interpret
19
+ assert_equal '{{example}}', template.render
18
20
 
19
21
  template = Handlebar::Template.new('example {{example}} text')
20
22
 
21
- assert_equal 'example something text', template.interpret(:example => 'something')
23
+ assert_equal 'example something text', template.render(:example => 'something')
22
24
 
23
25
  template = Handlebar::Template.new('example {{ example }} text')
24
26
 
25
- assert_equal 'example something text', template.interpret(:example => 'something')
27
+ assert_equal 'example something text', template.render(:example => 'something')
26
28
  end
27
29
 
28
30
  def test_boolean_templates
29
31
  template = Handlebar::Template.new('{{?boolean}}true {{/}}false')
30
32
 
31
- assert_equal 'false', template.interpret
32
- assert_equal 'true false', template.interpret(:boolean => true)
33
- assert_equal 'false', template.interpret(:boolean => false)
33
+ assert_equal 'false', template.render
34
+ assert_equal 'true false', template.render(:boolean => true)
35
+ assert_equal 'false', template.render(:boolean => false)
34
36
  end
35
37
 
36
38
  def test_sectioned_templates
37
39
  template = Handlebar::Template.new('<head>{{:head}}<{{tag}}>{{/}}</head>')
38
40
 
39
- assert_equal '<head><meta></head>', template.interpret(:head => 'meta')
40
- assert_equal '<head><meta><link></head>', template.interpret(:head => %w[ meta link ])
41
- assert_equal '<head><meta><link></head>', template.interpret(:head => [ { :tag => 'meta' }, { :tag => 'link' } ])
42
- assert_equal '<head></head>', template.interpret
43
- assert_equal '<head></head>', template.interpret(:head => nil)
44
- assert_equal '<head></head>', template.interpret(:head => [ ])
41
+ assert_equal '<head><meta></head>', template.render(:head => 'meta')
42
+ assert_equal '<head><meta><link></head>', template.render(:head => %w[ meta link ])
43
+ assert_equal '<head><meta><link></head>', template.render(:head => [ { :tag => 'meta' }, { :tag => 'link' } ])
44
+ assert_equal '<head></head>', template.render
45
+ assert_equal '<head></head>', template.render(:head => nil)
46
+ assert_equal '<head></head>', template.render(:head => [ ])
45
47
 
46
48
  template = Handlebar::Template.new('<div>{{:link}}<a href="{{href}}" alt="{{alt}}">{{/}}</div>')
47
49
 
48
- assert_equal '<div><a href="meta" alt=""></div>', template.interpret(:link => 'meta')
49
- assert_equal '<div><a href="meta" alt="link"></div>', template.interpret(:link => [ %w[ meta link ] ])
50
- assert_equal '<div><a href="/h" alt=""><a href="" alt="alt"><a href="/" alt="top"></div>', template.interpret(:link => [ { :href => '/h' }, { :alt => 'alt' }, { :href => '/', :alt => 'top' } ])
51
- assert_equal '<div></div>', template.interpret
52
- assert_equal '<div></div>', template.interpret(:link => nil)
53
- assert_equal '<div></div>', template.interpret(:link => [ ])
50
+ assert_equal '<div><a href="meta" alt=""></div>', template.render(:link => 'meta')
51
+ assert_equal '<div><a href="meta" alt="link"></div>', template.render(:link => [ %w[ meta link ] ])
52
+ assert_equal '<div><a href="/h" alt=""><a href="" alt="alt"><a href="/" alt="top"></div>', template.render(:link => [ { :href => '/h' }, { :alt => 'alt' }, { :href => '/', :alt => 'top' } ])
53
+ assert_equal '<div></div>', template.render
54
+ assert_equal '<div></div>', template.render(:link => nil)
55
+ assert_equal '<div></div>', template.render(:link => [ ])
54
56
  end
55
57
 
56
58
  def test_template_with_context
57
- template = Handlebar::Template.new('{{example}}', :html)
59
+ template = Handlebar::Template.new('{{example}}', :escape => :html)
58
60
 
59
- assert_equal '&lt;strong&gt;', template.interpret('<strong>')
61
+ assert_equal '&lt;strong&gt;', template.render('<strong>')
60
62
 
61
- template = Handlebar::Template.new('{{=example}}', :html)
63
+ template = Handlebar::Template.new('{{=example}}', :escape => :html)
62
64
 
63
- assert_equal '<strong>', template.interpret('<strong>')
65
+ assert_equal '<strong>', template.render('<strong>')
64
66
  end
65
67
 
66
68
  def test_recursive_templates
67
- template = Handlebar::Template.new('{{*example}}', :html)
69
+ template = Handlebar::Template.new('{{*example}}', :escape => :html)
68
70
 
69
- assert_equal 'child', template.interpret(nil, { :example => '{{*parent}}', :parent => 'child' })
71
+ assert_equal 'child', template.render(nil, { :example => '{{*parent}}', :parent => 'child' }.freeze)
70
72
  end
71
73
 
72
74
  def test_missing_templates
73
- template = Handlebar::Template.new('{{*example}}', :html)
75
+ template = Handlebar::Template.new('{{*example}}', :escape => :html)
74
76
 
75
- assert_equal '', template.interpret(nil, { })
77
+ assert_equal '', template.render(nil, { })
76
78
  end
77
79
 
78
80
  def test_recursive_circular_templates
79
- template = Handlebar::Template.new('{{*reference}}', :html)
81
+ template = Handlebar::Template.new('{{*reference}}', :escape => :html)
80
82
 
81
83
  assert_exception Handlebar::Template::RecursionError do
82
- template.interpret(nil, { :reference => '{{*backreference}}', :backreference => '{{*reference}}' })
84
+ template.render(nil, { :reference => '{{*backreference}}', :backreference => '{{*reference}}' }.freeze)
83
85
  end
84
86
  end
87
+
88
+ def test_parent_templates
89
+ parent_template = Handlebar::Template.new('{{a}}[{{*}}]{{b}}')
90
+ child_template = Handlebar::Template.new('{{c}}{{*}}')
91
+ final_template = Handlebar::Template.new('{{a}}')
92
+
93
+ variables = { :a => 'A', :b => 'B', :c => 'C' }
94
+
95
+ assert_equal 'A', final_template.render(variables)
96
+ assert_equal 'CA', final_template.render(variables, nil, child_template)
97
+ assert_equal 'A[CA]B', final_template.render(variables, nil, [ child_template, parent_template ].freeze)
98
+ end
99
+
100
+ def test_extract_variables
101
+ template = Handlebar::Template.new('{{a}}{{?b}}{{=c}}{{/b}}{{&d}}{{$e}}{{.f}}{{%g}}{{:h}}{{i}}{{/h}}')
102
+
103
+ variables = { }
104
+ sections = { }
105
+ templates = { }
106
+
107
+ template.compile(
108
+ :variables => variables,
109
+ :sections => sections,
110
+ :templates => templates
111
+ )
112
+
113
+ assert_equal [ :a, :b, :c, :d, :e, :f, :g, :i ], variables.keys.sort_by(&:to_s)
114
+ assert_equal [ :h ], sections.keys.sort_by(&:to_s)
115
+ assert_equal [ ], templates.keys.sort_by(&:to_s)
116
+ end
117
+
118
+ def test_chain_extract_variables
119
+ template = Handlebar::Template.new('{{a}}{{?b}}{{=c}}{{/b}}{{&d}}{{$e}}{{.f}}{{%g}}{{:h}}{{i}}{{/h}}')
120
+
121
+ variables = { :x => true }
122
+ sections = { :y => true }
123
+ templates = { :z => true }
124
+
125
+ template.compile(
126
+ :variables => variables,
127
+ :sections => sections,
128
+ :templates => templates
129
+ )
130
+
131
+ assert_equal [ :a, :b, :c, :d, :e, :f, :g, :i, :x ], variables.keys.sort_by(&:to_s)
132
+ assert_equal [ :h, :y ], sections.keys.sort_by(&:to_s)
133
+ assert_equal [ :z ], templates.keys.sort_by(&:to_s)
134
+ end
135
+
136
+ def test_variable_tracker
137
+ tracker = Handlebar::Template::VariableTracker.new
138
+
139
+ assert_equal true, tracker.empty?
140
+ assert_equal 0, tracker[:a]
141
+ assert_equal 1, tracker[:b]
142
+ assert_equal 2, tracker[:c]
143
+ assert_equal 0, tracker[:a]
144
+ assert_equal 2, tracker[:c]
145
+ assert_equal 3, tracker[:z]
146
+ end
147
+
148
+ def test_clone
149
+ template = Handlebar::Template.new('<p>{{example}}</p>', :escape => :html)
150
+
151
+ cloned = template.clone
152
+
153
+ assert_equal '<p>&lt;strong&gt;</p>', cloned.render('<strong>')
154
+ end
155
+
156
+ def test_serialization_with_yaml
157
+ template = Handlebar::Template.new('<p>{{example}}</p>', :escape => :html)
158
+
159
+ assert_equal '<p>&lt;strong&gt;</p>', template.render('<strong>')
160
+
161
+ serialized_template = YAML.dump(template)
162
+
163
+ deserialized_template = YAML.load(serialized_template)
164
+
165
+ assert_equal '<p>&lt;strong&gt;</p>', deserialized_template.render('<strong>')
166
+ end
167
+
168
+ def test_serialization_with_marshal
169
+ template = Handlebar::Template.new('<p>{{example}}</p>', :escape => :html)
170
+
171
+ assert_equal '<p>&lt;strong&gt;</p>', template.render('<strong>')
172
+
173
+ serialized_template = Marshal.dump(template)
174
+
175
+ deserialized_template = Marshal.load(serialized_template)
176
+
177
+ assert_equal '<p>&lt;strong&gt;</p>', deserialized_template.render('<strong>')
178
+ end
85
179
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: handlebar
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.0
5
+ version: 0.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Scott Tadman
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-06-29 00:00:00 -04:00
13
+ date: 2011-06-30 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -51,6 +51,8 @@ files:
51
51
  - LICENSE.txt
52
52
  - README.rdoc
53
53
  - Rakefile
54
+ - VERSION
55
+ - handlebar.gemspec
54
56
  - lib/handlebar.rb
55
57
  - lib/handlebar/support.rb
56
58
  - lib/handlebar/template.rb