commit
c8c6a1938e
9 changed files with 130 additions and 136 deletions
|
@ -15,5 +15,5 @@ Feature: Wildcards in Page helper
|
|||
Then I should see "Normal Layout"
|
||||
When I go to "/admin/"
|
||||
Then I should see "Admin Layout"
|
||||
When I go to "/admin/page.html"
|
||||
When I go to "/admin/page/"
|
||||
Then I should see "Admin Layout"
|
|
@ -370,13 +370,13 @@ class Middleman::Base
|
|||
|
||||
# Run before callbacks
|
||||
run_hook :before
|
||||
|
||||
# Return 404 if not in sitemap
|
||||
return not_found unless sitemap.exists?(@request_path)
|
||||
|
||||
|
||||
# Get the page object for this path
|
||||
sitemap_page = sitemap.page(@request_path)
|
||||
|
||||
sitemap_page = sitemap.page_by_destination(@request_path)
|
||||
|
||||
# Return 404 if not in sitemap
|
||||
return not_found unless sitemap_page
|
||||
|
||||
# Return 404 if this path is specifically ignored
|
||||
return not_found if sitemap_page.ignored?
|
||||
|
||||
|
@ -494,4 +494,4 @@ protected
|
|||
end
|
||||
res['Content-Type'] = mime_type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -99,27 +99,20 @@ module Middleman::Cli
|
|||
# Ignore following method
|
||||
desc "", "", :hide => true
|
||||
|
||||
# Render a template to a file.
|
||||
# Render a page to a file.
|
||||
#
|
||||
# @param [String] source
|
||||
# @param [String] destination
|
||||
# @param [Hash] config
|
||||
# @return [String] the actual destination file path that was created
|
||||
def tilt_template(source, destination, config={})
|
||||
# @param [Middleman::Sitemap::Page] page
|
||||
# @return [void]
|
||||
def tilt_template(page)
|
||||
build_dir = self.class.shared_instance.build_dir
|
||||
request_path = destination.sub(/^#{build_dir}/, "")
|
||||
config[:force] = true
|
||||
output_file = File.join(self.class.shared_instance.build_dir, page.destination_path)
|
||||
|
||||
begin
|
||||
destination, request_path = self.class.shared_instance.reroute_builder(destination, request_path)
|
||||
|
||||
response = self.class.shared_rack.get(request_path.gsub(/\s/, "%20"))
|
||||
|
||||
create_file(destination, response.body, config)
|
||||
|
||||
destination
|
||||
response = self.class.shared_rack.get(page.request_path.gsub(/\s/, "%20"))
|
||||
create_file(output_file, response.body, { :force => true })
|
||||
rescue
|
||||
say_status :error, destination, :red
|
||||
say_status :error, output_file, :red
|
||||
puts $!
|
||||
abort
|
||||
end
|
||||
end
|
||||
|
@ -213,6 +206,8 @@ module Middleman::Cli
|
|||
# Sort paths to be built by the above order. This is primarily so Compass can
|
||||
# find files in the build folder when it needs to generate sprites for the
|
||||
# css files
|
||||
|
||||
# TODO: deal with pages, not paths
|
||||
paths = @app.sitemap.all_paths.sort do |a, b|
|
||||
a_ext = File.extname(a)
|
||||
b_ext = File.extname(b)
|
||||
|
@ -225,21 +220,15 @@ module Middleman::Cli
|
|||
|
||||
# Loop over all the paths and build them.
|
||||
paths.each do |path|
|
||||
file_source = path
|
||||
file_destination = File.join(given_destination, file_source.gsub(source, '.'))
|
||||
file_destination.gsub!('/./', '/')
|
||||
page = @app.sitemap.page(path)
|
||||
|
||||
if @app.sitemap.proxied?(file_source)
|
||||
file_source = @app.sitemap.page(file_source).proxied_to
|
||||
elsif @app.sitemap.page(file_source).ignored?
|
||||
next
|
||||
end
|
||||
|
||||
next if @config[:glob] && !File.fnmatch(@config[:glob], file_source)
|
||||
next if page.ignored?
|
||||
next if @config[:glob] && !File.fnmatch(@config[:glob], path)
|
||||
|
||||
file_destination = base.tilt_template(file_source, file_destination)
|
||||
base.tilt_template(page)
|
||||
|
||||
@cleaning_queue.delete(Pathname.new(file_destination).realpath) if cleaning?
|
||||
output_path = File.join(@destination, page.destination_path)
|
||||
@cleaning_queue.delete(Pathname.new(output_path).realpath) if cleaning?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,7 +16,8 @@ module Middleman::CoreExtensions::Builder
|
|||
# Build Class Methods
|
||||
module ClassMethods
|
||||
# Get a list of callbacks which can modify a files build path
|
||||
#
|
||||
# Each callback takes a destination path and a request path and
|
||||
# returns a new destination path, or false if it doesn't want to reroute.
|
||||
# @return [Array<Proc>]
|
||||
def build_reroute(&block)
|
||||
@build_rerouters ||= []
|
||||
|
@ -29,14 +30,14 @@ module Middleman::CoreExtensions::Builder
|
|||
module InstanceMethods
|
||||
# Run through callbacks and get the new values
|
||||
#
|
||||
# @param [String] destination The current destination of the built file
|
||||
# @param [String] request_path The current request path of the file
|
||||
# @return [Array<String>] The new values
|
||||
# @param [String] destination The current destination path of the built file
|
||||
# @param [String] request_path The request path of the file
|
||||
# @return [String] The new destination path
|
||||
def reroute_builder(destination, request_path)
|
||||
result = [destination, request_path]
|
||||
|
||||
build_reroute.each do |block|
|
||||
output = instance_exec(destination, request_path, &block)
|
||||
output = block.call(destination, request_path)
|
||||
if output
|
||||
result = output
|
||||
break
|
||||
|
|
|
@ -64,7 +64,7 @@ module Middleman::CoreExtensions::Routing
|
|||
|
||||
# Setup proxy
|
||||
if opts.has_key?(:proxy)
|
||||
reroute(url, opts[:proxy])
|
||||
proxy(url, opts[:proxy])
|
||||
|
||||
if opts.has_key?(:ignore) && opts[:ignore]
|
||||
ignore(opts[:proxy])
|
||||
|
@ -89,4 +89,4 @@ module Middleman::CoreExtensions::Routing
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -74,10 +74,10 @@ module Middleman::CoreExtensions::Sitemap
|
|||
# @param [String] url
|
||||
# @param [String] target
|
||||
# @return [void]
|
||||
def reroute(*args)
|
||||
def proxy(*args)
|
||||
sitemap.proxy(*args)
|
||||
end
|
||||
|
||||
|
||||
# Register a handler to provide metadata on a file path
|
||||
# @param [Regexp] matcher
|
||||
# @return [Array<Array<Proc, Regexp>>]
|
||||
|
@ -96,4 +96,4 @@ module Middleman::CoreExtensions::Sitemap
|
|||
@_provides_metadata_for_path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,83 +12,43 @@ module Middleman::Extensions
|
|||
# Include methods
|
||||
app.send :include, InstanceMethods
|
||||
|
||||
# Before requests
|
||||
app.before do
|
||||
prefix = @original_path.sub(/\/$/, "")
|
||||
indexed_path = prefix + "/" + index_file
|
||||
extensioned_path = prefix + File.extname(index_file)
|
||||
|
||||
is_ignored = false
|
||||
fm_ignored = false
|
||||
|
||||
# If the sitemap knows about the path
|
||||
if sitemap.exists?(@original_path)
|
||||
# Inspect frontmatter
|
||||
d = sitemap.page(@original_path).data
|
||||
|
||||
# Allow the frontmatter to ignore a directory index
|
||||
if !d.nil? && d.has_key?("directory_index") && d["directory_index"] == false
|
||||
fm_ignored = true
|
||||
else
|
||||
next
|
||||
end
|
||||
else
|
||||
# Otherwise check this extension for list of ignored indexes
|
||||
is_ignored = ignored_directory_indexes.include?(extensioned_path)
|
||||
end
|
||||
app.after_configuration do
|
||||
# Register a reroute transform that turns regular paths into indexed paths
|
||||
sitemap.reroute do |destination, page|
|
||||
new_index_path = "/#{index_file}"
|
||||
frontmatter_ignore = false
|
||||
|
||||
# If we're going to remap to a directory index
|
||||
if !sitemap.exists?(indexed_path) && !is_ignored && !fm_ignored
|
||||
parts = @original_path.split("/")
|
||||
last_part = parts.last
|
||||
last_part_ext = File.extname(last_part)
|
||||
|
||||
# Change the request
|
||||
if last_part_ext.blank?
|
||||
# This is a folder, redirect to index
|
||||
@request_path = extensioned_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Basically does the same as above, but in build mode
|
||||
app.build_reroute do |destination, request_path|
|
||||
index_ext = File.extname(index_file)
|
||||
new_index_path = "/#{index_file}"
|
||||
frontmatter_ignore = false
|
||||
|
||||
# Check for file and frontmatter
|
||||
if sitemap.exists?(request_path)
|
||||
p = sitemap.page(request_path)
|
||||
d = p.data
|
||||
if !d.nil?
|
||||
# Check for file and frontmatter
|
||||
d = page.data
|
||||
if !page.data.nil?
|
||||
frontmatter_ignore = d.has_key?("directory_index") && d["directory_index"] == false
|
||||
end
|
||||
end
|
||||
|
||||
# Only reroute if not ignored
|
||||
if ignored_directory_indexes.include?(request_path)
|
||||
false
|
||||
elsif request_path =~ /#{new_index_path}$/
|
||||
false
|
||||
elsif frontmatter_ignore
|
||||
false
|
||||
else
|
||||
[
|
||||
destination.sub(/#{index_ext.gsub(".", "\\.")}$/, new_index_path),
|
||||
request_path
|
||||
]
|
||||
index_ext = File.extname(index_file)
|
||||
|
||||
# Only reroute if not ignored
|
||||
path = page.path
|
||||
if ignored_directory_indexes.include? page
|
||||
destination
|
||||
elsif path == index_file || path.end_with?(new_index_path)
|
||||
destination
|
||||
elsif frontmatter_ignore
|
||||
destination
|
||||
elsif index_ext != File.extname(path)
|
||||
destination
|
||||
else
|
||||
destination.chomp(File.extname(index_file)) + new_index_path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
alias :included :registered
|
||||
end
|
||||
|
||||
# Directory indexes instance methods
|
||||
module InstanceMethods
|
||||
# A list of pages which will not use directory indexes
|
||||
# @return [Array<String>]
|
||||
# @return [Array<Middleman::Sitemap::Page>]
|
||||
def ignored_directory_indexes
|
||||
@_ignored_directory_indexes ||= []
|
||||
end
|
||||
|
@ -100,7 +60,7 @@ module Middleman::Extensions
|
|||
# @return [void]
|
||||
def page(url, options={}, &block)
|
||||
if options.has_key?(:directory_index) && !options["directory_index"]
|
||||
ignored_directory_indexes << url
|
||||
ignored_directory_indexes << sitemap.page(url)
|
||||
else
|
||||
super
|
||||
end
|
||||
|
@ -110,4 +70,4 @@ module Middleman::Extensions
|
|||
|
||||
# Register the extension
|
||||
register :directory_indexes, DirectoryIndexes
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,8 @@ module Middleman::Sitemap
|
|||
# @return [Middleman::Sitemap::Store]
|
||||
attr_accessor :store
|
||||
|
||||
# The source path of this page (relative to the source directory,
|
||||
# without template extensions)
|
||||
# @return [String]
|
||||
attr_accessor :path
|
||||
|
||||
|
@ -41,9 +43,9 @@ module Middleman::Sitemap
|
|||
# @return [String]
|
||||
def request_path
|
||||
if proxy?
|
||||
store.page(proxied_to).path
|
||||
store.page(proxied_to).destination_path
|
||||
else
|
||||
path
|
||||
destination_path
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -185,6 +187,16 @@ module Middleman::Sitemap
|
|||
def relative_path
|
||||
self.source_file ? self.source_file.sub(app.source_dir, '') : nil
|
||||
end
|
||||
|
||||
# Get the destination path, relative to the build directory.
|
||||
# This path can be affected by proxy callbacks.
|
||||
# @return [String]
|
||||
def destination_path
|
||||
# TODO: memoize this value
|
||||
store.reroute_callbacks.inject(self.path) do |destination, callback|
|
||||
callback.call(destination, self)
|
||||
end
|
||||
end
|
||||
|
||||
# This page's frontmatter
|
||||
# @return [Hash, nil]
|
||||
|
@ -263,4 +275,4 @@ module Middleman::Sitemap
|
|||
store.app
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
module Middleman::Sitemap
|
||||
|
||||
# The Store class
|
||||
#
|
||||
# The Store manages a collection of Page objects, which represent
|
||||
# individual items in the sitemap. Pages are indexed by "source path",
|
||||
# which is the path relative to the source directory, minus any template
|
||||
# extensions. All "path" parameters used in this class are source paths.
|
||||
class Store
|
||||
|
||||
# @return [Middleman::Base]
|
||||
|
@ -16,24 +21,25 @@ module Middleman::Sitemap
|
|||
@ignored_globs = []
|
||||
@ignored_regexes = []
|
||||
@ignored_callbacks = []
|
||||
@reroute_callbacks = []
|
||||
end
|
||||
|
||||
# Check to see if we know about a specific path
|
||||
# @param [String] path
|
||||
# @return [Boolean]
|
||||
def exists?(path)
|
||||
@pages.has_key?(path.sub(/^\//, ""))
|
||||
@pages.has_key?(normalize_path(path))
|
||||
end
|
||||
|
||||
# Ignore a path or add an ignore callback
|
||||
# @param [String, Regexp] path
|
||||
# @param [String, Regexp] path, path glob expression, or path regex
|
||||
# @return [void]
|
||||
def ignore(path=nil, &block)
|
||||
if !path.nil? && path.include?("*")
|
||||
path_clean = path.sub(/^\//, "")
|
||||
path_clean = normalize_path(path)
|
||||
@ignored_globs << path_clean unless @ignored_globs.include?(path_clean)
|
||||
elsif path.is_a? String
|
||||
path_clean = path.sub(/^\//, "")
|
||||
path_clean = normalize_path(path)
|
||||
@ignored_paths << path_clean unless @ignored_paths.include?(path_clean)
|
||||
elsif path.is_a? Regexp
|
||||
@ignored_regexes << path unless @ignored_regexes.include?(path)
|
||||
|
@ -42,33 +48,52 @@ module Middleman::Sitemap
|
|||
end
|
||||
end
|
||||
|
||||
# Add a callback that will be run with each page's destination path
|
||||
# and can produce a new destination path or pass through the old one.
|
||||
# @return [void]
|
||||
def reroute(&block)
|
||||
@reroute_callbacks << block if block_given?
|
||||
end
|
||||
|
||||
# The list of reroute callbacks
|
||||
# @return [Array<Proc>]
|
||||
def reroute_callbacks
|
||||
@reroute_callbacks
|
||||
end
|
||||
|
||||
# Setup a proxy from a path to a target
|
||||
# @param [String] path
|
||||
# @param [String] target
|
||||
# @return [void]
|
||||
def proxy(path, target)
|
||||
page(path) { proxy_to(target.sub(%r{^/}, "")) }
|
||||
page(path).proxy_to(normalize_path(target))
|
||||
app.cache.remove(:proxied_paths)
|
||||
end
|
||||
|
||||
# Get a page instance for a given path
|
||||
# @param [String] path
|
||||
# @return [Middleman::Sitemap::Page]
|
||||
def page(path, &block)
|
||||
path = path.sub(/^\//, "").gsub("%20", " ")
|
||||
@pages[path] = ::Middleman::Sitemap::Page.new(self, path) unless @pages.has_key?(path)
|
||||
@pages[path].instance_exec(&block) if block_given?
|
||||
@pages[path]
|
||||
def page(path)
|
||||
path = normalize_path(path)
|
||||
@pages.fetch(path) { @pages[path] = ::Middleman::Sitemap::Page.new(self, path) }
|
||||
end
|
||||
|
||||
# Find a page given its destination path
|
||||
def page_by_destination(destination_path)
|
||||
# TODO: memoize this
|
||||
destination_path = normalize_path(destination_path)
|
||||
@pages.values.find {|p| p.destination_path == destination_path }
|
||||
end
|
||||
|
||||
# Loop over known pages
|
||||
# @yield [path, page]
|
||||
# @return [void]
|
||||
def each(&block)
|
||||
def each
|
||||
@pages.each do |k, v|
|
||||
yield k, v
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Get all known paths
|
||||
# @return [Array<String>]
|
||||
def all_paths
|
||||
|
@ -79,15 +104,15 @@ module Middleman::Sitemap
|
|||
# @param [String] path
|
||||
# @return [Boolean]
|
||||
def ignored?(path)
|
||||
path_clean = path.sub(/^\//, "")
|
||||
|
||||
# $stderr.puts path_clean, @ignored_globs, @ignored_paths
|
||||
path_clean = normalize_path(path)
|
||||
|
||||
return true if @ignored_paths.include?(path_clean)
|
||||
return true if @ignored_globs.any? { |g| File.fnmatch(g, path_clean) }
|
||||
return true if @ignored_regexes.any? { |r| r.match(path_clean) }
|
||||
return true if @ignored_callbacks.any? { |b| b.call(path_clean) }
|
||||
|
||||
|
||||
# TODO: We should also check ignored_sitemap_matchers here
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
|
@ -101,7 +126,7 @@ module Middleman::Sitemap
|
|||
# @param [String] path
|
||||
# @return [Boolean]
|
||||
def generic?(path)
|
||||
generic_paths.include?(path.sub(/^\//, ""))
|
||||
generic_paths.include?(normalize_path(path))
|
||||
end
|
||||
|
||||
# Get a list of generic paths
|
||||
|
@ -116,7 +141,7 @@ module Middleman::Sitemap
|
|||
# @param [String] path
|
||||
# @return [Boolean]
|
||||
def proxied?(path)
|
||||
proxied_paths.include?(path.sub(/^\//, ""))
|
||||
proxied_paths.include?(normalize_path(path))
|
||||
end
|
||||
|
||||
# Get a list of proxied paths
|
||||
|
@ -134,7 +159,7 @@ module Middleman::Sitemap
|
|||
path = file_to_path(file)
|
||||
return false unless path
|
||||
|
||||
path = path.sub(/^\//, "")
|
||||
path = normalize_path(path)
|
||||
if @pages.has_key?(path)
|
||||
page(path).delete()
|
||||
@pages.delete(path)
|
||||
|
@ -189,7 +214,7 @@ module Middleman::Sitemap
|
|||
|
||||
# Get a path without templating extensions
|
||||
# @param [String] file
|
||||
# @param [String]
|
||||
# @return [String]
|
||||
def extensionless_path(file)
|
||||
app.cache.fetch(:extensionless_path, file) do
|
||||
path = file.dup
|
||||
|
@ -206,5 +231,12 @@ module Middleman::Sitemap
|
|||
path
|
||||
end
|
||||
end
|
||||
|
||||
# Normalize a path to not include a leading slash
|
||||
# @param [String] path
|
||||
# @return [String]
|
||||
def normalize_path(path)
|
||||
path.sub(/^\//, "").gsub("%20", " ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue