tests passing
This commit is contained in:
parent
2400c670b4
commit
b1d300718f
|
@ -2,16 +2,7 @@
|
|||
|
||||
require 'optparse'
|
||||
|
||||
# Require Middleman
|
||||
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'
|
||||
env = ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development'
|
||||
options = { :Port => 4567, :Host => 'localhost', :AccessLog => [] }
|
||||
|
||||
OptionParser.new { |opts|
|
||||
|
@ -28,47 +19,21 @@ OptionParser.new { |opts|
|
|||
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
|
||||
|
||||
# Require Middleman
|
||||
require File.join(File.dirname(__FILE__), '..', 'lib', 'middleman')
|
||||
|
||||
class Middleman::Base
|
||||
set :root, Dir.pwd
|
||||
set :logging, false
|
||||
end
|
||||
|
||||
require 'shotgun'
|
||||
require 'thin'
|
||||
|
||||
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
|
||||
|
||||
Rack::Handler::Thin.run app, options do |inst|
|
||||
|
|
|
@ -9,7 +9,7 @@ module Middleman
|
|||
set :app_file, __FILE__
|
||||
set :root, Dir.pwd
|
||||
set :environment, ENV['MM_ENV'] || :development
|
||||
set :supported_formats, ["erb"]
|
||||
set :supported_formats, %w(erb)
|
||||
set :index_file, "index.html"
|
||||
set :js_dir, "javascripts"
|
||||
set :css_dir, "stylesheets"
|
||||
|
@ -17,9 +17,28 @@ module Middleman
|
|||
set :build_dir, "build"
|
||||
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
|
||||
enable :compass
|
||||
enable :content_for
|
||||
enable :sprockets
|
||||
|
||||
# Features disabled by default
|
||||
|
@ -66,26 +85,19 @@ module Middleman
|
|||
# This will match all requests not overridden in the project's init.rb
|
||||
not_found do
|
||||
self.class.init!(true, false)
|
||||
|
||||
|
||||
# Normalize the path and add index if we're looking at a directory
|
||||
path = request.path
|
||||
path << options.index_file if path.match(%r{/$})
|
||||
path.gsub!(%r{^/}, '')
|
||||
|
||||
|
||||
# If the enabled renderers succeed, return the content, mime-type and an HTTP 200
|
||||
if content = render_path(path)
|
||||
content_type media_type(File.extname(path)), :charset => 'utf-8'
|
||||
status 200
|
||||
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
|
||||
status 404
|
||||
end
|
||||
status 404
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -94,31 +106,24 @@ module Middleman
|
|||
def self.init!(quiet=false, rerun=true)
|
||||
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
|
||||
local_config = File.join(self.root, "init.rb")
|
||||
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)
|
||||
end
|
||||
|
||||
|
||||
# loop over enabled feature
|
||||
features_path = File.expand_path("features/*.rb", File.dirname(__FILE__))
|
||||
Dir[features_path].each do |f|
|
||||
feature_name = File.basename(f, '.rb')
|
||||
option_name = :"#{feature_name}?"
|
||||
if respond_to?(option_name) && send(option_name) === true
|
||||
require "middleman/features/#{feature_name}"
|
||||
end
|
||||
@@features.flatten.each do |feature_name|
|
||||
puts "== Enabling: #{feature_name.capitalize}" unless quiet
|
||||
require "middleman/features/#{feature_name}"
|
||||
end
|
||||
|
||||
@@inited = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Haml is required & includes helpers
|
||||
require "middleman/haml"
|
||||
require "middleman/sass"
|
|
@ -1,6 +1,5 @@
|
|||
require 'templater'
|
||||
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
|
||||
module Middleman
|
||||
|
@ -37,9 +36,12 @@ module Middleman
|
|||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
def after_run
|
||||
end
|
||||
end
|
||||
|
||||
module Generators
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
class Middleman::Base
|
||||
class << Middleman::Base
|
||||
alias_method :pre_cache_buster_asset_url, :asset_url
|
||||
helpers do
|
||||
def 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))
|
||||
http_path
|
||||
else
|
||||
real_path = File.join(self.class.environment == "build" ? options.build_dir : options.public, prefix, path)
|
||||
http_path << "?" + File.mtime(real_path).strftime("%s") if File.readable?(real_path)
|
||||
http_path
|
||||
end
|
||||
def 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))
|
||||
http_path
|
||||
else
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
|
@ -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
|
|
@ -12,20 +12,21 @@ module Middleman
|
|||
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
|
||||
class Builder
|
||||
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
|
||||
|
||||
class Base
|
||||
include Middleman::Minified::StaticJavascript
|
||||
end
|
||||
end
|
||||
end if Middleman::Base.environment == "build"
|
||||
end
|
||||
|
||||
Middleman::Base.supported_formats << "js"
|
|
@ -6,25 +6,25 @@ class Middleman::Base
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
helpers do
|
||||
alias_method :pre_relative_asset_url, :asset_url
|
||||
def asset_url(path, prefix="")
|
||||
path = pre_relative_asset_url(path, prefix)
|
||||
if path.include?("://")
|
||||
path
|
||||
end
|
||||
|
||||
class << Middleman::Base
|
||||
alias_method :pre_relative_asset_url, :asset_url
|
||||
def asset_url(path, prefix="")
|
||||
path = pre_relative_asset_url(path, prefix)
|
||||
if path.include?("://")
|
||||
path
|
||||
else
|
||||
path = path[1,path.length-1] if path[0,1] == '/'
|
||||
request_path = request.path_info.dup
|
||||
request_path << options.index_file if path.match(%r{/$})
|
||||
request_path.gsub!(%r{^/}, '')
|
||||
parts = request_path.split('/')
|
||||
|
||||
if parts.length > 1
|
||||
"../" * (parts.length - 1) + path
|
||||
else
|
||||
path = path[1,path.length-1] if path[0,1] == '/'
|
||||
request_path = request.path_info.dup
|
||||
request_path << options.index_file if path.match(%r{/$})
|
||||
request_path.gsub!(%r{^/}, '')
|
||||
parts = request_path.split('/')
|
||||
|
||||
if parts.length > 1
|
||||
"../" * (parts.length - 1) + path
|
||||
else
|
||||
path
|
||||
end
|
||||
path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,25 +6,30 @@ rescue LoadError
|
|||
end
|
||||
|
||||
module Middleman
|
||||
module Sprockets
|
||||
def self.included(base)
|
||||
base.supported_formats << "js"
|
||||
end
|
||||
|
||||
def render_path(path)
|
||||
source = File.join(options.public, path)
|
||||
if File.extname(path) == '.js' && File.exists?(source)
|
||||
secretary = ::Sprockets::Secretary.new( :asset_root => options.public,
|
||||
:source_files => [source] )
|
||||
# may need to rejigger since sprockets will only read views/ now
|
||||
secretary.concatenation.to_s
|
||||
else
|
||||
super
|
||||
module Rack
|
||||
class Sprockets
|
||||
def initialize(app, options={})
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
path = env["PATH_INFO"]
|
||||
source = File.join(Middleman::Base.views, path)
|
||||
|
||||
if path.match(/\.js$/) && File.exists?(source)
|
||||
secretary = ::Sprockets::Secretary.new( :root => Middleman::Base.root,
|
||||
: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
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Middleman::Base
|
||||
include Middleman::Sprockets
|
||||
end
|
||||
Middleman::Base.use Middleman::Rack::Sprockets
|
||||
Middleman::Base.supported_formats << "js"
|
|
@ -1,4 +1,4 @@
|
|||
require 'haml'
|
||||
require "haml"
|
||||
|
||||
module Middleman
|
||||
module Haml
|
||||
|
@ -62,71 +62,8 @@ module Middleman
|
|||
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
|
||||
|
||||
class Middleman::Base
|
||||
include Middleman::Haml::Renderer
|
||||
include Middleman::Sass
|
||||
end
|
|
@ -1,4 +1,11 @@
|
|||
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
|
||||
def page_classes(*additional)
|
||||
path = request.path_info
|
||||
|
@ -14,16 +21,15 @@ module Middleman
|
|||
classes.join(' ')
|
||||
end
|
||||
|
||||
def asset_url(*args)
|
||||
self.class.asset_url(*args)
|
||||
end
|
||||
|
||||
def link_to(title, url="#", params={})
|
||||
params.merge!(:href => url)
|
||||
params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ')
|
||||
%Q{<a #{params}>#{title}</a>}
|
||||
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={})
|
||||
params[:alt] ||= ""
|
||||
|
|
20
lib/middleman/rack/static.rb
Normal file
20
lib/middleman/rack/static.rb
Normal 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
70
lib/middleman/sass.rb
Normal 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
|
|
@ -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
|
||||
class Templater::Actions::File
|
||||
def identical?
|
||||
|
|
|
@ -4,25 +4,15 @@ base = ::Middleman::Base
|
|||
base.set :root, File.join(File.dirname(__FILE__), "fixtures", "sample")
|
||||
|
||||
describe "Cache Buster Feature" do
|
||||
before do
|
||||
it "should not append query string if off" do
|
||||
base.disable :cache_buster
|
||||
base.init!(true)
|
||||
@app = base.new
|
||||
base.init!(true, true)
|
||||
base.asset_url("stylesheets/static.css").should_not include("?")
|
||||
end
|
||||
|
||||
it "should not append query string if off" do
|
||||
@app.asset_url("stylesheets/static.css").should_not include("?")
|
||||
end
|
||||
end
|
||||
|
||||
describe "Cache Buster Feature" do
|
||||
before do
|
||||
base.enable :cache_buster
|
||||
base.init!(true)
|
||||
@app = base.new
|
||||
end
|
||||
|
||||
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
|
|
@ -1 +0,0 @@
|
|||
//= require "to-be-included"
|
1
spec/fixtures/sample/views/javascripts/empty-with-include.js
vendored
Normal file
1
spec/fixtures/sample/views/javascripts/empty-with-include.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
//= require <to-be-included>
|
Loading…
Reference in a new issue