lib/renee-render.rb in renee-render-0.1.1 vs lib/renee-render.rb in renee-render-0.2.0
- old
+ new
@@ -1,109 +1,116 @@
require 'tilt'
+require 'callsite'
+# Top-level Renee constant
class Renee
# This module is responsible for handling the rendering of templates
# using Tilt supporting all included template engines.
module Render
##
- # Exception responsible for when a generic rendering error occurs.
- #
- class RenderError < RuntimeError; end
-
- ##
# Exception responsible for when an expected template does not exist.
#
- class TemplateNotFound < RenderError; end
+ class TemplateNotFound < RuntimeError; end
# Same as render but automatically halts.
# @param (see #render)
# @return (see #render)
# @see #render
- def render!(*args, &blk)
- halt render(*args, &blk)
+ def render!(file, engine = nil, options = nil, &blk)
+ halt render(file, engine, options, &blk)
end
+ # Same as inline but automatically halts.
+ # @param (see #inline)
+ # @return (see #inline)
+ # @see #inline
+ def inline!(data, engine, options = {}, &blk)
+ options[:_caller] = Callsite.parse(caller.first)
+ halt inline(data, engine, options, &blk)
+ end
+
##
+ # Renders a file given the engine and the content.
+ #
+ # @param [String] file The path to the file to render
+ # @param [Symbol] engine The name of the engine to use to render the content. If this isn't specified
+ # it will be detected based on the extension of the file.
+ # @param [Hash] options The options to pass in for rendering.
+ #
+ # @return [String] The result of rendering the data with specified engine.
+ #
+ # @example
+ # render "index", :haml # => "<p>test</p>"
+ # render "index" # => "<p>test</p>"
+ #
+ # @api public
+ #
+ def render(file, engine = nil, options = nil, &block)
+ options, engine = engine, nil if engine.is_a?(Hash)
+ render_setup(engine, options, block) do |view_options, views|
+ template_cache.fetch(engine, file, view_options) do
+ file_path, found_engine = find_template(views, file, engine)
+ template = Tilt[found_engine]
+ raise TemplateNotFound, "Template engine not found: #{found_engine.inspect}" unless template
+ raise TemplateNotFound, "Template #{file.inspect} (with engine #{engine.inspect}) not found in #{views.inspect}!" unless file_path
+ # TODO suppress errors for layouts?
+ template.new(file_path, 1, view_options)
+ end
+ end
+ end # render
+
+ ##
# Renders a string given the engine and the content.
#
- # @param [Symbol] engine The template engine to use for rendering.
- # @param [String] data The content or file to render.
- # @param [Hash] options The rendering options to pass onto tilt.
+ # @param [String] data The string data to render.
+ # @param [Symbol] engine The name of the engine to use to render the content. If this isn't specified
+ # it will be detected based on the extension of the file.
+ # @param [Hash] options The options to pass in for rendering.
#
# @return [String] The result of rendering the data with specified engine.
#
# @example
- # render :haml, "%p test" => "<p>test</p>"
- # render :haml, :index => "<p>test</p>"
- # render "index" => "<p>test</p>"
+ # inline "%p test", :haml # => "<p>test</p>"
#
# @api public
#
- def render(engine, data=nil, options={}, &block)
- # Handles the case where engine is unspecified by shifting the data (i.e render "index")
- engine, data, options = nil, engine.to_sym, data if data.nil? || data.is_a?(Hash)
+ def inline(data, engine, options = nil, &block)
+ options, engine = engine, nil if engine.is_a?(Hash)
+ call_data = options.delete(:_caller) || Callsite.parse(caller.first)
+ render_setup(engine, options, block) do |view_options, views|
+ body = data.is_a?(Proc) ? data : Proc.new { data }
+ template = Tilt[engine]
+ raise "Template engine not found: #{engine}" if template.nil?
+ template.new(call_data.filename, call_data.line, view_options, &body)
+ end
+ end
+ private
+ def render_setup(engine, options, block)
options ||= {}
options[:outvar] ||= '@_out_buf'
- # TODO allow default encoding to be set (as an option)
- options[:default_encoding] ||= "utf-8"
+ options[:default_encoding] ||= settings.default_encoding || options[:encoding] || "utf-8"
locals = options.delete(:locals) || {}
views = options.delete(:views) || settings.views_path || "./views"
layout = options.delete(:layout)
- layout_engine = options.delete(:layout_engine) || engine
+ layout_engine = options.delete(:layout_engine)
# TODO suppress template errors for layouts?
# TODO allow content_type to be set with an option to render?
scope = options.delete(:scope) || self
# TODO default layout file convention?
- template = compile_template(engine, data, options, views)
+ template = yield(options, views)
output = template.render(scope, locals, &block)
if layout # render layout
# TODO handle when layout is missing better!
options = options.merge(:views => views, :layout => false, :scope => scope)
- return render(layout_engine, layout, options.merge(:locals => locals)) { output }
+ render(layout, layout_engine, options.merge(:locals => locals)) { output }
+ else
+ output
end
-
- output
- end # render
-
- ##
- # Constructs a template based on engine, data and options.
- #
- # @param [Symbol] engine The template engine to use for rendering.
- # @param [String] data The content or file to render.
- # @param [Hash] options The rendering options to pass onto tilt.
- # @param [String] views The view_path from which to locate the template.
- #
- # @return [Tilt::Template] The tilt template to render with all required options.
- # @raise [TemplateNotFound] The template to render could not be located.
- # @raise [RenderError] The template to render could not be located.
- #
- # @api private
- #
- def compile_template(engine, data, options, views)
- template_cache.fetch engine, data, options do
- if data.is_a?(Symbol) # data is template path
- file_path, engine = find_template(views, data, engine)
- template = Tilt[engine]
- raise TemplateNotFound, "Template engine not found: #{engine}" if template.nil?
- raise TemplateNotFound, "Template '#{data}' not found in '#{views}'!" unless file_path
- # TODO suppress errors for layouts?
- template.new(file_path, 1, options)
- elsif data.is_a?(String) # data is body string
- # TODO figure out path based on caller file
- path, line = options[:path] || "caller file", options[:line] || 1
- body = data.is_a?(String) ? Proc.new { data } : data
- template = Tilt[engine]
- raise "Template engine not found: #{engine}" if template.nil?
- template.new(path, line.to_i, options, &body)
- else # data can't be handled
- raise RenderError, "Cannot render data #{data.inspect}."
- end
- end # template_cache.fetch
- end # compile_template
+ end
##
# Searches view paths for template based on data and engine with rendering options.
# Supports finding a template without an engine.
#
\ No newline at end of file