move rendering into rendering extension, instead of sitemap

This commit is contained in:
Thomas Reynolds 2011-11-26 16:17:18 -08:00
parent 7c50c9e4d5
commit fed3dd5a85
3 changed files with 206 additions and 195 deletions

View file

@ -176,15 +176,15 @@ class Middleman::Base
# Add Guard Callbacks # Add Guard Callbacks
register Middleman::CoreExtensions::FileWatcher register Middleman::CoreExtensions::FileWatcher
# Sitemap
register Middleman::CoreExtensions::Sitemap
# Activate Data package # Activate Data package
register Middleman::CoreExtensions::Data register Middleman::CoreExtensions::Data
# Setup custom rendering # Setup custom rendering
register Middleman::CoreExtensions::Rendering register Middleman::CoreExtensions::Rendering
# Sitemap
register Middleman::CoreExtensions::Sitemap
# Compass framework # Compass framework
register Middleman::CoreExtensions::Compass register Middleman::CoreExtensions::Compass
@ -231,6 +231,8 @@ class Middleman::Base
# Current path defaults to nil, used in views. # Current path defaults to nil, used in views.
@current_path = nil @current_path = nil
cache.clear
# Setup the default values from calls to set before initialization # Setup the default values from calls to set before initialization
self.class.superclass.defaults.each { |k,v| set k,v } self.class.superclass.defaults.each { |k,v| set k,v }
@ -250,10 +252,18 @@ class Middleman::Base
# #
# @private # @private
# @return [Middleman::Cache] The cache # @return [Middleman::Cache] The cache
def cache def self.cache
@_cache ||= ::Middleman::Cache.new @_cache ||= ::Middleman::Cache.new
end end
# Cache accessor for instance, simply forwards to class
#
# @private
# @return [Middleman::Cache] The cache
def cache
self.class.cache
end
# Rack env # Rack env
attr :env attr :env
@ -334,7 +344,7 @@ class Middleman::Base
# Valid content is a 200 status # Valid content is a 200 status
res.status = 200 res.status = 200
rescue ::Middleman::Sitemap::TemplateNotFound => e rescue Middleman::CoreExtensions::Rendering::TemplateNotFound => e
res.write "Error: #{e.message}" res.write "Error: #{e.message}"
res.status = 500 res.status = 500
end end
@ -372,54 +382,6 @@ class Middleman::Base
end end
end end
# Sinatra/Padrino render method signature. Simply forwards to the sitemap
#
# @param [Symbol] Engine name
# @param [String] Path
# @param [Hash] Rendering options
# @param [Hash] Rendering locals
# @return [String] Output
def render(engine, data, options={}, locals={}, &block)
data = data.to_s
found_partial = false
engine = nil
if sitemap.exists?(current_path)
page = sitemap.page(current_path)
current_dir = File.dirname(page.source_file)
engine = File.extname(page.source_file)[1..-1].to_sym
if current_dir != self.source_dir
relative_dir = File.join(current_dir.sub("#{self.source_dir}/", ""), data)
found_partial, found_engine = Middleman::Sitemap::Template.resolve_template(self, relative_dir, :preferred_engine => engine)
if !found_partial
found_partial, found_engine = Middleman::Sitemap::Template.resolve_template(self, relative_dir)
end
end
end
if !found_partial && !engine.nil?
found_partial, found_engine = Middleman::Sitemap::Template.resolve_template(self, data, :preferred_engine => engine)
end
if !found_partial
found_partial, found_engine = Middleman::Sitemap::Template.resolve_template(self, data)
end
if found_partial
body = cache.fetch(:raw_template, found_partial) do
File.read(found_partial)
end
Middleman::Sitemap::Template.static_render(self, found_partial, body, locals, options, &block)
else
throw "Could not find file to render: #{data}"
end
end
# Add a new mime-type for a specific extension # Add a new mime-type for a specific extension
# #
# @param [Symbol] File extension # @param [Symbol] File extension

View file

@ -9,6 +9,8 @@ module Middleman::CoreExtensions::Rendering
rescue LoadError rescue LoadError
end end
app.send :include, InstanceMethods
# Activate custom renderers # Activate custom renderers
app.register Middleman::Renderers::Sass app.register Middleman::Renderers::Sass
app.register Middleman::Renderers::Markdown app.register Middleman::Renderers::Markdown
@ -17,4 +19,191 @@ module Middleman::CoreExtensions::Rendering
end end
alias :included :registered alias :included :registered
end end
class TemplateNotFound < RuntimeError
end
module InstanceMethods
def render_template(path, locs={}, opts={})
content = render_individual_file(path, locs, opts)
extension = File.extname(path)
needs_layout = !%w(.js .css .txt).include?(extension)
engine = extension[1..-1].to_sym
if needs_layout && layout_path = fetch_layout(engine, opts)
content = render_individual_file(layout_path, locs, opts) { content }
end
content
end
# Sinatra/Padrino render method signature.
def render(engine, data, options={}, locals={}, &block)
data = data.to_s
found_partial = false
engine = nil
if sitemap.exists?(current_path)
page = sitemap.page(current_path)
current_dir = File.dirname(page.source_file)
engine = File.extname(page.source_file)[1..-1].to_sym
if current_dir != self.source_dir
relative_dir = File.join(current_dir.sub("#{self.source_dir}/", ""), data)
found_partial, found_engine = resolve_template(relative_dir, :preferred_engine => engine)
if !found_partial
found_partial, found_engine = resolve_template(relative_dir)
end
end
end
if !found_partial && !engine.nil?
found_partial, found_engine = resolve_template(data, :preferred_engine => engine)
end
if !found_partial
found_partial, found_engine = resolve_template(data)
end
if found_partial
render_individual_file(found_partial, locals, options, &block)
else
raise ::Middleman::CoreExtensions::Rendering::TemplateNotFound, "Could not locate partial: #{data}"
end
end
# @private
def render_individual_file(path, locs = {}, opts = {}, &block)
path = path.to_s
body = cache.fetch(:raw_template, path) do
File.read(path)
end
options = opts.merge(options_for_ext(File.extname(path)))
template = cache.fetch(:compiled_template, options, body) do
::Tilt.new(path, 1, options) { body }
end
template.render(self, locs, &block)
end
# @private
def options_for_ext(ext)
cache.fetch(:options_for_ext, ext) do
options = {}
extension_class = ::Tilt[ext]
::Tilt.mappings.each do |ext, engines|
next unless engines.include? extension_class
engine_options = respond_to?(ext.to_sym) ? send(ext.to_sym) : {}
options.merge!(engine_options)
end
options
end
end
# @private
def fetch_layout(engine, opts)
local_layout = opts.has_key?(:layout) ? opts[:layout] : layout
return false unless local_layout
engine_options = respond_to?(engine) ? send(engine) : {}
layout_engine = if opts.has_key?(:layout_engine)
opts[:layout_engine]
elsif engine_options.has_key?(:layout_engine)
engine_options[:layout_engine]
else
engine
end
# Automatic
if local_layout == :_auto_layout
# Look for :layout of any extension
# If found, use it. If not, continue
locate_layout(:layout, layout_engine) || false
else
# Look for specific layout
# If found, use it. If not, error.
if layout_path = locate_layout(local_layout, layout_engine)
layout_path
else
raise ::Middleman::CoreExtensions::Rendering::TemplateNotFound, "Could not locate layout: #{local_layout}"
end
end
end
# @private
def locate_layout(name, preferred_engine=nil)
layout_path = false
if !preferred_engine.nil?
# Check root
layout_path, layout_engine = resolve_template(name, :preferred_engine => preferred_engine)
# Check layouts folder
if !layout_path
layout_path, layout_engine = resolve_template(File.join("layouts", name.to_s), :preferred_engine => preferred_engine)
end
end
# Check root, no preference
if !layout_path
layout_path, layout_engine = resolve_template(name)
end
# Check layouts folder, no preference
if !layout_path
layout_path, layout_engine = resolve_template(File.join("layouts", name.to_s))
end
layout_path
end
# @private
def resolve_template(request_path, options={})
request_path = request_path.to_s
cache.fetch(:resolve_template, request_path, options) do
relative_path = request_path.sub(%r{^/}, "")
on_disk_path = File.expand_path(relative_path, self.source_dir)
preferred_engine = "*"
if options.has_key?(:preferred_engine)
extension_class = ::Tilt[options[:preferred_engine]]
matched_exts = []
# TODO: Cache this
::Tilt.mappings.each do |ext, engines|
next unless engines.include? extension_class
matched_exts << ext
end
if matched_exts.length > 0
preferred_engine = "{" + matched_exts.join(",") + "}"
else
return false
end
end
path_with_ext = on_disk_path + "." + preferred_engine
found_path = Dir[path_with_ext].find do |path|
::Tilt[path]
end
if found_path || File.exists?(on_disk_path)
engine = found_path ? File.extname(found_path)[1..-1].to_sym : nil
[ found_path || on_disk_path, engine ]
else
false
end
end
end
end
end end

View file

@ -1,6 +1,4 @@
module Middleman::Sitemap module Middleman::Sitemap
class TemplateNotFound < RuntimeError
end
class Template class Template
attr_accessor :page, :options, :locals, :blocks#, :dependencies attr_accessor :page, :options, :locals, :blocks#, :dependencies
@ -53,14 +51,7 @@ module Middleman::Sitemap
end end
app.instance_eval(&block) if block_given? app.instance_eval(&block) if block_given?
app.render_template(source_file, locs, opts)
content = internal_render(source_file, locs, opts)
if layout_path = fetch_layout(opts)
content = internal_render(layout_path, locs, opts) { content }
end
content
end end
protected protected
@ -71,136 +62,5 @@ module Middleman::Sitemap
def cache def cache
self.class.cache self.class.cache
end end
def self.options_for_ext(ext)
cache.fetch(:options_for_ext, ext) do
options = {}
extension_class = ::Tilt[ext]
::Tilt.mappings.each do |ext, engines|
next unless engines.include? extension_class
engine_options = respond_to?(ext.to_sym) ? send(ext.to_sym) : {}
options.merge!(engine_options)
end
options
end
end
def fetch_layout(opts)
return false if %w(.js .css .txt).include?(ext)
local_layout = opts.has_key?(:layout) ? opts[:layout] : app.layout
return false unless local_layout
engine = File.extname(source_file)[1..-1].to_sym
engine_options = app.respond_to?(engine) ? app.send(engine) : {}
layout_engine = if opts.has_key?(:layout_engine)
opts[:layout_engine]
elsif engine_options.has_key?(:layout_engine)
engine_options[:layout_engine]
else
engine
end
# Automatic
if local_layout == :_auto_layout
# Look for :layout of any extension
# If found, use it. If not, continue
locate_layout(:layout, layout_engine) || false
else
# Look for specific layout
# If found, use it. If not, error.
if layout_path = locate_layout(local_layout, layout_engine)
layout_path
else
raise Middleman::Sitemap::TemplateNotFound, "Could not locate layout: #{local_layout}"
end
end
end
def locate_layout(name, preferred_engine=nil)
layout_path = false
if !preferred_engine.nil?
# Check root
layout_path, *etc = self.class.resolve_template(app, name, :preferred_engine => preferred_engine)
# Check layouts folder
if !layout_path
layout_path, *etc = self.class.resolve_template(app, File.join("layouts", name.to_s), :preferred_engine => preferred_engine)
end
end
# Check root, no preference
if !layout_path
layout_path, *etc = self.class.resolve_template(app, name)
end
# Check layouts folder, no preference
if !layout_path
layout_path, *etc = self.class.resolve_template(app, File.join("layouts", name.to_s))
end
layout_path
end
def self.resolve_template(app, request_path, options={})
request_path = request_path.to_s
cache.fetch(:resolve_template, request_path, options) do
relative_path = request_path.sub(%r{^/}, "")
on_disk_path = File.expand_path(relative_path, app.source_dir)
preferred_engine = "*"
if options.has_key?(:preferred_engine)
extension_class = ::Tilt[options[:preferred_engine]]
matched_exts = []
# TODO: Cache this
::Tilt.mappings.each do |ext, engines|
next unless engines.include? extension_class
matched_exts << ext
end
if matched_exts.length > 0
preferred_engine = "{" + matched_exts.join(",") + "}"
else
return false
end
end
path_with_ext = on_disk_path + "." + preferred_engine
found_path = Dir[path_with_ext].find do |path|
::Tilt[path]
end
if found_path || File.exists?(on_disk_path)
engine = found_path ? File.extname(found_path)[1..-1].to_sym : nil
[ found_path || on_disk_path, engine ]
else
false
end
end
end
def internal_render(path, locs = {}, opts = {}, &block)
path = path.to_s
body = app.cache.fetch(:raw_template, path) do
File.read(path)
end
self.class.static_render(app, path, body, locs, opts, &block)
end
def self.static_render(app, path, body, locs = {}, opts = {}, &block)
options = opts.merge(options_for_ext(File.extname(path)))
template = cache.fetch(:compiled_template, options, body) do
::Tilt.new(path, 1, options) { body }
end
template.render(app, locs, &block)
end
end end
end end