dictum 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/.travis.yml +0 -1
- data/README.md +28 -37
- data/dictum.gemspec +2 -2
- data/example.css +84 -0
- data/example.gif +0 -0
- data/example.md +42 -0
- data/lib/dictum.rb +19 -4
- data/lib/dictum/documenter.rb +17 -10
- data/lib/dictum/html_helpers.rb +40 -29
- data/lib/dictum/html_writer.rb +19 -13
- data/lib/dictum/markdown_writer.rb +7 -5
- data/lib/dictum/version.rb +1 -1
- data/lib/tasks/default_configuration +19 -0
- data/lib/tasks/default_initializer +6 -0
- data/lib/tasks/dictum.rake +21 -0
- metadata +14 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1abfdfd254c6440dd20d29a1f76339d413512ee5
|
4
|
+
data.tar.gz: 01f93d8ee750b724a6c93e4a9beabab729cadfbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43e9db9a4c534ffb44e4a648fff63f44a5c38565e716708dc2beff30d8cd6b31046f487f8769ccf1ebd89d74aff15145e4b51b861f5ad9847a001955c784b621
|
7
|
+
data.tar.gz: 96012528a2372d4bc8879367c4f64462e2209b6e9138f6ee7f5d40969910a1706e269a3e39a1d6973cdee088b6c2b4ab9c8d9c206473cb7066b6ae9af21fe591
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -25,7 +25,11 @@ Or install it yourself as:
|
|
25
25
|
|
26
26
|
## Basic usage
|
27
27
|
|
28
|
-
First
|
28
|
+
First run:
|
29
|
+
|
30
|
+
$ bundle exec rake dictum:configure [PATH_TO_HELPER_FILE]
|
31
|
+
|
32
|
+
This will create a basic Rspec configuration in 'spec/support/spec_helper.rb' or in PATH_TO_HELPER_FILE. Also it will create a configuration file inside /config/initializers/dictum.rb
|
29
33
|
|
30
34
|
```ruby
|
31
35
|
# /config/initializers/dictum.rb
|
@@ -34,6 +38,7 @@ Dictum.configure do |config|
|
|
34
38
|
config.root_path = Rails.root
|
35
39
|
config.output_filename = 'Documentation'
|
36
40
|
config.output_format = :markdown
|
41
|
+
config.index_title = 'My Documentation Title'
|
37
42
|
end
|
38
43
|
```
|
39
44
|
|
@@ -78,9 +83,9 @@ Then execute:
|
|
78
83
|
|
79
84
|
$ bundle exec rake dictum:document
|
80
85
|
|
81
|
-
And voilà, Dictum will create a document like this in '/docs/Documentation':
|
86
|
+
And voilà, Dictum will create a document like this in '/docs/Documentation' (see [example.md](https://github.com/Wolox/dictum/blob/master/example.md)):
|
82
87
|
|
83
|
-
#
|
88
|
+
# My Documentation Title
|
84
89
|
- MyResource
|
85
90
|
|
86
91
|
# MyResource
|
@@ -125,20 +130,14 @@ And voilà, Dictum will create a document like this in '/docs/Documentation':
|
|
125
130
|
|
126
131
|
# Advanced usage
|
127
132
|
|
128
|
-
If you pay attention to the basic usage, you will notice that
|
133
|
+
If you pay attention to the basic usage, you will notice that it is a lot of boilerplate if your API has a lot of endpoints, this is not DRY. Luckily you can work around it using some Rspec tricks:
|
129
134
|
|
130
135
|
```ruby
|
131
|
-
# spec/
|
132
|
-
|
133
|
-
|
134
|
-
describe V1::MyResourceController do
|
135
|
-
Dictum.resource(
|
136
|
-
name: 'MyResource',
|
137
|
-
description: 'This is MyResource description.'
|
138
|
-
)
|
139
|
-
|
140
|
-
after(:each) do |test|
|
136
|
+
# spec/rails_helper.rb
|
137
|
+
RSpec.configure do |config|
|
138
|
+
config.after(:each) do |test|
|
141
139
|
if test.metadata[:dictum]
|
140
|
+
Dictum.endpoint(
|
142
141
|
Dictum.endpoint(
|
143
142
|
resource: test.metadata[:described_class].to_s.gsub('V1::', '').gsub('Controller', ''),
|
144
143
|
endpoint: request.fullpath,
|
@@ -152,35 +151,14 @@ describe V1::MyResourceController do
|
|
152
151
|
response_headers: response.headers,
|
153
152
|
response_status: response.status,
|
154
153
|
response_body: response_body
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
describe '#some_method' do
|
159
|
-
context 'some context for my resource' do
|
160
|
-
it 'returns status ok', dictum: true, dictum_description: 'Some description of the endpoint.' do
|
161
|
-
get :index
|
162
|
-
expect(response_status).to eq(200)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
```
|
168
|
-
|
169
|
-
This is much better, but it is not DRYed enough because you would have to repeat the after(:each) declaration on every controller spec you have, so you can still improve it a bit more:
|
170
|
-
|
171
|
-
```ruby
|
172
|
-
# spec/rails_helper.rb
|
173
|
-
RSpec.configure do |config|
|
174
|
-
config.after(:each) do |test|
|
175
|
-
if test.metadata[:dictum]
|
176
|
-
Dictum.endpoint(
|
177
|
-
# All the parameters that you want
|
178
154
|
)
|
179
155
|
end
|
180
156
|
end
|
181
157
|
end
|
182
158
|
```
|
183
159
|
|
160
|
+
A file similar (and more complete) to that one is created when you run the rake dictum:configure task.
|
161
|
+
|
184
162
|
```ruby
|
185
163
|
# spec/controllers/my_resource_controller_spec.rb
|
186
164
|
require 'rails_helper'
|
@@ -202,6 +180,8 @@ describe V1::MyResourceController do
|
|
202
180
|
end
|
203
181
|
```
|
204
182
|
|
183
|
+
This is how your controller test should look now, much better.
|
184
|
+
|
205
185
|
# Dynamic HTML documentation
|
206
186
|
|
207
187
|
So far so good, but your team needs to read the documentation everytime you update it, and sending the documentation file to them doesn't seem too practical. Instead you can use the HTML version of Dictum and generate static views with the content. Here is a very basic example of what you can do to generate the views and routes dynamycally:
|
@@ -213,6 +193,9 @@ Dictum.configure do |config|
|
|
213
193
|
config.root_path = Rails.root
|
214
194
|
config.output_filename = 'docs'
|
215
195
|
config.output_format = :html
|
196
|
+
config.index_title = 'My documentation title'
|
197
|
+
config.header_title = 'API doc'
|
198
|
+
config.inline_css = File.read(Rails.root.join('app', 'assets', 'stylesheets', 'documentation.css'))
|
216
199
|
end
|
217
200
|
```
|
218
201
|
|
@@ -234,6 +217,14 @@ end
|
|
234
217
|
|
235
218
|
Of course you will need to have a controller for this, in this case one named 'docs_controller.rb'. And finally go to 'http://localhost:3000/docs/index.html'
|
236
219
|
|
220
|
+
This is an HTML example:
|
221
|
+
|
222
|
+
<p align="center">
|
223
|
+
<img src="https://raw.githubusercontent.com/Wolox/dictum/master/example.gif">
|
224
|
+
</p>
|
225
|
+
|
226
|
+
You can customize the HTML using css like this [example](https://raw.githubusercontent.com/Wolox/dictum/master/example.css).
|
227
|
+
|
237
228
|
## Contributing
|
238
229
|
|
239
230
|
1. Fork it
|
data/dictum.gemspec
CHANGED
@@ -19,10 +19,10 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
20
|
spec.test_files = spec.files.grep(%r{^(test|spec)/})
|
21
21
|
|
22
|
-
spec.add_dependency '
|
22
|
+
spec.add_dependency 'nokogiri', '~> 1.6'
|
23
23
|
|
24
24
|
spec.add_development_dependency 'bundler', '>= 1.3.0', '< 2.0'
|
25
25
|
spec.add_development_dependency 'rspec', '~> 3.4', '>= 3.4.0'
|
26
26
|
spec.add_development_dependency 'byebug', '~> 8.0', '>= 8.0.0' if RUBY_VERSION >= '2.0.0'
|
27
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
27
|
+
spec.add_development_dependency 'rubocop', '~> 0.40', '>= 0.40.0'
|
28
28
|
end
|
data/example.css
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
body {
|
2
|
+
background-color: white;
|
3
|
+
}
|
4
|
+
|
5
|
+
ul {
|
6
|
+
list-style-type: disc;
|
7
|
+
}
|
8
|
+
|
9
|
+
a {
|
10
|
+
color: blue;
|
11
|
+
font-family: sans-serif;
|
12
|
+
font-weight: bold;
|
13
|
+
}
|
14
|
+
|
15
|
+
.jumbotron {
|
16
|
+
background-color: grey;
|
17
|
+
}
|
18
|
+
|
19
|
+
pre {
|
20
|
+
background-color: grey;
|
21
|
+
}
|
22
|
+
|
23
|
+
.jumbotron > h1{
|
24
|
+
color: black;
|
25
|
+
font-family: sans-serif;
|
26
|
+
font-weight: bold;
|
27
|
+
text-transform: uppercase;
|
28
|
+
font-size: 50px;
|
29
|
+
}
|
30
|
+
|
31
|
+
h1 {
|
32
|
+
color: black;
|
33
|
+
font-family: sans-serif;
|
34
|
+
font-weight: bold;
|
35
|
+
text-transform: uppercase;
|
36
|
+
font-size: 40px;
|
37
|
+
}
|
38
|
+
|
39
|
+
p {
|
40
|
+
color: black;
|
41
|
+
font-family: sans-serif;
|
42
|
+
}
|
43
|
+
|
44
|
+
h3 {
|
45
|
+
color: black;
|
46
|
+
font-family: sans-serif;
|
47
|
+
font-weight: bold;
|
48
|
+
font-size: 30px;
|
49
|
+
}
|
50
|
+
|
51
|
+
h4 {
|
52
|
+
color: grey;
|
53
|
+
font-family: sans-serif;
|
54
|
+
font-weight: bold;
|
55
|
+
text-transform: uppercase;
|
56
|
+
font-size: 20px;
|
57
|
+
}
|
58
|
+
|
59
|
+
.dictum-button {
|
60
|
+
background-color: white;
|
61
|
+
border-color: black;
|
62
|
+
color: black;
|
63
|
+
margin-right: 10px;
|
64
|
+
}
|
65
|
+
|
66
|
+
.dictum-button > p {
|
67
|
+
font-family: sans-serif;
|
68
|
+
text-transform: uppercase;
|
69
|
+
display: inline;
|
70
|
+
}
|
71
|
+
|
72
|
+
.dictum-button:hover {
|
73
|
+
background-color: transparent;
|
74
|
+
border-color: blue;
|
75
|
+
color: blue;
|
76
|
+
}
|
77
|
+
|
78
|
+
span.lit, span.kwd {
|
79
|
+
color: green;
|
80
|
+
}
|
81
|
+
|
82
|
+
span.pun, span.str {
|
83
|
+
color: black;
|
84
|
+
}
|
data/example.gif
ADDED
Binary file
|
data/example.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Index
|
2
|
+
- MyResource
|
3
|
+
|
4
|
+
# MyResource
|
5
|
+
This is MyResource description.
|
6
|
+
|
7
|
+
## POST /api/v1/my_resource
|
8
|
+
|
9
|
+
### Description:
|
10
|
+
Some description of the endpoint.
|
11
|
+
|
12
|
+
### Request headers:
|
13
|
+
```json
|
14
|
+
{
|
15
|
+
"AUTHORIZATION" : "user_token",
|
16
|
+
"Content-Type" : "application/json",
|
17
|
+
"Accept" : "application/json"
|
18
|
+
}
|
19
|
+
```
|
20
|
+
|
21
|
+
### Path parameters:
|
22
|
+
```json
|
23
|
+
{ "id": 1, "page": 1 }
|
24
|
+
```
|
25
|
+
|
26
|
+
### Body parameters:
|
27
|
+
```json
|
28
|
+
{ "some": "parameter" }
|
29
|
+
```
|
30
|
+
|
31
|
+
### Response headers:
|
32
|
+
```json
|
33
|
+
{ "some_header": "some_header_value" }
|
34
|
+
```
|
35
|
+
|
36
|
+
### Response status:
|
37
|
+
200
|
38
|
+
|
39
|
+
### Response body:
|
40
|
+
```json
|
41
|
+
"no_content"
|
42
|
+
```
|
data/lib/dictum.rb
CHANGED
@@ -13,7 +13,10 @@ module Dictum
|
|
13
13
|
output_path: "#{Dir.tmpdir}/docs",
|
14
14
|
root_path: Dir.tmpdir,
|
15
15
|
test_suite: :rspec,
|
16
|
-
output_filename: 'Documentation'
|
16
|
+
output_filename: 'Documentation',
|
17
|
+
index_title: 'Index',
|
18
|
+
header_title: 'Dictum',
|
19
|
+
inline_css: nil
|
17
20
|
}
|
18
21
|
|
19
22
|
def self.configure
|
@@ -40,6 +43,18 @@ module Dictum
|
|
40
43
|
@config[:output_filename] = file
|
41
44
|
end
|
42
45
|
|
46
|
+
def self.index_title=(title)
|
47
|
+
@config[:index_title] = title
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.header_title=(title)
|
51
|
+
@config[:header_title] = title
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.inline_css=(style)
|
55
|
+
@config[:inline_css] = style
|
56
|
+
end
|
57
|
+
|
43
58
|
def self.config
|
44
59
|
@config
|
45
60
|
end
|
@@ -63,7 +78,7 @@ module Dictum
|
|
63
78
|
#
|
64
79
|
def self.document
|
65
80
|
Dir.mkdir(@config[:output_path]) unless Dir.exist?(@config[:output_path])
|
66
|
-
Documenter.instance.
|
81
|
+
Documenter.instance.reset_data
|
67
82
|
|
68
83
|
system "bundle exec rspec #{@config[:root_path]}" if @config[:test_suite] == :rspec
|
69
84
|
|
@@ -77,9 +92,9 @@ module Dictum
|
|
77
92
|
|
78
93
|
case @config[:output_format]
|
79
94
|
when :markdown
|
80
|
-
writer = MarkdownWriter.new(output_filename, tempfile_path)
|
95
|
+
writer = MarkdownWriter.new(output_filename, tempfile_path, @config)
|
81
96
|
when :html
|
82
|
-
writer = HtmlWriter.new(output_filename, tempfile_path,
|
97
|
+
writer = HtmlWriter.new(output_filename, tempfile_path, @config)
|
83
98
|
end
|
84
99
|
|
85
100
|
writer.write
|
data/lib/dictum/documenter.rb
CHANGED
@@ -8,21 +8,22 @@ module Dictum
|
|
8
8
|
class Documenter
|
9
9
|
include Singleton
|
10
10
|
|
11
|
-
attr_reader :
|
11
|
+
attr_reader :data, :tempfile_path
|
12
12
|
TEMPFILE_NAME = 'dictum_temp.json'.freeze
|
13
13
|
|
14
14
|
def initialize
|
15
|
-
|
15
|
+
reset_data
|
16
16
|
@tempfile_path = "#{Dir.tmpdir}/#{TEMPFILE_NAME}"
|
17
17
|
end
|
18
18
|
|
19
19
|
def resource(arguments = {})
|
20
20
|
return if arguments.nil?
|
21
21
|
name = arguments[:name]
|
22
|
+
description = arguments[:description]
|
22
23
|
return if name.nil?
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
resources[name] ||= {}
|
25
|
+
resources[name][:description] = description if description
|
26
|
+
resources[name][:endpoints] ||= []
|
26
27
|
update_temp
|
27
28
|
end
|
28
29
|
|
@@ -30,21 +31,27 @@ module Dictum
|
|
30
31
|
resource = arguments[:resource]
|
31
32
|
endpoint = arguments[:endpoint]
|
32
33
|
return if resource.nil? || endpoint.nil?
|
33
|
-
resource(name:
|
34
|
-
|
34
|
+
resource(name: resource) unless resources.key? resource
|
35
|
+
resources[resource][:endpoints] << arguments_hash(arguments)
|
35
36
|
update_temp
|
36
37
|
end
|
37
38
|
|
38
|
-
def
|
39
|
-
@
|
39
|
+
def reset_data
|
40
|
+
@data = {
|
41
|
+
resources: {}
|
42
|
+
}
|
40
43
|
end
|
41
44
|
|
42
45
|
private
|
43
46
|
|
47
|
+
def resources
|
48
|
+
@data[:resources]
|
49
|
+
end
|
50
|
+
|
44
51
|
def update_temp
|
45
52
|
File.delete(tempfile_path) if File.exist?(tempfile_path)
|
46
53
|
file = File.open(tempfile_path, 'w+')
|
47
|
-
file.write(JSON.generate(@
|
54
|
+
file.write(JSON.generate(@data))
|
48
55
|
file.close
|
49
56
|
end
|
50
57
|
|
data/lib/dictum/html_helpers.rb
CHANGED
@@ -10,23 +10,19 @@ module Dictum
|
|
10
10
|
yield self
|
11
11
|
end
|
12
12
|
|
13
|
-
def html_header(title, body_content)
|
14
|
-
"<!DOCTYPE html
|
15
|
-
"
|
16
|
-
"#{script(JQUERY)}
|
13
|
+
def html_header(title, body_content, inline_css = nil)
|
14
|
+
"<!DOCTYPE html><html><head><title>#{title}</title>#{external_css(BOOTSTRAP_CSS)}"\
|
15
|
+
"#{inline_css(inline_css)}</head><body>#{body_content}" \
|
16
|
+
"#{script(JQUERY)}#{script(BOOTSTRAP_JS)}#{script(PRETTIFY)}</body></html>"
|
17
17
|
end
|
18
18
|
|
19
19
|
def container(content)
|
20
|
-
tag('div',
|
20
|
+
tag('div', content.to_s, class: 'container-fluid')
|
21
21
|
end
|
22
22
|
|
23
23
|
def row(content)
|
24
|
-
internal_div = tag('div',
|
25
|
-
tag('div',
|
26
|
-
end
|
27
|
-
|
28
|
-
def page_css
|
29
|
-
''
|
24
|
+
internal_div = tag('div', content.to_s, class: 'col-md-8 col-md-offset-2')
|
25
|
+
tag('div', internal_div.to_s, class: 'row')
|
30
26
|
end
|
31
27
|
|
32
28
|
def script(script_path)
|
@@ -36,48 +32,59 @@ module Dictum
|
|
36
32
|
|
37
33
|
def external_css(css_path)
|
38
34
|
return '' unless css_path
|
39
|
-
"<link rel='stylesheet' href='#{css_path}'
|
35
|
+
"<link rel='stylesheet' href='#{css_path}' />"
|
36
|
+
end
|
37
|
+
|
38
|
+
def inline_css(style)
|
39
|
+
return '' unless style
|
40
|
+
"<style>#{style}</style>"
|
40
41
|
end
|
41
42
|
|
42
43
|
def unordered_list(elements)
|
43
|
-
return
|
44
|
-
answer =
|
44
|
+
return '<ul></ul>' unless elements
|
45
|
+
answer = '<ul>'
|
45
46
|
elements.each do |element|
|
46
|
-
answer += "
|
47
|
+
answer += list_item(link("#{element.downcase}.html", element))
|
47
48
|
end
|
48
|
-
answer +=
|
49
|
+
answer += '</ul>'
|
50
|
+
end
|
51
|
+
|
52
|
+
def list_item(content)
|
53
|
+
tag('li', content)
|
49
54
|
end
|
50
55
|
|
51
56
|
def link(href, content)
|
52
|
-
tag('a', content, href: href)
|
57
|
+
tag('a', content, href: './' + href)
|
53
58
|
end
|
54
59
|
|
55
60
|
def title(text, html_class = nil)
|
56
|
-
return "<h1>#{text}</h1
|
61
|
+
return "<h1>#{text}</h1>" unless html_class
|
57
62
|
tag('h1', text, class: html_class)
|
58
63
|
end
|
59
64
|
|
60
65
|
def subtitle(text, html_class = nil)
|
61
|
-
return "<h3>#{text}</h3
|
66
|
+
return "<h3>#{text}</h3>" unless html_class
|
62
67
|
tag('h3', text, class: html_class)
|
63
68
|
end
|
64
69
|
|
65
70
|
def sub_subtitle(text, html_class = nil)
|
66
|
-
return "<h4>#{text}</h4
|
71
|
+
return "<h4>#{text}</h4>" unless html_class
|
67
72
|
tag('h4', text, class: html_class)
|
68
73
|
end
|
69
74
|
|
70
75
|
def paragraph(text, html_class = nil)
|
71
|
-
return "<p>#{text}</p
|
76
|
+
return "<p>#{text}</p>" unless html_class
|
72
77
|
tag('p', text, class: html_class)
|
73
78
|
end
|
74
79
|
|
75
|
-
def button(text, glyphicon =
|
76
|
-
span = tag('span',
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
80
|
+
def button(text, glyphicon = 'glyphicon-menu-left')
|
81
|
+
span = tag('span', nil, class: "glyphicon #{glyphicon}", 'aria-hidden' => 'true')
|
82
|
+
paragraph = paragraph(text)
|
83
|
+
button_content = span.to_s + paragraph.to_s
|
84
|
+
button = tag('button', button_content, 'type' => 'button',
|
85
|
+
'class' => 'btn btn-primary back dictum-button',
|
86
|
+
'aria-label' => 'Left Align')
|
87
|
+
tag('a', button.to_s, href: 'index.html')
|
81
88
|
end
|
82
89
|
|
83
90
|
def code_block(title, json)
|
@@ -91,14 +98,18 @@ module Dictum
|
|
91
98
|
tag('pre', json, class: 'prettyprint')
|
92
99
|
end
|
93
100
|
|
101
|
+
def jumbotron(content)
|
102
|
+
return '' unless content
|
103
|
+
tag('div', content, class: 'jumbotron')
|
104
|
+
end
|
105
|
+
|
94
106
|
def tag(name, content, attributes = {})
|
95
107
|
return '' unless name
|
96
108
|
answer = "<#{name}"
|
97
109
|
attributes.each do |key, value|
|
98
110
|
answer += " #{key}='#{value}'"
|
99
111
|
end
|
100
|
-
answer += ">#{content}"
|
101
|
-
answer += "</#{name}>\n"
|
112
|
+
answer += ">#{content}</#{name}>"
|
102
113
|
end
|
103
114
|
end
|
104
115
|
end
|
data/lib/dictum/html_writer.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
require_relative 'html_helpers'
|
2
2
|
require 'json'
|
3
|
-
require '
|
3
|
+
require 'nokogiri'
|
4
4
|
|
5
5
|
module Dictum
|
6
6
|
class HtmlWriter
|
7
|
-
attr_reader :temp_path, :temp_json, :output_dir, :output_file, :
|
7
|
+
attr_reader :temp_path, :temp_json, :output_dir, :output_file, :header_title
|
8
8
|
|
9
|
-
def initialize(output_dir, temp_path,
|
9
|
+
def initialize(output_dir, temp_path, config)
|
10
10
|
@output_dir = output_dir
|
11
11
|
@temp_path = temp_path
|
12
12
|
@temp_json = JSON.parse(File.read(temp_path))
|
13
|
-
@
|
13
|
+
@config = config
|
14
|
+
@header_title = config[:header_title]
|
14
15
|
end
|
15
16
|
|
16
17
|
def write
|
@@ -23,33 +24,37 @@ module Dictum
|
|
23
24
|
|
24
25
|
def write_to_file(file_path, content)
|
25
26
|
index = File.open(file_path, 'w+')
|
26
|
-
index.puts(
|
27
|
+
index.puts(Nokogiri::HTML(content).to_html)
|
27
28
|
index.close
|
28
29
|
end
|
29
30
|
|
30
31
|
def write_index
|
31
32
|
html = HtmlHelpers.build do |b|
|
32
|
-
content =
|
33
|
-
content += b.unordered_list(
|
33
|
+
content = b.jumbotron(b.title(@config[:index_title], 'title'))
|
34
|
+
content += b.unordered_list(resources.keys)
|
34
35
|
container = b.container(b.row(content))
|
35
|
-
b.html_header(
|
36
|
+
b.html_header(header_title, container, @config[:inline_css])
|
36
37
|
end
|
37
38
|
write_to_file("#{output_dir}/index.html", html)
|
38
39
|
end
|
39
40
|
|
40
41
|
def write_pages
|
41
|
-
|
42
|
+
resources.each do |resource_name, information|
|
42
43
|
write_page(resource_name, information)
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
47
|
+
def resources
|
48
|
+
temp_json['resources']
|
49
|
+
end
|
50
|
+
|
46
51
|
def write_page(resource_name, information)
|
47
52
|
html = HtmlHelpers.build do |b|
|
48
53
|
content = resource_header_and_endpoints(
|
49
54
|
resource_name, information['description'], information['endpoints'], b
|
50
55
|
)
|
51
|
-
container = b.container(b.row(content) + b.row(b.button('Back'
|
52
|
-
b.html_header(
|
56
|
+
container = b.container(b.row(content) + b.row(b.button('Back')))
|
57
|
+
b.html_header(header_title, container, @config[:inline_css])
|
53
58
|
end
|
54
59
|
write_to_file("#{output_dir}/#{resource_name.downcase}.html", html)
|
55
60
|
end
|
@@ -83,7 +88,7 @@ module Dictum
|
|
83
88
|
) if endpoint['response_headers']
|
84
89
|
|
85
90
|
if endpoint['response_body']
|
86
|
-
param =
|
91
|
+
param = endpoint['response_body'] == 'no_content' ? {} : endpoint['response_body']
|
87
92
|
answer += write_codeblock('Response body', param, builder)
|
88
93
|
end
|
89
94
|
answer
|
@@ -91,7 +96,8 @@ module Dictum
|
|
91
96
|
|
92
97
|
def write_codeblock(text, json, builder)
|
93
98
|
return unless text && json && builder
|
94
|
-
|
99
|
+
sanitized_json = json.empty? ? {} : json
|
100
|
+
builder.code_block(text, JSON.pretty_generate(sanitized_json))
|
95
101
|
end
|
96
102
|
end
|
97
103
|
end
|
@@ -4,11 +4,12 @@ module Dictum
|
|
4
4
|
class MarkdownWriter
|
5
5
|
attr_reader :temp_path, :temp_json, :output_path, :output_file
|
6
6
|
|
7
|
-
def initialize(output_path, temp_path)
|
7
|
+
def initialize(output_path, temp_path, config)
|
8
8
|
@output_path = "#{output_path}.md"
|
9
9
|
File.delete(output_path) if File.exist?(output_path)
|
10
10
|
@temp_path = temp_path
|
11
11
|
@temp_json = JSON.parse(File.read(temp_path))
|
12
|
+
@config = config
|
12
13
|
end
|
13
14
|
|
14
15
|
def write
|
@@ -21,15 +22,15 @@ module Dictum
|
|
21
22
|
private
|
22
23
|
|
23
24
|
def write_index
|
24
|
-
output_file.puts
|
25
|
-
@temp_json.each do |resource_name, _information|
|
25
|
+
output_file.puts "# #{@config[:index_title]}"
|
26
|
+
@temp_json['resources'].each do |resource_name, _information|
|
26
27
|
output_file.puts "- #{resource_name}"
|
27
28
|
end
|
28
29
|
output_file.puts "\n"
|
29
30
|
end
|
30
31
|
|
31
32
|
def write_temp_path
|
32
|
-
@temp_json.each do |resource_name, information|
|
33
|
+
@temp_json['resources'].each do |resource_name, information|
|
33
34
|
output_file.puts "# #{resource_name}"
|
34
35
|
output_file.puts "#{information['description']}\n\n"
|
35
36
|
write_endpoints(information['endpoints'])
|
@@ -65,8 +66,9 @@ module Dictum
|
|
65
66
|
|
66
67
|
def print_subsubtitle_json(subtitle, contents)
|
67
68
|
return unless subtitle && contents
|
69
|
+
sanitized_contents = contents.empty? ? {} : contents
|
68
70
|
output_file.puts "\#\#\# #{subtitle}:"
|
69
|
-
output_file.puts "```json\n#{JSON.pretty_generate(
|
71
|
+
output_file.puts "```json\n#{JSON.pretty_generate(sanitized_contents)}\n```\n\n"
|
70
72
|
end
|
71
73
|
end
|
72
74
|
end
|
data/lib/dictum/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
RSpec.configure do |config|
|
3
|
+
config.after(:each) do |test|
|
4
|
+
if test.metadata[:dictum]
|
5
|
+
Dictum.endpoint(
|
6
|
+
resource: test.metadata[:described_class].to_s.gsub('V1::', '').gsub('Controller', ''),
|
7
|
+
endpoint: request.fullpath,
|
8
|
+
http_verb: request.env['REQUEST_METHOD'],
|
9
|
+
description: test.metadata[:dictum_description],
|
10
|
+
request_headers: test.metadata[:dictum_no_auth] ? DEFAULT_REQUEST_HEADERS.except('AUTHORIZATION') : DEFAULT_REQUEST_HEADERS,
|
11
|
+
request_path_parameters: request.env['action_dispatch.request.path_parameters'].except(:controller, :action),
|
12
|
+
request_body_parameters: request.env['action_dispatch.request.parameters'].except('controller', 'action'),
|
13
|
+
response_headers: response.headers['Location'] ? { 'Location' => response.headers['Location'] } : nil,
|
14
|
+
response_status: response.status,
|
15
|
+
response_body: response_body
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/tasks/dictum.rake
CHANGED
@@ -1,8 +1,29 @@
|
|
1
1
|
require 'rake'
|
2
2
|
|
3
3
|
namespace :dictum do
|
4
|
+
GEM_DIR = Gem::Specification.find_by_name('dictum').gem_dir
|
5
|
+
DEFAULT_CONFIG_PATH = GEM_DIR + '/lib/tasks/default_configuration'
|
6
|
+
DEFAULT_INITIALIZER = GEM_DIR + '/lib/tasks/default_initializer'
|
7
|
+
|
4
8
|
desc 'Starts the documenting process'
|
5
9
|
task document: :environment do
|
6
10
|
system 'bundle exec rails runner -e test Dictum.document'
|
7
11
|
end
|
12
|
+
|
13
|
+
desc 'Installs the basic configuration in the file specified or in spec/support/spec_helper.rb'
|
14
|
+
task configure: :environment do
|
15
|
+
configuration_file_path = ARGV[1] || 'spec/support/spec_helper.rb'
|
16
|
+
initializer_file_path = Rails.root.join('config', 'initializers', 'dictum.rb')
|
17
|
+
|
18
|
+
default_config = File.read(DEFAULT_CONFIG_PATH)
|
19
|
+
default_initializer = File.read(DEFAULT_INITIALIZER)
|
20
|
+
|
21
|
+
File.open(configuration_file_path, 'a+') do |file|
|
22
|
+
file.puts(default_config)
|
23
|
+
end
|
24
|
+
|
25
|
+
File.open(initializer_file_path, 'a+') do |file|
|
26
|
+
file.puts(default_initializer)
|
27
|
+
end
|
28
|
+
end
|
8
29
|
end
|
metadata
CHANGED
@@ -1,35 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dictum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alejandro Bezdjian
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: nokogiri
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 1.1.1
|
19
|
+
version: '1.6'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: '1.
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 1.1.1
|
26
|
+
version: '1.6'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: bundler
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -96,20 +90,20 @@ dependencies:
|
|
96
90
|
requirements:
|
97
91
|
- - "~>"
|
98
92
|
- !ruby/object:Gem::Version
|
99
|
-
version: '0.
|
93
|
+
version: '0.40'
|
100
94
|
- - ">="
|
101
95
|
- !ruby/object:Gem::Version
|
102
|
-
version: 0.
|
96
|
+
version: 0.40.0
|
103
97
|
type: :development
|
104
98
|
prerelease: false
|
105
99
|
version_requirements: !ruby/object:Gem::Requirement
|
106
100
|
requirements:
|
107
101
|
- - "~>"
|
108
102
|
- !ruby/object:Gem::Version
|
109
|
-
version: '0.
|
103
|
+
version: '0.40'
|
110
104
|
- - ">="
|
111
105
|
- !ruby/object:Gem::Version
|
112
|
-
version: 0.
|
106
|
+
version: 0.40.0
|
113
107
|
description: Create automatic documentation of your API endpoints through your tests.
|
114
108
|
email: alebezdjian@gmail.com
|
115
109
|
executables: []
|
@@ -126,12 +120,17 @@ files:
|
|
126
120
|
- Rakefile
|
127
121
|
- TODO.md
|
128
122
|
- dictum.gemspec
|
123
|
+
- example.css
|
124
|
+
- example.gif
|
125
|
+
- example.md
|
129
126
|
- lib/dictum.rb
|
130
127
|
- lib/dictum/documenter.rb
|
131
128
|
- lib/dictum/html_helpers.rb
|
132
129
|
- lib/dictum/html_writer.rb
|
133
130
|
- lib/dictum/markdown_writer.rb
|
134
131
|
- lib/dictum/version.rb
|
132
|
+
- lib/tasks/default_configuration
|
133
|
+
- lib/tasks/default_initializer
|
135
134
|
- lib/tasks/dictum.rake
|
136
135
|
homepage: https://github.com/Wolox/dictum
|
137
136
|
licenses:
|
@@ -158,4 +157,3 @@ signing_key:
|
|
158
157
|
specification_version: 4
|
159
158
|
summary: Document your APIs.
|
160
159
|
test_files: []
|
161
|
-
has_rdoc:
|