Class: Middleman::TemplateContext

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Contracts
Defined in:
lib/middleman-core/template_context.rb

Overview

The TemplateContext Class

A clean context, separate from Application, in which templates can be executed. All helper methods and values available in a template, but be accessible here. Also implements two helpers: wrap_layout & render (used by padrino's partial method). A new context is created for each render of a path, but that context is shared through the request, passed from template, to layouts and partials.

Constant Summary

Constants included from Contracts

Contracts::PATH_MATCHER

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Contracts

#Contract

Constructor Details

#initialize(app, locs = {}, opts = {}) ⇒ TemplateContext

Initialize a context with the current app and predefined locals and options hashes.

Parameters:



33
34
35
36
37
# File 'lib/middleman-core/template_context.rb', line 33

def initialize(app, locs={}, opts={})
  @app = app
  @locs = locs
  @opts = opts
end

Instance Attribute Details

#appMiddleman::Application (readonly)

Allow templates to directly access the current app instance.



20
21
22
# File 'lib/middleman-core/template_context.rb', line 20

def app
  @app
end

#current_engineObject

Required for Padrino's rendering



23
24
25
# File 'lib/middleman-core/template_context.rb', line 23

def current_engine
  @current_engine
end

Instance Method Details

#AnyString

Sinatra/Padrino compatible render method signature referenced by some view helpers. Especially partials.

Parameters:

  • name (String, Symbol)

    The partial to render.

  • options (Hash)
  • block (Proc)

    A block will be evaluated to return internal contents.

Returns:



102
# File 'lib/middleman-core/template_context.rb', line 102

Contract Any, Or[Symbol, String], Hash => String, Maybe[Proc] => String

#current_pathObject



156
157
158
# File 'lib/middleman-core/template_context.rb', line 156

def current_path
  @locs[:current_path]
end

#current_resourceMiddleman::Sitemap::Resource Also known as: current_page

Get the resource object for the current path



162
163
164
165
# File 'lib/middleman-core/template_context.rb', line 162

def current_resource
  return nil unless current_path
  sitemap.find_resource_by_destination_path(current_path)
end

#locate_partial(partial_path, try_static = true) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/middleman-core/template_context.rb', line 129

def locate_partial(partial_path, try_static=true)
  return unless resource = sitemap.find_resource_by_destination_path(current_path)

  # Look for partials relative to the current path
  current_dir = resource.file_descriptor[:relative_path].dirname
  non_root = partial_path.to_s.sub(/^\//, '')
  relative_dir = current_dir + Pathname(non_root)

  non_root_no_underscore = non_root.sub(/^_/, '').sub(/\/_/, '/')
  relative_dir_no_underscore = current_dir + Pathname(non_root_no_underscore)

  partial_file = nil

  [
    [relative_dir.to_s, { preferred_engine: resource.file_descriptor[:relative_path].extname[1..-1].to_sym }],
    [non_root],
    [non_root, { try_static: try_static }],
    [relative_dir_no_underscore.to_s, { try_static: try_static }],
    [non_root_no_underscore, { try_static: try_static }]
  ].each do |args|
    partial_file = ::Middleman::TemplateRenderer.resolve_template(@app, *args)
    break if partial_file
  end

  partial_file || nil
end

#render(_, name, options = {}, &block) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/middleman-core/template_context.rb', line 103

def render(_, name, options={}, &block)
  name = name.to_s

  partial_file = locate_partial(name, false) || locate_partial(name, true)

  raise ::Middleman::TemplateRenderer::TemplateNotFound, "Could not locate partial: #{name}" unless partial_file

  source_path = sitemap.file_to_path(partial_file)
  r = sitemap.find_resource_by_path(source_path)

  if (r && !r.template?) || (Tilt[partial_file[:full_path]].nil? && partial_file[:full_path].exist?)
    partial_file.read
  else
    opts = options.dup
    locs = opts.delete(:locals)

    render_file(partial_file, locs, opts, &block)
  end
end

#restore_buffer(buf_was)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Restore a previously saved buffer.

Parameters:



54
55
56
# File 'lib/middleman-core/template_context.rb', line 54

def restore_buffer(buf_was)
  @_out_buf = buf_was
end

#save_bufferString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return the current buffer to the caller and clear the value internally. Used when moving between templates when rendering layouts or partials.

Returns:

  • (String)

    The old buffer.



44
45
46
47
# File 'lib/middleman-core/template_context.rb', line 44

def save_buffer
  @_out_buf, buf_was = '', @_out_buf
  buf_was
end

#StringString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Locate a partial relative to the current path or the source dir, given a partial's path.

Parameters:

Returns:



128
# File 'lib/middleman-core/template_context.rb', line 128

Contract String, Maybe[Bool] => Maybe[IsA['Middleman::SourceFile']]

#wrap_layout(layout_name, &block)

This method returns an undefined value.

Allow layouts to be wrapped in the contents of other layouts.

Parameters:

  • layout_name (String, Symbol)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/middleman-core/template_context.rb', line 62

def wrap_layout(layout_name, &block)
  # Save current buffer for later
  buf_was = save_buffer

  # Find a layout for this file
  layout_file = ::Middleman::TemplateRenderer.locate_layout(@app, layout_name, current_engine)

  # Get the layout engine
  extension = File.extname(layout_file[:relative_path])
  engine = extension[1..-1].to_sym

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

  # By default, no content is captured
  content = ''

  # Attempt to capture HTML from block
  begin
    content = capture_html(&block) if block_given?
  ensure
    # Reset stored buffer, regardless of success
    restore_buffer(buf_was)
  end

  # Render the layout, with the contents of the block inside.
  concat_safe_content render_file(layout_file, @locs, @opts) { content }
ensure
  # Reset engine back to template's value, regardless of success
  self.current_engine = engine_was
end