tests passing

This commit is contained in:
tdreyno 2009-10-15 14:24:00 -07:00
parent 2400c670b4
commit b1d300718f
17 changed files with 225 additions and 233 deletions

View file

@ -2,16 +2,7 @@
require 'optparse' require 'optparse'
# Require Middleman env = ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development'
require File.join(File.dirname(__FILE__), '..', 'lib', 'middleman')
class Middleman::Base
set :root, Dir.pwd
set :logging, false
enable :static
end
env = ENV['RACK_ENV'] || 'development'
options = { :Port => 4567, :Host => 'localhost', :AccessLog => [] } options = { :Port => 4567, :Host => 'localhost', :AccessLog => [] }
OptionParser.new { |opts| OptionParser.new { |opts|
@ -28,47 +19,21 @@ OptionParser.new { |opts|
opts.parse! ARGV opts.parse! ARGV
} }
require 'rack'
require 'rack/utils'
require 'rack/request'
require 'rack/response'
require 'rack/showexceptions'
module Middleman
class Static
def initialize(app, options={})
@app = app
root = Middleman::Base.public
@file_server = Rack::File.new(root)
end
def call(env)
path = env["PATH_INFO"]
if path.include?("favicon.ico") || File.exists?(File.join(Middleman::Base.public, path))
@file_server.call(env)
else
@app.call(env)
end
end
end
end
app_wrapper = lambda do |inner_app|
Rack::Builder.new {
use Rack::ShowExceptions
use Middleman::Static
run Middleman::Base
}.to_app
end
ENV['RACK_ENV'] = env ENV['RACK_ENV'] = env
# Require Middleman
require File.join(File.dirname(__FILE__), '..', 'lib', 'middleman')
class Middleman::Base
set :root, Dir.pwd
set :logging, false
end
require 'shotgun' require 'shotgun'
require 'thin'
config = File.join(File.dirname(__FILE__), '..', 'lib', 'middleman', 'config.ru') config = File.join(File.dirname(__FILE__), '..', 'lib', 'middleman', 'config.ru')
app = Shotgun.new(config, app_wrapper) app = Shotgun.new(config, lambda { |inner_app| Middleman::Base.new })
require 'thin'
Thin::Logging.silent = true Thin::Logging.silent = true
Rack::Handler::Thin.run app, options do |inst| Rack::Handler::Thin.run app, options do |inst|

View file

@ -9,7 +9,7 @@ module Middleman
set :app_file, __FILE__ set :app_file, __FILE__
set :root, Dir.pwd set :root, Dir.pwd
set :environment, ENV['MM_ENV'] || :development set :environment, ENV['MM_ENV'] || :development
set :supported_formats, ["erb"] set :supported_formats, %w(erb)
set :index_file, "index.html" set :index_file, "index.html"
set :js_dir, "javascripts" set :js_dir, "javascripts"
set :css_dir, "stylesheets" set :css_dir, "stylesheets"
@ -17,9 +17,28 @@ module Middleman
set :build_dir, "build" set :build_dir, "build"
set :http_prefix, "/" set :http_prefix, "/"
require 'sinatra/content_for'
helpers Sinatra::ContentFor
require 'middleman/helpers'
helpers Middleman::Helpers
# Static files in public/
enable :static
require 'middleman/rack/static'
use Middleman::Rack::Static
@@features = []
def self.enable(*opts)
@@features << opts
super
end
def self.disable(*opts)
@@features -= opts
super
end
# Features enabled by default # Features enabled by default
enable :compass
enable :content_for
enable :sprockets enable :sprockets
# Features disabled by default # Features disabled by default
@ -77,48 +96,34 @@ module Middleman
content_type media_type(File.extname(path)), :charset => 'utf-8' content_type media_type(File.extname(path)), :charset => 'utf-8'
status 200 status 200
content content
else
# If no template handler renders the template, return the static file if it exists
path = File.join(options.public, request.path)
if !File.directory?(path) && File.exists?(path)
status 200
send_file(path)
else else
status 404 status 404
end end
end end
end
@@inited = false @@inited = false
# Require the features for this project # Require the features for this project
def self.init!(quiet=false, rerun=true) def self.init!(quiet=false, rerun=true)
return if @@inited && !rerun return if @@inited && !rerun
# Built-in helpers
require 'middleman/helpers'
helpers Middleman::Helpers
# Haml is required & includes helpers
require "middleman/features/haml"
# Check for and evaluate local configuration # Check for and evaluate local configuration
local_config = File.join(self.root, "init.rb") local_config = File.join(self.root, "init.rb")
if File.exists? local_config if File.exists? local_config
puts "== Local config at: #{local_config}" unless quiet puts "== Reading: Local config" unless quiet
class_eval File.read(local_config) class_eval File.read(local_config)
end end
# loop over enabled feature # loop over enabled feature
features_path = File.expand_path("features/*.rb", File.dirname(__FILE__)) @@features.flatten.each do |feature_name|
Dir[features_path].each do |f| puts "== Enabling: #{feature_name.capitalize}" unless quiet
feature_name = File.basename(f, '.rb')
option_name = :"#{feature_name}?"
if respond_to?(option_name) && send(option_name) === true
require "middleman/features/#{feature_name}" require "middleman/features/#{feature_name}"
end end
end
@@inited = true @@inited = true
end end
end end
end end
# Haml is required & includes helpers
require "middleman/haml"
require "middleman/sass"

View file

@ -1,6 +1,5 @@
require 'templater' require 'templater'
require 'middleman/templater+dynamic_renderer.rb' require 'middleman/templater+dynamic_renderer.rb'
require 'rack/test' # Use Rack::Test to access Sinatra without starting up a full server
# Placeholder for any methods the builder needs to abstract to allow feature integration # Placeholder for any methods the builder needs to abstract to allow feature integration
module Middleman module Middleman
@ -37,9 +36,12 @@ module Middleman
end end
def self.init! def self.init!
glob! File.basename(Middleman::Base.public), Middleman::Base.supported_formats glob! File.basename(Middleman::Base.public), []
glob! File.basename(Middleman::Base.views), Middleman::Base.supported_formats glob! File.basename(Middleman::Base.views), Middleman::Base.supported_formats
end end
def after_run
end
end end
module Generators module Generators

View file

@ -1,15 +1,13 @@
class Middleman::Base class << Middleman::Base
alias_method :pre_cache_buster_asset_url, :asset_url alias_method :pre_cache_buster_asset_url, :asset_url
helpers do
def asset_url(path, prefix="") def asset_url(path, prefix="")
http_path = pre_cache_buster_asset_url(path, prefix) http_path = pre_cache_buster_asset_url(path, prefix)
if http_path.include?("://") || !%w(.css .png .jpg .js .gif).include?(File.extname(http_path)) if http_path.include?("://") || !%w(.css .png .jpg .js .gif).include?(File.extname(http_path))
http_path http_path
else else
real_path = File.join(self.class.environment == "build" ? options.build_dir : options.public, prefix, path) real_path = File.join(self.environment == "build" ? self.build_dir : self.public, prefix, path)
http_path << "?" + File.mtime(real_path).strftime("%s") if File.readable?(real_path) http_path << "?" + File.mtime(real_path).strftime("%s") if File.readable?(real_path)
http_path http_path
end end
end end
end
end end

View file

@ -1,9 +0,0 @@
begin
require 'sinatra/content_for'
class Middleman::Base
helpers Sinatra::ContentFor
end
rescue LoadError
puts "Sinatra::ContentFor not available. Install it with: gem install sinatra-content-for"
end

View file

@ -12,20 +12,21 @@ module Middleman
END END
end end
end end
module StaticJavascript
def render_path(path)
if template_exists?(path, :js)
compressor = YUI::JavaScriptCompressor.new(:munge => true)
compressor.compress(super)
else
super
end
end
end
end end
class Base class Builder
include Middleman::Minified::StaticJavascript alias_method :pre_yui_after_run, :after_run
def after_run
pre_yui_after_run
compressor = ::YUI::JavaScriptCompressor.new(:munge => true)
Dir[File.join(Middleman::Base.build_dir, Middleman::Base.js_dir, "**", "*.js")].each do |path|
compressed_js = compressor.compress(File.read(path))
File.open(path, 'w') { |f| f.write(compressed_js) }
say "<%= color('#{"[COMPRESSED]".rjust(12)}', :yellow) %> " + path.gsub(Middleman::Base.build_dir+"/", '')
end end
end
end if Middleman::Base.environment == "build"
end end
Middleman::Base.supported_formats << "js"

View file

@ -6,8 +6,9 @@ class Middleman::Base
end end
end end
end end
end
helpers do class << Middleman::Base
alias_method :pre_relative_asset_url, :asset_url alias_method :pre_relative_asset_url, :asset_url
def asset_url(path, prefix="") def asset_url(path, prefix="")
path = pre_relative_asset_url(path, prefix) path = pre_relative_asset_url(path, prefix)
@ -27,5 +28,4 @@ class Middleman::Base
end end
end end
end end
end
end end

View file

@ -6,25 +6,30 @@ rescue LoadError
end end
module Middleman module Middleman
module Sprockets module Rack
def self.included(base) class Sprockets
base.supported_formats << "js" def initialize(app, options={})
@app = app
end end
def render_path(path) def call(env)
source = File.join(options.public, path) path = env["PATH_INFO"]
if File.extname(path) == '.js' && File.exists?(source) source = File.join(Middleman::Base.views, path)
secretary = ::Sprockets::Secretary.new( :asset_root => options.public,
:source_files => [source] ) if path.match(/\.js$/) && File.exists?(source)
# may need to rejigger since sprockets will only read views/ now secretary = ::Sprockets::Secretary.new( :root => Middleman::Base.root,
secretary.concatenation.to_s :source_files => [ File.join("views", path) ],
:load_path => [ File.join("public", Middleman::Base.js_dir),
File.join("views", Middleman::Base.js_dir) ])
[200, { "Content-Type" => "text/javascript" }, [secretary.concatenation.to_s]]
else else
super @app.call(env)
end
end end
end end
end end
end end
class Middleman::Base Middleman::Base.use Middleman::Rack::Sprockets
include Middleman::Sprockets Middleman::Base.supported_formats << "js"
end

View file

@ -1,4 +1,4 @@
require 'haml' require "haml"
module Middleman module Middleman
module Haml module Haml
@ -62,71 +62,8 @@ module Middleman
end end
end end
end end
module Sass
def self.included(base)
base.supported_formats << "sass"
end
def render_path(path)
if template_exists?(path, :sass)
begin
static_version = options.public + request.path_info
send_file(static_version) if File.exists? static_version
location_of_sass_file = options.environment == "build" ? File.join(options.build_dir, options.css_dir) : "public"
css_filename = File.join(Dir.pwd, location_of_sass_file) + request.path_info
sass(path.to_sym, Compass.sass_engine_options.merge({ :css_filename => css_filename }))
rescue Exception => e
sass_exception_string(e)
end
else
super
end
end
# Handle Sass errors
def sass_exception_string(e)
e_string = "#{e.class}: #{e.message}"
if e.is_a? ::Sass::SyntaxError
e_string << "\non line #{e.sass_line}"
if e.sass_filename
e_string << " of #{e.sass_filename}"
if File.exists?(e.sass_filename)
e_string << "\n\n"
min = [e.sass_line - 5, 0].max
begin
File.read(e.sass_filename).rstrip.split("\n")[
min .. e.sass_line + 5
].each_with_index do |line, i|
e_string << "#{min + i + 1}: #{line}\n"
end
rescue
e_string << "Couldn't read sass file: #{e.sass_filename}"
end
end
end
end
<<END
/*
#{e_string}
Backtrace:\n#{e.backtrace.join("\n")}
*/
body:before {
white-space: pre;
font-family: monospace;
content: "#{e_string.gsub('"', '\"').gsub("\n", '\\A ')}"; }
END
end
end
end end
class Middleman::Base class Middleman::Base
include Middleman::Haml::Renderer include Middleman::Haml::Renderer
include Middleman::Sass
end end

View file

@ -1,4 +1,11 @@
module Middleman module Middleman
class Base
def self.asset_url(path, prefix="")
base_url = File.join(self.http_prefix, prefix)
path.include?("://") ? path : File.join(base_url, path)
end
end
module Helpers module Helpers
def page_classes(*additional) def page_classes(*additional)
path = request.path_info path = request.path_info
@ -14,17 +21,16 @@ module Middleman
classes.join(' ') classes.join(' ')
end end
def asset_url(*args)
self.class.asset_url(*args)
end
def link_to(title, url="#", params={}) def link_to(title, url="#", params={})
params.merge!(:href => url) params.merge!(:href => url)
params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ') params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ')
%Q{<a #{params}>#{title}</a>} %Q{<a #{params}>#{title}</a>}
end end
def asset_url(path, prefix="")
base_url = File.join(options.http_prefix, prefix)
path.include?("://") ? path : File.join(base_url, path)
end
def image_tag(path, params={}) def image_tag(path, params={})
params[:alt] ||= "" params[:alt] ||= ""
params = params.merge(:src => asset_url(path, options.images_dir)) params = params.merge(:src => asset_url(path, options.images_dir))

View file

@ -0,0 +1,20 @@
module Middleman
module Rack
class Static
def initialize(app, options={})
@app = app
root = Middleman::Base.public
@file_server = ::Rack::File.new(root)
end
def call(env)
path = env["PATH_INFO"]
if path.include?("favicon.ico") || File.exists?(File.join(Middleman::Base.public, path))
@file_server.call(env)
else
@app.call(env)
end
end
end
end
end

70
lib/middleman/sass.rb Normal file
View file

@ -0,0 +1,70 @@
require "sass"
require "middleman/compass"
module Middleman
module Sass
def self.included(base)
base.supported_formats << "sass"
end
def render_path(path)
if template_exists?(path, :sass)
begin
static_version = options.public + request.path_info
send_file(static_version) if File.exists? static_version
location_of_sass_file = options.environment == "build" ? File.join(options.build_dir, options.css_dir) : "public"
css_filename = File.join(Dir.pwd, location_of_sass_file) + request.path_info
sass(path.to_sym, ::Compass.sass_engine_options.merge({ :css_filename => css_filename }))
rescue Exception => e
sass_exception_string(e)
end
else
super
end
end
# Handle Sass errors
def sass_exception_string(e)
e_string = "#{e.class}: #{e.message}"
if e.is_a? ::Sass::SyntaxError
e_string << "\non line #{e.sass_line}"
if e.sass_filename
e_string << " of #{e.sass_filename}"
if File.exists?(e.sass_filename)
e_string << "\n\n"
min = [e.sass_line - 5, 0].max
begin
File.read(e.sass_filename).rstrip.split("\n")[
min .. e.sass_line + 5
].each_with_index do |line, i|
e_string << "#{min + i + 1}: #{line}\n"
end
rescue
e_string << "Couldn't read sass file: #{e.sass_filename}"
end
end
end
end
<<END
/*
#{e_string}
Backtrace:\n#{e.backtrace.join("\n")}
*/
body:before {
white-space: pre;
font-family: monospace;
content: "#{e_string.gsub('"', '\"').gsub("\n", '\\A ')}"; }
END
end
end
end
class Middleman::Base
include Middleman::Sass
end

View file

@ -1,3 +1,5 @@
require 'rack/test' # Use Rack::Test to access Sinatra without starting up a full server
# Monkey-patch to use a dynamic renderer # Monkey-patch to use a dynamic renderer
class Templater::Actions::File class Templater::Actions::File
def identical? def identical?

View file

@ -4,25 +4,15 @@ base = ::Middleman::Base
base.set :root, File.join(File.dirname(__FILE__), "fixtures", "sample") base.set :root, File.join(File.dirname(__FILE__), "fixtures", "sample")
describe "Cache Buster Feature" do describe "Cache Buster Feature" do
before do
base.disable :cache_buster
base.init!(true)
@app = base.new
end
it "should not append query string if off" do it "should not append query string if off" do
@app.asset_url("stylesheets/static.css").should_not include("?") base.disable :cache_buster
end base.init!(true, true)
end base.asset_url("stylesheets/static.css").should_not include("?")
describe "Cache Buster Feature" do
before do
base.enable :cache_buster
base.init!(true)
@app = base.new
end end
it "should append query string if on" do it "should append query string if on" do
@app.asset_url("stylesheets/static.css").should include("?") base.enable :cache_buster
base.init!(true, true)
base.asset_url("stylesheets/static.css").should include("?")
end end
end end

View file

@ -1 +0,0 @@
//= require "to-be-included"

View file

@ -0,0 +1 @@
//= require <to-be-included>