Prefer loading layouts from layouts_dir
over layouts with the same name in the source root. This also includes a bunch of refactoring/cleanup of rendering.rb. Fixes #1176.
This commit is contained in:
parent
ca50f21fac
commit
477f87e98a
|
@ -28,3 +28,11 @@ Feature: Layouts dir
|
||||||
When I go to "/index.html"
|
When I go to "/index.html"
|
||||||
Then I should see "contents of the layout"
|
Then I should see "contents of the layout"
|
||||||
|
|
||||||
|
Scenario: Prefer a layout in the layouts_dir to one with the same name in the root
|
||||||
|
Given a fixture app "layouts-dir-app"
|
||||||
|
And a file named "config.rb" with:
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
And the Server is running
|
||||||
|
When I go to "/ambiguous.html"
|
||||||
|
Then I should see "contents of the layout in layouts_dir"
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
layout: other
|
||||||
|
---
|
||||||
|
|
||||||
|
Hello
|
|
@ -0,0 +1,3 @@
|
||||||
|
contents of the layout in layouts_dir
|
||||||
|
|
||||||
|
<%= yield %>
|
3
middleman-core/fixtures/layouts-dir-app/source/other.erb
Normal file
3
middleman-core/fixtures/layouts-dir-app/source/other.erb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
contents of the layout in the root
|
||||||
|
|
||||||
|
<%= yield %>
|
|
@ -157,7 +157,7 @@ module Middleman
|
||||||
content = render_individual_file(path, locs, opts, context)
|
content = render_individual_file(path, locs, opts, context)
|
||||||
path = File.basename(path, File.extname(path))
|
path = File.basename(path, File.extname(path))
|
||||||
rescue LocalJumpError
|
rescue LocalJumpError
|
||||||
raise "Tried to render a layout (calls yield) at #{path} like it was a template. Non-default layouts need to be in #{source}/#{layout_dir}."
|
raise "Tried to render a layout (calls yield) at #{path} like it was a template. Non-default layouts need to be in #{source}/#{config[:layouts_dir]}."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -190,42 +190,29 @@ module Middleman
|
||||||
locals = options[:locals]
|
locals = options[:locals]
|
||||||
|
|
||||||
found_partial = false
|
found_partial = false
|
||||||
engine = nil
|
resolve_opts = { try_without_underscore: true }
|
||||||
|
|
||||||
# If the path is known to the sitemap
|
# If the path is known to the sitemap
|
||||||
if resource = sitemap.find_resource_by_path(current_path)
|
if resource = sitemap.find_resource_by_path(current_path)
|
||||||
current_dir = File.dirname(resource.source_file)
|
current_dir = File.dirname(resource.source_file)
|
||||||
engine = File.extname(resource.source_file)[1..-1].to_sym
|
resolve_opts[:preferred_engine] = File.extname(resource.source_file)[1..-1].to_sym
|
||||||
|
|
||||||
# Look for partials relative to the current path
|
# Look for partials relative to the current path
|
||||||
relative_dir = File.join(current_dir.sub(%r{^#{Regexp.escape(self.source_dir)}/?}, ''), data)
|
relative_dir = File.join(current_dir.sub(%r{^#{Regexp.escape(self.source_dir)}/?}, ''), data)
|
||||||
|
|
||||||
# Try to use the current engine first
|
found_partial = resolve_template(relative_dir, resolve_opts)
|
||||||
found_partial, found_engine = resolve_template(relative_dir, :preferred_engine => engine, :try_without_underscore => true)
|
|
||||||
|
|
||||||
# Fall back to any engine available
|
|
||||||
if !found_partial
|
|
||||||
found_partial, found_engine = resolve_template(relative_dir, :try_without_underscore => true)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Look in the partials_dir for the partial with the current engine
|
# Look in the partials_dir for the partial with the current engine
|
||||||
|
if !found_partial
|
||||||
partials_path = File.join(config[:partials_dir], data)
|
partials_path = File.join(config[:partials_dir], data)
|
||||||
if !found_partial && !engine.nil?
|
found_partial = resolve_template(partials_path, resolve_opts)
|
||||||
found_partial, found_engine = resolve_template(partials_path, :preferred_engine => engine, :try_without_underscore => true)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Look in the root with any engine
|
raise ::Middleman::CoreExtensions::Rendering::TemplateNotFound, "Could not locate partial: #{data}" unless found_partial
|
||||||
if !found_partial
|
|
||||||
found_partial, found_engine = resolve_template(partials_path, :try_without_underscore => true)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Render the partial if found, otherwide throw exception
|
# Render the partial if found, otherwide throw exception
|
||||||
if found_partial
|
|
||||||
render_individual_file(found_partial, locals, options, self, &block)
|
render_individual_file(found_partial, locals, options, self, &block)
|
||||||
else
|
|
||||||
raise ::Middleman::CoreExtensions::Rendering::TemplateNotFound, "Could not locate partial: #{data}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Render an on-disk file. Used for everything, including layouts.
|
# Render an on-disk file. Used for everything, including layouts.
|
||||||
|
@ -370,26 +357,14 @@ module Middleman
|
||||||
# Whether we've found the layout
|
# Whether we've found the layout
|
||||||
layout_path = false
|
layout_path = false
|
||||||
|
|
||||||
# If we prefer a specific engine
|
resolve_opts = {}
|
||||||
if !preferred_engine.nil?
|
resolve_opts[:preferred_engine] = preferred_engine if !preferred_engine.nil?
|
||||||
# Check root
|
|
||||||
layout_path, layout_engine = resolve_template(name, :preferred_engine => preferred_engine)
|
|
||||||
|
|
||||||
# Check layouts folder
|
# Check layouts folder
|
||||||
if !layout_path
|
layout_path = resolve_template(File.join(config[:layouts_dir], name.to_s), resolve_opts)
|
||||||
layout_path, layout_engine = resolve_template(File.join(config[:layouts_dir], name.to_s), :preferred_engine => preferred_engine)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Check root, no preference
|
# If we didn't find it, check root
|
||||||
if !layout_path
|
layout_path = resolve_template(name, resolve_opts) unless 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(config[:layouts_dir], name.to_s))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Return the path
|
# Return the path
|
||||||
layout_path
|
layout_path
|
||||||
|
@ -440,7 +415,8 @@ module Middleman
|
||||||
|
|
||||||
# Find a template on disk given a output path
|
# Find a template on disk given a output path
|
||||||
# @param [String] request_path
|
# @param [String] request_path
|
||||||
# @param [Hash] options
|
# @option options [Boolean] :preferred_engine If set, try this engine first, then fall back to any engine.
|
||||||
|
# @option options [Boolean] :try_without_underscore
|
||||||
# @return [Array<String, Symbol>, Boolean]
|
# @return [Array<String, Symbol>, Boolean]
|
||||||
def resolve_template(request_path, options={})
|
def resolve_template(request_path, options={})
|
||||||
# Find the path by searching or using the cache
|
# Find the path by searching or using the cache
|
||||||
|
@ -450,48 +426,46 @@ module Middleman
|
||||||
on_disk_path = File.expand_path(relative_path, self.source_dir)
|
on_disk_path = File.expand_path(relative_path, self.source_dir)
|
||||||
|
|
||||||
# By default, any engine will do
|
# By default, any engine will do
|
||||||
preferred_engine = '*'
|
preferred_engines = ['*']
|
||||||
|
|
||||||
# Unless we're specifically looking for a preferred engine
|
# If we're specifically looking for a preferred engine
|
||||||
if options.has_key?(:preferred_engine)
|
if options.has_key?(:preferred_engine)
|
||||||
extension_class = ::Tilt[options[:preferred_engine]]
|
extension_class = ::Tilt[options[:preferred_engine]]
|
||||||
matched_exts = []
|
matched_exts = []
|
||||||
|
|
||||||
# Get a list of extensions for a preferred engine
|
# Get a list of extensions for a preferred engine
|
||||||
# TODO: Cache this
|
matched_exts = ::Tilt.mappings.select do |ext, engines|
|
||||||
::Tilt.mappings.each do |ext, engines|
|
engines.include? extension_class
|
||||||
next unless engines.include? extension_class
|
end.keys
|
||||||
matched_exts << ext
|
|
||||||
end
|
|
||||||
|
|
||||||
# Change the glob to only look for the matched extensions
|
# Prefer to look for the matched extensions
|
||||||
if matched_exts.length > 0
|
unless matched_exts.empty?
|
||||||
preferred_engine = '{' + matched_exts.join(',') + '}'
|
preferred_engines.unshift('{' + matched_exts.join(',') + '}')
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Look for files that match
|
search_paths = preferred_engines.flat_map do |preferred_engine|
|
||||||
path_with_ext = on_disk_path + '.' + preferred_engine
|
path_with_ext = on_disk_path + '.' + preferred_engine
|
||||||
|
paths = [path_with_ext]
|
||||||
|
if options[:try_without_underscore]
|
||||||
|
paths << path_with_ext.sub(relative_path, relative_path.sub(/^_/, '').sub(/\/_/, '/'))
|
||||||
|
end
|
||||||
|
paths
|
||||||
|
end
|
||||||
|
|
||||||
|
found_path = nil
|
||||||
|
search_paths.each do |path_with_ext|
|
||||||
found_path = Dir[path_with_ext].find do |path|
|
found_path = Dir[path_with_ext].find do |path|
|
||||||
::Tilt[path]
|
::Tilt[path]
|
||||||
end
|
end
|
||||||
|
break if found_path
|
||||||
if !found_path && options[:try_without_underscore] &&
|
|
||||||
path_no_underscore = path_with_ext.
|
|
||||||
sub(relative_path, relative_path.sub(/^_/, '').
|
|
||||||
sub(/\/_/, '/'))
|
|
||||||
found_path = Dir[path_no_underscore].find do |path|
|
|
||||||
::Tilt[path]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# If we found one, return it and the found engine
|
# If we found one, return it and the found engine
|
||||||
if found_path || files.exists?(on_disk_path)
|
if found_path
|
||||||
engine = found_path ? File.extname(found_path)[1..-1].to_sym : nil
|
found_path
|
||||||
[ found_path || on_disk_path, engine ]
|
elsif File.exists?(on_disk_path)
|
||||||
|
on_disk_path
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue