grape-markdown 0.0.1
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/.gitignore +17 -0
- data/.rspec +2 -0
- data/.rubocop.yml +18 -0
- data/.travis.yml +10 -0
- data/Gemfile +18 -0
- data/Guardfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +88 -0
- data/Rakefile +23 -0
- data/grape-markdown.gemspec +32 -0
- data/lib/grape/markdown.rb +1 -0
- data/lib/grape-markdown/config.rb +62 -0
- data/lib/grape-markdown/document.rb +76 -0
- data/lib/grape-markdown/parameter.rb +45 -0
- data/lib/grape-markdown/resource.rb +63 -0
- data/lib/grape-markdown/route.rb +54 -0
- data/lib/grape-markdown/sample_generator.rb +55 -0
- data/lib/grape-markdown/templates/document.md.erb +15 -0
- data/lib/grape-markdown/templates/properties.md.erb +7 -0
- data/lib/grape-markdown/version.rb +3 -0
- data/lib/grape-markdown.rb +27 -0
- data/spec/grape-markdown/config_spec.rb +91 -0
- data/spec/grape-markdown/document_spec.rb +73 -0
- data/spec/grape-markdown/resource_spec.rb +21 -0
- data/spec/grape-markdown/route_spec.rb +21 -0
- data/spec/grape-markdown/sample_generator_spec.rb +38 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/config_context.rb +13 -0
- data/spec/support/sample_api.rb +38 -0
- metadata +223 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3dc94cf1475a3e3615cc3215cdf9e54eb6a02fa8
|
4
|
+
data.tar.gz: 7d5e62aa00c83c69d95bc20c9b0d592bd47ddc87
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 855fcaf8917043fe5a6121a1722f6669a73d18bf3cb660ed8ca977f6f3b28b8534b27b1f6b4c600688e52a2c455c8fe34510e80ef54e7de7f4e88c45698bf999
|
7
|
+
data.tar.gz: 93694b04db560f1c38c99d1dc247602da9372092aab7501b71403eae875e2c57d80a59b2361a5c73660c867993f456f9edf68689f2ddad9797fd2c0ac6a218e0
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
AllCops:
|
2
|
+
Excludes:
|
3
|
+
- Rakefile
|
4
|
+
- vendor/**
|
5
|
+
- bin/**
|
6
|
+
|
7
|
+
Documentation:
|
8
|
+
# don't require classes to be documented
|
9
|
+
Enabled: false
|
10
|
+
|
11
|
+
Encoding:
|
12
|
+
# no need to always specify encoding
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
LineLength:
|
16
|
+
# just one more character please
|
17
|
+
Max: 80
|
18
|
+
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in grape-markdown.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'grape', github: 'intridea/grape'
|
7
|
+
|
8
|
+
group :development, :test do
|
9
|
+
gem 'coveralls', '~> 0.7'
|
10
|
+
gem 'rspec', '~> 2.14'
|
11
|
+
gem 'bundler', '~> 1.5'
|
12
|
+
gem 'rake', '~> 10.0'
|
13
|
+
gem 'rubocop', '~> 0.18'
|
14
|
+
gem 'pry', '~> 0.9'
|
15
|
+
gem 'guard', '~> 2.4'
|
16
|
+
gem 'guard-rspec', '~> 4.2'
|
17
|
+
gem 'guard-bundler', '~> 2.0'
|
18
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# More info at https://github.com/guard/guard#readme
|
2
|
+
|
3
|
+
guard 'rspec', :version => 2 do
|
4
|
+
watch(%r{^spec/.+_spec\.rb$})
|
5
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
6
|
+
watch('spec/spec_helper.rb') { "spec/" }
|
7
|
+
end
|
8
|
+
|
9
|
+
guard 'bundler' do
|
10
|
+
watch('Gemfile')
|
11
|
+
watch(/^.+\.gemspec/)
|
12
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 John Allen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# GrapeMarkdown
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/connexio-labs/grape-markdown)
|
4
|
+
[](https://travis-ci.org/connexio-labs/grape-markdown)
|
5
|
+
[](https://coveralls.io/r/connexio-labs/grape-markdown)
|
6
|
+
[](https://gemnasium.com/connexio-labs/grape-markdown)
|
7
|
+
[](http://badge.fury.io/rb/grape-markdown)
|
8
|
+
|
9
|
+
Auto generates Markdown from the docuementation that is created by your [Grape](https://github.com/intridea/grape) API.
|
10
|
+
|
11
|
+
### NOTE
|
12
|
+
|
13
|
+
This is an early implementation that makes some assumptions about your API (follows a standard REST pattern) that works with our implementation of Grape API's. This project will generate a very simplistic Markdown document. It primarily adds some wrappers around Grape's documentation and enables other gems ([grape-apiary](https://github.com/connexio-labs/grape-apiary) and [grape-slate](https://github.com/connexio-labs/grape-slate)) to generate Markdown in specific formats.
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
gem 'grape-markdown'
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install grape-markdown
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
Add some metadata about your API and then execute the `generate` method on the `GrapeMarkdown::Document` class.
|
32
|
+
|
33
|
+
### Configuration
|
34
|
+
|
35
|
+
Configure details about your api in an initializers or similar:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
GrapeMarkdown.config do |config|
|
39
|
+
# the name of your api
|
40
|
+
config.name = 'Awesome API'
|
41
|
+
# a description for your api
|
42
|
+
config.description = 'The awesome description'
|
43
|
+
# the type to use for generated sample id's (`integer` or `uuid`)
|
44
|
+
config.example_id_type = :uuid
|
45
|
+
# resources you do not want documented
|
46
|
+
config.resource_exclusion = [:admin, :swagger_doc]
|
47
|
+
# whether or not examples should include a root element (default: false)
|
48
|
+
config.include_root = true
|
49
|
+
end
|
50
|
+
|
51
|
+
# request headers you want documented
|
52
|
+
GrapeMarkdown.config.request_headers = [
|
53
|
+
{ 'Accept-Charset' => 'utf-8' },
|
54
|
+
{ 'Connection' => 'keep-alive' }
|
55
|
+
]
|
56
|
+
|
57
|
+
# response headers you want documented
|
58
|
+
GrapeMarkdown.config.response_headers = [
|
59
|
+
{ 'Content-Length' => '21685' },
|
60
|
+
{ 'Connection' => 'keep-alive' }
|
61
|
+
]
|
62
|
+
```
|
63
|
+
|
64
|
+
### Generation
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
# supply the class you'd like to document and generate your blueprint
|
68
|
+
GrapeMarkdown::Document.new(AwesomeAPI).generate
|
69
|
+
```
|
70
|
+
|
71
|
+
## TODO
|
72
|
+
|
73
|
+
* Add a rake task to simplify generation
|
74
|
+
* ~~Add support for listing all of a resources attributes at the resource level as a markdown table~~
|
75
|
+
* Handle ever changing sample id's (don't want git diff's after every generation)
|
76
|
+
* Add option to change or remove the sample id field (eg. `_id` vs `id`)
|
77
|
+
* What if someone does not use JSON?!?
|
78
|
+
* ~~Create sample response for list endpoints (array)~~
|
79
|
+
* Add support for writing the markdown to disk
|
80
|
+
* ~~Add an option to include root in json~~
|
81
|
+
|
82
|
+
## Contributing
|
83
|
+
|
84
|
+
1. Fork it ( http://github.com/connexio-labs/grape-markdown/fork )
|
85
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
86
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
87
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
88
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup :default, :test, :development
|
4
|
+
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
9
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'rainbow/ext/string' unless String.respond_to?(:color)
|
13
|
+
require 'rubocop/rake_task'
|
14
|
+
Rubocop::RakeTask.new(:rubocop)
|
15
|
+
|
16
|
+
task default: [:rubocop, :spec]
|
17
|
+
|
18
|
+
task :console do
|
19
|
+
require 'pry'
|
20
|
+
require 'grape-markdown'
|
21
|
+
ARGV.clear
|
22
|
+
Pry.start
|
23
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'grape-markdown/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'grape-markdown'
|
8
|
+
spec.version = GrapeMarkdown::VERSION
|
9
|
+
spec.authors = ['John Allen']
|
10
|
+
spec.email = ['john@threedogconsulting.com']
|
11
|
+
spec.summary = %q{Allows for generating a Markdown document from you Grape API}
|
12
|
+
spec.description = %q{Auto generates Markdown from the docuementation that is created by your Grape API}
|
13
|
+
spec.homepage = 'https://github.com/connexio-labs/grape-markdown'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'grape', '~> 0.6'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'coveralls', '~> 0.7'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 2.14'
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
+
spec.add_development_dependency 'rubocop', '~> 0.18'
|
28
|
+
spec.add_development_dependency 'pry', '~> 0.9'
|
29
|
+
spec.add_development_dependency 'guard', '~> 2.4'
|
30
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.2'
|
31
|
+
spec.add_development_dependency 'guard-bundler', '~> 2.0'
|
32
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'grape-markdown'
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module GrapeMarkdown
|
2
|
+
class Config
|
3
|
+
SETTINGS = [
|
4
|
+
:name,
|
5
|
+
:description,
|
6
|
+
:request_headers,
|
7
|
+
:response_headers,
|
8
|
+
:example_id_type,
|
9
|
+
:resource_exclusion,
|
10
|
+
:include_root
|
11
|
+
]
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_accessor(*SETTINGS)
|
15
|
+
|
16
|
+
def request_headers
|
17
|
+
@request_headers ||= []
|
18
|
+
end
|
19
|
+
|
20
|
+
def response_headers
|
21
|
+
@response_headers ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def resource_exclusion
|
25
|
+
@resource_exclusion ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
def include_root
|
29
|
+
@include_root ||= false
|
30
|
+
end
|
31
|
+
|
32
|
+
def supported_id_types
|
33
|
+
[:integer, :uuid, :bson]
|
34
|
+
end
|
35
|
+
|
36
|
+
def example_id_type=(value)
|
37
|
+
fail UnsupportedIDType unless supported_id_types.include?(value)
|
38
|
+
|
39
|
+
if value.to_sym == :bson && !Object.const_defined?('BSON')
|
40
|
+
fail BSONNotDefinied
|
41
|
+
end
|
42
|
+
|
43
|
+
@example_id_type = value
|
44
|
+
end
|
45
|
+
|
46
|
+
def example_id_type
|
47
|
+
@example_id_type ||= :integer
|
48
|
+
end
|
49
|
+
|
50
|
+
def generate_id
|
51
|
+
case example_id_type
|
52
|
+
when :integer
|
53
|
+
SecureRandom.random_number(1000)
|
54
|
+
when :uuid
|
55
|
+
SecureRandom.uuid
|
56
|
+
when :bson
|
57
|
+
BSON::ObjectId.new.to_s
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module GrapeMarkdown
|
2
|
+
class Document
|
3
|
+
attr_reader :api_class, :document_template, :properties_template
|
4
|
+
|
5
|
+
delegate(*GrapeMarkdown::Config::SETTINGS, to: 'GrapeMarkdown::Config')
|
6
|
+
|
7
|
+
def initialize(api_class)
|
8
|
+
@api_class = api_class
|
9
|
+
@document_template = template_for(:document)
|
10
|
+
@properties_template = template_for(:properties)
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate
|
14
|
+
ERB.new(document_template, nil, '-').result(binding)
|
15
|
+
end
|
16
|
+
|
17
|
+
def write
|
18
|
+
fail 'Not yet supported'
|
19
|
+
end
|
20
|
+
|
21
|
+
def routes
|
22
|
+
@routes ||= api_class.routes.map do |route|
|
23
|
+
GrapeMarkdown::Route.new(route)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def resources
|
28
|
+
@resources ||= begin
|
29
|
+
grouped_routes = routes.group_by(&:route_name).reject do |name, routes|
|
30
|
+
resource_exclusion.include?(name.to_sym)
|
31
|
+
end
|
32
|
+
|
33
|
+
grouped_routes.map { |name, routes| Resource.new(name, routes) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def properties_table(resource)
|
38
|
+
ERB.new(properties_template, nil, '-').result(resource.resource_binding)
|
39
|
+
end
|
40
|
+
|
41
|
+
def formatted_request_headers
|
42
|
+
formatted_headers(GrapeMarkdown::Config.request_headers)
|
43
|
+
end
|
44
|
+
|
45
|
+
def formatted_response_headers
|
46
|
+
formatted_headers(GrapeMarkdown::Config.response_headers)
|
47
|
+
end
|
48
|
+
|
49
|
+
def show_request_sample?(route)
|
50
|
+
%w(PUT POST).include?(route.route_method)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def template_for(name)
|
56
|
+
directory = File.dirname(File.expand_path(__FILE__))
|
57
|
+
path = File.join(directory, "./templates/#{name}.md.erb")
|
58
|
+
|
59
|
+
File.read(path)
|
60
|
+
end
|
61
|
+
|
62
|
+
def formatted_headers(headers)
|
63
|
+
return '' unless headers.present?
|
64
|
+
|
65
|
+
spacer = "\n" + (' ' * 12)
|
66
|
+
|
67
|
+
strings = headers.map do |header|
|
68
|
+
key, value = *header.first
|
69
|
+
|
70
|
+
"#{key}: #{value}"
|
71
|
+
end
|
72
|
+
|
73
|
+
" + Headers\n" + spacer + strings.join(spacer)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module GrapeMarkdown
|
2
|
+
class Parameter
|
3
|
+
attr_reader :route, :full_name, :name, :settings
|
4
|
+
|
5
|
+
delegate :route_model, :route_namespace, to: :route
|
6
|
+
delegate :requirement, :type, :documentation, :desc, to: :settings
|
7
|
+
delegate :example, to: :documentation, allow_nil: true
|
8
|
+
|
9
|
+
def initialize(route, name, options)
|
10
|
+
@full_name = name
|
11
|
+
@name = name
|
12
|
+
@name = name.scan(/\[(.*)\]/).flatten.first if name.include?('[')
|
13
|
+
@route = route
|
14
|
+
@settings = parse_options(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def description
|
18
|
+
"#{name} (#{requirement}, #{type}, `#{example}`) ... #{desc}"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def parse_options(options)
|
24
|
+
options = default_options(options) if options.blank?
|
25
|
+
|
26
|
+
options[:requirement] = options[:required] ? 'required' : 'optional'
|
27
|
+
|
28
|
+
Hashie::Mash.new(options)
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_options(options)
|
32
|
+
model = name.include?('_id') ? name.gsub('_id', '') : route.route_model
|
33
|
+
|
34
|
+
{
|
35
|
+
required: true,
|
36
|
+
requirement: 'required',
|
37
|
+
type: 'uuid',
|
38
|
+
desc: "the `id` of the `#{model}`",
|
39
|
+
documentation: {
|
40
|
+
example: GrapeMarkdown::Config.generate_id
|
41
|
+
}
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module GrapeMarkdown
|
2
|
+
class Resource
|
3
|
+
attr_reader :key, :name, :routes, :sample_generator
|
4
|
+
|
5
|
+
def initialize(key, routes)
|
6
|
+
@key = key
|
7
|
+
@name = key.humanize
|
8
|
+
@routes = routes
|
9
|
+
@sample_generator = SampleGenerator.new(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def title
|
13
|
+
@title ||= name.titleize
|
14
|
+
end
|
15
|
+
|
16
|
+
def namespaced
|
17
|
+
@namespaced ||= routes.group_by(&:route_namespace).map do |_, routes|
|
18
|
+
Resource.new(name, routes)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def paths
|
23
|
+
@paths ||= routes.group_by(&:route_path_without_format).map do |n, routes|
|
24
|
+
Resource.new(name, routes)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def header
|
29
|
+
# TODO: ???
|
30
|
+
route = routes.first
|
31
|
+
|
32
|
+
"#{title} #{route.route_type} [#{route.route_path_without_format}]"
|
33
|
+
end
|
34
|
+
|
35
|
+
def sample_request
|
36
|
+
sample_generator.request
|
37
|
+
end
|
38
|
+
|
39
|
+
def sample_response(route)
|
40
|
+
sample_generator.response(route.list?)
|
41
|
+
end
|
42
|
+
|
43
|
+
def unique_params
|
44
|
+
# TODO: this is a hack, assuming that the resource has a POST or PUT
|
45
|
+
# route that defines all of the parameters that would define the resource
|
46
|
+
methods = %w(POST PUT)
|
47
|
+
|
48
|
+
potential = routes.select do |route|
|
49
|
+
methods.include?(route.route_method) && route.route_params.present?
|
50
|
+
end
|
51
|
+
|
52
|
+
if potential.present?
|
53
|
+
potential.first.route_params
|
54
|
+
else
|
55
|
+
[]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def resource_binding
|
60
|
+
binding
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module GrapeMarkdown
|
2
|
+
class Route < SimpleDelegator
|
3
|
+
# would like to rely on SimpleDelegator but Grape::Route uses
|
4
|
+
# method_missing for these methods :'(
|
5
|
+
delegate :route_namespace, :route_path, :route_method, to: '__getobj__'
|
6
|
+
|
7
|
+
def route_params
|
8
|
+
@route_params ||= __getobj__.route_params.sort.map do |param|
|
9
|
+
Parameter.new(self, *param)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def route_name
|
14
|
+
route_namespace.split('/').last ||
|
15
|
+
route_path.match('\/(\w*?)[\.\/\(]').captures.first
|
16
|
+
end
|
17
|
+
|
18
|
+
def route_description
|
19
|
+
"#{__getobj__.route_description} [#{route_method.upcase}]"
|
20
|
+
end
|
21
|
+
|
22
|
+
def route_path_without_format
|
23
|
+
route_path.gsub(/\((.*?)\)/, '')
|
24
|
+
end
|
25
|
+
|
26
|
+
def route_model
|
27
|
+
route_namespace.split('/').last.singularize
|
28
|
+
end
|
29
|
+
|
30
|
+
def route_type
|
31
|
+
list? ? 'collection' : 'single'
|
32
|
+
end
|
33
|
+
|
34
|
+
def request_description
|
35
|
+
"+ Request #{'(application/json)' if request_body?}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def response_description
|
39
|
+
code = route_method == 'POST' ? 201 : 200
|
40
|
+
|
41
|
+
"+ Response #{code} (application/json)"
|
42
|
+
end
|
43
|
+
|
44
|
+
def list?
|
45
|
+
%w(GET POST).include?(route_method) && !route_path.include?(':id')
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def request_body?
|
51
|
+
!%w(GET DELETE).include?(route_method)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module GrapeMarkdown
|
2
|
+
class SampleGenerator
|
3
|
+
attr_reader :resource, :root
|
4
|
+
|
5
|
+
delegate :unique_params, to: :resource
|
6
|
+
|
7
|
+
def initialize(resource)
|
8
|
+
@resource = resource
|
9
|
+
@root = resource.key.singularize
|
10
|
+
end
|
11
|
+
|
12
|
+
def sample(id = false)
|
13
|
+
array = resource.unique_params.map do |param|
|
14
|
+
next if param.name == root
|
15
|
+
|
16
|
+
[param.name, param.example]
|
17
|
+
end
|
18
|
+
|
19
|
+
hash = Hash[array.compact]
|
20
|
+
|
21
|
+
hash = hash.reverse_merge(id: Config.generate_id) if id
|
22
|
+
hash = { root => hash } if Config.include_root
|
23
|
+
|
24
|
+
hash
|
25
|
+
end
|
26
|
+
|
27
|
+
def request
|
28
|
+
hash = sample
|
29
|
+
|
30
|
+
return unless hash.present?
|
31
|
+
|
32
|
+
# format json spaces for blueprint markdown
|
33
|
+
JSON.pretty_generate(hash)
|
34
|
+
.gsub('{', (' ' * 14) + '{')
|
35
|
+
.gsub('}', (' ' * 14) + '}')
|
36
|
+
.gsub(/\ {2}\"/, (' ' * 16) + '"')
|
37
|
+
end
|
38
|
+
|
39
|
+
def response(list = false)
|
40
|
+
hash = sample(true)
|
41
|
+
|
42
|
+
return unless hash.present?
|
43
|
+
|
44
|
+
hash = [hash] if list
|
45
|
+
|
46
|
+
# format json spaces for blueprint markdown
|
47
|
+
JSON.pretty_generate(hash)
|
48
|
+
.gsub('[', (' ' * 12) + '[')
|
49
|
+
.gsub(']', (' ' * 12) + ']')
|
50
|
+
.gsub('{', (' ' * 14) + '{')
|
51
|
+
.gsub('}', (' ' * 14) + '}')
|
52
|
+
.gsub(/\ {2}\"/, (' ' * 16) + '"')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# <%= name %>
|
2
|
+
|
3
|
+
<%= description %>
|
4
|
+
|
5
|
+
<% resources.each do |resource| %>
|
6
|
+
# <%= resource.title %>
|
7
|
+
<%= properties_table(resource) %>
|
8
|
+
<% resource.namespaced.each do |grouped_resource| %>
|
9
|
+
<% grouped_resource.paths.each do |resource_by_path| %>
|
10
|
+
<% resource_by_path.routes.each do |route| %>
|
11
|
+
## <%= route.route_description %>
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'grape'
|
2
|
+
|
3
|
+
module GrapeMarkdown
|
4
|
+
autoload :Version, 'grape-markdown/version'
|
5
|
+
autoload :Config, 'grape-markdown/config'
|
6
|
+
autoload :Parameter, 'grape-markdown/parameter'
|
7
|
+
autoload :SampleGenerator, 'grape-markdown/sample_generator'
|
8
|
+
autoload :Route, 'grape-markdown/route'
|
9
|
+
autoload :Resource, 'grape-markdown/resource'
|
10
|
+
autoload :Document, 'grape-markdown/document'
|
11
|
+
|
12
|
+
def self.config
|
13
|
+
block_given? ? yield(Config) : Config
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class UnsupportedIDType < StandardError
|
18
|
+
def message
|
19
|
+
'Unsupported id type, supported types are [integer, uuid, bson]'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class BSONNotDefinied < StandardError
|
24
|
+
def message
|
25
|
+
'BSON type id requested but bson library is not present'
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GrapeMarkdown::Config do
|
4
|
+
include_context 'configuration'
|
5
|
+
|
6
|
+
subject { GrapeMarkdown::Config }
|
7
|
+
|
8
|
+
it 'allows for name to be set' do
|
9
|
+
subject.name = name
|
10
|
+
|
11
|
+
expect(subject.name).to eq(name)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'allows for description to be set' do
|
15
|
+
subject.description = description
|
16
|
+
|
17
|
+
expect(subject.description).to eq(description)
|
18
|
+
end
|
19
|
+
|
20
|
+
context '.include_root' do
|
21
|
+
it 'defaults to false' do
|
22
|
+
expect(subject.include_root).to be(false)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'allows for inclusion of the root to be set' do
|
26
|
+
subject.include_root = true
|
27
|
+
|
28
|
+
expect(subject.include_root).to eq(true)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'headers' do
|
33
|
+
[:request_headers, :response_headers].each do |type|
|
34
|
+
context type do
|
35
|
+
it 'is an array' do
|
36
|
+
expect(subject.send(type)).to be_a(Array)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'allows for request headers to be set in bulk' do
|
40
|
+
headers = send(type)
|
41
|
+
|
42
|
+
subject.send("#{type}=", headers)
|
43
|
+
|
44
|
+
expect(subject.send(type)).to eq(headers)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'allows for request headers to be set individually' do
|
48
|
+
header = { Host: 'api.connexiolabs-qa.com' }
|
49
|
+
|
50
|
+
expect do
|
51
|
+
subject.send(type) << header
|
52
|
+
end.to change { subject.send(type).length }.by(1)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'sample id generation' do
|
59
|
+
it 'allows for setting the type for id generation' do
|
60
|
+
subject.example_id_type = :uuid
|
61
|
+
|
62
|
+
expect(subject.example_id_type).to eq(:uuid)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'guards against unsupported types' do
|
66
|
+
expect do
|
67
|
+
subject.example_id_type = :foo
|
68
|
+
end.to raise_error(UnsupportedIDType)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'checks for the bson library if requested' do
|
72
|
+
expect { subject.example_id_type = :bson }.to raise_error(BSONNotDefinied)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'generates a valid uuid' do
|
76
|
+
test = /[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/i
|
77
|
+
|
78
|
+
subject.example_id_type = :uuid
|
79
|
+
|
80
|
+
expect(subject.generate_id).to match(test)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'generates a valid integer' do
|
84
|
+
test = /^[0-9]{1,10}$/
|
85
|
+
|
86
|
+
subject.example_id_type = :integer
|
87
|
+
|
88
|
+
expect(subject.generate_id.to_s).to match(test)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GrapeMarkdown::Document do
|
4
|
+
include_context 'configuration'
|
5
|
+
|
6
|
+
before do
|
7
|
+
GrapeMarkdown.config do |config|
|
8
|
+
config.name = name
|
9
|
+
config.description = description
|
10
|
+
config.resource_exclusion = [:admin]
|
11
|
+
end
|
12
|
+
|
13
|
+
GrapeMarkdown.config.request_headers = [
|
14
|
+
{ 'Accept-Charset' => 'utf-8' },
|
15
|
+
{ 'Connection' => 'keep-alive' }
|
16
|
+
]
|
17
|
+
|
18
|
+
GrapeMarkdown.config.response_headers = [
|
19
|
+
{ 'Content-Length' => '21685' },
|
20
|
+
{ 'Connection' => 'keep-alive' }
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
subject { GrapeMarkdown::Document.new(SampleApi) }
|
25
|
+
|
26
|
+
context '#generate' do
|
27
|
+
let(:klass) { SampleApi }
|
28
|
+
|
29
|
+
subject { GrapeMarkdown::Document.new(klass).generate }
|
30
|
+
|
31
|
+
it 'creates a header from configuration' do
|
32
|
+
expect(subject).to include("# #{name}")
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'adds the description' do
|
36
|
+
expect(subject).to include(description)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'includes properties for the resources' do
|
40
|
+
expect(subject).to include('Properties')
|
41
|
+
`clear`
|
42
|
+
puts subject
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'exposes configuration settings' do
|
47
|
+
GrapeMarkdown::Config::SETTINGS.each do |setting|
|
48
|
+
expect(subject.send(setting)).to eq(GrapeMarkdown.config.send(setting))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'exposes the raw routes of the given api' do
|
53
|
+
expect(subject.routes).to eq(SampleApi.routes)
|
54
|
+
end
|
55
|
+
|
56
|
+
context '#resources' do
|
57
|
+
let(:unique_routes) { subject.routes.map(&:route_name).uniq }
|
58
|
+
|
59
|
+
let(:included_routes) do
|
60
|
+
unique_routes.reject do |name|
|
61
|
+
GrapeMarkdown.config.resource_exclusion.include?(name.to_sym)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'aggregates routes into resources' do
|
66
|
+
expect(subject.resources.first).to be_a(GrapeMarkdown::Resource)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'excluded resources based on configuration' do
|
70
|
+
expect(subject.resources.map(&:key)).to eq(included_routes)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GrapeMarkdown::Resource do
|
4
|
+
include_context 'configuration'
|
5
|
+
|
6
|
+
subject { GrapeMarkdown::Resource.new('foo', []) }
|
7
|
+
|
8
|
+
context 'sample' do
|
9
|
+
it 'request generation is delegated to a generator' do
|
10
|
+
expect(subject.sample_generator).to receive(:request)
|
11
|
+
|
12
|
+
subject.sample_request
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'response generation is delegated to a generator' do
|
16
|
+
expect(subject.sample_generator).to receive(:response)
|
17
|
+
|
18
|
+
subject.sample_response(GrapeMarkdown::Route.new(Grape::Route.new))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GrapeMarkdown::Route do
|
4
|
+
include_context 'configuration'
|
5
|
+
|
6
|
+
let(:routes) { GrapeMarkdown::Document.new(SampleApi).routes }
|
7
|
+
|
8
|
+
subject { routes.first }
|
9
|
+
|
10
|
+
it 'adds a name helper to routes' do
|
11
|
+
expect(subject.route_name).to eq('widgets')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'adds a path helper without format' do
|
15
|
+
expect(subject.route_path_without_format).to eq('/widgets')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'adds a type helper' do
|
19
|
+
expect(subject.route_type).to eq('collection')
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GrapeMarkdown::SampleGenerator do
|
4
|
+
include_context 'configuration'
|
5
|
+
|
6
|
+
before do
|
7
|
+
GrapeMarkdown.config do |config|
|
8
|
+
config.name = name
|
9
|
+
config.description = description
|
10
|
+
config.include_root = false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:blueprint) { GrapeMarkdown::Document.new(SampleApi) }
|
15
|
+
let(:resource) { blueprint.resources.first }
|
16
|
+
|
17
|
+
subject { GrapeMarkdown::SampleGenerator.new(resource) }
|
18
|
+
|
19
|
+
it 'creates a sample hash from a resource' do
|
20
|
+
expect(subject.sample).to be_a(Hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
context '#request' do
|
24
|
+
it 'creates a sample request in JSON form' do
|
25
|
+
expect { JSON.parse(subject.request) }.to_not raise_error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context '#response' do
|
30
|
+
it 'creates a sample response in JSON form' do
|
31
|
+
expect { JSON.parse(subject.response) }.to_not raise_error
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'includes a sample id' do
|
35
|
+
expect(JSON.parse(subject.response)['id']).to_not be(nil)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'support'))
|
4
|
+
|
5
|
+
require 'grape/markdown'
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'bundler'
|
9
|
+
Bundler.setup :default, :test
|
10
|
+
|
11
|
+
require 'coveralls'
|
12
|
+
Coveralls.wear!
|
13
|
+
|
14
|
+
require 'rspec'
|
15
|
+
require 'pry'
|
16
|
+
|
17
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
@@ -0,0 +1,13 @@
|
|
1
|
+
shared_context 'configuration' do
|
2
|
+
let(:name) { 'some api v1' }
|
3
|
+
let(:description) { 'some blueprint description' }
|
4
|
+
let(:resource_exclusion) { [:admin, :swagger_docs] }
|
5
|
+
|
6
|
+
let(:request_headers) do
|
7
|
+
[{ 'Accept-Charset' => 'utf-8' }]
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:response_headers) do
|
11
|
+
[{ 'Connection' => 'keep-alive' }]
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class SampleApi < Grape::API
|
2
|
+
resource 'widgets' do
|
3
|
+
desc 'widgets list'
|
4
|
+
get '/' do
|
5
|
+
end
|
6
|
+
|
7
|
+
desc 'individual widget'
|
8
|
+
get ':id' do
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'create a widget'
|
12
|
+
params do
|
13
|
+
requires :name,
|
14
|
+
type: 'string',
|
15
|
+
desc: 'the widgets name',
|
16
|
+
documentation: { example: 'super widget' }
|
17
|
+
optional :description,
|
18
|
+
type: 'string',
|
19
|
+
desc: 'the widgets name',
|
20
|
+
documentation: { example: 'the best widget ever made' }
|
21
|
+
end
|
22
|
+
post '/' do
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'update a widget'
|
26
|
+
params do
|
27
|
+
optional :name, type: 'string', desc: 'the widgets name'
|
28
|
+
optional :description, type: 'string', desc: 'the widgets name'
|
29
|
+
end
|
30
|
+
put ':id' do
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
resource 'admin' do
|
35
|
+
get '/' do
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: grape-markdown
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Allen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: grape
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: coveralls
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.14'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.14'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.5'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.5'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.18'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.18'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.9'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.9'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: guard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '2.4'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '2.4'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: guard-rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '4.2'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '4.2'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: guard-bundler
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '2.0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '2.0'
|
153
|
+
description: Auto generates Markdown from the docuementation that is created by your
|
154
|
+
Grape API
|
155
|
+
email:
|
156
|
+
- john@threedogconsulting.com
|
157
|
+
executables: []
|
158
|
+
extensions: []
|
159
|
+
extra_rdoc_files: []
|
160
|
+
files:
|
161
|
+
- ".gitignore"
|
162
|
+
- ".rspec"
|
163
|
+
- ".rubocop.yml"
|
164
|
+
- ".travis.yml"
|
165
|
+
- Gemfile
|
166
|
+
- Guardfile
|
167
|
+
- LICENSE.txt
|
168
|
+
- README.md
|
169
|
+
- Rakefile
|
170
|
+
- grape-markdown.gemspec
|
171
|
+
- lib/grape-markdown.rb
|
172
|
+
- lib/grape-markdown/config.rb
|
173
|
+
- lib/grape-markdown/document.rb
|
174
|
+
- lib/grape-markdown/parameter.rb
|
175
|
+
- lib/grape-markdown/resource.rb
|
176
|
+
- lib/grape-markdown/route.rb
|
177
|
+
- lib/grape-markdown/sample_generator.rb
|
178
|
+
- lib/grape-markdown/templates/document.md.erb
|
179
|
+
- lib/grape-markdown/templates/properties.md.erb
|
180
|
+
- lib/grape-markdown/version.rb
|
181
|
+
- lib/grape/markdown.rb
|
182
|
+
- spec/grape-markdown/config_spec.rb
|
183
|
+
- spec/grape-markdown/document_spec.rb
|
184
|
+
- spec/grape-markdown/resource_spec.rb
|
185
|
+
- spec/grape-markdown/route_spec.rb
|
186
|
+
- spec/grape-markdown/sample_generator_spec.rb
|
187
|
+
- spec/spec_helper.rb
|
188
|
+
- spec/support/config_context.rb
|
189
|
+
- spec/support/sample_api.rb
|
190
|
+
homepage: https://github.com/connexio-labs/grape-markdown
|
191
|
+
licenses:
|
192
|
+
- MIT
|
193
|
+
metadata: {}
|
194
|
+
post_install_message:
|
195
|
+
rdoc_options: []
|
196
|
+
require_paths:
|
197
|
+
- lib
|
198
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
199
|
+
requirements:
|
200
|
+
- - ">="
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: '0'
|
203
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
204
|
+
requirements:
|
205
|
+
- - ">="
|
206
|
+
- !ruby/object:Gem::Version
|
207
|
+
version: '0'
|
208
|
+
requirements: []
|
209
|
+
rubyforge_project:
|
210
|
+
rubygems_version: 2.2.2
|
211
|
+
signing_key:
|
212
|
+
specification_version: 4
|
213
|
+
summary: Allows for generating a Markdown document from you Grape API
|
214
|
+
test_files:
|
215
|
+
- spec/grape-markdown/config_spec.rb
|
216
|
+
- spec/grape-markdown/document_spec.rb
|
217
|
+
- spec/grape-markdown/resource_spec.rb
|
218
|
+
- spec/grape-markdown/route_spec.rb
|
219
|
+
- spec/grape-markdown/sample_generator_spec.rb
|
220
|
+
- spec/spec_helper.rb
|
221
|
+
- spec/support/config_context.rb
|
222
|
+
- spec/support/sample_api.rb
|
223
|
+
has_rdoc:
|