Rewritten core which makes better use of Tilt. Support for SCSS, Coffee and Less.
This commit is contained in:
parent
bccc6d2d74
commit
5523a10d9b
40 changed files with 642 additions and 668 deletions
33
Rakefile
33
Rakefile
|
@ -13,24 +13,21 @@ begin
|
|||
gem.authors = ["Thomas Reynolds"]
|
||||
gem.rubyforge_project = "middleman"
|
||||
gem.executables = %w(mm-init mm-build mm-server)
|
||||
gem.add_dependency("rack")
|
||||
gem.add_dependency("thin")
|
||||
|
||||
gem.add_dependency("shotgun", ">=0.8")
|
||||
gem.add_dependency("templater")
|
||||
gem.add_dependency("sprockets")
|
||||
gem.add_dependency("sinatra", ">=1.0")
|
||||
gem.add_dependency("sinatra-content-for")
|
||||
gem.add_dependency("less")
|
||||
gem.add_dependency("builder")
|
||||
gem.add_dependency("rack-test")
|
||||
gem.add_dependency("yui-compressor")
|
||||
gem.add_dependency("haml", ">=3.0")
|
||||
gem.add_dependency("compass", ">=0.10")
|
||||
gem.add_dependency("fancy-buttons")
|
||||
gem.add_dependency("json_pure")
|
||||
gem.add_dependency("smusher")
|
||||
gem.add_dependency("compass-slickmap")
|
||||
gem.add_dependency("rack", "~>1.0")
|
||||
gem.add_dependency("thin", "~>1.2.0")
|
||||
gem.add_dependency("shotgun", "~>0.8.0")
|
||||
gem.add_dependency("templater", "~>1.0.0")
|
||||
gem.add_dependency("sprockets", "~>1.0.0")
|
||||
gem.add_dependency("sinatra", "~>1.0")
|
||||
gem.add_dependency("sinatra-content-for", "~>0.2.0")
|
||||
gem.add_dependency("rack-test", "~>0.5.0")
|
||||
gem.add_dependency("yui-compressor", "~>0.9.0")
|
||||
gem.add_dependency("haml", "~>3.0")
|
||||
gem.add_dependency("compass", "~>0.10.0")
|
||||
gem.add_dependency("json_pure", "~>1.4.0")
|
||||
gem.add_dependency("smusher", "~>0.4.5")
|
||||
gem.add_dependency("compass-slickmap", "~>0.3.0")
|
||||
gem.add_dependency("livereload", "~>1.4.0")
|
||||
|
||||
gem.add_development_dependency("rspec")
|
||||
gem.add_development_dependency("cucumber")
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
Feature: Automatically detect and insert image dimensions into tags
|
||||
In order to speed up development and appease YSlow
|
||||
|
||||
Scenario: Rendering an image with the feature enabled
|
||||
Given "automatic_image_sizes" feature is "enabled"
|
||||
When I go to "/auto-image-sizes.html"
|
||||
Then I should see "width="
|
||||
And I should see "height="
|
||||
|
||||
Scenario: Rendering an image with the feature disabled
|
||||
Given "automatic_image_sizes" feature is "disabled"
|
||||
When I go to "/auto-image-sizes.html"
|
||||
Then I should not see "width="
|
||||
And I should not see "height="
|
||||
And I should not see "height="
|
||||
|
||||
Scenario: Rendering an image with the feature enabled
|
||||
Given "automatic_image_sizes" feature is "enabled"
|
||||
When I go to "/auto-image-sizes.html"
|
||||
Then I should see "width="
|
||||
And I should see "height="
|
|
@ -1,15 +1,5 @@
|
|||
Feature: Generate mtime-based query string for busting browser caches
|
||||
In order to display the most recent content for IE & CDNs and appease YSlow
|
||||
|
||||
Scenario: Rendering css with the feature enabled
|
||||
Given "cache_buster" feature is "enabled"
|
||||
When I go to "/stylesheets/relative_assets.css"
|
||||
Then I should see "?"
|
||||
|
||||
Scenario: Rendering html with the feature enabled
|
||||
Given "cache_buster" feature is "enabled"
|
||||
When I go to "/cache-buster.html"
|
||||
Then I should not see "?"
|
||||
|
||||
Scenario: Rendering css with the feature disabled
|
||||
Given "cache_buster" feature is "disabled"
|
||||
|
@ -19,4 +9,14 @@ Feature: Generate mtime-based query string for busting browser caches
|
|||
Scenario: Rendering html with the feature disabled
|
||||
Given "cache_buster" feature is "disabled"
|
||||
When I go to "/cache-buster.html"
|
||||
Then I should not see "?"
|
||||
|
||||
Scenario: Rendering css with the feature enabled
|
||||
Given "cache_buster" feature is "enabled"
|
||||
When I go to "/stylesheets/relative_assets.css"
|
||||
Then I should see "?"
|
||||
|
||||
Scenario: Rendering html with the feature enabled
|
||||
Given "cache_buster" feature is "enabled"
|
||||
When I go to "/cache-buster.html"
|
||||
Then I should not see "?"
|
|
@ -1,22 +1,22 @@
|
|||
Feature: Minify CSS
|
||||
In order reduce bytes sent to client and appease YSlow
|
||||
|
||||
Scenario: Rendering inline css with the feature enabled
|
||||
Given "minify_css" feature is "enabled"
|
||||
When I go to "/inline-css.html"
|
||||
Then I should see "1" lines
|
||||
|
||||
Scenario: Rendering inline css with the feature disabled
|
||||
Given "minify_css" feature is "disabled"
|
||||
When I go to "/inline-css.html"
|
||||
Then I should see "4" lines
|
||||
|
||||
Scenario: Rendering external css with the feature enabled
|
||||
Given "minify_css" feature is "enabled"
|
||||
When I go to "/stylesheets/site.css"
|
||||
Then I should see "1" lines
|
||||
|
||||
Scenario: Rendering external css with the feature disabled
|
||||
Given "minify_css" feature is "disabled"
|
||||
When I go to "/stylesheets/site.css"
|
||||
Then I should see "51" lines
|
||||
Then I should see "51" lines
|
||||
|
||||
Scenario: Rendering inline css with the feature enabled
|
||||
Given "minify_css" feature is "enabled"
|
||||
When I go to "/inline-css.html"
|
||||
Then I should see "1" lines
|
||||
|
||||
Scenario: Rendering external css with the feature enabled
|
||||
Given "minify_css" feature is "enabled"
|
||||
When I go to "/stylesheets/site.css"
|
||||
Then I should see "1" lines
|
|
@ -1,12 +1,12 @@
|
|||
Feature: Minify Javascript
|
||||
In order reduce bytes sent to client and appease YSlow
|
||||
|
||||
Scenario: Rendering inline js with the feature disabled
|
||||
Given "minify_javascript" feature is "disabled"
|
||||
When I go to "/inline-js.html"
|
||||
Then I should see "10" lines
|
||||
|
||||
Scenario: Rendering inline js with the feature enabled
|
||||
Given "minify_javascript" feature is "enabled"
|
||||
When I go to "/inline-js.html"
|
||||
Then I should see "1" lines
|
||||
|
||||
Scenario: Rendering inline js with the feature disabled
|
||||
Given "minify_javascript" feature is "disabled"
|
||||
When I go to "/inline-js.html"
|
||||
Then I should see "10" lines
|
||||
Then I should see "1" lines
|
|
@ -1,4 +1,5 @@
|
|||
Given /^I am using an asset host$/ do
|
||||
Middleman::Base.enable :asset_host
|
||||
Middleman::Base.set :asset_host do |asset|
|
||||
"http://assets%d.example.com" % (asset.hash % 4)
|
||||
end
|
||||
|
|
|
@ -23,6 +23,6 @@ Then /^I should not see "([^\"]*)"$/ do |expected|
|
|||
end
|
||||
|
||||
Then /^I should see "([^\"]*)" lines$/ do |lines|
|
||||
puts @browser.last_response.body
|
||||
$stderr.puts @browser.last_response.body
|
||||
@browser.last_response.body.chomp.split($/).length.should == lines.to_i
|
||||
end
|
|
@ -4,22 +4,5 @@ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
|||
require 'rubygems'
|
||||
|
||||
module Middleman
|
||||
|
||||
module Rack
|
||||
autoload :Sprockets, "middleman/rack/sprockets"
|
||||
autoload :MinifyJavascript, "middleman/rack/minify_javascript"
|
||||
autoload :MinifyCSS, "middleman/rack/minify_css"
|
||||
end
|
||||
|
||||
module Renderers
|
||||
autoload :ERb, "middleman/renderers/erb"
|
||||
autoload :Builder, "middleman/renderers/builder"
|
||||
autoload :Less, "middleman/renderers/less"
|
||||
end
|
||||
|
||||
autoload :Base, "middleman/base"
|
||||
autoload :Haml, "middleman/renderers/haml"
|
||||
autoload :Sass, "middleman/renderers/sass"
|
||||
autoload :Helpers, "middleman/helpers"
|
||||
|
||||
autoload :Base, "middleman/base"
|
||||
end
|
||||
|
|
33
lib/middleman/assets.rb
Normal file
33
lib/middleman/assets.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
module Middleman
|
||||
module Assets
|
||||
@@asset_handler_map = []
|
||||
@@asset_handler_stack = []
|
||||
|
||||
def self.register(handler_name, &block)
|
||||
if block_given?
|
||||
@@asset_handler_stack << block
|
||||
@@asset_handler_map << handler_name
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_url(path, prefix="", request=nil)
|
||||
@@asset_handler_stack.last.call(path, prefix, request)
|
||||
end
|
||||
|
||||
def self.before(position, *args)
|
||||
current_index = @@asset_handler_map.index(position)
|
||||
return nil unless current_index
|
||||
|
||||
previous = current_index - 1
|
||||
if (previous >= 0) && (previous < @@asset_handler_map.length)
|
||||
@@asset_handler_stack[previous].call(*args)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Assets.register :base do |path, prefix, request|
|
||||
path.include?("://") ? path : File.join(Middleman::Base.http_prefix || "/", prefix, path)
|
||||
end
|
|
@ -7,7 +7,6 @@ class Sinatra::Request
|
|||
end
|
||||
|
||||
module Middleman
|
||||
module Rack; end
|
||||
class Base < Sinatra::Base
|
||||
set :app_file, __FILE__
|
||||
set :root, ENV["MM_DIR"] || Dir.pwd
|
||||
|
@ -42,10 +41,9 @@ module Middleman
|
|||
def self.set(option, value=self, &block)
|
||||
if block_given?
|
||||
value = Proc.new { block }
|
||||
super(option, value, &nil)
|
||||
else
|
||||
super
|
||||
end
|
||||
|
||||
super(option, value, &nil)
|
||||
end
|
||||
|
||||
@@afters = []
|
||||
|
@ -58,22 +56,6 @@ module Middleman
|
|||
ext = ".#{ext}" unless ext.to_s[0] == ?.
|
||||
::Rack::Mime::MIME_TYPES[ext.to_s] = type
|
||||
end
|
||||
|
||||
# Convenience function to discover if a template exists for the requested renderer (haml, sass, etc)
|
||||
def template_exists?(path, renderer=nil)
|
||||
template_path = path.dup
|
||||
template_path << ".#{renderer}" if renderer
|
||||
File.readable? File.join(settings.views, template_path)
|
||||
end
|
||||
|
||||
# Base case renderer (do nothing), Should be over-ridden
|
||||
module StaticRender
|
||||
def render_path(path, layout)
|
||||
return false if !template_exists?(path, :erb)
|
||||
erb(path.to_sym, :layout => layout)
|
||||
end
|
||||
end
|
||||
include StaticRender
|
||||
|
||||
@@layout = nil
|
||||
def self.page(url, options={}, &block)
|
||||
|
@ -106,7 +88,7 @@ module Middleman
|
|||
not_found do
|
||||
process_request
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def process_request(layout = :layout)
|
||||
# Normalize the path and add index if we're looking at a directory
|
||||
|
@ -114,44 +96,33 @@ module Middleman
|
|||
path << settings.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, layout)
|
||||
template_path = locate_template_file(path)
|
||||
if template_path
|
||||
content_type mime_type(File.extname(path)), :charset => 'utf-8'
|
||||
status 200
|
||||
content
|
||||
else
|
||||
status 404
|
||||
|
||||
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
|
||||
|
||||
def locate_template_file(path)
|
||||
template_path = File.join(settings.views, "#{path}.*")
|
||||
Dir.glob(template_path).first
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "middleman/renderers/erb"
|
||||
require "middleman/renderers/haml"
|
||||
require "middleman/renderers/sass"
|
||||
require "middleman/renderers/less"
|
||||
require "middleman/renderers/builder"
|
||||
require "middleman/assets"
|
||||
require "middleman/renderers"
|
||||
require "middleman/features"
|
||||
|
||||
# The Rack App
|
||||
class Middleman::Base
|
||||
helpers Middleman::Helpers
|
||||
|
||||
# Features disabled by default
|
||||
enable :asset_host
|
||||
disable :slickmap
|
||||
disable :cache_buster
|
||||
disable :minify_css
|
||||
disable :minify_javascript
|
||||
disable :relative_assets
|
||||
disable :smush_pngs
|
||||
disable :automatic_image_sizes
|
||||
disable :relative_assets
|
||||
disable :cache_buster
|
||||
disable :ugly_haml
|
||||
|
||||
# Default build features
|
||||
configure :build do
|
||||
end
|
||||
|
||||
def self.new(*args, &block)
|
||||
# Check for and evaluate local configuration
|
||||
local_config = File.join(self.root, "init.rb")
|
||||
|
@ -164,22 +135,11 @@ class Middleman::Base
|
|||
# loop over enabled feature
|
||||
features.flatten.each do |feature_name|
|
||||
next unless send(:"#{feature_name}?")
|
||||
|
||||
feature_path = "features/#{feature_name}"
|
||||
if File.exists? File.join(File.dirname(__FILE__), "#{feature_path}.rb")
|
||||
puts "== Enabling: #{feature_name.to_s.capitalize}" if logging?
|
||||
require "middleman/#{feature_path}"
|
||||
end
|
||||
$stderr.puts "== Enabling: #{feature_name.to_s.capitalize}" if logging?
|
||||
Middleman::Features.run(feature_name, self)
|
||||
end
|
||||
|
||||
use ::Rack::ConditionalGet if environment == :development
|
||||
use Middleman::Rack::MinifyJavascript if minify_javascript?
|
||||
use Middleman::Rack::MinifyCSS if minify_css?
|
||||
|
||||
# Built-in javascript combination
|
||||
use Middleman::Rack::Sprockets, :root => Middleman::Base.root,
|
||||
:load_path => [ File.join("public", Middleman::Base.js_dir),
|
||||
File.join("views", Middleman::Base.js_dir) ]
|
||||
use ::Rack::ConditionalGet if environment == :development
|
||||
|
||||
@@afters.each { |block| class_eval(&block) }
|
||||
|
||||
|
|
40
lib/middleman/features.rb
Normal file
40
lib/middleman/features.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
module Middleman
|
||||
module Features
|
||||
# Top-level method to register a new feature
|
||||
@@features = {}
|
||||
def self.register(feature_name, feature_class=nil, options={})
|
||||
@@features[feature_name] = feature_class
|
||||
|
||||
# Default to disabled, unless the class asks to auto-enable
|
||||
activate_method = (options.has_key?(:auto_enable) && options[:auto_enable]) ? :enable : :disable
|
||||
Middleman::Base.send(activate_method, feature_name)
|
||||
end
|
||||
|
||||
def self.run(feature_name, scope)
|
||||
feature_class = @@features[feature_name]
|
||||
feature_class.new(scope) unless feature_class.nil?
|
||||
end
|
||||
|
||||
def self.all
|
||||
@@features
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
%w(asset_host
|
||||
automatic_image_sizes
|
||||
cache_buster
|
||||
default_helpers
|
||||
livereload
|
||||
minify_css
|
||||
minify_javascript
|
||||
relative_assets
|
||||
slickmap
|
||||
smush_pngs
|
||||
sprockets
|
||||
ugly_haml).each do |feature|
|
||||
|
||||
require File.join("middleman/features", feature)
|
||||
|
||||
end
|
|
@ -1,24 +1,21 @@
|
|||
class Middleman::Base
|
||||
after_feature_init do
|
||||
::Compass.configuration do |config|
|
||||
config.asset_host(&self.asset_host)
|
||||
class Middleman::Features::AssetHost
|
||||
def initialize(app)
|
||||
Middleman::Base.after_feature_init do
|
||||
if Middleman::Base.asset_host.is_a?(Proc)
|
||||
::Compass.configuration.asset_host(&Middleman::Base.asset_host)
|
||||
end
|
||||
end
|
||||
end if self.enabled?(:asset_host) && self.asset_host && self.asset_host.is_a?(Proc)
|
||||
end
|
||||
|
||||
Middleman::Assets.register :asset_host do |path, prefix, request|
|
||||
original_output = Middleman::Assets.before(:asset_host, path, prefix, request)
|
||||
|
||||
class << Middleman::Base
|
||||
alias_method :pre_asset_host_asset_url, :asset_url
|
||||
def asset_url(path, prefix="", request=nil)
|
||||
original_output = pre_asset_host_asset_url(path, prefix, request)
|
||||
|
||||
valid_extensions = %w(.png .gif .jpg .jpeg .js .css)
|
||||
|
||||
if !self.enabled?(:asset_host) || path.include?("://") || !valid_extensions.include?(File.extname(path)) || !self.asset_host || !self.asset_host.is_a?(Proc) || !self.asset_host.respond_to?(:call)
|
||||
return original_output
|
||||
valid_extensions = %w(.png .gif .jpg .jpeg .js .css)
|
||||
|
||||
asset_prefix = Middleman::Base.asset_host.call(original_output)
|
||||
|
||||
File.join(asset_prefix, original_output)
|
||||
end
|
||||
|
||||
asset_prefix = self.asset_host.call(original_output)
|
||||
|
||||
return File.join(asset_prefix, original_output)
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :asset_host, Middleman::Features::AssetHost
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
require "middleman/fastimage"
|
||||
class Middleman::Features::AutomaticImageSizes
|
||||
def initialize(app)
|
||||
require "middleman/features/automatic_image_sizes/fastimage"
|
||||
|
||||
class Middleman::Base
|
||||
alias_method :pre_automatic_image_tag, :image_tag
|
||||
helpers do
|
||||
def image_tag(path, params={})
|
||||
if !self.enabled?(:automatic_image_sizes)
|
||||
return pre_automatic_image_tag(path, params)
|
||||
end
|
||||
Middleman::Base.send :alias_method, :pre_automatic_image_tag, :image_tag
|
||||
Middleman::Base.helpers do
|
||||
def image_tag(path, params={})
|
||||
if (!params[:width] || !params[:height]) && !path.include?("://")
|
||||
params[:alt] ||= ""
|
||||
http_prefix = settings.http_images_path rescue settings.images_dir
|
||||
|
||||
if (!params[:width] || !params[:height]) && !path.include?("://")
|
||||
params[:alt] ||= ""
|
||||
http_prefix = settings.http_images_path rescue settings.images_dir
|
||||
|
||||
begin
|
||||
real_path = File.join(settings.public, settings.images_dir, path)
|
||||
if File.exists? real_path
|
||||
dimensions = Middleman::FastImage.size(real_path, :raise_on_failure => true)
|
||||
params[:width] ||= dimensions[0]
|
||||
params[:height] ||= dimensions[1]
|
||||
begin
|
||||
real_path = File.join(settings.public, settings.images_dir, path)
|
||||
if File.exists? real_path
|
||||
dimensions = Middleman::FastImage.size(real_path, :raise_on_failure => true)
|
||||
params[:width] ||= dimensions[0]
|
||||
params[:height] ||= dimensions[1]
|
||||
end
|
||||
rescue
|
||||
end
|
||||
rescue
|
||||
end
|
||||
|
||||
capture_haml { haml_tag(:img, params.merge(:src => asset_url(path, http_prefix))) }
|
||||
else
|
||||
pre_automatic_image_tag(path, params)
|
||||
capture_haml { haml_tag(:img, params.merge(:src => asset_url(path, http_prefix))) }
|
||||
else
|
||||
pre_automatic_image_tag(path, params)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :automatic_image_sizes, Middleman::Features::AutomaticImageSizes
|
|
@ -1,50 +1,43 @@
|
|||
class Middleman::Base
|
||||
after_feature_init do
|
||||
::Compass.configuration do |config|
|
||||
if self.enabled?(:cache_buster)
|
||||
class Middleman::Features::CacheBuster
|
||||
def initialize(app)
|
||||
Middleman::Assets.register :cache_buster do |path, prefix, request|
|
||||
http_path = Middleman::Assets.before(:cache_buster, path, prefix, request)
|
||||
|
||||
if http_path.include?("://") || !%w(.css .png .jpg .js .gif).include?(File.extname(http_path))
|
||||
http_path
|
||||
else
|
||||
begin
|
||||
prefix = Middleman::Base.images_dir if prefix == Middleman::Base.http_images_path
|
||||
rescue
|
||||
end
|
||||
|
||||
real_path_static = File.join(Middleman::Base.public, prefix, path)
|
||||
|
||||
if File.readable?(real_path_static)
|
||||
http_path << "?" + File.mtime(real_path_static).strftime("%s")
|
||||
elsif Middleman::Base.environment == "build"
|
||||
real_path_dynamic = File.join(Middleman::Base.root, Middleman::Base.build_dir, prefix, path)
|
||||
http_path << "?" + File.mtime(real_path_dynamic).strftime("%s") if File.readable?(real_path_dynamic)
|
||||
end
|
||||
|
||||
http_path
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Base.after_feature_init do
|
||||
::Compass.configuration do |config|
|
||||
config.asset_cache_buster do |path, real_path|
|
||||
real_path = real_path.path if real_path.is_a? File
|
||||
real_path = real_path.gsub(File.join(self.root, self.build_dir), self.public)
|
||||
real_path = real_path.gsub(File.join(Middleman::Base.root, Middleman::Base.build_dir), Middleman::Base.public)
|
||||
if File.readable?(real_path)
|
||||
File.mtime(real_path).strftime("%s")
|
||||
else
|
||||
$stderr.puts "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
|
||||
end
|
||||
end
|
||||
else
|
||||
config.asset_cache_buster { false }
|
||||
end
|
||||
end
|
||||
|
||||
::Compass.configure_sass_plugin!
|
||||
end
|
||||
end
|
||||
|
||||
class << Middleman::Base
|
||||
alias_method :pre_cache_buster_asset_url, :asset_url
|
||||
def asset_url(path, prefix="", request=nil)
|
||||
http_path = pre_cache_buster_asset_url(path, prefix, request)
|
||||
|
||||
return http_path unless self.enabled?(:cache_buster)
|
||||
|
||||
if http_path.include?("://") || !%w(.css .png .jpg .js .gif).include?(File.extname(http_path))
|
||||
http_path
|
||||
else
|
||||
begin
|
||||
prefix = self.images_dir if prefix == self.http_images_path
|
||||
rescue
|
||||
end
|
||||
|
||||
real_path_static = File.join(self.public, prefix, path)
|
||||
|
||||
if File.readable?(real_path_static)
|
||||
http_path << "?" + File.mtime(real_path_static).strftime("%s")
|
||||
elsif Middleman::Base.environment == "build"
|
||||
real_path_dynamic = File.join(self.root, self.build_dir, prefix, path)
|
||||
http_path << "?" + File.mtime(real_path_dynamic).strftime("%s") if File.readable?(real_path_dynamic)
|
||||
end
|
||||
|
||||
http_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :cache_buster, Middleman::Features::CacheBuster
|
19
lib/middleman/helpers.rb → lib/middleman/features/default_helpers.rb
Executable file → Normal file
19
lib/middleman/helpers.rb → lib/middleman/features/default_helpers.rb
Executable file → Normal file
|
@ -1,15 +1,9 @@
|
|||
module Middleman
|
||||
class Base
|
||||
def self.asset_url(path, prefix="", request=nil)
|
||||
path.include?("://") ? path : File.join(self.http_prefix || "/", prefix, path)
|
||||
end
|
||||
class Middleman::Features::DefaultHelpers
|
||||
def initialize(app)
|
||||
Middleman::Base.helpers Helpers
|
||||
end
|
||||
|
||||
module Helpers
|
||||
def haml_partial(name, options = {})
|
||||
haml name.to_sym, options.merge(:layout => false)
|
||||
end
|
||||
|
||||
def auto_stylesheet_link_tag(separator="/")
|
||||
path = request.path_info.dup
|
||||
path << self.class.index_file if path.match(%r{/$})
|
||||
|
@ -19,8 +13,9 @@ module Middleman
|
|||
|
||||
css_file = File.join(self.class.public, self.class.css_dir, "#{path}.css")
|
||||
sass_file = File.join(self.class.views, self.class.css_dir, "#{path}.css.sass")
|
||||
scss_file = File.join(self.class.views, self.class.css_dir, "#{path}.css.scss")
|
||||
|
||||
if File.exists?(css_file) || File.exists?(sass_file)
|
||||
if File.exists?(css_file) || File.exists?(sass_file) || File.exists?(scss_file)
|
||||
stylesheet_link_tag "#{path}.css"
|
||||
end
|
||||
end
|
||||
|
@ -38,7 +33,7 @@ module Middleman
|
|||
end
|
||||
|
||||
def asset_url(path, prefix="")
|
||||
self.class.asset_url(path, prefix, request)
|
||||
Middleman::Assets.get_url(path, prefix, request)
|
||||
end
|
||||
|
||||
def link_to(title, url="#", params={})
|
||||
|
@ -69,3 +64,5 @@ module Middleman
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :default_helpers, Middleman::Features::DefaultHelpers, { :auto_enable => true }
|
19
lib/middleman/features/livereload.rb
Normal file
19
lib/middleman/features/livereload.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
class Middleman::Features::LiveReload
|
||||
def initialize(app)
|
||||
return unless Middleman::Base.environment == :development
|
||||
|
||||
begin
|
||||
require 'livereload'
|
||||
rescue LoadError
|
||||
puts "Livereload not available. Install it with: gem install livereload"
|
||||
end
|
||||
|
||||
new_config = ::LiveReload::Config.new do |config|
|
||||
config.exts = %w(haml sass scss coffee less builder)
|
||||
end
|
||||
|
||||
::LiveReload.run [Middleman::Base.public, Middleman::Base.views], new_config
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :livereload, Middleman::Features::LiveReload
|
|
@ -0,0 +1,9 @@
|
|||
class Middleman::Features::MinifyCSS
|
||||
def initialize(app)
|
||||
Middleman::Base.after_feature_init do
|
||||
::Compass.configuration.output_style = :compressed
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :minify_css, Middleman::Features::MinifyCSS
|
|
@ -1,22 +1,20 @@
|
|||
module Middleman
|
||||
module Minified
|
||||
class Middleman::Features::MinifyJavascript
|
||||
def initialize(app)
|
||||
Haml::Javascript.send :include, ::Haml::Filters::Base
|
||||
|
||||
require "middleman/features/minify_javascript/rack"
|
||||
app.use Middleman::Rack::MinifyJavascript
|
||||
end
|
||||
|
||||
module Haml
|
||||
module Javascript
|
||||
include ::Haml::Filters::Base
|
||||
def render_with_options(text, options)
|
||||
if Middleman::Base.respond_to?(:minify_javascript?) && Middleman::Base.minify_javascript?
|
||||
compressor = ::YUI::JavaScriptCompressor.new(:munge => true)
|
||||
data = compressor.compress(text)
|
||||
%Q{<script type=#{options[:attr_wrapper]}text/javascript#{options[:attr_wrapper]}>#{data.chomp}</script>}
|
||||
else
|
||||
<<END
|
||||
<script type=#{options[:attr_wrapper]}text/javascript#{options[:attr_wrapper]}>
|
||||
//<![CDATA[
|
||||
#{text.rstrip.gsub("\n", "\n ")}
|
||||
//]]>
|
||||
</script>
|
||||
END
|
||||
end
|
||||
compressor = ::YUI::JavaScriptCompressor.new(:munge => true)
|
||||
data = compressor.compress(text)
|
||||
%Q{<script type=#{options[:attr_wrapper]}text/javascript#{options[:attr_wrapper]}>#{data.chomp}</script>}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :minify_javascript, Middleman::Features::MinifyJavascript
|
31
lib/middleman/features/minify_javascript/rack.rb
Normal file
31
lib/middleman/features/minify_javascript/rack.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
begin
|
||||
require "yui/compressor"
|
||||
rescue LoadError
|
||||
puts "YUI-Compressor not available. Install it with: gem install yui-compressor"
|
||||
end
|
||||
|
||||
module Middleman
|
||||
module Rack
|
||||
|
||||
class MinifyJavascript
|
||||
def initialize(app, options={})
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
status, headers, response = @app.call(env)
|
||||
|
||||
if env["PATH_INFO"].match(/\.js$/)
|
||||
compressor = ::YUI::JavaScriptCompressor.new(:munge => true)
|
||||
|
||||
uncompressed_source = response.is_a?(::Rack::File) ? File.read(response.path) : response
|
||||
response = compressor.compress(uncompressed_source)
|
||||
headers["Content-Length"] = ::Rack::Utils.bytesize(response).to_s
|
||||
end
|
||||
|
||||
[status, headers, response]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -1,46 +1,35 @@
|
|||
class Middleman::Base
|
||||
after_feature_init do
|
||||
::Compass.configuration do |config|
|
||||
config.relative_assets = Proc.new do
|
||||
Middleman::Base.enabled?(:relative_assets)
|
||||
class Middleman::Features::RelativeAssets
|
||||
def initialize(app)
|
||||
::Compass.configuration.relative_assets = true
|
||||
|
||||
Middleman::Assets.register :relative_assets do |path, prefix, request|
|
||||
begin
|
||||
prefix = Middleman::Base.images_dir if prefix == Middleman::Base.http_images_path
|
||||
rescue
|
||||
end
|
||||
|
||||
if path.include?("://")
|
||||
Middleman::Assets.before(:relative_assets, path, prefix, request)
|
||||
elsif path[0,1] == "/"
|
||||
path
|
||||
else
|
||||
path = File.join(prefix, path) if prefix.length > 0
|
||||
request_path = request.path_info.dup
|
||||
request_path << Middleman::Base.index_file if path.match(%r{/$})
|
||||
request_path.gsub!(%r{^/}, '')
|
||||
parts = request_path.split('/')
|
||||
|
||||
if parts.length > 1
|
||||
arry = []
|
||||
(parts.length - 1).times { arry << ".." }
|
||||
arry << path
|
||||
File.join(*arry)
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
::Compass.configure_sass_plugin!
|
||||
end
|
||||
end
|
||||
|
||||
class << Middleman::Base
|
||||
alias_method :pre_relative_asset_url, :asset_url
|
||||
def asset_url(path, prefix="", request=nil)
|
||||
if !self.enabled?(:relative_assets)
|
||||
return pre_relative_asset_url(path, prefix, request)
|
||||
end
|
||||
|
||||
begin
|
||||
prefix = self.images_dir if prefix == self.http_images_path
|
||||
rescue
|
||||
end
|
||||
|
||||
if path.include?("://")
|
||||
pre_relative_asset_url(path, prefix, request)
|
||||
elsif path[0,1] == "/"
|
||||
path
|
||||
else
|
||||
path = File.join(prefix, path) if prefix.length > 0
|
||||
request_path = request.path_info.dup
|
||||
request_path << self.index_file if path.match(%r{/$})
|
||||
request_path.gsub!(%r{^/}, '')
|
||||
parts = request_path.split('/')
|
||||
|
||||
if parts.length > 1
|
||||
arry = []
|
||||
(parts.length - 1).times { arry << ".." }
|
||||
arry << path
|
||||
File.join(*arry)
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Middleman::Features.register :relative_assets, Middleman::Features::RelativeAssets
|
||||
|
|
|
@ -1,92 +1,91 @@
|
|||
begin
|
||||
require 'slickmap'
|
||||
::Compass.configure_sass_plugin!
|
||||
rescue LoadError
|
||||
puts "Slickmap not available. Install it with: gem install compass-slickmap"
|
||||
end
|
||||
|
||||
if Middleman::Base.environment == "build"
|
||||
Middleman::Builder.template :slickmap, "sitemap.html", "sitemap.html"
|
||||
end
|
||||
|
||||
Entry = Struct.new(:dir, :children)
|
||||
|
||||
class Middleman::Base
|
||||
def build_sitemap(&block)
|
||||
@@utility = []
|
||||
[recurse_sitemap(Middleman::Base.views, &block), @@utility]
|
||||
end
|
||||
|
||||
def recurse_sitemap(path, &block)
|
||||
bad_ext = path.split('.html')[1]
|
||||
path = path.gsub(bad_ext, '') if bad_ext
|
||||
entry = Entry.new(path, [])
|
||||
class Middleman::Features::Slickmap
|
||||
def initialize(app)
|
||||
require 'slickmap'
|
||||
|
||||
#no "." or ".." dirs
|
||||
Dir[File.join(path, "*")].each do |e|
|
||||
next if !File.directory?(e) && !e.include?(".html")
|
||||
if File.directory?(e)
|
||||
entry.children << recurse_sitemap(e, &block)
|
||||
elsif block_given?
|
||||
how_to_handle = block.call(e)
|
||||
if how_to_handle == :valid
|
||||
entry.children << recurse_sitemap(e, &block)
|
||||
elsif how_to_handle == :utility
|
||||
bad_ext = e.split('.html')[1]
|
||||
e = e.gsub(bad_ext, '') if bad_ext
|
||||
@@utility << e.gsub(Middleman::Base.views + "/", '')
|
||||
end
|
||||
end
|
||||
if Middleman::Base.environment == "build"
|
||||
Middleman::Builder.template :slickmap, "sitemap.html", "sitemap.html"
|
||||
end
|
||||
|
||||
entry
|
||||
end
|
||||
|
||||
helpers do
|
||||
def sitemap_node(n, first=false)
|
||||
if n.children.length < 1
|
||||
if !first && File.extname(n.dir).length > 0
|
||||
haml_tag :li do
|
||||
path = n.dir.gsub(self.class.views, '')
|
||||
haml_concat link_to(File.basename(path), path)
|
||||
def build_sitemap(&block)
|
||||
@@utility = []
|
||||
[recurse_sitemap(Middleman::Base.views, &block), @@utility]
|
||||
end
|
||||
|
||||
def recurse_sitemap(path, &block)
|
||||
bad_ext = path.split('.html')[1]
|
||||
path = path.gsub(bad_ext, '') if bad_ext
|
||||
entry = Entry.new(path, [])
|
||||
|
||||
#no "." or ".." dirs
|
||||
Dir[File.join(path, "*")].each do |e|
|
||||
next if !File.directory?(e) && !e.include?(".html")
|
||||
if File.directory?(e)
|
||||
entry.children << recurse_sitemap(e, &block)
|
||||
elsif block_given?
|
||||
how_to_handle = block.call(e)
|
||||
if how_to_handle == :valid
|
||||
entry.children << recurse_sitemap(e, &block)
|
||||
elsif how_to_handle == :utility
|
||||
bad_ext = e.split('.html')[1]
|
||||
e = e.gsub(bad_ext, '') if bad_ext
|
||||
@@utility << e.gsub(Middleman::Base.views + "/", '')
|
||||
end
|
||||
end
|
||||
else
|
||||
haml_tag(:li, :id => first ? "home" : nil) do
|
||||
if first
|
||||
haml_concat link_to("Homepage", "/" + self.class.index_file)
|
||||
else
|
||||
# we are a dir
|
||||
index = n.children.find { |c| c.dir.include?(self.class.index_file) }
|
||||
haml_concat link_to(index.dir.gsub(self.class.views + "/", '').gsub("/" + File.basename(index.dir), '').capitalize, index.dir.gsub(self.class.views, ''))
|
||||
end
|
||||
|
||||
other_children = n.children.select { |c| !c.dir.include?(self.class.index_file) }
|
||||
if other_children.length > 0
|
||||
if first
|
||||
other_children.each { |i| sitemap_node(i) }
|
||||
else
|
||||
haml_tag :ul do
|
||||
other_children.each { |i| sitemap_node(i) }
|
||||
end
|
||||
end
|
||||
|
||||
entry
|
||||
end
|
||||
|
||||
Middleman::Base.helpers do
|
||||
def sitemap_node(n, first=false)
|
||||
if n.children.length < 1
|
||||
if !first && File.extname(n.dir).length > 0
|
||||
haml_tag :li do
|
||||
path = n.dir.gsub(self.class.views, '')
|
||||
haml_concat link_to(File.basename(path), path)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
haml_tag(:li, :id => first ? "home" : nil) do
|
||||
if first
|
||||
haml_concat link_to("Homepage", "/" + self.class.index_file)
|
||||
else
|
||||
# we are a dir
|
||||
index = n.children.find { |c| c.dir.include?(self.class.index_file) }
|
||||
haml_concat link_to(index.dir.gsub(self.class.views + "/", '').gsub("/" + File.basename(index.dir), '').capitalize, index.dir.gsub(self.class.views, ''))
|
||||
end
|
||||
|
||||
other_children = n.children.select { |c| !c.dir.include?(self.class.index_file) }
|
||||
if other_children.length > 0
|
||||
if first
|
||||
other_children.each { |i| sitemap_node(i) }
|
||||
else
|
||||
haml_tag :ul do
|
||||
other_children.each { |i| sitemap_node(i) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
get '/sitemap.html' do
|
||||
# Return :utility to put it util top menu. False to ignore
|
||||
@tree, @utility = build_sitemap do |file_name|
|
||||
:valid
|
||||
end
|
||||
haml :sitemap, :layout => false
|
||||
end
|
||||
|
||||
use_in_file_templates!
|
||||
Middleman::Base.get '/sitemap.html' do
|
||||
# Return :utility to put it util top menu. False to ignore
|
||||
@tree, @utility = build_sitemap do |file_name|
|
||||
:valid
|
||||
end
|
||||
haml :sitemap, :layout => false
|
||||
end
|
||||
|
||||
Middleman::Base.use_in_file_templates!
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :slickmap, Middleman::Features::Slickmap
|
||||
|
||||
__END__
|
||||
|
||||
@@ sitemap
|
||||
|
@ -97,7 +96,7 @@ __END__
|
|||
%title Sitemap
|
||||
%style{ :type => "text/css" }
|
||||
:sass
|
||||
@import slickmap.sass
|
||||
@import "slickmap"
|
||||
+slickmap
|
||||
:javascript
|
||||
window.onload = function() {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
require "middleman/builder"
|
||||
class Middleman::Features::SmushPngs
|
||||
def initialize(app)
|
||||
require "middleman/builder"
|
||||
|
||||
module Middleman
|
||||
class Builder
|
||||
alias_method :pre_smush_after_run, :after_run
|
||||
def after_run
|
||||
Middleman::Base.alias_method :pre_smush_after_run, :after_run
|
||||
Middleman::Base.define_method :after_run do
|
||||
pre_smush_after_run
|
||||
smush_dir = File.join(Middleman::Base.build_dir, Middleman::Base.images_dir)
|
||||
|
||||
|
@ -33,4 +33,6 @@ module Middleman
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :smush_pngs, Middleman::Features::SmushPngs
|
13
lib/middleman/features/sprockets.rb
Normal file
13
lib/middleman/features/sprockets.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
class Middleman::Features::Sprockets
|
||||
def initialize(app)
|
||||
require "middleman/features/sprockets/rack"
|
||||
app.use Middleman::Rack::Sprockets,
|
||||
:root => Middleman::Base.root,
|
||||
:load_path => [ File.join("public", Middleman::Base.js_dir),
|
||||
File.join("views", Middleman::Base.js_dir) ]
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :sprockets, Middleman::Features::Sprockets, { :auto_enable => true }
|
||||
|
||||
|
64
lib/middleman/features/sprockets/rack.rb
Normal file
64
lib/middleman/features/sprockets/rack.rb
Normal file
|
@ -0,0 +1,64 @@
|
|||
require 'sprockets'
|
||||
|
||||
module Middleman
|
||||
module Rack
|
||||
|
||||
class Sprockets
|
||||
def initialize(app, options={})
|
||||
@app = app
|
||||
@options = options
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if env["PATH_INFO"].match(/\.js$/)
|
||||
public_file_path = File.join(Middleman::Base.public, env["PATH_INFO"])
|
||||
view_file_path = File.join(Middleman::Base.views, env["PATH_INFO"])
|
||||
|
||||
source_file = ::Rack::File.new(Middleman::Base.public) if File.exists?(public_file_path)
|
||||
source_file = ::Rack::File.new(Middleman::Base.views) if File.exists?(view_file_path)
|
||||
|
||||
if source_file
|
||||
status, headers, response = source_file.call(env)
|
||||
secretary = ::Sprockets::Secretary.new(@options.merge( :source_files => [ response.path ] ))
|
||||
response = secretary.concatenation.to_s
|
||||
headers["Content-Length"] = ::Rack::Utils.bytesize(response).to_s
|
||||
return [status, headers, response]
|
||||
end
|
||||
end
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Sprockets ruby 1.9 duckpunch
|
||||
module Sprockets
|
||||
class SourceFile
|
||||
def source_lines
|
||||
@lines ||= begin
|
||||
lines = []
|
||||
|
||||
comments = []
|
||||
File.open(pathname.absolute_location, 'rb') do |file|
|
||||
file.each do |line|
|
||||
lines << line = SourceLine.new(self, line, file.lineno)
|
||||
|
||||
if line.begins_pdoc_comment? || comments.any?
|
||||
comments << line
|
||||
end
|
||||
|
||||
if line.ends_multiline_comment?
|
||||
if line.ends_pdoc_comment?
|
||||
comments.each { |l| l.comment! }
|
||||
end
|
||||
comments.clear
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
lines
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
7
lib/middleman/features/ugly_haml.rb
Normal file
7
lib/middleman/features/ugly_haml.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
class Middleman::Features::UglyHaml
|
||||
def initialize(app)
|
||||
Middleman::Base.set :haml, Middleman::Base.settings.haml.merge({ :ugly_haml => true })
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Features.register :ugly_haml, Middleman::Features::UglyHaml
|
|
@ -1,25 +0,0 @@
|
|||
begin
|
||||
require "yui/compressor"
|
||||
rescue LoadError
|
||||
puts "YUI-Compressor not available. Install it with: gem install yui-compressor"
|
||||
end
|
||||
|
||||
class Middleman::Rack::MinifyCSS
|
||||
def initialize(app, options={})
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
status, headers, response = @app.call(env)
|
||||
|
||||
if Middleman::Base.enabled?(:minify_css) && env["PATH_INFO"].match(/\.css$/)
|
||||
compressor = ::YUI::CssCompressor.new
|
||||
|
||||
uncompressed_source = response.is_a?(::Rack::File) ? File.read(response.path) : response
|
||||
response = compressor.compress(uncompressed_source)
|
||||
headers["Content-Length"] = ::Rack::Utils.bytesize(response).to_s
|
||||
end
|
||||
|
||||
[status, headers, response]
|
||||
end
|
||||
end
|
|
@ -1,25 +0,0 @@
|
|||
begin
|
||||
require "yui/compressor"
|
||||
rescue LoadError
|
||||
puts "YUI-Compressor not available. Install it with: gem install yui-compressor"
|
||||
end
|
||||
|
||||
class Middleman::Rack::MinifyJavascript
|
||||
def initialize(app, options={})
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
status, headers, response = @app.call(env)
|
||||
|
||||
if env["PATH_INFO"].match(/\.js$/)
|
||||
compressor = ::YUI::JavaScriptCompressor.new(:munge => true)
|
||||
|
||||
uncompressed_source = response.is_a?(::Rack::File) ? File.read(response.path) : response
|
||||
response = compressor.compress(uncompressed_source)
|
||||
headers["Content-Length"] = ::Rack::Utils.bytesize(response).to_s
|
||||
end
|
||||
|
||||
[status, headers, response]
|
||||
end
|
||||
end
|
|
@ -1,61 +0,0 @@
|
|||
require 'sprockets'
|
||||
|
||||
class Middleman::Rack::Sprockets
|
||||
def initialize(app, options={})
|
||||
@app = app
|
||||
@options = options
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if env["PATH_INFO"].match(/\.js$/)
|
||||
public_file_path = File.join(Middleman::Base.public, env["PATH_INFO"])
|
||||
view_file_path = File.join(Middleman::Base.views, env["PATH_INFO"])
|
||||
|
||||
source_file = Rack::File.new(Middleman::Base.public) if File.exists?(public_file_path)
|
||||
source_file = Rack::File.new(Middleman::Base.views) if File.exists?(view_file_path)
|
||||
|
||||
if source_file
|
||||
status, headers, response = source_file.call(env)
|
||||
secretary = ::Sprockets::Secretary.new(@options.merge( :source_files => [ response.path ] ))
|
||||
response = secretary.concatenation.to_s
|
||||
headers["Content-Length"] = ::Rack::Utils.bytesize(response).to_s
|
||||
return [status, headers, response]
|
||||
end
|
||||
end
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
|
||||
Middleman::Base.supported_formats << "js"
|
||||
|
||||
# Sprockets ruby 1.9 duckpunch
|
||||
module Sprockets
|
||||
class SourceFile
|
||||
def source_lines
|
||||
@lines ||= begin
|
||||
lines = []
|
||||
|
||||
comments = []
|
||||
File.open(pathname.absolute_location, 'rb') do |file|
|
||||
file.each do |line|
|
||||
lines << line = SourceLine.new(self, line, file.lineno)
|
||||
|
||||
if line.begins_pdoc_comment? || comments.any?
|
||||
comments << line
|
||||
end
|
||||
|
||||
if line.ends_multiline_comment?
|
||||
if line.ends_pdoc_comment?
|
||||
comments.each { |l| l.comment! }
|
||||
end
|
||||
comments.clear
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
lines
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
26
lib/middleman/renderers.rb
Normal file
26
lib/middleman/renderers.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
module Middleman
|
||||
|
||||
module Renderers
|
||||
@@render_method_for_template_types = {}
|
||||
|
||||
def self.register(method_name, template_type)
|
||||
@@render_method_for_template_types[template_type.to_s] = method_name
|
||||
end
|
||||
|
||||
def self.get_method(template_path)
|
||||
template_type = Tilt[template_path].to_s
|
||||
@@render_method_for_template_types[template_type]
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# Types built into Sinatra
|
||||
Middleman::Renderers.register(:less, Tilt::LessTemplate)
|
||||
Middleman::Renderers.register(:haml, Tilt::HamlTemplate)
|
||||
Middleman::Renderers.register(:builder, Tilt::BuilderTemplate)
|
||||
Middleman::Renderers.register(:erb, Tilt::ERBTemplate)
|
||||
|
||||
%w(haml
|
||||
sass
|
||||
coffee).each { |renderer| require "middleman/renderers/#{renderer}" }
|
|
@ -1,23 +0,0 @@
|
|||
require "builder"
|
||||
|
||||
module Middleman
|
||||
module Renderers
|
||||
module Builder
|
||||
def self.included(base)
|
||||
base.supported_formats << "builder"
|
||||
end
|
||||
|
||||
def render_path(path, layout)
|
||||
if template_exists?(path, :builder)
|
||||
builder(path.to_sym, :layout => layout)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Middleman::Base
|
||||
include Middleman::Renderers::Builder
|
||||
end
|
28
lib/middleman/renderers/coffee.rb
Executable file
28
lib/middleman/renderers/coffee.rb
Executable file
|
@ -0,0 +1,28 @@
|
|||
class Middleman::Base
|
||||
def coffee(template, options={}, locals={})
|
||||
options[:layout] = false
|
||||
render :coffee, template, options, locals
|
||||
end
|
||||
end
|
||||
|
||||
unless defined? Tilt::CoffeeTemplate
|
||||
# CoffeeScript info:
|
||||
# http://jashkenas.github.com/coffee-script/
|
||||
class Tilt::CoffeeTemplate < Tilt::Template
|
||||
def initialize_engine
|
||||
return if defined? ::CoffeeScript
|
||||
require_template_library 'coffee-script'
|
||||
end
|
||||
|
||||
def prepare
|
||||
@output = nil
|
||||
end
|
||||
|
||||
def evaluate(scope, locals, &block)
|
||||
@output ||= ::CoffeeScript::compile(data, options)
|
||||
end
|
||||
end
|
||||
Tilt.register 'coffee', Tilt::CoffeeTemplate
|
||||
end
|
||||
|
||||
Middleman::Renderers.register(:coffee, Tilt::CoffeeTemplate)
|
|
@ -1,24 +0,0 @@
|
|||
require "erb"
|
||||
|
||||
module Middleman
|
||||
module Renderers
|
||||
module ERb
|
||||
def self.included(base)
|
||||
base.supported_formats << "erb"
|
||||
end
|
||||
|
||||
def render_path(path, layout)
|
||||
if template_exists?(path, :erb)
|
||||
layout = false if File.extname(path) == ".xml"
|
||||
erb(path.to_sym, :layout => layout)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Middleman::Base
|
||||
include Middleman::Renderers::ERb
|
||||
end
|
|
@ -1,30 +1,7 @@
|
|||
require "haml"
|
||||
|
||||
module Middleman
|
||||
module Haml
|
||||
module Renderer
|
||||
def self.included(base)
|
||||
base.supported_formats << "haml"
|
||||
base.helpers Middleman::Haml::Helpers
|
||||
end
|
||||
|
||||
def render_path(path, layout)
|
||||
if template_exists?(path, :haml)
|
||||
result = nil
|
||||
begin
|
||||
layout = false if File.extname(path) == ".xml"
|
||||
result = haml(path.to_sym, :layout => layout, :ugly => Middleman::Base.enabled?(:ugly_haml))
|
||||
rescue ::Haml::Error => e
|
||||
result = "Haml Error: #{e}"
|
||||
result << "<pre>Backtrace: #{e.backtrace.join("\n")}</pre>"
|
||||
end
|
||||
result
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Haml
|
||||
module Helpers
|
||||
def haml_partial(name, options = {})
|
||||
item_name = name.to_sym
|
||||
|
@ -66,5 +43,5 @@ module Middleman
|
|||
end
|
||||
|
||||
class Middleman::Base
|
||||
include Middleman::Haml::Renderer
|
||||
helpers Middleman::Haml::Helpers
|
||||
end
|
|
@ -1,23 +0,0 @@
|
|||
require "less"
|
||||
|
||||
module Middleman
|
||||
module Renderers
|
||||
module Less
|
||||
def self.included(base)
|
||||
base.supported_formats << "less"
|
||||
end
|
||||
|
||||
def render_path(path, layout)
|
||||
if template_exists?(path, :less)
|
||||
less(path.to_sym)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Middleman::Base
|
||||
include Middleman::Renderers::Less
|
||||
end
|
|
@ -1,93 +1,18 @@
|
|||
require "sass"
|
||||
require "compass"
|
||||
require "fancy-buttons"
|
||||
|
||||
begin
|
||||
require "yui/compressor"
|
||||
rescue LoadError
|
||||
puts "YUI-Compressor not available. Install it with: gem install yui-compressor"
|
||||
end
|
||||
|
||||
module Middleman::Sass
|
||||
def self.included(base)
|
||||
base.supported_formats << "sass"
|
||||
end
|
||||
|
||||
def render_path(path, layout)
|
||||
if template_exists?(path, :sass)
|
||||
begin
|
||||
static_version = settings.public + request.path_info
|
||||
send_file(static_version) if File.exists? static_version
|
||||
|
||||
location_of_sass_file = settings.environment == "build" ?
|
||||
File.join(Dir.pwd, settings.build_dir) :
|
||||
settings.public
|
||||
|
||||
css_filename = File.join(location_of_sass_file, request.path_info)
|
||||
result = sass(path.to_sym, ::Compass.sass_engine_options.merge({ :css_filename => css_filename }))
|
||||
|
||||
if enabled?(:minify_css)
|
||||
::YUI::CssCompressor.new.compress(result)
|
||||
else
|
||||
result
|
||||
end
|
||||
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
|
||||
|
||||
class Middleman::Base
|
||||
include Middleman::Sass
|
||||
def scss(template, options={}, locals={})
|
||||
options[:layout] = false
|
||||
render :scss, template, options, locals
|
||||
end
|
||||
|
||||
after_feature_init do
|
||||
::Compass.configuration do |config|
|
||||
config.cache_path = File.join(self.root, ".sassc") # For sassc files
|
||||
config.cache_path = File.join(self.root, ".sass-cache") # For sassc files
|
||||
config.project_path = self.root
|
||||
config.sass_dir = File.join(File.basename(self.views), self.css_dir)
|
||||
config.output_style = self.enabled?(:minify_css) ? :compressed : :nested
|
||||
config.output_style = :nested
|
||||
config.fonts_dir = File.join(File.basename(self.public), self.fonts_dir)
|
||||
config.css_dir = File.join(File.basename(self.public), self.css_dir)
|
||||
config.images_dir = File.join(File.basename(self.public), self.images_dir)
|
||||
|
@ -98,17 +23,45 @@ class Middleman::Base
|
|||
config.add_import_path(config.sass_dir)
|
||||
end
|
||||
|
||||
::Compass.configure_sass_plugin!
|
||||
Sass::Plugin.options.update(:line_comments => true, :debug_info => true)
|
||||
|
||||
configure :build do
|
||||
::Compass.configuration do |config|
|
||||
config.css_dir = File.join(File.basename(self.build_dir), self.css_dir)
|
||||
config.images_dir = File.join(File.basename(self.build_dir), self.images_dir)
|
||||
end
|
||||
|
||||
::Compass.configure_sass_plugin!
|
||||
Sass::Plugin.options.update(:line_comments => false, :debug_info => false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Tilt::SassPlusCSSFilenameTemplate < Tilt::SassTemplate
|
||||
def sass_options
|
||||
location_of_sass_file = Middleman::Base.environment == "build" ?
|
||||
File.join(Middleman::Base.root, Middleman::Base.build_dir) :
|
||||
Middleman::Base.public
|
||||
|
||||
parts = basename.split('.')
|
||||
parts.pop
|
||||
css_filename = File.join(location_of_sass_file, Middleman::Base.css_dir, parts.join("."))
|
||||
super.merge(::Compass.configuration.to_sass_engine_options).merge(:css_filename => css_filename)
|
||||
end
|
||||
end
|
||||
Tilt.register 'sass', Tilt::SassPlusCSSFilenameTemplate
|
||||
Middleman::Renderers.register(:sass, Tilt::SassPlusCSSFilenameTemplate)
|
||||
|
||||
class Tilt::ScssPlusCSSFilenameTemplate < Tilt::SassPlusCSSFilenameTemplate
|
||||
def sass_options
|
||||
super.merge(:syntax => :scss)
|
||||
end
|
||||
end
|
||||
Tilt.register 'scss', Tilt::ScssPlusCSSFilenameTemplate
|
||||
Middleman::Renderers.register(:scss, Tilt::ScssPlusCSSFilenameTemplate)
|
||||
|
||||
|
||||
module Middleman::Haml
|
||||
module Sass
|
||||
include ::Haml::Filters::Base
|
||||
|
||||
def render(text)
|
||||
::Sass::Engine.new(text, ::Compass.configuration.to_sass_engine_options).render
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,14 @@
|
|||
<% if css_dir %>set :css_dir, "<%= css_dir -%>"<% end %>
|
||||
<% if js_dir %>set :js_dir, "<%= js_dir -%>"<% end %>
|
||||
<% if images_dir %>set :images_dir, "<%= images_dir -%>"<% end %>
|
||||
# Automatic sitemaps
|
||||
# enable :slickmap
|
||||
|
||||
# Automatic image dimension calculations
|
||||
# enable :automatic_image_sizes
|
||||
|
||||
# Per-page layout changes
|
||||
# With no layout
|
||||
# page "/path/to/file.html", :layout => false
|
||||
# With alternative layout
|
||||
# page "/path/to/file.html", :layout => :otherlayout
|
||||
|
||||
# Helpers
|
||||
helpers do
|
||||
|
@ -9,11 +17,26 @@ helpers do
|
|||
end
|
||||
end
|
||||
|
||||
# Automatic sitemaps
|
||||
# enable :slickmap
|
||||
<% if css_dir %>
|
||||
set :css_dir, "<%= css_dir -%>"
|
||||
<% else %>
|
||||
# Change the CSS directory
|
||||
# set :css_dir, "alternative_css_directory"
|
||||
<% end %>
|
||||
|
||||
# Automatic image dimension calculations
|
||||
# enable :automatic_image_sizes
|
||||
<% if js_dir %>
|
||||
set :js_dir, "<%= js_dir -%>"
|
||||
<% else %>
|
||||
# Change the JS directory
|
||||
# set :js_dir, "alternative_js_directory"
|
||||
<% end %>
|
||||
|
||||
<% if images_dir %>
|
||||
set :images_dir, "<%= images_dir -%>"
|
||||
<% else %>
|
||||
# Change the images directory
|
||||
# set :images_dir, "alternative_image_directory"
|
||||
<% end %>
|
||||
|
||||
# Build-specific configuration
|
||||
configure :build do
|
||||
|
|
|
@ -42,6 +42,16 @@ describe "Builder" do
|
|||
File.read("#{@root_dir}/build/stylesheets/site.css").gsub(/\s/, "").should include("html,body,div,span,applet,object,iframe")
|
||||
end
|
||||
|
||||
it "should build less files" do
|
||||
File.exists?("#{@root_dir}/build/stylesheets/test_less.css").should be_true
|
||||
File.read("#{@root_dir}/build/stylesheets/test_less.css").should include("666")
|
||||
end
|
||||
|
||||
it "should build scss files" do
|
||||
File.exists?("#{@root_dir}/build/stylesheets/site_scss.css").should be_true
|
||||
File.read("#{@root_dir}/build/stylesheets/site_scss.css").gsub(/\s/, "").should include("html,body,div,span,applet,object,iframe")
|
||||
end
|
||||
|
||||
it "should build static css files" do
|
||||
File.exists?("#{@root_dir}/build/stylesheets/static.css").should be_true
|
||||
end
|
||||
|
|
1
spec/fixtures/sample/views/stylesheets/site_scss.css.scss
vendored
Executable file
1
spec/fixtures/sample/views/stylesheets/site_scss.css.scss
vendored
Executable file
|
@ -0,0 +1 @@
|
|||
@import "compass/reset";
|
5
spec/fixtures/sample/views/stylesheets/test_less.css.less
vendored
Executable file
5
spec/fixtures/sample/views/stylesheets/test_less.css.less
vendored
Executable file
|
@ -0,0 +1,5 @@
|
|||
@brand_color: #666666;
|
||||
|
||||
#header {
|
||||
color: @brand_color;
|
||||
}
|
Loading…
Reference in a new issue