167 lines
4.9 KiB
Ruby
167 lines
4.9 KiB
Ruby
require 'middleman-core/sitemap/extensions/traversal'
|
|
require 'middleman-core/sitemap/extensions/content_type'
|
|
|
|
module Middleman
|
|
|
|
# Sitemap namespace
|
|
module Sitemap
|
|
|
|
# Sitemap Resource class
|
|
class Resource
|
|
include Middleman::Sitemap::Extensions::Traversal
|
|
include Middleman::Sitemap::Extensions::ContentType
|
|
|
|
# @return [Middleman::Application]
|
|
attr_reader :app
|
|
delegate :logger, :instrument, :to => :app
|
|
|
|
# @return [Middleman::Sitemap::Store]
|
|
attr_reader :store
|
|
|
|
# The source path of this resource (relative to the source directory,
|
|
# without template extensions)
|
|
# @return [String]
|
|
attr_reader :path
|
|
|
|
# The output path for this resource
|
|
# @return [String]
|
|
attr_accessor :destination_path
|
|
|
|
# Set the on-disk source file for this resource
|
|
# @return [String]
|
|
# attr_reader :source_file
|
|
|
|
def source_file
|
|
@source_file || get_source_file
|
|
end
|
|
|
|
# Initialize resource with parent store and URL
|
|
# @param [Middleman::Sitemap::Store] store
|
|
# @param [String] path
|
|
# @param [String] source_file
|
|
def initialize(store, path, source_file=nil)
|
|
@store = store
|
|
@app = @store.app
|
|
@path = path.gsub(' ', '%20') # handle spaces in filenames
|
|
@source_file = source_file
|
|
@destination_path = @path
|
|
|
|
@local_metadata = { :options => {}, :locals => {}, :page => {}, :blocks => [] }
|
|
end
|
|
|
|
# Whether this resource has a template file
|
|
# @return [Boolean]
|
|
def template?
|
|
return false if source_file.nil?
|
|
!::Tilt[source_file].nil?
|
|
end
|
|
|
|
# Get the metadata for both the current source_file and the current path
|
|
# @return [Hash]
|
|
def metadata
|
|
result = store.metadata_for_path(path).dup
|
|
|
|
file_meta = store.metadata_for_file(source_file).dup
|
|
if file_meta.has_key?(:blocks)
|
|
result[:blocks] += file_meta.delete(:blocks)
|
|
end
|
|
result.deep_merge!(file_meta)
|
|
|
|
local_meta = @local_metadata.dup
|
|
if local_meta.has_key?(:blocks)
|
|
result[:blocks] += local_meta.delete(:blocks)
|
|
end
|
|
result.deep_merge!(local_meta)
|
|
|
|
result[:blocks] = result[:blocks].flatten.compact
|
|
result
|
|
end
|
|
|
|
# Merge in new metadata specific to this resource.
|
|
# @param [Hash] metadata A metadata block like provides_metadata_for_path takes
|
|
def add_metadata(metadata={}, &block)
|
|
metadata = metadata.dup
|
|
if metadata.has_key?(:blocks)
|
|
@local_metadata[:blocks] += metadata.delete(:blocks)
|
|
end
|
|
@local_metadata.deep_merge!(metadata)
|
|
@local_metadata[:blocks] += [ block ] if block_given?
|
|
end
|
|
|
|
# The output/preview URL for this resource
|
|
# @return [String]
|
|
attr_accessor :destination_path
|
|
|
|
# Extension of the path (i.e. '.js')
|
|
# @return [String]
|
|
def ext
|
|
File.extname(path)
|
|
end
|
|
|
|
def request_path
|
|
self.destination_path
|
|
end
|
|
|
|
# Render this resource
|
|
# @return [String]
|
|
def render(opts={}, locs={}, &block)
|
|
if !template?
|
|
return app.template_data_for_file(source_file)
|
|
end
|
|
|
|
relative_source = Pathname(source_file).relative_path_from(Pathname(app.root))
|
|
|
|
instrument 'render.resource', :path => relative_source do
|
|
md = metadata.dup
|
|
opts = md[:options].deep_merge(opts)
|
|
|
|
# Pass "renderer_options" hash from frontmatter along to renderer
|
|
if md[:page]['renderer_options']
|
|
opts[:renderer_options] = {}
|
|
md[:page]['renderer_options'].each do |k, v|
|
|
opts[:renderer_options][k.to_sym] = v
|
|
end
|
|
end
|
|
|
|
locs = md[:locals].deep_merge(locs)
|
|
|
|
# Forward remaining data to helpers
|
|
if md.has_key?(:page)
|
|
app.data.store('page', md[:page])
|
|
end
|
|
|
|
blocks = Array(md[:blocks]).dup
|
|
blocks << block if block_given?
|
|
|
|
app.current_path ||= self.destination_path
|
|
|
|
# Certain output file types don't use layouts
|
|
if !opts.has_key?(:layout)
|
|
opts[:layout] = false if %w(.js .json .css .txt).include?(self.ext)
|
|
end
|
|
|
|
app.render_template(source_file, locs, opts, blocks)
|
|
end
|
|
end
|
|
|
|
# A path without the directory index - so foo/index.html becomes
|
|
# just foo. Best for linking.
|
|
# @return [String]
|
|
def url
|
|
url_path = destination_path
|
|
if app.strip_index_file
|
|
url_path = url_path.sub(/(^|\/)#{Regexp.escape(app.index_file)}$/,
|
|
app.trailing_slash ? '/' : '')
|
|
end
|
|
File.join(app.respond_to?(:http_prefix) ? app.http_prefix : '/', url_path)
|
|
end
|
|
|
|
# Whether the source file is binary.
|
|
#
|
|
# @return [Boolean]
|
|
def binary?
|
|
::Middleman::Util.binary?(source_file)
|
|
end
|
|
end
|
|
end
|
|
end
|