diff --git a/middleman-core/features/proxy_pages.feature b/middleman-core/features/proxy_pages.feature
new file mode 100644
index 00000000..522f1eb8
--- /dev/null
+++ b/middleman-core/features/proxy_pages.feature
@@ -0,0 +1,94 @@
+Feature: Proxy Pages (using proxy rather than page)
+ In order to use a single view to generate multiple output files
+
+ Scenario: Checking built folder for content
+ Given a successfully built app at "proxy-pages-app"
+ When I cd to "build"
+ Then the following files should exist:
+ | fake.html |
+ | fake2.html |
+ | fake3.html |
+ | fake4.html |
+ | fake/one.html |
+ | fake/two.html |
+ | fake2/one.html |
+ | fake2/two.html |
+ | fake3/one.html |
+ | fake3/two.html |
+ | fake4/one.html |
+ | fake4/two.html |
+ | target_ignore.html |
+ | target_ignore2.html |
+ | target_ignore3.html |
+ | target_ignore4.html |
+ | 明日がある.html |
+ Then the following files should not exist:
+ | should_be_ignored6.html |
+ | should_be_ignored7.html |
+ | should_be_ignored8.html |
+
+ Scenario: Preview basic proxy
+ Given the Server is running at "proxy-pages-app"
+ When I go to "/fake.html"
+ Then I should see "I am real"
+ When I go to "/fake2.html"
+ Then I should see "I am real"
+ When I go to "/fake3.html"
+ Then I should see "I am real"
+ When I go to "/fake4.html"
+ Then I should see "I am real"
+
+ Scenario: Preview proxy with variable one
+ Given the Server is running at "proxy-pages-app"
+ When I go to "/fake/one.html"
+ Then I should see "I am real: one"
+
+ When I go to "/fake2/one.html"
+ Then I should see "I am real: one"
+
+ When I go to "/fake3/one.html"
+ Then I should see "I am real: one"
+
+ When I go to "/fake4/one.html"
+ Then I should see "I am real: one"
+
+ Scenario: Preview proxy with variable two
+ Given the Server is running at "proxy-pages-app"
+ When I go to "/fake/two.html"
+ Then I should see "I am real: two"
+
+ When I go to "/fake2/two.html"
+ Then I should see "I am real: two"
+
+ When I go to "/fake3/two.html"
+ Then I should see "I am real: two"
+
+ When I go to "/fake4/two.html"
+ Then I should see "I am real: two"
+
+ Scenario: Build proxy with variable one
+ Given a successfully built app at "proxy-pages-app"
+ When I cd to "build"
+ Then the file "fake/one.html" should contain "I am real: one"
+ Then the file "fake2/one.html" should contain "I am real: one"
+ Then the file "fake3/one.html" should contain "I am real: one"
+
+ Scenario: Target ignore
+ Given the Server is running at "proxy-pages-app"
+ When I go to "/target_ignore.html"
+ Then I should see "Ignore me! 3"
+ When I go to "/target_ignore2.html"
+ Then I should see "Ignore me! 6"
+ When I go to "/target_ignore3.html"
+ Then I should see "Ignore me! 7"
+ When I go to "/target_ignore4.html"
+ Then I should see "Ignore me! 8"
+
+ Scenario: Preview ignored paths
+ Given the Server is running at "proxy-pages-app"
+ When I go to "/should_be_ignored6.html"
+ Then I should see "File Not Found"
+ When I go to "/should_be_ignored7.html"
+ Then I should see "File Not Found"
+ When I go to "/should_be_ignored8.html"
+ Then I should see "File Not Found"
\ No newline at end of file
diff --git a/middleman-core/fixtures/proxy-pages-app/config.rb b/middleman-core/fixtures/proxy-pages-app/config.rb
new file mode 100644
index 00000000..0cd260cf
--- /dev/null
+++ b/middleman-core/fixtures/proxy-pages-app/config.rb
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+proxy "/fake.html", "/real.html", :layout => false
+proxy "fake2.html", "/real.html", :layout => false
+proxy "fake3.html", "real.html", :layout => false
+proxy "/fake4.html", "real.html", :layout => false
+
+proxy "/target_ignore.html", "/should_be_ignored3.html", :ignore => true
+proxy "target_ignore2.html", "/should_be_ignored6.html", :ignore => true
+proxy "target_ignore3.html", "should_be_ignored7.html", :ignore => true
+proxy "/target_ignore4.html", "should_be_ignored8.html", :ignore => true
+
+%w(one two).each do |num|
+ proxy "/fake/#{num}.html", "/real/index.html", :ignore => true, :locals => { :num => num }
+ proxy "fake2/#{num}.html", "/real/index.html", :ignore => true, :locals => { :num => num }
+ proxy "fake3/#{num}.html", "real/index.html", :ignore => true, :locals => { :num => num }
+ proxy "/fake4/#{num}.html", "real/index-ivars.html", :ignore => true do
+ @num = num
+ end
+end
+
+proxy "明日がある.html", "/real.html", :layout => false
diff --git a/middleman-core/fixtures/proxy-pages-app/source/real.html b/middleman-core/fixtures/proxy-pages-app/source/real.html
new file mode 100644
index 00000000..cb312952
--- /dev/null
+++ b/middleman-core/fixtures/proxy-pages-app/source/real.html
@@ -0,0 +1 @@
+I am real
\ No newline at end of file
diff --git a/middleman-core/fixtures/proxy-pages-app/source/real/index-ivars.html.erb b/middleman-core/fixtures/proxy-pages-app/source/real/index-ivars.html.erb
new file mode 100644
index 00000000..07563e7d
--- /dev/null
+++ b/middleman-core/fixtures/proxy-pages-app/source/real/index-ivars.html.erb
@@ -0,0 +1,6 @@
+---
+layout: false
+---
+
+I am real: <%= @num %>
+
diff --git a/middleman-core/fixtures/proxy-pages-app/source/real/index.html.erb b/middleman-core/fixtures/proxy-pages-app/source/real/index.html.erb
new file mode 100644
index 00000000..db4a78b4
--- /dev/null
+++ b/middleman-core/fixtures/proxy-pages-app/source/real/index.html.erb
@@ -0,0 +1,5 @@
+---
+layout: false
+---
+
+I am real: <%= num %>
diff --git a/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored3.html b/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored3.html
new file mode 100644
index 00000000..98007c81
--- /dev/null
+++ b/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored3.html
@@ -0,0 +1 @@
+
Ignore me! 3
\ No newline at end of file
diff --git a/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored6.html b/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored6.html
new file mode 100644
index 00000000..234e60b7
--- /dev/null
+++ b/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored6.html
@@ -0,0 +1 @@
+Ignore me! 6
\ No newline at end of file
diff --git a/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored7.html b/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored7.html
new file mode 100644
index 00000000..4179fb19
--- /dev/null
+++ b/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored7.html
@@ -0,0 +1 @@
+Ignore me! 7
\ No newline at end of file
diff --git a/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored8.html b/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored8.html
new file mode 100644
index 00000000..2c2c24ab
--- /dev/null
+++ b/middleman-core/fixtures/proxy-pages-app/source/should_be_ignored8.html
@@ -0,0 +1 @@
+Ignore me! 8
\ No newline at end of file
diff --git a/middleman-core/lib/middleman-core/core_extensions/routing.rb b/middleman-core/lib/middleman-core/core_extensions/routing.rb
index db7c6e61..53f3c3ed 100644
--- a/middleman-core/lib/middleman-core/core_extensions/routing.rb
+++ b/middleman-core/lib/middleman-core/core_extensions/routing.rb
@@ -45,9 +45,7 @@ module Middleman
# @param [Hash] opts
# @return [void]
def page(url, opts={}, &block)
-
- blocks = []
- blocks << block if block_given?
+ blocks = Array(block)
# Default layout
opts[:layout] = layout if opts[:layout].nil?
@@ -70,20 +68,12 @@ module Middleman
end
# Setup proxy
- if opts.has_key?(:proxy)
- proxy(url, opts[:proxy])
-
- if opts.has_key?(:ignore) && opts[:ignore]
- ignore(opts[:proxy])
- opts.delete(:ignore)
- end
-
- opts.delete(:proxy)
- else
- if opts.has_key?(:ignore) && opts[:ignore]
- ignore(url)
- opts.delete(:ignore)
- end
+ if target = opts.delete(:proxy)
+ # TODO: deprecate proxy through page?
+ proxy(url, target, opts, &block) and return
+ elsif opts.delete(:ignore)
+ # TODO: deprecate ignore through page?
+ ignore(url)
end
# Setup a metadata matcher for rendering those options
diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb
index c12be353..9c2ea2db 100644
--- a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb
+++ b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb
@@ -60,8 +60,6 @@ module Middleman
# @param [String, Regexp] path Path glob expression, or path regex
# @return [void]
def ignore(path=nil, &block)
- original_callback_size = @ignored_callbacks.size
-
if path.is_a? Regexp
@ignored_callbacks << Proc.new {|p| p =~ path }
elsif path.is_a? String
diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb
index 0d37054a..61091a46 100644
--- a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb
+++ b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb
@@ -74,40 +74,87 @@ module Middleman
@_proxy_manager ||= ProxyManager.new(self)
end
- def proxy(*args)
- proxy_manager.proxy(*args)
+ def proxy(*args, &block)
+ proxy_manager.proxy(*args, &block)
end
end
+ # Manages the list of proxy configurations and manipulates the sitemap
+ # to include new resources based on those configurations
class ProxyManager
def initialize(app)
@app = app
-
- @proxy_paths = {}
+ @proxy_configs = Set.new
end
# Setup a proxy from a path to a target
# @param [String] path
# @param [String] target
+ # @param [Hash] opts options to apply to the proxy, including things like
+ # :locals, :ignore to hide the proxy target, :layout, and :directory_indexes.
# @return [void]
- def proxy(path, target)
- @proxy_paths[::Middleman::Util.normalize_path(path)] = ::Middleman::Util.normalize_path(target)
+ def proxy(path, target, opts={}, &block)
+ metadata = { :options => {}, :locals => {}, :blocks => [] }
+ metadata[:blocks] << block if block_given?
+ metadata[:locals] = opts.delete(:locals) || {}
+
+ @app.ignore(target) if opts.delete(:ignore)
+ metadata[:options] = opts
+
+ @proxy_configs << ProxyConfiguration.new(:path => path, :target => target, :metadata => metadata)
+
@app.sitemap.rebuild_resource_list!(:added_proxy)
end
# Update the main sitemap resource list
# @return [void]
def manipulate_resource_list(resources)
- resources + @proxy_paths.map do |key, value|
+ resources + @proxy_configs.map do |config|
p = ::Middleman::Sitemap::Resource.new(
@app.sitemap,
- key
+ config.path
)
- p.proxy_to(value)
+ p.proxy_to(config.target)
+ p.add_metadata(config.metadata)
p
end
end
end
+
+ # Configuration for a proxy instance
+ class ProxyConfiguration
+ # The path that this proxy will appear at in the sitemap
+ attr_reader :path
+ def path=(p)
+ @path = ::Middleman::Util.normalize_path(p)
+ end
+
+ # The existing sitemap path that this will proxy to
+ attr_reader :target
+ def target=(t)
+ @target = ::Middleman::Util.normalize_path(t)
+ end
+
+ # Additional metadata like blocks and locals to apply to the proxy
+ attr_accessor :metadata
+
+ # Create a new proxy configuration from hash options
+ def initialize(options={})
+ options.each do |key, value|
+ send "#{key}=", value
+ end
+ end
+
+ # Two configurations are equal if they reference the same path
+ def eql?(other)
+ other.path == path
+ end
+
+ # Two configurations are equal if they reference the same path
+ def hash
+ path.hash
+ end
+ end
end
end
end
diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb
index 0b4a1f71..6eb0d300 100644
--- a/middleman-core/lib/middleman-core/sitemap/store.rb
+++ b/middleman-core/lib/middleman-core/sitemap/store.rb
@@ -115,19 +115,10 @@ module Middleman
# @param [Symbol] origin an indicator of where this metadata came from - only one
# block per [matcher, origin] pair may exist.
# @return [Array>]
- def provides_metadata_for_path(matcher=nil, origin=nil, &block)
+ def provides_metadata_for_path(matcher=nil, &block)
@_provides_metadata_for_path ||= []
if block_given?
- if origin
- existing_provider = @_provides_metadata_for_path.find {|b,m,o| o == origin && m == matcher}
- end
-
- if existing_provider
- existing_provider[0] = block
- else
- @_provides_metadata_for_path << [block, matcher, origin]
- end
-
+ @_provides_metadata_for_path << [block, matcher]
@_cached_metadata = {}
end
@_provides_metadata_for_path
@@ -151,10 +142,7 @@ module Middleman
metadata = callback.call(request_path)
- if metadata.has_key?(:blocks)
- result[:blocks] << metadata[:blocks]
- metadata.delete(:blocks)
- end
+ result[:blocks] += Array(metadata.delete(:blocks))
result.deep_merge(metadata)
end