2012-01-08 01:57:50 +01:00
|
|
|
# Sitemap namespace
|
2011-11-21 02:05:29 +01:00
|
|
|
module Middleman::Sitemap
|
2012-01-08 01:57:50 +01:00
|
|
|
|
|
|
|
# The Store class
|
2011-11-21 02:05:29 +01:00
|
|
|
class Store
|
2012-01-08 01:57:50 +01:00
|
|
|
|
|
|
|
# @return [Middleman::Base]
|
2011-11-21 02:05:29 +01:00
|
|
|
attr_accessor :app
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Initialize with parent app
|
|
|
|
# @param [Middleman::Base] app
|
2011-11-21 02:05:29 +01:00
|
|
|
def initialize(app)
|
|
|
|
@app = app
|
|
|
|
@pages = {}
|
2012-01-08 01:57:50 +01:00
|
|
|
@ignored_paths = []
|
2012-01-14 23:09:20 +01:00
|
|
|
@ignored_globs = []
|
2012-01-08 01:57:50 +01:00
|
|
|
@ignored_regexes = []
|
|
|
|
@ignored_callbacks = []
|
2011-11-21 02:05:29 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
# Check to see if we know about a specific path
|
2012-01-08 01:57:50 +01:00
|
|
|
# @param [String] path
|
|
|
|
# @return [Boolean]
|
2011-11-21 02:05:29 +01:00
|
|
|
def exists?(path)
|
|
|
|
@pages.has_key?(path.sub(/^\//, ""))
|
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Ignore a path or add an ignore callback
|
|
|
|
# @param [String, Regexp] path
|
|
|
|
# @return [void]
|
|
|
|
def ignore(path=nil, &block)
|
2012-01-14 23:09:20 +01:00
|
|
|
if !path.nil? && path.include?("*")
|
|
|
|
path_clean = path.sub(/^\//, "")
|
|
|
|
@ignored_globs << path_clean unless @ignored_globs.include?(path_clean)
|
|
|
|
elsif path.is_a? String
|
2012-01-08 01:57:50 +01:00
|
|
|
path_clean = path.sub(/^\//, "")
|
|
|
|
@ignored_paths << path_clean unless @ignored_paths.include?(path_clean)
|
|
|
|
elsif path.is_a? Regexp
|
|
|
|
@ignored_regexes << path unless @ignored_regexes.include?(path)
|
|
|
|
elsif block_given?
|
|
|
|
@ignored_callbacks << block
|
2011-11-21 02:05:29 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Setup a proxy from a path to a target
|
|
|
|
# @param [String] path
|
|
|
|
# @param [String] target
|
|
|
|
# @return [void]
|
2011-11-21 02:05:29 +01:00
|
|
|
def proxy(path, target)
|
2012-02-01 07:15:45 +01:00
|
|
|
page(path).proxy_to(target.sub(%r{^/}, ""))
|
2011-11-27 05:09:14 +01:00
|
|
|
app.cache.remove(:proxied_paths)
|
2011-11-21 02:05:29 +01:00
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Get a page instance for a given path
|
|
|
|
# @param [String] path
|
|
|
|
# @return [Middleman::Sitemap::Page]
|
2012-02-01 07:15:45 +01:00
|
|
|
def page(path)
|
2011-11-21 02:05:29 +01:00
|
|
|
path = path.sub(/^\//, "").gsub("%20", " ")
|
2012-02-01 07:15:45 +01:00
|
|
|
@pages.fetch(path) { @pages[path] = ::Middleman::Sitemap::Page.new(self, path) }
|
2011-11-21 02:05:29 +01:00
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Loop over known pages
|
|
|
|
# @return [void]
|
2011-11-25 00:04:00 +01:00
|
|
|
def each(&block)
|
|
|
|
@pages.each do |k, v|
|
|
|
|
yield k, v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Get all known paths
|
|
|
|
# @return [Array<String>]
|
2011-11-21 02:05:29 +01:00
|
|
|
def all_paths
|
|
|
|
@pages.keys
|
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Whether a path is ignored
|
|
|
|
# @param [String] path
|
|
|
|
# @return [Boolean]
|
2011-11-21 02:05:29 +01:00
|
|
|
def ignored?(path)
|
2012-01-08 01:57:50 +01:00
|
|
|
path_clean = path.sub(/^\//, "")
|
|
|
|
|
2012-01-14 23:09:20 +01:00
|
|
|
# $stderr.puts path_clean, @ignored_globs, @ignored_paths
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
return true if @ignored_paths.include?(path_clean)
|
2012-01-14 23:09:20 +01:00
|
|
|
return true if @ignored_globs.any? { |g| File.fnmatch(g, path_clean) }
|
2012-01-08 01:57:50 +01:00
|
|
|
return true if @ignored_regexes.any? { |r| r.match(path_clean) }
|
|
|
|
return true if @ignored_callbacks.any? { |b| b.call(path_clean) }
|
|
|
|
|
|
|
|
false
|
2011-11-21 02:05:29 +01:00
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Get a list of ignored paths
|
|
|
|
# @return [Array<String>]
|
2011-11-21 02:05:29 +01:00
|
|
|
def ignored_paths
|
2012-01-08 01:57:50 +01:00
|
|
|
@pages.values.select(&:ignored?).map(&:path)
|
2011-11-21 02:05:29 +01:00
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Whether the given path is generic
|
|
|
|
# @param [String] path
|
|
|
|
# @return [Boolean]
|
2011-11-21 02:05:29 +01:00
|
|
|
def generic?(path)
|
|
|
|
generic_paths.include?(path.sub(/^\//, ""))
|
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Get a list of generic paths
|
|
|
|
# @return [Array<String>]
|
2011-11-21 02:05:29 +01:00
|
|
|
def generic_paths
|
2011-11-27 05:09:14 +01:00
|
|
|
app.cache.fetch :generic_paths do
|
2011-11-21 02:05:29 +01:00
|
|
|
@pages.values.select(&:generic?).map(&:path)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Whether the given path is proxied
|
|
|
|
# @param [String] path
|
|
|
|
# @return [Boolean]
|
2011-11-21 02:05:29 +01:00
|
|
|
def proxied?(path)
|
|
|
|
proxied_paths.include?(path.sub(/^\//, ""))
|
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Get a list of proxied paths
|
|
|
|
# @return [Array<String>]
|
2011-11-21 02:05:29 +01:00
|
|
|
def proxied_paths
|
2011-11-27 05:09:14 +01:00
|
|
|
app.cache.fetch :proxied_paths do
|
2011-11-21 02:05:29 +01:00
|
|
|
@pages.values.select(&:proxy?).map(&:path)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Remove a file from the store
|
|
|
|
# @param [String] file
|
|
|
|
# @return [void]
|
2011-11-21 02:05:29 +01:00
|
|
|
def remove_file(file)
|
|
|
|
path = file_to_path(file)
|
|
|
|
return false unless path
|
|
|
|
|
|
|
|
path = path.sub(/^\//, "")
|
2012-01-08 01:57:50 +01:00
|
|
|
if @pages.has_key?(path)
|
|
|
|
page(path).delete()
|
|
|
|
@pages.delete(path)
|
|
|
|
end
|
2011-11-21 02:05:29 +01:00
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Get the URL path for an on-disk file
|
|
|
|
# @param [String] file
|
|
|
|
# @return [String]
|
2011-11-21 02:05:29 +01:00
|
|
|
def file_to_path(file)
|
|
|
|
file = File.expand_path(file, @app.root)
|
|
|
|
|
2011-12-29 00:29:19 +01:00
|
|
|
prefix = @app.source_dir.sub(/\/$/, "") + "/"
|
2011-11-21 02:05:29 +01:00
|
|
|
return false unless file.include?(prefix)
|
|
|
|
|
|
|
|
path = file.sub(prefix, "")
|
|
|
|
path = extensionless_path(path)
|
|
|
|
|
|
|
|
path
|
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Update or add an on-disk file path
|
|
|
|
# @param [String] file
|
|
|
|
# @return [Boolean]
|
2011-11-21 02:05:29 +01:00
|
|
|
def touch_file(file)
|
2011-12-29 00:29:19 +01:00
|
|
|
return false if file == @app.source_dir || File.directory?(file)
|
2011-11-21 02:05:29 +01:00
|
|
|
|
2011-12-28 03:47:03 +01:00
|
|
|
path = file_to_path(file)
|
2011-11-21 02:05:29 +01:00
|
|
|
return false unless path
|
|
|
|
|
2011-12-28 03:47:03 +01:00
|
|
|
return false if @app.ignored_sitemap_matchers.any? do |name, callback|
|
|
|
|
callback.call(file, path)
|
|
|
|
end
|
|
|
|
|
2011-11-21 02:05:29 +01:00
|
|
|
# Add generic path
|
2011-12-08 06:00:27 +01:00
|
|
|
p = page(path)
|
|
|
|
p.source_file = File.expand_path(file, @app.root)
|
|
|
|
p.touch
|
2011-11-21 02:05:29 +01:00
|
|
|
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2012-01-08 01:57:50 +01:00
|
|
|
# Whether the sitemap should completely ignore a given file/path
|
|
|
|
# @param [String] file
|
|
|
|
# @param [String] path
|
|
|
|
# @return [Boolean]
|
2011-12-28 03:47:03 +01:00
|
|
|
def sitemap_should_ignore?(file, path)
|
|
|
|
@app.sitemap_ignore.every(&:call)
|
|
|
|
end
|
|
|
|
|
2011-11-21 02:05:29 +01:00
|
|
|
protected
|
2012-01-08 01:57:50 +01:00
|
|
|
|
|
|
|
# Get a path without templating extensions
|
|
|
|
# @param [String] file
|
|
|
|
# @param [String]
|
2011-11-21 02:05:29 +01:00
|
|
|
def extensionless_path(file)
|
2011-11-27 05:09:14 +01:00
|
|
|
app.cache.fetch(:extensionless_path, file) do
|
2011-11-21 02:05:29 +01:00
|
|
|
path = file.dup
|
|
|
|
|
|
|
|
end_of_the_line = false
|
|
|
|
while !end_of_the_line
|
|
|
|
if !::Tilt[path].nil?
|
|
|
|
path = path.sub(File.extname(path), "")
|
|
|
|
else
|
|
|
|
end_of_the_line = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
path
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2011-12-27 06:52:16 +01:00
|
|
|
end
|