Merge branch 'master' of git://github.com/tdreyno/middleman

This commit is contained in:
Eric Skogen 2011-12-22 16:27:02 -06:00
commit b9b2c2511c
50 changed files with 812 additions and 412 deletions

1
.gitignore vendored
View file

@ -13,3 +13,4 @@ fixtures/generator-test
build
doc
.yardoc
tmp

View file

@ -1,7 +1,11 @@
lib/**/*.rb
--exclude lib/middleman/vendor
--exclude lib/middleman/vendor/
--exclude lib/middleman/extensions/automatic_image_sizes/fastimage.rb
--exclude lib/middleman/extensions/minify_css/cssmin.rb
--exclude lib/middleman/step_definitions
--exclude lib/middleman/step_definitions.rb
--exclude lib/middleman/templates/default/
--exclude lib/middleman/templates/html5/
--exclude lib/middleman/templates/mobile/
--exclude lib/middleman/templates/shared/
--no-private
--hide-void-return

View file

@ -10,9 +10,13 @@
* Sitemap object representing the known world
* FileWatcher proxies file change events
* Unified callback solution
* Removed Slim and Maruku from base install. Will need to be installed and required by the user (in - config.rb)
* Removed Slim from base install. Will need to be installed and required by the user (in - config.rb)
* Activate mobile html5boilerplate template
* Update to Redcarpet for Markdown (breaks Haml :markdown filter)
* Return correct exit codes (0 for success, 1 for failure) from CLI
* Yard code docs: http://rubydoc.info/github/tdreyno/middleman
* config.rb and extensions can add command-line commands
* Nested layouts using `wrap_layout` helper
2.0.14
====

View file

@ -9,7 +9,7 @@ require 'rubygems'
module Middleman
module ProjectLocator
class << self
def locate_middleman_root!(args)
def locate_middleman_root!
cwd = Dir.pwd
if !in_middleman_project? && !in_middleman_project_subdirectory?
@ -18,14 +18,14 @@ module Middleman
end
if in_middleman_project?
did_locate_middleman_project(cwd, args)
did_locate_middleman_project(cwd)
return
end
Dir.chdir("..") do
# Recurse in a chdir block: if the search fails we want to be sure
# the application is generated in the original working directory.
locate_middleman_root!(args) unless cwd == Dir.pwd
locate_middleman_root! unless cwd == Dir.pwd
end
rescue SystemCallError
# could not chdir, no problem just return
@ -39,39 +39,27 @@ module Middleman
File.exists?(File.join(path, 'config.rb')) || !path.root? && in_middleman_project_subdirectory?(path.parent)
end
def did_locate_middleman_project(path, args)
def did_locate_middleman_project(path)
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('Gemfile', path)
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
start_cli!(args)
start_cli!
end
def start_cli!(args)
def start_cli!
require 'middleman'
Middleman::CLI.start(args)
Middleman::Cli::Base.start
end
end
end
end
args = ARGV.dup
ARGV << "server" if ARGV.length < 1
ARG_ALIASES = {
"s" => "server",
"b" => "build",
"i" => "init",
"new" => "init",
"n" => "init"
}
if ARG_ALIASES.has_key?(args[0])
args[0] = ARG_ALIASES[args[0]]
end
if args.length < 1 || %w(server build migrate).include?(args.first)
Middleman::ProjectLocator.locate_middleman_root!(args)
if %w(server build migrate).include?(ARGV)
Middleman::ProjectLocator.locate_middleman_root!
else
Middleman::ProjectLocator.start_cli!(args)
Middleman::ProjectLocator.start_cli!
end

View file

@ -0,0 +1,5 @@
Feature: Allow config.rb and extensions to add CLI commands
Scenario: Test 3rd Party Command
Given a fixture app "3rd-party-command"
When I run `middleman hello`
Then the output should contain "Hello World"

View file

@ -2,33 +2,51 @@ Feature: Builder
In order to output static html and css for delivery
Scenario: Checking built folder for content
Given a built app at "test-app"
Then "index.html" should exist at "test-app" and include "Comment in layout"
Then "javascripts/coffee_test.js" should exist at "test-app" and include "Array.prototype.slice"
Then "index.html" should exist at "test-app" and include "<h1>Welcome</h1>"
Then "static.html" should exist at "test-app" and include "Static, no code!"
Then "services/index.html" should exist at "test-app" and include "Services"
Then "stylesheets/site.css" should exist at "test-app" and include "html, body, div, span"
Then "stylesheets/site_scss.css" should exist at "test-app" and include "html, body, div, span"
Then "stylesheets/static.css" should exist at "test-app" and include "body"
Then "_partial.html" should not exist at "test-app"
Then "spaces in file.html" should exist at "test-app" and include "spaces"
Then "images/blank.gif" should exist at "test-app"
Then "images/Read me (example).txt" should exist at "test-app"
Then "images/Child folder/regular_file(example).txt" should exist at "test-app"
Then ".htaccess" should exist at "test-app"
Then the last exit code should be "0"
Given a successfully built app at "test-app"
When I cd to "build"
Then the following files should exist:
| index.html |
| javascripts/coffee_test.js |
| static.html |
| services/index.html |
| stylesheets/site.css |
| stylesheets/site_scss.css |
| stylesheets/static.css |
| spaces in file.html |
| images/blank.gif |
| images/Read me (example).txt |
| images/Child folder/regular_file(example).txt |
| .htaccess |
Then the following files should not exist:
| _partial |
| _liquid_partial |
| layout |
| layouts/custom |
| layouts/content_for |
And the file "index.html" should contain "Comment in layout"
And the file "index.html" should contain "<h1>Welcome</h1>"
And the file "javascripts/coffee_test.js" should contain "Array.prototype.slice"
And the file "static.html" should contain "Static, no code!"
And the file "services/index.html" should contain "Services"
And the file "stylesheets/site.css" should contain "html, body, div, span"
And the file "stylesheets/site_scss.css" should contain "html, body, div, span"
And the file "stylesheets/static.css" should contain "body"
And the file "spaces in file.html" should contain "spaces"
Scenario: Build glob
Given a built app at "glob-app" with flags "--glob '*.css'"
Then "stylesheets/site.css" should exist at "glob-app" and include "html"
Then "index.html" should not exist at "glob-app"
Then the last exit code should be "0"
Given a successfully built app at "glob-app" with flags "--glob '*.css'"
When I cd to "build"
Then the following files should not exist:
| index.html |
Then the following files should exist:
| stylesheets/site.css |
Scenario: Build with errors
Given a built app at "build-with-errors-app"
Then the last exit code should be "1"
Then the exit status should be 1
# Scenario: Force relative assets
# Given a built app at "relative-app" with flags "--relative"
# Then "stylesheets/relative_assets.css" should exist at "relative-app" and include "../"
Scenario: Build alias (b)
Given a fixture app "test-app"
When I run `middleman b`
Then was successfully built

View file

@ -9,7 +9,11 @@ Feature: Templates should be chainable
And I should see "Sup</h3>"
Scenario: Build chained template
Given a built app at "chained-app"
Then "index.html" should exist at "chained-app" and include "Title</h1>"
Then "index.html" should exist at "chained-app" and include "Subtitle</h2>"
Then "index.html" should exist at "chained-app" and include "Sup</h3>"
Given a successfully built app at "chained-app"
When I cd to "build"
Then the following files should exist:
| index.html |
And the file "index.html" should contain "Title</h1>"
And the file "index.html" should contain "Subtitle</h2>"
And the file "index.html" should contain "Sup</h3>"

View file

@ -1,20 +1,31 @@
Feature: Build Clean
Scenario: Build and Clean an app
Given app "clean-app" is using config "empty"
And a built app at "clean-app"
Given a fixture app "clean-app"
And app "clean-app" is using config "empty"
And a successfully built app at "clean-app"
And app "clean-app" is using config "complications"
And a built app at "clean-app" with flags "--clean"
Then "should_be_ignored.html" should not exist at "clean-app"
And "should_be_ignored2.html" should not exist at "clean-app"
And "should_be_ignored3.html" should not exist at "clean-app"
Given a successfully built app at "clean-app" with flags "--clean"
When I cd to "build"
Then the following files should not exist:
| should_be_ignored.html |
| should_be_ignored2.html |
| should_be_ignored3.html |
And the file "index.html" should contain "Comment in layout"
Scenario: Clean an app with directory indexes
Given a built app at "clean-dir-app"
Then "about/index.html" should exist at "clean-dir-app"
Given a built app at "clean-dir-app" with flags "--clean"
Then "about/index.html" should exist at "clean-dir-app"
Then cleanup built app at "clean-dir-app"
Given a successfully built app at "clean-dir-app"
When I cd to "build"
Then the following files should exist:
| about/index.html |
Given a successfully built app at "clean-dir-app" with flags "--clean"
When I cd to "build"
Then the following files should exist:
| about/index.html |
Scenario: Clean build an app that's never been built
Given a built app at "clean-dir-app" with flags "--clean"
Then "about/index.html" should exist at "clean-dir-app"
Given a successfully built app at "clean-dir-app" with flags "--clean"
When I cd to "build"
Then the following files should exist:
| about/index.html |

121
features/cli.feature Normal file
View file

@ -0,0 +1,121 @@
Feature: Middleman CLI
Scenario: Create a new project
When I run `middleman init MY_PROJECT`
Then a directory named "MY_PROJECT" should exist
When I cd to "MY_PROJECT"
Then the following files should exist:
| config.rb |
Then the following files should not exist:
| config.ru |
| Gemfile |
Then a directory named "source" should exist
When I cd to "source"
Then the following files should exist:
| index.html.erb |
| layout.erb |
| stylesheets/site.css.scss |
Scenario: Create a new project (alias i)
When I run `middleman i MY_PROJECT`
Then a directory named "MY_PROJECT" should exist
Scenario: Create a new project (alias i)
When I run `middleman new MY_PROJECT`
Then a directory named "MY_PROJECT" should exist
Scenario: Create a new project (alias i)
When I run `middleman n MY_PROJECT`
Then a directory named "MY_PROJECT" should exist
Scenario: Create a new project with Rack
When I run `middleman init MY_PROJECT --rack`
Then a directory named "MY_PROJECT" should exist
When I cd to "MY_PROJECT"
Then the following files should exist:
| config.rb |
| config.ru |
Then the following files should not exist:
| Gemfile |
Scenario: Create a new project with Bundler
When I run `middleman init MY_PROJECT --bundler`
Then a directory named "MY_PROJECT" should exist
When I cd to "MY_PROJECT"
Then the following files should exist:
| config.rb |
| Gemfile |
Then the following files should not exist:
| config.ru |
Scenario: Create a new HTML5 project
When I run `middleman init MY_PROJECT --template=html5`
Then a directory named "MY_PROJECT" should exist
When I cd to "MY_PROJECT"
Then the following files should exist:
| config.rb |
Then the following files should not exist:
| config.ru |
| Gemfile |
Then a directory named "source" should exist
When I cd to "source"
Then the following files should exist:
| index.html |
| humans.txt |
| js/script.js |
Scenario: Create a new HTML5 project with Rack
When I run `middleman init MY_PROJECT --rack --template=html5`
Then a directory named "MY_PROJECT" should exist
When I cd to "MY_PROJECT"
Then the following files should exist:
| config.rb |
| config.ru |
Then the following files should not exist:
| Gemfile |
Scenario: Create a new HTML5 project with Bundler
When I run `middleman init MY_PROJECT --bundler --template=html5`
Then a directory named "MY_PROJECT" should exist
When I cd to "MY_PROJECT"
Then the following files should exist:
| config.rb |
| Gemfile |
Then the following files should not exist:
| config.ru |
Scenario: Create a new Mobile HTML5 project
When I run `middleman init MY_PROJECT --template=mobile`
Then a directory named "MY_PROJECT" should exist
When I cd to "MY_PROJECT"
Then the following files should exist:
| config.rb |
Then the following files should not exist:
| config.ru |
| Gemfile |
Then a directory named "source" should exist
When I cd to "source"
Then the following files should exist:
| index.html |
| humans.txt |
| js/libs/respond.min.js |
Scenario: Create a new Mobile HTML5 project with Rack
When I run `middleman init MY_PROJECT --rack --template=mobile`
Then a directory named "MY_PROJECT" should exist
When I cd to "MY_PROJECT"
Then the following files should exist:
| config.rb |
| config.ru |
Then the following files should not exist:
| Gemfile |
Scenario: Create a new Mobile HTML5 project with Bundler
When I run `middleman init MY_PROJECT --bundler --template=mobile`
Then a directory named "MY_PROJECT" should exist
When I cd to "MY_PROJECT"
Then the following files should exist:
| config.rb |
| Gemfile |
Then the following files should not exist:
| config.ru |

View file

@ -14,4 +14,4 @@ Feature: Support coffee-script
Scenario: Rendering broken coffee
Given the Server is running at "test-app"
When I go to "/javascripts/broken-coffee.js"
Then I should see "ProgramError"
Then I should see "Error"

View file

@ -1,8 +1,11 @@
Feature: Custom Layout Engine
Scenario: Checking built folder for content
Given a built app at "custom-layout-app"
Then "index.html" should exist at "custom-layout-app" and include "Comment in layout"
Given a successfully built app at "custom-layout-app"
When I cd to "build"
Then the following files should exist:
| index.html |
And the file "index.html" should contain "Comment in layout"
Scenario: Checking server for content
Given the Server is running at "test-app"

View file

@ -2,16 +2,23 @@ Feature: Directory Index
In order output Apache-friendly directories and indexes
Scenario: Checking built folder for content
Given a built app at "indexable-app"
Then "needs_index/index.html" should exist at "indexable-app" and include "Indexable"
Then "a_folder/needs_index/index.html" should exist at "indexable-app" and include "Indexable"
Then "leave_me_alone.html" should exist at "indexable-app" and include "Stay away"
Then "regular/index.html" should exist at "indexable-app" and include "Regular"
Then "regular/index/index.html" should not exist at "indexable-app"
Then "needs_index.html" should not exist at "indexable-app"
Then "a_folder/needs_index.html" should not exist at "indexable-app"
Then "leave_me_alone/index.html" should not exist at "indexable-app"
Then ".htaccess" should exist at "indexable-app"
Given a successfully built app at "indexable-app"
When I cd to "build"
Then the following files should exist:
| needs_index/index.html |
| a_folder/needs_index/index.html |
| leave_me_alone.html |
| regular/index.html |
| .htaccess |
Then the following files should not exist:
| egular/index/index.html |
| needs_index.html |
| a_folder/needs_index.html |
| leave_me_alone/index.html |
And the file "needs_index/index.html" should contain "Indexable"
And the file "a_folder/needs_index/index.html" should contain "Indexable"
And the file "leave_me_alone.html" should contain "Stay away"
And the file "regular/index.html" should contain "Regular"
Scenario: Preview normal file
Given the Server is running at "indexable-app"

View file

@ -2,14 +2,17 @@ Feature: Dynamic Pages
In order to use a single view to generate multiple output files
Scenario: Checking built folder for content
Given a built app at "test-app"
Then "fake.html" should exist at "test-app" and include "I am real"
Then "fake/one.html" should exist at "test-app" and include "I am real: one"
Then "fake/two.html" should exist at "test-app" and include "I am real: two"
Then "target_ignore.html" should exist at "test-app" and include "Ignore me"
Then "should_be_ignored.html" should not exist at "test-app"
Then "should_be_ignored2.html" should not exist at "test-app"
Then "should_be_ignored3.html" should not exist at "test-app"
Given a successfully built app at "test-app"
When I cd to "build"
Then the following files should exist:
| fake.html |
| fake/one.html |
| fake/two.html |
| target_ignore.html |
Then the following files should not exist:
| should_be_ignored.html |
| should_be_ignored2.html |
| should_be_ignored3.html |
Scenario: Preview basic proxy
Given the Server is running at "test-app"

View file

@ -1,8 +1,11 @@
Feature: Web Fonts
Scenario: Checking built folder for content
Given a built app at "fonts-app"
Then "stylesheets/fonts.css" should exist at "fonts-app" and include "/fonts/StMarie-Thin.otf"
Given a successfully built app at "fonts-app"
When I cd to "build"
Then the following files should exist:
| stylesheets/fonts.css |
And the file "stylesheets/fonts.css" should contain "/fonts/StMarie-Thin.otf"
Scenario: Rendering scss
Given the Server is running at "fonts-app"

View file

@ -0,0 +1,9 @@
Feature: Allow nesting of layouts
Scenario: A page uses an inner layout when uses an outer layout
Given the Server is running at "nested-layout-app"
When I go to "/index.html"
Then I should see "Template"
And I should see "Inner"
And I should see "Outer"
And I should see "Master"

View file

@ -21,8 +21,10 @@ Feature: Sprockets
Then I should see "Hello One"
Scenario: Multiple engine files should build correctly
Given a built app at "test-app"
Then "javascripts/multiple_engines.js" should exist at "test-app" and include "Hello One"
Given a successfully built app at "test-app"
When I cd to "build"
Then a file named "javascripts/multiple_engines.js" should exist
And the file "javascripts/multiple_engines.js" should contain "Hello One"
Scenario: Sprockets CSS require //require
Given the Server is running at "test-app"

View file

@ -0,0 +1,10 @@
class HelloWorld < Thor
default_task :say_hi
desc "hello", "Say hello"
def say_hi
puts "Hello World"
end
end
Middleman::Cli::Base.register(HelloWorld, :hello, "hello", "Say hello")

View file

@ -0,0 +1 @@
set :layout, :inner

View file

@ -0,0 +1 @@
Template

View file

@ -0,0 +1,4 @@
<% wrap_layout :outer do %>
Inner
<%= yield %>
<% end %>

View file

@ -0,0 +1,2 @@
Master
<%= yield %>

View file

@ -0,0 +1,4 @@
<% wrap_layout :master do %>
Outer
<%= yield %>
<% end %>

View file

@ -1,17 +1,27 @@
require "rbconfig"
# Setup our load paths
libdir = File.dirname(__FILE__)
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
# Top-level Middleman object
module Middleman
WINDOWS = !!(RUBY_PLATFORM =~ /(mingw|bccwin|wince|mswin32)/i)
JRUBY = !!(RbConfig::CONFIG["RUBY_INSTALL_NAME"] =~ /^jruby/i)
# Auto-load modules on-demand
autoload :Base, "middleman/base"
autoload :Cache, "middleman/cache"
autoload :Builder, "middleman/builder"
autoload :CLI, "middleman/cli"
autoload :Templates, "middleman/templates"
autoload :Guard, "middleman/guard"
module Cli
autoload :Base, "middleman/cli"
autoload :Build, "middleman/cli/build"
autoload :Init, "middleman/cli/init"
autoload :Server, "middleman/cli/server"
end
# Custom Renderers
module Renderers
autoload :Haml, "middleman/renderers/haml"
@ -156,12 +166,6 @@ module Middleman
class << self
# Where to look for custom templates
# @returns [String]
def templates_path
File.join(File.expand_path("~/"), ".middleman")
end
# Automatically load extensions from available RubyGems
# which contain the EXTENSION_FILE
#
@ -225,10 +229,13 @@ module Middleman
app_class = options[:app] ||= ::Middleman.server.inst
opts[:app] = app_class
opts[:server] = 'thin'
# require "thin"
# ::Thin::Logging.silent = true if options[:debug] != "true"
opts[:server] = if ::Middleman::JRUBY
'webrick' # Maybe Kirk?
else
require "thin"
::Thin::Logging.silent = !options[:is_logging]
'thin'
end
server = ::Rack::Server.new(opts)
server.start

View file

@ -91,6 +91,7 @@ class Middleman::Base
# Use Rack middleware
#
# @param [Class] Middleware
# @return [void]
def use(middleware, *args, &block)
@middleware ||= []
@middleware << [middleware, args, block]
@ -99,6 +100,7 @@ class Middleman::Base
# Add Rack App mapped to specific path
#
# @param [String] Path to map
# @return [void]
def map(map, &block)
@mappings ||= []
@mappings << [map, block]
@ -106,6 +108,7 @@ class Middleman::Base
# Mix-in helper methods. Accepts either a list of Modules
# and/or a block to be evaluated
# @return [void]
def helpers(*extensions, &block)
class_eval(&block) if block_given?
include(*extensions) if extensions.any?
@ -123,6 +126,7 @@ class Middleman::Base
#
# @param [Symbol] Unique key name
# @param Default value
# @return [void]
def set(key, value)
@defaults ||= {}
@defaults[key] = value
@ -133,6 +137,7 @@ class Middleman::Base
#
# @param [Symbol] Name of the attribue
# @param Attribute value
# @return [void]
def set(key, value=nil, &block)
setter = "#{key}=".to_sym
self.class.send(:attr_accessor, key) if !respond_to?(setter)
@ -263,6 +268,10 @@ class Middleman::Base
@_current_path
end
# Set the current path
#
# @param [String] path The new current path
# @return [void]
def current_path=(path)
@_current_path = path
@request = Thor::CoreExt::HashWithIndifferentAccess.new({ :path => path })
@ -295,14 +304,7 @@ class Middleman::Base
def self.cache
@_cache ||= ::Middleman::Cache.new
end
# Cache accessor for instance, simply forwards to class
#
# @private
# @return [Middleman::Cache] The cache
def cache
self.class.cache
end
delegate :cache, :to => :"self.class"
# Rack env
attr :env
@ -423,7 +425,7 @@ class Middleman::Base
# Expand a path to include the index file if it's a directory
#
# @private
# @param [String] Request path
# @param [String] path Request path
# @return [String] Path with index file if necessary
def full_path(path)
cache.fetch(:full_path, path) do
@ -437,8 +439,9 @@ class Middleman::Base
# Add a new mime-type for a specific extension
#
# @param [Symbol] File extension
# @param [String] Mime type
# @param [Symbol] type File extension
# @param [String] value Mime type
# @return [void]
def mime_type(type, value=nil)
return type if type.nil? || type.to_s.include?('/')
type = ".#{type}" unless type.to_s[0] == ?.
@ -455,24 +458,11 @@ protected
@res.finish
end
# Set helpers at the class level
def helpers(*extensions, &block)
self.class.helpers(*extensions, &block)
end
# Set middleware at the class level
def use(middleware, *args, &block)
self.class.use(middleware, *args, &block)
end
# Set mapped rack app at the class level
def map(map, &block)
self.class.map(map, &block)
end
delegate :helpers, :use, :map, :to => :"self.class"
# Immediately send static file
#
# @param [String] File to send
# @param [String] path File to send
def send_file(path)
extension = File.extname(path)
matched_mime = mime_type(extension)
@ -488,7 +478,9 @@ protected
# Set the content type for the current request
#
# @param [String] Content type
# @param [String] type Content type
# @param [Hash] params
# @return [void]
def content_type(type = nil, params={})
return res['Content-Type'] unless type
default = params.delete :default

View file

@ -1,123 +1,47 @@
require 'thor'
require "thor/group"
module Middleman
class CLI < Thor
include Thor::Actions
check_unknown_options!
default_task :server
class_option "help",
:type => :boolean,
:default => false,
:aliases => "-h"
def initialize(*)
super
help_check if options[:help]
end
desc "init NAME [options]", "Create new project NAME"
available_templates = Middleman::Templates.registered.keys.join(", ")
method_option "template",
:aliases => "-T",
:default => "default",
:desc => "Use a project template: #{available_templates}"
method_option "css_dir",
:default => "stylesheets",
:desc => 'The path to the css files'
method_option "js_dir",
:default => "javascripts",
:desc => 'The path to the javascript files'
method_option "images_dir",
:default => "images",
:desc => 'The path to the image files'
method_option "rack",
:type => :boolean,
:default => false,
:desc => 'Include a config.ru file'
method_option "bundler",
:type => :boolean,
:default => false,
:desc => 'Create a Gemfile and use Bundler to manage gems'
def init(name)
key = options[:template].to_sym
unless Middleman::Templates.registered.has_key?(key)
raise Thor::Error.new "Unknown project template '#{key}'"
end
thor_group = Middleman::Templates.registered[key]
thor_group.new([name], options).invoke_all
end
desc "server [options]", "Start the preview server"
method_option "environment",
:aliases => "-e",
:default => ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development',
:desc => "The environment Middleman will run under"
method_option :host,
:type => :string,
:aliases => "-h",
# :required => true,
:default => "0.0.0.0",
:desc => "Bind to HOST address"
method_option "port",
:aliases => "-p",
:default => "4567",
:desc => "The port Middleman will listen on"
method_option "debug",
:type => :boolean,
:default => false,
:desc => 'Print debug messages'
def server
params = {
:port => options["port"],
:host => options["host"],
:environment => options["environment"],
:debug => options["debug"]
}
puts "== The Middleman is loading"
Middleman::Guard.start(params)
end
desc "build", "Builds the static site for deployment"
method_option :relative,
:type => :boolean,
:aliases => "-r",
:default => false,
:desc => 'Force relative urls'
method_option :clean,
:type => :boolean,
:aliases => "-c",
:default => false,
:desc => 'Removes orpahand files or directories from build'
method_option :glob,
:type => :string,
:aliases => "-g",
:default => nil,
:desc => 'Build a subset of the project'
def build
thor_group = Middleman::Builder.new([], options).invoke_all
end
desc "migrate", "Migrates an older project to the 2.0 structure"
def migrate
return if File.exists?("source")
`mv public source`
`cp -R views/* source/`
`rm -rf views`
end
# CLI Module
module Middleman::Cli
class Base < Thor
desc "version", "Show version"
def version
require 'middleman/version'
say "Middleman #{Middleman::VERSION}"
end
private
def help(meth = nil, subcommand = false)
if meth && !self.respond_to?(meth)
klass, task = Thor::Util.find_class_and_task_by_namespace("#{meth}:#{meth}")
klass.start(["-h", task].compact, :shell => self.shell)
else
list = []
Thor::Util.thor_classes_in(Middleman::Cli).each do |klass|
list += klass.printable_tasks(false)
end
list.sort!{ |a,b| a[0] <=> b[0] }
def help_check
help self.class.send(:retrieve_task_name, ARGV.dup)
exit 0
shell.say "Tasks:"
shell.print_table(list, :ident => 2, :truncate => true)
shell.say
end
end
def method_missing(meth, *args)
meth = meth.to_s
if self.class.map.has_key?(meth)
meth = self.class.map[meth]
end
klass, task = Thor::Util.find_class_and_task_by_namespace("#{meth}:#{meth}")
args.unshift(task) if task
klass.start(args, :shell => self.shell)
end
end
end
require "middleman/cli/init"
require "middleman/cli/server"
require "middleman/cli/build"

View file

@ -1,11 +1,44 @@
require "thor"
require "thor/group"
require "rack"
require "rack/test"
require "find"
module Middleman
class Builder < Thor::Group
module Middleman::Cli
class Build < Thor
include Thor::Actions
check_unknown_options!
namespace :build
desc "build [options]", "Builds the static site for deployment"
method_option :relative,
:type => :boolean,
:aliases => "-r",
:default => false,
:desc => 'Force relative urls'
method_option :clean,
:type => :boolean,
:aliases => "-c",
:default => false,
:desc => 'Removes orpahand files or directories from build'
method_option :glob,
:type => :string,
:aliases => "-g",
:default => nil,
:desc => 'Build a subset of the project'
def build
if options.has_key?("relative") && options["relative"]
self.class.shared_instance.activate :relative_assets
end
self.class.shared_rack
opts = {}
opts[:glob] = options["glob"] if options.has_key?("glob")
opts[:clean] = options["clean"] if options.has_key?("clean")
action GlobAction.new(self, self.class.shared_instance, opts)
self.class.shared_instance.run_hook :after_build, self
end
class << self
def shared_instance
@ -28,6 +61,8 @@ module Middleman
end
end
source_root(shared_instance.root)
# @private
module ThorActions
# Render a template to a file.
@ -36,12 +71,12 @@ module Middleman
config = args.last.is_a?(Hash) ? args.pop : {}
destination = args.first || source
request_path = destination.sub(/^#{::Middleman::Builder.shared_instance.build_dir}/, "")
request_path = destination.sub(/^#{self.class.shared_instance.build_dir}/, "")
begin
destination, request_path = ::Middleman::Builder.shared_instance.reroute_builder(destination, request_path)
destination, request_path = self.class.shared_instance.reroute_builder(destination, request_path)
response = ::Middleman::Builder.shared_rack.get(request_path.gsub(/\s/, "%20"))
response = self.class.shared_rack.get(request_path.gsub(/\s/, "%20"))
create_file(destination, response.body, config)
@ -52,36 +87,8 @@ module Middleman
end
end
end
include ThorActions
class_option :relative, :type => :boolean, :aliases => "-r", :default => false, :desc => 'Override the config.rb file and force relative urls'
class_option :glob, :type => :string, :aliases => "-g", :default => nil, :desc => 'Build a subset of the project'
def initialize(*args)
super
if options.has_key?("relative") && options["relative"]
self.class.shared_instance.activate :relative_assets
end
end
def source_paths
@source_paths ||= [
self.class.shared_instance.root
]
end
def build_all_files
self.class.shared_rack
opts = { }
opts[:glob] = options["glob"] if options.has_key?("glob")
opts[:clean] = options["clean"] if options.has_key?("clean")
action GlobAction.new(self, self.class.shared_instance, opts)
self.class.shared_instance.run_hook :after_build, self
end
end
# @private
@ -179,4 +186,6 @@ module Middleman
end
end
end
Base.map({ "b" => "build" })
end

47
lib/middleman/cli/init.rb Normal file
View file

@ -0,0 +1,47 @@
module Middleman::Cli
class Init < Thor
check_unknown_options!
namespace :init
desc "init NAME [options]", "Create new project NAME"
available_templates = ::Middleman::Templates.registered.keys.join(", ")
# argument :name
method_option "template",
:aliases => "-T",
:default => "default",
:desc => "Use a project template: #{available_templates}"
method_option "css_dir",
:default => "stylesheets",
:desc => 'The path to the css files'
method_option "js_dir",
:default => "javascripts",
:desc => 'The path to the javascript files'
method_option "images_dir",
:default => "images",
:desc => 'The path to the image files'
method_option "rack",
:type => :boolean,
:default => false,
:desc => 'Include a config.ru file'
method_option "bundler",
:type => :boolean,
:default => false,
:desc => 'Create a Gemfile and use Bundler to manage gems'
def init(name)
key = options[:template].to_sym
unless ::Middleman::Templates.registered.has_key?(key)
raise Thor::Error.new "Unknown project template '#{key}'"
end
thor_group = ::Middleman::Templates.registered[key]
thor_group.new([name], options).invoke_all
end
end
Base.map({
"i" => "init",
"new" => "init",
"n" => "init"
})
end

View file

@ -0,0 +1,40 @@
module Middleman::Cli
class Server < Thor
check_unknown_options!
namespace :server
desc "server [options]", "Start the preview server"
method_option "environment",
:aliases => "-e",
:default => ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development',
:desc => "The environment Middleman will run under"
method_option :host,
:type => :string,
:aliases => "-h",
# :required => true,
:default => "0.0.0.0",
:desc => "Bind to HOST address"
method_option "port",
:aliases => "-p",
:default => "4567",
:desc => "The port Middleman will listen on"
method_option "debug",
:type => :boolean,
:default => false,
:desc => 'Print debug messages'
def server
params = {
:port => options["port"],
:host => options["host"],
:environment => options["environment"],
:debug => options["debug"]
}
puts "== The Middleman is loading"
Middleman::Guard.start(params)
end
end
Base.map({ "s" => "server" })
end

View file

@ -21,6 +21,7 @@ module Middleman::CoreExtensions::Assets
#
# @param [String] path The path (such as "photo.jpg")
# @param [String] prefix The type prefix (such as "images")
# @return [String] The fully qualified asset url
def asset_url(path, prefix="")
# Don't touch assets which already have a full path
path.include?("://") ? path : File.join(http_prefix, prefix, path)

View file

@ -1,13 +1,23 @@
# Convenience methods to allow config.rb to talk to the Builder
module Middleman::CoreExtensions::Builder
# Extension registered
class << self
# @private
def registered(app)
app.define_hook :after_build
app.extend ClassMethods
app.send :include, InstanceMethods
app.delegate :build_reroute, :to => :"self.class"
end
alias :included :registered
end
# Build Class Methods
module ClassMethods
# Get a list of callbacks which can modify a files build path
#
# @return [Array<Proc>]
def build_reroute(&block)
@build_rerouters ||= []
@build_rerouters << block if block_given?
@ -15,11 +25,13 @@ module Middleman::CoreExtensions::Builder
end
end
# Build Instance Methods
module InstanceMethods
def build_reroute(&block)
self.class.build_reroute(&block)
end
# Run through callbacks and get the new values
#
# @param [String] destination The current destination of the built file
# @param [String] request_path The current request path of the file
# @return [Array<String>] The new values
def reroute_builder(destination, request_path)
result = [destination, request_path]

View file

@ -1,5 +1,10 @@
# Forward the settings on config.rb and the result of registered extensions
# to Compass
module Middleman::CoreExtensions::Compass
# Extension registered
class << self
# @private
def registered(app)
require "compass"
@ -47,7 +52,7 @@ module Middleman::CoreExtensions::Compass
config.output_style = :nested
end
# Required for relative paths
# Change paths when in build mode. Required for relative paths
configure :build do
::Compass.configuration do |config|
config.environment = :production

View file

@ -1,9 +1,17 @@
# Data formats
require "yaml"
require "active_support/json"
# Using Thor's indifferent hash access
require "thor"
# The data extension parses YAML and JSON files in the data/ directory
# and makes them available to config.rb, templates and extensions
module Middleman::CoreExtensions::Data
# Extension registered
class << self
# @private
def registered(app)
app.set :data_dir, "data"
app.send :include, InstanceMethods
@ -11,7 +19,10 @@ module Middleman::CoreExtensions::Data
alias :included :registered
end
# Instance methods
module InstanceMethods
# Setup data files before anything else so they are available when
# parsing config.rb
def initialize
file_changed DataStore.matcher do |file|
data.touch_file(file) if file.match(%r{^#{data_dir}\/})
@ -24,43 +35,77 @@ module Middleman::CoreExtensions::Data
super
end
# The data object
#
# @return [DataStore]
def data
@data ||= DataStore.new(self)
end
# Makes a hash available on the data var with a given name
#
# @param [Symbol] name Name of the data, used for namespacing
# @param [Hash] content The content for this data
# @return [void]
def data_content(name, content)
DataStore.data_content(name, content)
end
# Makes a hash available on the data var with a given name
#
# @param [Symbol] name Name of the data, used for namespacing
# @return [void]
def data_callback(name, &block)
DataStore.data_callback(name, block)
end
end
# The core logic behind the data extension.
class DataStore
# Static methods
class << self
# The regex which tells Middleman which files are for data
#
# @return [Regexp]
def matcher
%r{[\w-]+\.(yml|yaml|json)$}
end
# Store static data hash
#
# @param [Symbol] name Name of the data, used for namespacing
# @param [Hash] content The content for this data
# @return [void]
def data_content(name, content)
@@local_sources ||= {}
@@local_sources[name.to_s] = content
end
# Store callback-based data
#
# @param [Symbol] name Name of the data, used for namespacing
# @param [Proc] proc The callback which will return data
# @return [void]
def data_callback(name, proc)
@@callback_sources ||= {}
@@callback_sources[name.to_s] = proc
end
end
# Setup data store
#
# @param [Middleman::Base] app The current instance of Middleman
def initialize(app)
@app = app
@local_data = {}
end
# Update the internal cache for a given file path
#
# @param [String] file The file to be re-parsed
# @return [void]
def touch_file(file)
file = File.expand_path(file, @app.root)
extension = File.extname(file)
@ -74,16 +119,23 @@ module Middleman::CoreExtensions::Data
return
end
# @app.logger.debug :data_update, Time.now, basename if @app.logging?
@local_data[basename] = recursively_enhance(data)
end
# Remove a given file from the internal cache
#
# @param [String] file The file to be cleared
# @return [void]
def remove_file(file)
extension = File.extname(file)
basename = File.basename(file, extension)
@local_data.delete(basename) if @local_data.has_key?(basename)
end
# Get a hash hash from either internal static data or a callback
#
# @param [String, Symbol] path The name of the data namespace
# @return [Hash, nil]
def data_for_path(path)
response = nil
@ -99,6 +151,10 @@ module Middleman::CoreExtensions::Data
response
end
# "Magically" find namespaces of data if they exist
#
# @param [String] path The namespace to search for
# @return [Hash, nil]
def method_missing(path)
if @local_data.has_key?(path.to_s)
return @local_data[path.to_s]
@ -113,6 +169,9 @@ module Middleman::CoreExtensions::Data
super
end
# Convert all the data into a static hash
#
# @return [Hash]
def to_h
data = {}
@ -135,6 +194,11 @@ module Middleman::CoreExtensions::Data
end
private
# Recursively convert a normal Hash into a HashWithIndifferentAccess
#
# @private
# @param [Hash] data Normal hash
# @return [Thor::CoreExt::HashWithIndifferentAccess]
def recursively_enhance(data)
if data.is_a? Hash
data = Thor::CoreExt::HashWithIndifferentAccess.new(data)

View file

@ -9,8 +9,12 @@ require 'active_support/inflector' # humanize
FileSet.glob_require('../vendor/padrino-helpers-0.10.5/lib/padrino-helpers/**/*.rb', __FILE__)
# Built-in helpers
module Middleman::CoreExtensions::DefaultHelpers
# Extension registered
class << self
# @private
def registered(app)
app.helpers ::Padrino::Helpers::OutputHelpers
app.helpers ::Padrino::Helpers::TagHelpers
@ -30,19 +34,34 @@ module Middleman::CoreExtensions::DefaultHelpers
alias :included :registered
end
# The helpers
module Helpers
# Output a stylesheet link tag based on the current path
#
# @param [String] separator How to break up path in parts
# @return [String]
def auto_stylesheet_link_tag(separator="/")
auto_tag(:css, separator) do |path|
stylesheet_link_tag path
end
end
# Output a javascript tag based on the current path
#
# @param [String] separator How to break up path in parts
# @return [String]
def auto_javascript_include_tag(separator="/")
auto_tag(:js, separator) do |path|
javascript_include_tag path
end
end
# Output a stylesheet link tag based on the current path
#
# @param [Symbol] asset_ext The type of asset
# @param [String] separator How to break up path in parts
# @param [String] asset_dir Where to look for assets
# @return [void]
def auto_tag(asset_ext, separator="/", asset_dir=nil)
if asset_dir.nil?
asset_dir = case asset_ext
@ -61,6 +80,9 @@ module Middleman::CoreExtensions::DefaultHelpers
yield path if sitemap.exists?(File.join(asset_dir, path))
end
# Generate body css classes based on the current path
#
# @return [String]
def page_classes
path = current_path.dup
path << index_file if path.match(%r{/$})
@ -73,7 +95,11 @@ module Middleman::CoreExtensions::DefaultHelpers
classes.join(' ')
end
# Padrino's asset handling needs to pass through ours
# Get the path of a file of a given type
#
# @param [Symbol] kind The type of file
# @param [String] source The path to the file
# @return [String]
def asset_path(kind, source)
return source if source =~ /^http/
asset_folder = case kind

View file

@ -31,9 +31,12 @@
# Using for version parsing
require "rubygems"
# Namespace extensions module
module Middleman::CoreExtensions::Extensions
# Register extension
class << self
# @private
def included(app)
# app.set :default_extensions, []
app.define_hook :after_configuration
@ -43,18 +46,31 @@ module Middleman::CoreExtensions::Extensions
app.extend ClassMethods
app.send :include, InstanceMethods
app.delegate :configure, :to => :"self.class"
end
end
# Class methods
module ClassMethods
# Add a callback to run in a specific environment
#
# @param [String, Symbol] env The environment to run in
# @return [void]
def configure(env, &block)
send("#{env}_config", &block)
end
# Alias `extensions` to access registered extensions
#
# @return [Array<Module]
def extensions
@extensions ||= []
end
# Register a new extension
#
# @param [Array<Module>] new_extensions Extension modules to register
# @return [Array<Module]
def register(*new_extensions)
@extensions ||= []
@extensions += new_extensions
@ -65,12 +81,16 @@ module Middleman::CoreExtensions::Extensions
end
end
# Instance methods
module InstanceMethods
# This method is available in the project's `config.rb`.
# It takes a underscore-separated symbol, finds the appropriate
# feature module and includes it.
#
# activate :lorem
#
# @param [Symbol, Module] feature Which extension to activate
# @return [void]
def activate(feature)
ext = ::Middleman::Extensions.load(feature.to_sym)
@ -84,10 +104,6 @@ module Middleman::CoreExtensions::Extensions
end
end
def configure(env, &block)
self.class.configure(env, &block)
end
# Load features before starting server
def initialize
super

View file

@ -1,11 +1,17 @@
require "find"
# API for watching file change events
module Middleman::CoreExtensions::FileWatcher
# Setup extension
class << self
# @private
def registered(app)
app.extend ClassMethods
app.send :include, InstanceMethods
app.delegate :file_changed, :file_deleted, :to => :"self.class"
# Before parsing config, load the data/ directory
app.before_configuration do
data_path = File.join(root, data_dir)
Find.find(data_path) do |path|
@ -14,6 +20,7 @@ module Middleman::CoreExtensions::FileWatcher
end if File.exists?(data_path)
end
# After config, load everything else
app.ready do
Find.find(root) do |path|
next if File.directory?(path)
@ -24,13 +31,22 @@ module Middleman::CoreExtensions::FileWatcher
alias :included :registered
end
# Class methods
module ClassMethods
# Add callback to be run on file change
#
# @param [nil,Regexp] matcher A Regexp to match the change path against
# @return [Array<Proc>]
def file_changed(matcher=nil, &block)
@_file_changed ||= []
@_file_changed << [block, matcher] if block_given?
@_file_changed
end
# Add callback to be run on file deletion
#
# @param [nil,Regexp] matcher A Regexp to match the deleted path against
# @return [Array<Proc>]
def file_deleted(matcher=nil, &block)
@_file_deleted ||= []
@_file_deleted << [block, matcher] if block_given?
@ -38,11 +54,12 @@ module Middleman::CoreExtensions::FileWatcher
end
end
# Instance methods
module InstanceMethods
def file_changed(*args, &block)
self.class.file_changed(*args, &block)
end
# Notify callbacks that a file changed
#
# @param [String] path The file that changed
# @return [void]
def file_did_change(path)
file_changed.each do |callback, matcher|
next if path.match(%r{^#{build_dir}/})
@ -51,10 +68,10 @@ module Middleman::CoreExtensions::FileWatcher
end
end
def file_deleted(*args)
self.class.file_deleted(*args)
end
# Notify callbacks that a file was deleted
#
# @param [String] path The file that was deleted
# @return [void]
def file_did_delete(path)
file_deleted.each do |callback, matcher|
next if path.match(%r{^#{build_dir}/})

View file

@ -7,6 +7,7 @@ module Middleman::CoreExtensions::FrontMatter
app.set :frontmatter_extensions, %w(.htm .html .php)
app.extend ClassMethods
app.send :include, InstanceMethods
app.delegate :frontmatter_changed, :to => :"self.class"
end
alias :included :registered
end
@ -56,10 +57,6 @@ module Middleman::CoreExtensions::FrontMatter
end
end
def frontmatter_changed(*args, &block)
self.class.frontmatter_changed(*args, &block)
end
def frontmatter_did_change(path)
frontmatter_changed.each do |callback, matcher|
next if path.match(%r{^#{build_dir}/})

View file

@ -44,6 +44,8 @@ module Middleman::CoreExtensions::Rendering
# the template don't persist for other templates.
context = self.dup
@current_locs = locs, @current_opts = opts
while ::Tilt[path]
content = render_individual_file(path, locs, opts, context)
path = File.basename(path, File.extname(path))
@ -60,6 +62,8 @@ module Middleman::CoreExtensions::Rendering
ensure
@current_engine = engine_was
@content_blocks = nil
@current_locs = nil
@current_opts = nil
end
# Sinatra/Padrino render method signature.
@ -199,6 +203,12 @@ module Middleman::CoreExtensions::Rendering
layout_path
end
def wrap_layout(layout_name, &block)
content = capture(&block) if block_given?
layout_path = locate_layout(layout_name, current_engine)
concat render_individual_file(layout_path, @current_locs || {}, @current_opts || {}, self) { content }
end
def current_engine
@current_engine ||= nil
end

View file

@ -1,5 +1,4 @@
require 'pathname'
require 'rbconfig'
require "sprockets"
module Middleman::CoreExtensions::Sprockets

View file

@ -6,8 +6,7 @@ require "guard/guard"
require "net/http"
# Support forking on Windows
require "rbconfig"
require "win32/process" if RbConfig::CONFIG['host_os'].downcase =~ %r{mingw}
require "win32/process" if Middleman::WINDOWS
module Middleman::Guard
def self.start(options={})
@ -21,7 +20,8 @@ module Middleman::Guard
watch(%r{(.*)})
end
},
:watch_all_modifications => true
:watch_all_modifications => true,
:no_interactions => true
})
end
end
@ -45,32 +45,40 @@ module Guard
# Start Middleman in a fork
def start
@server_job = fork do
env = (@options[:environment] || "development").to_sym
is_logging = @options.has_key?(:debug) && (@options[:debug] == "true")
app = ::Middleman.server.inst do
set :environment, env
set :logging, is_logging
end
require "thin"
::Thin::Logging.silent = !is_logging
app_rack = app.class.to_rack_app
opts = @options.dup
opts[:app] = app_rack
puts "== The Middleman is standing watch on port #{opts[:port]||4567}"
::Middleman.start_server(opts)
if ::Middleman::JRUBY
thread = Thread.new { bootup }
thread.join
else
@server_job = fork { bootup }
end
end
def bootup
env = (@options[:environment] || "development").to_sym
is_logging = @options.has_key?(:debug) && (@options[:debug] == "true")
app = ::Middleman.server.inst do
set :environment, env
set :logging, is_logging
end
app_rack = app.class.to_rack_app
opts = @options.dup
opts[:app] = app_rack
opts[:logging] = is_logging
puts "== The Middleman is standing watch on port #{opts[:port]||4567}"
::Middleman.start_server(opts)
end
# Stop the forked Middleman
def stop
puts "== The Middleman is shutting down"
Process.kill("KILL", @server_job)
Process.wait @server_job
@server_job = nil
if ::Middleman::JRUBY
else
Process.kill(self.class.kill_command, @server_job)
Process.wait @server_job
@server_job = nil
end
end
# Simply stop, then start
@ -99,6 +107,10 @@ module Guard
paths.each { |path| tell_server(:delete => path) }
end
def self.kill_command
::Middleman::WINDOWS ? 1 : :INT
end
private
# Whether the passed files are config.rb or lib/*.rb
# @param [Array<String>] paths Array of paths to check
@ -119,7 +131,7 @@ module Guard
end
# Trap the interupt signal and shut down Guard (and thus the server) smoothly
trap(:INT) do
trap(::Guard::Middleman.kill_command) do
::Guard.stop
exit
# exit!(0)
end

View file

@ -1,7 +1,13 @@
MIDDLEMAN_ROOT_PATH = File.dirname(File.dirname(File.dirname(__FILE__)))
MIDDLEMAN_BIN_PATH = File.join(MIDDLEMAN_ROOT_PATH, "bin")
ENV['PATH'] = "#{MIDDLEMAN_BIN_PATH}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
require "aruba/cucumber"
require "middleman/step_definitions/middleman_steps"
require "middleman/step_definitions/builder_steps"
require "middleman/step_definitions/generator_steps"
require "middleman/step_definitions/server_steps"
Before do
@aruba_timeout_seconds = 30
end

View file

@ -3,48 +3,40 @@ require 'fileutils'
Given /^app "([^\"]*)" is using config "([^\"]*)"$/ do |path, config_name|
target = File.join(PROJECT_ROOT_PATH, "fixtures", path)
config_path = File.join(target, "config-#{config_name}.rb")
config_dest = File.join(target, "config.rb")
config_dest = File.join(current_dir, "config.rb")
FileUtils.cp(config_path, config_dest)
end
Given /^a built app at "([^\"]*)"$/ do |path|
target = File.join(PROJECT_ROOT_PATH, "fixtures", path)
Given /^a fixture app "([^\"]*)"$/ do |path|
step %Q{a directory named "#{path}"}
build_target = File.join(target, "build")
FileUtils.rm_rf(build_target)
target_path = File.join(PROJECT_ROOT_PATH, "fixtures", path)
FileUtils.cp_r(target_path, current_dir)
build_cmd = File.join(MIDDLEMAN_BIN_PATH, "middleman build")
`cd #{target} && #{build_cmd}`
step %Q{I cd to "#{path}"}
end
Then /^cleanup built app at "([^\"]*)"$/ do |path|
target = File.join(PROJECT_ROOT_PATH, "fixtures", path, "build")
FileUtils.rm_rf(target)
Given /^a built app at "([^\"]*)"$/ do |path|
step %Q{a fixture app "#{path}"}
step %Q{I run `middleman build`}
end
Given /^was successfully built$/ do
step %Q{a directory named "build" should exist}
step %Q{the exit status should be 0}
end
Given /^a successfully built app at "([^\"]*)"$/ do |path|
step %Q{a built app at "#{path}"}
step %Q{was successfully built}
end
Given /^a built app at "([^\"]*)" with flags "([^\"]*)"$/ do |path, flags|
target = File.join(PROJECT_ROOT_PATH, "fixtures", path)
build_cmd = File.join(MIDDLEMAN_BIN_PATH, "middleman build")
`cd #{target} && #{build_cmd} #{flags}`
step %Q{a fixture app "#{path}"}
step %Q{I run `middleman build #{flags}`}
end
Then /^"([^\"]*)" should exist at "([^\"]*)"$/ do |target_file, path|
target = File.join(PROJECT_ROOT_PATH, "fixtures", path, "build", target_file)
File.exists?(target).should be_true
end
Then /^"([^\"]*)" should exist at "([^\"]*)" and include "([^\"]*)"$/ do |target_file, path, expected|
target = File.join(PROJECT_ROOT_PATH, "fixtures", path, "build", target_file)
File.exists?(target).should be_true
File.read(target).should include(expected)
end
Then /^"([^\"]*)" should not exist at "([^\"]*)"$/ do |target_file, path|
target = File.join(PROJECT_ROOT_PATH, "fixtures", path, "build", target_file)
File.exists?(target).should be_false
end
Then /^the last exit code should be "([^\"]*)"$/ do |exit_code|
exit_code = exit_code.to_i
$?.exitstatus.should == exit_code
Given /^a successfully built app at "([^\"]*)" with flags "([^\"]*)"$/ do |path, flags|
step %Q{a built app at "#{path}" with flags "#{flags}"}
step %Q{was successfully built}
end

View file

@ -1,3 +1,5 @@
require "fileutils"
Given /^a project at "([^\"]*)"$/ do |dirname|
@target = File.join(PROJECT_ROOT_PATH, "fixtures", dirname)
end

View file

@ -10,17 +10,19 @@ module Middleman::Templates
# Get list of registered templates and add new ones
#
# Middleman::Templates.register(:ext_name, klass)
#
# @param [Symbol] name The name of the template
# @param [Class] klass The class to be executed for this template
# @return [Hash] List of registered templates
def registered(*args)
def register(*args)
@_template_mappings ||= {}
@_template_mappings[args[0]] = args[1] if args.length == 2
@_template_mappings
end
# Middleman::Templates.register(name, klass)
alias :register :registered
alias :registered :register
end
# Base Template class. Handles basic options and paths.
@ -44,14 +46,20 @@ module Middleman::Templates
# Output a config.ru file for Rack if --rack is passed
class_option :rack, :type => :boolean, :default => false
def generate_rack
# Write a Rack config.ru file for project
# @return [void]
def generate_rack!
return unless options[:rack]
template "shared/config.ru", File.join(location, "config.ru")
end
# Output a Gemfile file for Bundler if --bundler is passed
class_option :bundler, :type => :boolean, :default => false
def generate_bundler
# Write a Bundler Gemfile file for project
# @return [void]
def generate_bundler!
return unless options[:bundler]
template "shared/Gemfile.tt", File.join(location, "Gemfile")

View file

@ -2,12 +2,14 @@
class Middleman::Templates::Default < Middleman::Templates::Base
# Template files are relative to this file
# @return [String]
def self.source_root
File.dirname(__FILE__)
end
# Actually output the files
def build_scaffold
# @return [void]
def build_scaffold!
template "shared/config.tt", File.join(location, "config.rb")
copy_file "default/source/index.html.erb", File.join(location, "source/index.html.erb")
copy_file "default/source/layout.erb", File.join(location, "source/layout.erb")

View file

@ -7,12 +7,14 @@ class Middleman::Templates::Html5 < Middleman::Templates::Base
class_option :images_dir, :default => "img"
# Templates are relative to this file
# @return [String]
def self.source_root
File.dirname(__FILE__)
end
# Output the files
def build_scaffold
# @return [void]
def build_scaffold!
template "shared/config.tt", File.join(location, "config.rb")
directory "html5/source", File.join(location, "source")
empty_directory File.join(location, "source")

View file

@ -2,18 +2,20 @@
class Middleman::Templates::Local < Middleman::Templates::Base
# Look for templates in ~/.middleman
# @return [String]
def self.source_root
Middleman.templates_path
File.join(File.expand_path("~/"), ".middleman")
end
# Just copy from the template path
def build_scaffold
# @return [void]
def build_scaffold!
directory options[:template].to_s, location
end
end
# Iterate over the directories in the templates path and register each one.
Dir[File.join(Middleman.templates_path, "*")].each do |dir|
Dir[File.join(Middleman::Templates::Local.source_root, "*")].each do |dir|
next unless File.directory?(dir)
Middleman::Templates.register(File.basename(dir).to_sym, Middleman::Templates::Local)
end

View file

@ -7,12 +7,14 @@ class Middleman::Templates::Mobile < Middleman::Templates::Base
class_option :images_dir, :default => "img"
# Template files are relative to this file
# @return [String]
def self.source_root
File.dirname(__FILE__)
end
# Output the files
def build_scaffold
# @return [void]
def build_scaffold!
template "shared/config.tt", File.join(location, "config.rb")
directory "mobile/source", File.join(location, "source")
empty_directory File.join(location, "source")

View file

@ -2,8 +2,12 @@
require "rubygems"
module Middleman
VERSION = "3.0.0.alpha.4"
# Current Version
# @return [String]
VERSION = "3.0.0.alpha.5"
# Parsed version for RubyGems
# @private
# @return [String]
GEM_VERSION = ::Gem::Version.create(VERSION)
end

View file

@ -1,6 +1,4 @@
# -*- encoding: utf-8 -*-
require "rbconfig"
$:.push File.expand_path("../lib", __FILE__)
require "middleman/version"
@ -26,7 +24,7 @@ Gem::Specification.new do |s|
s.add_dependency("tilt", ["~> 1.3.1"])
s.add_dependency("i18n", ["~> 0.6.0"])
s.add_dependency("rack-test", ["~> 0.6.1"])
s.add_dependency("uglifier", ["~> 1.1.0"])
s.add_dependency("uglifier", ["~> 1.2.0"])
s.add_dependency("haml", ["~> 3.1.0"])
s.add_dependency("sass", ["~> 3.1.7"])
s.add_dependency("activesupport", ["~> 3.1.0"])
@ -34,22 +32,25 @@ Gem::Specification.new do |s|
s.add_dependency("coffee-script", ["~> 2.2.0"])
s.add_dependency("execjs", ["~> 1.2.7"])
s.add_dependency("sprockets", ["~> 2.1.2"])
s.add_dependency("sprockets-sass", ["~> 0.3.0"])
s.add_dependency("guard", ["~> 0.8.8"])
s.add_dependency("sprockets-sass", ["~> 0.6.0"])
s.add_dependency("guard", ["~> 0.9.1"])
s.add_dependency("redcarpet", ["~> 2.0.0"])
s.add_dependency("eventmachine", ["1.0.0.beta.4.1"])
s.add_dependency("win32-process", ["~> 0.6.5"])
s.add_dependency("rb-fchange")
# Development and test
s.add_development_dependency("slim")
s.add_development_dependency("maruku")
s.add_development_dependency("sinatra")
s.add_development_dependency("coffee-filter", ["~> 0.1.1"])
s.add_development_dependency("liquid", ["~> 2.2.0"])
s.add_development_dependency("liquid", ["~> 2.2"])
s.add_development_dependency("cucumber", ["~> 1.1.0"])
s.add_development_dependency("aruba")
s.add_development_dependency("rake", ["~> 0.9.2"])
s.add_development_dependency("rspec", ["~> 2.7.0"])
s.add_development_dependency("rspec", ["~> 2.7"])
s.add_development_dependency("rdoc", ["~> 3.9"])
s.add_development_dependency("yard")
s.add_development_dependency("jquery-rails")
s.add_development_dependency("bootstrap-rails")
s.add_development_dependency("bootstrap-rails", ["0.0.5"])
end

View file

@ -1,6 +1,4 @@
# -*- encoding: utf-8 -*-
require "rbconfig"
$:.push File.expand_path("../lib", __FILE__)
require "middleman/version"
@ -26,7 +24,7 @@ Gem::Specification.new do |s|
s.add_dependency("tilt", ["~> 1.3.1"])
s.add_dependency("i18n", ["~> 0.6.0"])
s.add_dependency("rack-test", ["~> 0.6.1"])
s.add_dependency("uglifier", ["~> 1.1.0"])
s.add_dependency("uglifier", ["~> 1.2.0"])
s.add_dependency("haml", ["~> 3.1.0"])
s.add_dependency("sass", ["~> 3.1.7"])
s.add_dependency("activesupport", ["~> 3.1.0"])
@ -34,22 +32,20 @@ Gem::Specification.new do |s|
s.add_dependency("coffee-script", ["~> 2.2.0"])
s.add_dependency("execjs", ["~> 1.2.7"])
s.add_dependency("sprockets", ["~> 2.1.2"])
s.add_dependency("sprockets-sass", ["~> 0.5.0"])
s.add_dependency("guard", ["~> 0.8.8"])
s.add_dependency("sprockets-sass", ["~> 0.6.0"])
s.add_dependency("guard", ["~> 0.9.1"])
s.add_dependency("redcarpet", ["~> 2.0.0"])
# OSX
s.add_dependency("rb-fsevent")
# Development and test
s.add_development_dependency("slim")
s.add_development_dependency("sinatra")
s.add_development_dependency("coffee-filter", ["~> 0.1.1"])
s.add_development_dependency("liquid", ["~> 2.2.0"])
s.add_development_dependency("liquid", ["~> 2.2"])
s.add_development_dependency("cucumber", ["~> 1.1.0"])
s.add_development_dependency("aruba")
s.add_development_dependency("rake", ["~> 0.9.2"])
s.add_development_dependency("rspec", ["~> 2.7.0"])
s.add_development_dependency("rdoc", ["~> 3.9.4"])
s.add_development_dependency("rspec", ["~> 2.7"])
s.add_development_dependency("rdoc", ["~> 3.9"])
s.add_development_dependency("yard")
s.add_development_dependency("jquery-rails")
s.add_development_dependency("bootstrap-rails", ["0.0.5"])