class Tilt::Mapping

  1. lib/tilt/mapping.rb
Superclass: BaseMapping

Tilt::Mapping associates file extensions with template implementations.

mapping = Tilt::Mapping.new
mapping.register(Tilt::RDocTemplate, 'rdoc')
mapping['index.rdoc'] # => Tilt::RDocTemplate
mapping.new('index.rdoc').render

You can use {#register} to register a template class by file extension, {#registered?} to see if a file extension is mapped, {#[]} to lookup template classes, and {#new} to instantiate template objects.

Mapping also supports lazy template implementations. Note that regularly registered template implementations always have preference over lazily registered template implementations. You should use {#register} if you depend on a specific template implementation and {#register_lazy} if there are multiple alternatives.

mapping = Tilt::Mapping.new
mapping.register_lazy('RDiscount::Template', 'rdiscount/template', 'md')
mapping['index.md']
# => RDiscount::Template

{#register_lazy} takes a class name, a filename, and a list of file extensions. When you try to lookup a template name that matches the file extension, Tilt will automatically try to require the filename and constantize the class name.

Unlike {#register}, there can be multiple template implementations registered lazily to the same file extension. Tilt will attempt to load the template implementations in order (registered last would be tried first), returning the first which doesn’t raise LoadError.

If all of the registered template implementations fails, Tilt will raise the exception of the first, since that was the most preferred one.

mapping = Tilt::Mapping.new
mapping.register_lazy('Kramdown::Template', 'kramdown/template', 'md')
mapping.register_lazy('RDiscount::Template', 'rdiscount/template', 'md')
mapping['index.md']
# => RDiscount::Template

In the previous example we say that RDiscount has a *higher priority* than Kramdown. Tilt will first try to require "rdiscount/template", falling back to require "kramdown/template". If none of these are successful, the first error will be raised.

Constants

LOCK = Mutex.new  

Attributes

lazy_map [R]

@private

template_map [R]

@private

Public Class methods

new()
[show source]
    # File lib/tilt/mapping.rb
131 def initialize
132   @template_map = Hash.new
133   @lazy_map = Hash.new { |h, k| h[k] = [] }
134 end

Public Instance methods

extensions_for(template_class)

Finds the extensions the template class has been registered under. @param [template class] template_class

[show source]
    # File lib/tilt/mapping.rb
287 def extensions_for(template_class)
288   res = []
289   LOCK.synchronize{@template_map.to_a}.each do |ext, klass|
290     res << ext if template_class == klass
291   end
292   LOCK.synchronize{@lazy_map.to_a}.each do |ext, choices|
293     res << ext if LOCK.synchronize{choices.dup}.any? { |klass, file| template_class.to_s == klass }
294   end
295   res.uniq!
296   res
297 end
finalized()

Return a finalized mapping. A finalized mapping will only include support for template libraries already loaded, and will not allow registering new template libraries or lazy loading template libraries not yet loaded. Finalized mappings improve performance by not requiring synchronization and ensure that the mapping will not attempt to load additional files (useful when restricting file system access after template libraries in use are loaded).

[show source]
    # File lib/tilt/mapping.rb
151 def finalized
152   LOCK.synchronize{@lazy_map.dup}.each do |pattern, classes|
153     register_defined_classes(LOCK.synchronize{classes.map(&:first)}, pattern)
154   end
155 
156   # Check if a template class is already present
157   FinalizedMapping.new(LOCK.synchronize{@template_map.dup}.freeze)
158 end
initialize_copy(other)

@private

[show source]
    # File lib/tilt/mapping.rb
137 def initialize_copy(other)
138   LOCK.synchronize do
139     @template_map = other.template_map.dup
140     @lazy_map = other.lazy_map.dup
141   end
142 end
register(template_class, *extensions)

Registers a template implementation by file extension. There can only be one template implementation per file extension, and this method will override any existing mapping.

@param template_class @param extensions [Array<String>] List of extensions. @return [void]

@example

mapping.register MyEngine::Template, 'mt'
mapping['index.mt'] # => MyEngine::Template
[show source]
    # File lib/tilt/mapping.rb
200 def register(template_class, *extensions)
201   if template_class.respond_to?(:to_str)
202     # Support register(ext, template_class) too
203     extensions, template_class = [template_class], extensions[0]
204   end
205 
206   extensions.each do |ext|
207     ext = ext.to_s
208     LOCK.synchronize do
209       @template_map[ext] = template_class
210     end
211   end
212 end
register_lazy(class_name, file, *extensions)

Registers a lazy template implementation by file extension. You can have multiple lazy template implementations defined on the same file extension, in which case the template implementation defined last will be attempted loaded first.

@param class_name [String] Class name of a template class. @param file [String] Filename where the template class is defined. @param extensions [Array<String>] List of extensions. @return [void]

@example

mapping.register_lazy 'MyEngine::Template', 'my_engine/template',  'mt'

defined?(MyEngine::Template) # => false
mapping['index.mt'] # => MyEngine::Template
defined?(MyEngine::Template) # => true
[show source]
    # File lib/tilt/mapping.rb
176 def register_lazy(class_name, file, *extensions)
177   # Internal API
178   if class_name.is_a?(Symbol)
179     Tilt.autoload class_name, file
180     class_name = "Tilt::#{class_name}"
181   end
182 
183   v = [class_name, file].freeze
184   extensions.each do |ext|
185     LOCK.synchronize{@lazy_map[ext].unshift(v)}
186   end
187 end
register_pipeline(ext, options=EMPTY_HASH)

Register a new template class using the given extension that represents a pipeline of multiple existing template, where the output from the previous template is used as input to the next template.

This will register a template class that processes the input with the erb template processor, and takes the output of that and feeds it to the scss template processor, returning the output of the scss template processor as the result of the pipeline.

@param ext [String] Primary extension to register @option :templates [Array<String>] Extensions of templates

to execute in order (defaults to the ext.split('.').reverse)

@option :extra_exts [Array<String>] Additional extensions to register @option String [Hash] Options hash for individual template in the

pipeline (key is extension).

@return [void]

@example

mapping.register_pipeline('scss.erb')
mapping.register_pipeline('scss.erb', 'erb'=>{:outvar=>'@foo'})
mapping.register_pipeline('scsserb', :extra_exts => 'scss.erb',
                          :templates=>['erb', 'scss'])
[show source]
    # File lib/tilt/mapping.rb
238 def register_pipeline(ext, options=EMPTY_HASH)
239   templates = options[:templates] || ext.split('.').reverse
240   templates = templates.map{|t| [self[t], options[t] || EMPTY_HASH]}
241 
242   klass = Class.new(Pipeline)
243   klass.send(:const_set, :TEMPLATES, templates)
244 
245   register(klass, ext, *Array(options[:extra_exts]))
246   klass
247 end
registered?(ext)

Checks if a file extension is registered (either eagerly or lazily) in this mapping.

@param ext [String] File extension.

@example

mapping.registered?('erb')  # => true
mapping.registered?('nope') # => false
[show source]
    # File lib/tilt/mapping.rb
280 def registered?(ext)
281   ext_downcase = ext.downcase
282   LOCK.synchronize{@template_map.has_key?(ext_downcase)} or lazy?(ext)
283 end
unregister(*extensions)

Unregisters an extension. This removes the both normal registrations and lazy registrations.

@param extensions [Array<String>] List of extensions. @return nil

@example

mapping.register MyEngine::Template, 'mt'
mapping['index.mt'] # => MyEngine::Template
mapping.unregister('mt')
mapping['index.mt'] # => nil
[show source]
    # File lib/tilt/mapping.rb
260 def unregister(*extensions)
261   extensions.each do |ext|
262     ext = ext.to_s
263     LOCK.synchronize do
264       @template_map.delete(ext)
265       @lazy_map.delete(ext)
266     end
267   end
268 
269   nil
270 end