swaggard 0.0.4

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 (74) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +178 -0
  4. data/Rakefile +24 -0
  5. data/app/assets/fonts/swaggard/droid-sans-v6-latin-700.eot +0 -0
  6. data/app/assets/fonts/swaggard/droid-sans-v6-latin-700.svg +411 -0
  7. data/app/assets/fonts/swaggard/droid-sans-v6-latin-700.ttf +0 -0
  8. data/app/assets/fonts/swaggard/droid-sans-v6-latin-700.woff +0 -0
  9. data/app/assets/fonts/swaggard/droid-sans-v6-latin-700.woff2 +0 -0
  10. data/app/assets/fonts/swaggard/droid-sans-v6-latin-regular.eot +0 -0
  11. data/app/assets/fonts/swaggard/droid-sans-v6-latin-regular.svg +403 -0
  12. data/app/assets/fonts/swaggard/droid-sans-v6-latin-regular.ttf +0 -0
  13. data/app/assets/fonts/swaggard/droid-sans-v6-latin-regular.woff +0 -0
  14. data/app/assets/fonts/swaggard/droid-sans-v6-latin-regular.woff2 +0 -0
  15. data/app/assets/images/swaggard/logo_small.png +0 -0
  16. data/app/assets/images/swaggard/pet_store_api.png +0 -0
  17. data/app/assets/images/swaggard/throbber.gif +0 -0
  18. data/app/assets/images/swaggard/wordnik_api.png +0 -0
  19. data/app/assets/javascripts/swaggard/application.js +24 -0
  20. data/app/assets/javascripts/swaggard/lib/MD5.js +319 -0
  21. data/app/assets/javascripts/swaggard/lib/backbone-min.js +15 -0
  22. data/app/assets/javascripts/swaggard/lib/handlebars-1.0.rc.1.js +1920 -0
  23. data/app/assets/javascripts/swaggard/lib/handlebars-2.0.0.js +28 -0
  24. data/app/assets/javascripts/swaggard/lib/highlight.7.3.pack.js +1 -0
  25. data/app/assets/javascripts/swaggard/lib/jquery-1.8.0.min.js +2 -0
  26. data/app/assets/javascripts/swaggard/lib/jquery.ba-bbq.min.js +18 -0
  27. data/app/assets/javascripts/swaggard/lib/jquery.slideto.min.js +1 -0
  28. data/app/assets/javascripts/swaggard/lib/jquery.wiggle.min.js +8 -0
  29. data/app/assets/javascripts/swaggard/lib/marked.js +1272 -0
  30. data/app/assets/javascripts/swaggard/lib/shred.bundle.js +2765 -0
  31. data/app/assets/javascripts/swaggard/lib/swagger-client.js +3294 -0
  32. data/app/assets/javascripts/swaggard/lib/swagger.js +794 -0
  33. data/app/assets/javascripts/swaggard/lib/underscore-min.js +32 -0
  34. data/app/assets/javascripts/swaggard/swagger-ui.js +2240 -0
  35. data/app/assets/javascripts/swaggard/swagger-ui_org.js +2005 -0
  36. data/app/assets/stylesheets/swaggard/application.css +16 -0
  37. data/app/assets/stylesheets/swaggard/reset.css +125 -0
  38. data/app/assets/stylesheets/swaggard/screen.css.scss +1256 -0
  39. data/app/assets/stylesheets/swaggard/typography.css.scss +26 -0
  40. data/app/controllers/swaggard/application_controller.rb +4 -0
  41. data/app/controllers/swaggard/swagger_controller.rb +21 -0
  42. data/app/views/swaggard/swagger/index.html.erb +74 -0
  43. data/config/routes.rb +3 -0
  44. data/lib/swaggard.rb +92 -0
  45. data/lib/swaggard/api_definition.rb +52 -0
  46. data/lib/swaggard/configuration.rb +82 -0
  47. data/lib/swaggard/engine.rb +18 -0
  48. data/lib/swaggard/parsers/controllers.rb +30 -0
  49. data/lib/swaggard/parsers/models.rb +29 -0
  50. data/lib/swaggard/parsers/routes.rb +54 -0
  51. data/lib/swaggard/swagger/definition.rb +24 -0
  52. data/lib/swaggard/swagger/operation.rb +98 -0
  53. data/lib/swaggard/swagger/parameters/base.rb +21 -0
  54. data/lib/swaggard/swagger/parameters/body.rb +67 -0
  55. data/lib/swaggard/swagger/parameters/form.rb +32 -0
  56. data/lib/swaggard/swagger/parameters/list.rb +46 -0
  57. data/lib/swaggard/swagger/parameters/path.rb +21 -0
  58. data/lib/swaggard/swagger/parameters/query.rb +32 -0
  59. data/lib/swaggard/swagger/path.rb +24 -0
  60. data/lib/swaggard/swagger/property.rb +23 -0
  61. data/lib/swaggard/swagger/response.rb +45 -0
  62. data/lib/swaggard/swagger/tag.rb +28 -0
  63. data/lib/swaggard/swagger/type.rb +72 -0
  64. data/lib/swaggard/version.rb +5 -0
  65. data/spec/fixtures/api.json +1 -0
  66. data/spec/fixtures/dummy/app/controllers/application_controller.rb +2 -0
  67. data/spec/fixtures/dummy/app/controllers/pets_controller.rb +15 -0
  68. data/spec/fixtures/dummy/config/application.rb +15 -0
  69. data/spec/fixtures/dummy/config/environments/development.rb +5 -0
  70. data/spec/fixtures/dummy/config/routes.rb +5 -0
  71. data/spec/fixtures/dummy/log/development.log +0 -0
  72. data/spec/integration/swaggard_spec.rb +19 -0
  73. data/spec/spec_helper.rb +27 -0
  74. metadata +210 -0
@@ -0,0 +1,26 @@
1
+ /* droid-sans-regular - latin */
2
+ @font-face {
3
+ font-family: 'Droid Sans';
4
+ font-style: normal;
5
+ font-weight: 400;
6
+ src: url('../fonts/droid-sans-v6-latin-regular.eot'); /* IE9 Compat Modes */
7
+ src: local('Droid Sans'), local('DroidSans'),
8
+ font-url('swaggard/droid-sans-v6-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
9
+ font-url('swaggard/droid-sans-v6-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
10
+ font-url('swaggard/droid-sans-v6-latin-regular.woff') format('woff'), /* Modern Browsers */
11
+ font-url('swaggard/droid-sans-v6-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
12
+ font-url('swaggard/droid-sans-v6-latin-regular.svg#DroidSans') format('svg'); /* Legacy iOS */
13
+ }
14
+ /* droid-sans-700 - latin */
15
+ @font-face {
16
+ font-family: 'Droid Sans';
17
+ font-style: normal;
18
+ font-weight: 700;
19
+ src: font-url('swaggard/droid-sans-v6-latin-700.eot'); /* IE9 Compat Modes */
20
+ src: local('Droid Sans Bold'), local('DroidSans-Bold'),
21
+ font-url('swaggard/droid-sans-v6-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
22
+ font-url('swaggard/droid-sans-v6-latin-700.woff2') format('woff2'), /* Super Modern Browsers */
23
+ font-url('swaggard/droid-sans-v6-latin-700.woff') format('woff'), /* Modern Browsers */
24
+ font-url('swaggard/droid-sans-v6-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */
25
+ font-url('swaggard/droid-sans-v6-latin-700.svg#DroidSans') format('svg'); /* Legacy iOS */
26
+ }
@@ -0,0 +1,4 @@
1
+ module Swaggard
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,21 @@
1
+ module Swaggard
2
+ class SwaggerController < ApplicationController
3
+
4
+ def index
5
+ respond_to do |format|
6
+ format.html do
7
+ @authentication_type = Swaggard.configuration.authentication_type
8
+ @authentication_key = Swaggard.configuration.authentication_key
9
+ @authentication_value = Swaggard.configuration.authentication_value
10
+
11
+ render :index
12
+ end
13
+
14
+ format.json do
15
+ render :json => Swaggard.get_doc
16
+ end
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,74 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Swagger UI</title>
5
+
6
+ <%= stylesheet_link_tag 'swaggard/application', media: 'all' %>
7
+ <%= javascript_include_tag 'swaggard/application' %>
8
+
9
+ <script type="text/javascript">
10
+ $(function () {
11
+ var url = window.location.search.match(/url=([^&]+)/);
12
+ if (url && url.length > 1) {
13
+ url = decodeURIComponent(url[1]);
14
+ } else {
15
+ url = location.protocol + "//" + location.host + "/swagger.json";
16
+ }
17
+ window.swaggerUi = new SwaggerUi({
18
+ url: url,
19
+ dom_id: "swagger-ui-container",
20
+ supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
21
+ onComplete: function(swaggerApi, swaggerUi){
22
+ $('pre code').each(function(i, e) {
23
+ hljs.highlightBlock(e)
24
+ });
25
+ },
26
+ onFailure: function(data) {
27
+ log("Unable to Load SwaggerUI");
28
+ },
29
+ docExpansion: "none",
30
+ apisSorter : "alpha"
31
+ });
32
+
33
+ function addApiKeyAuthorization() {
34
+ var key = $('#input_apiKey')[0].value;
35
+ log("key: " + key);
36
+ if(key && key.trim() != "") {
37
+ log("added key " + key);
38
+ window.authorizations.add('key', new ApiKeyAuthorization("<%= @authentication_key %>",
39
+ key,
40
+ "<%= @authentication_type %>"));
41
+ }
42
+ }
43
+
44
+ var $apiKeyInput = $('#input_apiKey');
45
+
46
+ $apiKeyInput.change(function() {
47
+ addApiKeyAuthorization();
48
+ });
49
+
50
+ var apiKey = "<%= @authentication_value %>";
51
+ $apiKeyInput.val(apiKey);
52
+ addApiKeyAuthorization();
53
+
54
+ window.swaggerUi.load();
55
+ });
56
+ </script>
57
+ </head>
58
+
59
+ <body class="swagger-section">
60
+ <div id='header'>
61
+ <div class="swagger-ui-wrap">
62
+ <a id="logo" href="http://swagger.io">swagger</a>
63
+ <form id='api_selector'>
64
+ <div class='input'><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/></div>
65
+ <div class='input'><input placeholder="<%= @authentication_key %>" id="input_apiKey" name="apiKey" type="text"/></div>
66
+ <div class='input'><a id="explore" href="#">Explore</a></div>
67
+ </form>
68
+ </div>
69
+ </div>
70
+
71
+ <div id="message-bar" class="swagger-ui-wrap">&nbsp;</div>
72
+ <div id="swagger-ui-container" class="swagger-ui-wrap"></div>
73
+ </body>
74
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Swaggard::Engine.routes.draw do
2
+ get '/(.:format)', to: 'swagger#index'
3
+ end
data/lib/swaggard.rb ADDED
@@ -0,0 +1,92 @@
1
+ require 'json'
2
+ require 'yard'
3
+
4
+ require 'swaggard/api_definition'
5
+ require 'swaggard/configuration'
6
+ require 'swaggard/engine'
7
+
8
+ require 'swaggard/parsers/controllers'
9
+ require 'swaggard/parsers/models'
10
+ require 'swaggard/parsers/routes'
11
+
12
+ module Swaggard
13
+
14
+ class << self
15
+ def configure
16
+ yield configuration
17
+ end
18
+
19
+ def configuration
20
+ @configuration ||= Swaggard::Configuration.new
21
+ end
22
+
23
+ # Register some custom yard tags
24
+ def register_custom_yard_tags!
25
+ ::YARD::Tags::Library.define_tag('Controller\'s tag', :tag)
26
+ ::YARD::Tags::Library.define_tag('Query parameter', :query_parameter)
27
+ ::YARD::Tags::Library.define_tag('Form parameter', :form_parameter)
28
+ ::YARD::Tags::Library.define_tag('Body parameter', :body_parameter)
29
+ ::YARD::Tags::Library.define_tag('Parameter list', :parameter_list)
30
+ ::YARD::Tags::Library.define_tag('Response class', :response_class)
31
+ end
32
+
33
+ def get_doc
34
+ load!
35
+
36
+ @api.to_doc
37
+ end
38
+
39
+ private
40
+
41
+ def load!
42
+ @api = Swaggard::ApiDefinition.new
43
+
44
+ parse_models
45
+ parse_controllers
46
+ end
47
+
48
+ def parse_controllers
49
+ parser = Parsers::Controllers.new
50
+
51
+ Dir[configuration.controllers_path].each do |file|
52
+ yard_objects = get_yard_objects(file)
53
+
54
+ tag, operations = parser.run(yard_objects, routes)
55
+
56
+ next unless tag
57
+
58
+ @api.add_tag(tag)
59
+ operations.each { |operation| @api.add_operation(operation) }
60
+ end
61
+ end
62
+
63
+ def routes
64
+ return @routes if @routes
65
+
66
+ parser = Parsers::Routes.new
67
+ @routes = parser.run(configuration.routes)
68
+ end
69
+
70
+ def parse_models
71
+ parser = Parsers::Models.new
72
+
73
+ definitions =[]
74
+ Dir[configuration.models_path].each do |file|
75
+ yard_objects = get_yard_objects(file)
76
+
77
+ definitions.concat(parser.run(yard_objects))
78
+ end
79
+
80
+ @api.definitions = definitions
81
+ end
82
+
83
+ def get_yard_objects(file)
84
+ ::YARD.parse(file)
85
+ yard_objects = ::YARD::Registry.all
86
+ ::YARD::Registry.clear
87
+
88
+ yard_objects
89
+ end
90
+
91
+ end
92
+ end
@@ -0,0 +1,52 @@
1
+ require_relative 'swagger/path'
2
+
3
+ module Swaggard
4
+ class ApiDefinition
5
+
6
+ attr_accessor :definitions
7
+
8
+ def initialize
9
+ @paths = {}
10
+ @tags = {}
11
+ @definitions = []
12
+ end
13
+
14
+ def add_tag(tag)
15
+ @tags[tag.name] ||= tag
16
+
17
+ @tags[tag.name].description = tag.description unless tag.description.blank?
18
+ end
19
+
20
+ def add_operation(operation)
21
+ @paths[operation.path] ||= Swagger::Path.new(operation.path)
22
+ @paths[operation.path].add_operation(operation)
23
+ @definitions.concat(operation.definitions)
24
+ end
25
+
26
+ def to_doc
27
+ {
28
+ 'swagger' => Swaggard.configuration.swagger_version,
29
+ 'info' => {
30
+ 'description' => Swaggard.configuration.description,
31
+ 'version' => Swaggard.configuration.api_version,
32
+ 'title' => Swaggard.configuration.title,
33
+ 'termsOfService' => Swaggard.configuration.tos,
34
+ 'contact' => {
35
+ 'email' => Swaggard.configuration.contact
36
+ },
37
+ 'license' => {
38
+ 'name' => Swaggard.configuration.license_name,
39
+ 'url' => Swaggard.configuration.license_url
40
+ }
41
+ },
42
+ 'host' => Swaggard.configuration.host,
43
+ 'basePath' => Swaggard.configuration.api_base_path,
44
+ 'tags' => @tags.map { |_, tag| tag.to_doc },
45
+ 'schemes' => Swaggard.configuration.schemes,
46
+ 'paths' => Hash[@paths.values.map { |path| [path.path, path.to_doc] }],
47
+ 'definitions' => Hash[@definitions.map { |definition| [definition.id, definition.to_doc] }]
48
+ }
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,82 @@
1
+ module Swaggard
2
+
3
+ # Configuration for Swagger Yard, use like:
4
+ #
5
+ # Swaggard.configure do |config|
6
+ # config.api_version = '0.1'
7
+ # config.doc_base_path = 'http://swagger.example.com/doc'
8
+ # config.api_base_path = 'http://swagger.example.com/api'
9
+ # config.authentication_type = 'header'
10
+ # config.authentication_key = 'X-AUTHORIZATION'
11
+ # config.authentication_value = 'you-secret-key'
12
+ # end
13
+ class Configuration
14
+
15
+ attr_accessor :doc_base_path, :api_base_path, :controllers_path, :models_path, :routes
16
+
17
+ attr_writer :swagger_version, :api_version, :api_path, :api_formats, :title, :description,
18
+ :tos, :contact, :host, :authentication_type, :authentication_key,
19
+ :authentication_value
20
+
21
+ def swagger_version
22
+ @swagger_version ||= '2.0'
23
+ end
24
+
25
+ def api_version
26
+ @api_version ||= '0.1'
27
+ end
28
+
29
+ def api_path
30
+ @api_path ||= ''
31
+ end
32
+
33
+ def api_formats
34
+ @api_formats ||= [:xml, :json]
35
+ end
36
+
37
+ def host
38
+ @host ||= ''
39
+ end
40
+
41
+ def schemes
42
+ @schemes ||= [:http]
43
+ end
44
+
45
+ def title
46
+ @title ||= ''
47
+ end
48
+
49
+ def description
50
+ @description ||= ''
51
+ end
52
+
53
+ def tos
54
+ @tos ||= ''
55
+ end
56
+
57
+ def contact
58
+ @contact ||= ''
59
+ end
60
+
61
+ def license_name
62
+ @license_name ||= ''
63
+ end
64
+
65
+ def license_url
66
+ @license_url ||= ''
67
+ end
68
+
69
+ def authentication_type
70
+ @authentication_type ||= 'query'
71
+ end
72
+
73
+ def authentication_key
74
+ @authentication_key ||= 'api_key'
75
+ end
76
+
77
+ def authentication_value
78
+ @authentication_value ||= ''
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,18 @@
1
+ module Swaggard
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Swaggard
4
+
5
+ initializer 'swaggard.finisher_hook', :after => :finisher_hook do |app|
6
+ app.reload_routes!
7
+
8
+ Swaggard.configure do |config|
9
+ config.controllers_path = "#{app.root}/app/controllers/**/*.rb"
10
+ config.models_path = "#{app.root}/app/serializers/**/*.rb"
11
+ config.routes = app.routes.routes
12
+ end
13
+
14
+ Swaggard.register_custom_yard_tags!
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ require_relative '../swagger/operation'
2
+ require_relative '../swagger/tag'
3
+
4
+ module Swaggard
5
+ module Parsers
6
+ class Controllers
7
+
8
+ def run(yard_objects, routes)
9
+ tag = nil
10
+ operations = []
11
+
12
+ yard_objects.each do |yard_object|
13
+ if yard_object.type == :class
14
+ tag = Swagger::Tag.new(yard_object)
15
+ elsif tag && yard_object.type == :method
16
+ operation = Swagger::Operation.new(yard_object, tag, routes)
17
+ operations << operation if operation.valid?
18
+ else
19
+ break
20
+ end
21
+ end
22
+
23
+ return unless operations.any?
24
+
25
+ return tag, operations
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ require_relative '../swagger/definition'
2
+ require_relative '../swagger/property'
3
+
4
+ module Swaggard
5
+ module Parsers
6
+ class Models
7
+
8
+ def run(yard_objects)
9
+ definitions = []
10
+
11
+ yard_objects.each do |yard_object|
12
+ next unless yard_object.type == :class
13
+
14
+ definition = Swagger::Definition.new(yard_object.name)
15
+
16
+ yard_object.tags.each do |tag|
17
+ property = Swagger::Property.new(tag)
18
+ definition.add_property(property)
19
+ end
20
+
21
+ definitions << definition
22
+ end
23
+
24
+ definitions
25
+ end
26
+
27
+ end
28
+ end
29
+ end