pirj-sinatra-contrib 1.3.0
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.
- data/LICENSE +20 -0
- data/README.md +135 -0
- data/Rakefile +61 -0
- data/ideas.md +29 -0
- data/lib/sinatra/capture.rb +42 -0
- data/lib/sinatra/config_file.rb +151 -0
- data/lib/sinatra/content_for.rb +111 -0
- data/lib/sinatra/contrib.rb +39 -0
- data/lib/sinatra/contrib/all.rb +2 -0
- data/lib/sinatra/contrib/setup.rb +53 -0
- data/lib/sinatra/contrib/version.rb +45 -0
- data/lib/sinatra/decompile.rb +113 -0
- data/lib/sinatra/engine_tracking.rb +96 -0
- data/lib/sinatra/extension.rb +95 -0
- data/lib/sinatra/json.rb +134 -0
- data/lib/sinatra/link_header.rb +132 -0
- data/lib/sinatra/namespace.rb +282 -0
- data/lib/sinatra/reloader.rb +384 -0
- data/lib/sinatra/respond_with.rb +245 -0
- data/lib/sinatra/streaming.rb +267 -0
- data/lib/sinatra/test_helpers.rb +87 -0
- data/sinatra-contrib.gemspec +121 -0
- data/spec/capture_spec.rb +80 -0
- data/spec/config_file/key_value.yml +6 -0
- data/spec/config_file/missing_env.yml +4 -0
- data/spec/config_file/with_envs.yml +7 -0
- data/spec/config_file/with_nested_envs.yml +11 -0
- data/spec/config_file_spec.rb +44 -0
- data/spec/content_for/different_key.erb +1 -0
- data/spec/content_for/different_key.erubis +1 -0
- data/spec/content_for/different_key.haml +2 -0
- data/spec/content_for/different_key.slim +2 -0
- data/spec/content_for/layout.erb +1 -0
- data/spec/content_for/layout.erubis +1 -0
- data/spec/content_for/layout.haml +1 -0
- data/spec/content_for/layout.slim +1 -0
- data/spec/content_for/multiple_blocks.erb +4 -0
- data/spec/content_for/multiple_blocks.erubis +4 -0
- data/spec/content_for/multiple_blocks.haml +8 -0
- data/spec/content_for/multiple_blocks.slim +8 -0
- data/spec/content_for/multiple_yields.erb +3 -0
- data/spec/content_for/multiple_yields.erubis +3 -0
- data/spec/content_for/multiple_yields.haml +3 -0
- data/spec/content_for/multiple_yields.slim +3 -0
- data/spec/content_for/passes_values.erb +1 -0
- data/spec/content_for/passes_values.erubis +1 -0
- data/spec/content_for/passes_values.haml +1 -0
- data/spec/content_for/passes_values.slim +1 -0
- data/spec/content_for/same_key.erb +1 -0
- data/spec/content_for/same_key.erubis +1 -0
- data/spec/content_for/same_key.haml +2 -0
- data/spec/content_for/same_key.slim +2 -0
- data/spec/content_for/takes_values.erb +1 -0
- data/spec/content_for/takes_values.erubis +1 -0
- data/spec/content_for/takes_values.haml +3 -0
- data/spec/content_for/takes_values.slim +3 -0
- data/spec/content_for_spec.rb +201 -0
- data/spec/decompile_spec.rb +44 -0
- data/spec/extension_spec.rb +33 -0
- data/spec/json_spec.rb +115 -0
- data/spec/link_header_spec.rb +100 -0
- data/spec/namespace/foo.erb +1 -0
- data/spec/namespace/nested/foo.erb +1 -0
- data/spec/namespace_spec.rb +623 -0
- data/spec/okjson.rb +581 -0
- data/spec/reloader/app.rb.erb +40 -0
- data/spec/reloader_spec.rb +441 -0
- data/spec/respond_with/bar.erb +1 -0
- data/spec/respond_with/bar.json.erb +1 -0
- data/spec/respond_with/foo.html.erb +1 -0
- data/spec/respond_with/not_html.sass +2 -0
- data/spec/respond_with_spec.rb +289 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/streaming_spec.rb +436 -0
- metadata +252 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'sinatra/contrib/setup'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
module Contrib
|
5
|
+
##
|
6
|
+
# Common middleware that doesn't bring run time overhead if not used
|
7
|
+
# or breaks if external dependencies are missing. Will extend
|
8
|
+
# Sinatra::Application by default.
|
9
|
+
module Common
|
10
|
+
register :ConfigFile
|
11
|
+
register :MultiRoute
|
12
|
+
register :Namespace
|
13
|
+
register :RespondWith
|
14
|
+
|
15
|
+
helpers :Capture
|
16
|
+
helpers :ContentFor
|
17
|
+
helpers :Cookies
|
18
|
+
helpers :EngineTracking
|
19
|
+
helpers :JSON
|
20
|
+
helpers :LinkHeader
|
21
|
+
helpers :Streaming
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Other extensions you don't want to be loaded unless needed.
|
26
|
+
module Custom
|
27
|
+
# register :Compass
|
28
|
+
register :Decompile
|
29
|
+
register :Reloader
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Stuff that aren't Sinatra extensions, technically.
|
34
|
+
autoload :Extension
|
35
|
+
autoload :TestHelpers
|
36
|
+
end
|
37
|
+
|
38
|
+
register Sinatra::Contrib::Common
|
39
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/contrib/version'
|
3
|
+
require 'backports'
|
4
|
+
|
5
|
+
module Sinatra
|
6
|
+
module Contrib
|
7
|
+
module Loader
|
8
|
+
def extensions
|
9
|
+
@extensions ||= {:helpers => [], :register => []}
|
10
|
+
end
|
11
|
+
|
12
|
+
def register(name, path = nil)
|
13
|
+
autoload name, path, :register
|
14
|
+
end
|
15
|
+
|
16
|
+
def helpers(name, path = nil)
|
17
|
+
autoload name, path, :helpers
|
18
|
+
end
|
19
|
+
|
20
|
+
def autoload(name, path = nil, method = nil)
|
21
|
+
path ||= "sinatra/#{name.to_s.underscore}"
|
22
|
+
extensions[method] << name if method
|
23
|
+
Sinatra.autoload(name, path)
|
24
|
+
end
|
25
|
+
|
26
|
+
def registered(base)
|
27
|
+
@extensions.each do |meth, list|
|
28
|
+
list = list.map { |name| Sinatra.const_get name }
|
29
|
+
base.send(meth, *list) unless base == ::Sinatra::Application
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module Common
|
35
|
+
extend Loader
|
36
|
+
end
|
37
|
+
|
38
|
+
module Custom
|
39
|
+
extend Loader
|
40
|
+
end
|
41
|
+
|
42
|
+
module All
|
43
|
+
def self.registered(base)
|
44
|
+
base.register Common, Custom
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
extend Loader
|
49
|
+
def self.registered(base)
|
50
|
+
base.register Common, Custom
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module Contrib
|
3
|
+
def self.version
|
4
|
+
VERSION
|
5
|
+
end
|
6
|
+
|
7
|
+
module VERSION
|
8
|
+
extend Comparable
|
9
|
+
|
10
|
+
MAJOR = 1
|
11
|
+
MINOR = 3
|
12
|
+
TINY = 0
|
13
|
+
SIGNATURE = [MAJOR, MINOR, TINY]
|
14
|
+
STRING = SIGNATURE.join '.'
|
15
|
+
|
16
|
+
def self.major; MAJOR end
|
17
|
+
def self.minor; MINOR end
|
18
|
+
def self.tiny; TINY end
|
19
|
+
def self.to_s; STRING end
|
20
|
+
|
21
|
+
def self.hash
|
22
|
+
STRING.hash
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.<=>(other)
|
26
|
+
other = other.split('.').map { |i| i.to_i } if other.respond_to? :split
|
27
|
+
SIGNATURE <=> Array(other)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.inspect
|
31
|
+
STRING.inspect
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.respond_to?(meth, *)
|
35
|
+
return true if super
|
36
|
+
meth.to_s !~ /^__|^to_str$/ and STRING.respond_to? meth
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.method_missing(meth, *args, &block)
|
40
|
+
return super unless STRING.respond_to?(meth)
|
41
|
+
STRING.send(meth, *args, &block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'backports'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Sinatra
|
6
|
+
|
7
|
+
# = Sinatra::Decompile
|
8
|
+
#
|
9
|
+
# <tt>Sinatra::Decompile</tt> is an extension that provides a method,
|
10
|
+
# conveniently called +decompile+, that will generate a String pattern for a
|
11
|
+
# given route.
|
12
|
+
#
|
13
|
+
# == Usage
|
14
|
+
#
|
15
|
+
# === Classic Application
|
16
|
+
#
|
17
|
+
# To use the extension in a classic application all you need to do is require
|
18
|
+
# it:
|
19
|
+
#
|
20
|
+
# require "sinatra"
|
21
|
+
# require "sinatra/decompile"
|
22
|
+
#
|
23
|
+
# # Your classic application code goes here...
|
24
|
+
#
|
25
|
+
# This will add the +decompile+ method to the application/class scope, but
|
26
|
+
# you can also call it as <tt>Sinatra::Decompile.decompile</tt>.
|
27
|
+
#
|
28
|
+
# === Modular Application
|
29
|
+
#
|
30
|
+
# To use the extension in a modular application you need to require it, and
|
31
|
+
# then, tell the application you will use it:
|
32
|
+
#
|
33
|
+
# require "sinatra/base"
|
34
|
+
# require "sinatra/decompile"
|
35
|
+
#
|
36
|
+
# class MyApp < Sinatra::Base
|
37
|
+
# register Sinatra::Decompile
|
38
|
+
#
|
39
|
+
# # The rest of your modular application code goes here...
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# This will add the +decompile+ method to the application/class scope. You
|
43
|
+
# can choose not to register the extension, but instead of calling
|
44
|
+
# +decompile+, you will need to call <tt>Sinatra::Decompile.decompile</tt>.
|
45
|
+
#
|
46
|
+
module Decompile
|
47
|
+
extend self
|
48
|
+
|
49
|
+
##
|
50
|
+
# Regenerates a string pattern for a given route
|
51
|
+
#
|
52
|
+
# Example:
|
53
|
+
#
|
54
|
+
# class Sinatra::Application
|
55
|
+
# routes.each do |verb, list|
|
56
|
+
# puts "#{verb}:"
|
57
|
+
# list.each do |data|
|
58
|
+
# puts "\t" << decompile(data)
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# Will return the internal Regexp if unable to reconstruct the pattern,
|
64
|
+
# which likely indicates that a Regexp was used in the first place.
|
65
|
+
#
|
66
|
+
# You can also use this to check whether you could actually use a string
|
67
|
+
# pattern instead of your regexp:
|
68
|
+
#
|
69
|
+
# decompile /^/foo$/ # => '/foo'
|
70
|
+
def decompile(pattern, keys = nil, *)
|
71
|
+
# Everything in here is basically just the reverse of
|
72
|
+
# Sinatra::Base#compile
|
73
|
+
pattern, keys = pattern if pattern.respond_to? :to_ary
|
74
|
+
keys, str = keys.try(:dup), pattern.inspect
|
75
|
+
return pattern unless str.start_with? '/' and str.end_with? '/'
|
76
|
+
str.gsub! /^\/\^?|\$?\/$/, ''
|
77
|
+
str.gsub! encoded(' '), ' '
|
78
|
+
return pattern if str =~ /^[\.\+]/
|
79
|
+
str.gsub! /\([^\(\)]*\)/ do |part|
|
80
|
+
case part
|
81
|
+
when '(.*?)'
|
82
|
+
return pattern if keys.shift != 'splat'
|
83
|
+
'*'
|
84
|
+
when '([^\/?#]+)'
|
85
|
+
return pattern if keys.empty?
|
86
|
+
":" << keys.shift
|
87
|
+
when /^\(\?\:\\?(.)\|/
|
88
|
+
char = $1
|
89
|
+
return pattern unless encoded(char) == part
|
90
|
+
Regexp.escape(char)
|
91
|
+
else
|
92
|
+
return pattern
|
93
|
+
end
|
94
|
+
end
|
95
|
+
str.gsub /(.)([\.\+\(\)\/])/ do
|
96
|
+
return pattern if $1 != "\\"
|
97
|
+
$2
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def encoded(char)
|
104
|
+
return super if defined? super
|
105
|
+
enc = URI.encode(char)
|
106
|
+
enc = "(?:#{Regexp.escape enc}|#{URI.encode char, /./})" if enc == char
|
107
|
+
enc = "(?:#{enc}|#{encoded('+')})" if char == " "
|
108
|
+
enc
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
register Decompile
|
113
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
module EngineTracking
|
5
|
+
attr_reader :current_engine
|
6
|
+
|
7
|
+
def erb?
|
8
|
+
@current_engine == :erb
|
9
|
+
end
|
10
|
+
|
11
|
+
def erubis?
|
12
|
+
@current_engine == :erubis or
|
13
|
+
erb? && Tilt[:erb] == Tilt::ErubisTemplate
|
14
|
+
end
|
15
|
+
|
16
|
+
def haml?
|
17
|
+
@current_engine == :haml
|
18
|
+
end
|
19
|
+
|
20
|
+
def sass?
|
21
|
+
@current_engine == :sass
|
22
|
+
end
|
23
|
+
|
24
|
+
def scss?
|
25
|
+
@current_engine == :scss
|
26
|
+
end
|
27
|
+
|
28
|
+
def less?
|
29
|
+
@current_engine == :less
|
30
|
+
end
|
31
|
+
|
32
|
+
def builder?
|
33
|
+
@current_engine == :builder
|
34
|
+
end
|
35
|
+
|
36
|
+
def liquid?
|
37
|
+
@current_engine == :liquid
|
38
|
+
end
|
39
|
+
|
40
|
+
def markdown?
|
41
|
+
@current_engine == :markdown
|
42
|
+
end
|
43
|
+
|
44
|
+
def textile?
|
45
|
+
@current_engine == :textile
|
46
|
+
end
|
47
|
+
|
48
|
+
def rdoc?
|
49
|
+
@current_engine == :rdoc
|
50
|
+
end
|
51
|
+
|
52
|
+
def radius?
|
53
|
+
@current_engine == :radius
|
54
|
+
end
|
55
|
+
|
56
|
+
def markaby?
|
57
|
+
@current_engine == :markaby
|
58
|
+
end
|
59
|
+
|
60
|
+
def coffee?
|
61
|
+
@current_engine == :coffee
|
62
|
+
end
|
63
|
+
|
64
|
+
def nokogiri?
|
65
|
+
@current_engine == :nokogiri
|
66
|
+
end
|
67
|
+
|
68
|
+
def slim?
|
69
|
+
@current_engine == :slim
|
70
|
+
end
|
71
|
+
|
72
|
+
def creole?
|
73
|
+
@current_engine == :creole
|
74
|
+
end
|
75
|
+
|
76
|
+
def initialize(*)
|
77
|
+
@current_engine = :ruby
|
78
|
+
super
|
79
|
+
end
|
80
|
+
|
81
|
+
def with_engine(engine)
|
82
|
+
@current_engine, engine_was = engine.to_sym, @current_engine
|
83
|
+
yield
|
84
|
+
ensure
|
85
|
+
@current_engine = engine_was
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def render(engine, *)
|
91
|
+
with_engine(engine) { super }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
helpers EngineTracking
|
96
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'backports/basic_object' unless defined? BasicObject
|
3
|
+
|
4
|
+
module Sinatra
|
5
|
+
|
6
|
+
# = Sinatra::Extension
|
7
|
+
#
|
8
|
+
# <tt>Sinatra::Extension</tt> is a mixin that provides some syntactic sugar
|
9
|
+
# for your extensions. It allows you to call directly inside your extension
|
10
|
+
# module almost any <tt>Sinatra::Base</tt> method. This means you can use
|
11
|
+
# +get+ to define a route, +before+ to define a before filter, +set+ to
|
12
|
+
# define a setting, a so on.
|
13
|
+
#
|
14
|
+
# Is important to be aware that this mixin remembers the methods calls you
|
15
|
+
# make, and then, when your extension is registered, replays them on the
|
16
|
+
# Sinatra application that has been extended. In order to do that, it
|
17
|
+
# defines a <tt>registered</tt> method, so, if your extension defines one
|
18
|
+
# too, remember to call +super+.
|
19
|
+
#
|
20
|
+
# == Usage
|
21
|
+
#
|
22
|
+
# Just require the mixin and extend your extension with it:
|
23
|
+
#
|
24
|
+
# require 'sinatra/extension'
|
25
|
+
#
|
26
|
+
# module MyExtension
|
27
|
+
# extend Sinatra::Extension
|
28
|
+
#
|
29
|
+
# # set some settings for development
|
30
|
+
# configure :development do
|
31
|
+
# set :reload_stuff, true
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# # define a route
|
35
|
+
# get '/' do
|
36
|
+
# 'Hello World'
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# # The rest of your extension code goes here...
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# You can also create an extension with the +new+ method:
|
43
|
+
#
|
44
|
+
# MyExtension = Sinatra::Extension.new do
|
45
|
+
# # Your extension code goes here...
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# This is useful when you just want to pass a block to
|
49
|
+
# <tt>Sinatra::Base.register</tt>.
|
50
|
+
module Extension
|
51
|
+
def self.new(&block)
|
52
|
+
ext = Module.new.extend(self)
|
53
|
+
ext.class_eval(&block)
|
54
|
+
ext
|
55
|
+
end
|
56
|
+
|
57
|
+
def settings
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def configure(*args, &block)
|
62
|
+
record(:configure, *args) { |c| c.instance_exec(c, &block) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def registered(base = nil, &block)
|
66
|
+
base ? replay(base) : record(:class_eval, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def record(method, *args, &block)
|
72
|
+
recorded_methods << [method, args, block]
|
73
|
+
end
|
74
|
+
|
75
|
+
def replay(object)
|
76
|
+
recorded_methods.each { |m, a, b| object.send(m, *a, &b) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def recorded_methods
|
80
|
+
@recorded_methods ||= []
|
81
|
+
end
|
82
|
+
|
83
|
+
def method_missing(method, *args, &block)
|
84
|
+
return super unless Sinatra::Base.respond_to? method
|
85
|
+
record(method, *args, &block)
|
86
|
+
DontCall.new(method)
|
87
|
+
end
|
88
|
+
|
89
|
+
class DontCall < BasicObject
|
90
|
+
def initialize(method) @method = method end
|
91
|
+
def method_missing(*) fail "not supposed to use result of #@method!" end
|
92
|
+
def inspect; "#<#{self.class}: #{@method}>" end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|