1
0
Fork 0
mirror of https://github.com/middleman/middleman.git synced 2022-11-09 12:20:27 -05:00
middleman--middleman/lib/middleman/base.rb
2011-11-10 15:56:04 -08:00

228 lines
No EOL
6.9 KiB
Ruby

require "i18n"
require "hooks"
require "active_support"
require "active_support/json"
require "active_support/core_ext/class/attribute_accessors"
module Middleman::Base
class << self
def registered(app)
app.send :include, ::Hooks
app.define_hook :initialized
app.extend ClassMethods
app.send :include, InstanceMethods
# Basic Sinatra config
app.set :app_file, __FILE__
app.set :root, Dir.pwd
app.set :sessions, false
app.set :logging, false
app.set :protection, false
app.set :environment, (ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :development
# Middleman-specific options
app.set :index_file, "index.html" # What file responds to folder requests
# Such as the homepage (/) or subfolders (/about/)
# These directories are passed directly to Compass
app.set :js_dir, "javascripts" # Where to look for javascript files
app.set :css_dir, "stylesheets" # Where to look for CSS files
app.set :images_dir, "images" # Where to look for images
app.set :build_dir, "build" # Which folder are builds output to
app.set :http_prefix, nil # During build, add a prefix for absolute paths
# Pass all request to Middleman, even "static" files
app.set :static, false
app.set :views, "source"
# Add Builder Callbacks
app.register Middleman::CoreExtensions::Builder
# Add Rack::Builder.map to Sinatra
app.register Middleman::CoreExtensions::RackMap
# Activate custom features
app.register Middleman::CoreExtensions::Features
# Add Builder Callbacks
app.register Middleman::CoreExtensions::FileWatcher
# Sitemap
app.register Middleman::CoreExtensions::Sitemap
# Activate Yaml Data package
app.register Middleman::CoreExtensions::Data
# Setup custom rendering
app.register Middleman::CoreExtensions::Rendering
# Compass framework
app.register Middleman::CoreExtensions::Compass
# Sprockets asset handling
app.register Middleman::CoreExtensions::Sprockets
# Setup asset path pipeline
app.register Middleman::CoreExtensions::Assets
# Activate built-in helpers
app.register Middleman::CoreExtensions::DefaultHelpers
# with_layout and page routing
app.register Middleman::CoreExtensions::Routing
# Parse YAML from templates
app.register Middleman::CoreExtensions::FrontMatter
app.set :default_features, [
# :lorem,
# :sitemap_tree
]
# Default layout name
app.set :layout, :layout
# This will match all requests not overridden in the project's config.rb
app.not_found do
process_request
end
# Custom 404 handler (to be styled)
app.error Sinatra::NotFound do
content_type 'text/html'
"<html><body><h1>File Not Found</h1><p>#{request.path_info}</p></body>"
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
module ClassMethods
# Override Sinatra's set to accept a block
# Specifically for the asset_host feature
def set(option, value = (not_set = true), ignore_setter = false, &block)
if block_given?
value = Proc.new { block }
end
super(option, value, ignore_setter, &nil)
end
def before_processing(name=:unnamed, idx=-1, &block)
@before_processes ||= []
@before_processes.insert(idx, [name, block])
end
def execute_before_processing!(inst, resolved_template)
@before_processes ||= []
@before_processes.all? do |name, block|
inst.instance_exec(resolved_template, &block)
end
end
# Convenience method to check if we're in build mode
def build?; environment == :build; end
# Creates a Rack::Builder instance with all the middleware set up and
# an instance of this class as end point.
def build_new(inst=false)
builder = Rack::Builder.new
setup_default_middleware builder
setup_middleware builder
builder.run inst || new!
builder.to_app
end
end
module InstanceMethods
def initialize(*args)
super
run_hook :initialized, settings
end
def forward
raise ::Sinatra::NotFound
end
# Internal method to look for templates and evaluate them if found
def process_request(options={})
if !settings.views.include?(settings.root)
settings.set :views, File.join(settings.root, settings.views)
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", " ")
found_template = resolve_template(request_path, :raise_exceptions => false)
return status(404) unless found_template
return unless settings.execute_before_processing!(self, found_template)
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)$/
false
else
settings.fetch_layout_path(settings.layout).to_sym
end
else
false
end
render_options = { :layout => local_layout }
render_options[:layout_engine] = options[:layout_engine] if options.has_key? :layout_engine
path, engine = found_template
locals = request['custom_locals'] || {}
begin
result = render(engine, path, render_options, locals)
if result
content_type mime_type(File.extname(request_path))
status 200
body result
end
ensure
settings.set :layout, old_layout
end
end
end
end