sinatra-browse 0.4 → 0.5
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/sinatra/browse.rb +40 -23
- data/lib/sinatra/browse/erb_templates/html.erb +35 -0
- data/lib/sinatra/browse/erb_templates/markdown.erb +7 -0
- data/lib/sinatra/browse/errors.rb +7 -0
- data/lib/sinatra/browse/format.rb +17 -16
- data/lib/sinatra/browse/parameter_type.rb +117 -0
- data/lib/sinatra/browse/parameter_types/boolean.rb +18 -0
- data/lib/sinatra/browse/parameter_types/float.rb +7 -0
- data/lib/sinatra/browse/parameter_types/integer.rb +7 -0
- data/lib/sinatra/browse/parameter_types/string.rb +13 -0
- data/lib/sinatra/browse/route.rb +39 -60
- data/lib/sinatra/browse/validator.rb +22 -0
- metadata +12 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1faa38c99f34fe11336ea7e4beb14b9c6c8c5d44
|
4
|
+
data.tar.gz: 2d1cc86c5d25a45f8c557202f095f74a9e145325
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a68e861b2d04655faa2a459d9246754b526829c1ca4ebfae6ef0c7c2502a7a39583981cdb22b5ec08819aa311f9d460136b96d90f904db964d586d0b0d448b1
|
7
|
+
data.tar.gz: 740fbf66e097ea5d34c5998ba248df93a09db40948312b9af0659f5f0b47186ad1f314904419ceee38e4434ebe1a4a8418fe35e8f02a237b4b8a0f2fa168fcdc
|
data/README.md
CHANGED
@@ -94,7 +94,7 @@ param :order, :String, in: ["ascending", "descending"]
|
|
94
94
|
|
95
95
|
The following parameter validators can only be used for parameters of type `:String`.
|
96
96
|
|
97
|
-
`format`
|
97
|
+
`format` The string must match this regular expression.
|
98
98
|
|
99
99
|
```ruby
|
100
100
|
param :alphanumeric, :String, format: /^[0-9A-Za-z]*$/
|
data/lib/sinatra/browse.rb
CHANGED
@@ -3,18 +3,36 @@
|
|
3
3
|
require 'sinatra/base'
|
4
4
|
|
5
5
|
Dir["#{File.dirname(__FILE__)}/browse/*.rb"].each {|f| require f }
|
6
|
+
Dir["#{File.dirname(__FILE__)}/browse/parameter_types/*.rb"].each do |f|
|
7
|
+
require f
|
8
|
+
end
|
6
9
|
|
7
10
|
module Sinatra::Browse
|
11
|
+
#
|
12
|
+
# Main DSL methods
|
13
|
+
#
|
8
14
|
def param(name, type, options = {})
|
9
15
|
temp_browse_params[name] = options.merge({ type: type })
|
10
16
|
end
|
11
17
|
|
12
18
|
def parameter_options(parameter, options)
|
13
|
-
|
19
|
+
if temp_browse_params[parameter].nil?
|
20
|
+
msg = "Tried to override undeclared parameter #{parameter}"
|
21
|
+
raise Errors::UnknownParameterError, msg
|
22
|
+
end
|
23
|
+
|
14
24
|
temp_browse_params[parameter].merge! options
|
15
25
|
end
|
16
26
|
alias :param_options :parameter_options
|
17
27
|
|
28
|
+
def describe(description)
|
29
|
+
@_browse_description = description
|
30
|
+
end
|
31
|
+
alias :desc :describe
|
32
|
+
|
33
|
+
#
|
34
|
+
# Internal stuff
|
35
|
+
#
|
18
36
|
def temp_browse_params
|
19
37
|
@_temp_browse_params ||= reset_temp_params
|
20
38
|
end
|
@@ -31,18 +49,20 @@ module Sinatra::Browse
|
|
31
49
|
@_browse_description ||= ""
|
32
50
|
end
|
33
51
|
|
34
|
-
def describe(description)
|
35
|
-
@_browse_description = description
|
36
|
-
end
|
37
|
-
alias :desc :describe
|
38
|
-
|
39
52
|
def browse_routes_for(request_method, path_info)
|
40
53
|
browse_routes.values.find { |v| v.matches?(request_method, path_info) }
|
41
54
|
end
|
42
55
|
|
43
|
-
|
44
|
-
|
45
|
-
|
56
|
+
def create_browse_route(request_method,
|
57
|
+
path_info,
|
58
|
+
description = browse_description,
|
59
|
+
new_params = temp_browse_params)
|
60
|
+
|
61
|
+
new_route = Route.new(request_method,
|
62
|
+
path_info,
|
63
|
+
browse_description,
|
64
|
+
new_params)
|
65
|
+
|
46
66
|
browse_routes[new_route.name] = new_route
|
47
67
|
end
|
48
68
|
|
@@ -76,29 +96,26 @@ module Sinatra::Browse
|
|
76
96
|
browse_route = app.browse_routes_for(request.request_method, request.path_info)
|
77
97
|
|
78
98
|
if browse_route
|
79
|
-
#TODO: Optionally throw error for undefined params
|
80
|
-
|
81
99
|
if settings.remove_undefined_parameters
|
82
100
|
browse_route.delete_undefined(params, settings.allowed_undefined_parameters)
|
83
101
|
end
|
84
102
|
|
85
|
-
browse_route.
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
instance_exec validation_result, &error_proc
|
103
|
+
validation_successful, error_hash = browse_route.process(params)
|
104
|
+
|
105
|
+
unless validation_successful
|
106
|
+
if error_hash[:on_error].respond_to?(:to_proc)
|
107
|
+
error_proc = error_hash.delete(:on_error).to_proc
|
108
|
+
instance_exec error_hash, &error_proc
|
92
109
|
else
|
93
|
-
instance_exec
|
110
|
+
instance_exec error_hash, &app.default_on_error
|
94
111
|
end
|
95
112
|
end
|
96
|
-
|
113
|
+
|
97
114
|
end
|
98
115
|
end
|
99
116
|
|
100
|
-
|
101
|
-
app.param :format, :String, in: ["
|
117
|
+
app.describe "Displays this browsable API."
|
118
|
+
app.param :format, :String, in: ["html", "json", "yaml", "yml"], default: "html"
|
102
119
|
app.get '/browse' do
|
103
120
|
Sinatra::Browse.format(params["format"], app.browse_routes).generate
|
104
121
|
end
|
@@ -106,7 +123,7 @@ module Sinatra::Browse
|
|
106
123
|
|
107
124
|
def self.route_added(verb, path, block)
|
108
125
|
return if verb == "HEAD" && !@app.settings.show_head_routes
|
109
|
-
@app.
|
126
|
+
@app.create_browse_route(verb, path)
|
110
127
|
@app.reset_temp_params
|
111
128
|
@app.desc ""
|
112
129
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<body>
|
4
|
+
<% @browse_routes.each do |name, route| %>
|
5
|
+
<h1><%= name %></h1>
|
6
|
+
|
7
|
+
<p><%= route.description %></p>
|
8
|
+
|
9
|
+
<% unless route.param_declarations.empty? %>
|
10
|
+
<h2>Parameters</h2>
|
11
|
+
|
12
|
+
<dl>
|
13
|
+
<% route.param_declarations.each do |name, param| %>
|
14
|
+
<dt><%= param.name %></dt>
|
15
|
+
|
16
|
+
<% if param.required? %>
|
17
|
+
<dd>Required</dd>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<dd>Type: <%= param.type %></dd>
|
21
|
+
|
22
|
+
<% if param.default %>
|
23
|
+
<dd>Default: <%= param.default %></dd>
|
24
|
+
<% end %>
|
25
|
+
|
26
|
+
<% param.validators.each do |v| %>
|
27
|
+
<dd><%= v.name %>: <%= h v.criteria %></dd>
|
28
|
+
<% end %>
|
29
|
+
|
30
|
+
<% end %>
|
31
|
+
</dl>
|
32
|
+
<% end %>
|
33
|
+
<% end %>
|
34
|
+
</body>
|
35
|
+
</html>
|
@@ -1,16 +1,19 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
require 'yaml'
|
4
|
+
require 'erb'
|
4
5
|
|
5
6
|
module Sinatra::Browse
|
6
7
|
def self.format(f, browse_routes)
|
7
8
|
case f
|
8
|
-
when "
|
9
|
-
|
9
|
+
when "html"
|
10
|
+
ErbTemplate.new(browse_routes, "html.erb")
|
10
11
|
when "json"
|
11
12
|
JSON.new(browse_routes)
|
12
|
-
when "yaml"
|
13
|
+
when "yaml", "yml"
|
13
14
|
YAML.new(browse_routes)
|
15
|
+
when "markdown"
|
16
|
+
ErbTemplate.new(browse_routes, "markdown.erb")
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
@@ -20,30 +23,28 @@ module Sinatra::Browse
|
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
23
|
-
class
|
26
|
+
class ErbTemplate < BrowseFormat
|
27
|
+
include ERB::Util
|
28
|
+
|
29
|
+
def initialize(browse_routes, filename)
|
30
|
+
super(browse_routes)
|
31
|
+
@template = File.read(File.dirname(__FILE__) + "/erb_templates/" + filename)
|
32
|
+
end
|
33
|
+
|
24
34
|
def generate
|
25
|
-
|
26
|
-
@browse_routes.each { |name, route|
|
27
|
-
output += "<h3>#{name}</h3>"
|
28
|
-
output += "<p>#{route.description}</p><ul>"
|
29
|
-
route.parameters.each { |param_key, param_value|
|
30
|
-
output += "<li>#{param_key} #{param_value.to_s}</li>"
|
31
|
-
}
|
32
|
-
output += "</ul>"
|
33
|
-
}
|
34
|
-
output
|
35
|
+
ERB.new(@template).result(binding)
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
39
|
class JSON < BrowseFormat
|
39
40
|
def generate
|
40
|
-
@browse_routes.values.map { |br| br.to_hash }.to_json
|
41
|
+
@browse_routes.values.map { |br| br.to_hash(noprocs: true) }.to_json
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
45
|
class YAML < BrowseFormat
|
45
46
|
def generate
|
46
|
-
@browse_routes.values.map { |br| br.to_hash }.to_yaml
|
47
|
+
@browse_routes.values.map { |br| br.to_hash(noprocs: true) }.to_yaml
|
47
48
|
end
|
48
49
|
end
|
49
50
|
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Sinatra::Browse
|
4
|
+
def self.parameter_type(name, &blk)
|
5
|
+
const_set "#{name}Type", Class.new(ParameterType, &blk)
|
6
|
+
end
|
7
|
+
|
8
|
+
class ParameterType
|
9
|
+
attr_reader :name
|
10
|
+
attr_reader :default
|
11
|
+
attr_reader :validators
|
12
|
+
|
13
|
+
def initialize(name, map)
|
14
|
+
@name = name
|
15
|
+
@default = map.delete(:default)
|
16
|
+
|
17
|
+
@transform = map.delete(:transform)
|
18
|
+
@transform = @transform.to_proc if @transform
|
19
|
+
|
20
|
+
@required = !! map[:required]
|
21
|
+
@on_error = map.delete(:on_error)
|
22
|
+
|
23
|
+
@validators = []
|
24
|
+
map.each do |key, value|
|
25
|
+
if val_blk = @@validator_declarations[key]
|
26
|
+
@validators << Validator.new(
|
27
|
+
name: key,
|
28
|
+
criteria: map[key],
|
29
|
+
validation_blk: val_blk
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def default
|
37
|
+
@default.is_a?(Proc) ? @default.call : @default
|
38
|
+
end
|
39
|
+
|
40
|
+
def required?
|
41
|
+
@required
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate(params)
|
45
|
+
@validators.each do |v|
|
46
|
+
return false, build_error_hash(v.name, v.value) unless v.validate(self.name, params)
|
47
|
+
end
|
48
|
+
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
def transform(value)
|
53
|
+
@transform ? @transform.call(value) : value
|
54
|
+
end
|
55
|
+
|
56
|
+
def coerce(value)
|
57
|
+
raise NotImplementedError
|
58
|
+
end
|
59
|
+
|
60
|
+
def build_error_hash(reason, value)
|
61
|
+
{
|
62
|
+
reason: reason,
|
63
|
+
parameter: self.name,
|
64
|
+
value: value,
|
65
|
+
on_error: @on_error
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def type
|
70
|
+
type_string = self.class.to_s.split("::").last
|
71
|
+
type_string[0, type_string.size - 4].to_sym
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_hash(options = {})
|
75
|
+
h = {
|
76
|
+
name: @name,
|
77
|
+
type: type,
|
78
|
+
required: required?,
|
79
|
+
}
|
80
|
+
|
81
|
+
if @default
|
82
|
+
h[:default] = if @default.is_a?(Proc) && options[:noprocs]
|
83
|
+
"dynamically generated"
|
84
|
+
else
|
85
|
+
@default
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
@validators.each { |v| h[v.name.to_sym] = v.criteria }
|
90
|
+
|
91
|
+
h
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# DSL
|
96
|
+
#
|
97
|
+
|
98
|
+
def self.coerce(&blk)
|
99
|
+
define_method(:coerce) { |value| blk.call(value) }
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.validator(name, &blk)
|
103
|
+
@@validator_declarations ||= {}
|
104
|
+
|
105
|
+
@@validator_declarations[name] = blk
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# Validators
|
110
|
+
#
|
111
|
+
|
112
|
+
# We need a to_s here because the user should be allowed to define dependencies
|
113
|
+
# using symbols while the actual keys of the params hash are strings
|
114
|
+
validator(:depends_on) { |dep| @params.has_key?(dep.to_s) }
|
115
|
+
validator(:in) { |possible_values| possible_values.member?(@value) }
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Sinatra::Browse
|
4
|
+
parameter_type(:Boolean) do
|
5
|
+
coerce do |value|
|
6
|
+
#TODO: Raise error if it's something else
|
7
|
+
# true and false are included here because they can be set as default
|
8
|
+
# values even though only strings will come through http requests
|
9
|
+
case value
|
10
|
+
when "y", "yes", "t", "true", "1", true
|
11
|
+
true
|
12
|
+
when "n", "no", "f", "false", "0", false
|
13
|
+
false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Sinatra::Browse
|
4
|
+
|
5
|
+
parameter_type(:String) do
|
6
|
+
coerce { |value| String(value) }
|
7
|
+
|
8
|
+
validator(:format) { |regex| !! (@value =~ regex) }
|
9
|
+
validator(:min_length) { |min_len| @value.length >= min_len }
|
10
|
+
validator(:max_length) { |max_len| @value.length <= max_len }
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
data/lib/sinatra/browse/route.rb
CHANGED
@@ -1,100 +1,69 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
|
3
|
+
module Sinatra::Browse
|
4
4
|
class Route
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :param_declarations
|
6
6
|
attr_reader :name
|
7
7
|
attr_reader :match
|
8
8
|
attr_reader :description
|
9
9
|
|
10
|
-
class ValidationError < Exception; end
|
11
|
-
|
12
10
|
# This is here because we're using the name as the keys for the
|
13
11
|
# _browse_routes hash. We want to build it outside of this class for that.
|
14
12
|
def self.build_name(request_method, path_info)
|
15
13
|
"#{request_method} #{path_info}"
|
16
14
|
end
|
17
15
|
|
18
|
-
def initialize(request_method, path_info, description,
|
16
|
+
def initialize(request_method, path_info, description, declaration_maps = nil)
|
19
17
|
@name = build_name(request_method, path_info)
|
20
18
|
@match = build_match(request_method, path_info)
|
21
19
|
@description = description
|
22
|
-
|
20
|
+
build_declarations(declaration_maps || {})
|
23
21
|
end
|
24
22
|
|
25
|
-
def to_hash
|
26
|
-
{
|
23
|
+
def to_hash(options = {})
|
24
|
+
{
|
25
|
+
route: @name,
|
26
|
+
description: @description,
|
27
|
+
parameters: @param_declarations.map { |name, pd| pd.to_hash(options) }
|
28
|
+
}
|
27
29
|
end
|
28
30
|
|
29
31
|
def matches?(request_method, path_info)
|
30
32
|
!! (build_name(request_method,path_info) =~ @match)
|
31
33
|
end
|
32
34
|
|
33
|
-
def has_parameter?(
|
34
|
-
@
|
35
|
+
def has_parameter?(name)
|
36
|
+
@param_declarations.has_key?(name.to_sym)
|
35
37
|
end
|
36
38
|
|
37
|
-
def
|
38
|
-
@
|
39
|
-
params
|
40
|
-
when :Boolean
|
41
|
-
cast_to_boolean(params[k])
|
42
|
-
else
|
43
|
-
send(v[:type], params[k])
|
44
|
-
end
|
45
|
-
}
|
46
|
-
end
|
39
|
+
def process(params)
|
40
|
+
@param_declarations.each do |name, pd|
|
41
|
+
name = name.to_s # The params hash uses strings but declarations use symbols
|
47
42
|
|
48
|
-
|
49
|
-
@parameters.each { |k,v|
|
50
|
-
unless params[k] || v[:default].nil?
|
51
|
-
params[k] = v[:default].is_a?(Proc) ? v[:default].call(params[k]) : v[:default]
|
52
|
-
end
|
53
|
-
}
|
54
|
-
end
|
55
|
-
|
56
|
-
def delete_undefined(params, allowed)
|
57
|
-
params.delete_if { |i| !(self.has_parameter?(i) || allowed.member?(i)) }
|
58
|
-
end
|
43
|
+
params[name] ||= pd.default
|
59
44
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
return fail_validation k, params[k], v, :depends_on if v[:depends_on] && !params[v[:depends_on]]
|
65
|
-
return fail_validation k, params[k], v, :in if v[:in] && !v[:in].member?(params[k])
|
66
|
-
|
67
|
-
if v[:type] == :String
|
68
|
-
return fail_validation k, params[k], v, :format if v[:format] && !(params[k] =~ v[:format])
|
69
|
-
return fail_validation k, params[k], v, :min_length if v[:min_length] && params[k].length < v[:min_length]
|
70
|
-
return fail_validation k, params[k], v, :max_length if v[:max_length] && params[k].length > v[:max_length]
|
71
|
-
end
|
45
|
+
# We specifically check for nil here since a boolean's default can be false
|
46
|
+
if params[name].nil?
|
47
|
+
return false, pd.build_error_hash(:required, nil) if pd.required?
|
48
|
+
next
|
72
49
|
end
|
73
|
-
}
|
74
50
|
|
75
|
-
|
76
|
-
end
|
51
|
+
params[name] = pd.coerce(params[name])
|
77
52
|
|
78
|
-
|
79
|
-
|
80
|
-
params[k] = v[:transform].to_proc.call(params[k]) if params[k] && v[:transform]
|
81
|
-
}
|
82
|
-
end
|
53
|
+
success, error_hash = pd.validate(params)
|
54
|
+
return false, error_hash unless success
|
83
55
|
|
84
|
-
|
85
|
-
def cast_to_boolean(param)
|
86
|
-
case param
|
87
|
-
when "y", "yes", "t", "true", "1"
|
88
|
-
true
|
89
|
-
when "n", "no", "f", "false", "0"
|
90
|
-
false
|
56
|
+
params[name] = pd.transform(params[name])
|
91
57
|
end
|
58
|
+
|
59
|
+
true
|
92
60
|
end
|
93
61
|
|
94
|
-
def
|
95
|
-
{
|
62
|
+
def delete_undefined(params, allowed)
|
63
|
+
params.delete_if { |i| !(self.has_parameter?(i) || allowed.member?(i)) }
|
96
64
|
end
|
97
65
|
|
66
|
+
private
|
98
67
|
def build_name(request_method, path_info)
|
99
68
|
self.class.build_name(request_method, path_info)
|
100
69
|
end
|
@@ -102,5 +71,15 @@
|
|
102
71
|
def build_match(request_method, path_info)
|
103
72
|
/^#{request_method}\s\s#{path_info.gsub(/:[^\/]*/, '[^\/]*')}$/
|
104
73
|
end
|
74
|
+
|
75
|
+
def build_declarations(declaration_maps)
|
76
|
+
@param_declarations = {}
|
77
|
+
|
78
|
+
declaration_maps.each do |name, map|
|
79
|
+
type = map.delete(:type)
|
80
|
+
|
81
|
+
@param_declarations[name] = Sinatra::Browse.const_get("#{type}Type").new(name, map)
|
82
|
+
end
|
83
|
+
end
|
105
84
|
end
|
106
85
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Sinatra::Browse
|
4
|
+
class Validator
|
5
|
+
attr_reader :criteria
|
6
|
+
attr_reader :value
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
def initialize(map)
|
10
|
+
@name = map[:name]
|
11
|
+
@criteria = map[:criteria]
|
12
|
+
@validation_blk = map[:validation_blk]
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate(param_name, params)
|
16
|
+
@value = params[param_name]
|
17
|
+
@params = params
|
18
|
+
|
19
|
+
instance_exec @criteria, &@validation_blk
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-browse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.5'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Axsh Co. LTD
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Parameter declaration framework and browsable API for Sinatra
|
14
14
|
email: dev@axsh.net
|
@@ -17,8 +17,17 @@ extensions: []
|
|
17
17
|
extra_rdoc_files: []
|
18
18
|
files:
|
19
19
|
- lib/sinatra/browse.rb
|
20
|
-
- lib/sinatra/browse/format.rb
|
21
20
|
- lib/sinatra/browse/route.rb
|
21
|
+
- lib/sinatra/browse/errors.rb
|
22
|
+
- lib/sinatra/browse/erb_templates/html.erb
|
23
|
+
- lib/sinatra/browse/erb_templates/markdown.erb
|
24
|
+
- lib/sinatra/browse/parameter_type.rb
|
25
|
+
- lib/sinatra/browse/parameter_types/boolean.rb
|
26
|
+
- lib/sinatra/browse/parameter_types/float.rb
|
27
|
+
- lib/sinatra/browse/parameter_types/string.rb
|
28
|
+
- lib/sinatra/browse/parameter_types/integer.rb
|
29
|
+
- lib/sinatra/browse/format.rb
|
30
|
+
- lib/sinatra/browse/validator.rb
|
22
31
|
- LICENSE
|
23
32
|
- README.md
|
24
33
|
homepage: https://github.com/axsh/sinatra-browse
|