tilt 0.6 → 0.7

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/README.md CHANGED
@@ -33,6 +33,12 @@ Support for these template engines is included with the package:
33
33
  RDiscount .markdown rdiscount
34
34
  RedCloth .textile redcloth
35
35
 
36
+ See [TEMPLATES.md][t] for detailed information on template engine
37
+ options and supported features.
38
+
39
+ [t]: http://github.com/rtomayko/tilt/blob/master/TEMPLATES.md
40
+ "Tilt Template Engine Documentation"
41
+
36
42
  Basic Usage
37
43
  -----------
38
44
 
data/Rakefile CHANGED
@@ -16,38 +16,39 @@ end
16
16
 
17
17
  # PACKAGING =================================================================
18
18
 
19
- require 'rubygems/specification'
20
- $spec ||= eval(File.read('tilt.gemspec'))
21
-
22
- def package(ext='')
23
- "dist/tilt-#{$spec.version}" + ext
24
- end
25
-
26
- desc 'Build packages'
27
- task :package => %w[.gem .tar.gz].map {|e| package(e)}
28
-
29
- desc 'Build and install as local gem'
30
- task :install => package('.gem') do
31
- sh "gem install #{package('.gem')}"
32
- end
33
-
34
- directory 'dist/'
35
-
36
- file package('.gem') => %w[dist/ tilt.gemspec] + $spec.files do |f|
37
- sh "gem build tilt.gemspec"
38
- mv File.basename(f.name), f.name
39
- end
40
-
41
- file package('.tar.gz') => %w[dist/] + $spec.files do |f|
42
- sh "git archive --format=tar HEAD | gzip > #{f.name}"
43
- end
44
-
45
- desc 'Upload gem and tar.gz distributables to rubyforge'
46
- task :release => [package('.gem'), package('.tar.gz')] do |t|
47
- sh <<-SH
48
- rubyforge add_release sinatra tilt #{$spec.version} #{package('.gem')} &&
49
- rubyforge add_file sinatra tilt #{$spec.version} #{package('.tar.gz')}
50
- SH
19
+ if defined?(Gem)
20
+ SPEC = eval(File.read('tilt.gemspec'))
21
+
22
+ def package(ext='')
23
+ "pkg/tilt-#{SPEC.version}" + ext
24
+ end
25
+
26
+ desc 'Build packages'
27
+ task :package => %w[.gem .tar.gz].map {|e| package(e)}
28
+
29
+ desc 'Build and install as local gem'
30
+ task :install => package('.gem') do
31
+ sh "gem install #{package('.gem')}"
32
+ end
33
+
34
+ directory 'pkg/'
35
+
36
+ file package('.gem') => %w[pkg/ tilt.gemspec] + SPEC.files do |f|
37
+ sh "gem build tilt.gemspec"
38
+ mv File.basename(f.name), f.name
39
+ end
40
+
41
+ file package('.tar.gz') => %w[pkg/] + SPEC.files do |f|
42
+ sh "git archive --format=tar HEAD | gzip > #{f.name}"
43
+ end
44
+
45
+ desc 'Upload gem and tar.gz distributables to rubyforge'
46
+ task :release => [package('.gem'), package('.tar.gz')] do |t|
47
+ sh <<-SH
48
+ rubyforge add_release sinatra tilt #{SPEC.version} #{package('.gem')} &&
49
+ rubyforge add_file sinatra tilt #{SPEC.version} #{package('.tar.gz')}
50
+ SH
51
+ end
51
52
  end
52
53
 
53
54
  # GEMSPEC ===================================================================
@@ -67,6 +67,12 @@ of any combination of the following characters:
67
67
  The `$SAFE` level; when set, ERB code will be run in a
68
68
  separate thread with `$SAFE` set to the provided level.
69
69
 
70
+ #### `:outvar => '_erbout'`
71
+
72
+ The name of the variable used to accumulate template output. This can be
73
+ any valid Ruby expression but must be assignable. By default a local
74
+ variable named `_erbout` is used.
75
+
70
76
  ### See also
71
77
 
72
78
  * [ERB documentation](http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html)
@@ -98,14 +104,19 @@ Set pattern for embedded Ruby code.
98
104
 
99
105
  See the [ERB](#erb) template documentation for examples, usage, and options.
100
106
 
101
- __NOTE:__ It's suggested that your program `require 'erubis'` at load time when
102
- using this template engine within a threaded environment.
107
+ #### `:outvar => '_erbout'`
108
+
109
+ The name of the variable used to accumulate template output. This can be
110
+ any valid Ruby expression but must be assignable. By default a local
111
+ variable named `_erbout` is used.
103
112
 
104
113
  ### See also
105
114
 
106
115
  * [Erubis Home](http://www.kuwata-lab.com/erubis/)
107
116
  * [Erubis User's Guide](http://www.kuwata-lab.com/erubis/users-guide.html)
108
117
 
118
+ __NOTE:__ It's suggested that your program `require 'erubis'` at load time when
119
+ using this template engine within a threaded environment.
109
120
 
110
121
  <a name='haml'></a>
111
122
  Haml (`haml`)
@@ -1,10 +1,9 @@
1
1
  module Tilt
2
- VERSION = '0.6'
2
+ VERSION = '0.7'
3
3
 
4
4
  @template_mappings = {}
5
5
 
6
- # Hash of template path pattern => template implementation
7
- # class mappings.
6
+ # Hash of template path pattern => template implementation class mappings.
8
7
  def self.mappings
9
8
  @template_mappings
10
9
  end
@@ -25,7 +24,7 @@ module Tilt
25
24
  end
26
25
  end
27
26
 
28
- # Lookup a template class given for the given filename or file
27
+ # Lookup a template class for the given filename or file
29
28
  # extension. Return nil when no implementation is found.
30
29
  def self.[](file)
31
30
  if @template_mappings.key?(pattern = file.to_s.downcase)
@@ -44,9 +43,24 @@ module Tilt
44
43
  end
45
44
  end
46
45
 
46
+ # Mixin allowing template compilation on scope objects.
47
+ #
48
+ # Including this module in scope objects passed to Template#render
49
+ # causes template source to be compiled to methods the first time they're
50
+ # used. This can yield significant (5x-10x) performance increases for
51
+ # templates that support it (ERB, Erubis, Builder).
52
+ #
53
+ # It's also possible (though not recommended) to include this module in
54
+ # Object to enable template compilation globally. The downside is that
55
+ # the template methods will polute the global namespace and could lead to
56
+ # unexpected behavior.
57
+ module CompileSite
58
+ def __tilt__
59
+ end
60
+ end
47
61
 
48
62
  # Base class for template implementations. Subclasses must implement
49
- # the #compile! method and one of the #evaluate or #template_source
63
+ # the #prepare method and one of the #evaluate or #template_source
50
64
  # methods.
51
65
  class Template
52
66
  # Template source; loaded from a file or given directly.
@@ -63,52 +77,55 @@ module Tilt
63
77
  # interface.
64
78
  attr_reader :options
65
79
 
80
+ # Used to determine if this class's initialize_engine method has
81
+ # been called yet.
82
+ @engine_initialized = false
83
+ class << self
84
+ attr_accessor :engine_initialized
85
+ alias engine_initialized? engine_initialized
86
+ end
87
+
66
88
  # Create a new template with the file, line, and options specified. By
67
- # default, template data is read from the file specified. When a block
68
- # is given, it should read template data and return as a String. When
69
- # file is nil, a block is required.
89
+ # default, template data is read from the file. When a block is given,
90
+ # it should read template data and return as a String. When file is nil,
91
+ # a block is required.
70
92
  #
71
- # The #initialize_engine method is called if this is the very first
72
- # time this template subclass has been initialized.
93
+ # All arguments are optional.
73
94
  def initialize(file=nil, line=1, options={}, &block)
74
- raise ArgumentError, "file or block required" if file.nil? && block.nil?
75
- options, line = line, 1 if line.is_a?(Hash)
76
- @file = file
77
- @line = line || 1
78
- @options = options || {}
79
- @reader = block || lambda { |t| File.read(file) }
80
- @data = nil
81
-
82
- if !self.class.engine_initialized
95
+ @file, @line, @options = nil, 1, {}
96
+
97
+ [options, line, file].compact.each do |arg|
98
+ case
99
+ when arg.respond_to?(:to_str) ; @file = arg.to_str
100
+ when arg.respond_to?(:to_int) ; @line = arg.to_int
101
+ when arg.respond_to?(:to_hash) ; @options = arg.to_hash
102
+ else raise TypeError
103
+ end
104
+ end
105
+
106
+ raise ArgumentError, "file or block required" if (@file || block).nil?
107
+
108
+ # call the initialize_engine method if this is the very first time
109
+ # an instance of this class has been created.
110
+ if !self.class.engine_initialized?
83
111
  initialize_engine
84
112
  self.class.engine_initialized = true
85
113
  end
86
- end
87
-
88
- # Called once and only once for each template subclass the first time
89
- # the template class is initialized. This should be used to require the
90
- # underlying template library and perform any initial setup.
91
- def initialize_engine
92
- end
93
- @engine_initialized = false
94
- class << self ; attr_accessor :engine_initialized ; end
95
114
 
115
+ # used to generate unique method names for template compilation
116
+ stamp = (Time.now.to_f * 10000).to_i
117
+ @_prefix = "__tilt_O#{object_id.to_s(16)}T#{stamp.to_s(16)}"
96
118
 
97
- # Load template source and compile the template. The template is
98
- # loaded and compiled the first time this method is called; subsequent
99
- # calls are no-ops.
100
- def compile
101
- if @data.nil?
102
- @data = @reader.call(self)
103
- compile!
104
- end
119
+ # load template data and prepare
120
+ @reader = block || lambda { |t| File.read(@file) }
121
+ @data = @reader.call(self)
122
+ prepare
105
123
  end
106
124
 
107
125
  # Render the template in the given scope with the locals specified. If a
108
126
  # block is given, it is typically available within the template via
109
127
  # +yield+.
110
128
  def render(scope=Object.new, locals={}, &block)
111
- compile
112
129
  evaluate scope, locals || {}, &block
113
130
  end
114
131
 
@@ -128,26 +145,56 @@ module Tilt
128
145
  end
129
146
 
130
147
  protected
131
- # Do whatever preparation is necessary to "compile" the template.
132
- # Called immediately after template #data is loaded. Instance variables
133
- # set in this method are available when #evaluate is called.
148
+ # Called once and only once for each template subclass the first time
149
+ # the template class is initialized. This should be used to require the
150
+ # underlying template library and perform any initial setup.
151
+ def initialize_engine
152
+ end
153
+
154
+ # Do whatever preparation is necessary to setup the underlying template
155
+ # engine. Called immediately after template data is loaded. Instance
156
+ # variables set in this method are available when #evaluate is called.
134
157
  #
135
158
  # Subclasses must provide an implementation of this method.
136
- def compile!
137
- raise NotImplementedError
159
+ def prepare
160
+ if respond_to?(:compile!)
161
+ # backward compat with tilt < 0.6; just in case
162
+ warn 'Tilt::Template#compile! is deprecated; implement #prepare instead.'
163
+ compile!
164
+ else
165
+ raise NotImplementedError
166
+ end
138
167
  end
139
168
 
140
- # Process the template and return the result. Subclasses should override
141
- # this method unless they implement the #template_source.
169
+ # Process the template and return the result. When the scope mixes in
170
+ # the Tilt::CompileSite module, the template is compiled to a method and
171
+ # reused given identical locals keys. When the scope object
172
+ # does not mix in the CompileSite module, the template source is
173
+ # evaluated with instance_eval. In any case, template executation
174
+ # is guaranteed to be performed in the scope object with the locals
175
+ # specified and with support for yielding to the block.
142
176
  def evaluate(scope, locals, &block)
143
- source, offset = local_assignment_code(locals)
144
- source = [source, template_source].join("\n")
145
- scope.instance_eval source, eval_file, line - offset
177
+ if scope.respond_to?(:__tilt__)
178
+ method_name = compiled_method_name(locals.keys.hash)
179
+ if scope.respond_to?(method_name)
180
+ # fast path
181
+ scope.send method_name, locals, &block
182
+ else
183
+ # compile first and then run
184
+ compile_template_method(method_name, locals)
185
+ scope.send method_name, locals, &block
186
+ end
187
+ else
188
+ source, offset = local_assignment_code(locals)
189
+ source = [source, template_source].join("\n")
190
+ scope.instance_eval source, eval_file, line - offset
191
+ end
146
192
  end
147
193
 
148
194
  # Return a string containing the (Ruby) source code for the template. The
149
195
  # default Template#evaluate implementation requires this method be
150
- # defined.
196
+ # defined and guarantees correct file/line handling, custom scopes, and
197
+ # support for template compilation when the scope object allows it.
151
198
  def template_source
152
199
  raise NotImplementedError
153
200
  end
@@ -159,6 +206,41 @@ module Tilt
159
206
  [source.join("\n"), source.length]
160
207
  end
161
208
 
209
+ def compiled_method_name(locals_hash)
210
+ "#{@_prefix}L#{locals_hash.to_s(16).sub('-', 'n')}"
211
+ end
212
+
213
+ def compile_template_method(method_name, locals)
214
+ source, offset = local_assignment_code(locals)
215
+ source = [source, template_source].join("\n")
216
+ offset += 1
217
+
218
+ # add the new method
219
+ CompileSite.module_eval <<-RUBY, eval_file, line - offset
220
+ def #{method_name}(locals)
221
+ #{source}
222
+ end
223
+ RUBY
224
+
225
+ # setup a finalizer to remove the newly added method
226
+ ObjectSpace.define_finalizer self,
227
+ Template.compiled_template_method_remover(CompileSite, method_name)
228
+ end
229
+
230
+ def self.compiled_template_method_remover(site, method_name)
231
+ proc { |oid| garbage_collect_compiled_template_method(site, method_name) }
232
+ end
233
+
234
+ def self.garbage_collect_compiled_template_method(site, method_name)
235
+ site.module_eval do
236
+ begin
237
+ remove_method(method_name)
238
+ rescue NameError
239
+ # method was already removed (ruby >= 1.9)
240
+ end
241
+ end
242
+ end
243
+
162
244
  def require_template_library(name)
163
245
  if Thread.list.size > 1
164
246
  warn "WARN: tilt autoloading '#{name}' in a non thread-safe way; " +
@@ -174,7 +256,7 @@ module Tilt
174
256
  # cache = Tilt::Cache.new
175
257
  # cache.fetch(path, line, options) { Tilt.new(path, line, options) }
176
258
  #
177
- # Subsequent invocations return the already compiled template object.
259
+ # Subsequent invocations return the already loaded template object.
178
260
  class Cache
179
261
  def initialize
180
262
  @cache = {}
@@ -196,7 +278,7 @@ module Tilt
196
278
  # The template source is evaluated as a Ruby string. The #{} interpolation
197
279
  # syntax can be used to generated dynamic output.
198
280
  class StringTemplate < Template
199
- def compile!
281
+ def prepare
200
282
  @code = "%Q{#{data}}"
201
283
  end
202
284
 
@@ -214,8 +296,9 @@ module Tilt
214
296
  require_template_library 'erb' unless defined? ::ERB
215
297
  end
216
298
 
217
- def compile!
218
- @engine = ::ERB.new(data, options[:safe], options[:trim], '@_out_buf')
299
+ def prepare
300
+ @outvar = (options[:outvar] || '_erbout').to_s
301
+ @engine = ::ERB.new(data, options[:safe], options[:trim], @outvar)
219
302
  end
220
303
 
221
304
  def template_source
@@ -223,22 +306,23 @@ module Tilt
223
306
  end
224
307
 
225
308
  def evaluate(scope, locals, &block)
226
- source, offset = local_assignment_code(locals)
227
- source = [source, template_source].join("\n")
228
-
229
- original_out_buf =
230
- scope.instance_variables.any? { |var| var.to_sym == :@_out_buf } &&
231
- scope.instance_variable_get(:@_out_buf)
232
-
233
- scope.instance_eval source, eval_file, line - offset
234
-
235
- output = scope.instance_variable_get(:@_out_buf)
236
- scope.instance_variable_set(:@_out_buf, original_out_buf)
237
-
238
- output
309
+ preserve_outvar_value(scope) { super }
239
310
  end
240
311
 
241
312
  private
313
+ # Retains the previous value of outvar when configured to use
314
+ # an instance variable. This allows multiple templates to be rendered
315
+ # within the context of an object without overwriting the outvar.
316
+ def preserve_outvar_value(scope)
317
+ if @outvar[0] == ?@
318
+ previous = scope.instance_variable_get(@outvar)
319
+ output = yield
320
+ scope.instance_variable_set(@outvar, previous)
321
+ output
322
+ else
323
+ yield
324
+ end
325
+ end
242
326
 
243
327
  # ERB generates a line to specify the character coding of the generated
244
328
  # source in 1.9. Account for this in the line offset.
@@ -259,13 +343,17 @@ module Tilt
259
343
  require_template_library 'erubis' unless defined? ::Erubis
260
344
  end
261
345
 
262
- def compile!
263
- Erubis::Eruby.class_eval(%Q{def add_preamble(src) src << "@_out_buf = _buf = '';" end})
346
+ def prepare
347
+ @options.merge!(:preamble => false, :postamble => false)
348
+ @outvar = (options.delete(:outvar) || '_erbout').to_s
264
349
  @engine = ::Erubis::Eruby.new(data, options)
265
350
  end
266
351
 
267
- private
352
+ def template_source
353
+ ["#{@outvar} = _buf = ''", @engine.src, "_buf.to_s"].join(";")
354
+ end
268
355
 
356
+ private
269
357
  # Erubis doesn't have ERB's line-off-by-one under 1.9 problem. Override
270
358
  # and adjust back.
271
359
  if RUBY_VERSION >= '1.9.0'
@@ -285,15 +373,37 @@ module Tilt
285
373
  require_template_library 'haml' unless defined? ::Haml::Engine
286
374
  end
287
375
 
288
- def compile!
376
+ def prepare
289
377
  @engine = ::Haml::Engine.new(data, haml_options)
290
378
  end
291
379
 
292
- def evaluate(scope, locals, &block)
293
- @engine.render(scope, locals, &block)
380
+ # Precompiled Haml source. Taken from the precompiled_with_ambles
381
+ # method in Haml::Precompiler:
382
+ # http://github.com/nex3/haml/blob/master/lib/haml/precompiler.rb#L111-126
383
+ def template_source
384
+ @engine.instance_eval do
385
+ <<-RUBY
386
+ _haml_locals = locals
387
+ begin
388
+ extend Haml::Helpers
389
+ _hamlout = @haml_buffer = Haml::Buffer.new(@haml_buffer, #{options_for_buffer.inspect})
390
+ _erbout = _hamlout.buffer
391
+ __in_erb_template = true
392
+ #{precompiled}
393
+ #{precompiled_method_return_value}
394
+ ensure
395
+ @haml_buffer = @haml_buffer.upper
396
+ end
397
+ RUBY
398
+ end
294
399
  end
295
400
 
296
401
  private
402
+ def local_assignment_code(locals)
403
+ source, offset = super
404
+ [source, offset + 6]
405
+ end
406
+
297
407
  def haml_options
298
408
  options.merge(:filename => eval_file, :line => line)
299
409
  end
@@ -310,12 +420,12 @@ module Tilt
310
420
  require_template_library 'sass' unless defined? ::Sass::Engine
311
421
  end
312
422
 
313
- def compile!
423
+ def prepare
314
424
  @engine = ::Sass::Engine.new(data, sass_options)
315
425
  end
316
426
 
317
427
  def evaluate(scope, locals, &block)
318
- @engine.render
428
+ @output ||= @engine.render
319
429
  end
320
430
 
321
431
  private
@@ -335,7 +445,7 @@ module Tilt
335
445
  require_template_library 'less' unless defined? ::Less::Engine
336
446
  end
337
447
 
338
- def compile!
448
+ def prepare
339
449
  @engine = ::Less::Engine.new(data)
340
450
  end
341
451
 
@@ -345,6 +455,7 @@ module Tilt
345
455
  end
346
456
  register 'less', LessTemplate
347
457
 
458
+
348
459
  # Builder template implementation. See:
349
460
  # http://builder.rubyforge.org/
350
461
  class BuilderTemplate < Template
@@ -352,7 +463,7 @@ module Tilt
352
463
  require_template_library 'builder' unless defined?(::Builder)
353
464
  end
354
465
 
355
- def compile!
466
+ def prepare
356
467
  end
357
468
 
358
469
  def evaluate(scope, locals, &block)
@@ -391,7 +502,7 @@ module Tilt
391
502
  require_template_library 'liquid' unless defined? ::Liquid::Template
392
503
  end
393
504
 
394
- def compile!
505
+ def prepare
395
506
  @engine = ::Liquid::Template.parse(data)
396
507
  end
397
508
 
@@ -424,7 +535,7 @@ module Tilt
424
535
  require_template_library 'rdiscount' unless defined? ::RDiscount
425
536
  end
426
537
 
427
- def compile!
538
+ def prepare
428
539
  @engine = RDiscount.new(data, *flags)
429
540
  end
430
541
 
@@ -444,7 +555,7 @@ module Tilt
444
555
  require_template_library 'redcloth' unless defined? ::RedCloth
445
556
  end
446
557
 
447
- def compile!
558
+ def prepare
448
559
  @engine = RedCloth.new(data)
449
560
  end
450
561
 
@@ -468,7 +579,7 @@ module Tilt
468
579
  require_template_library 'mustache' unless defined? ::Mustache
469
580
  end
470
581
 
471
- def compile!
582
+ def prepare
472
583
  Mustache.view_namespace = options[:namespace]
473
584
  Mustache.view_path = options[:view_path] || options[:mustaches]
474
585
  @engine = options[:view] || Mustache.view_class(name)
@@ -502,6 +613,7 @@ module Tilt
502
613
  end
503
614
  register 'mustache', MustacheTemplate
504
615
 
616
+
505
617
  # RDoc template. See:
506
618
  # http://rdoc.rubyforge.org/
507
619
  #
@@ -516,7 +628,7 @@ module Tilt
516
628
  end
517
629
  end
518
630
 
519
- def compile!
631
+ def prepare
520
632
  markup = RDoc::Markup::ToHtml.new
521
633
  @engine = markup.convert(data)
522
634
  end
@@ -527,6 +639,7 @@ module Tilt
527
639
  end
528
640
  register 'rdoc', RDocTemplate
529
641
 
642
+
530
643
  # CoffeeScript info:
531
644
  # http://jashkenas.github.com/coffee-script/
532
645
  class CoffeeTemplate < Template
@@ -534,7 +647,7 @@ module Tilt
534
647
  require_template_library 'coffee-script' unless defined? ::CoffeeScript
535
648
  end
536
649
 
537
- def compile!
650
+ def prepare
538
651
  @engine = ::CoffeeScript::compile(data, options)
539
652
  end
540
653
 
@@ -9,7 +9,7 @@ begin
9
9
  assert_equal Tilt::BuilderTemplate, Tilt['test.xml.builder']
10
10
  end
11
11
 
12
- test "compiling and evaluating the template on #render" do
12
+ test "preparing and evaluating the template on #render" do
13
13
  template = Tilt::BuilderTemplate.new { |t| "xml.em 'Hello World!'" }
14
14
  assert_equal "<em>Hello World!</em>\n", template.render
15
15
  end
@@ -0,0 +1,62 @@
1
+ require 'contest'
2
+ require 'tilt'
3
+
4
+ class CompileSiteTest < Test::Unit::TestCase
5
+ def setup
6
+ GC.start
7
+ end
8
+
9
+ class CompilingTemplate < Tilt::Template
10
+ def prepare
11
+ end
12
+
13
+ def template_source
14
+ @data.inspect
15
+ end
16
+ end
17
+
18
+ class Scope
19
+ include Tilt::CompileSite
20
+ end
21
+
22
+ test "compiling template source to a method" do
23
+ template = CompilingTemplate.new { |t| "Hello World!" }
24
+ template.render(Scope.new)
25
+ method_name = template.send(:compiled_method_name, [].hash)
26
+ method_name = method_name.to_sym if Symbol === Kernel.methods.first
27
+ assert Tilt::CompileSite.instance_methods.include?(method_name),
28
+ "CompileSite.instance_methods.include?(#{method_name.inspect})"
29
+ assert Scope.new.respond_to?(method_name),
30
+ "scope.respond_to?(#{method_name.inspect})"
31
+ end
32
+
33
+ test 'garbage collecting compiled methods' do
34
+ template = CompilingTemplate.new { '' }
35
+ method_name = template.send(:compiled_method_name, [].hash)
36
+ template.render(Scope.new)
37
+ assert Scope.new.respond_to?(method_name)
38
+ Tilt::Template.send(
39
+ :garbage_collect_compiled_template_method,
40
+ Tilt::CompileSite,
41
+ method_name
42
+ )
43
+ assert !Scope.new.respond_to?(method_name), "compiled method not removed"
44
+ end
45
+
46
+ def self.create_and_destroy_template
47
+ template = CompilingTemplate.new { 'Hello World' }
48
+ template.render(Scope.new)
49
+ method_name = template.send(:compiled_method_name, [].hash)
50
+ method_name = method_name.to_sym if Symbol === Kernel.methods.first
51
+ [template.object_id, method_name]
52
+ end
53
+
54
+ finalized_object_id, finalized_method_name = create_and_destroy_template
55
+
56
+ test "triggering compiled method gc finalizer" do
57
+ assert !Tilt::CompileSite.instance_methods.include?(finalized_method_name),
58
+ "CompileSite.instance_methods.include?(#{finalized_method_name.inspect})"
59
+ assert !Scope.new.respond_to?(finalized_method_name),
60
+ "Scope.new.respond_to?(#{finalized_method_name.inspect})"
61
+ end
62
+ end
@@ -12,7 +12,7 @@ class ERBTemplateTest < Test::Unit::TestCase
12
12
  assert_equal Tilt::ERBTemplate, Tilt['test.rhtml']
13
13
  end
14
14
 
15
- test "compiling and evaluating templates on #render" do
15
+ test "loading and evaluating templates on #render" do
16
16
  template = Tilt::ERBTemplate.new { |t| "Hello World!" }
17
17
  assert_equal "Hello World!", template.render
18
18
  end
@@ -77,9 +77,111 @@ class ERBTemplateTest < Test::Unit::TestCase
77
77
  end
78
78
 
79
79
  test "shorthand whole line syntax trim mode" do
80
- template = Tilt.new('test.erb', 1, :trim => '%') { "\n% if true\nhello\n%end\n" }
80
+ template = Tilt.new('test.erb', :trim => '%') { "\n% if true\nhello\n%end\n" }
81
81
  assert_equal "\nhello\n", template.render
82
82
  end
83
+
84
+ test "using an instance variable as the outvar" do
85
+ template = Tilt::ERBTemplate.new(nil, :outvar => '@buf') { "<%= 1 + 1 %>" }
86
+ scope = Object.new
87
+ scope.instance_variable_set(:@buf, 'original value')
88
+ assert_equal '2', template.render(scope)
89
+ assert_equal 'original value', scope.instance_variable_get(:@buf)
90
+ end
91
+ end
92
+
93
+ class CompiledERBTemplateTest < Test::Unit::TestCase
94
+ def teardown
95
+ GC.start
96
+ end
97
+
98
+ class Scope
99
+ include Tilt::CompileSite
100
+ end
101
+
102
+ test "compiling template source to a method" do
103
+ template = Tilt::ERBTemplate.new { |t| "Hello World!" }
104
+ template.render(Scope.new)
105
+ method_name = template.send(:compiled_method_name, [].hash)
106
+ method_name = method_name.to_sym if Symbol === Kernel.methods.first
107
+ assert Tilt::CompileSite.instance_methods.include?(method_name),
108
+ "CompileSite.instance_methods.include?(#{method_name.inspect})"
109
+ assert Scope.new.respond_to?(method_name),
110
+ "scope.respond_to?(#{method_name.inspect})"
111
+ end
112
+
113
+ test "loading and evaluating templates on #render" do
114
+ template = Tilt::ERBTemplate.new { |t| "Hello World!" }
115
+ assert_equal "Hello World!", template.render(Scope.new)
116
+ assert_equal "Hello World!", template.render(Scope.new)
117
+ end
118
+
119
+ test "passing locals" do
120
+ template = Tilt::ERBTemplate.new { 'Hey <%= name %>!' }
121
+ assert_equal "Hey Joe!", template.render(Scope.new, :name => 'Joe')
122
+ end
123
+
124
+ test "evaluating in an object scope" do
125
+ template = Tilt::ERBTemplate.new { 'Hey <%= @name %>!' }
126
+ scope = Scope.new
127
+ scope.instance_variable_set :@name, 'Joe'
128
+ assert_equal "Hey Joe!", template.render(scope)
129
+ scope.instance_variable_set :@name, 'Jane'
130
+ assert_equal "Hey Jane!", template.render(scope)
131
+ end
132
+
133
+ test "passing a block for yield" do
134
+ template = Tilt::ERBTemplate.new { 'Hey <%= yield %>!' }
135
+ assert_equal "Hey Joe!", template.render(Scope.new) { 'Joe' }
136
+ assert_equal "Hey Jane!", template.render(Scope.new) { 'Jane' }
137
+ end
138
+
139
+ test "backtrace file and line reporting without locals" do
140
+ data = File.read(__FILE__).split("\n__END__\n").last
141
+ fail unless data[0] == ?<
142
+ template = Tilt::ERBTemplate.new('test.erb', 11) { data }
143
+ begin
144
+ template.render(Scope.new)
145
+ fail 'should have raised an exception'
146
+ rescue => boom
147
+ assert_kind_of NameError, boom
148
+ line = boom.backtrace.first
149
+ file, line, meth = line.split(":")
150
+ assert_equal 'test.erb', file
151
+ assert_equal '13', line
152
+ end
153
+ end
154
+
155
+ test "backtrace file and line reporting with locals" do
156
+ data = File.read(__FILE__).split("\n__END__\n").last
157
+ fail unless data[0] == ?<
158
+ template = Tilt::ERBTemplate.new('test.erb') { data }
159
+ begin
160
+ template.render(Scope.new, :name => 'Joe', :foo => 'bar')
161
+ fail 'should have raised an exception'
162
+ rescue => boom
163
+ assert_kind_of RuntimeError, boom
164
+ line = boom.backtrace.first
165
+ file, line, meth = line.split(":")
166
+ assert_equal 'test.erb', file
167
+ assert_equal '6', line
168
+ end
169
+ end
170
+
171
+ test "default non-stripping trim mode" do
172
+ template = Tilt.new('test.erb') { "\n<%= 1 + 1 %>\n" }
173
+ assert_equal "\n2\n", template.render(Scope.new)
174
+ end
175
+
176
+ test "stripping trim mode" do
177
+ template = Tilt.new('test.erb', :trim => '-') { "\n<%= 1 + 1 -%>\n" }
178
+ assert_equal "\n2", template.render(Scope.new)
179
+ end
180
+
181
+ test "shorthand whole line syntax trim mode" do
182
+ template = Tilt.new('test.erb', :trim => '%') { "\n% if true\nhello\n%end\n" }
183
+ assert_equal "\nhello\n", template.render(Scope.new)
184
+ end
83
185
  end
84
186
 
85
187
  __END__
@@ -9,7 +9,7 @@ begin
9
9
  assert_equal Tilt::ErubisTemplate, Tilt['test.html.erubis']
10
10
  end
11
11
 
12
- test "compiling and evaluating templates on #render" do
12
+ test "preparing and evaluating templates on #render" do
13
13
  template = Tilt::ErubisTemplate.new { |t| "Hello World!" }
14
14
  assert_equal "Hello World!", template.render
15
15
  end
@@ -69,6 +69,14 @@ begin
69
69
  scope.instance_variable_set :@name, 'Joe'
70
70
  assert_equal "Hey Joe!", template.render(scope)
71
71
  end
72
+
73
+ test "using an instance variable as the outvar" do
74
+ template = Tilt::ErubisTemplate.new(nil, :outvar => '@buf') { "<%= 1 + 1 %>" }
75
+ scope = Object.new
76
+ scope.instance_variable_set(:@buf, 'original value')
77
+ assert_equal '2', template.render(scope)
78
+ assert_equal 'original value', scope.instance_variable_get(:@buf)
79
+ end
72
80
  end
73
81
  rescue LoadError => boom
74
82
  warn "Tilt::ErubisTemplate (disabled)\n"
@@ -12,7 +12,7 @@ begin
12
12
  assert_equal Tilt::HamlTemplate, Tilt['test.haml']
13
13
  end
14
14
 
15
- test "compiling and evaluating templates on #render" do
15
+ test "preparing and evaluating templates on #render" do
16
16
  template = Tilt::HamlTemplate.new { |t| "%p Hello World!" }
17
17
  assert_equal "<p>Hello World!</p>\n", template.render
18
18
  end
@@ -66,6 +66,59 @@ begin
66
66
  end
67
67
  end
68
68
 
69
+ class CompiledHamlTemplateTest < Test::Unit::TestCase
70
+ class Scope
71
+ include Tilt::CompileSite
72
+ end
73
+
74
+ test "passing locals" do
75
+ template = Tilt::HamlTemplate.new { "%p= 'Hey ' + name + '!'" }
76
+ assert_equal "<p>Hey Joe!</p>\n", template.render(Scope.new, :name => 'Joe')
77
+ end
78
+
79
+ test "evaluating in an object scope" do
80
+ template = Tilt::HamlTemplate.new { "%p= 'Hey ' + @name + '!'" }
81
+ scope = Scope.new
82
+ scope.instance_variable_set :@name, 'Joe'
83
+ assert_equal "<p>Hey Joe!</p>\n", template.render(scope)
84
+ end
85
+
86
+ test "passing a block for yield" do
87
+ template = Tilt::HamlTemplate.new { "%p= 'Hey ' + yield + '!'" }
88
+ assert_equal "<p>Hey Joe!</p>\n", template.render(Scope.new) { 'Joe' }
89
+ end
90
+
91
+ test "backtrace file and line reporting without locals" do
92
+ data = File.read(__FILE__).split("\n__END__\n").last
93
+ fail unless data[0] == ?%
94
+ template = Tilt::HamlTemplate.new('test.haml', 10) { data }
95
+ begin
96
+ template.render(Scope.new)
97
+ fail 'should have raised an exception'
98
+ rescue => boom
99
+ assert_kind_of NameError, boom
100
+ line = boom.backtrace.first
101
+ file, line, meth = line.split(":")
102
+ assert_equal 'test.haml', file
103
+ assert_equal '12', line
104
+ end
105
+ end
106
+
107
+ test "backtrace file and line reporting with locals" do
108
+ data = File.read(__FILE__).split("\n__END__\n").last
109
+ fail unless data[0] == ?%
110
+ template = Tilt::HamlTemplate.new('test.haml') { data }
111
+ begin
112
+ res = template.render(Scope.new, :name => 'Joe', :foo => 'bar')
113
+ rescue => boom
114
+ assert_kind_of MockError, boom
115
+ line = boom.backtrace.first
116
+ file, line, meth = line.split(":")
117
+ assert_equal 'test.haml', file
118
+ assert_equal '5', line
119
+ end
120
+ end
121
+ end
69
122
  rescue LoadError => boom
70
123
  warn "Tilt::HamlTemplate (disabled)\n"
71
124
  end
@@ -9,7 +9,7 @@ begin
9
9
  assert_equal Tilt::LiquidTemplate, Tilt['test.liquid']
10
10
  end
11
11
 
12
- test "compiling and evaluating templates on #render" do
12
+ test "preparing and evaluating templates on #render" do
13
13
  template = Tilt::LiquidTemplate.new { |t| "Hello World!" }
14
14
  assert_equal "Hello World!", template.render
15
15
  end
@@ -16,7 +16,7 @@ begin
16
16
  assert_equal Tilt::MustacheTemplate, Tilt['test.mustache']
17
17
  end
18
18
 
19
- test "compiling and evaluating templates on #render" do
19
+ test "preparing and evaluating templates on #render" do
20
20
  template = Tilt::MustacheTemplate.new { |t| "Hello World!" }
21
21
  assert_equal "Hello World!", template.render
22
22
  end
@@ -33,7 +33,6 @@ begin
33
33
 
34
34
  test "locating views defined at the top-level" do
35
35
  template = Tilt::MustacheTemplate.new('foo.mustache') { "<p>Hey {{foo}}!</p>" }
36
- template.compile
37
36
  assert_equal Views::Foo, template.engine
38
37
  end
39
38
 
@@ -46,7 +45,6 @@ begin
46
45
 
47
46
  test "locating views defined in a custom namespace" do
48
47
  template = Tilt::MustacheTemplate.new('bizzle.mustache', :namespace => Bar) { "<p>Hello World!</p>" }
49
- template.compile
50
48
  assert_equal Bar::Views::Bizzle, template.engine
51
49
  assert_equal "<p>Hello World!</p>", template.render
52
50
  end
@@ -54,7 +52,6 @@ begin
54
52
  test "locating views in files" do
55
53
  view_path = File.expand_path('../tilt_mustache_views', __FILE__)
56
54
  template = Tilt::MustacheTemplate.new('external.mustache', :view_path => view_path) { "<p>{{hello}}!</p>" }
57
- template.compile
58
55
  assert defined?(Views::External), "external.rb should have been required"
59
56
  assert_equal Views::External, template.engine
60
57
  assert_equal "<p>Stached!</p>", template.render
@@ -17,20 +17,20 @@ begin
17
17
  assert_equal Tilt::RDiscountTemplate, Tilt['test.mkd']
18
18
  end
19
19
 
20
- test "compiling and evaluating templates on #render" do
20
+ test "preparing and evaluating templates on #render" do
21
21
  template = Tilt::RDiscountTemplate.new { |t| "# Hello World!" }
22
22
  assert_equal "<h1>Hello World!</h1>\n", template.render
23
23
  end
24
24
 
25
25
  test "smartypants when :smart is set" do
26
- template = Tilt::RDiscountTemplate.new(nil, :smart => true) { |t|
26
+ template = Tilt::RDiscountTemplate.new(:smart => true) { |t|
27
27
  "OKAY -- 'Smarty Pants'" }
28
28
  assert_equal "<p>OKAY &mdash; &lsquo;Smarty Pants&rsquo;</p>\n",
29
29
  template.render
30
30
  end
31
31
 
32
32
  test "stripping HTML when :filter_html is set" do
33
- template = Tilt::RDiscountTemplate.new(nil, :filter_html => true) { |t|
33
+ template = Tilt::RDiscountTemplate.new(:filter_html => true) { |t|
34
34
  "HELLO <blink>WORLD</blink>" }
35
35
  assert_equal "<p>HELLO &lt;blink>WORLD&lt;/blink></p>\n", template.render
36
36
  end
@@ -9,7 +9,7 @@ begin
9
9
  assert_equal Tilt::RDocTemplate, Tilt['test.rdoc']
10
10
  end
11
11
 
12
- test "compiling and evaluating the template with #render" do
12
+ test "preparing and evaluating the template with #render" do
13
13
  template = Tilt::RDocTemplate.new { |t| "= Hello World!" }
14
14
  assert_equal "<h1>Hello World!</h1>\n", template.render
15
15
  end
@@ -6,7 +6,7 @@ class StringTemplateTest < Test::Unit::TestCase
6
6
  assert_equal Tilt::StringTemplate, Tilt['test.str']
7
7
  end
8
8
 
9
- test "compiling and evaluating templates on #render" do
9
+ test "loading and evaluating templates on #render" do
10
10
  template = Tilt::StringTemplate.new { |t| "Hello World!" }
11
11
  assert_equal "Hello World!", template.render
12
12
  end
@@ -26,6 +26,7 @@ class StringTemplateTest < Test::Unit::TestCase
26
26
  test "passing a block for yield" do
27
27
  template = Tilt::StringTemplate.new { 'Hey #{yield}!' }
28
28
  assert_equal "Hey Joe!", template.render { 'Joe' }
29
+ assert_equal "Hey Moe!", template.render { 'Moe' }
29
30
  end
30
31
 
31
32
  test "multiline templates" do
@@ -66,6 +67,91 @@ class StringTemplateTest < Test::Unit::TestCase
66
67
  end
67
68
  end
68
69
 
70
+
71
+ class CompiledStringTemplateTest < Test::Unit::TestCase
72
+ def teardown
73
+ GC.start
74
+ end
75
+
76
+ class Scope
77
+ include Tilt::CompileSite
78
+ end
79
+
80
+ test "compiling template source to a method" do
81
+ template = Tilt::StringTemplate.new { |t| "Hello World!" }
82
+ template.render(Scope.new)
83
+ method_name = template.send(:compiled_method_name, [].hash)
84
+ method_name = method_name.to_sym if Symbol === Kernel.methods.first
85
+ assert Tilt::CompileSite.instance_methods.include?(method_name),
86
+ "CompileSite.instance_methods.include?(#{method_name.inspect})"
87
+ assert Scope.new.respond_to?(method_name),
88
+ "scope.respond_to?(#{method_name.inspect})"
89
+ end
90
+
91
+ test "loading and evaluating templates on #render" do
92
+ template = Tilt::StringTemplate.new { |t| "Hello World!" }
93
+ assert_equal "Hello World!", template.render(Scope.new)
94
+ end
95
+
96
+ test "passing locals" do
97
+ template = Tilt::StringTemplate.new { 'Hey #{name}!' }
98
+ assert_equal "Hey Joe!", template.render(Scope.new, :name => 'Joe')
99
+ assert_equal "Hey Moe!", template.render(Scope.new, :name => 'Moe')
100
+ end
101
+
102
+ test "evaluating in an object scope" do
103
+ template = Tilt::StringTemplate.new { 'Hey #{@name}!' }
104
+ scope = Scope.new
105
+ scope.instance_variable_set :@name, 'Joe'
106
+ assert_equal "Hey Joe!", template.render(scope)
107
+ scope.instance_variable_set :@name, 'Moe'
108
+ assert_equal "Hey Moe!", template.render(scope)
109
+ end
110
+
111
+ test "passing a block for yield" do
112
+ template = Tilt::StringTemplate.new { 'Hey #{yield}!' }
113
+ assert_equal "Hey Joe!", template.render(Scope.new) { 'Joe' }
114
+ assert_equal "Hey Moe!", template.render(Scope.new) { 'Moe' }
115
+ end
116
+
117
+ test "multiline templates" do
118
+ template = Tilt::StringTemplate.new { "Hello\nWorld!\n" }
119
+ assert_equal "Hello\nWorld!\n", template.render(Scope.new)
120
+ end
121
+
122
+ test "backtrace file and line reporting without locals" do
123
+ data = File.read(__FILE__).split("\n__END__\n").last
124
+ fail unless data[0] == ?<
125
+ template = Tilt::StringTemplate.new('test.str', 11) { data }
126
+ begin
127
+ template.render(Scope.new)
128
+ fail 'should have raised an exception'
129
+ rescue => boom
130
+ assert_kind_of NameError, boom
131
+ line = boom.backtrace.first
132
+ file, line, meth = line.split(":")
133
+ assert_equal 'test.str', file
134
+ assert_equal '13', line
135
+ end
136
+ end
137
+
138
+ test "backtrace file and line reporting with locals" do
139
+ data = File.read(__FILE__).split("\n__END__\n").last
140
+ fail unless data[0] == ?<
141
+ template = Tilt::StringTemplate.new('test.str') { data }
142
+ begin
143
+ template.render(Scope.new, :name => 'Joe', :foo => 'bar')
144
+ fail 'should have raised an exception'
145
+ rescue => boom
146
+ assert_kind_of RuntimeError, boom
147
+ line = boom.backtrace.first
148
+ file, line, meth = line.split(":")
149
+ assert_equal 'test.str', file
150
+ assert_equal '6', line
151
+ end
152
+ end
153
+ end
154
+
69
155
  __END__
70
156
  <html>
71
157
  <body>
@@ -2,44 +2,50 @@ require 'contest'
2
2
  require 'tilt'
3
3
 
4
4
  class TiltTemplateTest < Test::Unit::TestCase
5
+
6
+ class MockTemplate < Tilt::Template
7
+ def prepare
8
+ end
9
+ end
10
+
5
11
  test "needs a file or block" do
6
12
  assert_raise(ArgumentError) { Tilt::Template.new }
7
13
  end
8
14
 
9
15
  test "initializing with a file" do
10
- inst = Tilt::Template.new('foo.erb')
16
+ inst = MockTemplate.new('foo.erb') {}
11
17
  assert_equal 'foo.erb', inst.file
12
18
  end
13
19
 
14
20
  test "initializing with a file and line" do
15
- inst = Tilt::Template.new('foo.erb', 55)
21
+ inst = MockTemplate.new('foo.erb', 55) {}
16
22
  assert_equal 'foo.erb', inst.file
17
23
  assert_equal 55, inst.line
18
24
  end
19
25
 
20
26
  test "uses correct eval_file" do
21
- inst = Tilt::Template.new('foo.erb', 55)
27
+ inst = MockTemplate.new('foo.erb', 55) {}
22
28
  assert_equal 'foo.erb', inst.eval_file
23
29
  end
24
30
 
25
31
  test "uses a default filename for #eval_file when no file provided" do
26
- inst = Tilt::Template.new { 'Hi' }
32
+ inst = MockTemplate.new { 'Hi' }
27
33
  assert_not_nil inst.eval_file
28
34
  assert !inst.eval_file.include?("\n")
29
35
  end
30
36
 
31
37
  test "calculating template's #basename" do
32
- inst = Tilt::Template.new('/tmp/templates/foo.html.erb')
38
+ inst = MockTemplate.new('/tmp/templates/foo.html.erb') {}
33
39
  assert_equal 'foo.html.erb', inst.basename
34
40
  end
35
41
 
36
42
  test "calculating the template's #name" do
37
- inst = Tilt::Template.new('/tmp/templates/foo.html.erb')
43
+ inst = MockTemplate.new('/tmp/templates/foo.html.erb') {}
38
44
  assert_equal 'foo', inst.name
39
45
  end
40
46
 
41
47
  test "initializing with a data loading block" do
42
- Tilt::Template.new { |template| "Hello World!" }
48
+ MockTemplate.new { |template| "Hello World!" }
43
49
  end
44
50
 
45
51
  class InitializingMockTemplate < Tilt::Template
@@ -52,7 +58,7 @@ class TiltTemplateTest < Test::Unit::TestCase
52
58
  @@initialized_count += 1
53
59
  end
54
60
 
55
- def compile!
61
+ def prepare
56
62
  end
57
63
  end
58
64
 
@@ -68,43 +74,42 @@ class TiltTemplateTest < Test::Unit::TestCase
68
74
  assert_equal 1, InitializingMockTemplate.initialized_count
69
75
  end
70
76
 
71
- class CompilingMockTemplate < Tilt::Template
77
+ class PreparingMockTemplate < Tilt::Template
72
78
  include Test::Unit::Assertions
73
- def compile!
79
+ def prepare
74
80
  assert !data.nil?
75
- @compiled = true
81
+ @prepared = true
76
82
  end
77
- def compiled? ; @compiled ; end
83
+ def prepared? ; @prepared ; end
78
84
  end
79
85
 
80
- test "raises NotImplementedError when #compile! not defined" do
81
- inst = Tilt::Template.new { |template| "Hello World!" }
82
- assert_raise(NotImplementedError) { inst.render }
86
+ test "raises NotImplementedError when #prepare not defined" do
87
+ assert_raise(NotImplementedError) { Tilt::Template.new { |template| "Hello World!" } }
83
88
  end
84
89
 
85
90
  test "raises NotImplementedError when #evaluate or #template_source not defined" do
86
- inst = CompilingMockTemplate.new { |t| "Hello World!" }
91
+ inst = PreparingMockTemplate.new { |t| "Hello World!" }
87
92
  assert_raise(NotImplementedError) { inst.render }
88
- assert inst.compiled?
93
+ assert inst.prepared?
89
94
  end
90
95
 
91
- class SimpleMockTemplate < CompilingMockTemplate
96
+ class SimpleMockTemplate < PreparingMockTemplate
92
97
  include Test::Unit::Assertions
93
98
  def evaluate(scope, locals, &block)
94
- assert compiled?
99
+ assert prepared?
95
100
  assert !scope.nil?
96
101
  assert !locals.nil?
97
102
  "<em>#{@data}</em>"
98
103
  end
99
104
  end
100
105
 
101
- test "compiles and evaluates the template on #render" do
106
+ test "prepares and evaluates the template on #render" do
102
107
  inst = SimpleMockTemplate.new { |t| "Hello World!" }
103
108
  assert_equal "<em>Hello World!</em>", inst.render
104
- assert inst.compiled?
109
+ assert inst.prepared?
105
110
  end
106
111
 
107
- class SourceGeneratingMockTemplate < CompilingMockTemplate
112
+ class SourceGeneratingMockTemplate < PreparingMockTemplate
108
113
  def template_source
109
114
  "foo = [] ; foo << %Q{#{data}} ; foo.join"
110
115
  end
@@ -113,7 +118,7 @@ class TiltTemplateTest < Test::Unit::TestCase
113
118
  test "template_source with locals" do
114
119
  inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{name}!' }
115
120
  assert_equal "Hey Joe!", inst.render(Object.new, :name => 'Joe')
116
- assert inst.compiled?
121
+ assert inst.prepared?
117
122
  end
118
123
 
119
124
  class Person
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
4
 
5
5
  s.name = 'tilt'
6
- s.version = '0.6'
7
- s.date = '2010-02-22'
6
+ s.version = '0.7'
7
+ s.date = '2010-03-04'
8
8
 
9
9
  s.description = "Generic interface to multiple Ruby template engines"
10
10
  s.summary = s.description
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  test/tilt_buildertemplate_test.rb
24
24
  test/tilt_cache_test.rb
25
25
  test/tilt_coffeetemplate_test.rb
26
+ test/tilt_compilesite_test.rb
26
27
  test/tilt_erbtemplate_test.rb
27
28
  test/tilt_erubistemplate_test.rb
28
29
  test/tilt_hamltemplate_test.rb
@@ -50,6 +51,7 @@ Gem::Specification.new do |s|
50
51
  s.add_development_dependency 'rdiscount'
51
52
  s.add_development_dependency 'liquid'
52
53
  s.add_development_dependency 'less'
54
+ s.add_development_dependency 'coffee-script'
53
55
 
54
56
  s.extra_rdoc_files = %w[COPYING]
55
57
 
metadata CHANGED
@@ -4,8 +4,8 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 6
8
- version: "0.6"
7
+ - 7
8
+ version: "0.7"
9
9
  platform: ruby
10
10
  authors:
11
11
  - Ryan Tomayko
@@ -13,7 +13,7 @@ autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
15
 
16
- date: 2010-02-22 00:00:00 -08:00
16
+ date: 2010-03-04 00:00:00 -08:00
17
17
  default_executable:
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
@@ -112,6 +112,18 @@ dependencies:
112
112
  version: "0"
113
113
  type: :development
114
114
  version_requirements: *id008
115
+ - !ruby/object:Gem::Dependency
116
+ name: coffee-script
117
+ prerelease: false
118
+ requirement: &id009 !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ type: :development
126
+ version_requirements: *id009
115
127
  description: Generic interface to multiple Ruby template engines
116
128
  email: r@tomayko.com
117
129
  executables: []
@@ -130,6 +142,7 @@ files:
130
142
  - test/tilt_buildertemplate_test.rb
131
143
  - test/tilt_cache_test.rb
132
144
  - test/tilt_coffeetemplate_test.rb
145
+ - test/tilt_compilesite_test.rb
133
146
  - test/tilt_erbtemplate_test.rb
134
147
  - test/tilt_erubistemplate_test.rb
135
148
  - test/tilt_hamltemplate_test.rb