#-- # Copyright protects this work. # See LICENSE file for details. #++ require 'ember' module ERBook ## # eRuby template that provides access to the underlying result # buffer (which contains the result of template evaluation thus # far) and provides sandboxing for isolated template rendering. # class Template < Ember::Template attr_reader :sandbox ## # ==== Parameters # # [source] # Replacement for the ambiguous '(erb)' identifier in stack traces; # so that the user can better determine the source of an error. # # [input] # A string containing eRuby directives. # # [unindent] # If true, then all content blocks will be unindented hierarchically, # # [safe_level] # See safe_level in ERB::new(). # def initialize source, input, unindent = true, safe_level = nil super input, :result_variable => :@buffer, :source_file => source, :unindent => unindent, :shorthand => true, :infer_end => true @sandbox = Sandbox.new if $DEBUG IO.popen('cat -n', 'w+') do |io| io.write self.program io.close_write STDERR.puts io.read end end end ## # Returns the output of evaluating this template inside the given context. # # If no context is given, then the sandbox of this template is used. # def render super @sandbox.instance_eval('binding') end ## # Returns the result of template evaluation thus far. # def buffer @sandbox.instance_variable_get(:@buffer) end ## # Renders this template within a fresh sandbox that is populated with # the given instance variables, whose names must be prefixed with '@'. # def render_with inst_vars = {} old_sandbox = @sandbox begin @sandbox = Sandbox.new inst_vars.each_pair do |var, val| @sandbox.instance_variable_set var, val end render ensure @sandbox = old_sandbox end end ## # Environment for template evaluation. # class Sandbox ## # Returns an array of things that the given # block wants to append to the buffer. If # the given block does not want to append # to the buffer, then returns the result of # invoking the given block inside an array. # def __block_content__ *block_args raise ArgumentError, 'block must be given' unless block_given? original = @buffer begin block_content = @buffer = [] return_value = yield(*block_args) # this appends content to @buffer ensure @buffer = original end if block_content.empty? [return_value] else block_content end end end end end