Method: Middleman::CoreExtensions::Rendering::InstanceMethods#render_individual_file

Defined in:
lib/middleman-core/core_extensions/rendering.rb

#render_individual_file(path, locs = {}, opts = {}, context = self, &block) ⇒ String

Render an on-disk file. Used for everything, including layouts.

Parameters:

  • path (String, Symbol)
  • locs (Hash) (defaults to: {})
  • opts (Hash) (defaults to: {})
  • context (Class) (defaults to: self)

Returns:

  • (String)


252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/middleman-core/core_extensions/rendering.rb', line 252

def render_individual_file(path, locs={}, opts={}, context=self, &block)
  path = path.to_s

  # Mutability is FUN!
  # Try to work around: https://github.com/middleman/middleman/issues/501
  locs = locs.dup

  # Detect the remdering engine from the extension
  extension = File.extname(path)
  engine = extension[1..-1].to_sym

  # Store last engine for later (could be inside nested renders)
  context.current_engine, engine_was = engine, context.current_engine

  # Save current buffer for later
  @_out_buf, _buf_was = '', @_out_buf

  # Read from disk or cache the contents of the file
  body = if opts[:template_body]
    opts.delete(:template_body)
  else
    template_data_for_file(path)
  end

  # Merge per-extension options from config
  extension = File.extname(path)
  options = opts.dup.merge(options_for_ext(extension))
  options[:outvar] ||= '@_out_buf'
  options.delete(:layout)

  # Overwrite with frontmatter options
  options = options.deep_merge(options[:renderer_options]) if options[:renderer_options]

  template_class = ::Tilt[path]
  # Allow hooks to manipulate the template before render
  self.class.callbacks_for_hook(:before_render).each do |callback|
    # Uber::Options::Value doesn't respond to call
    newbody = if callback.respond_to?(:call)
      callback.call(body, path, locs, template_class)
    elsif callback.respond_to?(:evaluate)
      callback.evaluate(self, body, path, locs, template_class)
    end
    body = newbody if newbody # Allow the callback to return nil to skip it
  end

  # Read compiled template from disk or cache
  template = cache.fetch(:compiled_template, extension, options, body) do
    ::Tilt.new(path, 1, options) { body }
  end

  # Render using Tilt
  content = template.render(context, locs, &block)

  # Allow hooks to manipulate the result after render
  self.class.callbacks_for_hook(:after_render).each do |callback|
    # Uber::Options::Value doesn't respond to call
    newcontent = if callback.respond_to?(:call)
      content = callback.call(content, path, locs, template_class)
    elsif callback.respond_to?(:evaluate)
      content = callback.evaluate(self, content, path, locs, template_class)
    end
    content = newcontent if newcontent # Allow the callback to return nil to skip it
  end

  output = ::ActiveSupport::SafeBuffer.new ''
  output.safe_concat content
  output
ensure
  # Reset stored buffer
  @_out_buf = _buf_was
  context.current_engine = engine_was
end