From 74bfcbe1aa41f6996af712d6027438fd8bc24e85 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 13 Nov 2011 21:57:53 -0800 Subject: [PATCH] refactor sitemap to add context cache --- lib/middleman/base.rb | 82 ++++++++++--------- lib/middleman/core_extensions/front_matter.rb | 2 +- lib/middleman/core_extensions/routing.rb | 38 ++------- lib/middleman/core_extensions/sitemap.rb | 21 +++++ 4 files changed, 73 insertions(+), 70 deletions(-) diff --git a/lib/middleman/base.rb b/lib/middleman/base.rb index ed380a04..ce7ec58e 100644 --- a/lib/middleman/base.rb +++ b/lib/middleman/base.rb @@ -96,36 +96,6 @@ module Middleman::Base content_type 'text/html' "

File Not Found

#{request.path_info}

" end - - # See if Tilt cannot handle this file - app.before_processing(:base) do |result| - request_path = request.path_info.gsub("%20", " ") - - should_be_ignored = !(request["is_proxy"]) && settings.sitemap.ignored_path?("/#{request_path}") - - if result && !should_be_ignored - extensionless_path, template_engine = result - - # Return static files - if !::Tilt.mappings.has_key?(template_engine.to_s) - matched_mime = mime_type(File.extname(request_path)) - matched_mime = "application/octet-stream" if matched_mime.nil? - content_type matched_mime - status 200 - send_file File.join(settings.views, request_path) - false - else - true - end - else - if !%w(favicon.ico).include?(request_path) - $stderr.puts "File not found: #{request_path}" - end - - status 404 - false - end - end end alias :included :registered end @@ -141,6 +111,14 @@ module Middleman::Base super(option, value, ignore_setter, &nil) end + def full_path(path) + parts = path ? path.split('/') : [] + if parts.last.nil? || parts.last.split('.').length == 1 + path = File.join(path, index_file) + end + "/" + path.sub(%r{^/}, '') + end + def before_processing(name=:unnamed, idx=-1, &block) @before_processes ||= [] @before_processes.insert(idx, [name, block]) @@ -177,27 +155,50 @@ module Middleman::Base def forward raise ::Sinatra::NotFound end - + # Internal method to look for templates and evaluate them if found - def process_request(options={}) + def process_request if !settings.views.include?(settings.root) settings.set :views, File.join(settings.root, settings.views) - end + end # Normalize the path and add index if we're looking at a directory - request.path_info = self.class.path_to_index(request.path) - request_path = request.path_info.gsub("%20", " ") + request_path = settings.full_path(request.path.gsub("%20", " ")) + original_path = request_path.dup + + return status(404) if settings.sitemap.ignored_path?(request_path) + + if settings.sitemap.path_is_proxy?(request_path) + request["is_proxy"] = true + request_path = "/" + settings.sitemap.path_target(request_path) + end + found_template = resolve_template(request_path, :raise_exceptions => false) return status(404) unless found_template + + path, engine = found_template + + if !::Tilt.mappings.has_key?(engine.to_s) + matched_mime = mime_type(File.extname(request_path)) + matched_mime = "application/octet-stream" if matched_mime.nil? + content_type matched_mime + status 200 + send_file File.join(settings.views, request_path) + return + end + return unless settings.execute_before_processing!(self, found_template) + context = settings.sitemap.get_context(original_path) || {} + + options = context.has_key?(:options) ? context[:options] : {} options.merge!(request['custom_options'] || {}) old_layout = settings.layout settings.set :layout, options[:layout] if !options[:layout].nil? local_layout = if settings.layout - if options[:layout] == false || request.path_info =~ /\.(css|js)$/ + if options[:layout] == false || request_path =~ /\.(css|js)$/ false else settings.fetch_layout_path(settings.layout).to_sym @@ -207,11 +208,14 @@ module Middleman::Base end render_options = { :layout => local_layout } - render_options[:layout_engine] = options[:layout_engine] if options.has_key? :layout_engine - - path, engine = found_template + render_options[:layout_engine] = options[:layout_engine] if options.has_key?(:layout_engine) + locals = request['custom_locals'] || {} + if context.has_key?(:block) && context[:block] + instance_eval(&context[:block]) + end + begin result = render(engine, path, render_options, locals) diff --git a/lib/middleman/core_extensions/front_matter.rb b/lib/middleman/core_extensions/front_matter.rb index 7bc20a4b..38e8a6bf 100644 --- a/lib/middleman/core_extensions/front_matter.rb +++ b/lib/middleman/core_extensions/front_matter.rb @@ -15,7 +15,7 @@ module Middleman::CoreExtensions::FrontMatter end app.after_configuration do - app.before_processing(:front_matter, 0) do |result| + app.before_processing(:front_matter) do |result| if result && Tilt.mappings.has_key?(result[1].to_s) extensionless_path, template_engine = result full_file_path = "#{extensionless_path}.#{template_engine}" diff --git a/lib/middleman/core_extensions/routing.rb b/lib/middleman/core_extensions/routing.rb index 02fb6bdd..1cd6cb97 100644 --- a/lib/middleman/core_extensions/routing.rb +++ b/lib/middleman/core_extensions/routing.rb @@ -7,14 +7,6 @@ module Middleman::CoreExtensions::Routing end module ClassMethods - def path_to_index(path) - parts = path ? path.split('/') : [] - if parts.last.nil? || parts.last.split('.').length == 1 - path = File.join(path, index_file) - end - path.gsub(%r{^/}, '') - end - # Takes a block which allows many pages to have the same layout # with_layout :admin do # page "/admin/" @@ -28,48 +20,34 @@ module Middleman::CoreExtensions::Routing ensure set :layout, old_layout end - - def paths_for_url(url) - url = url.gsub(%r{\/#{index_file}$}, "") - url = url.gsub(%r{(\/)$}, "") if url.length > 1 - - paths = [url] - paths << "#{url}/" if url.length > 1 && url.split("/").last.split('.').length <= 1 - paths << "/#{path_to_index(url)}" - paths - end # The page method allows the layout to be set on a specific path # page "/about.html", :layout => false # page "/", :layout => :homepage_layout def page(url, options={}, &block) - has_block = block_given? options[:layout] = layout if options[:layout].nil? + + url = full_path(url) if options.has_key?(:proxy) reroute(url, options[:proxy]) if options.has_key?(:ignore) && options[:ignore] ignore(options[:proxy]) + options.delete(:ignore) end options.delete(:proxy) else if options.has_key?(:ignore) && options[:ignore] ignore(url) + options.delete(:ignore) end end - - paths_for_url(url).each do |p| - get(p) do - if settings.sitemap.path_is_proxy?(url) - request["is_proxy"] = true - request.path_info = settings.sitemap.path_target(url) - end - - instance_eval(&block) if has_block - process_request(options) - end + + a_block = block_given? ? block : nil + if a_block || !options.empty? + sitemap.set_context(url, options, a_block) end end end diff --git a/lib/middleman/core_extensions/sitemap.rb b/lib/middleman/core_extensions/sitemap.rb index 87898dea..08346a72 100644 --- a/lib/middleman/core_extensions/sitemap.rb +++ b/lib/middleman/core_extensions/sitemap.rb @@ -43,6 +43,7 @@ module Middleman::CoreExtensions::Sitemap @app = app @source = File.expand_path(@app.views, @app.root) @map = {} + @context_map = {} @source_map = {} @ignored_paths = false @generic_paths = false @@ -68,6 +69,11 @@ module Middleman::CoreExtensions::Sitemap @map[path] end + def path_context(path) + path = path.sub(/^\//, "") + @context_map[path] + end + def set_path(path, target=true) path = path.sub(/^\//, "") target = target.sub(/^\//, "") if target.is_a?(String) @@ -79,8 +85,22 @@ module Middleman::CoreExtensions::Sitemap @proxied_paths = false if target.is_a?(String) end + def set_context(path, options={}, block=nil) + path = path.sub(/^\//, "") + @context_map[path] = { + :options => options, + :block => block + } + end + + def get_context(path) + path = path.sub(/^\//, "") + @context_map[path] + end + def ignore_path(path) set_path(path, false) + @ignored_paths = false end def each(&block) @@ -154,6 +174,7 @@ module Middleman::CoreExtensions::Sitemap def remove_path(path) path = path.sub(/^\//, "") @map.delete(path) if path_exists?(path) + @context_map.delete(path) if @context_map.has_key?(path) end def source_map