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