Class: Middleman::TemplateRenderer

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

Defined Under Namespace

Classes: Cache, TemplateNotFound

Constant Summary

Constants included from Contracts

Contracts::PATH_MATCHER

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Contracts

#Contract

Constructor Details

#initialize(app, path) ⇒ TemplateRenderer

Returns a new instance of TemplateRenderer.



103
104
105
106
# File 'lib/middleman-core/template_renderer.rb', line 103

def initialize(app, path)
  @app = app
  @path = path
end

Class Method Details

.cacheObject



27
28
29
# File 'lib/middleman-core/template_renderer.rb', line 27

def self.cache
  @_cache ||= Cache.new
end

.locate_layout(app, name, preferred_engine = nil) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/middleman-core/template_renderer.rb', line 36

def self.locate_layout(app, name, preferred_engine=nil)
  resolve_opts = {}
  resolve_opts[:preferred_engine] = preferred_engine unless preferred_engine.nil?

  # Check layouts folder
  layout_file = resolve_template(app, File.join(app.config[:layouts_dir], name.to_s), resolve_opts)

  # If we didn't find it, check root
  layout_file = resolve_template(app, name, resolve_opts) unless layout_file

  # Return the path
  layout_file
end

.resolve_template(app, request_path, options = {}) ⇒ Object



55
56
57
58
59
60
61
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
94
95
96
97
98
# File 'lib/middleman-core/template_renderer.rb', line 55

def self.resolve_template(app, request_path, options={})
  # Find the path by searching
  relative_path = Util.strip_leading_slash(request_path.to_s)

  # By default, any engine will do
  preferred_engines = []

  # If we're specifically looking for a preferred engine
  if options.key?(:preferred_engine)
    extension_class = ::Middleman::Util.tilt_class(options[:preferred_engine])

    # Get a list of extensions for a preferred engine
    preferred_engines += ::Tilt.mappings.select do |_, engines|
      engines.include? extension_class
    end.keys
  end

  preferred_engines << '*'
  preferred_engines << nil if options[:try_static]

  found_template = nil

  preferred_engines.each do |preferred_engine|
    path_with_ext = relative_path.dup
    path_with_ext << ('.' + preferred_engine) unless preferred_engine.nil?

    globbing = preferred_engine == '*'

    # Cache lookups in build mode only
    file = if app.build?
      cache.fetch(path_with_ext, preferred_engine) do
        app.files.find(:source, path_with_ext, globbing)
      end
    else
      app.files.find(:source, path_with_ext, globbing)
    end

    found_template = file if file && (preferred_engine.nil? || ::Middleman::Util.tilt_class(file[:full_path].to_s))
    break if found_template
  end

  # If we found one, return it
  found_template
end

Instance Method Details

#HashString

Render a template, with layout, given a path

Parameters:

Returns:

  • (String)


113
# File 'lib/middleman-core/template_renderer.rb', line 113

Contract Hash, Hash => String

#render(locs = {}, opts = {}, &block) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/middleman-core/template_renderer.rb', line 114

def render(locs={}, opts={}, &block)
  path = @path.dup
  locals = locs.dup.freeze
  options = opts.dup

  extension = File.extname(path)
  engine = extension[1..-1].to_sym

  if defined?(::I18n)
    old_locale = ::I18n.locale
    ::I18n.locale = options[:locale] if options[:locale]

    # Backwards compat
    ::I18n.locale = options[:lang] if options[:lang]
  end

  # Sandboxed class for template eval
  context = @app.template_context_class.new(@app, locals, options)

  # Add extension helpers to context.
  @app.extensions.add_exposed_to_context(context)

  locals.each do |k, _|
    next unless context.respond_to?(k) && ![:current_path, :paginate, :page_articles, :blog_controller, :lang, :locale].include?(k.to_sym)

    msg = "Template local `#{k}` tried to overwrite an existing context value. Please rename the key when passing to `locals`"

    if @app.build?
      throw msg
    else
      @app.logger.error(msg)
    end
  end

  content = ::Middleman::Util.instrument 'builder.output.resource.render-template', path: File.basename(path) do
    _render_with_all_renderers(path, locals, context, options, &block)
  end

  # If we need a layout and have a layout, use it
  layout_file = fetch_layout(engine, options)
  if layout_file
    content = if layout_file = fetch_layout(engine, options)
      layout_renderer = ::Middleman::FileRenderer.new(@app, layout_file[:relative_path].to_s)

      ::Middleman::Util.instrument 'builder.output.resource.render-layout', path: File.basename(layout_file[:relative_path].to_s) do
        layout_renderer.render(locals, options, context) { content }
      end
    else
      content
    end
  end

  # Return result
  content
ensure
  # Pop all the saved variables from earlier as we may be returning to a
  # previous render (layouts, partials, nested layouts).
  ::I18n.locale = old_locale if defined?(::I18n)
end