handlebar 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/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