def render(path, options = {}, &block)
      template, layout = template_and_layout_for_render(path, options)

      # Set new current template
      template_nesting.push(template)

      # Copy data to our data store. A bit clunky; as this should be inherited
      @data = {}.update(@data).update(template.data)

      # Render the template first so we have access to
      # it's data in the layout.
      render_result = template.render(options[:locals] || {}, &block)

      # Wrap it in a layout
      layout.render do
        render_result
      end
    ensure
      # Only pop the template from the nesting if we actually
      # put it on the nesting stack.
      template_nesting.pop if template
    end
def render(path, options = {}, &block)
      template, layout = template_and_layout_for_render(path, options)

      # Set new current template
      template_nesting.push(template)

      # Copy data to our data store. A bit clunky; as this should be inherited
      @data = {}.update(@data).update(template.data)

      # Render the template first so we have access to
      # it's data in the layout.
      render_result = template.render(options[:locals] || {}, &block)

      # Wrap it in a layout
      layout.render do
        render_result
      end
    ensure
      # Only pop the template from the nesting if we actually
      # put it on the nesting stack.
      template_nesting.pop if template
    end
The render function

 The render function will take care of rendering the right thing
 in the right context. It will:

 - Wrap templates with layouts if it's defined in the frontmatter and
   load them from the right layout path.
 - Render only partials if called from within an existing template

 If you just want to render an arbitrary file, use #render_file instead

 @option options [Hash] :locals Locals to use during rendering
 @option options [String] :source The source for the template
 @option options [String, nil] :layout The default layout to use