swaggard 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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