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.
Methods
Public Class
Public Instance
Constants
| LOCK | = | Mutex.new |
Attributes
| lazy_map | [R] |
@private |
| template_map | [R] |
@private |
Public Class methods
# 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
Finds the extensions the template class has been registered under. @param [template class] template_class
# 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
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).
# 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
@private
# 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
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
# 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
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
# 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 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'])
# 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
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
# 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
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
# 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