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.
Files changed (75) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +135 -0
  3. data/Rakefile +61 -0
  4. data/ideas.md +29 -0
  5. data/lib/sinatra/capture.rb +42 -0
  6. data/lib/sinatra/config_file.rb +151 -0
  7. data/lib/sinatra/content_for.rb +111 -0
  8. data/lib/sinatra/contrib.rb +39 -0
  9. data/lib/sinatra/contrib/all.rb +2 -0
  10. data/lib/sinatra/contrib/setup.rb +53 -0
  11. data/lib/sinatra/contrib/version.rb +45 -0
  12. data/lib/sinatra/decompile.rb +113 -0
  13. data/lib/sinatra/engine_tracking.rb +96 -0
  14. data/lib/sinatra/extension.rb +95 -0
  15. data/lib/sinatra/json.rb +134 -0
  16. data/lib/sinatra/link_header.rb +132 -0
  17. data/lib/sinatra/namespace.rb +282 -0
  18. data/lib/sinatra/reloader.rb +384 -0
  19. data/lib/sinatra/respond_with.rb +245 -0
  20. data/lib/sinatra/streaming.rb +267 -0
  21. data/lib/sinatra/test_helpers.rb +87 -0
  22. data/sinatra-contrib.gemspec +121 -0
  23. data/spec/capture_spec.rb +80 -0
  24. data/spec/config_file/key_value.yml +6 -0
  25. data/spec/config_file/missing_env.yml +4 -0
  26. data/spec/config_file/with_envs.yml +7 -0
  27. data/spec/config_file/with_nested_envs.yml +11 -0
  28. data/spec/config_file_spec.rb +44 -0
  29. data/spec/content_for/different_key.erb +1 -0
  30. data/spec/content_for/different_key.erubis +1 -0
  31. data/spec/content_for/different_key.haml +2 -0
  32. data/spec/content_for/different_key.slim +2 -0
  33. data/spec/content_for/layout.erb +1 -0
  34. data/spec/content_for/layout.erubis +1 -0
  35. data/spec/content_for/layout.haml +1 -0
  36. data/spec/content_for/layout.slim +1 -0
  37. data/spec/content_for/multiple_blocks.erb +4 -0
  38. data/spec/content_for/multiple_blocks.erubis +4 -0
  39. data/spec/content_for/multiple_blocks.haml +8 -0
  40. data/spec/content_for/multiple_blocks.slim +8 -0
  41. data/spec/content_for/multiple_yields.erb +3 -0
  42. data/spec/content_for/multiple_yields.erubis +3 -0
  43. data/spec/content_for/multiple_yields.haml +3 -0
  44. data/spec/content_for/multiple_yields.slim +3 -0
  45. data/spec/content_for/passes_values.erb +1 -0
  46. data/spec/content_for/passes_values.erubis +1 -0
  47. data/spec/content_for/passes_values.haml +1 -0
  48. data/spec/content_for/passes_values.slim +1 -0
  49. data/spec/content_for/same_key.erb +1 -0
  50. data/spec/content_for/same_key.erubis +1 -0
  51. data/spec/content_for/same_key.haml +2 -0
  52. data/spec/content_for/same_key.slim +2 -0
  53. data/spec/content_for/takes_values.erb +1 -0
  54. data/spec/content_for/takes_values.erubis +1 -0
  55. data/spec/content_for/takes_values.haml +3 -0
  56. data/spec/content_for/takes_values.slim +3 -0
  57. data/spec/content_for_spec.rb +201 -0
  58. data/spec/decompile_spec.rb +44 -0
  59. data/spec/extension_spec.rb +33 -0
  60. data/spec/json_spec.rb +115 -0
  61. data/spec/link_header_spec.rb +100 -0
  62. data/spec/namespace/foo.erb +1 -0
  63. data/spec/namespace/nested/foo.erb +1 -0
  64. data/spec/namespace_spec.rb +623 -0
  65. data/spec/okjson.rb +581 -0
  66. data/spec/reloader/app.rb.erb +40 -0
  67. data/spec/reloader_spec.rb +441 -0
  68. data/spec/respond_with/bar.erb +1 -0
  69. data/spec/respond_with/bar.json.erb +1 -0
  70. data/spec/respond_with/foo.html.erb +1 -0
  71. data/spec/respond_with/not_html.sass +2 -0
  72. data/spec/respond_with_spec.rb +289 -0
  73. data/spec/spec_helper.rb +6 -0
  74. data/spec/streaming_spec.rb +436 -0
  75. 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,2 @@
1
+ require 'sinatra/contrib'
2
+ Sinatra.register Sinatra::Contrib::All
@@ -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