diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..5ce6144d --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2009 Thomas Reynolds + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..6832f8a0 --- /dev/null +++ b/Rakefile @@ -0,0 +1,84 @@ +require 'rubygems' +require 'rake' + +begin + require 'jeweler' + Jeweler::Tasks.new do |gem| + gem.name = "middleman" + gem.summary = %Q{A static site generator utilizing Haml, Sass and providing YUI compression and cache busting} + gem.email = "tdreyno@gmail.com" + gem.homepage = "http://wiki.github.com/tdreyno/middleman" + gem.authors = ["Thomas Reynolds"] + gem.rubyforge_project = "middleman" + gem.executables = %w(mm-init mm-build mm-server) + gem.add_dependency("thin") + gem.add_dependency("shotgun") + gem.add_dependency("templater") + gem.add_dependency("sprockets") + gem.add_dependency("sinatra") + gem.add_dependency("sinatra-content-for") + gem.add_dependency("rack-test") + gem.add_dependency("yui-compressor") + gem.add_dependency("haml", ">=2.1.0") + gem.add_dependency("compass") + gem.add_development_dependency("rspec") + gem.add_development_dependency("sdoc") + end + + Jeweler::RubyforgeTasks.new do |rubyforge| + rubyforge.doc_task = "rdoc" + end + + Jeweler::GemcutterTasks.new +rescue LoadError + puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler" +end + +require 'spec/rake/spectask' +Spec::Rake::SpecTask.new(:spec) do |spec| + spec.libs << 'lib' << 'spec' + spec.spec_files = FileList['spec/**/*_spec.rb'] +end + +Spec::Rake::SpecTask.new(:rcov) do |spec| + spec.libs << 'lib' << 'spec' + spec.pattern = 'spec/**/*_spec.rb' + spec.rcov = true +end + +task :spec => :check_dependencies + +task :default => :spec + +require 'rake/rdoctask' +require 'sdoc' + +Rake::RDocTask.new do |rdoc| + if File.exist?('VERSION') + version = File.read('VERSION') + else + version = "" + end + + # rdoc.template = 'direct' + + rdoc.rdoc_dir = 'rdoc' + rdoc.title = "middleman #{version}" + rdoc.rdoc_files.include('README*') + rdoc.rdoc_files.include('lib/**/*.rb') + rdoc.rdoc_files.exclude('lib/middleman/features/sprockets+ruby19.rb') + rdoc.rdoc_files.exclude('lib/middleman/templater+dynamic_renderer.rb') +end + +desc "Build and publish documentation using GitHub Pages." +task :pages do + if !`git status`.include?('nothing to commit') + abort "dirty index - not publishing!" + end + + Rake::Task[:rerdoc].invoke + `git checkout gh-pages` + `ls -1 | grep -v rdoc | xargs rm -rf; mv rdoc/* .; rm -rf rdoc` + `git commit -a -m "update docs"; git push origin gh-pages` + `git checkout master` +end \ No newline at end of file diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..bd758c92 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.9.20 diff --git a/bin/mm-build b/bin/mm-build new file mode 100755 index 00000000..11ac2cbc --- /dev/null +++ b/bin/mm-build @@ -0,0 +1,12 @@ +#!/usr/bin/env ruby + +ENV['MM_ENV'] = "build" + +# Require app +require File.join(File.dirname(__FILE__), "..", "lib", "middleman") +require 'middleman/builder' + +#Middleman::Base.init! +Middleman::Builder.init! + +Middleman::Generators.run_cli(Dir.pwd, 'mm-build', 1, %w(build --force).concat(ARGV)) \ No newline at end of file diff --git a/bin/mm-init b/bin/mm-init new file mode 100755 index 00000000..99005033 --- /dev/null +++ b/bin/mm-init @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby +require 'templater' + +module Generators + extend Templater::Manifold + desc "Generator for streamlining staticmatic" + + class NewSite < Templater::Generator + desc "Creates a new middleman scaffold." + first_argument :location, :required => true, :desc => "Project location" + + option :css_dir, :desc => 'The path to the css files' + option :js_dir, :desc => 'The path to the javascript files' + option :images_dir, :desc => 'The path to the image files' + + def destination_root + File.expand_path(location) + end + + def self.source_root + File.join(File.dirname(__FILE__), '..', 'lib', 'middleman', 'template') + end + + template :init, "init.rb" + glob! :views + glob! :public + + empty_directory :stylesheets, "public/stylesheets"#, File.join("public", css_dir) + empty_directory :javascripts, "public/javascripts"#, File.join("public", js_dir) + empty_directory :images, "public/images"#, File.join("public", images_dir) + end + + add :setup, NewSite +end + +Generators.run_cli(Dir.pwd, 'mm-init', 1, %w(setup).concat(ARGV)) \ No newline at end of file diff --git a/bin/mm-server b/bin/mm-server new file mode 100755 index 00000000..d5b04e39 --- /dev/null +++ b/bin/mm-server @@ -0,0 +1,43 @@ +#!/usr/bin/env ruby + +require 'optparse' + +# Require Middleman +require File.join(File.dirname(__FILE__), '..', 'lib', 'middleman') + +env = ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development' +options = { :Port => 4567, :AccessLog => [] } + +OptionParser.new { |opts| + opts.banner = "Usage: mm-server [rack options]" + opts.separator "" + opts.separator "Rack options:" + opts.on("-p", "--port PORT", "use PORT (default: 4567)") { |port| + options[:Port] = port + } + opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development)") { |e| + env = e + } + opts.on("--debug", "Debug mode") { + ::Middleman::Base.set :logging, true + } + + opts.parse! ARGV +} + +ENV['RACK_ENV'] = env + +class Middleman::Base + set :root, Dir.pwd +end + +require 'shotgun' +config = File.join(File.dirname(__FILE__), '..', 'lib', 'middleman', 'config.ru') +app = Shotgun.new(config, lambda { |inner_app| Middleman::Base }) + +require 'thin' +Thin::Logging.silent = true + +Rack::Handler::Thin.run app, options do |inst| + puts "== The Middleman is standing watch on port #{options[:Port]}" +end \ No newline at end of file diff --git a/deps.rip b/deps.rip new file mode 100644 index 00000000..33d75a7b --- /dev/null +++ b/deps.rip @@ -0,0 +1,7 @@ +git://github.com/jnicklas/templater.git +git://github.com/sstephenson/sprockets.git +git://github.com/sinatra/sinatra.git +git://github.com/nex3/haml.git +git://github.com/chriseppstein/compass.git +git://github.com/foca/sinatra-content-for.git +git://github.com/brynary/rack-test.git \ No newline at end of file diff --git a/lib/middleman.rb b/lib/middleman.rb new file mode 100644 index 00000000..158577dd --- /dev/null +++ b/lib/middleman.rb @@ -0,0 +1,4 @@ +libdir = File.dirname(__FILE__) +$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir) + +require 'middleman/base' \ No newline at end of file diff --git a/lib/middleman/base.rb b/lib/middleman/base.rb new file mode 100644 index 00000000..9f7114dd --- /dev/null +++ b/lib/middleman/base.rb @@ -0,0 +1,137 @@ +# Be nice to other library systems, like the wonderful Rip +require 'rubygems' unless ENV['NO_RUBYGEMS'] + +# We're riding on Sinatra, so let's include it +require 'sinatra/base' + +module Middleman + class Base < Sinatra::Base + set :app_file, __FILE__ + set :root, Dir.pwd + set :reload, false + set :logging, false + set :environment, ENV['MM_ENV'] || :development + set :supported_formats, %w(erb) + set :index_file, "index.html" + set :js_dir, "javascripts" + set :css_dir, "stylesheets" + set :images_dir, "images" + set :build_dir, "build" + set :http_prefix, "/" + + use Rack::ConditionalGet if environment == :development + + @@features = [] + + def self.enable(*opts) + @@features << opts + super + end + + def self.disable(*opts) + @@features -= opts + super + end + + # Rack helper for adding mime-types during local preview + def self.mime(ext, type) + ext = ".#{ext}" unless ext.to_s[0] == ?. + ::Rack::Mime::MIME_TYPES[ext.to_s] = type + end + + # Convenience function to discover if a tempalte exists for the requested renderer (haml, sass, etc) + def template_exists?(path, renderer=nil) + template_path = path.dup + template_path << ".#{renderer}" if renderer + File.exists? File.join(options.views, template_path) + end + + # Base case renderer (do nothing), Should be over-ridden + module StaticRender + def render_path(path) + if template_exists?(path, :erb) + erb(path.to_sym) + else + false + end + end + end + include StaticRender + + # This will match all requests not overridden in the project's init.rb + not_found do + # Normalize the path and add index if we're looking at a directory + path = request.path + path << options.index_file if path.match(%r{/$}) + path.gsub!(%r{^/}, '') + + # If the enabled renderers succeed, return the content, mime-type and an HTTP 200 + if content = render_path(path) + content_type media_type(File.extname(path)), :charset => 'utf-8' + status 200 + content + else + status 404 + end + end + end +end + +# Haml is required & includes helpers +require "middleman/haml" +require "middleman/sass" +require 'sinatra/content_for' +require 'middleman/helpers' +require 'middleman/rack/static' +require 'middleman/rack/sprockets' + +class Middleman::Base + helpers Sinatra::ContentFor + helpers Middleman::Helpers + + use Middleman::Rack::Static + use Middleman::Rack::Sprockets + + enable :compass + require "middleman/features/compass" + @@features -= [:compass] + + # Features disabled by default + disable :slickmap + disable :cache_buster + disable :minify_css + disable :minify_javascript + disable :relative_assets + disable :maruku + disable :smush_pngs + + # Default build features + configure :build do + enable :minify_css + enable :minify_javascript + enable :cache_buster + end + + def self.new(*args, &bk) + # Check for and evaluate local configuration + local_config = File.join(self.root, "init.rb") + if File.exists? local_config + puts "== Reading: Local config" if logging? + class_eval File.read(local_config) + end + + # loop over enabled feature + @@features.flatten.each do |feature_name| + next unless send(:"#{feature_name}?") + puts "== Enabling: #{feature_name.capitalize}" if logging? + require "middleman/features/#{feature_name}" + end + + ::Compass.configuration do |config| + config.http_images_path = self.http_images_path rescue File.join(self.http_prefix, self.images_dir) + config.http_stylesheets_path = self.http_css_path rescue File.join(self.http_prefix, self.css_dir) + end + + super + end +end \ No newline at end of file diff --git a/lib/middleman/builder.rb b/lib/middleman/builder.rb new file mode 100644 index 00000000..6b05d8c4 --- /dev/null +++ b/lib/middleman/builder.rb @@ -0,0 +1,53 @@ +require 'templater' +require 'middleman/templater+dynamic_renderer.rb' + +# Placeholder for any methods the builder needs to abstract to allow feature integration +module Middleman + class Builder < ::Templater::Generator + # Define source and desintation + def self.source_root; Dir.pwd; end + def destination_root; File.join(Dir.pwd, Middleman::Base.build_dir); end + + # Override template to ask middleman for the correct extension to output + def self.template(name, *args, &block) + return if args[0].include?('layout') + + args.first.split('/').each do |part| + return if part[0,1] == '_' + end + + if (args[0] === args[1]) + args[1] = args[0].gsub("#{File.basename(Middleman::Base.views)}/", "") + .gsub("#{File.basename(Middleman::Base.public)}/", "") + if File.extname(args[1]) != ".js" + args[1] = args[1].gsub!(File.extname(args[1]), "") if File.basename(args[1]).split('.').length > 2 + end + end + + super(name, *args, &block) + end + + def self.file(name, *args, &block) + if (args[0] === args[1]) + args[1] = args[0].gsub("#{File.basename(Middleman::Base.views)}/", "") + .gsub("#{File.basename(Middleman::Base.public)}/", "") + end + super(name, *args, &block) + end + + def self.init! + glob! File.basename(Middleman::Base.public), [] + glob! File.basename(Middleman::Base.views), Middleman::Base.supported_formats + end + + def after_run + end + end + + module Generators + extend ::Templater::Manifold + desc "Build a static site" + + add :build, ::Middleman::Builder + end +end \ No newline at end of file diff --git a/lib/middleman/config.ru b/lib/middleman/config.ru new file mode 100644 index 00000000..de3cfdb9 --- /dev/null +++ b/lib/middleman/config.ru @@ -0,0 +1,2 @@ +require 'middleman' +run Middleman::Base \ No newline at end of file diff --git a/lib/middleman/features/cache_buster.rb b/lib/middleman/features/cache_buster.rb new file mode 100644 index 00000000..ae9e1732 --- /dev/null +++ b/lib/middleman/features/cache_buster.rb @@ -0,0 +1,18 @@ +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) + 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 = File.join(self.environment == "build" ? self.build_dir : self.public, prefix, path) + http_path << "?" + File.mtime(real_path).strftime("%s") if File.readable?(real_path) + http_path + end + end +end \ No newline at end of file diff --git a/lib/middleman/features/compass.rb b/lib/middleman/features/compass.rb new file mode 100644 index 00000000..8f5501c4 --- /dev/null +++ b/lib/middleman/features/compass.rb @@ -0,0 +1,18 @@ +class Middleman::Base + configure do + ::Compass.configuration do |config| + images_location = (self.environment == "build") ? self.build_dir : self.public + + config.project_path = Dir.pwd + config.sass_dir = File.join(File.basename(self.views), self.css_dir) + config.output_style = :nested + config.css_dir = File.join(File.basename(images_location), self.css_dir) + config.images_dir = File.join(File.basename(images_location), self.images_dir) + # File.expand_path(self.images_dir, self.public) + + config.add_import_path(config.sass_dir) + end + + ::Compass.configure_sass_plugin! + end +end \ No newline at end of file diff --git a/lib/middleman/features/growl.rb b/lib/middleman/features/growl.rb new file mode 100644 index 00000000..de67b438 --- /dev/null +++ b/lib/middleman/features/growl.rb @@ -0,0 +1,2 @@ +# Errors to growl +# Build complete to growl \ No newline at end of file diff --git a/lib/middleman/features/maruku.rb b/lib/middleman/features/maruku.rb new file mode 100644 index 00000000..b3d35b69 --- /dev/null +++ b/lib/middleman/features/maruku.rb @@ -0,0 +1,39 @@ +begin + require 'maruku' +rescue LoadError + puts "Maruku not available. Install it with: gem install maruku" +end + +module Middleman + module Maruku + def self.included(base) + base.supported_formats << "maruku" + base.set :maruku, {} + end + + def render_path(path) + if template_exists?(path, :maruku) + render :maruku, path.to_sym + else + super + end + end + + private + def render_maruku(template, data, options, locals, &block) + maruku_src = render_erb(template, data, options, locals, &block) + instance = ::Maruku.new(maruku_src, options) + if block_given? + # render layout + instance.to_html_document + else + # render template + instance.to_html + end + end + end + + class Base + include Middleman::Maruku + end +end \ No newline at end of file diff --git a/lib/middleman/features/minify_css.rb b/lib/middleman/features/minify_css.rb new file mode 100644 index 00000000..d89bfb85 --- /dev/null +++ b/lib/middleman/features/minify_css.rb @@ -0,0 +1,9 @@ +# Otherwise use YUI +# Fine a way to minify inline/css +class Middleman::Base + configure do + ::Compass.configuration do |config| + config.output_style = :compressed + end + end +end \ No newline at end of file diff --git a/lib/middleman/features/minify_javascript.rb b/lib/middleman/features/minify_javascript.rb new file mode 100644 index 00000000..b1292513 --- /dev/null +++ b/lib/middleman/features/minify_javascript.rb @@ -0,0 +1,35 @@ +require "yui/compressor" + +module Middleman + module Minified + module Javascript + include ::Haml::Filters::Base + def render_with_options(text, options) + compressor = ::YUI::JavaScriptCompressor.new(:munge => true) + data = compressor.compress(text) + <#{data.chomp} +END + end + end + end + + class Builder + alias_method :pre_yui_after_run, :after_run + def after_run + pre_yui_after_run + + compressor = ::YUI::JavaScriptCompressor.new(:munge => true) + Dir[File.join(Middleman::Base.build_dir, Middleman::Base.js_dir, "**", "*.js")].each do |path| + lines = IO.readlines(path) + if lines.length > 1 + compressed_js = compressor.compress(lines.join($/)) + File.open(path, 'w') { |f| f.write(compressed_js) } + say "<%= color('#{"[COMPRESSED]".rjust(12)}', :yellow) %> " + path.gsub(Middleman::Base.build_dir+"/", '') + end + end + end + end if Middleman::Base.environment == "build" +end + +Middleman::Base.supported_formats << "js" \ No newline at end of file diff --git a/lib/middleman/features/relative_assets.rb b/lib/middleman/features/relative_assets.rb new file mode 100644 index 00000000..97959c99 --- /dev/null +++ b/lib/middleman/features/relative_assets.rb @@ -0,0 +1,30 @@ +::Compass.configuration do |config| + config.relative_assets = true +end + +class << Middleman::Base + alias_method :pre_relative_asset_url, :asset_url + def asset_url(path, prefix="", request=nil) + begin + prefix = self.images_dir if prefix == self.http_images_path + rescue + end + + path = pre_relative_asset_url(path, prefix, request) + if path.include?("://") + path + else + path = path[1,path.length-1] if path[0,1] == '/' + request_path = request.path_info.dup + request_path << self.class.index_file if path.match(%r{/$}) + request_path.gsub!(%r{^/}, '') + parts = request_path.split('/') + + if parts.length > 1 + "../" * (parts.length - 1) + path + else + path + end + end + end +end \ No newline at end of file diff --git a/lib/middleman/features/slickmap.rb b/lib/middleman/features/slickmap.rb new file mode 100644 index 00000000..33b8f71e --- /dev/null +++ b/lib/middleman/features/slickmap.rb @@ -0,0 +1,119 @@ +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, []) + + #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 + 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) + 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 + + 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! +end + +__END__ + +@@ sitemap +!!! +%html{ :xmlns => "http://www.w3.org/1999/xhtml" } + %head + %meta{ :content => "text/html; charset=utf-8", "http-equiv" => "Content-type" } + %title Sitemap + %style{ :type => "text/css" } + :sass + @import slickmap.sass + +slickmap + :javascript + window.onload = function() { + document.getElementById('primaryNav').className = "col" + document.querySelectorAll("#primaryNav > li:not(#home)").length; + }; + + %body + .logo + %h1= @project_name || "Sitemap" + - if @project_subtitle + %h2= @project_subtitle + + - if @utility.length > 0 + %ul#utilityNav + - @utility.each do |u| + %li= link_to u, u + + %ul#primaryNav + - sitemap_node(@tree, true) \ No newline at end of file diff --git a/lib/middleman/features/smush_pngs.rb b/lib/middleman/features/smush_pngs.rb new file mode 100644 index 00000000..9c4c9b71 --- /dev/null +++ b/lib/middleman/features/smush_pngs.rb @@ -0,0 +1,58 @@ +require 'json' +require 'open-uri' + +begin + require 'httpclient' +rescue LoadError + puts "httpclient not available. Install it with: gem install httpclient" +end + +module Middleman + module SmushPngs + def self.included(base) + base.supported_formats << "png" + end + + def render_path(file) + if File.extname(file) == ".png" + file = File.join(options.public, file) + optimized = optimized_image_data_for(file) + + begin + raise "Error: got larger" if size(file) < optimized.size + raise "Error: empty file downloaded" if optimized.size < 20 + + optimized + rescue + File.read(file) + end + else + super + end + end + + protected + def size(file) + File.exist?(file) ? File.size(file) : 0 + end + + def optimized_image_data_for(file) + # I leave these urls here, just in case it stops working again... + # url = "http://smush.it/ws.php" # original, redirects to somewhere else.. + url = 'http://ws1.adq.ac4.yahoo.com/ysmush.it/ws.php' + # url = "http://developer.yahoo.com/yslow/smushit/ws.php" # official but does not work + # url = "http://smushit.com/ysmush.it/ws.php" # used at the new page but does not hande uploads + # url = "http://smushit.eperf.vip.ac4.yahoo.com/ysmush.it/ws.php" # used at the new page but does not hande uploads + response = HTTPClient.post url, { 'files[]' => File.new(file) } + response = JSON.parse(response.body.content) + raise "smush.it: #{response['error']}" if response['error'] + image_url = response['dest'] + raise "no dest path found" unless image_url + open(image_url) { |source| source.read() } + end + end + + class Base + include Middleman::SmushPngs + end +end \ No newline at end of file diff --git a/lib/middleman/haml.rb b/lib/middleman/haml.rb new file mode 100644 index 00000000..d5583adb --- /dev/null +++ b/lib/middleman/haml.rb @@ -0,0 +1,69 @@ +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) + if template_exists?(path, :haml) + result = nil + begin + result = haml(path.to_sym, :layout => File.extname(path) != ".xml") + rescue ::Haml::Error => e + result = "Haml Error: #{e}" + result << "
Backtrace: #{e.backtrace.join("\n")}
" + end + result + else + super + end + end + end + + module Helpers + def haml_partial(name, options = {}) + item_name = name.to_sym + counter_name = "#{name}_counter".to_sym + if collection = options.delete(:collection) + collection.enum_for(:each_with_index).collect do |item,index| + haml_partial name, options.merge(:locals => {item_name => item, counter_name => index+1}) + end.join + elsif object = options.delete(:object) + haml_partial name, options.merge(:locals => {item_name => object, counter_name => nil}) + else + haml "_#{name}".to_sym, options.merge(:layout => false) + end + end + end + + module Table + include ::Haml::Filters::Base + + def render(text) + output = '
' + line_num = 0 + text.each_line do |line| + line_num += 1 + next if line.strip.empty? + output << %Q{} + + columns = line.split("|").map { |p| p.strip } + columns.each_with_index do |col, i| + output << %Q{} + end + + output << "" + end + output + "
#{col}
" + end + end + end +end + +class Middleman::Base + include Middleman::Haml::Renderer +end \ No newline at end of file diff --git a/lib/middleman/helpers.rb b/lib/middleman/helpers.rb new file mode 100644 index 00000000..9071ce2c --- /dev/null +++ b/lib/middleman/helpers.rb @@ -0,0 +1,55 @@ +module Middleman + class Base + def self.asset_url(path, prefix="", request=nil) + base_url = File.join(self.http_prefix, prefix) + path.include?("://") ? path : File.join(base_url, path) + end + end + + module Helpers + def page_classes(*additional) + path = request.path_info + path << options.index_file if path.match(%r{/$}) + path.gsub!(%r{^/}, '') + + classes = [] + parts = path.split('.')[0].split('/') + parts.each_with_index { |path, i| classes << parts.first(i+1).join('_') } + + classes << "index" if classes.empty? + classes += additional unless additional.empty? + classes.join(' ') + end + + def asset_url(path, prefix="") + self.class.asset_url(path, prefix, request) + end + + def link_to(title, url="#", params={}) + params.merge!(:href => url) + params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ') + %Q{#{title}} + end + + def image_tag(path, params={}) + params[:alt] ||= "" + prefix = options.http_images_path rescue options.images_dir + params = params.merge(:src => asset_url(path, prefix)) + params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ') + "" + end + + def javascript_include_tag(path, params={}) + params = params.merge(:src => asset_url(path, options.js_dir), :type => "text/javascript") + params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ') + "" + end + + def stylesheet_link_tag(path, params={}) + params[:rel] ||= "stylesheet" + params = params.merge(:href => asset_url(path, options.css_dir), :type => "text/css") + params = params.map { |k,v| %Q{#{k}="#{v}"}}.join(' ') + "" + end + end +end diff --git a/lib/middleman/rack/sprockets+ruby19.rb b/lib/middleman/rack/sprockets+ruby19.rb new file mode 100644 index 00000000..59894983 --- /dev/null +++ b/lib/middleman/rack/sprockets+ruby19.rb @@ -0,0 +1,29 @@ +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/rack/sprockets.rb b/lib/middleman/rack/sprockets.rb new file mode 100644 index 00000000..a9faccae --- /dev/null +++ b/lib/middleman/rack/sprockets.rb @@ -0,0 +1,34 @@ +begin + require 'sprockets' + require 'middleman/rack/sprockets+ruby19' # Sprockets ruby 1.9 duckpunch +rescue LoadError + puts "Sprockets not available. Install it with: gem install sprockets" +end + +module Middleman + module Rack + class Sprockets + def initialize(app, options={}) + @app = app + end + + def call(env) + path = env["PATH_INFO"] + source = File.join(Middleman::Base.views, path) + + if path.match(/\.js$/) && File.exists?(source) + secretary = ::Sprockets::Secretary.new( :root => Middleman::Base.root, + :source_files => [ File.join("views", path) ], + :load_path => [ File.join("public", Middleman::Base.js_dir), + File.join("views", Middleman::Base.js_dir) ]) + + [200, { "Content-Type" => "text/javascript" }, [secretary.concatenation.to_s]] + else + @app.call(env) + end + end + end + end +end + +Middleman::Base.supported_formats << "js" \ No newline at end of file diff --git a/lib/middleman/rack/static.rb b/lib/middleman/rack/static.rb new file mode 100644 index 00000000..69d967a4 --- /dev/null +++ b/lib/middleman/rack/static.rb @@ -0,0 +1,21 @@ +module Middleman + module Rack + class Static + def initialize(app, options={}) + @app = app + root = Middleman::Base.public + @file_server = ::Rack::File.new(root) + end + + def call(env) + path = env["PATH_INFO"] + file_path = File.join(Middleman::Base.public, path) + if path.include?("favicon.ico") || (File.exists?(file_path) && !File.directory?(file_path)) + @file_server.call(env) + else + @app.call(env) + end + end + end + end +end \ No newline at end of file diff --git a/lib/middleman/sass.rb b/lib/middleman/sass.rb new file mode 100644 index 00000000..3bb780c5 --- /dev/null +++ b/lib/middleman/sass.rb @@ -0,0 +1,70 @@ +require "sass" +require 'compass' + +module Middleman + module Sass + def self.included(base) + base.supported_formats << "sass" + end + + def render_path(path) + if template_exists?(path, :sass) + begin + static_version = options.public + request.path_info + send_file(static_version) if File.exists? static_version + + location_of_sass_file = options.environment == "build" ? File.join(options.build_dir, options.css_dir) : "public" + css_filename = File.join(Dir.pwd, location_of_sass_file) + request.path_info + sass(path.to_sym, ::Compass.sass_engine_options.merge({ :css_filename => css_filename })) + rescue Exception => e + sass_exception_string(e) + end + else + super + end + end + + # Handle Sass errors + def sass_exception_string(e) + e_string = "#{e.class}: #{e.message}" + + if e.is_a? ::Sass::SyntaxError + e_string << "\non line #{e.sass_line}" + + if e.sass_filename + e_string << " of #{e.sass_filename}" + + if File.exists?(e.sass_filename) + e_string << "\n\n" + + min = [e.sass_line - 5, 0].max + begin + File.read(e.sass_filename).rstrip.split("\n")[ + min .. e.sass_line + 5 + ].each_with_index do |line, i| + e_string << "#{min + i + 1}: #{line}\n" + end + rescue + e_string << "Couldn't read sass file: #{e.sass_filename}" + end + end + end + end + <set :css_dir, "<%= css_dir -%>"<% end %> +<% if js_dir %>set :js_dir, "<%= js_dir -%>"<% end %> +<% if images_dir %>set :images_dir, "<%= images_dir -%>"<% end %> + +# Helpers +helpers do +end + +# Generic configuration +# enable :slickmap + +# Build-specific configuration +configure :build do + # For example, change the Compass output style for deployment + # enable :minified_css + + # Or use a different image path + # set :http_path, "/Content/images/" + + # Disable cache buster + # disable :cache_buster +end \ No newline at end of file diff --git a/lib/middleman/template/views/index.html.haml b/lib/middleman/template/views/index.html.haml new file mode 100644 index 00000000..7b2bc807 --- /dev/null +++ b/lib/middleman/template/views/index.html.haml @@ -0,0 +1,4 @@ +- content_for :head do + %title Custom head title + +%h1 The Middleman is watching. \ No newline at end of file diff --git a/lib/middleman/template/views/layout.html.haml b/lib/middleman/template/views/layout.html.haml new file mode 100644 index 00000000..f53be024 --- /dev/null +++ b/lib/middleman/template/views/layout.html.haml @@ -0,0 +1,7 @@ +%html + %head + %title The Middleman! + = yield_content :head + + %body + = yield \ No newline at end of file diff --git a/lib/middleman/template/views/stylesheets/site.css.sass b/lib/middleman/template/views/stylesheets/site.css.sass new file mode 100644 index 00000000..7afde1f8 --- /dev/null +++ b/lib/middleman/template/views/stylesheets/site.css.sass @@ -0,0 +1 @@ +@import compass/reset.sass \ No newline at end of file diff --git a/lib/middleman/templater+dynamic_renderer.rb b/lib/middleman/templater+dynamic_renderer.rb new file mode 100644 index 00000000..4f1882a4 --- /dev/null +++ b/lib/middleman/templater+dynamic_renderer.rb @@ -0,0 +1,25 @@ +require 'rack/test' # Use Rack::Test to access Sinatra without starting up a full server + +# Monkey-patch to use a dynamic renderer +class Templater::Actions::File + def identical? + if exists? + return true if File.mtime(source) < File.mtime(destination) + FileUtils.identical?(source, destination) + else + false + end + end +end + +class Templater::Actions::Template + def render + @render_cache ||= begin + # The default render just requests the page over Rack and writes the response + request_path = destination.gsub(File.join(Dir.pwd, Middleman::Base.build_dir), "") + browser = Rack::Test::Session.new(Rack::MockSession.new(Middleman::Base)) + browser.get(request_path) + browser.last_response.body + end + end +end \ No newline at end of file diff --git a/middleman.gemspec b/middleman.gemspec new file mode 100644 index 00000000..82801904 --- /dev/null +++ b/middleman.gemspec @@ -0,0 +1,134 @@ +# Generated by jeweler +# DO NOT EDIT THIS FILE DIRECTLY +# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{middleman} + s.version = "0.9.20" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Thomas Reynolds"] + s.date = %q{2009-10-22} + s.email = %q{tdreyno@gmail.com} + s.executables = ["mm-init", "mm-build", "mm-server"] + s.extra_rdoc_files = [ + "LICENSE", + "README.rdoc" + ] + s.files = [ + ".document", + ".gitignore", + "LICENSE", + "README.rdoc", + "Rakefile", + "VERSION", + "bin/mm-build", + "bin/mm-init", + "bin/mm-server", + "deps.rip", + "lib/middleman.rb", + "lib/middleman/base.rb", + "lib/middleman/builder.rb", + "lib/middleman/config.ru", + "lib/middleman/features/cache_buster.rb", + "lib/middleman/features/compass.rb", + "lib/middleman/features/growl.rb", + "lib/middleman/features/maruku.rb", + "lib/middleman/features/minify_css.rb", + "lib/middleman/features/minify_javascript.rb", + "lib/middleman/features/relative_assets.rb", + "lib/middleman/features/slickmap.rb", + "lib/middleman/features/smush_pngs.rb", + "lib/middleman/haml.rb", + "lib/middleman/helpers.rb", + "lib/middleman/rack/sprockets+ruby19.rb", + "lib/middleman/rack/sprockets.rb", + "lib/middleman/rack/static.rb", + "lib/middleman/sass.rb", + "lib/middleman/template/init.rbt", + "lib/middleman/template/views/index.html.haml", + "lib/middleman/template/views/layout.html.haml", + "lib/middleman/template/views/stylesheets/site.css.sass", + "lib/middleman/templater+dynamic_renderer.rb", + "middleman.gemspec", + "spec/builder_spec.rb", + "spec/cache_buster_spec.rb", + "spec/fixtures/sample/init.rb", + "spec/fixtures/sample/public/javascripts/to-be-included.js", + "spec/fixtures/sample/public/static.html", + "spec/fixtures/sample/public/stylesheets/static.css", + "spec/fixtures/sample/views/_partial.haml", + "spec/fixtures/sample/views/index.html.haml", + "spec/fixtures/sample/views/inline-js.html.haml", + "spec/fixtures/sample/views/javascripts/empty-with-include.js", + "spec/fixtures/sample/views/layout.haml", + "spec/fixtures/sample/views/maruku.html.maruku", + "spec/fixtures/sample/views/services/index.html.haml", + "spec/fixtures/sample/views/stylesheets/site.css.sass", + "spec/generator_spec.rb", + "spec/relative_assets_spec.rb", + "spec/spec_helper.rb" + ] + s.homepage = %q{http://wiki.github.com/tdreyno/middleman} + s.rdoc_options = ["--charset=UTF-8"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{middleman} + s.rubygems_version = %q{1.3.5} + s.summary = %q{A static site generator utilizing Haml, Sass and providing YUI compression and cache busting} + s.test_files = [ + "spec/builder_spec.rb", + "spec/cache_buster_spec.rb", + "spec/fixtures/sample/init.rb", + "spec/generator_spec.rb", + "spec/relative_assets_spec.rb", + "spec/spec_helper.rb" + ] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 2.1.0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + else + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 2.1.0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + end + else + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 2.1.0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + end +end + diff --git a/spec/builder_spec.rb b/spec/builder_spec.rb new file mode 100644 index 00000000..66d3b1ee --- /dev/null +++ b/spec/builder_spec.rb @@ -0,0 +1,60 @@ +require 'fileutils' + +describe "Builder" do + def project_file(*parts) + File.expand_path(File.join(File.dirname(__FILE__), "..", *parts)) + end + + before :all do + @root_dir = project_file("spec", "fixtures", "sample") + end + + before :each do + build_cmd = project_file("bin", "mm-build") + `cd #{@root_dir} && #{build_cmd}` + end + + after :each do + FileUtils.rm_rf(File.join(@root_dir, "build")) + end + + it "should build haml files" do + File.exists?("#{@root_dir}/build/index.html").should be_true + File.read("#{@root_dir}/build/index.html").should include("

Welcome

") + end + + xit "should build maruku files" do + File.exists?("#{@root_dir}/build/maruku.html").should be_true + File.read("#{@root_dir}/build/maruku.html").should include("

Hello Maruku

") + end + + it "should build static files" do + File.exists?("#{@root_dir}/build/static.html").should be_true + File.read("#{@root_dir}/build/static.html").should include("Static, no code!") + end + + it "should build subdirectory files" do + File.exists?("#{@root_dir}/build/services/index.html").should be_true + end + + it "should build sass files" do + File.exists?("#{@root_dir}/build/stylesheets/site.css").should be_true + File.read("#{@root_dir}/build/stylesheets/site.css").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 + + it "should not build partial files" do + File.exists?("#{@root_dir}/build/_partial.html").should be_false + end + + it "should minify inline javascript" do + File.readlines("#{@root_dir}/build/inline-js.html").length.should == 9 + end + + it "should combine javascript" do + File.read("#{@root_dir}/build/javascripts/empty-with-include.js").should include("combo") + end +end \ No newline at end of file diff --git a/spec/cache_buster_spec.rb b/spec/cache_buster_spec.rb new file mode 100644 index 00000000..a92a63fc --- /dev/null +++ b/spec/cache_buster_spec.rb @@ -0,0 +1,18 @@ +require File.join(File.dirname(__FILE__), "spec_helper") + +base = ::Middleman::Base +base.set :root, File.join(File.dirname(__FILE__), "fixtures", "sample") + +describe "Cache Buster Feature" do + it "should not append query string if off" do + base.disable :cache_buster + base.new + base.asset_url("stylesheets/static.css").should_not include("?") + end + + it "should append query string if on" do + base.enable :cache_buster + base.new + base.asset_url("stylesheets/static.css").should include("?") + end +end \ No newline at end of file diff --git a/spec/fixtures/sample/init.rb b/spec/fixtures/sample/init.rb new file mode 100644 index 00000000..41a78066 --- /dev/null +++ b/spec/fixtures/sample/init.rb @@ -0,0 +1 @@ +enable :maruku \ No newline at end of file diff --git a/spec/fixtures/sample/public/javascripts/to-be-included.js b/spec/fixtures/sample/public/javascripts/to-be-included.js new file mode 100644 index 00000000..f90b7eb8 --- /dev/null +++ b/spec/fixtures/sample/public/javascripts/to-be-included.js @@ -0,0 +1 @@ +function() { return "combo"; }; \ No newline at end of file diff --git a/spec/fixtures/sample/public/static.html b/spec/fixtures/sample/public/static.html new file mode 100644 index 00000000..7e50df4e --- /dev/null +++ b/spec/fixtures/sample/public/static.html @@ -0,0 +1 @@ +Static, no code! \ No newline at end of file diff --git a/spec/fixtures/sample/public/stylesheets/static.css b/spec/fixtures/sample/public/stylesheets/static.css new file mode 100644 index 00000000..536410d1 --- /dev/null +++ b/spec/fixtures/sample/public/stylesheets/static.css @@ -0,0 +1,2 @@ +body { + font-size: 12px; } \ No newline at end of file diff --git a/spec/fixtures/sample/views/_partial.haml b/spec/fixtures/sample/views/_partial.haml new file mode 100644 index 00000000..a46a3dbf --- /dev/null +++ b/spec/fixtures/sample/views/_partial.haml @@ -0,0 +1 @@ +%p Test diff --git a/spec/fixtures/sample/views/index.html.haml b/spec/fixtures/sample/views/index.html.haml new file mode 100644 index 00000000..0582dd93 --- /dev/null +++ b/spec/fixtures/sample/views/index.html.haml @@ -0,0 +1 @@ +%h1 Welcome \ No newline at end of file diff --git a/spec/fixtures/sample/views/inline-js.html.haml b/spec/fixtures/sample/views/inline-js.html.haml new file mode 100644 index 00000000..27d3ca64 --- /dev/null +++ b/spec/fixtures/sample/views/inline-js.html.haml @@ -0,0 +1,7 @@ +:javascript + ;(function() { + this; + should(); + all.be(); + on = { one: line }; + }); \ No newline at end of file diff --git a/spec/fixtures/sample/views/javascripts/empty-with-include.js b/spec/fixtures/sample/views/javascripts/empty-with-include.js new file mode 100644 index 00000000..5b2bea44 --- /dev/null +++ b/spec/fixtures/sample/views/javascripts/empty-with-include.js @@ -0,0 +1 @@ +//= require \ No newline at end of file diff --git a/spec/fixtures/sample/views/layout.haml b/spec/fixtures/sample/views/layout.haml new file mode 100644 index 00000000..4396e77c --- /dev/null +++ b/spec/fixtures/sample/views/layout.haml @@ -0,0 +1,6 @@ +%html + %head + %link{ :href => "/stylesheets/site.css", :rel => "stylesheet", :type => "text/css" } + %title My Sample Site + %body + = yield \ No newline at end of file diff --git a/spec/fixtures/sample/views/maruku.html.maruku b/spec/fixtures/sample/views/maruku.html.maruku new file mode 100644 index 00000000..9eab2091 --- /dev/null +++ b/spec/fixtures/sample/views/maruku.html.maruku @@ -0,0 +1 @@ +# Hello Maruku {.header} \ No newline at end of file diff --git a/spec/fixtures/sample/views/services/index.html.haml b/spec/fixtures/sample/views/services/index.html.haml new file mode 100644 index 00000000..bb6a9fca --- /dev/null +++ b/spec/fixtures/sample/views/services/index.html.haml @@ -0,0 +1 @@ +%h2 Services \ No newline at end of file diff --git a/spec/fixtures/sample/views/stylesheets/site.css.sass b/spec/fixtures/sample/views/stylesheets/site.css.sass new file mode 100644 index 00000000..7afde1f8 --- /dev/null +++ b/spec/fixtures/sample/views/stylesheets/site.css.sass @@ -0,0 +1 @@ +@import compass/reset.sass \ No newline at end of file diff --git a/spec/generator_spec.rb b/spec/generator_spec.rb new file mode 100644 index 00000000..2070c43e --- /dev/null +++ b/spec/generator_spec.rb @@ -0,0 +1,34 @@ +require 'fileutils' + +describe "Generator" do + def project_file(*parts) + File.expand_path(File.join(File.dirname(__FILE__), "..", *parts)) + end + + before :all do + @root_dir = project_file("spec", "fixtures", "generator-test") + end + + before :each do + init_cmd = project_file("bin", "mm-init") + `cd #{File.dirname(@root_dir)} && #{init_cmd} #{File.basename(@root_dir)}` + end + + after :each do + FileUtils.rm_rf(@root_dir) + end + + it "should copy template files" do + template_dir = project_file("lib", "template", "**/*") + Dir[template_dir].each do |f| + next if File.directory?(f) + File.exists?("#{@root_dir}/#{f.split('template/')[1]}").should be_true + end + end + + it "should create empty directories" do + %w(views/stylesheets public/stylesheets public/javascripts public/images).each do |d| + File.exists?("#{@root_dir}/#{d}").should be_true + end + end +end \ No newline at end of file diff --git a/spec/relative_assets_spec.rb b/spec/relative_assets_spec.rb new file mode 100644 index 00000000..622dabf1 --- /dev/null +++ b/spec/relative_assets_spec.rb @@ -0,0 +1,28 @@ +# require File.join(File.dirname(__FILE__), "spec_helper") +# +# base = ::Middleman::Base +# base.set :root, File.join(File.dirname(__FILE__), "fixtures", "sample") +# +# describe "Relative Assets Feature" do +# before do +# base.disable :relative_assets +# base.init! +# @app = base.new +# end +# +# it "should not contain ../ if off" do +# @app.asset_url("stylesheets/static.css").should_not include("?") +# end +# end +# +# describe "Relative Assets Feature" do +# before do +# base.enable :relative_assets +# base.init! +# @app = base.new +# end +# +# it "should contain ../ if on" do +# @app.asset_url("stylesheets/static.css").should include("?") +# end +# end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 00000000..cfbd9d72 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,10 @@ +require 'rubygems' +require 'spec' + +$LOAD_PATH.unshift(File.dirname(__FILE__)) +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) +require 'middleman' + +Spec::Runner.configure do |config| + +end