swagger_yard 0.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +113 -0
- data/Rakefile +40 -0
- data/app/controllers/swagger_yard/application_controller.rb +4 -0
- data/app/controllers/swagger_yard/swagger_controller.rb +21 -0
- data/app/views/swagger_yard/swagger/doc.html.erb +80 -0
- data/config/routes.rb +6 -0
- data/lib/generators/swagger_yard/doc_generator.rb +11 -0
- data/lib/generators/swagger_yard/js_generator.rb +13 -0
- data/lib/swagger_yard.rb +113 -0
- data/lib/swagger_yard/api.rb +132 -0
- data/lib/swagger_yard/api_declaration.rb +42 -0
- data/lib/swagger_yard/cache.rb +50 -0
- data/lib/swagger_yard/engine.rb +18 -0
- data/lib/swagger_yard/local_dispatcher.rb +51 -0
- data/lib/swagger_yard/parameter.rb +9 -0
- data/lib/swagger_yard/parser.rb +35 -0
- data/lib/swagger_yard/resource_listing.rb +32 -0
- data/lib/swagger_yard/version.rb +3 -0
- data/public/swagger-ui/css/hightlight.default.css +135 -0
- data/public/swagger-ui/css/screen.css +1759 -0
- data/public/swagger-ui/images/logo_small.png +0 -0
- data/public/swagger-ui/images/pet_store_api.png +0 -0
- data/public/swagger-ui/images/throbber.gif +0 -0
- data/public/swagger-ui/images/wordnik_api.png +0 -0
- data/public/swagger-ui/lib/MD5.js +319 -0
- data/public/swagger-ui/lib/backbone-min.js +38 -0
- data/public/swagger-ui/lib/handlebars-1.0.rc.1.js +1920 -0
- data/public/swagger-ui/lib/highlight.7.3.pack.js +1 -0
- data/public/swagger-ui/lib/jquery-1.8.0.min.js +2 -0
- data/public/swagger-ui/lib/jquery.ba-bbq.min.js +18 -0
- data/public/swagger-ui/lib/jquery.slideto.min.js +1 -0
- data/public/swagger-ui/lib/jquery.wiggle.min.js +8 -0
- data/public/swagger-ui/lib/swagger.js +794 -0
- data/public/swagger-ui/lib/underscore-min.js +32 -0
- data/public/swagger-ui/swagger-ui.js +2090 -0
- data/public/swagger-ui/swagger-ui_org.js +2005 -0
- metadata +125 -0
@@ -0,0 +1,132 @@
|
|
1
|
+
module SwaggerYard
|
2
|
+
class Api
|
3
|
+
attr_reader :nickname
|
4
|
+
attr_accessor :path, :parameters, :description, :http_method, :response_class, :summary, :notes, :error_responses
|
5
|
+
|
6
|
+
def initialize(yard_object)
|
7
|
+
@description = yard_object.docstring
|
8
|
+
@parameters = []
|
9
|
+
|
10
|
+
yard_object.tags.each do |tag|
|
11
|
+
value = tag.text
|
12
|
+
|
13
|
+
case tag.tag_name
|
14
|
+
when "path"
|
15
|
+
parse_path(value)
|
16
|
+
when "parameter"
|
17
|
+
@parameters << parse_parameter(value)
|
18
|
+
when "parameter_list"
|
19
|
+
@parameters << parse_parameter_list(value)
|
20
|
+
when "summary"
|
21
|
+
@summary = value
|
22
|
+
when "notes"
|
23
|
+
@notes = value.gsub("\n", "<br\>")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
@parameters.sort_by { |parameter| parameter["name"] }
|
28
|
+
@parameters << add_format_parameters
|
29
|
+
end
|
30
|
+
|
31
|
+
def nickname
|
32
|
+
@nickname ||= "#{http_method}".camelize
|
33
|
+
end
|
34
|
+
|
35
|
+
def operation
|
36
|
+
{
|
37
|
+
"httpMethod" => http_method,
|
38
|
+
"nickname" => path[1..-1].gsub(/[^a-zA-Z\d:]/, '-').squeeze("-") + http_method.downcase,
|
39
|
+
"responseClass" => response_class || "void",
|
40
|
+
"produces" => ["application/json", "application/xml"],
|
41
|
+
"parameters" => parameters,
|
42
|
+
"summary" => summary || description,
|
43
|
+
"notes" => notes,
|
44
|
+
"errorResponses" => error_responses
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_h
|
49
|
+
{
|
50
|
+
"path" => path,
|
51
|
+
"description" => description,
|
52
|
+
"operations" => [operation],
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def valid?
|
57
|
+
path.present?
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
##
|
62
|
+
# Example: [GET] /api/v2/ownerships.{format_type}
|
63
|
+
def parse_path(string)
|
64
|
+
@http_method, @path = string.match(/^\[(\w*)\]\s*(.*)$/).captures
|
65
|
+
|
66
|
+
path_params = @path.scan(/\{([^\}]+)\}/).flatten.reject { |value| value == "format_type" }
|
67
|
+
|
68
|
+
path_params.each do |path_param|
|
69
|
+
@parameters << {
|
70
|
+
"paramType" => "path",
|
71
|
+
"name" => path_param,
|
72
|
+
"description" => "Scope response to #{path_param}",
|
73
|
+
"dataType" => "string",
|
74
|
+
"required" => true,
|
75
|
+
"allowMultiple" => false
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Example: [Array] status Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
|
82
|
+
# Example: [Array] status(required) Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
|
83
|
+
# Example: [Integer] media[media_type_id] ID of the desired media type.
|
84
|
+
def parse_parameter(string)
|
85
|
+
data_type, name, required, description = string.match(/\A\[(\w*)\]\s*([\w\[\]]*)(\(required\))?\s*(.*)\Z/).captures
|
86
|
+
allow_multiple = name.gsub!("[]", "")
|
87
|
+
|
88
|
+
parameter = {
|
89
|
+
"paramType" => "query",
|
90
|
+
"name" => name,
|
91
|
+
"description" => description,
|
92
|
+
"dataType" => data_type.downcase,
|
93
|
+
"required" => required.present?,
|
94
|
+
"allowMultiple" => allow_multiple.present?
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Example: [String] sort_order Orders ownerships by fields. (e.g. sort_order=created_at)
|
100
|
+
# [List] id
|
101
|
+
# [List] begin_at
|
102
|
+
# [List] end_at
|
103
|
+
# [List] created_at
|
104
|
+
def parse_parameter_list(string)
|
105
|
+
data_type, name, required, description, set_string = string.match(/\A\[(\w*)\]\s*(\w*)(\(required\))?\s*(.*)\n([.\s\S]*)\Z/).captures
|
106
|
+
|
107
|
+
list_values = set_string.split("[List]").map(&:strip).reject { |string| string.empty? }
|
108
|
+
|
109
|
+
parameter = {
|
110
|
+
"paramType" => "query",
|
111
|
+
"name" => name,
|
112
|
+
"description" => description,
|
113
|
+
"dataType" => data_type.downcase,
|
114
|
+
"required" => required.present?,
|
115
|
+
"allowMultiple" => false,
|
116
|
+
"allowableValues" => {"valueType" => 'LIST', "values" => list_values}
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_format_parameters
|
121
|
+
@add_format_parameters ||= {
|
122
|
+
"paramType" => "path",
|
123
|
+
"name" => "format_type",
|
124
|
+
"description" => "Response format either JSON or XML",
|
125
|
+
"dataType" => "string",
|
126
|
+
"required" => true,
|
127
|
+
"allowMultiple" => false,
|
128
|
+
"allowableValues" => {"valueType" => "LIST", "values" => ["json", "xml"]}
|
129
|
+
}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module SwaggerYard
|
2
|
+
class ApiDeclaration
|
3
|
+
attr_accessor :description, :resource_path
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@apis = {}
|
7
|
+
@models = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_listing_info(yard_object)
|
11
|
+
@description = yard_object.docstring if yard_object.docstring.present?
|
12
|
+
tag = yard_object.tags.find { |tag| tag.tag_name == "resource_path"}
|
13
|
+
@resource_path = tag.text.downcase if tag.present?
|
14
|
+
tag.present?
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_api(api)
|
18
|
+
if @apis.keys.include?(api.path)
|
19
|
+
same_api_path = @apis[api.path]
|
20
|
+
same_api_path["operations"] << api.operation
|
21
|
+
@apis[api.path] = same_api_path
|
22
|
+
else
|
23
|
+
@apis[api.path] = api.to_h
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def resource_name
|
28
|
+
@resource_path
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_h
|
32
|
+
{
|
33
|
+
"apiVersion" => SwaggerYard.api_version,
|
34
|
+
"swaggerVersion" => SwaggerYard.swagger_version,
|
35
|
+
"basePath" => SwaggerYard.api_base_path,
|
36
|
+
"resource_path" => @resource_path,
|
37
|
+
"apis" => @apis.values,
|
38
|
+
"models" => @models
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module SwaggerYard
|
2
|
+
# For now just a simple wrapper class for a Memcache client.
|
3
|
+
class Cache
|
4
|
+
|
5
|
+
attr_reader :prefix, :store
|
6
|
+
|
7
|
+
def initialize(store, prefix)
|
8
|
+
@store = store
|
9
|
+
@prefix = prefix
|
10
|
+
end
|
11
|
+
|
12
|
+
# Read from the Cache.
|
13
|
+
def [](resource_name)
|
14
|
+
case
|
15
|
+
when store.respond_to?(:read)
|
16
|
+
store.read key_for(resource_name)
|
17
|
+
when store.respond_to?(:[])
|
18
|
+
store[key_for(resource_name)]
|
19
|
+
when store.respond_to?(:get)
|
20
|
+
store.get key_for(resource_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Write to the Cache.
|
25
|
+
def []=(resource_name, value)
|
26
|
+
case
|
27
|
+
when store.respond_to?(:write)
|
28
|
+
store.write key_for(resource_name), value
|
29
|
+
when store.respond_to?(:[]=)
|
30
|
+
store[key_for(resource_name)] = value
|
31
|
+
when store.respond_to?(:set)
|
32
|
+
store.set key_for(resource_name), value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def fetch(resource_name)
|
37
|
+
value = self[resource_name]
|
38
|
+
if value.nil? && block_given?
|
39
|
+
value = yield
|
40
|
+
self[resource_name] = yield
|
41
|
+
end
|
42
|
+
value
|
43
|
+
end
|
44
|
+
|
45
|
+
# Cache key for a given entry.
|
46
|
+
def key_for(resource_name)
|
47
|
+
[prefix, resource_name].join
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "swagger_yard/local_dispatcher"
|
2
|
+
|
3
|
+
module SwaggerYard
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
if SwaggerYard::LocalDispatcher.new.server?
|
6
|
+
isolate_namespace SwaggerYard
|
7
|
+
|
8
|
+
# NOTE: We should opt for asset pipeline instead of this.
|
9
|
+
initializer 'swagger_yard.load_static_assets' do |app|
|
10
|
+
app.middleware.use(::ActionDispatch::Static, "#{root}/public")
|
11
|
+
end
|
12
|
+
|
13
|
+
initializer "swagger_yard.finisher_hook" do |app|
|
14
|
+
SwaggerYard.generate!("#{app.root}/app/controllers/**/*.rb")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module SwaggerYard
|
2
|
+
# An instance of LocalEnvironment is responsible for determining the dispatcher.
|
3
|
+
# This is useful to determine whether or not to run SwaggerYard#generate!.
|
4
|
+
#
|
5
|
+
# Implementation heavily borrowed from NewRelic.
|
6
|
+
class LocalDispatcher
|
7
|
+
def discovered_dispatcher
|
8
|
+
discover_dispatcher unless @discovered_dispatcher
|
9
|
+
@discovered_dispatcher
|
10
|
+
end
|
11
|
+
|
12
|
+
def server?
|
13
|
+
[:thin, :unicorn].include?(discovered_dispatcher)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def discover_dispatcher
|
19
|
+
dispatchers = %w[sidekiq thin unicorn]
|
20
|
+
while dispatchers.any? && @discovered_dispatcher.nil?
|
21
|
+
send 'check_for_' + (dispatchers.shift)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_class_in_object_space(klass)
|
26
|
+
ObjectSpace.each_object(klass) do |x|
|
27
|
+
return x
|
28
|
+
end
|
29
|
+
return nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_for_unicorn
|
33
|
+
if defined?(::Unicorn) && defined?(::Unicorn::HttpServer)
|
34
|
+
v = find_class_in_object_space(::Unicorn::HttpServer)
|
35
|
+
@discovered_dispatcher = :unicorn if v
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def check_for_sidekiq
|
40
|
+
if defined?(::Sidekiq) && File.basename($0) == 'sidekiq'
|
41
|
+
@discovered_dispatcher = :sidekiq
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def check_for_thin
|
46
|
+
if defined?(::Thin) && defined?(::Thin::VERSION)
|
47
|
+
@discovered_dispatcher = :thin
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'api'
|
2
|
+
require_relative 'api_declaration'
|
3
|
+
require_relative 'resource_listing'
|
4
|
+
|
5
|
+
module SwaggerYard
|
6
|
+
class Parser
|
7
|
+
attr_reader :listing
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@listing = ResourceListing.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(yard_objects)
|
14
|
+
api_declaration = ApiDeclaration.new
|
15
|
+
retain_api = true
|
16
|
+
|
17
|
+
yard_objects.each do |yard_object|
|
18
|
+
case yard_object.type
|
19
|
+
when :class
|
20
|
+
break unless retain_api = api_declaration.add_listing_info(yard_object)
|
21
|
+
when :method
|
22
|
+
api = Api.new(yard_object)
|
23
|
+
api_declaration.add_api(api) if api.valid?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
if retain_api
|
28
|
+
@listing.add(api_declaration)
|
29
|
+
api_declaration
|
30
|
+
else
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module SwaggerYard
|
2
|
+
class ResourceListing
|
3
|
+
attr_reader :api_declarations
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@api_declarations = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(api_declaration)
|
10
|
+
@api_declarations << api_declaration
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_h
|
14
|
+
{
|
15
|
+
"apiVersion" => SwaggerYard.api_version,
|
16
|
+
"swaggerVersion" => SwaggerYard.swagger_version,
|
17
|
+
"basePath" => SwaggerYard.doc_base_path,
|
18
|
+
"apis" => list_api
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def list_api
|
24
|
+
@api_declarations.map do |api_declaration|
|
25
|
+
{
|
26
|
+
"path" => api_declaration.resource_path,
|
27
|
+
"description" => api_declaration.description
|
28
|
+
}
|
29
|
+
end.sort_by { |hsh| hsh["path"] }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
Original style from softwaremaniacs.org (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org>
|
4
|
+
|
5
|
+
*/
|
6
|
+
|
7
|
+
pre code {
|
8
|
+
display: block; padding: 0.5em;
|
9
|
+
background: #F0F0F0;
|
10
|
+
}
|
11
|
+
|
12
|
+
pre code,
|
13
|
+
pre .subst,
|
14
|
+
pre .tag .title,
|
15
|
+
pre .lisp .title,
|
16
|
+
pre .clojure .built_in,
|
17
|
+
pre .nginx .title {
|
18
|
+
color: black;
|
19
|
+
}
|
20
|
+
|
21
|
+
pre .string,
|
22
|
+
pre .title,
|
23
|
+
pre .constant,
|
24
|
+
pre .parent,
|
25
|
+
pre .tag .value,
|
26
|
+
pre .rules .value,
|
27
|
+
pre .rules .value .number,
|
28
|
+
pre .preprocessor,
|
29
|
+
pre .ruby .symbol,
|
30
|
+
pre .ruby .symbol .string,
|
31
|
+
pre .aggregate,
|
32
|
+
pre .template_tag,
|
33
|
+
pre .django .variable,
|
34
|
+
pre .smalltalk .class,
|
35
|
+
pre .addition,
|
36
|
+
pre .flow,
|
37
|
+
pre .stream,
|
38
|
+
pre .bash .variable,
|
39
|
+
pre .apache .tag,
|
40
|
+
pre .apache .cbracket,
|
41
|
+
pre .tex .command,
|
42
|
+
pre .tex .special,
|
43
|
+
pre .erlang_repl .function_or_atom,
|
44
|
+
pre .markdown .header {
|
45
|
+
color: #800;
|
46
|
+
}
|
47
|
+
|
48
|
+
pre .comment,
|
49
|
+
pre .annotation,
|
50
|
+
pre .template_comment,
|
51
|
+
pre .diff .header,
|
52
|
+
pre .chunk,
|
53
|
+
pre .markdown .blockquote {
|
54
|
+
color: #888;
|
55
|
+
}
|
56
|
+
|
57
|
+
pre .number,
|
58
|
+
pre .date,
|
59
|
+
pre .regexp,
|
60
|
+
pre .literal,
|
61
|
+
pre .smalltalk .symbol,
|
62
|
+
pre .smalltalk .char,
|
63
|
+
pre .go .constant,
|
64
|
+
pre .change,
|
65
|
+
pre .markdown .bullet,
|
66
|
+
pre .markdown .link_url {
|
67
|
+
color: #080;
|
68
|
+
}
|
69
|
+
|
70
|
+
pre .label,
|
71
|
+
pre .javadoc,
|
72
|
+
pre .ruby .string,
|
73
|
+
pre .decorator,
|
74
|
+
pre .filter .argument,
|
75
|
+
pre .localvars,
|
76
|
+
pre .array,
|
77
|
+
pre .attr_selector,
|
78
|
+
pre .important,
|
79
|
+
pre .pseudo,
|
80
|
+
pre .pi,
|
81
|
+
pre .doctype,
|
82
|
+
pre .deletion,
|
83
|
+
pre .envvar,
|
84
|
+
pre .shebang,
|
85
|
+
pre .apache .sqbracket,
|
86
|
+
pre .nginx .built_in,
|
87
|
+
pre .tex .formula,
|
88
|
+
pre .erlang_repl .reserved,
|
89
|
+
pre .prompt,
|
90
|
+
pre .markdown .link_label,
|
91
|
+
pre .vhdl .attribute,
|
92
|
+
pre .clojure .attribute,
|
93
|
+
pre .coffeescript .property {
|
94
|
+
color: #88F
|
95
|
+
}
|
96
|
+
|
97
|
+
pre .keyword,
|
98
|
+
pre .id,
|
99
|
+
pre .phpdoc,
|
100
|
+
pre .title,
|
101
|
+
pre .built_in,
|
102
|
+
pre .aggregate,
|
103
|
+
pre .css .tag,
|
104
|
+
pre .javadoctag,
|
105
|
+
pre .phpdoc,
|
106
|
+
pre .yardoctag,
|
107
|
+
pre .smalltalk .class,
|
108
|
+
pre .winutils,
|
109
|
+
pre .bash .variable,
|
110
|
+
pre .apache .tag,
|
111
|
+
pre .go .typename,
|
112
|
+
pre .tex .command,
|
113
|
+
pre .markdown .strong,
|
114
|
+
pre .request,
|
115
|
+
pre .status {
|
116
|
+
font-weight: bold;
|
117
|
+
}
|
118
|
+
|
119
|
+
pre .markdown .emphasis {
|
120
|
+
font-style: italic;
|
121
|
+
}
|
122
|
+
|
123
|
+
pre .nginx .built_in {
|
124
|
+
font-weight: normal;
|
125
|
+
}
|
126
|
+
|
127
|
+
pre .coffeescript .javascript,
|
128
|
+
pre .javascript .xml,
|
129
|
+
pre .tex .formula,
|
130
|
+
pre .xml .javascript,
|
131
|
+
pre .xml .vbscript,
|
132
|
+
pre .xml .css,
|
133
|
+
pre .xml .cdata {
|
134
|
+
opacity: 0.5;
|
135
|
+
}
|