middleman/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb

147 lines
5.6 KiB
Ruby
Raw Normal View History

require 'middleman-core/sitemap/resource'
2014-06-29 00:07:43 +02:00
require 'middleman-core/core_extensions/collections/step_context'
module Middleman
module Sitemap
module Extensions
2014-01-01 03:21:30 +01:00
# Manages the list of proxy configurations and manipulates the sitemap
# to include new resources based on those configurations
class Proxies < Extension
2015-09-15 02:37:35 +02:00
self.resource_list_manipulator_priority = 0
# Expose `create_proxy` as `app.proxy`
expose_to_application proxy: :create_proxy
# Expose `create_proxy` to config as `proxy`
expose_to_config proxy: :create_proxy
def initialize(app, config={}, &block)
super
2014-01-01 03:21:30 +01:00
@proxy_configs = Set.new
2014-06-29 00:07:43 +02:00
@post_config = false
end
def after_configuration
@post_config = true
::Middleman::CoreExtensions::Collections::StepContext.add_to_context(:proxy, &method(:create_anonymous_proxy))
end
2014-01-01 03:21:30 +01:00
# Setup a proxy from a path to a target
# @param [String] path The new, proxied path to create
# @param [String] target The existing path that should be proxied to. This must be a real resource, not another proxy.
# @option opts [Boolean] ignore Ignore the target from the sitemap (so only the new, proxy resource ends up in the output)
# @option opts [Symbol, Boolean, String] layout The layout name to use (e.g. `:article`) or `false` to disable layout.
# @option opts [Boolean] directory_indexes Whether or not the `:directory_indexes` extension applies to these paths.
# @option opts [Hash] locals Local variables for the template. These will be available when the template renders.
# @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}.
2014-01-01 03:21:30 +01:00
# @return [void]
2014-07-03 04:04:34 +02:00
Contract String, String, Maybe[Hash] => Any
def create_proxy(path, target, opts={})
options = opts.dup
@app.ignore(target) if options.delete(:ignore)
2014-06-29 00:07:43 +02:00
@proxy_configs << create_anonymous_proxy(path, target, options)
2014-01-01 03:21:30 +01:00
@app.sitemap.rebuild_resource_list!(:added_proxy)
end
2014-06-29 00:07:43 +02:00
# Setup a proxy from a path to a target
# @param [String] path The new, proxied path to create
# @param [String] target The existing path that should be proxied to. This must be a real resource, not another proxy.
# @option opts [Boolean] ignore Ignore the target from the sitemap (so only the new, proxy resource ends up in the output)
# @option opts [Symbol, Boolean, String] layout The layout name to use (e.g. `:article`) or `false` to disable layout.
# @option opts [Boolean] directory_indexes Whether or not the `:directory_indexes` extension applies to these paths.
# @option opts [Hash] locals Local variables for the template. These will be available when the template renders.
# @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}.
# @return [void]
def create_anonymous_proxy(path, target, options={})
ProxyDescriptor.new(
::Middleman::Util.normalize_path(path),
::Middleman::Util.normalize_path(target),
options
)
end
2014-01-01 03:21:30 +01:00
# Update the main sitemap resource list
2014-07-03 04:04:34 +02:00
# @return Array<Middleman::Sitemap::Resource>
Contract ResourceList => ResourceList
2014-01-01 03:21:30 +01:00
def manipulate_resource_list(resources)
2014-06-29 00:07:43 +02:00
resources + @proxy_configs.map { |c| c.to_resource(@app) }
2014-01-01 03:21:30 +01:00
end
end
2014-06-29 00:07:43 +02:00
ProxyDescriptor = Struct.new(:path, :target, :metadata) do
def to_resource(app)
ProxyResource.new(app.sitemap, path, target).tap do |p|
md = metadata.dup
p.add_metadata(
2015-02-07 22:38:29 +01:00
locals: md.delete(:locals) || {},
page: md.delete(:data) || {},
options: md
2015-04-26 20:13:29 +02:00
)
end
end
2014-01-01 03:21:30 +01:00
end
end
2015-09-15 02:37:35 +02:00
class Resource
2015-09-17 18:41:17 +02:00
def proxy_to(_path)
throw 'Resource#proxy_to has been removed. Use ProxyResource class instead.'
2015-09-15 02:37:35 +02:00
end
end
class ProxyResource < ::Middleman::Sitemap::Resource
2015-09-15 02:37:35 +02:00
Contract String
attr_reader :target
# Initialize resource with parent store and URL
# @param [Middleman::Sitemap::Store] store
# @param [String] path
# @param [String] target
def initialize(store, path, target)
super(store, path)
target = ::Middleman::Util.normalize_path(target)
raise "You can't proxy #{path} to itself!" if target == path
@target = target
end
# The resource for the page this page is proxied to. Throws an exception
# if there is no resource.
# @return [Sitemap::Resource]
2015-04-24 19:26:42 +02:00
Contract IsA['Middleman::Sitemap::Resource']
def target_resource
resource = @store.find_resource_by_path(@target)
unless resource
raise "Path #{path} proxies to unknown file #{@target}:#{@store.resources.map(&:path)}"
2014-01-01 03:21:30 +01:00
end
2012-04-04 19:26:07 +02:00
if resource.is_a? ProxyResource
raise "You can't proxy #{path} to #{@target} which is itself a proxy."
end
resource
end
2014-01-01 03:21:30 +01:00
2015-04-24 19:26:42 +02:00
Contract IsA['Middleman::SourceFile']
def file_descriptor
target_resource.file_descriptor
end
2015-09-15 02:37:35 +02:00
def metadata
target_resource.metadata.deep_merge super
end
2015-04-24 19:26:42 +02:00
Contract Maybe[String]
def content_type
mime_type = super
return mime_type if mime_type
target_resource.content_type
end
2012-04-04 19:26:07 +02:00
end
end
end