rocket_docs 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +24 -0
  4. data/app/assets/javascripts/rocket_docs/application.js +206 -0
  5. data/app/assets/stylesheets/rocket_docs/application.scss +51 -0
  6. data/app/controllers/rocket_docs/application_controller.rb +13 -0
  7. data/app/helpers/rocket_docs/application_helper.rb +24 -0
  8. data/app/views/docs/rocket_docs/_action.markdown.erb +23 -0
  9. data/app/views/docs/rocket_docs/_action.slim +43 -0
  10. data/app/views/docs/rocket_docs/_controller.markdown.erb +7 -0
  11. data/app/views/docs/rocket_docs/_controller.slim +9 -0
  12. data/app/views/docs/rocket_docs/_documentation.markdown.erb +4 -0
  13. data/app/views/docs/rocket_docs/_documentation.slim +3 -0
  14. data/app/views/docs/rocket_docs/_hash_param.slim +7 -0
  15. data/app/views/docs/rocket_docs/_version.slim +7 -0
  16. data/app/views/docs/rocket_docs/index.slim +3 -0
  17. data/app/views/docs/rocket_docs/show.markdown.erb +3 -0
  18. data/app/views/docs/rocket_docs/show.slim +4 -0
  19. data/app/views/layouts/rocket_docs/_modal.slim +12 -0
  20. data/app/views/layouts/rocket_docs/_navigation.slim +10 -0
  21. data/app/views/layouts/rocket_docs/application.slim +9 -0
  22. data/config/routes.rb +5 -0
  23. data/lib/rocket_docs/documentation/action.rb +98 -0
  24. data/lib/rocket_docs/documentation/controller.rb +57 -0
  25. data/lib/rocket_docs/documentation.rb +46 -0
  26. data/lib/rocket_docs/engine.rb +12 -0
  27. data/lib/rocket_docs/parser.rb +105 -0
  28. data/lib/rocket_docs/router.rb +86 -0
  29. data/lib/rocket_docs/version.rb +3 -0
  30. data/lib/rocket_docs.rb +30 -0
  31. data/lib/tasks/rocket_docs_tasks.rake +85 -0
  32. metadata +284 -0
@@ -0,0 +1,46 @@
1
+ require 'rocket_docs/documentation/controller'
2
+ require 'rocket_docs/documentation/action'
3
+
4
+ module RocketDocs
5
+ class Documentation
6
+ attr_reader :version
7
+ attr_reader :controllers
8
+
9
+ def initialize(version, controllers_hash)
10
+ @version = version
11
+ @controllers = []
12
+ @controllers_in = controllers_hash
13
+ generate
14
+ end
15
+
16
+ def should_update?
17
+ should_update = false
18
+ controllers.each { |c| should_update ||= c.should_update? }
19
+ should_update
20
+ end
21
+
22
+ def update
23
+ controllers.each(&:update)
24
+ self
25
+ end
26
+
27
+ def update!
28
+ controllers.each(&:update!)
29
+ self
30
+ end
31
+
32
+ private
33
+
34
+ def generate
35
+ build_controllers
36
+ update
37
+ end
38
+
39
+ def build_controllers
40
+ @controllers = []
41
+ @controllers_in.each do |n, v|
42
+ @controllers << Controller.new(n, v[:path], v[:actions], self)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,12 @@
1
+ module RocketDocs
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace RocketDocs
4
+ require 'jquery-rails'
5
+ require 'bootstrap-sass'
6
+
7
+ config.generators do |g|
8
+ g.test_framework :rspec
9
+ g.fixture_replacement :factory_girl, dir: 'spec/factories'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,105 @@
1
+ module RocketDocs
2
+ module Parser
3
+ class << self
4
+ def comments_for_method(method_name, file_path)
5
+ method_comments(file_path)[method_name.to_s]
6
+ end
7
+
8
+ def method_comments(file_path)
9
+ comments = {}
10
+ temp_comment = []
11
+ File.read(file_path).each_line do |line|
12
+ if extract_method_comment(line, comments, temp_comment)
13
+ temp_comment = []
14
+ end
15
+ end
16
+ clean_comments(comments)
17
+ end
18
+
19
+ def parse_comments(comments)
20
+ indentation_parser.read(comments, {})
21
+ end
22
+
23
+ def keywords
24
+ http_keywords + parser_keywords
25
+ end
26
+
27
+ def http_keywords
28
+ %w(GET POST PUT PATCH DELETE)
29
+ end
30
+
31
+ def parser_keywords
32
+ string_keywords + hash_keywords
33
+ end
34
+
35
+ private
36
+
37
+ def string_keywords
38
+ %w(DOC URL)
39
+ end
40
+
41
+ def hash_keywords
42
+ %w(PARAMS)
43
+ end
44
+
45
+ def indentation_parser
46
+ IndentationParser.new do |p|
47
+ indentation_parser_default(p)
48
+ indentation_parser_leafs(p)
49
+ end
50
+ end
51
+
52
+ def indentation_parser_default(p)
53
+ p.default do |parent, source|
54
+ parent ||= {}
55
+ words = source.split
56
+ keyword, key = words.first.upcase, words.first
57
+ if words.count == 1 && keywords.include?(keyword)
58
+ parent[keyword] = string_keywords.include?(keyword) ? '' : {}
59
+ elsif words.count == 1 && parent.is_a?(Hash)
60
+ parent[key] = {}
61
+ end
62
+ end
63
+ end
64
+
65
+ def indentation_parser_leafs(p)
66
+ p.on_leaf do |parent, source|
67
+ case parent
68
+ when String
69
+ parent << "\n" if parent.length != 0
70
+ parent << source.try(:strip) || ''
71
+ when Hash
72
+ k, v = source.split(':', 2)
73
+ parent[k] = v ? v.try(:strip) : {}
74
+ end
75
+ end
76
+ end
77
+
78
+ def extract_method_comment(line, comments = {}, temp_comment = [])
79
+ return true unless valid_line?(line)
80
+ if line =~ /^\s*def\s+\w+$/
81
+ comments[method_name(line)] = temp_comment.join("\n")
82
+ true
83
+ else
84
+ temp_comment << line
85
+ false
86
+ end
87
+ end
88
+
89
+ def valid_line?(line)
90
+ line =~ /^\s*#.*$/ || line =~ /^\s*def\s+\w+$/ || line =~ /^\s+$/
91
+ end
92
+
93
+ def method_name(line)
94
+ line.match(/^\s*def\s+\w+$/).to_s.split(' ').last
95
+ end
96
+
97
+ def clean_comments(comments)
98
+ comments.each do |k, v|
99
+ comments[k] = v.gsub(/^\s*#\s?/, '').gsub(/\n+/, "\n")
100
+ end
101
+ comments
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,86 @@
1
+ module RocketDocs
2
+ module Router
3
+ class << self
4
+ def api_full
5
+ result = {}
6
+ versions.each { |v| result[v] = {} }
7
+ result.each { |k, v| fill_controllers_hash_for_version(k, v) }
8
+ result
9
+ end
10
+
11
+ def api_controller_paths(controllers = api_controllers)
12
+ cp = controllers.map do |c|
13
+ c.instance_methods(false).map do |m|
14
+ c.instance_method(m).source_location.first
15
+ end
16
+ end
17
+ cp.flatten.uniq.compact
18
+ end
19
+
20
+ def api_controllers(names = api_controller_names)
21
+ names.map do |cn|
22
+ cn += '_controller'
23
+ cn.classify.constantize
24
+ end
25
+ end
26
+
27
+ def api_controller_names
28
+ ar = routes.named_routes.select { |_k, v| v.defaults[:rp_prefix] }
29
+ ar.values.map { |r| r.defaults[:controller] }.uniq
30
+ end
31
+
32
+ def routes_for_version(version)
33
+ routes.to_a.select { |v| v && v.defaults[:version] == version }
34
+ end
35
+
36
+ def versions
37
+ routes.to_a.map { |r| r && r.defaults[:version] }.uniq.compact
38
+ end
39
+
40
+ def routes
41
+ app_routes.routes
42
+ end
43
+
44
+ def app_routes
45
+ Rails.application.class.routes
46
+ end
47
+
48
+ private
49
+
50
+ def fill_controllers_hash_for_version(version, hash)
51
+ routes = routes_for_version(version)
52
+ routes.each do |r|
53
+ route_controller(hash, r)
54
+ end
55
+ end
56
+
57
+ def route_controller(ch, r)
58
+ cn = r.defaults[:controller]
59
+ ch[cn] ||= {}
60
+ ch[cn][:path] ||= api_controller_paths(api_controllers([cn])).first
61
+ ch[cn][:actions] ||= {}
62
+ route_action(ch[cn][:actions], r)
63
+ end
64
+
65
+ def route_action(hash, r)
66
+ ah = hash[r.defaults[:action]] ||= {}
67
+ ah[:params] = route_params(r)
68
+ route_methods(ah, r)
69
+ end
70
+
71
+ def route_params(r)
72
+ Hash[
73
+ r.required_parts.map do |name|
74
+ type = r.constraints[name.to_sym] || '???'
75
+ [name, type]
76
+ end
77
+ ]
78
+ end
79
+
80
+ def route_methods(hash, r)
81
+ hash[:methods] ||= []
82
+ hash[:methods] << r.constraints[:request_method]
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,3 @@
1
+ module RocketDocs
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,30 @@
1
+ require 'pry'
2
+ require 'slim'
3
+ require 'indentation-parser'
4
+ require 'rocket_docs/engine'
5
+ require 'rocket_docs/router'
6
+ require 'rocket_docs/parser'
7
+ require 'rocket_docs/documentation'
8
+
9
+ module RocketDocs
10
+ def self.documentation
11
+ Router.api_full.map do |version, controller|
12
+ Documentation.new(version, controller)
13
+ end
14
+ end
15
+
16
+ def self.documentation_for_version(version)
17
+ Documentation.new(version, Router.api_full[version])
18
+ end
19
+
20
+ def self.documentation_for_files(files, version_name = 'Unknown')
21
+ fake_controlers = files.map do |file|
22
+ fake_controller = {
23
+ path: file,
24
+ actions: Hash[Parser.method_comments(file).keys.map { |m, _c| [m, []] }]
25
+ }
26
+ [File.basename(file, '.rb'), fake_controller]
27
+ end
28
+ Documentation.new(version_name, Hash[fake_controlers])
29
+ end
30
+ end
@@ -0,0 +1,85 @@
1
+ namespace :rocket_docs do
2
+ desc 'Generates static HTML documentation files'
3
+ generator_args = [:version_name, :input_files, :output_folder]
4
+ task :generate, generator_args => :environment do |_task, args|
5
+ version, input, output = sanitize_generator_input(args)
6
+ fail('A version name has to be provided') unless version
7
+ fail('At leas one input file has to be provided') unless input
8
+
9
+ doc = RocketDocs.documentation_for_files(input, version)
10
+
11
+ template_folder = generator_template_folder
12
+ layout_path = template_folder + '/layouts/rocket_docs/application.slim'
13
+ template_path = template_folder + '/docs/rocket_docs/show.slim'
14
+
15
+ prepare_generator_output(output, version, 'html')
16
+
17
+ view_builder = generator_view_builder(template_folder)
18
+ view_builder.instance_variable_set(:@doc, doc)
19
+ layout = Slim::Template.new { File.open(layout_path, 'r').read }
20
+ view = Slim::Template.new { File.open(template_path, 'r').read }
21
+ html = layout.render(view_builder) do
22
+ view.render(view_builder).html_safe
23
+ end
24
+ File.open(output, 'w+') do |file|
25
+ file.puts(html)
26
+ end
27
+ end
28
+ task :gen, generator_args => :generate
29
+
30
+ desc 'Generates static MARKDOWN documentation files'
31
+ md_generator_args = generator_args
32
+ task :generate_markdown, md_generator_args => :environment do |_task, args|
33
+ version, input, output = sanitize_generator_input(args)
34
+
35
+ doc = RocketDocs.documentation_for_files(input, version)
36
+
37
+ template_folder = generator_template_folder
38
+ template_path = template_folder + '/docs/rocket_docs/show.markdown.erb'
39
+
40
+ prepare_generator_output(output, version, 'markdown')
41
+
42
+ view_builder = generator_view_builder(template_folder)
43
+ view_builder.instance_variable_set(:@doc, doc)
44
+ view = ERB.new(File.open(template_path, 'r').read)
45
+ html = view.result(view_builder.instance_eval { binding })
46
+ File.open(output, 'w+') do |file|
47
+ file.puts(html)
48
+ end
49
+ end
50
+ task :generate_md, md_generator_args => :generate_markdown
51
+ task :gen_md, md_generator_args => :generate_markdown
52
+
53
+ ###############
54
+ ### HELPERS ###
55
+ ###############
56
+
57
+ def sanitize_generator_input(args)
58
+ version = args[:version_name].presence
59
+ # TODO: Potential bug with pathnames containing spaces
60
+ input = args[:input_files] && args[:input_files].split.presence
61
+ output = args[:output_folder].presence ||
62
+ Rails.root.join('public', 'system', 'documentation').to_s
63
+ fail('A version name has to be provided') unless version
64
+ fail('At leas one input file has to be provided') unless input
65
+ [version, input, output]
66
+ end
67
+
68
+ def generator_template_folder
69
+ File.expand_path('../../../app/views', __FILE__)
70
+ end
71
+
72
+ def prepare_generator_output(output, name, ext)
73
+ FileUtils.mkdir_p(output)
74
+ output = output[-1] == '/' ? output : output << '/'
75
+ output << "#{name}.#{ext}"
76
+ end
77
+
78
+ def generator_view_builder(template_folder)
79
+ lookup_context = ActionView::LookupContext.new(template_folder)
80
+ view_builder = ActionView::Base.new(lookup_context)
81
+ view_builder.extend ActionView::Helpers
82
+ view_builder.extend RocketDocs::ApplicationHelper
83
+ view_builder
84
+ end
85
+ end
metadata ADDED
@@ -0,0 +1,284 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rocket_docs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Stanko Krtalić Rusendić
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: slim-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: jquery-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sass-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bootstrap-sass
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.3'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: indentation-parser
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.2'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.2'
111
+ - !ruby/object:Gem::Dependency
112
+ name: factory_girl_rails
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '4.5'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '4.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rocket_pants
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.10'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.10'
139
+ - !ruby/object:Gem::Dependency
140
+ name: pry
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.10'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.10'
153
+ - !ruby/object:Gem::Dependency
154
+ name: pry-rails
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.3'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '0.3'
167
+ - !ruby/object:Gem::Dependency
168
+ name: better_errors
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '2.1'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '2.1'
181
+ - !ruby/object:Gem::Dependency
182
+ name: binding_of_caller
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '0.7'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '0.7'
195
+ - !ruby/object:Gem::Dependency
196
+ name: sqlite3
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '1.3'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '1.3'
209
+ - !ruby/object:Gem::Dependency
210
+ name: appraisal
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '1.0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '1.0'
223
+ description: Unintrusive interactive API documentation generator for rails apps
224
+ email:
225
+ - stanko.krtalic@gmial.com
226
+ executables: []
227
+ extensions: []
228
+ extra_rdoc_files: []
229
+ files:
230
+ - MIT-LICENSE
231
+ - Rakefile
232
+ - app/assets/javascripts/rocket_docs/application.js
233
+ - app/assets/stylesheets/rocket_docs/application.scss
234
+ - app/controllers/rocket_docs/application_controller.rb
235
+ - app/helpers/rocket_docs/application_helper.rb
236
+ - app/views/docs/rocket_docs/_action.markdown.erb
237
+ - app/views/docs/rocket_docs/_action.slim
238
+ - app/views/docs/rocket_docs/_controller.markdown.erb
239
+ - app/views/docs/rocket_docs/_controller.slim
240
+ - app/views/docs/rocket_docs/_documentation.markdown.erb
241
+ - app/views/docs/rocket_docs/_documentation.slim
242
+ - app/views/docs/rocket_docs/_hash_param.slim
243
+ - app/views/docs/rocket_docs/_version.slim
244
+ - app/views/docs/rocket_docs/index.slim
245
+ - app/views/docs/rocket_docs/show.markdown.erb
246
+ - app/views/docs/rocket_docs/show.slim
247
+ - app/views/layouts/rocket_docs/_modal.slim
248
+ - app/views/layouts/rocket_docs/_navigation.slim
249
+ - app/views/layouts/rocket_docs/application.slim
250
+ - config/routes.rb
251
+ - lib/rocket_docs.rb
252
+ - lib/rocket_docs/documentation.rb
253
+ - lib/rocket_docs/documentation/action.rb
254
+ - lib/rocket_docs/documentation/controller.rb
255
+ - lib/rocket_docs/engine.rb
256
+ - lib/rocket_docs/parser.rb
257
+ - lib/rocket_docs/router.rb
258
+ - lib/rocket_docs/version.rb
259
+ - lib/tasks/rocket_docs_tasks.rake
260
+ homepage: http://github.com/stankec/Rocket_Docs
261
+ licenses:
262
+ - MIT
263
+ metadata: {}
264
+ post_install_message:
265
+ rdoc_options: []
266
+ require_paths:
267
+ - lib
268
+ required_ruby_version: !ruby/object:Gem::Requirement
269
+ requirements:
270
+ - - ">="
271
+ - !ruby/object:Gem::Version
272
+ version: '0'
273
+ required_rubygems_version: !ruby/object:Gem::Requirement
274
+ requirements:
275
+ - - ">="
276
+ - !ruby/object:Gem::Version
277
+ version: '0'
278
+ requirements: []
279
+ rubyforge_project:
280
+ rubygems_version: 2.4.5
281
+ signing_key:
282
+ specification_version: 4
283
+ summary: Interactive API documentation for rails apps
284
+ test_files: []