sinatra 1.2.0.a → 1.2.0.c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- data/AUTHORS +2 -0
- data/CHANGES +69 -1
- data/Gemfile +35 -0
- data/Gemfile.lock +74 -0
- data/README.de.rdoc +16 -16
- data/README.es.rdoc +360 -80
- data/README.fr.rdoc +16 -16
- data/README.hu.rdoc +4 -4
- data/README.jp.rdoc +16 -16
- data/README.pt-br.rdoc +6 -6
- data/README.rdoc +629 -95
- data/README.ru.rdoc +317 -103
- data/README.zh.rdoc +16 -16
- data/Rakefile +6 -14
- data/lib/sinatra/base.rb +70 -30
- data/lib/sinatra/showexceptions.rb +25 -0
- data/sinatra.gemspec +8 -18
- data/test/builder_test.rb +6 -0
- data/test/coffee_test.rb +1 -1
- data/test/erubis_test.rb +6 -0
- data/test/haml_test.rb +2 -1
- data/test/helpers_test.rb +53 -0
- data/test/less_test.rb +6 -0
- data/test/liquid_test.rb +2 -1
- data/test/markaby_test.rb +2 -1
- data/test/markdown_test.rb +3 -2
- data/test/nokogiri_test.rb +2 -1
- data/test/radius_test.rb +3 -2
- data/test/rdoc_test.rb +2 -1
- data/test/routing_test.rb +49 -5
- data/test/sass_test.rb +1 -1
- data/test/scss_test.rb +1 -1
- data/test/slim_test.rb +2 -1
- data/test/templates_test.rb +43 -0
- data/test/textile_test.rb +2 -1
- data/test/views/a/in_a.str +1 -0
- data/test/views/b/in_b.str +1 -0
- data/test/views/calc.html.erb +1 -0
- metadata +22 -223
data/README.zh.rdoc
CHANGED
@@ -172,7 +172,7 @@ Rack body对象或者HTTP状态码:
|
|
172
172
|
|
173
173
|
需要引入haml gem/library以渲染 HAML 模板:
|
174
174
|
|
175
|
-
|
175
|
+
# 你需要在你的应用中引入 haml
|
176
176
|
require 'haml'
|
177
177
|
|
178
178
|
get '/' do
|
@@ -195,7 +195,7 @@ Rack body对象或者HTTP状态码:
|
|
195
195
|
|
196
196
|
=== Erb模板
|
197
197
|
|
198
|
-
|
198
|
+
# 你需要在你的应用中引入 erb
|
199
199
|
require 'erb'
|
200
200
|
|
201
201
|
get '/' do
|
@@ -208,7 +208,7 @@ Rack body对象或者HTTP状态码:
|
|
208
208
|
|
209
209
|
需要引入erubis gem/library以渲染 erubis 模板:
|
210
210
|
|
211
|
-
|
211
|
+
# 你需要在你的应用中引入 erubis
|
212
212
|
require 'erubis'
|
213
213
|
|
214
214
|
get '/' do
|
@@ -221,7 +221,7 @@ Rack body对象或者HTTP状态码:
|
|
221
221
|
|
222
222
|
需要引入 builder gem/library 以渲染 builder templates:
|
223
223
|
|
224
|
-
|
224
|
+
# 需要在你的应用中引入builder
|
225
225
|
require 'builder'
|
226
226
|
|
227
227
|
get '/' do
|
@@ -234,7 +234,7 @@ Rack body对象或者HTTP状态码:
|
|
234
234
|
|
235
235
|
需要引入 nokogiri gem/library 以渲染 nokogiri 模板:
|
236
236
|
|
237
|
-
|
237
|
+
# 需要在你的应用中引入 nokogiri
|
238
238
|
require 'nokogiri'
|
239
239
|
|
240
240
|
get '/' do
|
@@ -247,7 +247,7 @@ Rack body对象或者HTTP状态码:
|
|
247
247
|
|
248
248
|
需要引入 haml gem/library 以渲染 Sass 模板:
|
249
249
|
|
250
|
-
|
250
|
+
# 需要在你的应用中引入 haml 或者 sass
|
251
251
|
require 'sass'
|
252
252
|
|
253
253
|
get '/stylesheet.css' do
|
@@ -271,7 +271,7 @@ Rack body对象或者HTTP状态码:
|
|
271
271
|
|
272
272
|
需要引入 haml gem/library 来渲染 Scss templates:
|
273
273
|
|
274
|
-
|
274
|
+
# 需要在你的应用中引入 haml 或者 sass
|
275
275
|
require 'sass'
|
276
276
|
|
277
277
|
get '/stylesheet.css' do
|
@@ -295,7 +295,7 @@ Rack body对象或者HTTP状态码:
|
|
295
295
|
|
296
296
|
需要引入 less gem/library 以渲染 Less 模板:
|
297
297
|
|
298
|
-
|
298
|
+
# 需要在你的应用中引入 less
|
299
299
|
require 'less'
|
300
300
|
|
301
301
|
get '/stylesheet.css' do
|
@@ -308,7 +308,7 @@ Rack body对象或者HTTP状态码:
|
|
308
308
|
|
309
309
|
需要引入 liquid gem/library 来渲染 Liquid 模板:
|
310
310
|
|
311
|
-
|
311
|
+
# 需要在你的应用中引入 liquid
|
312
312
|
require 'liquid'
|
313
313
|
|
314
314
|
get '/' do
|
@@ -326,7 +326,7 @@ Rack body对象或者HTTP状态码:
|
|
326
326
|
|
327
327
|
需要引入 rdiscount gem/library 以渲染 Markdown 模板:
|
328
328
|
|
329
|
-
|
329
|
+
# 需要在你的应用中引入rdiscount
|
330
330
|
require "rdiscount"
|
331
331
|
|
332
332
|
get '/' do
|
@@ -349,7 +349,7 @@ Rack body对象或者HTTP状态码:
|
|
349
349
|
|
350
350
|
需要引入 RedCloth gem/library 以渲染 Textile 模板:
|
351
351
|
|
352
|
-
|
352
|
+
# 在你的应用中引入redcloth
|
353
353
|
require "redcloth"
|
354
354
|
|
355
355
|
get '/' do
|
@@ -371,7 +371,7 @@ Rack body对象或者HTTP状态码:
|
|
371
371
|
|
372
372
|
需要引入 RDoc gem/library 以渲染RDoc模板:
|
373
373
|
|
374
|
-
|
374
|
+
# 需要在你的应用中引入rdoc
|
375
375
|
require "rdoc"
|
376
376
|
|
377
377
|
get '/' do
|
@@ -393,7 +393,7 @@ Rack body对象或者HTTP状态码:
|
|
393
393
|
|
394
394
|
需要引入 radius gem/library 以渲染 Radius 模板:
|
395
395
|
|
396
|
-
|
396
|
+
# You'll need to require radius in your app
|
397
397
|
require 'radius'
|
398
398
|
|
399
399
|
get '/' do
|
@@ -411,7 +411,7 @@ Rack body对象或者HTTP状态码:
|
|
411
411
|
|
412
412
|
需要引入markaby gem/library以渲染Markaby模板:
|
413
413
|
|
414
|
-
|
414
|
+
#需要在你的应用中引入 markaby
|
415
415
|
require 'markaby'
|
416
416
|
|
417
417
|
get '/' do
|
@@ -424,7 +424,7 @@ Rack body对象或者HTTP状态码:
|
|
424
424
|
|
425
425
|
需要引入 slim gem/library 来渲染 Slim 模板:
|
426
426
|
|
427
|
-
|
427
|
+
# 需要在你的应用中引入 slim
|
428
428
|
require 'slim'
|
429
429
|
|
430
430
|
get '/' do
|
@@ -438,7 +438,7 @@ Rack body对象或者HTTP状态码:
|
|
438
438
|
需要引入 coffee-script gem/library 并在路径中存在 `coffee` 二进制文件以渲染
|
439
439
|
CoffeeScript 模板:
|
440
440
|
|
441
|
-
|
441
|
+
# 需要在你的应用中引入coffee-script
|
442
442
|
require 'coffee-script'
|
443
443
|
|
444
444
|
get '/application.js' do
|
data/Rakefile
CHANGED
@@ -6,6 +6,8 @@ require 'date'
|
|
6
6
|
task :default => :test
|
7
7
|
task :spec => :test
|
8
8
|
|
9
|
+
CLEAN.include "**/*.rbc"
|
10
|
+
|
9
11
|
def source_version
|
10
12
|
line = File.read('lib/sinatra/base.rb')[/^\s*VERSION = .*/]
|
11
13
|
line.match(/.*VERSION = '(.*)'/)[1]
|
@@ -17,21 +19,11 @@ task :test do
|
|
17
19
|
ENV.delete 'LC_CTYPE'
|
18
20
|
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
first_run = Dir.glob('test/*_test.rb') - second_run
|
25
|
-
[first_run, second_run].each { |f| sh "testrb #{f.join ' '}" }
|
26
|
-
end
|
27
|
-
else
|
28
|
-
Rake::TestTask.new(:test) do |t|
|
29
|
-
t.test_files = FileList['test/*_test.rb']
|
30
|
-
t.ruby_opts = ['-rubygems'] if defined? Gem
|
31
|
-
t.ruby_opts << '-I.'
|
32
|
-
end
|
22
|
+
Rake::TestTask.new(:test) do |t|
|
23
|
+
t.test_files = FileList['test/*_test.rb']
|
24
|
+
t.ruby_opts = ['-rubygems'] if defined? Gem
|
25
|
+
t.ruby_opts << '-I.'
|
33
26
|
end
|
34
|
-
|
35
27
|
# Rcov ================================================================
|
36
28
|
namespace :test do
|
37
29
|
desc 'Mesures test coverage'
|
data/lib/sinatra/base.rb
CHANGED
@@ -7,7 +7,7 @@ require 'sinatra/showexceptions'
|
|
7
7
|
require 'tilt'
|
8
8
|
|
9
9
|
module Sinatra
|
10
|
-
VERSION = '1.2.0.
|
10
|
+
VERSION = '1.2.0.c'
|
11
11
|
|
12
12
|
# The request object. See Rack::Request for more info:
|
13
13
|
# http://rack.rubyforge.org/doc/classes/Rack/Request.html
|
@@ -29,6 +29,10 @@ module Sinatra
|
|
29
29
|
alias secure? ssl?
|
30
30
|
end
|
31
31
|
|
32
|
+
def forwarded?
|
33
|
+
@env.include? "HTTP_X_FORWARDED_HOST"
|
34
|
+
end
|
35
|
+
|
32
36
|
def route
|
33
37
|
@route ||= begin
|
34
38
|
path = Rack::Utils.unescape(path_info)
|
@@ -91,24 +95,37 @@ module Sinatra
|
|
91
95
|
|
92
96
|
# Halt processing and redirect to the URI provided.
|
93
97
|
def redirect(uri, *args)
|
94
|
-
if not uri =~ /^https?:\/\//
|
95
|
-
# According to RFC 2616 section 14.30, "the field value consists of a
|
96
|
-
# single absolute URI"
|
97
|
-
abs_uri = "#{request.scheme}://#{request.host}"
|
98
|
-
|
99
|
-
if request.scheme == 'https' && request.port != 443 ||
|
100
|
-
request.scheme == 'http' && request.port != 80
|
101
|
-
abs_uri << ":#{request.port}"
|
102
|
-
end
|
103
|
-
|
104
|
-
uri = (abs_uri << uri)
|
105
|
-
end
|
106
|
-
|
107
98
|
status 302
|
108
|
-
|
99
|
+
|
100
|
+
# According to RFC 2616 section 14.30, "the field value consists of a
|
101
|
+
# single absolute URI"
|
102
|
+
response['Location'] = url(uri, settings.absolute_redirects?, settings.prefixed_redirects?)
|
109
103
|
halt(*args)
|
110
104
|
end
|
111
105
|
|
106
|
+
# Generates the absolute URI for a given path in the app.
|
107
|
+
# Takes Rack routers and reverse proxies into account.
|
108
|
+
def uri(addr = nil, absolute = true, add_script_name = true)
|
109
|
+
return addr if addr =~ /^https?:\/\//
|
110
|
+
uri = [host = ""]
|
111
|
+
if absolute
|
112
|
+
host << 'http'
|
113
|
+
host << 's' if request.secure?
|
114
|
+
host << "://"
|
115
|
+
if request.forwarded? or request.port != (request.secure? ? 443 : 80)
|
116
|
+
host << request.host_with_port
|
117
|
+
else
|
118
|
+
host << request.host
|
119
|
+
end
|
120
|
+
end
|
121
|
+
uri << request.script_name.to_s if add_script_name
|
122
|
+
uri << (addr ? addr : request.path_info).to_s
|
123
|
+
File.join uri
|
124
|
+
end
|
125
|
+
|
126
|
+
alias url uri
|
127
|
+
alias to uri
|
128
|
+
|
112
129
|
# Halt processing and return the error status provided.
|
113
130
|
def error(code, body=nil)
|
114
131
|
code, body = 500, code.to_str if code.respond_to? :to_str
|
@@ -324,10 +341,17 @@ module Sinatra
|
|
324
341
|
# with a '304 Not Modified' response.
|
325
342
|
def last_modified(time)
|
326
343
|
return unless time
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
344
|
+
if time.respond_to?(:to_time)
|
345
|
+
time = time.to_time
|
346
|
+
else
|
347
|
+
## make a best effort to convert something else to a time object
|
348
|
+
## if this fails, this should throw an ArgumentError, then the
|
349
|
+
# rescue will result in an http 200, which should be safe
|
350
|
+
time = Time.parse(time.to_s)
|
351
|
+
end
|
352
|
+
response['Last-Modified'] = time.httpdate
|
353
|
+
# compare based on seconds since epoch
|
354
|
+
halt 304 if Time.httpdate(request.env['HTTP_IF_MODIFIED_SINCE']).to_i >= time.to_i
|
331
355
|
rescue ArgumentError
|
332
356
|
end
|
333
357
|
|
@@ -446,6 +470,15 @@ module Sinatra
|
|
446
470
|
render :slim, template, options, locals
|
447
471
|
end
|
448
472
|
|
473
|
+
# Calls the given block for every possible template file in views,
|
474
|
+
# named name.ext, where ext is registered on engine.
|
475
|
+
def find_template(views, name, engine)
|
476
|
+
Tilt.mappings.each do |ext, klass|
|
477
|
+
next unless klass == engine
|
478
|
+
yield ::File.join(views, "#{name}.#{ext}")
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
449
482
|
private
|
450
483
|
# logic shared between builder and nokogiri
|
451
484
|
def render_ruby(engine, template, options={}, locals={}, &block)
|
@@ -469,17 +502,18 @@ module Sinatra
|
|
469
502
|
layout = @default_layout if layout.nil? or layout == true
|
470
503
|
content_type = options.delete(:content_type) || options.delete(:default_content_type)
|
471
504
|
layout_engine = options.delete(:layout_engine) || engine
|
505
|
+
scope = options.delete(:scope) || self
|
472
506
|
|
473
507
|
# compile and render template
|
474
508
|
layout_was = @default_layout
|
475
509
|
@default_layout = false
|
476
510
|
template = compile_template(engine, data, options, views)
|
477
|
-
output = template.render(
|
511
|
+
output = template.render(scope, locals, &block)
|
478
512
|
@default_layout = layout_was
|
479
513
|
|
480
514
|
# render layout
|
481
515
|
if layout
|
482
|
-
options = options.merge(:views => views, :layout => false, :eat_errors => eat_errors)
|
516
|
+
options = options.merge(:views => views, :layout => false, :eat_errors => eat_errors, :scope => scope)
|
483
517
|
catch(:layout_missing) { output = render(layout_engine, layout, options, locals) { output }}
|
484
518
|
end
|
485
519
|
|
@@ -501,13 +535,14 @@ module Sinatra
|
|
501
535
|
template.new(path, line.to_i, options) { body }
|
502
536
|
else
|
503
537
|
found = false
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
538
|
+
find_template(views, data, template) do |file|
|
539
|
+
path ||= file # keep the initial path rather than the last one
|
540
|
+
if found = File.exists?(file)
|
541
|
+
path = file
|
542
|
+
break
|
543
|
+
end
|
509
544
|
end
|
510
|
-
throw :layout_missing if eat_errors and
|
545
|
+
throw :layout_missing if eat_errors and not found
|
511
546
|
template.new(path, 1, options)
|
512
547
|
end
|
513
548
|
when data.is_a?(Proc) || data.is_a?(String)
|
@@ -990,7 +1025,7 @@ module Sinatra
|
|
990
1025
|
# Will set params[:agent].
|
991
1026
|
def user_agent(pattern)
|
992
1027
|
condition do
|
993
|
-
if request.user_agent =~ pattern
|
1028
|
+
if request.user_agent.to_s =~ pattern
|
994
1029
|
@params[:agent] = $~[1..-1]
|
995
1030
|
true
|
996
1031
|
else
|
@@ -1007,7 +1042,7 @@ module Sinatra
|
|
1007
1042
|
condition do
|
1008
1043
|
matching_types = (request.accept & types)
|
1009
1044
|
unless matching_types.empty?
|
1010
|
-
|
1045
|
+
content_type matching_types.first
|
1011
1046
|
true
|
1012
1047
|
else
|
1013
1048
|
false
|
@@ -1067,7 +1102,7 @@ module Sinatra
|
|
1067
1102
|
def compile(path)
|
1068
1103
|
keys = []
|
1069
1104
|
if path.respond_to? :to_str
|
1070
|
-
special_chars = %w{. + ( )}
|
1105
|
+
special_chars = %w{. + ( ) $}
|
1071
1106
|
pattern =
|
1072
1107
|
path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
|
1073
1108
|
case match
|
@@ -1084,6 +1119,8 @@ module Sinatra
|
|
1084
1119
|
[/^#{pattern}$/, keys]
|
1085
1120
|
elsif path.respond_to?(:keys) && path.respond_to?(:match)
|
1086
1121
|
[path, path.keys]
|
1122
|
+
elsif path.respond_to?(:names) && path.respond_to?(:match)
|
1123
|
+
[path, path.names]
|
1087
1124
|
elsif path.respond_to? :match
|
1088
1125
|
[path, keys]
|
1089
1126
|
else
|
@@ -1280,6 +1317,9 @@ module Sinatra
|
|
1280
1317
|
set :bind, '0.0.0.0'
|
1281
1318
|
set :port, 4567
|
1282
1319
|
|
1320
|
+
set :absolute_redirects, true
|
1321
|
+
set :prefixed_redirects, false
|
1322
|
+
|
1283
1323
|
set :app_file, nil
|
1284
1324
|
set :root, Proc.new { app_file && File.expand_path(File.dirname(app_file)) }
|
1285
1325
|
set :views, Proc.new { root && File.join(root, 'views') }
|
@@ -8,11 +8,36 @@ module Sinatra
|
|
8
8
|
# Be careful when you use this on public-facing sites as it could reveal
|
9
9
|
# information helpful to attackers.
|
10
10
|
class ShowExceptions < Rack::ShowExceptions
|
11
|
+
@@eats_errors = Object.new
|
12
|
+
def @@eats_errors.flush(*) end
|
13
|
+
def @@eats_errors.puts(*) end
|
14
|
+
|
11
15
|
def initialize(app)
|
12
16
|
@app = app
|
13
17
|
@template = ERB.new(TEMPLATE)
|
14
18
|
end
|
15
19
|
|
20
|
+
def call(env)
|
21
|
+
@app.call(env)
|
22
|
+
rescue Exception => e
|
23
|
+
errors, env["rack.errors"] = env["rack.errors"], @@eats_errors
|
24
|
+
|
25
|
+
if respond_to?(:prefers_plain_text?) and prefers_plain_text?(env)
|
26
|
+
content_type = "text/plain"
|
27
|
+
body = [dump_exception(e)]
|
28
|
+
else
|
29
|
+
content_type = "text/html"
|
30
|
+
body = pretty(env, e)
|
31
|
+
end
|
32
|
+
|
33
|
+
env["rack.errors"] = errors
|
34
|
+
|
35
|
+
[500,
|
36
|
+
{"Content-Type" => content_type,
|
37
|
+
"Content-Length" => Rack::Utils.bytesize(body.join).to_s},
|
38
|
+
body]
|
39
|
+
end
|
40
|
+
|
16
41
|
private
|
17
42
|
|
18
43
|
def frame_class(frame)
|
data/sinatra.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
|
5
5
|
s.name = 'sinatra'
|
6
|
-
s.version = '1.2.0.
|
7
|
-
s.date = '
|
6
|
+
s.version = '1.2.0.c'
|
7
|
+
s.date = '2011-02-19'
|
8
8
|
|
9
9
|
s.description = "Classy web-development dressed in a DSL"
|
10
10
|
s.summary = "Classy web-development dressed in a DSL"
|
@@ -16,6 +16,8 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.files = %w[
|
17
17
|
AUTHORS
|
18
18
|
CHANGES
|
19
|
+
Gemfile
|
20
|
+
Gemfile.lock
|
19
21
|
LICENSE
|
20
22
|
README.de.rdoc
|
21
23
|
README.es.rdoc
|
@@ -71,7 +73,10 @@ Gem::Specification.new do |s|
|
|
71
73
|
test/static_test.rb
|
72
74
|
test/templates_test.rb
|
73
75
|
test/textile_test.rb
|
76
|
+
test/views/a/in_a.str
|
74
77
|
test/views/ascii.haml
|
78
|
+
test/views/b/in_b.str
|
79
|
+
test/views/calc.html.erb
|
75
80
|
test/views/error.builder
|
76
81
|
test/views/error.erb
|
77
82
|
test/views/error.erubis
|
@@ -117,23 +122,8 @@ Gem::Specification.new do |s|
|
|
117
122
|
|
118
123
|
s.extra_rdoc_files = %w[README.rdoc README.de.rdoc README.jp.rdoc README.fr.rdoc README.es.rdoc README.hu.rdoc README.zh.rdoc LICENSE]
|
119
124
|
s.add_dependency 'rack', '~> 1.1'
|
120
|
-
s.add_dependency 'tilt', '
|
121
|
-
s.add_development_dependency 'rake'
|
125
|
+
s.add_dependency 'tilt', '>= 1.2.2', '< 2.0'
|
122
126
|
s.add_development_dependency 'shotgun', '~> 0.6'
|
123
|
-
s.add_development_dependency 'rack-test', '>= 0.5.6'
|
124
|
-
s.add_development_dependency 'haml', '>= 3.0'
|
125
|
-
s.add_development_dependency 'builder'
|
126
|
-
s.add_development_dependency 'erubis'
|
127
|
-
s.add_development_dependency 'less'
|
128
|
-
s.add_development_dependency 'liquid'
|
129
|
-
s.add_development_dependency 'rdiscount'
|
130
|
-
s.add_development_dependency 'RedCloth'
|
131
|
-
s.add_development_dependency 'radius'
|
132
|
-
s.add_development_dependency 'markaby'
|
133
|
-
s.add_development_dependency 'coffee-script', '>= 2.0'
|
134
|
-
s.add_development_dependency 'rdoc'
|
135
|
-
s.add_development_dependency 'nokogiri'
|
136
|
-
s.add_development_dependency 'slim'
|
137
127
|
|
138
128
|
s.has_rdoc = true
|
139
129
|
s.homepage = "http://sinatra.rubyforge.org"
|