mirror of
https://github.com/middleman/middleman.git
synced 2022-11-09 12:20:27 -05:00
169 lines
5.2 KiB
Ruby
169 lines
5.2 KiB
Ruby
|
# We're riding on Sinatra, so let's include it.
|
||
|
require "sinatra/base"
|
||
|
|
||
|
# The content_for plugin allows Sinatra to use the throw/yield block
|
||
|
# system similar to Rails views.
|
||
|
require "sinatra/content_for"
|
||
|
|
||
|
# Monkey-patch Sinatra to expose the layout parameter
|
||
|
class Sinatra::Request
|
||
|
attr_accessor :layout
|
||
|
end
|
||
|
|
||
|
module Middleman
|
||
|
class Server < Sinatra::Base
|
||
|
# Basic Sinatra config
|
||
|
set :app_file, __FILE__
|
||
|
set :root, ENV["MM_DIR"] || Dir.pwd
|
||
|
set :reload, false
|
||
|
set :sessions, false
|
||
|
set :logging, false
|
||
|
set :environment, (ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :development
|
||
|
|
||
|
# Import content_for methods
|
||
|
helpers Sinatra::ContentFor
|
||
|
|
||
|
# Middleman-specific options
|
||
|
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
|
||
|
set :js_dir, "javascripts" # Where to look for javascript files
|
||
|
set :css_dir, "stylesheets" # Where to look for CSS files
|
||
|
set :images_dir, "images" # Where to look for images
|
||
|
set :fonts_dir, "fonts" # Where to look for fonts
|
||
|
|
||
|
set :build_dir, "build" # Which folder are builds output to
|
||
|
set :http_prefix, nil # During build, add a prefix for absolute paths
|
||
|
|
||
|
# A hash of enabled features
|
||
|
@@enabled_features = {}
|
||
|
|
||
|
# Override Sinatra's enable to keep track of enabled features
|
||
|
def self.enable(feature_name, config={})
|
||
|
@@enabled_features[feature_name] = config
|
||
|
super(feature_name)
|
||
|
end
|
||
|
|
||
|
# Disable a feature, then pass to Sinatra's method
|
||
|
def self.disable(feature_name)
|
||
|
@@enabled_features.delete(feature_name)
|
||
|
super(feature_name)
|
||
|
end
|
||
|
|
||
|
# Override Sinatra's set to accept a block
|
||
|
def self.set(option, value=self, &block)
|
||
|
if block_given?
|
||
|
value = Proc.new { block }
|
||
|
end
|
||
|
|
||
|
super(option, value, &nil)
|
||
|
end
|
||
|
|
||
|
# An array of callback procs to run after all features have been setup
|
||
|
@@run_after_features = []
|
||
|
|
||
|
# Add a block/proc to be run after features have been setup
|
||
|
def self.after_feature_init(&block)
|
||
|
@@run_after_features << block
|
||
|
end
|
||
|
|
||
|
# Rack helper for adding mime-types during local preview
|
||
|
def self.mime(ext, type)
|
||
|
ext = ".#{ext}" unless ext.to_s[0] == ?.
|
||
|
::Rack::Mime::MIME_TYPES[ext.to_s] = type
|
||
|
end
|
||
|
|
||
|
# Keep track of a block-specific layout
|
||
|
@@layout = nil
|
||
|
|
||
|
# Takes a block which allows many pages to have the same layout
|
||
|
# with_layout :admin do
|
||
|
# page "/admin/"
|
||
|
# page "/admin/login.html"
|
||
|
# end
|
||
|
def self.with_layout(layout, &block)
|
||
|
@@layout = layout
|
||
|
class_eval(&block) if block_given?
|
||
|
ensure
|
||
|
@@layout = nil
|
||
|
end
|
||
|
|
||
|
# The page method allows the layout to be set on a specific path
|
||
|
# page "/about.html", :layout => false
|
||
|
# page "/", :layout => :homepage_layout
|
||
|
def self.page(url, options={}, &block)
|
||
|
layout = @@layout
|
||
|
layout = options[:layout] if !options[:layout].nil?
|
||
|
|
||
|
get(url) do
|
||
|
return yield if block_given?
|
||
|
process_request(layout)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# This will match all requests not overridden in the project's config.rb
|
||
|
not_found do
|
||
|
process_request
|
||
|
end
|
||
|
|
||
|
private
|
||
|
# Internal method to look for templates and evaluate them if found
|
||
|
def process_request(layout = :layout)
|
||
|
# Normalize the path and add index if we're looking at a directory
|
||
|
path = request.path
|
||
|
path << settings.index_file if path.match(%r{/$})
|
||
|
path.gsub!(%r{^/}, '')
|
||
|
|
||
|
if template_path = Dir.glob(File.join(settings.views, "#{path}.*")).first
|
||
|
content_type mime_type(File.extname(path)), :charset => 'utf-8'
|
||
|
|
||
|
renderer = Middleman::Renderers.get_method(template_path)
|
||
|
if respond_to? renderer
|
||
|
status 200
|
||
|
return send(renderer, path.to_sym, { :layout => layout })
|
||
|
end
|
||
|
end
|
||
|
|
||
|
status 404
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
require "middleman/assets"
|
||
|
require "middleman/renderers"
|
||
|
require "middleman/features"
|
||
|
|
||
|
# The Rack App
|
||
|
class Middleman::Server
|
||
|
def self.new(*args, &block)
|
||
|
# If the old init.rb exists, use it, but issue warning
|
||
|
old_config = File.join(self.root, "init.rb")
|
||
|
if File.exists? old_config
|
||
|
$stderr.puts "== Warning: The init.rb file has been renamed to config.rb"
|
||
|
local_config = old_config
|
||
|
end
|
||
|
|
||
|
# Check for and evaluate local configuration
|
||
|
local_config ||= File.join(self.root, "config.rb")
|
||
|
if File.exists? local_config
|
||
|
$stderr.puts "== Reading: Local config" if logging?
|
||
|
Middleman::Server.class_eval File.read(local_config)
|
||
|
set :app_file, File.expand_path(local_config)
|
||
|
end
|
||
|
|
||
|
# loop over enabled feature
|
||
|
@@enabled_features.each do |feature_name, feature_config|
|
||
|
next unless send(:"#{feature_name}?")
|
||
|
$stderr.puts "== Enabling: #{feature_name.to_s.capitalize}" if logging?
|
||
|
Middleman::Features.run(feature_name, feature_config, self)
|
||
|
end
|
||
|
|
||
|
use ::Rack::ConditionalGet if environment == :development
|
||
|
|
||
|
@@run_after_features.each { |block| class_eval(&block) }
|
||
|
|
||
|
super
|
||
|
end
|
||
|
end
|