Fix whitespace errors across all source files and tests
I can't stand this shit anymore.
This commit is contained in:
parent
7be3682605
commit
60d50062d7
576
lib/sinatra.rb
576
lib/sinatra.rb
|
@ -28,15 +28,16 @@ module Rack #:nodoc:
|
||||||
|
|
||||||
class Request #:nodoc:
|
class Request #:nodoc:
|
||||||
|
|
||||||
# Set of request method names allowed via the _method parameter hack. By default,
|
# Set of request method names allowed via the _method parameter hack. By
|
||||||
# all request methods defined in RFC2616 are included, with the exception of
|
# default, all request methods defined in RFC2616 are included, with the
|
||||||
# TRACE and CONNECT.
|
# exception of TRACE and CONNECT.
|
||||||
POST_TUNNEL_METHODS_ALLOWED = %w( PUT DELETE OPTIONS HEAD )
|
POST_TUNNEL_METHODS_ALLOWED = %w( PUT DELETE OPTIONS HEAD )
|
||||||
|
|
||||||
# Return the HTTP request method with support for method tunneling using the POST
|
# Return the HTTP request method with support for method tunneling using
|
||||||
# _method parameter hack. If the real request method is POST and a _method param is
|
# the POST _method parameter hack. If the real request method is POST and
|
||||||
# given and the value is one defined in +POST_TUNNEL_METHODS_ALLOWED+, return the value
|
# a _method param is given and the value is one defined in
|
||||||
# of the _method param instead.
|
# +POST_TUNNEL_METHODS_ALLOWED+, return the value of the _method param
|
||||||
|
# instead.
|
||||||
def request_method
|
def request_method
|
||||||
if post_tunnel_method_hack?
|
if post_tunnel_method_hack?
|
||||||
params['_method'].upcase
|
params['_method'].upcase
|
||||||
|
@ -49,19 +50,13 @@ module Rack #:nodoc:
|
||||||
@env['HTTP_USER_AGENT']
|
@env['HTTP_USER_AGENT']
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Return truthfully if and only if the following conditions are met: 1.) the
|
|
||||||
# *actual* request method is POST, 2.) the request content-type is one of
|
|
||||||
# 'application/x-www-form-urlencoded' or 'multipart/form-data', 3.) there is a
|
|
||||||
# "_method" parameter in the POST body (not in the query string), and 4.) the
|
|
||||||
# method parameter is one of the verbs listed in the POST_TUNNEL_METHODS_ALLOWED
|
|
||||||
# list.
|
|
||||||
def post_tunnel_method_hack?
|
|
||||||
@env['REQUEST_METHOD'] == 'POST' &&
|
|
||||||
POST_TUNNEL_METHODS_ALLOWED.include?(self.POST.fetch('_method', '').upcase)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
# Return truthfully if the request is a valid verb-over-post hack.
|
||||||
|
def post_tunnel_method_hack?
|
||||||
|
@env['REQUEST_METHOD'] == 'POST' &&
|
||||||
|
POST_TUNNEL_METHODS_ALLOWED.include?(self.POST.fetch('_method', '').upcase)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module Utils
|
module Utils
|
||||||
|
@ -70,17 +65,11 @@ module Rack #:nodoc:
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
module Sinatra
|
module Sinatra
|
||||||
extend self
|
extend self
|
||||||
|
|
||||||
module Version
|
VERSION = '0.3.0'
|
||||||
MAJOR = '0'
|
|
||||||
MINOR = '2'
|
|
||||||
REVISION = '3'
|
|
||||||
def self.combined
|
|
||||||
[MAJOR, MINOR, REVISION].join('.')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class NotFound < RuntimeError; end
|
class NotFound < RuntimeError; end
|
||||||
class ServerError < RuntimeError; end
|
class ServerError < RuntimeError; end
|
||||||
|
@ -130,7 +119,6 @@ module Sinatra
|
||||||
def run
|
def run
|
||||||
begin
|
begin
|
||||||
puts "== Sinatra has taken the stage on port #{port} for #{env} with backup by #{server.name}"
|
puts "== Sinatra has taken the stage on port #{port} for #{env} with backup by #{server.name}"
|
||||||
require 'pp'
|
|
||||||
server.run(application, {:Port => port, :Host => host}) do |server|
|
server.run(application, {:Port => port, :Host => host}) do |server|
|
||||||
trap(:INT) do
|
trap(:INT) do
|
||||||
server.stop
|
server.stop
|
||||||
|
@ -215,14 +203,13 @@ module Sinatra
|
||||||
|
|
||||||
def block
|
def block
|
||||||
Proc.new do
|
Proc.new do
|
||||||
send_file Sinatra.application.options.public + request.path_info.http_unescape,
|
send_file Sinatra.application.options.public +
|
||||||
:disposition => nil
|
request.path_info.http_unescape, :disposition => nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adapted from actionpack
|
|
||||||
# Methods for sending files and streams to the browser instead of rendering.
|
# Methods for sending files and streams to the browser instead of rendering.
|
||||||
module Streaming
|
module Streaming
|
||||||
DEFAULT_SEND_FILE_OPTIONS = {
|
DEFAULT_SEND_FILE_OPTIONS = {
|
||||||
|
@ -256,140 +243,153 @@ module Sinatra
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
# Sends the file by streaming it 4096 bytes at a time. This way the
|
|
||||||
# whole file doesn't need to be read into memory at once. This makes
|
|
||||||
# it feasible to send even large files.
|
|
||||||
#
|
|
||||||
# Be careful to sanitize the path parameter if it coming from a web
|
|
||||||
# page. send_file(params[:path]) allows a malicious user to
|
|
||||||
# download any file on your server.
|
|
||||||
#
|
|
||||||
# Options:
|
|
||||||
# * <tt>:filename</tt> - suggests a filename for the browser to use.
|
|
||||||
# Defaults to File.basename(path).
|
|
||||||
# * <tt>:type</tt> - specifies an HTTP content type.
|
|
||||||
# Defaults to 'application/octet-stream'.
|
|
||||||
# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
|
|
||||||
# Valid values are 'inline' and 'attachment' (default). When set to nil, the
|
|
||||||
# Content-Disposition and Content-Transfer-Encoding headers are omitted entirely.
|
|
||||||
# * <tt>:stream</tt> - whether to send the file to the user agent as it is read (true)
|
|
||||||
# or to read the entire file before sending (false). Defaults to true.
|
|
||||||
# * <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used to stream the file.
|
|
||||||
# Defaults to 4096.
|
|
||||||
# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
|
|
||||||
# * <tt>:last_modified</tt> - an optional RFC 2616 formatted date value (See Time#httpdate)
|
|
||||||
# indicating the last modified time of the file. If the request includes an
|
|
||||||
# If-Modified-Since header that matches this value exactly, a 304 Not Modified response
|
|
||||||
# is sent instead of the file. Defaults to the file's last modified
|
|
||||||
# time.
|
|
||||||
#
|
|
||||||
# The default Content-Type and Content-Disposition headers are
|
|
||||||
# set to download arbitrary binary files in as many browsers as
|
|
||||||
# possible. IE versions 4, 5, 5.5, and 6 are all known to have
|
|
||||||
# a variety of quirks (especially when downloading over SSL).
|
|
||||||
#
|
|
||||||
# Simple download:
|
|
||||||
# send_file '/path/to.zip'
|
|
||||||
#
|
|
||||||
# Show a JPEG in the browser:
|
|
||||||
# send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
|
|
||||||
#
|
|
||||||
# Show a 404 page in the browser:
|
|
||||||
# send_file '/path/to/404.html, :type => 'text/html; charset=utf-8', :status => 404
|
|
||||||
#
|
|
||||||
# Read about the other Content-* HTTP headers if you'd like to
|
|
||||||
# provide the user with more information (such as Content-Description).
|
|
||||||
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
|
|
||||||
#
|
|
||||||
# Also be aware that the document may be cached by proxies and browsers.
|
|
||||||
# The Pragma and Cache-Control headers declare how the file may be cached
|
|
||||||
# by intermediaries. They default to require clients to validate with
|
|
||||||
# the server before releasing cached responses. See
|
|
||||||
# http://www.mnot.net/cache_docs/ for an overview of web caching and
|
|
||||||
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
|
|
||||||
# for the Cache-Control header spec.
|
|
||||||
def send_file(path, options = {}) #:doc:
|
|
||||||
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
|
|
||||||
|
|
||||||
options[:length] ||= File.size(path)
|
# Sends the file by streaming it 4096 bytes at a time. This way the
|
||||||
options[:filename] ||= File.basename(path)
|
# whole file doesn't need to be read into memory at once. This makes
|
||||||
options[:type] ||= Rack::File::MIME_TYPES[File.extname(options[:filename])[1..-1]] || 'text/plain'
|
# it feasible to send even large files.
|
||||||
options[:last_modified] ||= File.mtime(path).httpdate
|
#
|
||||||
send_file_headers! options
|
# Be careful to sanitize the path parameter if it coming from a web
|
||||||
|
# page. send_file(params[:path]) allows a malicious user to
|
||||||
|
# download any file on your server.
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# * <tt>:filename</tt> - suggests a filename for the browser to use.
|
||||||
|
# Defaults to File.basename(path).
|
||||||
|
# * <tt>:type</tt> - specifies an HTTP content type.
|
||||||
|
# Defaults to 'application/octet-stream'.
|
||||||
|
# * <tt>:disposition</tt> - specifies whether the file will be shown
|
||||||
|
# inline or downloaded. Valid values are 'inline' and 'attachment'
|
||||||
|
# (default). When set to nil, the Content-Disposition and
|
||||||
|
# Content-Transfer-Encoding headers are omitted entirely.
|
||||||
|
# * <tt>:stream</tt> - whether to send the file to the user agent as it
|
||||||
|
# is read (true) or to read the entire file before sending (false).
|
||||||
|
# Defaults to true.
|
||||||
|
# * <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used
|
||||||
|
# to stream the file. Defaults to 4096.
|
||||||
|
# * <tt>:status</tt> - specifies the status code to send with the
|
||||||
|
# response. Defaults to '200 OK'.
|
||||||
|
# * <tt>:last_modified</tt> - an optional RFC 2616 formatted date value
|
||||||
|
# (See Time#httpdate) indicating the last modified time of the file.
|
||||||
|
# If the request includes an If-Modified-Since header that matches this
|
||||||
|
# value exactly, a 304 Not Modified response is sent instead of the file.
|
||||||
|
# Defaults to the file's last modified time.
|
||||||
|
#
|
||||||
|
# The default Content-Type and Content-Disposition headers are
|
||||||
|
# set to download arbitrary binary files in as many browsers as
|
||||||
|
# possible. IE versions 4, 5, 5.5, and 6 are all known to have
|
||||||
|
# a variety of quirks (especially when downloading over SSL).
|
||||||
|
#
|
||||||
|
# Simple download:
|
||||||
|
# send_file '/path/to.zip'
|
||||||
|
#
|
||||||
|
# Show a JPEG in the browser:
|
||||||
|
# send_file '/path/to.jpeg',
|
||||||
|
# :type => 'image/jpeg',
|
||||||
|
# :disposition => 'inline'
|
||||||
|
#
|
||||||
|
# Show a 404 page in the browser:
|
||||||
|
# send_file '/path/to/404.html,
|
||||||
|
# :type => 'text/html; charset=utf-8',
|
||||||
|
# :status => 404
|
||||||
|
#
|
||||||
|
# Read about the other Content-* HTTP headers if you'd like to
|
||||||
|
# provide the user with more information (such as Content-Description).
|
||||||
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
|
||||||
|
#
|
||||||
|
# Also be aware that the document may be cached by proxies and browsers.
|
||||||
|
# The Pragma and Cache-Control headers declare how the file may be cached
|
||||||
|
# by intermediaries. They default to require clients to validate with
|
||||||
|
# the server before releasing cached responses. See
|
||||||
|
# http://www.mnot.net/cache_docs/ for an overview of web caching and
|
||||||
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
|
||||||
|
# for the Cache-Control header spec.
|
||||||
|
def send_file(path, options = {}) #:doc:
|
||||||
|
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
|
||||||
|
|
||||||
if options[:stream]
|
options[:length] ||= File.size(path)
|
||||||
throw :halt, [options[:status] || 200, FileStreamer.new(path, options)]
|
options[:filename] ||= File.basename(path)
|
||||||
else
|
options[:type] ||= Rack::File::MIME_TYPES[File.extname(options[:filename])[1..-1]] || 'text/plain'
|
||||||
File.open(path, 'rb') { |file| throw :halt, [options[:status] || 200, file.read] }
|
options[:last_modified] ||= File.mtime(path).httpdate
|
||||||
end
|
send_file_headers! options
|
||||||
|
|
||||||
|
if options[:stream]
|
||||||
|
throw :halt, [options[:status] || 200, FileStreamer.new(path, options)]
|
||||||
|
else
|
||||||
|
File.open(path, 'rb') { |file| throw :halt, [options[:status] || 200, file.read] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Send binary data to the user as a file download. May set content type,
|
||||||
|
# apparent file name, and specify whether to show data inline or download
|
||||||
|
# as an attachment.
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# * <tt>:filename</tt> - Suggests a filename for the browser to use.
|
||||||
|
# * <tt>:type</tt> - specifies an HTTP content type.
|
||||||
|
# Defaults to 'application/octet-stream'.
|
||||||
|
# * <tt>:disposition</tt> - specifies whether the file will be shown inline
|
||||||
|
# or downloaded. Valid values are 'inline' and 'attachment' (default).
|
||||||
|
# * <tt>:status</tt> - specifies the status code to send with the response.
|
||||||
|
# Defaults to '200 OK'.
|
||||||
|
# * <tt>:last_modified</tt> - an optional RFC 2616 formatted date value (See
|
||||||
|
# Time#httpdate) indicating the last modified time of the response entity.
|
||||||
|
# If the request includes an If-Modified-Since header that matches this
|
||||||
|
# value exactly, a 304 Not Modified response is sent instead of the data.
|
||||||
|
#
|
||||||
|
# Generic data download:
|
||||||
|
# send_data buffer
|
||||||
|
#
|
||||||
|
# Download a dynamically-generated tarball:
|
||||||
|
# send_data generate_tgz('dir'), :filename => 'dir.tgz'
|
||||||
|
#
|
||||||
|
# Display an image Active Record in the browser:
|
||||||
|
# send_data image.data,
|
||||||
|
# :type => image.content_type,
|
||||||
|
# :disposition => 'inline'
|
||||||
|
#
|
||||||
|
# See +send_file+ for more information on HTTP Content-* headers and caching.
|
||||||
|
def send_data(data, options = {}) #:doc:
|
||||||
|
send_file_headers! options.merge(:length => data.size)
|
||||||
|
throw :halt, [options[:status] || 200, data]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def send_file_headers!(options)
|
||||||
|
options = DEFAULT_SEND_FILE_OPTIONS.merge(options)
|
||||||
|
[:length, :type, :disposition].each do |arg|
|
||||||
|
raise ArgumentError, ":#{arg} option required" unless options.key?(arg)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Send binary data to the user as a file download. May set content type, apparent file name,
|
# Send a "304 Not Modified" if the last_modified option is provided and
|
||||||
# and specify whether to show data inline or download as an attachment.
|
# matches the If-Modified-Since request header value.
|
||||||
#
|
if last_modified = options[:last_modified]
|
||||||
# Options:
|
header 'Last-Modified' => last_modified
|
||||||
# * <tt>:filename</tt> - Suggests a filename for the browser to use.
|
throw :halt, [ 304, '' ] if last_modified == request.env['HTTP_IF_MODIFIED_SINCE']
|
||||||
# * <tt>:type</tt> - specifies an HTTP content type.
|
|
||||||
# Defaults to 'application/octet-stream'.
|
|
||||||
# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
|
|
||||||
# Valid values are 'inline' and 'attachment' (default).
|
|
||||||
# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
|
|
||||||
# * <tt>:last_modified</tt> - an optional RFC 2616 formatted date value (See Time#httpdate)
|
|
||||||
# indicating the last modified time of the response entity. If the request includes an
|
|
||||||
# If-Modified-Since header that matches this value exactly, a 304 Not Modified response
|
|
||||||
# is sent instead of the data.
|
|
||||||
#
|
|
||||||
# Generic data download:
|
|
||||||
# send_data buffer
|
|
||||||
#
|
|
||||||
# Download a dynamically-generated tarball:
|
|
||||||
# send_data generate_tgz('dir'), :filename => 'dir.tgz'
|
|
||||||
#
|
|
||||||
# Display an image Active Record in the browser:
|
|
||||||
# send_data image.data, :type => image.content_type, :disposition => 'inline'
|
|
||||||
#
|
|
||||||
# See +send_file+ for more information on HTTP Content-* headers and caching.
|
|
||||||
def send_data(data, options = {}) #:doc:
|
|
||||||
send_file_headers! options.merge(:length => data.size)
|
|
||||||
throw :halt, [options[:status] || 200, data]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
headers(
|
||||||
def send_file_headers!(options)
|
'Content-Length' => options[:length].to_s,
|
||||||
options = DEFAULT_SEND_FILE_OPTIONS.merge(options)
|
'Content-Type' => options[:type].strip # fixes a problem with extra '\r' with some browsers
|
||||||
[:length, :type, :disposition].each do |arg|
|
)
|
||||||
raise ArgumentError, ":#{arg} option required" unless options.key?(arg)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Send a "304 Not Modified" if the last_modified option is provided and matches
|
# Omit Content-Disposition and Content-Transfer-Encoding headers if
|
||||||
# the If-Modified-Since request header value.
|
# the :disposition option set to nil.
|
||||||
if last_modified = options[:last_modified]
|
if !options[:disposition].nil?
|
||||||
header 'Last-Modified' => last_modified
|
disposition = options[:disposition].dup || 'attachment'
|
||||||
throw :halt, [ 304, '' ] if last_modified == request.env['HTTP_IF_MODIFIED_SINCE']
|
disposition <<= %(; filename="#{options[:filename]}") if options[:filename]
|
||||||
end
|
headers 'Content-Disposition' => disposition, 'Content-Transfer-Encoding' => 'binary'
|
||||||
|
|
||||||
headers(
|
|
||||||
'Content-Length' => options[:length].to_s,
|
|
||||||
'Content-Type' => options[:type].strip # fixes a problem with extra '\r' with some browsers
|
|
||||||
)
|
|
||||||
|
|
||||||
# Omit Content-Disposition and Content-Transfer-Encoding headers if
|
|
||||||
# the :disposition option set to nil.
|
|
||||||
if !options[:disposition].nil?
|
|
||||||
disposition = options[:disposition].dup || 'attachment'
|
|
||||||
disposition <<= %(; filename="#{options[:filename]}") if options[:filename]
|
|
||||||
headers 'Content-Disposition' => disposition, 'Content-Transfer-Encoding' => 'binary'
|
|
||||||
end
|
|
||||||
|
|
||||||
# Fix a problem with IE 6.0 on opening downloaded files:
|
|
||||||
# If Cache-Control: no-cache is set (which Rails does by default),
|
|
||||||
# IE removes the file it just downloaded from its cache immediately
|
|
||||||
# after it displays the "open/save" dialog, which means that if you
|
|
||||||
# hit "open" the file isn't there anymore when the application that
|
|
||||||
# is called for handling the download is run, so let's workaround that
|
|
||||||
header('Cache-Control' => 'private') if headers['Cache-Control'] == 'no-cache'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Fix a problem with IE 6.0 on opening downloaded files:
|
||||||
|
# If Cache-Control: no-cache is set (which Rails does by default),
|
||||||
|
# IE removes the file it just downloaded from its cache immediately
|
||||||
|
# after it displays the "open/save" dialog, which means that if you
|
||||||
|
# hit "open" the file isn't there anymore when the application that
|
||||||
|
# is called for handling the download is run, so let's workaround that
|
||||||
|
header('Cache-Control' => 'private') if headers['Cache-Control'] == 'no-cache'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -532,41 +532,41 @@ module Sinatra
|
||||||
resolve_template(renderer, layout_from_options, options, false)
|
resolve_template(renderer, layout_from_options, options, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def resolve_template(renderer, template, options, scream = true)
|
def resolve_template(renderer, template, options, scream = true)
|
||||||
case template
|
case template
|
||||||
when String
|
when String
|
||||||
template
|
template
|
||||||
when Proc
|
when Proc
|
||||||
template.call
|
template.call
|
||||||
when Symbol
|
when Symbol
|
||||||
if proc = templates[template]
|
if proc = templates[template]
|
||||||
resolve_template(renderer, proc, options, scream)
|
resolve_template(renderer, proc, options, scream)
|
||||||
else
|
|
||||||
read_template_file(renderer, template, options, scream)
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
nil
|
read_template_file(renderer, template, options, scream)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def read_template_file(renderer, template, options, scream = true)
|
def read_template_file(renderer, template, options, scream = true)
|
||||||
path = File.join(
|
path = File.join(
|
||||||
options[:views_directory] || Sinatra.application.options.views,
|
options[:views_directory] || Sinatra.application.options.views,
|
||||||
"#{template}.#{renderer}"
|
"#{template}.#{renderer}"
|
||||||
)
|
)
|
||||||
unless File.exists?(path)
|
unless File.exists?(path)
|
||||||
raise Errno::ENOENT.new(path) if scream
|
raise Errno::ENOENT.new(path) if scream
|
||||||
nil
|
nil
|
||||||
else
|
else
|
||||||
File.read(path)
|
File.read(path)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def templates
|
def templates
|
||||||
Sinatra.application.templates
|
Sinatra.application.templates
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -577,22 +577,22 @@ module Sinatra
|
||||||
render(:erb, content, options)
|
render(:erb, content, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def render_erb(content, options = {})
|
def render_erb(content, options = {})
|
||||||
locals_opt = options.delete(:locals) || {}
|
locals_opt = options.delete(:locals) || {}
|
||||||
|
|
||||||
locals_code = ""
|
locals_code = ""
|
||||||
locals_hash = {}
|
locals_hash = {}
|
||||||
locals_opt.each do |key, value|
|
locals_opt.each do |key, value|
|
||||||
locals_code << "#{key} = locals_hash[:#{key}]\n"
|
locals_code << "#{key} = locals_hash[:#{key}]\n"
|
||||||
locals_hash[:"#{key}"] = value
|
locals_hash[:"#{key}"] = value
|
||||||
end
|
|
||||||
|
|
||||||
body = ::ERB.new(content).src
|
|
||||||
eval("#{locals_code}#{body}", binding)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
body = ::ERB.new(content).src
|
||||||
|
eval("#{locals_code}#{body}", binding)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Haml
|
module Haml
|
||||||
|
@ -602,24 +602,27 @@ module Sinatra
|
||||||
render(:haml, content, options)
|
render(:haml, content, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def render_haml(content, options = {}, &b)
|
def render_haml(content, options = {}, &b)
|
||||||
haml_options = (options[:options] || {}).merge(Sinatra.options.haml || {})
|
haml_options = (options[:options] || {}).
|
||||||
::Haml::Engine.new(content, haml_options).render(options[:scope] || self, options[:locals] || {}, &b)
|
merge(Sinatra.options.haml || {})
|
||||||
end
|
::Haml::Engine.new(content, haml_options).
|
||||||
|
render(options[:scope] || self, options[:locals] || {}, &b)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Generate valid CSS using Sass (part of Haml)
|
# Generate valid CSS using Sass (part of Haml)
|
||||||
#
|
#
|
||||||
# Sass templates can be in external files with <tt>.sass</tt> extension or can use Sinatra's
|
# Sass templates can be in external files with <tt>.sass</tt> extension
|
||||||
# in_file_templates. In either case, the file can be rendered by passing the name of
|
# or can use Sinatra's in_file_templates. In either case, the file can
|
||||||
# the template to the +sass+ method as a symbol.
|
# be rendered by passing the name of the template to the +sass+ method
|
||||||
|
# as a symbol.
|
||||||
#
|
#
|
||||||
# Unlike Haml, Sass does not support a layout file, so the +sass+ method will ignore both
|
# Unlike Haml, Sass does not support a layout file, so the +sass+ method
|
||||||
# the default <tt>layout.sass</tt> file and any parameters passed in as <tt>:layout</tt> in
|
# will ignore both the default <tt>layout.sass</tt> file and any parameters
|
||||||
# the options hash.
|
# passed in as <tt>:layout</tt> in the options hash.
|
||||||
#
|
#
|
||||||
# === Sass Template Files
|
# === Sass Template Files
|
||||||
#
|
#
|
||||||
|
@ -659,8 +662,6 @@ module Sinatra
|
||||||
# attempt is made to render a Sass template.
|
# attempt is made to render a Sass template.
|
||||||
#
|
#
|
||||||
# See http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html for comprehensive documentation on Sass.
|
# See http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html for comprehensive documentation on Sass.
|
||||||
|
|
||||||
|
|
||||||
module Sass
|
module Sass
|
||||||
|
|
||||||
def sass(content, options = {})
|
def sass(content, options = {})
|
||||||
|
@ -672,23 +673,24 @@ module Sinatra
|
||||||
render(:sass, content, options)
|
render(:sass, content, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def render_sass(content, options = {})
|
||||||
|
::Sass::Engine.new(content).render
|
||||||
|
end
|
||||||
|
|
||||||
def render_sass(content, options = {})
|
|
||||||
::Sass::Engine.new(content).render
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Generating conservative XML content using Builder templates.
|
# Generating conservative XML content using Builder templates.
|
||||||
#
|
#
|
||||||
# Builder templates can be inline by passing a block to the builder method, or in
|
# Builder templates can be inline by passing a block to the builder method,
|
||||||
# external files with +.builder+ extension by passing the name of the template
|
# or in external files with +.builder+ extension by passing the name of the
|
||||||
# to the +builder+ method as a Symbol.
|
# template to the +builder+ method as a Symbol.
|
||||||
#
|
#
|
||||||
# === Inline Rendering
|
# === Inline Rendering
|
||||||
#
|
#
|
||||||
# If the builder method is given a block, the block is called directly with an
|
# If the builder method is given a block, the block is called directly with
|
||||||
# +XmlMarkup+ instance and the result is returned as String:
|
# an +XmlMarkup+ instance and the result is returned as String:
|
||||||
# get '/who.xml' do
|
# get '/who.xml' do
|
||||||
# builder do |xml|
|
# builder do |xml|
|
||||||
# xml.instruct!
|
# xml.instruct!
|
||||||
|
@ -710,8 +712,8 @@ module Sinatra
|
||||||
# === Builder Template Files
|
# === Builder Template Files
|
||||||
#
|
#
|
||||||
# Builder templates can be stored in separate files with a +.builder+
|
# Builder templates can be stored in separate files with a +.builder+
|
||||||
# extension under the view path. An +XmlMarkup+ object named +xml+ is automatically
|
# extension under the view path. An +XmlMarkup+ object named +xml+ is
|
||||||
# made available to template.
|
# automatically made available to template.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
# get '/bio.xml' do
|
# get '/bio.xml' do
|
||||||
|
@ -742,10 +744,11 @@ module Sinatra
|
||||||
# <died age='82' />
|
# <died age='82' />
|
||||||
# </person>
|
# </person>
|
||||||
#
|
#
|
||||||
# NOTE: Builder must be installed or a LoadError will be raised the first time an
|
# NOTE: Builder must be installed or a LoadError will be raised the first
|
||||||
# attempt is made to render a builder template.
|
# time an attempt is made to render a builder template.
|
||||||
#
|
#
|
||||||
# See http://builder.rubyforge.org/ for comprehensive documentation on Builder.
|
# See http://builder.rubyforge.org/ for comprehensive documentation on
|
||||||
|
# Builder.
|
||||||
module Builder
|
module Builder
|
||||||
|
|
||||||
def builder(content=nil, options={}, &block)
|
def builder(content=nil, options={}, &block)
|
||||||
|
@ -754,19 +757,19 @@ module Sinatra
|
||||||
render(:builder, content, options)
|
render(:builder, content, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def render_builder(content, options = {}, &b)
|
def render_builder(content, options = {}, &b)
|
||||||
require 'builder'
|
require 'builder'
|
||||||
xml = ::Builder::XmlMarkup.new(:indent => 2)
|
xml = ::Builder::XmlMarkup.new(:indent => 2)
|
||||||
case content
|
case content
|
||||||
when String
|
when String
|
||||||
eval(content, binding, '<BUILDER>', 1)
|
eval(content, binding, '<BUILDER>', 1)
|
||||||
when Proc
|
when Proc
|
||||||
content.call(xml)
|
content.call(xml)
|
||||||
end
|
|
||||||
xml.target!
|
|
||||||
end
|
end
|
||||||
|
xml.target!
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -814,11 +817,11 @@ module Sinatra
|
||||||
request.env['rack.session'] ||= {}
|
request.env['rack.session'] ||= {}
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def method_missing(name, *args, &b)
|
def method_missing(name, *args, &b)
|
||||||
@response.send(name, *args, &b)
|
@response.send(name, *args, &b)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1043,7 +1046,6 @@ module Sinatra
|
||||||
errors[NotFound].invoke(request)
|
errors[NotFound].invoke(request)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Define a named template. The template may be referenced from
|
# Define a named template. The template may be referenced from
|
||||||
# event handlers by passing the name as a Symbol to rendering
|
# event handlers by passing the name as a Symbol to rendering
|
||||||
# methods. The block is executed each time the template is rendered
|
# methods. The block is executed each time the template is rendered
|
||||||
|
@ -1259,18 +1261,8 @@ module Sinatra
|
||||||
not_found do
|
not_found do
|
||||||
%Q(
|
%Q(
|
||||||
<style>
|
<style>
|
||||||
body {
|
body { text-align:center;color:#888;font-family:arial;font-size:22px;margin:20px; }
|
||||||
text-align: center;
|
#content { margin:0 auto;width:500px;text-align:left}
|
||||||
color: #888;
|
|
||||||
font-family: Arial;
|
|
||||||
font-size: 22px;
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
#content {
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 500px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
|
@ -1278,9 +1270,7 @@ module Sinatra
|
||||||
<img src='/sinatra_custom_images/404.png'></img>
|
<img src='/sinatra_custom_images/404.png'></img>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
Try this:
|
Try this:
|
||||||
<pre>#{request.request_method.downcase} "#{request.path_info}" do
|
<pre>#{request.request_method.downcase} "#{request.path_info}" do\n .. do something ..\n end<pre>
|
||||||
.. do something ..
|
|
||||||
end<pre>
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1289,52 +1279,29 @@ end<pre>
|
||||||
|
|
||||||
error do
|
error do
|
||||||
@error = request.env['sinatra.error']
|
@error = request.env['sinatra.error']
|
||||||
%Q(
|
(<<-HTML).sub(/ {12}/, '')
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<style type="text/css" media="screen">
|
<style type="text/css" media="screen">
|
||||||
body {
|
body {font-family:verdana;color: #333}
|
||||||
font-family: Verdana;
|
#content {width:700px;margin-left:20px}
|
||||||
color: #333;
|
#content h1 {width:99%;color:#1D6B8D;font-weight:bold}
|
||||||
}
|
#stacktrace {margin-top:-20px}
|
||||||
|
#stacktrace pre {font-size:12px;border-left:2px solid #ddd;padding-left: 10px}
|
||||||
#content {
|
#stacktrace img {margin-top: 10px}
|
||||||
width: 700px;
|
</style>
|
||||||
margin-left: 20px;
|
<div id="content">
|
||||||
}
|
<img src="/sinatra_custom_images/500.png" />
|
||||||
|
<div class="info">
|
||||||
#content h1 {
|
|
||||||
width: 99%;
|
|
||||||
color: #1D6B8D;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
#stacktrace {
|
|
||||||
margin-top: -20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#stacktrace pre {
|
|
||||||
font-size: 12px;
|
|
||||||
border-left: 2px solid #ddd;
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#stacktrace img {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div id="content">
|
|
||||||
<img src="/sinatra_custom_images/500.png" />
|
|
||||||
<div class="info">
|
|
||||||
Params: <pre>#{params.inspect}
|
Params: <pre>#{params.inspect}
|
||||||
</div>
|
</div>
|
||||||
<div id="stacktrace">
|
<div id="stacktrace">
|
||||||
<h1>#{Rack::Utils.escape_html(@error.class.name + ' - ' + @error.message.to_s)}</h1>
|
<h1>#{Rack::Utils.escape_html(@error.class.name + ' - ' + @error.message.to_s)}</h1>
|
||||||
<pre><code>#{Rack::Utils.escape_html(@error.backtrace.join("\n"))}</code></pre>
|
<pre><code>#{Rack::Utils.escape_html(@error.backtrace.join("\n"))}</code></pre>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
)
|
HTML
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1381,14 +1348,12 @@ end
|
||||||
### Misc Core Extensions
|
### Misc Core Extensions
|
||||||
|
|
||||||
module Kernel
|
module Kernel
|
||||||
|
|
||||||
def silence_warnings
|
def silence_warnings
|
||||||
old_verbose, $VERBOSE = $VERBOSE, nil
|
old_verbose, $VERBOSE = $VERBOSE, nil
|
||||||
yield
|
yield
|
||||||
ensure
|
ensure
|
||||||
$VERBOSE = old_verbose
|
$VERBOSE = old_verbose
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class String
|
class String
|
||||||
|
@ -1410,47 +1375,36 @@ class String
|
||||||
end
|
end
|
||||||
|
|
||||||
class Hash
|
class Hash
|
||||||
|
|
||||||
def to_params
|
def to_params
|
||||||
map { |k,v| "#{k}=#{URI.escape(v)}" }.join('&')
|
map { |k,v| "#{k}=#{URI.escape(v)}" }.join('&')
|
||||||
end
|
end
|
||||||
|
|
||||||
def symbolize_keys
|
def symbolize_keys
|
||||||
self.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
|
self.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
|
||||||
end
|
end
|
||||||
|
|
||||||
def pass(*keys)
|
def pass(*keys)
|
||||||
reject { |k,v| !keys.include?(k) }
|
reject { |k,v| !keys.include?(k) }
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Symbol
|
class Symbol
|
||||||
|
|
||||||
def to_proc
|
def to_proc
|
||||||
Proc.new { |*args| args.shift.__send__(self, *args) }
|
Proc.new { |*args| args.shift.__send__(self, *args) }
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Array
|
class Array
|
||||||
|
|
||||||
def to_hash
|
def to_hash
|
||||||
self.inject({}) { |h, (k, v)| h[k] = v; h }
|
self.inject({}) { |h, (k, v)| h[k] = v; h }
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_proc
|
def to_proc
|
||||||
Proc.new { |*args| args.shift.__send__(self[0], *(args + self[1..-1])) }
|
Proc.new { |*args| args.shift.__send__(self[0], *(args + self[1..-1])) }
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Enumerable
|
module Enumerable
|
||||||
|
|
||||||
def eject(&block)
|
def eject(&block)
|
||||||
find { |e| result = block[e] and break result }
|
find { |e| result = block[e] and break result }
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
### Core Extension results for throw :halt
|
### Core Extension results for throw :halt
|
||||||
|
|
|
@ -60,8 +60,3 @@ context "Custom Errors (in general)" do
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
require File.dirname(__FILE__) + '/helper'
|
require File.dirname(__FILE__) + '/helper'
|
||||||
|
|
||||||
|
# XXX: How does any of this have anything to do with REST?
|
||||||
context "RESTful tests" do
|
context "RESTful tests" do
|
||||||
|
|
||||||
specify "should take xml" do
|
specify "should take xml" do
|
||||||
|
|
|
@ -33,7 +33,6 @@ context "Rendering in file templates" do
|
||||||
assert_equal "X\nthis is foo\nX\n", body
|
assert_equal "X\nthis is foo\nX\n", body
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
__END__
|
__END__
|
||||||
|
|
Loading…
Reference in New Issue