From 59451d1e20cfa226c15d05abaddf9b0c097663f9 Mon Sep 17 00:00:00 2001
From: tdreyno
Date: Wed, 12 Aug 2009 13:04:58 -0700
Subject: [PATCH] add vendor back
---
vendor/rack-test/History.txt | 64 +++
vendor/rack-test/MIT-LICENSE.txt | 19 +
vendor/rack-test/README.rdoc | 57 +++
vendor/rack-test/Rakefile | 62 +++
vendor/rack-test/lib/rack/mock_session.rb | 57 +++
vendor/rack-test/lib/rack/test.rb | 246 ++++++++++++
vendor/rack-test/lib/rack/test/cookie_jar.rb | 169 ++++++++
vendor/rack-test/lib/rack/test/methods.rb | 73 ++++
.../lib/rack/test/mock_digest_request.rb | 27 ++
.../rack-test/lib/rack/test/uploaded_file.rb | 36 ++
vendor/rack-test/lib/rack/test/utils.rb | 75 ++++
vendor/rack-test/spec/fixtures/config.ru | 3 +
vendor/rack-test/spec/fixtures/fake_app.rb | 109 ++++++
vendor/rack-test/spec/fixtures/foo.txt | 1 +
.../rack-test/spec/rack/test/cookie_spec.rb | 176 +++++++++
.../spec/rack/test/digest_auth_spec.rb | 48 +++
.../spec/rack/test/multipart_spec.rb | 85 ++++
vendor/rack-test/spec/rack/test/utils_spec.rb | 44 +++
vendor/rack-test/spec/rack/test_spec.rb | 363 ++++++++++++++++++
vendor/rack-test/spec/rcov.opts | 1 +
vendor/rack-test/spec/spec.opts | 1 +
vendor/rack-test/spec/spec_helper.rb | 48 +++
vendor/sinatra-content-for/LICENSE | 22 ++
vendor/sinatra-content-for/README.rdoc | 49 +++
vendor/sinatra-content-for/Rakefile | 33 ++
.../lib/sinatra/content_for.rb | 58 +++
.../sinatra-content-for.gemspec | 34 ++
.../test/content_for_test.rb | 156 ++++++++
vendor/sinatra-markaby/CHANGES | 7 +
vendor/sinatra-markaby/LICENSE | 20 +
vendor/sinatra-markaby/README.rdoc | 33 ++
vendor/sinatra-markaby/Rakefile | 45 +++
vendor/sinatra-markaby/TODO | 3 +
vendor/sinatra-markaby/VERSION.yml | 4 +
vendor/sinatra-markaby/lib/sinatra/markaby.rb | 31 ++
.../sinatra-markaby/sinatra-markaby.gemspec | 49 +++
.../test/sinatra_markaby_test.rb | 72 ++++
vendor/sinatra-markaby/test/test_helper.rb | 19 +
vendor/sinatra-markaby/test/views/hello.mab | 1 +
vendor/sinatra-markaby/test/views/html.mab | 4 +
vendor/sinatra-maruku/LICENSE | 22 ++
vendor/sinatra-maruku/README.markdown | 85 ++++
vendor/sinatra-maruku/Rakefile | 34 ++
vendor/sinatra-maruku/VERSION.yml | 4 +
vendor/sinatra-maruku/examples/app.rb | 8 +
vendor/sinatra-maruku/examples/config.ru | 4 +
vendor/sinatra-maruku/examples/mapp.rb | 15 +
.../public/javascripts/application.js | 0
.../public/stylesheets/application.css | 23 ++
.../examples/public/stylesheets/print.css | 0
.../examples/views/index.maruku | 32 ++
.../examples/views/layout.maruku | 9 +
vendor/sinatra-maruku/lib/sinatra/maruku.rb | 25 ++
vendor/sinatra-maruku/sinatra-maruku.gemspec | 70 ++++
.../test/sinatra_maruku_test.rb | 91 +++++
vendor/sinatra-maruku/test/test_helper.rb | 21 +
vendor/sinatra-maruku/test/views/hello.maruku | 1 +
.../sinatra-maruku/test/views/layout2.maruku | 2 +
58 files changed, 2850 insertions(+)
create mode 100644 vendor/rack-test/History.txt
create mode 100644 vendor/rack-test/MIT-LICENSE.txt
create mode 100644 vendor/rack-test/README.rdoc
create mode 100644 vendor/rack-test/Rakefile
create mode 100644 vendor/rack-test/lib/rack/mock_session.rb
create mode 100644 vendor/rack-test/lib/rack/test.rb
create mode 100644 vendor/rack-test/lib/rack/test/cookie_jar.rb
create mode 100644 vendor/rack-test/lib/rack/test/methods.rb
create mode 100644 vendor/rack-test/lib/rack/test/mock_digest_request.rb
create mode 100644 vendor/rack-test/lib/rack/test/uploaded_file.rb
create mode 100644 vendor/rack-test/lib/rack/test/utils.rb
create mode 100644 vendor/rack-test/spec/fixtures/config.ru
create mode 100644 vendor/rack-test/spec/fixtures/fake_app.rb
create mode 100644 vendor/rack-test/spec/fixtures/foo.txt
create mode 100644 vendor/rack-test/spec/rack/test/cookie_spec.rb
create mode 100644 vendor/rack-test/spec/rack/test/digest_auth_spec.rb
create mode 100644 vendor/rack-test/spec/rack/test/multipart_spec.rb
create mode 100644 vendor/rack-test/spec/rack/test/utils_spec.rb
create mode 100644 vendor/rack-test/spec/rack/test_spec.rb
create mode 100644 vendor/rack-test/spec/rcov.opts
create mode 100644 vendor/rack-test/spec/spec.opts
create mode 100644 vendor/rack-test/spec/spec_helper.rb
create mode 100644 vendor/sinatra-content-for/LICENSE
create mode 100644 vendor/sinatra-content-for/README.rdoc
create mode 100644 vendor/sinatra-content-for/Rakefile
create mode 100644 vendor/sinatra-content-for/lib/sinatra/content_for.rb
create mode 100644 vendor/sinatra-content-for/sinatra-content-for.gemspec
create mode 100644 vendor/sinatra-content-for/test/content_for_test.rb
create mode 100644 vendor/sinatra-markaby/CHANGES
create mode 100644 vendor/sinatra-markaby/LICENSE
create mode 100644 vendor/sinatra-markaby/README.rdoc
create mode 100644 vendor/sinatra-markaby/Rakefile
create mode 100644 vendor/sinatra-markaby/TODO
create mode 100644 vendor/sinatra-markaby/VERSION.yml
create mode 100644 vendor/sinatra-markaby/lib/sinatra/markaby.rb
create mode 100644 vendor/sinatra-markaby/sinatra-markaby.gemspec
create mode 100644 vendor/sinatra-markaby/test/sinatra_markaby_test.rb
create mode 100644 vendor/sinatra-markaby/test/test_helper.rb
create mode 100644 vendor/sinatra-markaby/test/views/hello.mab
create mode 100644 vendor/sinatra-markaby/test/views/html.mab
create mode 100644 vendor/sinatra-maruku/LICENSE
create mode 100644 vendor/sinatra-maruku/README.markdown
create mode 100644 vendor/sinatra-maruku/Rakefile
create mode 100644 vendor/sinatra-maruku/VERSION.yml
create mode 100644 vendor/sinatra-maruku/examples/app.rb
create mode 100644 vendor/sinatra-maruku/examples/config.ru
create mode 100644 vendor/sinatra-maruku/examples/mapp.rb
rename .gitmodules => vendor/sinatra-maruku/examples/public/javascripts/application.js (100%)
create mode 100644 vendor/sinatra-maruku/examples/public/stylesheets/application.css
create mode 100644 vendor/sinatra-maruku/examples/public/stylesheets/print.css
create mode 100644 vendor/sinatra-maruku/examples/views/index.maruku
create mode 100644 vendor/sinatra-maruku/examples/views/layout.maruku
create mode 100644 vendor/sinatra-maruku/lib/sinatra/maruku.rb
create mode 100644 vendor/sinatra-maruku/sinatra-maruku.gemspec
create mode 100644 vendor/sinatra-maruku/test/sinatra_maruku_test.rb
create mode 100644 vendor/sinatra-maruku/test/test_helper.rb
create mode 100644 vendor/sinatra-maruku/test/views/hello.maruku
create mode 100644 vendor/sinatra-maruku/test/views/layout2.maruku
diff --git a/vendor/rack-test/History.txt b/vendor/rack-test/History.txt
new file mode 100644
index 00000000..61705a4f
--- /dev/null
+++ b/vendor/rack-test/History.txt
@@ -0,0 +1,64 @@
+== Git
+
+* Minor enhancements
+
+ * Support initializing a Rack::Test::Session with an app in addition to
+ a Rack::MockSession
+ * Allow CONTENT_TYPE to be specified in the env and not overwritten when
+ sending a POST or PUT
+
+== 0.4.0 / 2009-06-25
+
+* Minor enhancements
+
+ * Expose hook for building Rack::MockSessions for frameworks that need
+ to configure them before use
+ * Support passing in arrays of raw cookies in addition to a newline
+ separated string
+ * Support after_request callbacks in MockSession for things like running
+ background jobs
+ * Allow multiple named sessions using with_session
+ * Initialize Rack::Test::Sessions with Rack::MockSessions instead of apps.
+ This change should help integration with other Ruby web frameworks
+ (like Merb).
+ * Support sending bodies for PUT requests (Larry Diehl)
+
+== 0.3.0 / 2009-05-17
+
+* Major enhancements
+
+ * Ruby 1.9 compatible (Simon Rozet, Michael Fellinger)
+
+* Minor enhancements
+
+ * Add CookieJar#[] and CookieJar#[]= methods
+ * Make the default host configurable
+ * Use Rack::Lint and fix errors (Simon Rozet)
+ * Extract Rack::MockSession from Rack::Test::Session to handle tracking
+ the last request and response and the cookie jar
+ * Add #set_cookie and #clear_cookies methods
+ * Rename #authorize to #basic_authorize (#authorize remains as an alias)
+ (Simon Rozet)
+
+== 0.2.0 / 2009-04-26
+
+Because #last_response is now a MockResponse instead of a Rack::Response,
+#last_response.body now returns a string instead of an array.
+
+* Major enhancements
+
+ * Support multipart requests via the UploadedFile class (thanks, Rails)
+
+* Minor enhancements
+
+ * Updated for Rack 1.0
+ * Don't require rubygems (See http://gist.github.com/54177)
+ * Support HTTP Digest authentication with the #digest_authorize method
+ * #last_response returns a MockResponse instead of a Response
+ (Michael Fellinger)
+
+== 0.1.0 / 2009-03-02
+
+* 1 major enhancement
+
+ * Birthday!
diff --git a/vendor/rack-test/MIT-LICENSE.txt b/vendor/rack-test/MIT-LICENSE.txt
new file mode 100644
index 00000000..f387441c
--- /dev/null
+++ b/vendor/rack-test/MIT-LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2008-2009 Bryan Helmkamp, Engine Yard Inc.
+
+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/vendor/rack-test/README.rdoc b/vendor/rack-test/README.rdoc
new file mode 100644
index 00000000..c9f96b60
--- /dev/null
+++ b/vendor/rack-test/README.rdoc
@@ -0,0 +1,57 @@
+= Rack::Test
+
+- http://gitrdoc.com/brynary/rack-test
+- http://github.com/brynary/rack-test
+
+== Description
+
+Rack::Test is a small, simple testing API for Rack apps. It can be used on its
+own or as a reusable starting point for Web frameworks and testing libraries
+to build on. Most of its initial functionality is an extraction of Merb 1.0's
+request helpers feature.
+
+== Features
+
+* Maintains a cookie jar across requests
+* Easily follow redirects when desired
+* Set request headers to be used by all subsequent requests
+* Small footprint. Approximately 200 LOC
+
+== Example
+
+ require "rack/test"
+
+ class HomepageTest < Test::Unit::TestCase
+ include Rack::Test::Methods
+
+ def app
+ MyApp.new
+ end
+
+ def test_redirect_logged_in_users_to_dashboard
+ authorize "bryan", "secret"
+ get "/"
+ follow_redirect!
+
+ assert_equal "http://example.org/redirected", last_request.url
+ assert last_response.ok?
+ end
+
+ end
+
+== Install
+
+To install the latest release as a gem:
+
+ sudo gem install rack-test
+
+== Authors
+
+- Maintained by {Bryan Helmkamp}[mailto:bryan@brynary.com]
+- Contributions from Simon Rozet and Pat Nakajima
+- Much of the original code was extracted from Merb 1.0's request helper
+
+== License
+
+Copyright (c) 2008-2009 Bryan Helmkamp, Engine Yard Inc.
+See MIT-LICENSE.txt in this directory.
diff --git a/vendor/rack-test/Rakefile b/vendor/rack-test/Rakefile
new file mode 100644
index 00000000..87fb4c29
--- /dev/null
+++ b/vendor/rack-test/Rakefile
@@ -0,0 +1,62 @@
+require "rubygems"
+require "rake/rdoctask"
+require "rake/gempackagetask"
+require "rake/clean"
+require "spec/rake/spectask"
+require File.expand_path("./lib/rack/test")
+
+Spec::Rake::SpecTask.new do |t|
+ t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
+end
+
+desc "Run all specs in spec directory with RCov"
+Spec::Rake::SpecTask.new(:rcov) do |t|
+ t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
+ t.rcov = true
+ t.rcov_opts = lambda do
+ IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
+ end
+end
+
+desc "Run the specs"
+task :default => :spec
+
+spec = Gem::Specification.new do |s|
+ s.name = "rack-test"
+ s.version = Rack::Test::VERSION
+ s.author = "Bryan Helmkamp"
+ s.email = "bryan" + "@" + "brynary.com"
+ s.homepage = "http://github.com/brynary/rack-test"
+ s.summary = "Simple testing API built on Rack"
+ s.description = s.summary
+ s.files = %w[History.txt Rakefile README.rdoc] + Dir["lib/**/*"]
+
+ # rdoc
+ s.has_rdoc = true
+ s.extra_rdoc_files = %w(README.rdoc MIT-LICENSE.txt)
+end
+
+Rake::GemPackageTask.new(spec) do |package|
+ package.gem_spec = spec
+end
+
+desc "Delete generated RDoc"
+task :clobber_docs do
+ FileUtils.rm_rf("doc")
+end
+
+desc "Generate RDoc"
+task :docs => :clobber_docs do
+ system "hanna --title 'Rack::Test #{Rack::Test::VERSION} API Documentation'"
+end
+
+desc 'Install the package as a gem.'
+task :install => [:clean, :package] do
+ gem = Dir['pkg/*.gem'].first
+ sh "sudo gem install --no-rdoc --no-ri --local #{gem}"
+end
+
+desc 'Removes trailing whitespace'
+task :whitespace do
+ sh %{find . -name '*.rb' -exec sed -i '' 's/ *$//g' {} \\;}
+end
diff --git a/vendor/rack-test/lib/rack/mock_session.rb b/vendor/rack-test/lib/rack/mock_session.rb
new file mode 100644
index 00000000..b5ba12a9
--- /dev/null
+++ b/vendor/rack-test/lib/rack/mock_session.rb
@@ -0,0 +1,57 @@
+module Rack
+
+ class MockSession
+ attr_writer :cookie_jar
+ attr_reader :last_response
+ attr_reader :default_host
+
+ def initialize(app, default_host = Rack::Test::DEFAULT_HOST)
+ @app = app
+ @after_request = []
+ @default_host = default_host
+ end
+
+ def after_request(&block)
+ @after_request << block
+ end
+
+ def clear_cookies
+ @cookie_jar = Rack::Test::CookieJar.new([], @default_host)
+ end
+
+ def set_cookie(cookie, uri = nil)
+ cookie_jar.merge(cookie, uri)
+ end
+
+ def request(uri, env)
+ env["HTTP_COOKIE"] ||= cookie_jar.for(uri)
+ @last_request = Rack::Request.new(env)
+ status, headers, body = @app.call(@last_request.env)
+ @last_response = MockResponse.new(status, headers, body, env["rack.errors"].flush)
+ cookie_jar.merge(last_response.headers["Set-Cookie"], uri)
+
+ @after_request.each { |hook| hook.call }
+ @last_response
+ end
+
+ # Return the last request issued in the session. Raises an error if no
+ # requests have been sent yet.
+ def last_request
+ raise Rack::Test::Error.new("No request yet. Request a page first.") unless @last_request
+ @last_request
+ end
+
+ # Return the last response received in the session. Raises an error if
+ # no requests have been sent yet.
+ def last_response
+ raise Rack::Test::Error.new("No response yet. Request a page first.") unless @last_response
+ @last_response
+ end
+
+ def cookie_jar
+ @cookie_jar ||= Rack::Test::CookieJar.new([], @default_host)
+ end
+
+ end
+
+end
diff --git a/vendor/rack-test/lib/rack/test.rb b/vendor/rack-test/lib/rack/test.rb
new file mode 100644
index 00000000..34532e36
--- /dev/null
+++ b/vendor/rack-test/lib/rack/test.rb
@@ -0,0 +1,246 @@
+unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__) + "/.."))
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/.."))
+end
+
+require "uri"
+require "rack"
+require "rack/mock_session"
+require "rack/test/cookie_jar"
+require "rack/test/mock_digest_request"
+require "rack/test/utils"
+require "rack/test/methods"
+require "rack/test/uploaded_file"
+
+module Rack
+ module Test
+
+ VERSION = "0.4.0"
+
+ DEFAULT_HOST = "example.org"
+ MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
+
+ # The common base class for exceptions raised by Rack::Test
+ class Error < StandardError; end
+
+ class Session
+ extend Forwardable
+ include Rack::Test::Utils
+
+ def_delegators :@rack_mock_session, :clear_cookies, :set_cookie, :last_response, :last_request
+
+ # Initialize a new session for the given Rack app
+ def initialize(mock_session)
+ @headers = {}
+
+ if mock_session.is_a?(MockSession)
+ @rack_mock_session = mock_session
+ else
+ @rack_mock_session = MockSession.new(mock_session)
+ end
+
+ @default_host = @rack_mock_session.default_host
+ end
+
+ # Issue a GET request for the given URI with the given params and Rack
+ # environment. Stores the issues request object in #last_request and
+ # the app's response in #last_response. Yield #last_response to a block
+ # if given.
+ #
+ # Example:
+ # get "/"
+ def get(uri, params = {}, env = {}, &block)
+ env = env_for(uri, env.merge(:method => "GET", :params => params))
+ process_request(uri, env, &block)
+ end
+
+ # Issue a POST request for the given URI. See #get
+ #
+ # Example:
+ # post "/signup", "name" => "Bryan"
+ def post(uri, params = {}, env = {}, &block)
+ env = env_for(uri, env.merge(:method => "POST", :params => params))
+ process_request(uri, env, &block)
+ end
+
+ # Issue a PUT request for the given URI. See #get
+ #
+ # Example:
+ # put "/"
+ def put(uri, params = {}, env = {}, &block)
+ env = env_for(uri, env.merge(:method => "PUT", :params => params))
+ process_request(uri, env, &block)
+ end
+
+ # Issue a DELETE request for the given URI. See #get
+ #
+ # Example:
+ # delete "/"
+ def delete(uri, params = {}, env = {}, &block)
+ env = env_for(uri, env.merge(:method => "DELETE", :params => params))
+ process_request(uri, env, &block)
+ end
+
+ # Issue a HEAD request for the given URI. See #get
+ #
+ # Example:
+ # head "/"
+ def head(uri, params = {}, env = {}, &block)
+ env = env_for(uri, env.merge(:method => "HEAD", :params => params))
+ process_request(uri, env, &block)
+ end
+
+ # Issue a request to the Rack app for the given URI and optional Rack
+ # environment. Stores the issues request object in #last_request and
+ # the app's response in #last_response. Yield #last_response to a block
+ # if given.
+ #
+ # Example:
+ # request "/"
+ def request(uri, env = {}, &block)
+ env = env_for(uri, env)
+ process_request(uri, env, &block)
+ end
+
+ # Set a header to be included on all subsequent requests through the
+ # session. Use a value of nil to remove a previously configured header.
+ #
+ # Example:
+ # header "User-Agent", "Firefox"
+ def header(name, value)
+ if value.nil?
+ @headers.delete(name)
+ else
+ @headers[name] = value
+ end
+ end
+
+ # Set the username and password for HTTP Basic authorization, to be
+ # included in subsequent requests in the HTTP_AUTHORIZATION header.
+ #
+ # Example:
+ # basic_authorize "bryan", "secret"
+ def basic_authorize(username, password)
+ encoded_login = ["#{username}:#{password}"].pack("m*")
+ header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
+ end
+
+ alias_method :authorize, :basic_authorize
+
+ def digest_authorize(username, password)
+ @digest_username = username
+ @digest_password = password
+ end
+
+ # Rack::Test will not follow any redirects automatically. This method
+ # will follow the redirect returned in the last response. If the last
+ # response was not a redirect, an error will be raised.
+ def follow_redirect!
+ unless last_response.redirect?
+ raise Error.new("Last response was not a redirect. Cannot follow_redirect!")
+ end
+
+ get(last_response["Location"])
+ end
+
+ private
+
+ def env_for(path, env)
+ uri = URI.parse(path)
+ uri.host ||= @default_host
+
+ env = default_env.merge(env)
+
+ env.update("HTTPS" => "on") if URI::HTTPS === uri
+ env["X-Requested-With"] = "XMLHttpRequest" if env[:xhr]
+
+ if (env[:method] == "POST" || env["REQUEST_METHOD"] == "POST" ||
+ env[:method] == "PUT" || env["REQUEST_METHOD"] == "PUT") && !env.has_key?(:input)
+ env["CONTENT_TYPE"] ||= "application/x-www-form-urlencoded"
+
+ multipart = (Hash === env[:params]) &&
+ env[:params].any? { |_, v| UploadedFile === v }
+
+ if multipart
+ env[:input] = multipart_body(env.delete(:params))
+ env["CONTENT_LENGTH"] ||= env[:input].length.to_s
+ env["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
+ else
+ env[:input] = params_to_string(env.delete(:params))
+ end
+ end
+
+ params = env[:params] || {}
+ params.update(parse_query(uri.query))
+
+ uri.query = requestify(params)
+
+ if env.has_key?(:cookie)
+ set_cookie(env.delete(:cookie), uri)
+ end
+
+ Rack::MockRequest.env_for(uri.to_s, env)
+ end
+
+ def process_request(uri, env)
+ uri = URI.parse(uri)
+ uri.host ||= @default_host
+
+ @rack_mock_session.request(uri, env)
+
+ if retry_with_digest_auth?(env)
+ auth_env = env.merge({
+ "HTTP_AUTHORIZATION" => digest_auth_header,
+ "rack-test.digest_auth_retry" => true
+ })
+ auth_env.delete('rack.request')
+ process_request(uri.path, auth_env)
+ else
+ yield last_response if block_given?
+
+ last_response
+ end
+ end
+
+ def digest_auth_header
+ challenge = last_response["WWW-Authenticate"].split(" ", 2).last
+ params = Rack::Auth::Digest::Params.parse(challenge)
+
+ params.merge!({
+ "username" => @digest_username,
+ "nc" => "00000001",
+ "cnonce" => "nonsensenonce",
+ "uri" => last_request.path_info,
+ "method" => last_request.env["REQUEST_METHOD"],
+ })
+
+ params["response"] = MockDigestRequest.new(params).response(@digest_password)
+
+ "Digest #{params}"
+ end
+
+ def retry_with_digest_auth?(env)
+ last_response.status == 401 &&
+ digest_auth_configured? &&
+ !env["rack-test.digest_auth_retry"]
+ end
+
+ def digest_auth_configured?
+ @digest_username
+ end
+
+ def default_env
+ { "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(@headers)
+ end
+
+ def params_to_string(params)
+ case params
+ when Hash then requestify(params)
+ when nil then ""
+ else params
+ end
+ end
+
+ end
+
+ end
+end
diff --git a/vendor/rack-test/lib/rack/test/cookie_jar.rb b/vendor/rack-test/lib/rack/test/cookie_jar.rb
new file mode 100644
index 00000000..d2f3d2b9
--- /dev/null
+++ b/vendor/rack-test/lib/rack/test/cookie_jar.rb
@@ -0,0 +1,169 @@
+require "uri"
+module Rack
+ module Test
+
+ class Cookie
+ include Rack::Utils
+
+ # :api: private
+ attr_reader :name, :value
+
+ # :api: private
+ def initialize(raw, uri = nil, default_host = DEFAULT_HOST)
+ @default_host = default_host
+ uri ||= default_uri
+
+ # separate the name / value pair from the cookie options
+ @name_value_raw, options = raw.split(/[;,] */n, 2)
+
+ @name, @value = parse_query(@name_value_raw, ';').to_a.first
+ @options = parse_query(options, ';')
+
+ @options["domain"] ||= (uri.host || default_host)
+ @options["path"] ||= uri.path.sub(/\/[^\/]*\Z/, "")
+ end
+
+ def replaces?(other)
+ [name.downcase, domain, path] == [other.name.downcase, other.domain, other.path]
+ end
+
+ # :api: private
+ def raw
+ @name_value_raw
+ end
+
+ # :api: private
+ def empty?
+ @value.nil? || @value.empty?
+ end
+
+ # :api: private
+ def domain
+ @options["domain"]
+ end
+
+ def secure?
+ @options.has_key?("secure")
+ end
+
+ # :api: private
+ def path
+ @options["path"].strip || "/"
+ end
+
+ # :api: private
+ def expires
+ Time.parse(@options["expires"]) if @options["expires"]
+ end
+
+ # :api: private
+ def expired?
+ expires && expires < Time.now
+ end
+
+ # :api: private
+ def valid?(uri)
+ uri ||= default_uri
+
+ if uri.host.nil?
+ uri.host = @default_host
+ end
+
+ (!secure? || (secure? && uri.scheme == "https")) &&
+ uri.host =~ Regexp.new("#{Regexp.escape(domain)}$", Regexp::IGNORECASE) &&
+ uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
+ end
+
+ # :api: private
+ def matches?(uri)
+ ! expired? && valid?(uri)
+ end
+
+ # :api: private
+ def <=>(other)
+ # Orders the cookies from least specific to most
+ [name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse]
+ end
+
+ protected
+
+ def default_uri
+ URI.parse("//" + @default_host + "/")
+ end
+
+ end
+
+ class CookieJar
+
+ # :api: private
+ def initialize(cookies = [], default_host = DEFAULT_HOST)
+ @default_host = default_host
+ @cookies = cookies
+ @cookies.sort!
+ end
+
+ def [](name)
+ cookies = hash_for(nil)
+ # TODO: Should be case insensitive
+ cookies[name] && cookies[name].value
+ end
+
+ def []=(name, value)
+ # TODO: needs proper escaping
+ merge("#{name}=#{value}")
+ end
+
+ def merge(raw_cookies, uri = nil)
+ return unless raw_cookies
+
+ Array(raw_cookies).join("\n").split("\n").each do |raw_cookie|
+ cookie = Cookie.new(raw_cookie, uri, @default_host)
+ self << cookie if cookie.valid?(uri)
+ end
+ end
+
+ def <<(new_cookie)
+ @cookies.reject! do |existing_cookie|
+ new_cookie.replaces?(existing_cookie)
+ end
+
+ @cookies << new_cookie
+ @cookies.sort!
+ end
+
+ # :api: private
+ def for(uri)
+ hash_for(uri).values.map { |c| c.raw }.join(';')
+ end
+
+ def to_hash
+ cookies = {}
+
+ hash_for(nil).each do |name, cookie|
+ cookies[name] = cookie.value
+ end
+
+ return cookies
+ end
+
+ protected
+
+ def hash_for(uri = nil)
+ cookies = {}
+
+ # The cookies are sorted by most specific first. So, we loop through
+ # all the cookies in order and add it to a hash by cookie name if
+ # the cookie can be sent to the current URI. It's added to the hash
+ # so that when we are done, the cookies will be unique by name and
+ # we'll have grabbed the most specific to the URI.
+ @cookies.each do |cookie|
+ cookies[cookie.name] = cookie if cookie.matches?(uri)
+ end
+
+ return cookies
+ end
+
+ end
+
+ end
+end
diff --git a/vendor/rack-test/lib/rack/test/methods.rb b/vendor/rack-test/lib/rack/test/methods.rb
new file mode 100644
index 00000000..1678fe56
--- /dev/null
+++ b/vendor/rack-test/lib/rack/test/methods.rb
@@ -0,0 +1,73 @@
+require "forwardable"
+
+module Rack
+ module Test
+ module Methods
+ extend Forwardable
+
+ def rack_mock_session(name = :default)
+ return build_rack_mock_session unless name
+
+ @_rack_mock_sessions ||= {}
+ @_rack_mock_sessions[name] ||= build_rack_mock_session
+ end
+
+ def build_rack_mock_session
+ Rack::MockSession.new(app)
+ end
+
+ def rack_test_session(name = :default)
+ return build_rack_test_session(name) unless name
+
+ @_rack_test_sessions ||= {}
+ @_rack_test_sessions[name] ||= build_rack_test_session(name)
+ end
+
+ def build_rack_test_session(name)
+ Rack::Test::Session.new(rack_mock_session(name))
+ end
+
+ def current_session
+ rack_test_session(_current_session_names.last)
+ end
+
+ def with_session(name)
+ _current_session_names.push(name)
+ yield rack_test_session(name)
+ _current_session_names.pop
+ end
+
+ def _current_session_names
+ @_current_session_names ||= [:default]
+ end
+
+ METHODS = [
+ :request,
+
+ # HTTP verbs
+ :get,
+ :post,
+ :put,
+ :delete,
+ :head,
+
+ # Redirects
+ :follow_redirect!,
+
+ # Header-related features
+ :header,
+ :set_cookie,
+ :clear_cookies,
+ :authorize,
+ :basic_authorize,
+ :digest_authorize,
+
+ # Expose the last request and response
+ :last_response,
+ :last_request
+ ]
+
+ def_delegators :current_session, *METHODS
+ end
+ end
+end
diff --git a/vendor/rack-test/lib/rack/test/mock_digest_request.rb b/vendor/rack-test/lib/rack/test/mock_digest_request.rb
new file mode 100644
index 00000000..81c398ba
--- /dev/null
+++ b/vendor/rack-test/lib/rack/test/mock_digest_request.rb
@@ -0,0 +1,27 @@
+module Rack
+ module Test
+
+ class MockDigestRequest
+ def initialize(params)
+ @params = params
+ end
+
+ def method_missing(sym)
+ if @params.has_key? k = sym.to_s
+ return @params[k]
+ end
+
+ super
+ end
+
+ def method
+ @params['method']
+ end
+
+ def response(password)
+ Rack::Auth::Digest::MD5.new(nil).send :digest, self, password
+ end
+ end
+
+ end
+end
diff --git a/vendor/rack-test/lib/rack/test/uploaded_file.rb b/vendor/rack-test/lib/rack/test/uploaded_file.rb
new file mode 100644
index 00000000..239302fb
--- /dev/null
+++ b/vendor/rack-test/lib/rack/test/uploaded_file.rb
@@ -0,0 +1,36 @@
+require "tempfile"
+
+module Rack
+ module Test
+
+ class UploadedFile
+ # The filename, *not* including the path, of the "uploaded" file
+ attr_reader :original_filename
+
+ # The content type of the "uploaded" file
+ attr_accessor :content_type
+
+ def initialize(path, content_type = "text/plain", binary = false)
+ raise "#{path} file does not exist" unless ::File.exist?(path)
+ @content_type = content_type
+ @original_filename = ::File.basename(path)
+ @tempfile = Tempfile.new(@original_filename)
+ @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
+ @tempfile.binmode if binary
+ FileUtils.copy_file(path, @tempfile.path)
+ end
+
+ def path
+ @tempfile.path
+ end
+
+ alias_method :local_path, :path
+
+ def method_missing(method_name, *args, &block) #:nodoc:
+ @tempfile.__send__(method_name, *args, &block)
+ end
+
+ end
+
+ end
+end
diff --git a/vendor/rack-test/lib/rack/test/utils.rb b/vendor/rack-test/lib/rack/test/utils.rb
new file mode 100644
index 00000000..d25b8497
--- /dev/null
+++ b/vendor/rack-test/lib/rack/test/utils.rb
@@ -0,0 +1,75 @@
+module Rack
+ module Test
+
+ module Utils
+ include Rack::Utils
+
+ def requestify(value, prefix = nil)
+ case value
+ when Array
+ value.map do |v|
+ requestify(v, "#{prefix}[]")
+ end.join("&")
+ when Hash
+ value.map do |k, v|
+ requestify(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
+ end.join("&")
+ else
+ "#{prefix}=#{escape(value)}"
+ end
+ end
+
+ module_function :requestify
+
+ def multipart_requestify(params, first=true)
+ p = Hash.new
+
+ params.each do |key, value|
+ k = first ? key.to_s : "[#{key}]"
+
+ if Hash === value
+ multipart_requestify(value, false).each do |subkey, subvalue|
+ p[k + subkey] = subvalue
+ end
+ else
+ p[k] = value
+ end
+ end
+
+ return p
+ end
+
+ module_function :multipart_requestify
+
+ def multipart_body(params)
+ multipart_requestify(params).map do |key, value|
+ if value.respond_to?(:original_filename)
+ ::File.open(value.path, "rb") do |f|
+ f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
+
+ <<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{key}"; filename="#{escape(value.original_filename)}"\r
+Content-Type: #{value.content_type}\r
+Content-Length: #{::File.stat(value.path).size}\r
+\r
+#{f.read}\r
+EOF
+ end
+ else
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{key}"\r
+\r
+#{value}\r
+EOF
+ end
+ end.join("")+"--#{MULTIPART_BOUNDARY}--\r"
+ end
+
+ module_function :multipart_body
+
+ end
+
+ end
+end
diff --git a/vendor/rack-test/spec/fixtures/config.ru b/vendor/rack-test/spec/fixtures/config.ru
new file mode 100644
index 00000000..407c9b94
--- /dev/null
+++ b/vendor/rack-test/spec/fixtures/config.ru
@@ -0,0 +1,3 @@
+require "fake_app"
+
+run Rack::Test::FakeApp
diff --git a/vendor/rack-test/spec/fixtures/fake_app.rb b/vendor/rack-test/spec/fixtures/fake_app.rb
new file mode 100644
index 00000000..3b2a7541
--- /dev/null
+++ b/vendor/rack-test/spec/fixtures/fake_app.rb
@@ -0,0 +1,109 @@
+require "sinatra/base"
+
+module Rack
+ module Test
+
+ class FakeApp < Sinatra::Default
+ head "/" do
+ "meh"
+ end
+
+ get "/" do
+ "Hello, GET: #{params.inspect}"
+ end
+
+ get "/redirect" do
+ redirect "/redirected"
+ end
+
+ get "/redirected" do
+ "You've been redirected"
+ end
+
+ get "/void" do
+ [200, {}, ""]
+ end
+
+ get "/cookies/show" do
+ request.cookies.inspect
+ end
+
+ get "/COOKIES/show" do
+ request.cookies.inspect
+ end
+
+ get "/not-cookies/show" do
+ request.cookies.inspect
+ end
+
+ get "/cookies/set-secure" do
+ raise if params["value"].nil?
+
+ response.set_cookie("secure-cookie", :value => params["value"], :secure => true)
+ "Set"
+ end
+
+ get "/cookies/set-simple" do
+ raise if params["value"].nil?
+
+ response.set_cookie "simple", params["value"]
+ "Set"
+ end
+
+ get "/cookies/delete" do
+ response.delete_cookie "value"
+ end
+
+ get "/cookies/count" do
+ old_value = request.cookies["count"].to_i || 0
+ new_value = (old_value + 1).to_s
+
+ response.set_cookie("count", :value => new_value)
+ new_value
+ end
+
+ get "/cookies/set" do
+ raise if params["value"].nil?
+
+ response.set_cookie("value", {
+ :value => params["value"],
+ :path => "/cookies",
+ :expires => Time.now + 10
+ })
+ "Set"
+ end
+
+ get "/cookies/domain" do
+ old_value = request.cookies["count"].to_i || 0
+ new_value = (old_value + 1).to_s
+
+ response.set_cookie("count", :value => new_value, :domain => "localhost.com")
+ new_value
+ end
+
+ get "/cookies/set-uppercase" do
+ raise if params["value"].nil?
+
+ response.set_cookie("VALUE", {
+ :value => params["value"],
+ :path => "/cookies",
+ :expires => Time.now + 10
+ })
+ "Set"
+ end
+
+ post "/" do
+ "Hello, POST: #{params.inspect}"
+ end
+
+ put "/" do
+ "Hello, PUT: #{params.inspect}"
+ end
+
+ delete "/" do
+ "Hello, DELETE: #{params.inspect}"
+ end
+ end
+
+ end
+end
diff --git a/vendor/rack-test/spec/fixtures/foo.txt b/vendor/rack-test/spec/fixtures/foo.txt
new file mode 100644
index 00000000..5716ca59
--- /dev/null
+++ b/vendor/rack-test/spec/fixtures/foo.txt
@@ -0,0 +1 @@
+bar
diff --git a/vendor/rack-test/spec/rack/test/cookie_spec.rb b/vendor/rack-test/spec/rack/test/cookie_spec.rb
new file mode 100644
index 00000000..a008d9c6
--- /dev/null
+++ b/vendor/rack-test/spec/rack/test/cookie_spec.rb
@@ -0,0 +1,176 @@
+require File.dirname(__FILE__) + "/../../spec_helper"
+
+describe Rack::Test::Session do
+ def have_body(string)
+ simple_matcher "have body #{string.inspect}" do |response|
+ response.body.should == string
+ end
+ end
+
+ context "cookies" do
+ it "keeps a cookie jar" do
+ get "/cookies/show"
+ last_request.cookies.should == {}
+
+ get "/cookies/set", "value" => "1"
+ get "/cookies/show"
+ last_request.cookies.should == { "value" => "1" }
+ end
+
+ it "doesn't send expired cookies" do
+ get "/cookies/set", "value" => "1"
+ now = Time.now
+ Time.stub!(:now => now + 60)
+ get "/cookies/show"
+ last_request.cookies.should == {}
+ end
+
+ it "doesn't send cookies with the wrong domain" do
+ get "http://www.example.com/cookies/set", "value" => "1"
+ get "http://www.other.example/cookies/show"
+ last_request.cookies.should == {}
+ end
+
+ it "doesn't send cookies with the wrong path" do
+ get "/cookies/set", "value" => "1"
+ get "/not-cookies/show"
+ last_request.cookies.should == {}
+ end
+
+ it "persists cookies across requests that don't return any cookie headers" do
+ get "/cookies/set", "value" => "1"
+ get "/void"
+ get "/cookies/show"
+ last_request.cookies.should == { "value" => "1" }
+ end
+
+ it "deletes cookies" do
+ get "/cookies/set", "value" => "1"
+ get "/cookies/delete"
+ get "/cookies/show"
+ last_request.cookies.should == { }
+ end
+
+ xit "respects cookie domains when no domain is explicitly set" do
+ request("http://example.org/cookies/count").should have_body("1")
+ request("http://www.example.org/cookies/count").should have_body("1")
+ request("http://example.org/cookies/count").should have_body("2")
+ request("http://www.example.org/cookies/count").should have_body("2")
+ end
+
+ it "treats domains case insensitively" do
+ get "http://example.com/cookies/set", "value" => "1"
+ get "http://EXAMPLE.COM/cookies/show"
+ last_request.cookies.should == { "value" => "1" }
+ end
+
+ it "treats paths case sensitively" do
+ get "/cookies/set", "value" => "1"
+ get "/COOKIES/show"
+ last_request.cookies.should == {}
+ end
+
+ it "prefers more specific cookies" do
+ get "http://example.com/cookies/set", "value" => "domain"
+ get "http://sub.example.com/cookies/set", "value" => "sub"
+
+ get "http://sub.example.com/cookies/show"
+ last_request.cookies.should == { "value" => "sub" }
+
+ get "http://example.com/cookies/show"
+ last_request.cookies.should == { "value" => "domain" }
+ end
+
+ it "treats cookie names case insensitively" do
+ get "/cookies/set", "value" => "lowercase"
+ get "/cookies/set-uppercase", "value" => "UPPERCASE"
+ get "/cookies/show"
+ last_request.cookies.should == { "VALUE" => "UPPERCASE" }
+ end
+
+ it "defaults the domain to the request domain" do
+ get "http://example.com/cookies/set-simple", "value" => "cookie"
+ get "http://example.com/cookies/show"
+ last_request.cookies.should == { "simple" => "cookie" }
+
+ get "http://other.example/cookies/show"
+ last_request.cookies.should == {}
+ end
+
+ it "defaults the domain to the request path up to the last slash" do
+ get "/cookies/set-simple", "value" => "1"
+ get "/not-cookies/show"
+ last_request.cookies.should == {}
+ end
+
+ it "supports secure cookies" do
+ get "https://example.com/cookies/set-secure", "value" => "set"
+ get "http://example.com/cookies/show"
+ last_request.cookies.should == {}
+
+ get "https://example.com/cookies/show"
+ last_request.cookies.should == { "secure-cookie" => "set" }
+ end
+
+ it "keeps separate cookie jars for different domains" do
+ get "http://example.com/cookies/set", "value" => "example"
+ get "http://example.com/cookies/show"
+ last_request.cookies.should == { "value" => "example" }
+
+ get "http://other.example/cookies/set", "value" => "other"
+ get "http://other.example/cookies/show"
+ last_request.cookies.should == { "value" => "other" }
+
+ get "http://example.com/cookies/show"
+ last_request.cookies.should == { "value" => "example" }
+ end
+
+ it "allows cookies to be cleared" do
+ get "/cookies/set", "value" => "1"
+ clear_cookies
+ get "/cookies/show"
+ last_request.cookies.should == {}
+ end
+
+ it "allow cookies to be set" do
+ set_cookie "value=10"
+ get "/cookies/show"
+ last_request.cookies.should == { "value" => "10" }
+ end
+
+ it "allows an array of cookies to be set" do
+ set_cookie ["value=10", "foo=bar"]
+ get "/cookies/show"
+ last_request.cookies.should == { "value" => "10", "foo" => "bar" }
+ end
+
+ it "supports multiple sessions" do
+ with_session(:first) do
+ get "/cookies/set", "value" => "1"
+ get "/cookies/show"
+ last_request.cookies.should == { "value" => "1" }
+ end
+
+ with_session(:second) do
+ get "/cookies/show"
+ last_request.cookies.should == { }
+ end
+ end
+
+ it "uses :default as the default session name" do
+ get "/cookies/set", "value" => "1"
+ get "/cookies/show"
+ last_request.cookies.should == { "value" => "1" }
+
+ with_session(:default) do
+ get "/cookies/show"
+ last_request.cookies.should == { "value" => "1" }
+ end
+ end
+
+ it "accepts explicitly provided cookies" do
+ request "/cookies/show", :cookie => "value=1"
+ last_request.cookies.should == { "value" => "1" }
+ end
+ end
+end
diff --git a/vendor/rack-test/spec/rack/test/digest_auth_spec.rb b/vendor/rack-test/spec/rack/test/digest_auth_spec.rb
new file mode 100644
index 00000000..9e7de744
--- /dev/null
+++ b/vendor/rack-test/spec/rack/test/digest_auth_spec.rb
@@ -0,0 +1,48 @@
+require File.dirname(__FILE__) + "/../../spec_helper"
+
+describe Rack::Test::Session do
+ context "HTTP Digest authentication" do
+
+ def app
+ app = Rack::Auth::Digest::MD5.new(Rack::Test::FakeApp.new) do |username|
+ { 'alice' => 'correct-password' }[username]
+ end
+ app.realm = 'WallysWorld'
+ app.opaque = 'this-should-be-secret'
+ app
+ end
+
+ def be_challenge
+ simple_matcher "a HTTP Digest challenge response" do |response|
+ response.status == 401 &&
+ response['WWW-Authenticate'] =~ /^Digest / &&
+ response.body.empty?
+ end
+ end
+
+ it 'incorrectly authenticates GETs' do
+ digest_authorize 'foo', 'bar'
+ get '/'
+ last_response.should be_challenge
+ end
+
+ it "correctly authenticates GETs" do
+ digest_authorize "alice", "correct-password"
+ response = get "/"
+ response.should be_ok
+ end
+
+ it "correctly authenticates POSTs" do
+ digest_authorize "alice", "correct-password"
+ response = post "/"
+ response.should be_ok
+ end
+
+ it "returns a re-challenge if authenticating incorrectly" do
+ digest_authorize "alice", "incorrect-password"
+ response = get "/"
+ response.should be_challenge
+ end
+
+ end
+end
diff --git a/vendor/rack-test/spec/rack/test/multipart_spec.rb b/vendor/rack-test/spec/rack/test/multipart_spec.rb
new file mode 100644
index 00000000..12351847
--- /dev/null
+++ b/vendor/rack-test/spec/rack/test/multipart_spec.rb
@@ -0,0 +1,85 @@
+require File.dirname(__FILE__) + "/../../spec_helper"
+
+describe Rack::Test::Session do
+
+ def test_file_path
+ File.dirname(__FILE__) + "/../../fixtures/foo.txt"
+ end
+
+ def uploaded_file
+ Rack::Test::UploadedFile.new(test_file_path)
+ end
+
+ context "uploading a file" do
+ it "sends the multipart/form-data content type" do
+ post "/", "photo" => uploaded_file
+ last_request.env["CONTENT_TYPE"].should include("multipart/form-data;")
+ end
+
+ it "sends regular params" do
+ post "/", "photo" => uploaded_file, "foo" => "bar"
+ last_request.POST["foo"].should == "bar"
+ end
+
+ it "sends nested params" do
+ post "/", "photo" => uploaded_file, "foo" => {"bar" => "baz"}
+ last_request.POST["foo"]["bar"].should == "baz"
+ end
+
+ it "sends multiple nested params" do
+ post "/", "photo" => uploaded_file, "foo" => {"bar" => {"baz" => "bop"}}
+ last_request.POST["foo"]["bar"]["baz"].should == "bop"
+ end
+
+ xit "sends params with arrays" do
+ post "/", "photo" => uploaded_file, "foo" => ["1", "2"]
+ last_request.POST["foo[]"].should == ["1", "2"]
+ end
+
+ it "sends params with encoding sensitive values" do
+ post "/", "photo" => uploaded_file, "foo" => "bar? baz"
+ last_request.POST["foo"].should == "bar? baz"
+ end
+
+ it "sends params with parens in names" do
+ post "/", "photo" => uploaded_file, "foo(1i)" => "bar"
+ last_request.POST["foo(1i)"].should == "bar"
+ end
+
+ it "sends params with encoding sensitive names" do
+ post "/", "photo" => uploaded_file, "foo bar" => "baz"
+ last_request.POST["foo bar"].should == "baz"
+ end
+
+ it "sends files with the filename" do
+ post "/", "photo" => uploaded_file
+ last_request.POST["photo"][:filename].should == "foo.txt"
+ end
+
+ it "sends files with the text/plain MIME type by default" do
+ post "/", "photo" => uploaded_file
+ last_request.POST["photo"][:type].should == "text/plain"
+ end
+
+ it "sends files with the right name" do
+ post "/", "photo" => uploaded_file
+ last_request.POST["photo"][:name].should == "photo"
+ end
+
+ it "allows overriding the content type" do
+ post "/", "photo" => Rack::Test::UploadedFile.new(test_file_path, "image/jpeg")
+ last_request.POST["photo"][:type].should == "image/jpeg"
+ end
+
+ it "sends files with a Content-Length in the header" do
+ post "/", "photo" => uploaded_file
+ last_request.POST["photo"][:head].should include("Content-Length: 4")
+ end
+
+ it "sends files as Tempfiles" do
+ post "/", "photo" => uploaded_file
+ last_request.POST["photo"][:tempfile].should be_a(::Tempfile)
+ end
+ end
+
+end
diff --git a/vendor/rack-test/spec/rack/test/utils_spec.rb b/vendor/rack-test/spec/rack/test/utils_spec.rb
new file mode 100644
index 00000000..0a38811d
--- /dev/null
+++ b/vendor/rack-test/spec/rack/test/utils_spec.rb
@@ -0,0 +1,44 @@
+require File.dirname(__FILE__) + "/../../spec_helper"
+
+describe Rack::Test::Utils do
+ include Rack::Test::Utils
+
+ describe "requestify" do
+ it "converts empty strings to =" do
+ requestify("").should == "="
+ end
+
+ it "converts nil to =" do
+ requestify(nil).should == "="
+ end
+
+ it "converts hashes" do
+ requestify(:a => 1).should == "a=1"
+ end
+
+ it "converts hashes with multiple keys" do
+ hash = { :a => 1, :b => 2 }
+ ["a=1&b=2", "b=2&a=1"].should include(requestify(hash))
+ end
+
+ it "converts arrays with one element" do
+ requestify(:a => [1]).should == "a[]=1"
+ end
+
+ it "converts arrays with multiple elements" do
+ requestify(:a => [1, 2]).should == "a[]=1&a[]=2"
+ end
+
+ it "converts nested hashes" do
+ requestify(:a => { :b => 1 }).should == "a[b]=1"
+ end
+
+ it "converts arrays nested in a hash" do
+ requestify(:a => { :b => [1, 2] }).should == "a[b][]=1&a[b][]=2"
+ end
+
+ it "converts arrays of hashes" do
+ requestify(:a => [{ :b => 2}, { :c => 3}]).should == "a[][b]=2&a[][c]=3"
+ end
+ end
+end
diff --git a/vendor/rack-test/spec/rack/test_spec.rb b/vendor/rack-test/spec/rack/test_spec.rb
new file mode 100644
index 00000000..332fbc61
--- /dev/null
+++ b/vendor/rack-test/spec/rack/test_spec.rb
@@ -0,0 +1,363 @@
+require File.dirname(__FILE__) + "/../spec_helper"
+
+describe Rack::Test::Session do
+ describe "initialization" do
+ it "supports being initialized with a Rack::MockSession app" do
+ session = Rack::Test::Session.new(Rack::MockSession.new(app))
+ session.request("/").should be_ok
+ end
+
+ it "supports being initialized with an app" do
+ session = Rack::Test::Session.new(app)
+ session.request("/").should be_ok
+ end
+ end
+
+ describe "#request" do
+ it "requests the URI using GET by default" do
+ request "/"
+ last_request.should be_get
+ last_response.should be_ok
+ end
+
+ it "returns a response" do
+ request("/").should be_ok
+ end
+
+ it "uses the provided env" do
+ request "/", "X-Foo" => "bar"
+ last_request.env["X-Foo"].should == "bar"
+ end
+
+ it "defaults to GET" do
+ request "/"
+ last_request.env["REQUEST_METHOD"].should == "GET"
+ end
+
+ it "defaults the REMOTE_ADDR to 127.0.0.1" do
+ request "/"
+ last_request.env["REMOTE_ADDR"].should == "127.0.0.1"
+ end
+
+ it "sets rack.test to true in the env" do
+ request "/"
+ last_request.env["rack.test"].should == true
+ end
+
+ it "defaults to port 80" do
+ request "/"
+ last_request.env["SERVER_PORT"].should == "80"
+ end
+
+ it "defaults to example.org" do
+ request "/"
+ last_request.env["SERVER_NAME"].should == "example.org"
+ end
+
+ it "yields the response to a given block" do
+ request "/" do |response|
+ response.should be_ok
+ end
+ end
+
+ it "supports sending :params" do
+ request "/", :params => { "foo" => "bar" }
+ last_request.GET["foo"].should == "bar"
+ end
+
+ it "doesn't follow redirects by default" do
+ request "/redirect"
+ last_response.should be_redirect
+ last_response.body.should be_empty
+ end
+
+ context "when input is given" do
+ it "should send the input" do
+ request "/", :method => "POST", :input => "foo"
+ last_request.env["rack.input"].read.should == "foo"
+ end
+
+ it "should not send a multipart request" do
+ request "/", :method => "POST", :input => "foo"
+ last_request.env["CONTENT_TYPE"].should_not == "application/x-www-form-urlencoded"
+ end
+ end
+
+ context "for a POST specified with :method" do
+ it "uses application/x-www-form-urlencoded as the CONTENT_TYPE" do
+ request "/", :method => "POST"
+ last_request.env["CONTENT_TYPE"].should == "application/x-www-form-urlencoded"
+ end
+ end
+
+ context "for a POST specified with REQUEST_METHOD" do
+ it "uses application/x-www-form-urlencoded as the CONTENT_TYPE" do
+ request "/", "REQUEST_METHOD" => "POST"
+ last_request.env["CONTENT_TYPE"].should == "application/x-www-form-urlencoded"
+ end
+ end
+
+ context "when CONTENT_TYPE is specified in the env" do
+ it "does not overwrite the CONTENT_TYPE" do
+ request "/", "CONTENT_TYPE" => "application/xml"
+ last_request.env["CONTENT_TYPE"].should == "application/xml"
+ end
+ end
+
+ context "when the URL is https://" do
+ it "sets SERVER_PORT to 443" do
+ get "https://example.org/"
+ last_request.env["SERVER_PORT"].should == "443"
+ end
+
+ it "sets HTTPS to on" do
+ get "https://example.org/"
+ last_request.env["HTTPS"].should == "on"
+ end
+ end
+
+ context "for a XHR" do
+ it "sends XMLHttpRequest for the X-Requested-With header" do
+ request "/", :xhr => true
+ last_request.env["X-Requested-With"].should == "XMLHttpRequest"
+ end
+ end
+ end
+
+ describe "#header" do
+ it "sets a header to be sent with requests" do
+ header "User-Agent", "Firefox"
+ request "/"
+
+ last_request.env["User-Agent"].should == "Firefox"
+ end
+
+ it "persists across multiple requests" do
+ header "User-Agent", "Firefox"
+ request "/"
+ request "/"
+
+ last_request.env["User-Agent"].should == "Firefox"
+ end
+
+ it "overwrites previously set headers" do
+ header "User-Agent", "Firefox"
+ header "User-Agent", "Safari"
+ request "/"
+
+ last_request.env["User-Agent"].should == "Safari"
+ end
+
+ it "can be used to clear a header" do
+ header "User-Agent", "Firefox"
+ header "User-Agent", nil
+ request "/"
+
+ last_request.env.should_not have_key("User-Agent")
+ end
+
+ it "is overridden by headers sent during the request" do
+ header "User-Agent", "Firefox"
+ request "/", "User-Agent" => "Safari"
+
+ last_request.env["User-Agent"].should == "Safari"
+ end
+ end
+
+ describe "#authorize" do
+ it "sets the HTTP_AUTHORIZATION header" do
+ authorize "bryan", "secret"
+ request "/"
+
+ last_request.env["HTTP_AUTHORIZATION"].should == "Basic YnJ5YW46c2VjcmV0\n"
+ end
+
+ it "includes the header for subsequent requests" do
+ basic_authorize "bryan", "secret"
+ request "/"
+ request "/"
+
+ last_request.env["HTTP_AUTHORIZATION"].should == "Basic YnJ5YW46c2VjcmV0\n"
+ end
+ end
+
+ describe "follow_redirect!" do
+ it "follows redirects" do
+ get "/redirect"
+ follow_redirect!
+
+ last_response.should_not be_redirect
+ last_response.body.should == "You've been redirected"
+ end
+
+ it "does not include params when following the redirect" do
+ get "/redirect", { "foo" => "bar" }
+ follow_redirect!
+
+ last_request.GET.should == {}
+ end
+
+ it "raises an error if the last_response is not set" do
+ lambda {
+ follow_redirect!
+ }.should raise_error(Rack::Test::Error)
+ end
+
+ it "raises an error if the last_response is not a redirect" do
+ get "/"
+
+ lambda {
+ follow_redirect!
+ }.should raise_error(Rack::Test::Error)
+ end
+ end
+
+ describe "#last_request" do
+ it "returns the most recent request" do
+ request "/"
+ last_request.env["PATH_INFO"].should == "/"
+ end
+
+ it "raises an error if no requests have been issued" do
+ lambda {
+ last_request
+ }.should raise_error(Rack::Test::Error)
+ end
+ end
+
+ describe "#last_response" do
+ it "returns the most recent response" do
+ request "/"
+ last_response["Content-Type"].should == "text/html"
+ end
+
+ it "raises an error if no requests have been issued" do
+ lambda {
+ last_response
+ }.should raise_error
+ end
+ end
+
+ describe "after_request" do
+ it "runs callbacks after each request" do
+ ran = false
+
+ rack_mock_session.after_request do
+ ran = true
+ end
+
+ get "/"
+ ran.should == true
+ end
+
+ it "runs multiple callbacks" do
+ count = 0
+
+ 2.times do
+ rack_mock_session.after_request do
+ count += 1
+ end
+ end
+
+ get "/"
+ count.should == 2
+ end
+ end
+
+ describe "#get" do
+ it_should_behave_like "any #verb methods"
+
+ def verb
+ "get"
+ end
+
+ it "uses the provided params hash" do
+ get "/", :foo => "bar"
+ last_request.GET.should == { "foo" => "bar" }
+ end
+
+ it "sends params with parens in names" do
+ get "/", "foo(1i)" => "bar"
+ last_request.GET["foo(1i)"].should == "bar"
+ end
+
+ it "supports params with encoding sensitive names" do
+ get "/", "foo bar" => "baz"
+ last_request.GET["foo bar"].should == "baz"
+ end
+
+ it "supports params with nested encoding sensitive names" do
+ get "/", "boo" => {"foo bar" => "baz"}
+ last_request.GET.should == {"boo" => {"foo bar" => "baz"}}
+ end
+
+ it "accepts params in the path" do
+ get "/?foo=bar"
+ last_request.GET.should == { "foo" => "bar" }
+ end
+ end
+
+ describe "#head" do
+ it_should_behave_like "any #verb methods"
+
+ def verb
+ "head"
+ end
+ end
+
+ describe "#post" do
+ it_should_behave_like "any #verb methods"
+
+ def verb
+ "post"
+ end
+
+ it "uses the provided params hash" do
+ post "/", :foo => "bar"
+ last_request.POST.should == { "foo" => "bar" }
+ end
+
+ it "supports params with encoding sensitive names" do
+ post "/", "foo bar" => "baz"
+ last_request.POST["foo bar"].should == "baz"
+ end
+
+ it "uses application/x-www-form-urlencoded as the CONTENT_TYPE" do
+ post "/"
+ last_request.env["CONTENT_TYPE"].should == "application/x-www-form-urlencoded"
+ end
+
+ it "accepts a body" do
+ post "/", "Lobsterlicious!"
+ last_request.body.read.should == "Lobsterlicious!"
+ end
+
+ context "when CONTENT_TYPE is specified in the env" do
+ it "does not overwrite the CONTENT_TYPE" do
+ post "/", {}, { "CONTENT_TYPE" => "application/xml" }
+ last_request.env["CONTENT_TYPE"].should == "application/xml"
+ end
+ end
+ end
+
+ describe "#put" do
+ it_should_behave_like "any #verb methods"
+
+ def verb
+ "put"
+ end
+
+ it "accepts a body" do
+ put "/", "Lobsterlicious!"
+ last_request.body.read.should == "Lobsterlicious!"
+ end
+ end
+
+ describe "#delete" do
+ it_should_behave_like "any #verb methods"
+
+ def verb
+ "delete"
+ end
+ end
+end
diff --git a/vendor/rack-test/spec/rcov.opts b/vendor/rack-test/spec/rcov.opts
new file mode 100644
index 00000000..9ed978e1
--- /dev/null
+++ b/vendor/rack-test/spec/rcov.opts
@@ -0,0 +1 @@
+-x gems,spec
diff --git a/vendor/rack-test/spec/spec.opts b/vendor/rack-test/spec/spec.opts
new file mode 100644
index 00000000..4e1e0d2f
--- /dev/null
+++ b/vendor/rack-test/spec/spec.opts
@@ -0,0 +1 @@
+--color
diff --git a/vendor/rack-test/spec/spec_helper.rb b/vendor/rack-test/spec/spec_helper.rb
new file mode 100644
index 00000000..c18479ef
--- /dev/null
+++ b/vendor/rack-test/spec/spec_helper.rb
@@ -0,0 +1,48 @@
+require "rubygems"
+require "spec"
+
+gem "rack", "~> 1.0.0"
+
+require File.expand_path(File.dirname(__FILE__) + "/../lib/rack/test")
+require File.dirname(__FILE__) + "/fixtures/fake_app"
+
+Spec::Runner.configure do |config|
+ config.include Rack::Test::Methods
+
+ def app
+ Rack::Lint.new(Rack::Test::FakeApp.new)
+ end
+
+end
+
+describe "any #verb methods", :shared => true do
+ it "requests the URL using VERB" do
+ send(verb, "/")
+
+ last_request.env["REQUEST_METHOD"].should == verb.upcase
+ last_response.should be_ok
+ end
+
+ it "uses the provided env" do
+ send(verb, "/", {}, { "User-Agent" => "Rack::Test" })
+ last_request.env["User-Agent"].should == "Rack::Test"
+ end
+
+ it "yields the response to a given block" do
+ yielded = false
+
+ send(verb, "/") do |response|
+ response.should be_ok
+ yielded = true
+ end
+
+ yielded.should be_true
+ end
+
+ context "for a XHR" do
+ it "sends XMLHttpRequest for the X-Requested-With header" do
+ send(verb, "/", {}, { :xhr => true })
+ last_request.env["X-Requested-With"].should == "XMLHttpRequest"
+ end
+ end
+end
diff --git a/vendor/sinatra-content-for/LICENSE b/vendor/sinatra-content-for/LICENSE
new file mode 100644
index 00000000..3eb6c2f4
--- /dev/null
+++ b/vendor/sinatra-content-for/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2008-2009 Nicolas Sanguinetti, entp.com
+
+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/vendor/sinatra-content-for/README.rdoc b/vendor/sinatra-content-for/README.rdoc
new file mode 100644
index 00000000..cf7c2abb
--- /dev/null
+++ b/vendor/sinatra-content-for/README.rdoc
@@ -0,0 +1,49 @@
+= ContentFor
+
+Small extension for the Sinatra[http://sinatrarb.com] web framework
+that allows you to use the following helpers in your views:
+
+ <% content_for :some_key do %>
+ ...
+ <% end %>
+
+ <% yield_content :some_key %>
+
+This allows you to capture blocks inside views to be rendered later
+in this request. For example, to populate different parts of your
+layout from your view.
+
+When using this with the Haml rendering engine, you should do the
+following:
+
+ - content_for :some_key do
+ %chunk{ :of => "html" } ...
+
+ = yield_content :some_key
+
+Note that with ERB yield_content is called without
+an '=' block (<%= %>), but with Haml it uses = yield_content.
+
+Using an '=' block in ERB will output the content twice for each block,
+so if you have problems with that, make sure to check for this.
+
+== Usage
+
+If you're writing "classic" style apps, then requring
+sinatra/content_for should be enough. If you're writing
+"classy" apps, then you also need to call
+helpers Sinatra::ContentFor in your app definition.
+
+== And how is this useful?
+
+For example, some of your views might need a few javascript tags and
+stylesheets, but you don't want to force this files in all your pages.
+Then you can put <% yield_content :scripts_and_styles %> on
+your layout, inside the tag, and each view can call
+content_for setting the appropriate set of tags that should
+be added to the layout.
+
+== Credits
+
+Code by foca[http://github.com/foca], inspired on the Ruby on Rails
+helpers with the same name. Haml support by mattly[http://github.com/mattly].
diff --git a/vendor/sinatra-content-for/Rakefile b/vendor/sinatra-content-for/Rakefile
new file mode 100644
index 00000000..37989821
--- /dev/null
+++ b/vendor/sinatra-content-for/Rakefile
@@ -0,0 +1,33 @@
+require "rake/testtask"
+
+begin
+ require "hanna/rdoctask"
+rescue LoadError
+ require "rake/rdoctask"
+end
+
+begin
+ require "metric_fu"
+rescue LoadError
+end
+
+begin
+ require "mg"
+ MG.new("sinatra-content-for.gemspec")
+rescue LoadError
+end
+
+desc "Default: run all tests"
+task :default => :test
+
+desc "Run library tests"
+Rake::TestTask.new do |t|
+ t.test_files = FileList['test/**/*_test.rb']
+end
+
+Rake::RDocTask.new do |rd|
+ rd.main = "README"
+ rd.title = "Documentation for ContentFor"
+ rd.rdoc_files.include("README.rdoc", "LICENSE", "lib/**/*.rb")
+ rd.rdoc_dir = "doc"
+end
diff --git a/vendor/sinatra-content-for/lib/sinatra/content_for.rb b/vendor/sinatra-content-for/lib/sinatra/content_for.rb
new file mode 100644
index 00000000..31848c63
--- /dev/null
+++ b/vendor/sinatra-content-for/lib/sinatra/content_for.rb
@@ -0,0 +1,58 @@
+module Sinatra
+ module ContentFor
+ # Capture a block of content to be rendered later. For example:
+ #
+ # <% content_for :head do %>
+ #
+ # <% end %>
+ #
+ # You can call +content_for+ multiple times with the same key
+ # (in the example +:head+), and when you render the blocks for
+ # that key all of them will be rendered, in the same order you
+ # captured them.
+ #
+ # Your blocks can also receive values, which are passed to them
+ # by yield_content
+ def content_for(key, &block)
+ content_blocks[key.to_sym] << block
+ end
+
+ # Render the captured blocks for a given key. For example:
+ #
+ #
+ # Example
+ # <% yield_content :head %>
+ #
+ #
+ # Would render everything you declared with content_for
+ # :head before closing the tag.
+ #
+ # You can also pass values to the content blocks by passing them
+ # as arguments after the key:
+ #
+ # <% yield_content :head, 1, 2 %>
+ #
+ # Would pass 1 and 2 to all the blocks registered
+ # for :head.
+ #
+ # *NOTICE* that you call this without an = sign. IE,
+ # in a <% %> block, and not in a <%= %> block.
+ def yield_content(key, *args)
+ content_blocks[key.to_sym].map do |content|
+ if respond_to?(:block_is_haml?) && block_is_haml?(content)
+ capture_haml(*args, &content)
+ else
+ content.call(*args)
+ end
+ end.join
+ end
+
+ private
+
+ def content_blocks
+ @content_blocks ||= Hash.new {|h,k| h[k] = [] }
+ end
+ end
+
+ helpers ContentFor
+end
diff --git a/vendor/sinatra-content-for/sinatra-content-for.gemspec b/vendor/sinatra-content-for/sinatra-content-for.gemspec
new file mode 100644
index 00000000..63242e6b
--- /dev/null
+++ b/vendor/sinatra-content-for/sinatra-content-for.gemspec
@@ -0,0 +1,34 @@
+Gem::Specification.new do |s|
+ s.name = "sinatra-content-for"
+ s.version = "0.2"
+ s.date = "2009-05-09"
+
+ s.description = "Small Sinatra extension to add a content_for helper similar to Rails'"
+ s.summary = "Small Sinatra extension to add a content_for helper similar to Rails'"
+ s.homepage = "http://sinatrarb.com"
+
+ s.authors = ["Nicolás Sanguinetti"]
+ s.email = "contacto@nicolassanguinetti.info"
+
+ s.require_paths = ["lib"]
+ s.rubyforge_project = "sinatra-ditties"
+ s.has_rdoc = true
+ s.rubygems_version = "1.3.1"
+
+ s.add_dependency "sinatra"
+
+ if s.respond_to?(:add_development_dependency)
+ s.add_development_dependency "contest"
+ s.add_development_dependency "sr-mg"
+ s.add_development_dependency "redgreen"
+ end
+
+ s.files = %w[
+.gitignore
+LICENSE
+README.rdoc
+sinatra-content-for.gemspec
+lib/sinatra/content_for.rb
+test/content_for_test.rb
+]
+end
diff --git a/vendor/sinatra-content-for/test/content_for_test.rb b/vendor/sinatra-content-for/test/content_for_test.rb
new file mode 100644
index 00000000..c9560f22
--- /dev/null
+++ b/vendor/sinatra-content-for/test/content_for_test.rb
@@ -0,0 +1,156 @@
+ENV['RACK_ENV'] = 'test'
+
+begin
+ require 'rack'
+rescue LoadError
+ require 'rubygems'
+ require 'rack'
+end
+
+require 'contest'
+require 'sinatra/test'
+require 'haml'
+
+begin
+ require 'redgreen'
+rescue LoadError
+end
+
+require File.dirname(__FILE__) + '/../lib/sinatra/content_for'
+
+Sinatra::Base.set :environment, :test
+
+module Sinatra
+ class Base
+ set :environment, :test
+ helpers ContentFor
+ end
+end
+
+class Test::Unit::TestCase
+ include Sinatra::Test
+
+ class << self
+ alias_method :it, :test
+ end
+
+ def mock_app(base=Sinatra::Base, &block)
+ @app = Sinatra.new(base, &block)
+ end
+end
+
+class ContentForTest < Test::Unit::TestCase
+ context 'using erb' do
+ def erb_app(view)
+ mock_app {
+ layout { '<% yield_content :foo %>' }
+ get('/') { erb view }
+ }
+ end
+
+ it 'renders blocks declared with the same key you use when rendering' do
+ erb_app '<% content_for :foo do %>foo<% end %>'
+
+ get '/'
+ assert ok?
+ assert_equal 'foo', body
+ end
+
+ it 'does not render a block with a different key' do
+ erb_app '<% content_for :bar do %>bar<% end %>'
+
+ get '/'
+ assert ok?
+ assert_equal '', body
+ end
+
+ it 'renders multiple blocks with the same key' do
+ erb_app <<-erb_snippet
+ <% content_for :foo do %>foo<% end %>
+ <% content_for :foo do %>bar<% end %>
+ <% content_for :baz do %>WON'T RENDER ME<% end %>
+ <% content_for :foo do %>baz<% end %>
+ erb_snippet
+
+ get '/'
+ assert ok?
+ assert_equal 'foobarbaz', body
+ end
+
+ it 'passes values to the blocks' do
+ mock_app {
+ layout { '<% yield_content :foo, 1, 2 %>' }
+ get('/') { erb '<% content_for :foo do |a, b| %><%= a %> <%= b %><% end %>' }
+ }
+
+ get '/'
+ assert ok?
+ assert_equal '1 2', body
+ end
+ end
+
+ context 'with haml' do
+ def haml_app(view)
+ mock_app {
+ layout { '= yield_content :foo' }
+ get('/') { haml view }
+ }
+ end
+
+ it 'renders blocks declared with the same key you use when rendering' do
+ haml_app <<-haml_end
+- content_for :foo do
+ foo
+haml_end
+
+ get '/'
+ assert ok?
+ assert_equal "foo\n", body
+ end
+
+ it 'does not render a block with a different key' do
+ haml_app <<-haml_end
+- content_for :bar do
+ bar
+haml_end
+
+ get '/'
+ assert ok?
+ assert_equal "\n", body
+ end
+
+ it 'renders multiple blocks with the same key' do
+ haml_app <<-haml_end
+- content_for :foo do
+ foo
+- content_for :foo do
+ bar
+- content_for :baz do
+ WON'T RENDER ME
+- content_for :foo do
+ baz
+haml_end
+
+ get '/'
+ assert ok?
+ assert_equal "foo\nbar\nbaz\n", body
+ end
+
+ it 'passes values to the blocks' do
+ mock_app {
+ layout { '= yield_content :foo, 1, 2' }
+ get('/') {
+ haml <<-haml_end
+- content_for :foo do |a, b|
+ %i= a
+ =b
+haml_end
+ }
+ }
+
+ get '/'
+ assert ok?
+ assert_equal "1\n2\n", body
+ end
+ end
+end
diff --git a/vendor/sinatra-markaby/CHANGES b/vendor/sinatra-markaby/CHANGES
new file mode 100644
index 00000000..802e5133
--- /dev/null
+++ b/vendor/sinatra-markaby/CHANGES
@@ -0,0 +1,7 @@
+= 0.9.2.2
+
+* layout support is tested
+
+= 0.9.2.1
+
+* use Rack::Test instead of Sinatra::Test
diff --git a/vendor/sinatra-markaby/LICENSE b/vendor/sinatra-markaby/LICENSE
new file mode 100644
index 00000000..333cf6f2
--- /dev/null
+++ b/vendor/sinatra-markaby/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 unwwwired.net
+
+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/vendor/sinatra-markaby/README.rdoc b/vendor/sinatra-markaby/README.rdoc
new file mode 100644
index 00000000..0815c81d
--- /dev/null
+++ b/vendor/sinatra-markaby/README.rdoc
@@ -0,0 +1,33 @@
+= sinatra-markaby
+
+sinatra-markaby is an extension for sinatra to enable rendering of html files
+using markaby templates.
+
+== Installation
+
+ sudo gem install sbfaulkner-sinatra-markaby -s http://gems.github.com
+
+== Example
+
+ require 'rubygems'
+ require 'sinatra'
+ require 'sinatra/markaby'
+
+ get '/' do
+ markaby :template
+ end
+
+ __END__
+
+ @@ template
+ mab.html do
+ head { title "Hello world" }
+ body do
+ p "Hello world!!!!!"
+ end
+ end
+
+== Legal
+
+Author:: S. Brent Faulkner
+License:: Copyright (c) 2009 unwwwired.net, released under the MIT license
diff --git a/vendor/sinatra-markaby/Rakefile b/vendor/sinatra-markaby/Rakefile
new file mode 100644
index 00000000..bad3f2ee
--- /dev/null
+++ b/vendor/sinatra-markaby/Rakefile
@@ -0,0 +1,45 @@
+require 'rake'
+
+begin
+ require 'jeweler'
+ Jeweler::Tasks.new do |s|
+ s.name = "sinatra-markaby"
+ s.summary = %Q{Sinatra plugin to enable markaby (.mab) template rendering.}
+ s.email = "brentf@unwwwired.net"
+ s.homepage = "http://github.com/sbfaulkner/sinatra-markaby"
+ s.description = "Sinatra plugin to enable markaby (.mab) template rendering."
+ s.authors = ["S. Brent Faulkner"]
+ s.add_dependency "markaby"
+ end
+rescue LoadError
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
+end
+
+require 'rake/rdoctask'
+Rake::RDocTask.new do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'sinatra-markaby'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README*')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+require 'rake/testtask'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib' << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = false
+end
+
+begin
+ require 'rcov/rcovtask'
+ Rcov::RcovTask.new do |t|
+ t.libs << 'test'
+ t.test_files = FileList['test/**/*_test.rb']
+ t.verbose = true
+ end
+rescue LoadError
+ puts "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
+end
+
+task :default => :test
diff --git a/vendor/sinatra-markaby/TODO b/vendor/sinatra-markaby/TODO
new file mode 100644
index 00000000..39a2947d
--- /dev/null
+++ b/vendor/sinatra-markaby/TODO
@@ -0,0 +1,3 @@
+= TODO
+
+* refactor render/views in sinatra
\ No newline at end of file
diff --git a/vendor/sinatra-markaby/VERSION.yml b/vendor/sinatra-markaby/VERSION.yml
new file mode 100644
index 00000000..8ee2d0c5
--- /dev/null
+++ b/vendor/sinatra-markaby/VERSION.yml
@@ -0,0 +1,4 @@
+---
+:major: 0
+:minor: 9
+:patch: 2.2
diff --git a/vendor/sinatra-markaby/lib/sinatra/markaby.rb b/vendor/sinatra-markaby/lib/sinatra/markaby.rb
new file mode 100644
index 00000000..611eee04
--- /dev/null
+++ b/vendor/sinatra-markaby/lib/sinatra/markaby.rb
@@ -0,0 +1,31 @@
+require 'sinatra/base'
+require 'markaby'
+
+module Sinatra
+ module Markaby
+ # Generate html file using Markaby.
+ # Takes the name of a template to render as a Symbol and returns a String with the rendered output.
+ #
+ # Options for markaby may be specified in Sinatra using set :markaby, { ... }
+ # TODO: the options aren't actually used yet
+ def mab(template=nil, options={}, locals = {}, &block)
+ options, template = template, nil if template.is_a?(Hash)
+ template = lambda { block } if template.nil?
+ render :mab, template, options, locals
+ end
+
+ protected
+ def render_mab(template, data, options, locals, &block)
+ filename = options.delete(:filename) || ''
+ line = options.delete(:line) || 1
+ mab = ::Markaby::Builder.new(locals)
+ if data.respond_to?(:to_str)
+ eval(data.to_str, binding, filename, line)
+ elsif data.kind_of?(Proc)
+ data.call(mab)
+ end
+ end
+ end
+
+ helpers Markaby
+end
diff --git a/vendor/sinatra-markaby/sinatra-markaby.gemspec b/vendor/sinatra-markaby/sinatra-markaby.gemspec
new file mode 100644
index 00000000..648a4b39
--- /dev/null
+++ b/vendor/sinatra-markaby/sinatra-markaby.gemspec
@@ -0,0 +1,49 @@
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{sinatra-markaby}
+ s.version = "0.9.2.2"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["S. Brent Faulkner"]
+ s.date = %q{2009-04-29}
+ s.description = %q{Sinatra plugin to enable markaby (.mab) template rendering.}
+ s.email = %q{brentf@unwwwired.net}
+ s.extra_rdoc_files = [
+ "LICENSE",
+ "README.rdoc"
+ ]
+ s.files = [
+ "LICENSE",
+ "README.rdoc",
+ "Rakefile",
+ "VERSION.yml",
+ "lib/sinatra/markaby.rb",
+ "test/sinatra_markaby_test.rb",
+ "test/test_helper.rb",
+ "test/views/hello.mab"
+ ]
+ s.has_rdoc = true
+ s.homepage = %q{http://github.com/sbfaulkner/sinatra-markaby}
+ s.rdoc_options = ["--charset=UTF-8"]
+ s.require_paths = ["lib"]
+ s.rubygems_version = %q{1.3.1}
+ s.summary = %q{Sinatra plugin to enable markaby (.mab) template rendering.}
+ s.test_files = [
+ "test/sinatra_markaby_test.rb",
+ "test/test_helper.rb"
+ ]
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 2
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ s.add_runtime_dependency(%q, [">= 0"])
+ else
+ s.add_dependency(%q, [">= 0"])
+ end
+ else
+ s.add_dependency(%q, [">= 0"])
+ end
+end
diff --git a/vendor/sinatra-markaby/test/sinatra_markaby_test.rb b/vendor/sinatra-markaby/test/sinatra_markaby_test.rb
new file mode 100644
index 00000000..edee03ff
--- /dev/null
+++ b/vendor/sinatra-markaby/test/sinatra_markaby_test.rb
@@ -0,0 +1,72 @@
+require File.dirname(__FILE__) + '/test_helper'
+
+class SinatraMarkabyTest < Test::Unit::TestCase
+ def markaby_app(&block)
+ mock_app {
+ use_in_file_templates!
+ helpers Sinatra::Markaby
+ set :views, File.dirname(__FILE__) + '/views'
+ get '/', &block
+ }
+ get '/'
+ end
+
+ def test_renders_inline_strings
+ markaby_app { markaby 'mab.p "Hello shrimp!"' }
+ assert last_response.ok?
+ assert_equal 'Hello shrimp!
', last_response.body
+ end
+
+ def test_renders_inline_blocks
+ markaby_app {
+ @name = 'Frank & Mary'
+ markaby do |mab|
+ mab.p "Hello #{@name}!"
+ end
+ }
+ assert last_response.ok?
+ assert_equal 'Hello Frank & Mary!
', last_response.body
+ end
+
+ def test_renders_markaby_files_in_views_path
+ markaby_app {
+ @name = 'World'
+ markaby :hello
+ }
+ assert last_response.ok?
+ assert_equal 'Hello, World!
', last_response.body
+ end
+
+ def test_renders_in_file_template
+ markaby_app {
+ @name = 'Joe'
+ markaby :in_file
+ }
+ assert last_response.ok?
+ assert_equal 'Hey Joe
', last_response.body
+ end
+
+ def test_renders_with_layout
+ markaby_app {
+ @name = 'with Layout'
+ markaby :hello, :layout => :html
+ }
+ assert last_response.ok?
+ assert_equal 'HelloHello, with Layout!
', last_response.body
+ end
+
+ def test_raises_error_if_template_not_found
+ mock_app {
+ helpers Sinatra::Markaby
+ set :environment, :test
+ set :raise_errors, true
+ get('/') { markaby :no_such_template }
+ }
+ assert_raises(Errno::ENOENT) { get('/') }
+ end
+end
+
+__END__
+
+@@ in_file
+mab.p "Hey #{@name}"
diff --git a/vendor/sinatra-markaby/test/test_helper.rb b/vendor/sinatra-markaby/test/test_helper.rb
new file mode 100644
index 00000000..60fd6bfe
--- /dev/null
+++ b/vendor/sinatra-markaby/test/test_helper.rb
@@ -0,0 +1,19 @@
+require 'rubygems'
+require 'test/unit'
+require 'rack/test'
+
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+require 'sinatra/markaby'
+
+class Test::Unit::TestCase
+ include Rack::Test::Methods
+
+ attr_reader :app
+
+ # Sets up a Sinatra::Base subclass defined with the block
+ # given. Used in setup or individual spec methods to establish
+ # the application.
+ def mock_app(base=Sinatra::Base, &block)
+ @app = Sinatra.new(base, &block)
+ end
+end
diff --git a/vendor/sinatra-markaby/test/views/hello.mab b/vendor/sinatra-markaby/test/views/hello.mab
new file mode 100644
index 00000000..afd9080a
--- /dev/null
+++ b/vendor/sinatra-markaby/test/views/hello.mab
@@ -0,0 +1 @@
+mab.p "Hello, #{@name}!"
diff --git a/vendor/sinatra-markaby/test/views/html.mab b/vendor/sinatra-markaby/test/views/html.mab
new file mode 100644
index 00000000..a49025b7
--- /dev/null
+++ b/vendor/sinatra-markaby/test/views/html.mab
@@ -0,0 +1,4 @@
+mab.html do
+ head { title "Hello" }
+ body { yield }
+end
\ No newline at end of file
diff --git a/vendor/sinatra-maruku/LICENSE b/vendor/sinatra-maruku/LICENSE
new file mode 100644
index 00000000..222dc0bc
--- /dev/null
+++ b/vendor/sinatra-maruku/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2008 Wlodek Bzyl
+
+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/vendor/sinatra-maruku/README.markdown b/vendor/sinatra-maruku/README.markdown
new file mode 100644
index 00000000..bb2bad9f
--- /dev/null
+++ b/vendor/sinatra-maruku/README.markdown
@@ -0,0 +1,85 @@
+# Sinatra Maruku Extension
+
+The *sinatra-maruku* extension provides `maruku` helper method
+for rendering Maruku templates.
+
+To install it, run:
+
+ sudo gem install wbzyl-sinatra-maruku -s http://gems.github.com
+
+To test it, create a simple Sinatra application:
+
+ # app.rb
+ require 'rubygems'
+ require 'sinatra'
+
+ gem 'wbzyl-sinatra-maruku'
+ require 'sinatra/maruku'
+
+ get "/" do
+ maruku "# Hello Maruku"
+ end
+
+and run it with:
+
+ ruby app.rb
+
+The result could be seen at *http://localhost:4567*.
+
+Another example could be find in the *examples* directory.
+Run it with:
+
+ rackup -p 4567 config.ru
+
+and visit *http://localhost:4567* to contemplate the sheer
+beauty of rendered text written in Maruku notation.
+
+
+## Two links to Maruku related material
+
+* [Maruku features](http://maruku.rubyforge.org/maruku.html)
+* [Literate Maruku](http://www.slideshare.net/schmidt/literate-maruku)
+
+
+## Template Languages (*update to The Sinatra Book*)
+
+### Maruku Templates
+
+This helper method:
+
+ get '/' do
+ maruku :index
+ end
+
+renders template *./views/index.maruku*.
+
+If a layout named *layout.maruku* exists, it will be used each time
+a template is rendered.
+
+You can disable layouts by passing `:layout => false`
+to *maruku* helper. For example
+
+ get '/' do
+ maruku :index, :layout => false
+ end
+
+You can set a different layout from the default one with:
+
+ get '/' do
+ maruku :index, :layout => :application
+ end
+
+This renders *./views/index.maruku* template
+within *./views/application.maruku* layout.
+
+
+## Sample layout for Maruku templates
+
+ CSS: /stylesheets/application.css /stylesheets/print.css
+ Lang: pl
+ Title: Hello Maruku
+ LaTeX preamble: preamble.tex
+
+ # Hello Maruku {.header}
+
+ <%= yield %>
diff --git a/vendor/sinatra-maruku/Rakefile b/vendor/sinatra-maruku/Rakefile
new file mode 100644
index 00000000..eb96caef
--- /dev/null
+++ b/vendor/sinatra-maruku/Rakefile
@@ -0,0 +1,34 @@
+require 'rake'
+require 'rake/testtask'
+require "rake/clean"
+
+begin
+ require 'jeweler'
+ Jeweler::Tasks.new do |gem|
+ gem.name = "sinatra-maruku"
+ gem.summary = "An extension providing Maruku templates for Sinatra applications."
+ gem.email = "matwb@univ.gda.pl"
+ gem.homepage = "http://github.com/wbzyl/sinatra-maruku"
+ gem.description = gem.description
+ gem.authors = ["Wlodek Bzyl"]
+
+ gem.add_runtime_dependency 'sinatra', '>=0.10.1'
+ gem.add_runtime_dependency 'maruku', '>=0.6.0'
+
+ gem.add_development_dependency 'rack', '>=1.0.0'
+ gem.add_development_dependency 'rack-test', '>=0.3.0'
+
+ # gem is a Gem::Specification
+ # refer to http://www.rubygems.org/read/chapter/20 for additional settings
+ end
+rescue LoadError
+ puts "Jeweler not available."
+ puts "Install it with:"
+ puts " sudo gem install technicalpickles-jeweler -s http://gems.github.com"
+end
+
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib' << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = false
+end
diff --git a/vendor/sinatra-maruku/VERSION.yml b/vendor/sinatra-maruku/VERSION.yml
new file mode 100644
index 00000000..eface56c
--- /dev/null
+++ b/vendor/sinatra-maruku/VERSION.yml
@@ -0,0 +1,4 @@
+---
+:major: 0
+:minor: 10
+:patch: 1
diff --git a/vendor/sinatra-maruku/examples/app.rb b/vendor/sinatra-maruku/examples/app.rb
new file mode 100644
index 00000000..f760b06f
--- /dev/null
+++ b/vendor/sinatra-maruku/examples/app.rb
@@ -0,0 +1,8 @@
+require 'rubygems'
+require 'sinatra'
+require 'sinatra/maruku'
+
+get "/" do
+ #maruku :hello, :layout => false
+ maruku :index
+end
diff --git a/vendor/sinatra-maruku/examples/config.ru b/vendor/sinatra-maruku/examples/config.ru
new file mode 100644
index 00000000..75999267
--- /dev/null
+++ b/vendor/sinatra-maruku/examples/config.ru
@@ -0,0 +1,4 @@
+# run it: rackup config.ru -p 4567
+
+require 'app'
+run Sinatra::Application
diff --git a/vendor/sinatra-maruku/examples/mapp.rb b/vendor/sinatra-maruku/examples/mapp.rb
new file mode 100644
index 00000000..76b9ccaa
--- /dev/null
+++ b/vendor/sinatra-maruku/examples/mapp.rb
@@ -0,0 +1,15 @@
+require 'rubygems'
+require 'sinatra/base'
+require 'sinatra/maruku'
+
+require 'rack'
+
+class MApp < Sinatra::Base
+ helpers Sinatra::Maruku
+
+ get '/' do
+ maruku "## hello form modular app"
+ end
+end
+
+Rack::Handler::Thin.run MApp.new, :Port => 4567
diff --git a/.gitmodules b/vendor/sinatra-maruku/examples/public/javascripts/application.js
similarity index 100%
rename from .gitmodules
rename to vendor/sinatra-maruku/examples/public/javascripts/application.js
diff --git a/vendor/sinatra-maruku/examples/public/stylesheets/application.css b/vendor/sinatra-maruku/examples/public/stylesheets/application.css
new file mode 100644
index 00000000..702b3926
--- /dev/null
+++ b/vendor/sinatra-maruku/examples/public/stylesheets/application.css
@@ -0,0 +1,23 @@
+html {
+ margin: 0;
+ padding: 0;
+ background-color: #B5052E;
+ line-height: 1.6;
+}
+
+body {
+ margin: 1em auto 1em auto;
+ padding: 1em 2em 2em 1em;
+ width: 760px;
+ border: 1px solid black;
+ background-color: #E8DDCB;
+}
+
+pre {
+ padding: 0.5em 0 0.5em 2em;
+ background-color: #D7D3C1;
+}
+
+h1, h2, h3 {
+ color: #B5052E;
+}
diff --git a/vendor/sinatra-maruku/examples/public/stylesheets/print.css b/vendor/sinatra-maruku/examples/public/stylesheets/print.css
new file mode 100644
index 00000000..e69de29b
diff --git a/vendor/sinatra-maruku/examples/views/index.maruku b/vendor/sinatra-maruku/examples/views/index.maruku
new file mode 100644
index 00000000..788a1119
--- /dev/null
+++ b/vendor/sinatra-maruku/examples/views/index.maruku
@@ -0,0 +1,32 @@
+Maruku features
+===============
+
+Maruku allows you to write in an easy-to-read-and-write syntax, like this:
+
+> [This document in Markdown][this_md]
+
+Then it can be translated to HTML:
+
+> [This document in HTML][this_html]
+
+or LaTeX, which is then converted to PDF:
+
+> [This document in PDF][this_pdf]
+
+Maruku implements:
+
+* the original [Markdown syntax][markdown_html]
+ ([HTML][markdown_html] or [PDF][markdown_pdf]), translated by Maruku).
+
+* all the improvements in PHP Markdown Extra.
+
+* a new [meta-data syntax][meta_data_proposal]
+
+[markdown_html]: http://maruku.rubyforge.org/markdown_syntax.html
+[markdown_pdf]: http://maruku.rubyforge.org/markdown_syntax.pdf
+[this_md]: http://maruku.rubyforge.org/maruku.md
+[this_html]: http://maruku.rubyforge.org/maruku.html
+[this_pdf]: http://maruku.rubyforge.org/maruku.pdf
+[Andrea Censi]: http://www.dis.uniroma1.it/~acensi/
+
+[meta_data_proposal]: http://maruku.rubyforge.org/proposal.html
diff --git a/vendor/sinatra-maruku/examples/views/layout.maruku b/vendor/sinatra-maruku/examples/views/layout.maruku
new file mode 100644
index 00000000..3207ebfd
--- /dev/null
+++ b/vendor/sinatra-maruku/examples/views/layout.maruku
@@ -0,0 +1,9 @@
+CSS: /stylesheets/application.css /stylesheets/print.css
+Javascript: /javascriprs/application.js
+Lang: pl
+Title: Hello Maruku
+LaTeX preamble: preamble.tex
+
+# Hello Maruku {.header}
+
+<%= yield %>
diff --git a/vendor/sinatra-maruku/lib/sinatra/maruku.rb b/vendor/sinatra-maruku/lib/sinatra/maruku.rb
new file mode 100644
index 00000000..c798b2f4
--- /dev/null
+++ b/vendor/sinatra-maruku/lib/sinatra/maruku.rb
@@ -0,0 +1,25 @@
+require 'maruku'
+require 'sinatra/base'
+
+module Sinatra
+ module Maruku
+ def maruku(template, options={}, locals={})
+ render :maruku, template, options, locals
+ 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
+
+ helpers Maruku
+end
diff --git a/vendor/sinatra-maruku/sinatra-maruku.gemspec b/vendor/sinatra-maruku/sinatra-maruku.gemspec
new file mode 100644
index 00000000..b8bd41e7
--- /dev/null
+++ b/vendor/sinatra-maruku/sinatra-maruku.gemspec
@@ -0,0 +1,70 @@
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{sinatra-maruku}
+ s.version = "0.10.1"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Wlodek Bzyl"]
+ s.date = %q{2009-07-26}
+ s.description = %q{}
+ s.email = %q{matwb@univ.gda.pl}
+ s.extra_rdoc_files = [
+ "LICENSE",
+ "README.markdown"
+ ]
+ s.files = [
+ ".gitignore",
+ "LICENSE",
+ "README.markdown",
+ "Rakefile",
+ "VERSION.yml",
+ "examples/app.rb",
+ "examples/config.ru",
+ "examples/mapp.rb",
+ "examples/public/javascripts/application.js",
+ "examples/public/stylesheets/application.css",
+ "examples/public/stylesheets/print.css",
+ "examples/views/index.maruku",
+ "examples/views/layout.maruku",
+ "lib/sinatra/maruku.rb",
+ "sinatra-maruku.gemspec",
+ "test/sinatra_maruku_test.rb",
+ "test/test_helper.rb",
+ "test/views/hello.maruku",
+ "test/views/layout2.maruku"
+ ]
+ s.homepage = %q{http://github.com/wbzyl/sinatra-maruku}
+ s.rdoc_options = ["--charset=UTF-8"]
+ s.require_paths = ["lib"]
+ s.rubygems_version = %q{1.3.5}
+ s.summary = %q{An extension providing Maruku templates for Sinatra applications.}
+ s.test_files = [
+ "test/test_helper.rb",
+ "test/sinatra_maruku_test.rb",
+ "examples/mapp.rb",
+ "examples/app.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.10.1"])
+ s.add_runtime_dependency(%q, [">= 0.6.0"])
+ s.add_development_dependency(%q, [">= 1.0.0"])
+ s.add_development_dependency(%q, [">= 0.3.0"])
+ else
+ s.add_dependency(%q, [">= 0.10.1"])
+ s.add_dependency(%q, [">= 0.6.0"])
+ s.add_dependency(%q, [">= 1.0.0"])
+ s.add_dependency(%q, [">= 0.3.0"])
+ end
+ else
+ s.add_dependency(%q, [">= 0.10.1"])
+ s.add_dependency(%q, [">= 0.6.0"])
+ s.add_dependency(%q, [">= 1.0.0"])
+ s.add_dependency(%q, [">= 0.3.0"])
+ end
+end
diff --git a/vendor/sinatra-maruku/test/sinatra_maruku_test.rb b/vendor/sinatra-maruku/test/sinatra_maruku_test.rb
new file mode 100644
index 00000000..8d99824e
--- /dev/null
+++ b/vendor/sinatra-maruku/test/sinatra_maruku_test.rb
@@ -0,0 +1,91 @@
+require File.dirname(__FILE__) + '/test_helper'
+
+class SinatraMarukuTest < Test::Unit::TestCase
+ include Rack::Test::Methods
+
+ def maruku_app(&block)
+ mock_app {
+ set :views, File.dirname(__FILE__) + '/views'
+ helpers Sinatra::Maruku
+ set :show_exceptions, false
+ get '/', &block
+ }
+ get '/'
+ end
+
+ def test_renders_inline_strings
+ maruku_app { maruku 'hello world' }
+ assert last_response.ok?
+ assert_equal "hello world
", last_response.body
+ end
+
+ def test_renders_inline_erb_string
+ maruku_app { maruku '<%= 1 + 1 %>' }
+ assert last_response.ok?
+ assert_equal "2
", last_response.body
+ end
+
+ def test_renders_files_in_views_path
+ maruku_app { maruku :hello }
+ assert last_response.ok?
+ assert_equal "hello world
", last_response.body
+ end
+
+ def test_takes_locals_option
+ maruku_app {
+ locals = {:foo => 'Bar'}
+ maruku "<%= foo %>", :locals => locals
+ }
+ assert last_response.ok?
+ assert_equal "Bar
", last_response.body
+ end
+
+ def test_renders_with_inline_layouts
+ maruku_app {
+ maruku 'Sparta', :layout => 'THIS. IS. <%= yield.upcase %>'
+ }
+ assert last_response.ok?
+ assert_equal "\n\n\n\n\nTHIS. IS.
SPARTA
\n", last_response.body
+ end
+
+ def test_renders_with_file_layouts
+ maruku_app {
+ maruku 'hello world', :layout => :layout2
+ }
+ assert last_response.ok?
+ assert_equal "\n\n\n\n\nerb layout
hello world
\n", last_response.body
+ end
+
+ def test_renders_erb_with_blocks
+ mock_app {
+ set :views, File.dirname(__FILE__) + '/views'
+ helpers Sinatra::Maruku
+
+ def container
+ yield
+ end
+ def is
+ "THIS. IS. SPARTA!"
+ end
+
+ get '/' do
+ maruku '<% container do %> <%= is %> <% end %>'
+ end
+ }
+
+ get '/'
+ assert last_response.ok?
+ assert_equal "THIS. IS. SPARTA!
", last_response.body
+ end
+
+ def test_raises_error_if_template_not_found
+ mock_app {
+ set :views, File.dirname(__FILE__) + '/views'
+ helpers Sinatra::Maruku
+ set :show_exceptions, false
+
+ get('/') { maruku :no_such_template }
+ }
+ assert_raise(Errno::ENOENT) { get('/') }
+ end
+end
diff --git a/vendor/sinatra-maruku/test/test_helper.rb b/vendor/sinatra-maruku/test/test_helper.rb
new file mode 100644
index 00000000..99dd126f
--- /dev/null
+++ b/vendor/sinatra-maruku/test/test_helper.rb
@@ -0,0 +1,21 @@
+require 'rubygems'
+require 'test/unit'
+require 'rack/test'
+
+path = File.expand_path("../lib" + File.dirname(__FILE__))
+$:.unshift(path) unless $:.include?(path)
+
+require 'sinatra/maruku'
+
+class Test::Unit::TestCase
+ include Rack::Test::Methods
+
+ attr_reader :app
+
+ # Sets up a Sinatra::Base subclass defined with the block
+ # given. Used in setup or individual spec methods to establish
+ # the application.
+ def mock_app(base=Sinatra::Base, &block)
+ @app = Sinatra.new(base, &block)
+ end
+end
diff --git a/vendor/sinatra-maruku/test/views/hello.maruku b/vendor/sinatra-maruku/test/views/hello.maruku
new file mode 100644
index 00000000..2be7c65a
--- /dev/null
+++ b/vendor/sinatra-maruku/test/views/hello.maruku
@@ -0,0 +1 @@
+# hello world
diff --git a/vendor/sinatra-maruku/test/views/layout2.maruku b/vendor/sinatra-maruku/test/views/layout2.maruku
new file mode 100644
index 00000000..8f33055d
--- /dev/null
+++ b/vendor/sinatra-maruku/test/views/layout2.maruku
@@ -0,0 +1,2 @@
+erb layout
+<%= yield %>