apidoc 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/VERSION +1 -1
- data/apidoc.gemspec +8 -2
- data/examples/burritos_api.html +30 -17
- data/examples/burritos_api.rb +13 -2
- data/examples/tacos_api.html +22 -21
- data/examples/tacos_api.rb +5 -5
- data/ftags +8 -0
- data/lib/apidoc.rb +49 -52
- data/spec/apidoc_spec.rb +16 -320
- data/spec/before_and_after_spec.rb +203 -0
- data/spec/html_writer_spec.rb +113 -0
- data/spec/support/test_apps.rb +34 -0
- data/templates/layout.mustache +14 -15
- data/templates/resource.mustache +1 -1
- metadata +37 -23
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -9,6 +9,7 @@ GEM
|
|
9
9
|
rake
|
10
10
|
rdoc
|
11
11
|
json (1.7.3)
|
12
|
+
kramdown (0.13.5)
|
12
13
|
mustache (0.99.4)
|
13
14
|
rack (1.4.0)
|
14
15
|
rack-protection (1.2.0)
|
@@ -40,6 +41,7 @@ DEPENDENCIES
|
|
40
41
|
bundler (~> 1.0.0)
|
41
42
|
jeweler (~> 1.8.3)
|
42
43
|
json
|
44
|
+
kramdown
|
43
45
|
mustache
|
44
46
|
rack-test
|
45
47
|
rdoc (~> 3.12)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/apidoc.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "apidoc"
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["T.J. VanSlyke"]
|
12
|
-
s.date = "2012-06-
|
12
|
+
s.date = "2012-06-05"
|
13
13
|
s.description = "Minimalist API documentation generator for Rack applications."
|
14
14
|
s.email = "tj@turing.com"
|
15
15
|
s.executables = ["apidoc"]
|
@@ -36,7 +36,10 @@ Gem::Specification.new do |s|
|
|
36
36
|
"ftags",
|
37
37
|
"lib/apidoc.rb",
|
38
38
|
"spec/apidoc_spec.rb",
|
39
|
+
"spec/before_and_after_spec.rb",
|
40
|
+
"spec/html_writer_spec.rb",
|
39
41
|
"spec/spec_helper.rb",
|
42
|
+
"spec/support/test_apps.rb",
|
40
43
|
"templates/apidoc_helper.rb",
|
41
44
|
"templates/layout.mustache",
|
42
45
|
"templates/resource.mustache"
|
@@ -55,6 +58,7 @@ Gem::Specification.new do |s|
|
|
55
58
|
s.add_runtime_dependency(%q<mustache>, [">= 0"])
|
56
59
|
s.add_runtime_dependency(%q<rack-test>, [">= 0"])
|
57
60
|
s.add_runtime_dependency(%q<mustache>, [">= 0"])
|
61
|
+
s.add_runtime_dependency(%q<kramdown>, [">= 0"])
|
58
62
|
s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
|
59
63
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
60
64
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
@@ -66,6 +70,7 @@ Gem::Specification.new do |s|
|
|
66
70
|
s.add_dependency(%q<mustache>, [">= 0"])
|
67
71
|
s.add_dependency(%q<rack-test>, [">= 0"])
|
68
72
|
s.add_dependency(%q<mustache>, [">= 0"])
|
73
|
+
s.add_dependency(%q<kramdown>, [">= 0"])
|
69
74
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
70
75
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
71
76
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
@@ -78,6 +83,7 @@ Gem::Specification.new do |s|
|
|
78
83
|
s.add_dependency(%q<mustache>, [">= 0"])
|
79
84
|
s.add_dependency(%q<rack-test>, [">= 0"])
|
80
85
|
s.add_dependency(%q<mustache>, [">= 0"])
|
86
|
+
s.add_dependency(%q<kramdown>, [">= 0"])
|
81
87
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
82
88
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
83
89
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
data/examples/burritos_api.html
CHANGED
@@ -108,21 +108,20 @@
|
|
108
108
|
font-size: 1em;
|
109
109
|
}
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
}
|
111
|
+
.api-resource .desc {
|
112
|
+
margin: 1em 0;
|
113
|
+
color:
|
114
|
+
#333;
|
115
|
+
display: block;
|
116
|
+
font-family: Helvetica, sans-serif;
|
117
|
+
font-size: 13px;
|
118
|
+
font-weight: 100;
|
119
|
+
height: 17px;
|
120
|
+
line-height: 17px;
|
121
|
+
text-shadow:
|
122
|
+
rgba(255, 255, 255, 0.597656) 0px 1px 0px;
|
123
|
+
vertical-align: baseline;
|
124
|
+
}
|
126
125
|
.api-resource .params,
|
127
126
|
.api-resource .response {
|
128
127
|
font-family: Monaco, fixed;
|
@@ -159,7 +158,8 @@
|
|
159
158
|
<div class="api-resource">
|
160
159
|
<div class="method">GET</div>
|
161
160
|
<div class="path">/burritos.json</div>
|
162
|
-
<div class="desc">Get all burritos
|
161
|
+
<div class="desc"><p>Get all burritos. <em>Note:</em> When requesting all burritos, please give the commissary ample time to prepare your order. Fattie.</p>
|
162
|
+
</div>
|
163
163
|
<div class="params"></div>
|
164
164
|
<div class="response">[
|
165
165
|
{
|
@@ -173,7 +173,8 @@
|
|
173
173
|
<div class="api-resource">
|
174
174
|
<div class="method">POST</div>
|
175
175
|
<div class="path">/burritos.json</div>
|
176
|
-
<div class="desc">Make a new delicious burrito</
|
176
|
+
<div class="desc"><p>Make a new delicious burrito</p>
|
177
|
+
</div>
|
177
178
|
<div class="params">{
|
178
179
|
"meat": "beef",
|
179
180
|
"lettuce": true
|
@@ -182,6 +183,18 @@
|
|
182
183
|
"meat": "beef",
|
183
184
|
"lettuce": true
|
184
185
|
}</div>
|
186
|
+
</div>
|
187
|
+
<div class="api-resource">
|
188
|
+
<div class="method">GET</div>
|
189
|
+
<div class="path">/burritos/:id.json</div>
|
190
|
+
<div class="desc"><p>Get a burrito by its ID</p>
|
191
|
+
</div>
|
192
|
+
<div class="params">{
|
193
|
+
}</div>
|
194
|
+
<div class="response">{
|
195
|
+
"meat": "beef",
|
196
|
+
"id": "123"
|
197
|
+
}</div>
|
185
198
|
</div>
|
186
199
|
|
187
200
|
</div>
|
data/examples/burritos_api.rb
CHANGED
@@ -13,6 +13,10 @@ class BurritoApp < Sinatra::Base
|
|
13
13
|
request.body
|
14
14
|
end
|
15
15
|
|
16
|
+
get '/burritos/:id.json' do
|
17
|
+
JSON.generate({ meat: 'beef', id: params['id'] })
|
18
|
+
end
|
19
|
+
|
16
20
|
end
|
17
21
|
|
18
22
|
doc = ApiDoc.new BurritoApp do
|
@@ -21,13 +25,20 @@ doc = ApiDoc.new BurritoApp do
|
|
21
25
|
content_type :json
|
22
26
|
|
23
27
|
get '/burritos.json' do
|
24
|
-
desc
|
28
|
+
desc %{Get all burritos. *Note:* When requesting all burritos, please give the commissary ample time to prepare your order. Fattie.}
|
25
29
|
end
|
26
30
|
|
27
31
|
post '/burritos.json' do
|
28
32
|
desc "Make a new delicious burrito"
|
29
33
|
params do
|
30
|
-
|
34
|
+
{ meat: 'beef', lettuce: true }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
get '/burritos/:id.json' do
|
39
|
+
desc "Get a burrito by its ID"
|
40
|
+
params do
|
41
|
+
{ id: 123 }
|
31
42
|
end
|
32
43
|
end
|
33
44
|
|
data/examples/tacos_api.html
CHANGED
@@ -108,21 +108,20 @@
|
|
108
108
|
font-size: 1em;
|
109
109
|
}
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
}
|
111
|
+
.api-resource .desc {
|
112
|
+
margin: 1em 0;
|
113
|
+
color:
|
114
|
+
#333;
|
115
|
+
display: block;
|
116
|
+
font-family: Helvetica, sans-serif;
|
117
|
+
font-size: 13px;
|
118
|
+
font-weight: 100;
|
119
|
+
height: 17px;
|
120
|
+
line-height: 17px;
|
121
|
+
text-shadow:
|
122
|
+
rgba(255, 255, 255, 0.597656) 0px 1px 0px;
|
123
|
+
vertical-align: baseline;
|
124
|
+
}
|
126
125
|
.api-resource .params,
|
127
126
|
.api-resource .response {
|
128
127
|
font-family: Monaco, fixed;
|
@@ -158,17 +157,19 @@
|
|
158
157
|
<div class="name"></div>
|
159
158
|
<div class="api-resource">
|
160
159
|
<div class="method">GET</div>
|
161
|
-
<div class="path">/tacos
|
162
|
-
<div class="desc">Get all tacos</
|
160
|
+
<div class="path">/tacos</div>
|
161
|
+
<div class="desc"><p>Get all tacos</p>
|
162
|
+
</div>
|
163
163
|
<div class="params"></div>
|
164
164
|
<div class="response">[{"meat":"chicken"}]</div>
|
165
165
|
</div>
|
166
166
|
<div class="api-resource">
|
167
167
|
<div class="method">POST</div>
|
168
|
-
<div class="path">/tacos
|
169
|
-
<div class="desc">Make a new delicious taco</
|
170
|
-
|
171
|
-
<div class="
|
168
|
+
<div class="path">/tacos</div>
|
169
|
+
<div class="desc"><p>Make a new delicious taco</p>
|
170
|
+
</div>
|
171
|
+
<div class="params">{:meat=>"beef", :lettuce=>true}</div>
|
172
|
+
<div class="response">meat=beef&lettuce=true</div>
|
172
173
|
</div>
|
173
174
|
|
174
175
|
</div>
|
data/examples/tacos_api.rb
CHANGED
@@ -5,11 +5,11 @@ require 'sinatra/base'
|
|
5
5
|
|
6
6
|
class TacoApp < Sinatra::Base
|
7
7
|
|
8
|
-
get '/tacos
|
8
|
+
get '/tacos' do
|
9
9
|
JSON.generate [ { meat: 'chicken' } ]
|
10
10
|
end
|
11
11
|
|
12
|
-
post '/tacos
|
12
|
+
post '/tacos' do
|
13
13
|
request.body
|
14
14
|
end
|
15
15
|
|
@@ -17,14 +17,14 @@ end
|
|
17
17
|
|
18
18
|
doc = ApiDoc.new TacoApp do
|
19
19
|
|
20
|
-
get '/tacos
|
20
|
+
get '/tacos' do
|
21
21
|
desc "Get all tacos"
|
22
22
|
end
|
23
23
|
|
24
|
-
post '/tacos
|
24
|
+
post '/tacos' do
|
25
25
|
desc "Make a new delicious taco"
|
26
26
|
params do
|
27
|
-
|
27
|
+
{ meat: 'beef', lettuce: true }
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
data/ftags
CHANGED
@@ -11,13 +11,21 @@ Gemfile.lock ./Gemfile.lock /^/;" r
|
|
11
11
|
LICENSE.txt ./LICENSE.txt /^/;" r
|
12
12
|
README.rdoc ./README.rdoc /^/;" r
|
13
13
|
Rakefile ./Rakefile /^/;" r
|
14
|
+
VERSION ./VERSION /^/;" r
|
14
15
|
apidoc ./bin/apidoc /^/;" r
|
16
|
+
apidoc-0.1.2.gem ./pkg/apidoc-0.1.2.gem /^/;" r
|
17
|
+
apidoc.gemspec ./apidoc.gemspec /^/;" r
|
15
18
|
apidoc.rb ./lib/apidoc.rb /^/;" r
|
16
19
|
apidoc_helper.rb ./templates/apidoc_helper.rb /^/;" r
|
17
20
|
apidoc_spec.rb ./spec/apidoc_spec.rb /^/;" r
|
18
21
|
authentication.rb ./examples/authentication.rb /^/;" r
|
22
|
+
before_and_after_spec.rb ./spec/before_and_after_spec.rb /^/;" r
|
23
|
+
burritos_api.html ./examples/burritos_api.html /^/;" r
|
24
|
+
burritos_api.rb ./examples/burritos_api.rb /^/;" r
|
19
25
|
config ./.bundle/config /^/;" r
|
20
26
|
ftags ./ftags /^/;" r
|
21
27
|
layout.mustache ./templates/layout.mustache /^/;" r
|
22
28
|
resource.mustache ./templates/resource.mustache /^/;" r
|
23
29
|
spec_helper.rb ./spec/spec_helper.rb /^/;" r
|
30
|
+
tacos_api.html ./examples/tacos_api.html /^/;" r
|
31
|
+
tacos_api.rb ./examples/tacos_api.rb /^/;" r
|
data/lib/apidoc.rb
CHANGED
@@ -2,6 +2,7 @@ require 'rack/test'
|
|
2
2
|
require 'thor'
|
3
3
|
require 'mustache'
|
4
4
|
require 'json'
|
5
|
+
require 'kramdown'
|
5
6
|
|
6
7
|
module ApiDoc
|
7
8
|
VERSION = "0.1.0"
|
@@ -99,6 +100,8 @@ module ApiDoc
|
|
99
100
|
end
|
100
101
|
|
101
102
|
def write(stream)
|
103
|
+
@runner.run
|
104
|
+
|
102
105
|
stream.write(
|
103
106
|
Mustache.to_html(File.read(File.dirname(__FILE__) + '/../templates/layout.mustache'), {
|
104
107
|
content: @runner.resources.map {|r| resource_html(r) }.join
|
@@ -109,39 +112,15 @@ module ApiDoc
|
|
109
112
|
end
|
110
113
|
|
111
114
|
def resource_html(resource)
|
112
|
-
resource.run
|
113
|
-
|
114
115
|
Mustache.to_html(File.read(File.dirname(__FILE__) + '/../templates/resource.mustache'), {
|
115
116
|
method: resource.method,
|
116
117
|
path: resource.path,
|
117
|
-
desc: resource.desc,
|
118
|
-
params: formatted_params
|
119
|
-
response: formatted_response
|
118
|
+
desc: Kramdown::Document.new(resource.desc).to_html,
|
119
|
+
params: resource.formatted_params,
|
120
|
+
response: resource.formatted_response
|
120
121
|
})
|
121
122
|
end
|
122
123
|
|
123
|
-
def formatted_params(resource)
|
124
|
-
return '' unless resource.params
|
125
|
-
return resource.params unless resource.accept
|
126
|
-
|
127
|
-
case resource.accept.intern
|
128
|
-
when :json
|
129
|
-
JSON.pretty_generate(JSON.parse(resource.params))
|
130
|
-
else
|
131
|
-
resource.params
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def formatted_response(resource)
|
136
|
-
return resource.response_body unless resource.content_type
|
137
|
-
|
138
|
-
case resource.content_type.intern
|
139
|
-
when :json
|
140
|
-
JSON.pretty_generate(JSON.parse(resource.response_body))
|
141
|
-
else
|
142
|
-
resource.response_body
|
143
|
-
end
|
144
|
-
end
|
145
124
|
end
|
146
125
|
|
147
126
|
class Resource
|
@@ -205,22 +184,60 @@ module ApiDoc
|
|
205
184
|
def run
|
206
185
|
@before_blocks.each {|block| instance_eval &block }
|
207
186
|
@params = @params.call if @params.is_a?(Proc)
|
208
|
-
@response = make_request
|
187
|
+
@response = make_request
|
209
188
|
@after_blocks.each {|block| instance_eval &block }
|
210
189
|
end
|
211
190
|
|
191
|
+
def filtered_params
|
192
|
+
params.reject {|k, v| path_captures.include?(k) or path_captures.include?(k.to_s)}
|
193
|
+
end
|
194
|
+
|
195
|
+
def formatted_params
|
196
|
+
return '' unless params
|
197
|
+
return filtered_params unless accept
|
198
|
+
|
199
|
+
case accept.intern
|
200
|
+
when :json
|
201
|
+
JSON.pretty_generate(filtered_params)
|
202
|
+
else
|
203
|
+
filtered_params
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def formatted_response
|
208
|
+
return response_body unless content_type
|
209
|
+
|
210
|
+
case content_type.intern
|
211
|
+
when :json
|
212
|
+
JSON.pretty_generate(JSON.parse(response_body))
|
213
|
+
else
|
214
|
+
response_body
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
212
218
|
def response_body
|
213
219
|
@response.body
|
214
220
|
end
|
215
221
|
|
216
|
-
|
222
|
+
PATH_CAPTURE_REGEXP = /:[^\.\/]+/
|
217
223
|
|
218
|
-
|
224
|
+
def path_captures
|
225
|
+
@path.match(PATH_CAPTURE_REGEXP).to_a.map {|m| m.gsub(':', '').intern }
|
226
|
+
end
|
219
227
|
|
220
|
-
def
|
221
|
-
|
228
|
+
def interpolated_path
|
229
|
+
@path.gsub(PATH_CAPTURE_REGEXP) do |match|
|
230
|
+
params[match.gsub(':', '').intern]
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def make_request
|
235
|
+
self.send(@method.downcase.intern, interpolated_path, formatted_params)
|
222
236
|
end
|
223
237
|
|
238
|
+
end
|
239
|
+
|
240
|
+
class PostResource < Resource
|
224
241
|
def initialize(runner, path, &block)
|
225
242
|
super runner, path, &block
|
226
243
|
@method = 'POST'
|
@@ -228,11 +245,6 @@ module ApiDoc
|
|
228
245
|
end
|
229
246
|
|
230
247
|
class GetResource < Resource
|
231
|
-
|
232
|
-
def make_request(path, params)
|
233
|
-
get path, params
|
234
|
-
end
|
235
|
-
|
236
248
|
def initialize(runner, path, &block)
|
237
249
|
super runner, path, &block
|
238
250
|
@method = 'GET'
|
@@ -240,11 +252,6 @@ module ApiDoc
|
|
240
252
|
end
|
241
253
|
|
242
254
|
class PutResource < Resource
|
243
|
-
|
244
|
-
def make_request(path, params)
|
245
|
-
put path, params
|
246
|
-
end
|
247
|
-
|
248
255
|
def initialize(runner, path, &block)
|
249
256
|
super runner, path, &block
|
250
257
|
@method = 'PUT'
|
@@ -252,11 +259,6 @@ module ApiDoc
|
|
252
259
|
end
|
253
260
|
|
254
261
|
class DeleteResource < Resource
|
255
|
-
|
256
|
-
def make_request(path, params)
|
257
|
-
delete path, params
|
258
|
-
end
|
259
|
-
|
260
262
|
def initialize(runner, path, &block)
|
261
263
|
super runner, path, &block
|
262
264
|
@method = 'DELETE'
|
@@ -264,11 +266,6 @@ module ApiDoc
|
|
264
266
|
end
|
265
267
|
|
266
268
|
class OptionsResource < Resource
|
267
|
-
|
268
|
-
def make_request(path, params)
|
269
|
-
options path, params
|
270
|
-
end
|
271
|
-
|
272
269
|
def initialize(runner, path, &block)
|
273
270
|
super runner, path, &block
|
274
271
|
@method = 'OPTIONS'
|