sinatra 1.0 → 1.1.a

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sinatra might be problematic. Click here for more details.

Files changed (57) hide show
  1. data/CHANGES +108 -1
  2. data/LICENSE +1 -1
  3. data/README.de.rdoc +1024 -0
  4. data/README.es.rdoc +1047 -0
  5. data/README.fr.rdoc +1038 -0
  6. data/README.hu.rdoc +607 -0
  7. data/README.jp.rdoc +473 -15
  8. data/README.rdoc +429 -41
  9. data/Rakefile +17 -6
  10. data/lib/sinatra/base.rb +357 -158
  11. data/lib/sinatra/showexceptions.rb +9 -1
  12. data/sinatra.gemspec +52 -9
  13. data/test/builder_test.rb +25 -1
  14. data/test/coffee_test.rb +88 -0
  15. data/test/encoding_test.rb +18 -0
  16. data/test/filter_test.rb +61 -2
  17. data/test/hello.mab +1 -0
  18. data/test/helper.rb +1 -0
  19. data/test/helpers_test.rb +141 -37
  20. data/test/less_test.rb +26 -2
  21. data/test/liquid_test.rb +58 -0
  22. data/test/markaby_test.rb +58 -0
  23. data/test/markdown_test.rb +35 -0
  24. data/test/nokogiri_test.rb +69 -0
  25. data/test/radius_test.rb +59 -0
  26. data/test/rdoc_test.rb +34 -0
  27. data/test/request_test.rb +12 -0
  28. data/test/routing_test.rb +35 -1
  29. data/test/sass_test.rb +46 -16
  30. data/test/scss_test.rb +88 -0
  31. data/test/settings_test.rb +32 -0
  32. data/test/sinatra_test.rb +4 -0
  33. data/test/static_test.rb +64 -0
  34. data/test/templates_test.rb +55 -1
  35. data/test/textile_test.rb +34 -0
  36. data/test/views/ascii.haml +2 -0
  37. data/test/views/explicitly_nested.str +1 -0
  38. data/test/views/hello.coffee +1 -0
  39. data/test/views/hello.liquid +1 -0
  40. data/test/views/hello.mab +1 -0
  41. data/test/views/hello.md +1 -0
  42. data/test/views/hello.nokogiri +1 -0
  43. data/test/views/hello.radius +1 -0
  44. data/test/views/hello.rdoc +1 -0
  45. data/test/views/hello.sass +1 -1
  46. data/test/views/hello.scss +3 -0
  47. data/test/views/hello.str +1 -0
  48. data/test/views/hello.textile +1 -0
  49. data/test/views/layout2.liquid +2 -0
  50. data/test/views/layout2.mab +2 -0
  51. data/test/views/layout2.nokogiri +3 -0
  52. data/test/views/layout2.radius +2 -0
  53. data/test/views/layout2.str +2 -0
  54. data/test/views/nested.str +1 -0
  55. data/test/views/utf8.haml +2 -0
  56. metadata +240 -33
  57. data/lib/sinatra/tilt.rb +0 -746
@@ -1,746 +0,0 @@
1
- require 'digest/md5'
2
-
3
- module Tilt
4
- VERSION = '0.8'
5
-
6
- @template_mappings = {}
7
-
8
- # Hash of template path pattern => template implementation class mappings.
9
- def self.mappings
10
- @template_mappings
11
- end
12
-
13
- # Register a template implementation by file extension.
14
- def self.register(ext, template_class)
15
- ext = ext.to_s.sub(/^\./, '')
16
- mappings[ext.downcase] = template_class
17
- end
18
-
19
- # Create a new template for the given file using the file's extension
20
- # to determine the the template mapping.
21
- def self.new(file, line=nil, options={}, &block)
22
- if template_class = self[file]
23
- template_class.new(file, line, options, &block)
24
- else
25
- fail "No template engine registered for #{File.basename(file)}"
26
- end
27
- end
28
-
29
- # Lookup a template class for the given filename or file
30
- # extension. Return nil when no implementation is found.
31
- def self.[](file)
32
- if @template_mappings.key?(pattern = file.to_s.downcase)
33
- @template_mappings[pattern]
34
- elsif @template_mappings.key?(pattern = File.basename(pattern))
35
- @template_mappings[pattern]
36
- else
37
- while !pattern.empty?
38
- if @template_mappings.key?(pattern)
39
- return @template_mappings[pattern]
40
- else
41
- pattern = pattern.sub(/^[^.]*\.?/, '')
42
- end
43
- end
44
- nil
45
- end
46
- end
47
-
48
- # Mixin allowing template compilation on scope objects.
49
- #
50
- # Including this module in scope objects passed to Template#render
51
- # causes template source to be compiled to methods the first time they're
52
- # used. This can yield significant (5x-10x) performance increases for
53
- # templates that support it (ERB, Erubis, Builder).
54
- #
55
- # It's also possible (though not recommended) to include this module in
56
- # Object to enable template compilation globally. The downside is that
57
- # the template methods will polute the global namespace and could lead to
58
- # unexpected behavior.
59
- module CompileSite
60
- def __tilt__
61
- end
62
- end
63
-
64
- # Base class for template implementations. Subclasses must implement
65
- # the #prepare method and one of the #evaluate or #template_source
66
- # methods.
67
- class Template
68
- # Template source; loaded from a file or given directly.
69
- attr_reader :data
70
-
71
- # The name of the file where the template data was loaded from.
72
- attr_reader :file
73
-
74
- # The line number in #file where template data was loaded from.
75
- attr_reader :line
76
-
77
- # A Hash of template engine specific options. This is passed directly
78
- # to the underlying engine and is not used by the generic template
79
- # interface.
80
- attr_reader :options
81
-
82
- # Used to determine if this class's initialize_engine method has
83
- # been called yet.
84
- @engine_initialized = false
85
- class << self
86
- attr_accessor :engine_initialized
87
- alias engine_initialized? engine_initialized
88
- end
89
-
90
- # Create a new template with the file, line, and options specified. By
91
- # default, template data is read from the file. When a block is given,
92
- # it should read template data and return as a String. When file is nil,
93
- # a block is required.
94
- #
95
- # All arguments are optional.
96
- def initialize(file=nil, line=1, options={}, &block)
97
- @file, @line, @options = nil, 1, {}
98
-
99
- [options, line, file].compact.each do |arg|
100
- case
101
- when arg.respond_to?(:to_str) ; @file = arg.to_str
102
- when arg.respond_to?(:to_int) ; @line = arg.to_int
103
- when arg.respond_to?(:to_hash) ; @options = arg.to_hash
104
- else raise TypeError
105
- end
106
- end
107
-
108
- raise ArgumentError, "file or block required" if (@file || block).nil?
109
-
110
- # call the initialize_engine method if this is the very first time
111
- # an instance of this class has been created.
112
- if !self.class.engine_initialized?
113
- initialize_engine
114
- self.class.engine_initialized = true
115
- end
116
-
117
- # used to generate unique method names for template compilation
118
- @stamp = (Time.now.to_f * 10000).to_i
119
- @compiled_method_names = {}
120
-
121
- # load template data and prepare
122
- @reader = block || lambda { |t| File.read(@file) }
123
- @data = @reader.call(self)
124
- prepare
125
- end
126
-
127
- # Render the template in the given scope with the locals specified. If a
128
- # block is given, it is typically available within the template via
129
- # +yield+.
130
- def render(scope=Object.new, locals={}, &block)
131
- evaluate scope, locals || {}, &block
132
- end
133
-
134
- # The basename of the template file.
135
- def basename(suffix='')
136
- File.basename(file, suffix) if file
137
- end
138
-
139
- # The template file's basename with all extensions chomped off.
140
- def name
141
- basename.split('.', 2).first if basename
142
- end
143
-
144
- # The filename used in backtraces to describe the template.
145
- def eval_file
146
- file || '(__TEMPLATE__)'
147
- end
148
-
149
- protected
150
- # Called once and only once for each template subclass the first time
151
- # the template class is initialized. This should be used to require the
152
- # underlying template library and perform any initial setup.
153
- def initialize_engine
154
- end
155
-
156
- # Like Kernel::require but issues a warning urging a manual require when
157
- # running under a threaded environment.
158
- def require_template_library(name)
159
- if Thread.list.size > 1
160
- warn "WARN: tilt autoloading '#{name}' in a non thread-safe way; " +
161
- "explicit require '#{name}' suggested."
162
- end
163
- require name
164
- end
165
-
166
- # Do whatever preparation is necessary to setup the underlying template
167
- # engine. Called immediately after template data is loaded. Instance
168
- # variables set in this method are available when #evaluate is called.
169
- #
170
- # Subclasses must provide an implementation of this method.
171
- def prepare
172
- if respond_to?(:compile!)
173
- # backward compat with tilt < 0.6; just in case
174
- warn 'Tilt::Template#compile! is deprecated; implement #prepare instead.'
175
- compile!
176
- else
177
- raise NotImplementedError
178
- end
179
- end
180
-
181
- # Process the template and return the result. When the scope mixes in
182
- # the Tilt::CompileSite module, the template is compiled to a method and
183
- # reused given identical locals keys. When the scope object
184
- # does not mix in the CompileSite module, the template source is
185
- # evaluated with instance_eval. In any case, template executation
186
- # is guaranteed to be performed in the scope object with the locals
187
- # specified and with support for yielding to the block.
188
- def evaluate(scope, locals, &block)
189
- if scope.respond_to?(:__tilt__)
190
- method_name = compiled_method_name(locals.keys)
191
- if scope.respond_to?(method_name)
192
- scope.send(method_name, locals, &block)
193
- else
194
- compile_template_method(method_name, locals)
195
- scope.send(method_name, locals, &block)
196
- end
197
- else
198
- evaluate_source(scope, locals, &block)
199
- end
200
- end
201
-
202
- # Generates all template source by combining the preamble, template, and
203
- # postamble and returns a two-tuple of the form: [source, offset], where
204
- # source is the string containing (Ruby) source code for the template and
205
- # offset is the integer line offset where line reporting should begin.
206
- #
207
- # Template subclasses may override this method when they need complete
208
- # control over source generation or want to adjust the default line
209
- # offset. In most cases, overriding the #precompiled_template method is
210
- # easier and more appropriate.
211
- def precompiled(locals)
212
- preamble = precompiled_preamble(locals)
213
- parts = [
214
- preamble,
215
- precompiled_template(locals),
216
- precompiled_postamble(locals)
217
- ]
218
- [parts.join("\n"), preamble.count("\n") + 1]
219
- end
220
-
221
- # A string containing the (Ruby) source code for the template. The
222
- # default Template#evaluate implementation requires either this method
223
- # or the #precompiled method be overridden. When defined, the base
224
- # Template guarantees correct file/line handling, locals support, custom
225
- # scopes, and support for template compilation when the scope object
226
- # allows it.
227
- def precompiled_template(locals)
228
- raise NotImplementedError
229
- end
230
-
231
- # Generates preamble code for initializing template state, and performing
232
- # locals assignment. The default implementation performs locals
233
- # assignment only. Lines included in the preamble are subtracted from the
234
- # source line offset, so adding code to the preamble does not effect line
235
- # reporting in Kernel::caller and backtraces.
236
- def precompiled_preamble(locals)
237
- locals.map { |k,v| "#{k} = locals[:#{k}]" }.join("\n")
238
- end
239
-
240
- # Generates postamble code for the precompiled template source. The
241
- # string returned from this method is appended to the precompiled
242
- # template source.
243
- def precompiled_postamble(locals)
244
- ''
245
- end
246
-
247
- # The unique compiled method name for the locals keys provided.
248
- def compiled_method_name(locals_keys)
249
- @compiled_method_names[locals_keys] ||=
250
- generate_compiled_method_name(locals_keys)
251
- end
252
-
253
- private
254
- # Evaluate the template source in the context of the scope object.
255
- def evaluate_source(scope, locals, &block)
256
- source, offset = precompiled(locals)
257
- scope.instance_eval(source, eval_file, line - offset)
258
- end
259
-
260
- # JRuby doesn't allow Object#instance_eval to yield to the block it's
261
- # closed over. This is by design and (ostensibly) something that will
262
- # change in MRI, though no current MRI version tested (1.8.6 - 1.9.2)
263
- # exhibits the behavior. More info here:
264
- #
265
- # http://jira.codehaus.org/browse/JRUBY-2599
266
- #
267
- # Additionally, JRuby's eval line reporting is off by one compared to
268
- # all MRI versions tested.
269
- #
270
- # We redefine evaluate_source to work around both issues.
271
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
272
- undef evaluate_source
273
- def evaluate_source(scope, locals, &block)
274
- source, offset = precompiled(locals)
275
- file, lineno = eval_file, (line - offset) - 1
276
- scope.instance_eval { Kernel::eval(source, binding, file, lineno) }
277
- end
278
- end
279
-
280
- def generate_compiled_method_name(locals_keys)
281
- parts = [object_id, @stamp] + locals_keys.map { |k| k.to_s }.sort
282
- digest = Digest::MD5.hexdigest(parts.join(':'))
283
- "__tilt_#{digest}"
284
- end
285
-
286
- def compile_template_method(method_name, locals)
287
- source, offset = precompiled(locals)
288
- offset += 1
289
- CompileSite.module_eval <<-RUBY, eval_file, line - offset
290
- def #{method_name}(locals)
291
- #{source}
292
- end
293
- RUBY
294
-
295
- ObjectSpace.define_finalizer self,
296
- Template.compiled_template_method_remover(CompileSite, method_name)
297
- end
298
-
299
- def self.compiled_template_method_remover(site, method_name)
300
- proc { |oid| garbage_collect_compiled_template_method(site, method_name) }
301
- end
302
-
303
- def self.garbage_collect_compiled_template_method(site, method_name)
304
- site.module_eval do
305
- begin
306
- remove_method(method_name)
307
- rescue NameError
308
- # method was already removed (ruby >= 1.9)
309
- end
310
- end
311
- end
312
- end
313
-
314
- # Extremely simple template cache implementation. Calling applications
315
- # create a Tilt::Cache instance and use #fetch with any set of hashable
316
- # arguments (such as those to Tilt.new):
317
- # cache = Tilt::Cache.new
318
- # cache.fetch(path, line, options) { Tilt.new(path, line, options) }
319
- #
320
- # Subsequent invocations return the already loaded template object.
321
- class Cache
322
- def initialize
323
- @cache = {}
324
- end
325
-
326
- def fetch(*key)
327
- @cache[key] ||= yield
328
- end
329
-
330
- def clear
331
- @cache = {}
332
- end
333
- end
334
-
335
-
336
- # Template Implementations ================================================
337
-
338
-
339
- # The template source is evaluated as a Ruby string. The #{} interpolation
340
- # syntax can be used to generated dynamic output.
341
- class StringTemplate < Template
342
- def prepare
343
- @code = "%Q{#{data}}"
344
- end
345
-
346
- def precompiled_template(locals)
347
- @code
348
- end
349
- end
350
- register 'str', StringTemplate
351
-
352
-
353
- # ERB template implementation. See:
354
- # http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html
355
- class ERBTemplate < Template
356
- def initialize_engine
357
- return if defined? ::ERB
358
- require_template_library 'erb'
359
- end
360
-
361
- def prepare
362
- @outvar = (options[:outvar] || '_erbout').to_s
363
- @engine = ::ERB.new(data, options[:safe], options[:trim], @outvar)
364
- end
365
-
366
- def precompiled_template(locals)
367
- @engine.src
368
- end
369
-
370
- def precompiled_preamble(locals)
371
- <<-RUBY
372
- begin
373
- __original_outvar = #{@outvar} if defined?(#{@outvar})
374
- #{super}
375
- RUBY
376
- end
377
-
378
- def precompiled_postamble(locals)
379
- <<-RUBY
380
- #{super}
381
- ensure
382
- #{@outvar} = __original_outvar
383
- end
384
- RUBY
385
- end
386
-
387
- # ERB generates a line to specify the character coding of the generated
388
- # source in 1.9. Account for this in the line offset.
389
- if RUBY_VERSION >= '1.9.0'
390
- def precompiled(locals)
391
- source, offset = super
392
- [source, offset + 1]
393
- end
394
- end
395
- end
396
-
397
- %w[erb rhtml].each { |ext| register ext, ERBTemplate }
398
-
399
-
400
- # Erubis template implementation. See:
401
- # http://www.kuwata-lab.com/erubis/
402
- class ErubisTemplate < ERBTemplate
403
- def initialize_engine
404
- return if defined? ::Erubis
405
- require_template_library 'erubis'
406
- end
407
-
408
- def prepare
409
- @options.merge!(:preamble => false, :postamble => false)
410
- @outvar = (options.delete(:outvar) || '_erbout').to_s
411
- @engine = ::Erubis::Eruby.new(data, options)
412
- end
413
-
414
- def precompiled_preamble(locals)
415
- [super, "#{@outvar} = _buf = ''"].join("\n")
416
- end
417
-
418
- def precompiled_postamble(locals)
419
- ["_buf", super].join("\n")
420
- end
421
-
422
- # Erubis doesn't have ERB's line-off-by-one under 1.9 problem.
423
- # Override and adjust back.
424
- if RUBY_VERSION >= '1.9.0'
425
- def precompiled(locals)
426
- source, offset = super
427
- [source, offset - 1]
428
- end
429
- end
430
- end
431
- register 'erubis', ErubisTemplate
432
-
433
-
434
- # Haml template implementation. See:
435
- # http://haml.hamptoncatlin.com/
436
- class HamlTemplate < Template
437
- def initialize_engine
438
- return if defined? ::Haml::Engine
439
- require_template_library 'haml'
440
- end
441
-
442
- def prepare
443
- options = @options.merge(:filename => eval_file, :line => line)
444
- @engine = ::Haml::Engine.new(data, options)
445
- end
446
-
447
- def evaluate(scope, locals, &block)
448
- if @engine.respond_to?(:precompiled_method_return_value, true)
449
- super
450
- else
451
- @engine.render(scope, locals, &block)
452
- end
453
- end
454
-
455
- # Precompiled Haml source. Taken from the precompiled_with_ambles
456
- # method in Haml::Precompiler:
457
- # http://github.com/nex3/haml/blob/master/lib/haml/precompiler.rb#L111-126
458
- def precompiled_template(locals)
459
- @engine.precompiled
460
- end
461
-
462
- def precompiled_preamble(locals)
463
- local_assigns = super
464
- @engine.instance_eval do
465
- <<-RUBY
466
- begin
467
- extend Haml::Helpers
468
- _hamlout = @haml_buffer = Haml::Buffer.new(@haml_buffer, #{options_for_buffer.inspect})
469
- _erbout = _hamlout.buffer
470
- __in_erb_template = true
471
- _haml_locals = locals
472
- #{local_assigns}
473
- RUBY
474
- end
475
- end
476
-
477
- def precompiled_postamble(locals)
478
- @engine.instance_eval do
479
- <<-RUBY
480
- #{precompiled_method_return_value}
481
- ensure
482
- @haml_buffer = @haml_buffer.upper
483
- end
484
- RUBY
485
- end
486
- end
487
- end
488
- register 'haml', HamlTemplate
489
-
490
-
491
- # Sass template implementation. See:
492
- # http://haml.hamptoncatlin.com/
493
- #
494
- # Sass templates do not support object scopes, locals, or yield.
495
- class SassTemplate < Template
496
- def initialize_engine
497
- return if defined? ::Sass::Engine
498
- require_template_library 'sass'
499
- end
500
-
501
- def prepare
502
- @engine = ::Sass::Engine.new(data, sass_options)
503
- end
504
-
505
- def evaluate(scope, locals, &block)
506
- @output ||= @engine.render
507
- end
508
-
509
- private
510
- def sass_options
511
- options.merge(:filename => eval_file, :line => line)
512
- end
513
- end
514
- register 'sass', SassTemplate
515
-
516
-
517
- # Lessscss template implementation. See:
518
- # http://lesscss.org/
519
- #
520
- # Less templates do not support object scopes, locals, or yield.
521
- class LessTemplate < Template
522
- def initialize_engine
523
- return if defined? ::Less::Engine
524
- require_template_library 'less'
525
- end
526
-
527
- def prepare
528
- @engine = ::Less::Engine.new(data)
529
- end
530
-
531
- def evaluate(scope, locals, &block)
532
- @engine.to_css
533
- end
534
- end
535
- register 'less', LessTemplate
536
-
537
-
538
- # Builder template implementation. See:
539
- # http://builder.rubyforge.org/
540
- class BuilderTemplate < Template
541
- def initialize_engine
542
- return if defined?(::Builder)
543
- require_template_library 'builder'
544
- end
545
-
546
- def prepare
547
- end
548
-
549
- def evaluate(scope, locals, &block)
550
- xml = ::Builder::XmlMarkup.new(:indent => 2)
551
- if data.respond_to?(:to_str)
552
- locals[:xml] = xml
553
- super(scope, locals, &block)
554
- elsif data.kind_of?(Proc)
555
- data.call(xml)
556
- end
557
- xml.target!
558
- end
559
-
560
- def precompiled_template(locals)
561
- data.to_str
562
- end
563
- end
564
- register 'builder', BuilderTemplate
565
-
566
-
567
- # Liquid template implementation. See:
568
- # http://liquid.rubyforge.org/
569
- #
570
- # Liquid is designed to be a *safe* template system and threfore
571
- # does not provide direct access to execuatable scopes. In order to
572
- # support a +scope+, the +scope+ must be able to represent itself
573
- # as a hash by responding to #to_h. If the +scope+ does not respond
574
- # to #to_h it will be ignored.
575
- #
576
- # LiquidTemplate does not support yield blocks.
577
- #
578
- # It's suggested that your program require 'liquid' at load
579
- # time when using this template engine.
580
- class LiquidTemplate < Template
581
- def initialize_engine
582
- return if defined? ::Liquid::Template
583
- require_template_library 'liquid'
584
- end
585
-
586
- def prepare
587
- @engine = ::Liquid::Template.parse(data)
588
- end
589
-
590
- def evaluate(scope, locals, &block)
591
- locals = locals.inject({}){ |h,(k,v)| h[k.to_s] = v ; h }
592
- if scope.respond_to?(:to_h)
593
- scope = scope.to_h.inject({}){ |h,(k,v)| h[k.to_s] = v ; h }
594
- locals = scope.merge(locals)
595
- end
596
- locals['yield'] = block.nil? ? '' : yield
597
- locals['content'] = locals['yield']
598
- @engine.render(locals)
599
- end
600
- end
601
- register 'liquid', LiquidTemplate
602
-
603
-
604
- # Discount Markdown implementation. See:
605
- # http://github.com/rtomayko/rdiscount
606
- #
607
- # RDiscount is a simple text filter. It does not support +scope+ or
608
- # +locals+. The +:smart+ and +:filter_html+ options may be set true
609
- # to enable those flags on the underlying RDiscount object.
610
- class RDiscountTemplate < Template
611
- def flags
612
- [:smart, :filter_html].select { |flag| options[flag] }
613
- end
614
-
615
- def initialize_engine
616
- return if defined? ::RDiscount
617
- require_template_library 'rdiscount'
618
- end
619
-
620
- def prepare
621
- @engine = RDiscount.new(data, *flags)
622
- @output = nil
623
- end
624
-
625
- def evaluate(scope, locals, &block)
626
- @output ||= @engine.to_html
627
- end
628
- end
629
- register 'markdown', RDiscountTemplate
630
- register 'mkd', RDiscountTemplate
631
- register 'md', RDiscountTemplate
632
-
633
-
634
- # RedCloth implementation. See:
635
- # http://redcloth.org/
636
- class RedClothTemplate < Template
637
- def initialize_engine
638
- return if defined? ::RedCloth
639
- require_template_library 'redcloth'
640
- end
641
-
642
- def prepare
643
- @engine = RedCloth.new(data)
644
- @output = nil
645
- end
646
-
647
- def evaluate(scope, locals, &block)
648
- @output ||= @engine.to_html
649
- end
650
- end
651
- register 'textile', RedClothTemplate
652
-
653
-
654
- # Mustache is written and maintained by Chris Wanstrath. See:
655
- # http://github.com/defunkt/mustache
656
- #
657
- # When a scope argument is provided to MustacheTemplate#render, the
658
- # instance variables are copied from the scope object to the Mustache
659
- # view.
660
- class MustacheTemplate < Template
661
- attr_reader :engine
662
-
663
- def initialize_engine
664
- return if defined? ::Mustache
665
- require_template_library 'mustache'
666
- end
667
-
668
- def prepare
669
- Mustache.view_namespace = options[:namespace]
670
- Mustache.view_path = options[:view_path] || options[:mustaches]
671
- @engine = options[:view] || Mustache.view_class(name)
672
- options.each do |key, value|
673
- next if %w[view view_path namespace mustaches].include?(key.to_s)
674
- @engine.send("#{key}=", value) if @engine.respond_to? "#{key}="
675
- end
676
- end
677
-
678
- def evaluate(scope=nil, locals={}, &block)
679
- instance = @engine.new
680
-
681
- # copy instance variables from scope to the view
682
- scope.instance_variables.each do |name|
683
- instance.instance_variable_set(name, scope.instance_variable_get(name))
684
- end
685
-
686
- # locals get added to the view's context
687
- locals.each do |local, value|
688
- instance[local] = value
689
- end
690
-
691
- # if we're passed a block it's a subview. Sticking it in yield
692
- # lets us use {{yield}} in layout.html to render the actual page.
693
- instance[:yield] = block.call if block
694
-
695
- instance.template = data unless instance.compiled?
696
-
697
- instance.to_html
698
- end
699
- end
700
- register 'mustache', MustacheTemplate
701
-
702
-
703
- # RDoc template. See:
704
- # http://rdoc.rubyforge.org/
705
- #
706
- # It's suggested that your program require 'rdoc/markup' and
707
- # 'rdoc/markup/to_html' at load time when using this template
708
- # engine.
709
- class RDocTemplate < Template
710
- def initialize_engine
711
- return if defined?(::RDoc::Markup)
712
- require_template_library 'rdoc/markup'
713
- require_template_library 'rdoc/markup/to_html'
714
- end
715
-
716
- def prepare
717
- markup = RDoc::Markup::ToHtml.new
718
- @engine = markup.convert(data)
719
- @output = nil
720
- end
721
-
722
- def evaluate(scope, locals, &block)
723
- @output ||= @engine.to_s
724
- end
725
- end
726
- register 'rdoc', RDocTemplate
727
-
728
-
729
- # CoffeeScript info:
730
- # http://jashkenas.github.com/coffee-script/
731
- class CoffeeTemplate < Template
732
- def initialize_engine
733
- return if defined? ::CoffeeScript
734
- require_template_library 'coffee-script'
735
- end
736
-
737
- def prepare
738
- @output = nil
739
- end
740
-
741
- def evaluate(scope, locals, &block)
742
- @output ||= ::CoffeeScript::compile(data, options)
743
- end
744
- end
745
- register 'coffee', CoffeeTemplate
746
- end