tilt 0.6 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
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