From 5523a10d9b26ebc087259bff8a88fe5deae18964 Mon Sep 17 00:00:00 2001 From: tdreyno Date: Sat, 4 Sep 2010 20:26:48 -0700 Subject: [PATCH] Rewritten core which makes better use of Tilt. Support for SCSS, Coffee and Less. --- Rakefile | 33 ++-- features/automatic_image_sizes.feature | 14 +- features/cache_buster.feature | 20 +-- features/minify_css.feature | 22 +-- features/minify_javascript.feature | 12 +- features/step_definitions/asset_host_steps.rb | 1 + features/step_definitions/middleman_steps.rb | 2 +- lib/middleman.rb | 19 +-- lib/middleman/assets.rb | 33 ++++ lib/middleman/base.rb | 90 +++-------- lib/middleman/features.rb | 40 +++++ lib/middleman/features/asset_host.rb | 35 ++-- .../features/automatic_image_sizes.rb | 48 +++--- .../automatic_image_sizes}/fastimage.rb | 0 lib/middleman/features/cache_buster.rb | 69 ++++---- .../default_helpers.rb} | 19 +-- lib/middleman/features/livereload.rb | 19 +++ lib/middleman/features/minify_css.rb | 9 ++ lib/middleman/features/minify_javascript.rb | 32 ++-- .../features/minify_javascript/rack.rb | 31 ++++ lib/middleman/features/relative_assets.rb | 71 ++++---- lib/middleman/features/slickmap.rb | 151 +++++++++--------- lib/middleman/features/smush_pngs.rb | 14 +- lib/middleman/features/sprockets.rb | 13 ++ lib/middleman/features/sprockets/rack.rb | 64 ++++++++ lib/middleman/features/ugly_haml.rb | 7 + lib/middleman/rack/minify_css.rb | 25 --- lib/middleman/rack/minify_javascript.rb | 25 --- lib/middleman/rack/sprockets.rb | 61 ------- lib/middleman/renderers.rb | 26 +++ lib/middleman/renderers/builder.rb | 23 --- lib/middleman/renderers/coffee.rb | 28 ++++ lib/middleman/renderers/erb.rb | 24 --- lib/middleman/renderers/haml.rb | 27 +--- lib/middleman/renderers/less.rb | 23 --- lib/middleman/renderers/sass.rb | 127 +++++---------- lib/middleman/template/init.rbt | 37 ++++- spec/builder_spec.rb | 10 ++ .../views/stylesheets/site_scss.css.scss | 1 + .../views/stylesheets/test_less.css.less | 5 + 40 files changed, 642 insertions(+), 668 deletions(-) create mode 100644 lib/middleman/assets.rb create mode 100644 lib/middleman/features.rb rename lib/middleman/{ => features/automatic_image_sizes}/fastimage.rb (100%) rename lib/middleman/{helpers.rb => features/default_helpers.rb} (81%) mode change 100755 => 100644 create mode 100644 lib/middleman/features/livereload.rb create mode 100644 lib/middleman/features/minify_javascript/rack.rb create mode 100644 lib/middleman/features/sprockets.rb create mode 100644 lib/middleman/features/sprockets/rack.rb create mode 100644 lib/middleman/features/ugly_haml.rb delete mode 100644 lib/middleman/rack/minify_css.rb delete mode 100644 lib/middleman/rack/minify_javascript.rb delete mode 100644 lib/middleman/rack/sprockets.rb create mode 100644 lib/middleman/renderers.rb delete mode 100644 lib/middleman/renderers/builder.rb create mode 100755 lib/middleman/renderers/coffee.rb delete mode 100755 lib/middleman/renderers/erb.rb delete mode 100644 lib/middleman/renderers/less.rb create mode 100755 spec/fixtures/sample/views/stylesheets/site_scss.css.scss create mode 100755 spec/fixtures/sample/views/stylesheets/test_less.css.less diff --git a/Rakefile b/Rakefile index 915aea62..fe2e67b5 100644 --- a/Rakefile +++ b/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") diff --git a/features/automatic_image_sizes.feature b/features/automatic_image_sizes.feature index 39ad67e7..02c3b6cb 100644 --- a/features/automatic_image_sizes.feature +++ b/features/automatic_image_sizes.feature @@ -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=" \ No newline at end of file + 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=" \ No newline at end of file diff --git a/features/cache_buster.feature b/features/cache_buster.feature index da8e3055..ef62ff16 100644 --- a/features/cache_buster.feature +++ b/features/cache_buster.feature @@ -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 "?" \ No newline at end of file diff --git a/features/minify_css.feature b/features/minify_css.feature index c986f0b7..22b2d121 100644 --- a/features/minify_css.feature +++ b/features/minify_css.feature @@ -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 \ No newline at end of file + 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 \ No newline at end of file diff --git a/features/minify_javascript.feature b/features/minify_javascript.feature index 9fe7d0ab..947bee96 100644 --- a/features/minify_javascript.feature +++ b/features/minify_javascript.feature @@ -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 \ No newline at end of file + Then I should see "1" lines \ No newline at end of file diff --git a/features/step_definitions/asset_host_steps.rb b/features/step_definitions/asset_host_steps.rb index 1a12a49f..75c2c518 100644 --- a/features/step_definitions/asset_host_steps.rb +++ b/features/step_definitions/asset_host_steps.rb @@ -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 diff --git a/features/step_definitions/middleman_steps.rb b/features/step_definitions/middleman_steps.rb index 5efcbaf3..60cd9d5b 100644 --- a/features/step_definitions/middleman_steps.rb +++ b/features/step_definitions/middleman_steps.rb @@ -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 \ No newline at end of file diff --git a/lib/middleman.rb b/lib/middleman.rb index 2a172483..9556fad7 100755 --- a/lib/middleman.rb +++ b/lib/middleman.rb @@ -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 diff --git a/lib/middleman/assets.rb b/lib/middleman/assets.rb new file mode 100644 index 00000000..2cacb035 --- /dev/null +++ b/lib/middleman/assets.rb @@ -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 \ No newline at end of file diff --git a/lib/middleman/base.rb b/lib/middleman/base.rb index 95c60e46..76d26fcb 100644 --- a/lib/middleman/base.rb +++ b/lib/middleman/base.rb @@ -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) } diff --git a/lib/middleman/features.rb b/lib/middleman/features.rb new file mode 100644 index 00000000..18eac4e1 --- /dev/null +++ b/lib/middleman/features.rb @@ -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 \ No newline at end of file diff --git a/lib/middleman/features/asset_host.rb b/lib/middleman/features/asset_host.rb index 342955ae..d363fbc3 100644 --- a/lib/middleman/features/asset_host.rb +++ b/lib/middleman/features/asset_host.rb @@ -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 diff --git a/lib/middleman/features/automatic_image_sizes.rb b/lib/middleman/features/automatic_image_sizes.rb index bc3e4c3b..c5b0210f 100755 --- a/lib/middleman/features/automatic_image_sizes.rb +++ b/lib/middleman/features/automatic_image_sizes.rb @@ -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 \ No newline at end of file +end + +Middleman::Features.register :automatic_image_sizes, Middleman::Features::AutomaticImageSizes \ No newline at end of file diff --git a/lib/middleman/fastimage.rb b/lib/middleman/features/automatic_image_sizes/fastimage.rb similarity index 100% rename from lib/middleman/fastimage.rb rename to lib/middleman/features/automatic_image_sizes/fastimage.rb diff --git a/lib/middleman/features/cache_buster.rb b/lib/middleman/features/cache_buster.rb index 24861ab7..6c0befd5 100755 --- a/lib/middleman/features/cache_buster.rb +++ b/lib/middleman/features/cache_buster.rb @@ -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 \ No newline at end of file + +Middleman::Features.register :cache_buster, Middleman::Features::CacheBuster \ No newline at end of file diff --git a/lib/middleman/helpers.rb b/lib/middleman/features/default_helpers.rb old mode 100755 new mode 100644 similarity index 81% rename from lib/middleman/helpers.rb rename to lib/middleman/features/default_helpers.rb index 05598ab7..16690391 --- a/lib/middleman/helpers.rb +++ b/lib/middleman/features/default_helpers.rb @@ -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 } \ No newline at end of file diff --git a/lib/middleman/features/livereload.rb b/lib/middleman/features/livereload.rb new file mode 100644 index 00000000..56a776c0 --- /dev/null +++ b/lib/middleman/features/livereload.rb @@ -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 \ No newline at end of file diff --git a/lib/middleman/features/minify_css.rb b/lib/middleman/features/minify_css.rb index e69de29b..158799d9 100644 --- a/lib/middleman/features/minify_css.rb +++ b/lib/middleman/features/minify_css.rb @@ -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 \ No newline at end of file diff --git a/lib/middleman/features/minify_javascript.rb b/lib/middleman/features/minify_javascript.rb index 20f468d9..eb812b9f 100755 --- a/lib/middleman/features/minify_javascript.rb +++ b/lib/middleman/features/minify_javascript.rb @@ -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{} - else - < - // - -END - end + compressor = ::YUI::JavaScriptCompressor.new(:munge => true) + data = compressor.compress(text) + %Q{} end end end -end \ No newline at end of file +end + +Middleman::Features.register :minify_javascript, Middleman::Features::MinifyJavascript \ No newline at end of file diff --git a/lib/middleman/features/minify_javascript/rack.rb b/lib/middleman/features/minify_javascript/rack.rb new file mode 100644 index 00000000..c58e5966 --- /dev/null +++ b/lib/middleman/features/minify_javascript/rack.rb @@ -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 \ No newline at end of file diff --git a/lib/middleman/features/relative_assets.rb b/lib/middleman/features/relative_assets.rb index d931a6bb..f2874a49 100755 --- a/lib/middleman/features/relative_assets.rb +++ b/lib/middleman/features/relative_assets.rb @@ -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 \ No newline at end of file +Middleman::Features.register :relative_assets, Middleman::Features::RelativeAssets diff --git a/lib/middleman/features/slickmap.rb b/lib/middleman/features/slickmap.rb index 33b8f71e..e1ee8dfc 100755 --- a/lib/middleman/features/slickmap.rb +++ b/lib/middleman/features/slickmap.rb @@ -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() { diff --git a/lib/middleman/features/smush_pngs.rb b/lib/middleman/features/smush_pngs.rb index 294536c6..b3cd7759 100644 --- a/lib/middleman/features/smush_pngs.rb +++ b/lib/middleman/features/smush_pngs.rb @@ -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 \ No newline at end of file +end + +Middleman::Features.register :smush_pngs, Middleman::Features::SmushPngs \ No newline at end of file diff --git a/lib/middleman/features/sprockets.rb b/lib/middleman/features/sprockets.rb new file mode 100644 index 00000000..c1b50f14 --- /dev/null +++ b/lib/middleman/features/sprockets.rb @@ -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 } + + diff --git a/lib/middleman/features/sprockets/rack.rb b/lib/middleman/features/sprockets/rack.rb new file mode 100644 index 00000000..c22a8b5e --- /dev/null +++ b/lib/middleman/features/sprockets/rack.rb @@ -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 \ No newline at end of file diff --git a/lib/middleman/features/ugly_haml.rb b/lib/middleman/features/ugly_haml.rb new file mode 100644 index 00000000..cbc159aa --- /dev/null +++ b/lib/middleman/features/ugly_haml.rb @@ -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 \ No newline at end of file diff --git a/lib/middleman/rack/minify_css.rb b/lib/middleman/rack/minify_css.rb deleted file mode 100644 index 1392b4d6..00000000 --- a/lib/middleman/rack/minify_css.rb +++ /dev/null @@ -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 \ No newline at end of file diff --git a/lib/middleman/rack/minify_javascript.rb b/lib/middleman/rack/minify_javascript.rb deleted file mode 100644 index bb5e5b7a..00000000 --- a/lib/middleman/rack/minify_javascript.rb +++ /dev/null @@ -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 \ No newline at end of file diff --git a/lib/middleman/rack/sprockets.rb b/lib/middleman/rack/sprockets.rb deleted file mode 100644 index add50482..00000000 --- a/lib/middleman/rack/sprockets.rb +++ /dev/null @@ -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 \ No newline at end of file diff --git a/lib/middleman/renderers.rb b/lib/middleman/renderers.rb new file mode 100644 index 00000000..e5580e6f --- /dev/null +++ b/lib/middleman/renderers.rb @@ -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}" } \ No newline at end of file diff --git a/lib/middleman/renderers/builder.rb b/lib/middleman/renderers/builder.rb deleted file mode 100644 index 10091e83..00000000 --- a/lib/middleman/renderers/builder.rb +++ /dev/null @@ -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 diff --git a/lib/middleman/renderers/coffee.rb b/lib/middleman/renderers/coffee.rb new file mode 100755 index 00000000..2e2c5a39 --- /dev/null +++ b/lib/middleman/renderers/coffee.rb @@ -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) \ No newline at end of file diff --git a/lib/middleman/renderers/erb.rb b/lib/middleman/renderers/erb.rb deleted file mode 100755 index ac273767..00000000 --- a/lib/middleman/renderers/erb.rb +++ /dev/null @@ -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 diff --git a/lib/middleman/renderers/haml.rb b/lib/middleman/renderers/haml.rb index 36f3037c..2b315a5a 100755 --- a/lib/middleman/renderers/haml.rb +++ b/lib/middleman/renderers/haml.rb @@ -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 << "
Backtrace: #{e.backtrace.join("\n")}
" - 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 \ No newline at end of file diff --git a/lib/middleman/renderers/less.rb b/lib/middleman/renderers/less.rb deleted file mode 100644 index 1034ee93..00000000 --- a/lib/middleman/renderers/less.rb +++ /dev/null @@ -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 diff --git a/lib/middleman/renderers/sass.rb b/lib/middleman/renderers/sass.rb index 6f5a9fc1..3fa01427 100644 --- a/lib/middleman/renderers/sass.rb +++ b/lib/middleman/renderers/sass.rb @@ -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 - < 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 \ No newline at end of file diff --git a/lib/middleman/template/init.rbt b/lib/middleman/template/init.rbt index efcb876f..f1d50a2a 100755 --- a/lib/middleman/template/init.rbt +++ b/lib/middleman/template/init.rbt @@ -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 diff --git a/spec/builder_spec.rb b/spec/builder_spec.rb index b3311bdc..6d1593b9 100644 --- a/spec/builder_spec.rb +++ b/spec/builder_spec.rb @@ -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 diff --git a/spec/fixtures/sample/views/stylesheets/site_scss.css.scss b/spec/fixtures/sample/views/stylesheets/site_scss.css.scss new file mode 100755 index 00000000..0cc04182 --- /dev/null +++ b/spec/fixtures/sample/views/stylesheets/site_scss.css.scss @@ -0,0 +1 @@ +@import "compass/reset"; \ No newline at end of file diff --git a/spec/fixtures/sample/views/stylesheets/test_less.css.less b/spec/fixtures/sample/views/stylesheets/test_less.css.less new file mode 100755 index 00000000..a57c304f --- /dev/null +++ b/spec/fixtures/sample/views/stylesheets/test_less.css.less @@ -0,0 +1,5 @@ +@brand_color: #666666; + +#header { + color: @brand_color; +} \ No newline at end of file