fdoc 0.2.1 → 0.2.2

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.
data/README.md CHANGED
@@ -18,26 +18,32 @@ Add fdoc to your Gemfile.
18
18
 
19
19
  gem 'fdoc'
20
20
 
21
- Tell fdoc where to look for .fdoc files. By default, fdoc will look in `docs/fdoc`, but you can change this behavior to look anywhere. This fits best in something like a spec\_helper file.
21
+ Tell fdoc where to look for `.fdoc` files. By default, fdoc will look in `docs/fdoc`, but you can change this behavior to look anywhere. This fits best in something like a spec\_helper file.
22
22
 
23
- require 'fdoc'
23
+ ```ruby
24
+ require 'fdoc'
24
25
 
25
- Fdoc.service_path = "path/to/your/fdocs"
26
+ Fdoc.service_path = "path/to/your/fdocs"
27
+ ```
26
28
 
27
29
  fdoc is built to work around controller specs in rspec, and provides `Fdoc::SpecWatcher` as a mixin. Make sure to include it *inside* your top level describe.
28
30
 
29
- require 'fdoc/spec_watcher'
31
+ ```ruby
32
+ require 'fdoc/spec_watcher'
30
33
 
31
- describe MembersController do
32
- include Fdoc::SpecWatcher
33
- ...
34
- end
34
+ describe MembersController do
35
+ include Fdoc::SpecWatcher
36
+ # ...
37
+ end
38
+ ```
35
39
 
36
40
  To enable fdoc for an endpoint, add the `fdoc` option with the path to the endpoint. fdoc will intercept all calls to `get`, `post`, `put`, and `delete` and verify those parameters accordingly.
37
41
 
38
- context "#show", :fdoc => 'members/list' do
39
- ..
40
- end
42
+ ```ruby
43
+ context "#show", :fdoc => 'members/list' do
44
+ # ...
45
+ end
46
+ ```
41
47
 
42
48
  fdoc also has a scaffolding mode, where it attemps to infer the schema of a request based on sample responses. The interface is exactly the same as verifying, just set the environment variable `FDOC_SCAFFOLD=true`.
43
49
 
@@ -51,7 +57,7 @@ fdoc provides the `fdoc_to_html` script to transform a directory of `.fdoc` file
51
57
 
52
58
  In this repo, try running:
53
59
 
54
- bin/fdoc_to_html spec/fixtures html
60
+ bin/fdoc_to_html ./spec/fixtures ./html
55
61
 
56
62
  ## Example
57
63
 
@@ -60,37 +66,90 @@ In this repo, try running:
60
66
  - For more information on fdoc file naming conventions, please see the [fdoc file conventions guide][github_files].
61
67
  - For more information on how fdoc uses JSON schema, please see the [json schema usage document][github_json].
62
68
 
63
- Here is `members/list-POST.fdoc`:
64
-
65
- description: The list of members.
66
- requestParameters:
67
- properties:
68
- limit:
69
- type: integer
70
- required: no
71
- default: 50
72
- description: Limits the number of results returned, used for paging.
73
- responseParameters:
74
- properties:
75
- members:
76
- type: array
77
- items:
78
- title: member
79
- description: Representation of a member
80
- type: object
81
- properties:
82
- name:
83
- description: Member's name
84
- type: string
85
- required: yes
86
- example: Captain Smellypants
87
- responseCodes:
88
- - status: 200 OK
89
- successful: yes
90
- description: A list of current members
91
- - status: 400 Bad Request
92
- successful: no
93
- description: Indicates malformed parameters
69
+ Here is `docs/fdoc/members/list-GET.fdoc`:
70
+
71
+ ```yaml
72
+ description: The list of members.
73
+ requestParameters:
74
+ properties:
75
+ limit:
76
+ type: integer
77
+ required: no
78
+ default: 50
79
+ description: Limits the number of results returned, used for paging.
80
+ responseParameters:
81
+ properties:
82
+ members:
83
+ type: array
84
+ items:
85
+ title: member
86
+ description: Representation of a member
87
+ type: object
88
+ properties:
89
+ name:
90
+ description: Member's name
91
+ type: string
92
+ required: yes
93
+ example: Captain Smellypants
94
+ responseCodes:
95
+ - status: 200 OK
96
+ successful: yes
97
+ description: A list of current members
98
+ - status: 400 Bad Request
99
+ successful: no
100
+ description: Indicates malformed parameters
101
+ ```
102
+
103
+ If we run a test against our members controller with an undocumented parameter, `offset`, we'll get an error.
104
+
105
+ Our spec file, `spec/controllers/members_controller_spec.rb` looks like:
106
+
107
+ ```ruby
108
+ require 'fdoc/spec_watcher'
109
+
110
+ describe MembersController do
111
+ content "#show", :fdoc => "members/list" do
112
+ it "can take an offset" do
113
+ get :show, {
114
+ :offset => 5
115
+ }
116
+ end
117
+ end
118
+ end
119
+ ```
120
+
121
+ We run:
122
+
123
+ bundle exec rspec spec/controllers/members_controller_spec.rb
124
+
125
+ And since `offset` is undocumented, fdoc will fail the test:
126
+
127
+ Failures:
128
+
129
+ 1) MembersController#show can take an offset
130
+ Failure/Error: get :show, { :offset => 5 }
131
+ JSON::Schema::ValidationError:
132
+ The property '#/' contains additional properties ["offset"] outside of the schema when none are allowed in schema 8fcac6c4-294b-56a2-a3de-9342e2e729da#
133
+ # ./spec/controllers/members_controller_spec.rb:5:in `block (3 levels) in <top (required)>'
134
+
135
+ If we run the same spec in scaffold mode, it passes and fdoc will write changes to the correspoding `.fdoc` file:
136
+
137
+ FDOC_SCAFFOLD=true bundle exec spec/controllers/members_controller_spec.rb
138
+
139
+ The diff looks like:
140
+
141
+ ```diff
142
+ diff --git a/docs/fdoc/members/list-GET.fdoc b/docs/fdoc/members/list-GET.fdoc b2e3656..dfa363a 100644
143
+ --- a/docs/fdoc/members/list-GET.fdoc
144
+ +++ b/docs/fdoc/members/list-GET.fdoc
145
+ + offset:
146
+ + description: ???
147
+ + required: ???
148
+ + type: integer
149
+ + example: 5
150
+ ```
151
+
152
+ Notice how it infers a type, and copies an example, but leaves description and required blank. These fields are best left to humans to decide.
94
153
 
95
154
 
96
155
  ## Goals
@@ -55,4 +55,15 @@ class Fdoc::HtmlPresenter
55
55
  html_path
56
56
  end
57
57
  end
58
+
59
+ def tag_with_anchor(tag, content, anchor_slug = nil)
60
+ anchor_slug ||= content.downcase.gsub(' ', '_')
61
+ <<-EOS
62
+ <#{tag} id="#{anchor_slug}">
63
+ <a href="##{anchor_slug}" class="anchor">
64
+ #{content}
65
+ </a>
66
+ </#{tag}>
67
+ EOS
68
+ end
58
69
  end
@@ -61,5 +61,6 @@ class Fdoc::MetaServicePresenter < Fdoc::HtmlPresenter
61
61
  presenter = Fdoc::EndpointPresenter.new(endpoint,
62
62
  options.merge(:prefix => (service_presenter.slug_name + "/")))
63
63
  presenter.service_presenter = service_presenter
64
+ presenter
64
65
  end
65
66
  end
@@ -128,11 +128,19 @@ class Fdoc::SchemaPresenter < Fdoc::HtmlPresenter
128
128
  properties.each do |key, property|
129
129
  next if property.nil?
130
130
  html << '<li>'
131
- html << '<tt>%s</tt>' % key
131
+ html << tag_with_anchor(
132
+ 'span',
133
+ '<tt>%s</tt>' % key,
134
+ schema_slug(key, property)
135
+ )
132
136
  html << self.class.new(property, options.merge(:nested => true)).to_html
133
137
  html << '</li>'
134
138
  end
135
139
 
136
140
  html
137
141
  end
142
+
143
+ def schema_slug(key, property)
144
+ "#{key}-#{property.hash}"
145
+ end
138
146
  end
@@ -28,27 +28,27 @@
28
28
  <%= description %>
29
29
 
30
30
  <% if show_request? %>
31
- <h2>Request</h2>
31
+ <%= tag_with_anchor('h2', 'Request') %>
32
32
 
33
- <h3>Example Request</h3>
33
+ <%= tag_with_anchor('h3', 'Example Request') %>
34
34
  <%= example_request %>
35
35
 
36
- <h3>Request Parameters</h3>
36
+ <%= tag_with_anchor('h3', 'Request Parameters') %>
37
37
  <%= request_parameters %>
38
38
  <% end %>
39
39
 
40
- <h2>Response</h2>
40
+ <%= tag_with_anchor('h2', 'Response') %>
41
41
  <% if show_response? %>
42
- <h3>Example Response</h3>
42
+ <%= tag_with_anchor('h3', 'Example Response') %>
43
43
  <%= example_response %>
44
44
 
45
- <h3>Response Parameters</h3>
45
+ <%= tag_with_anchor('h3', 'Response Parameters') %>
46
46
  <%= response_parameters %>
47
47
  <% end %>
48
48
 
49
- <h3>Response Codes</h3>
49
+ <%= tag_with_anchor('h3', 'Response Codes') %>
50
50
  <% if !successful_response_codes.empty? %>
51
- <h4>Successful Response Codes</h4>
51
+ <%= tag_with_anchor('h4', 'Successful Response Codes') %>
52
52
  <ul>
53
53
  <% successful_response_codes.each do |response_code| %>
54
54
  <li>
@@ -59,7 +59,7 @@
59
59
  <% end %>
60
60
 
61
61
  <% if !successful_response_codes.empty? %>
62
- <h4>Failure Response Codes</h4>
62
+ <%= tag_with_anchor('h4', 'Failure Response Codes') %>
63
63
  <ul>
64
64
  <% failure_response_codes.each do |response_code| %>
65
65
  <li>
@@ -16,9 +16,7 @@
16
16
 
17
17
  <%= description %>
18
18
 
19
- <h2>
20
- Services
21
- </h2>
19
+ <%= tag_with_anchor('h2', 'Services') %>
22
20
 
23
21
  <ul>
24
22
  <% services.each do |serv| %>
@@ -30,14 +28,10 @@
30
28
  <% end %>
31
29
  </ul>
32
30
 
33
- <h2>
34
- Endpoints
35
- </h2>
31
+ <%= tag_with_anchor('h2', 'Endpoints') %>
36
32
 
37
33
  <% endpoints.each do |endpoint_ary| %>
38
- <h3>
39
- <%= endpoint_ary.first.prefix %>
40
- </h3>
34
+ <%= tag_with_anchor('h3', endpoint_ary.first.prefix) %>
41
35
  <ul>
42
36
  <% endpoint_ary.each do |endpoint| %>
43
37
  <li>
@@ -48,9 +42,7 @@
48
42
  <% end %>
49
43
 
50
44
  <% if discussion %>
51
- <h2>
52
- Discussion
53
- </h2>
45
+ <%= tag_with_anchor('h2', 'Discussion') %>
54
46
  <%= discussion %>
55
47
  <% end %>
56
48
  </div>
@@ -24,14 +24,10 @@
24
24
 
25
25
  <%= description %>
26
26
 
27
- <h2>
28
- Endpoints
29
- </h2>
27
+ <%= tag_with_anchor('h2', 'Endpoints') %>
30
28
 
31
29
  <% endpoints.each do |endpoint_ary| %>
32
- <h3>
33
- <%= endpoint_ary.first.prefix %>
34
- </h3>
30
+ <%= tag_with_anchor('h3', endpoint_ary.first.prefix) %>
35
31
  <ul>
36
32
  <% endpoint_ary.each do |endpoint| %>
37
33
  <li>
@@ -42,9 +38,7 @@
42
38
  <% end %>
43
39
 
44
40
  <% if discussion %>
45
- <h2>
46
- Discussion
47
- </h2>
41
+ <%= tag_with_anchor('h2', 'Discussion') %>
48
42
  <%= discussion %>
49
43
  <% end %>
50
44
  </div>
@@ -29,6 +29,18 @@ h1, h2, h3 { font-weight: 200; }
29
29
  a { text-decoration: none; color: #66f; }
30
30
  a:hover, a:active { text-decoration: underline; }
31
31
 
32
+ a.anchor { color: inherit; }
33
+ a.anchor:hover, a.anchor:active { text-decoration: none;}
34
+ a.anchor:hover::before, a.anchor.active::before {
35
+ background: white;
36
+ display: inline-block;
37
+ position: absolute;
38
+ content: '\0261E';
39
+ font-size: 120%;
40
+ font-weight: bold;
41
+ margin-left: -1.2em;
42
+ }
43
+
32
44
  ul {
33
45
  list-style: square;
34
46
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fdoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -15,7 +15,7 @@ date: 2011-11-07 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: json
18
- requirement: &70339438797600 !ruby/object:Gem::Requirement
18
+ requirement: &70290789895620 !ruby/object:Gem::Requirement
19
19
  none: false
20
20
  requirements:
21
21
  - - ! '>='
@@ -23,10 +23,10 @@ dependencies:
23
23
  version: '0'
24
24
  type: :runtime
25
25
  prerelease: false
26
- version_requirements: *70339438797600
26
+ version_requirements: *70290789895620
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: json-schema
29
- requirement: &70339438796920 !ruby/object:Gem::Requirement
29
+ requirement: &70290789911300 !ruby/object:Gem::Requirement
30
30
  none: false
31
31
  requirements:
32
32
  - - ! '>='
@@ -34,10 +34,10 @@ dependencies:
34
34
  version: 1.0.1
35
35
  type: :runtime
36
36
  prerelease: false
37
- version_requirements: *70339438796920
37
+ version_requirements: *70290789911300
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: kramdown
40
- requirement: &70339438796340 !ruby/object:Gem::Requirement
40
+ requirement: &70290789910780 !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
43
  - - ! '>='
@@ -45,10 +45,10 @@ dependencies:
45
45
  version: '0'
46
46
  type: :runtime
47
47
  prerelease: false
48
- version_requirements: *70339438796340
48
+ version_requirements: *70290789910780
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: rake
51
- requirement: &70339438792260 !ruby/object:Gem::Requirement
51
+ requirement: &70290789910100 !ruby/object:Gem::Requirement
52
52
  none: false
53
53
  requirements:
54
54
  - - ! '>='
@@ -56,10 +56,10 @@ dependencies:
56
56
  version: '0'
57
57
  type: :development
58
58
  prerelease: false
59
- version_requirements: *70339438792260
59
+ version_requirements: *70290789910100
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: rspec
62
- requirement: &70339438791760 !ruby/object:Gem::Requirement
62
+ requirement: &70290789909420 !ruby/object:Gem::Requirement
63
63
  none: false
64
64
  requirements:
65
65
  - - ~>
@@ -67,10 +67,10 @@ dependencies:
67
67
  version: '2.5'
68
68
  type: :development
69
69
  prerelease: false
70
- version_requirements: *70339438791760
70
+ version_requirements: *70290789909420
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: nokogiri
73
- requirement: &70339438791300 !ruby/object:Gem::Requirement
73
+ requirement: &70290789908980 !ruby/object:Gem::Requirement
74
74
  none: false
75
75
  requirements:
76
76
  - - ! '>='
@@ -78,10 +78,10 @@ dependencies:
78
78
  version: '0'
79
79
  type: :development
80
80
  prerelease: false
81
- version_requirements: *70339438791300
81
+ version_requirements: *70290789908980
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: cane
84
- requirement: &70339438790760 !ruby/object:Gem::Requirement
84
+ requirement: &70290789908380 !ruby/object:Gem::Requirement
85
85
  none: false
86
86
  requirements:
87
87
  - - ! '>='
@@ -89,7 +89,7 @@ dependencies:
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
- version_requirements: *70339438790760
92
+ version_requirements: *70290789908380
93
93
  description: A tool for documenting API endpoints.
94
94
  email: support@squareup.com
95
95
  executables:
@@ -172,3 +172,4 @@ test_files:
172
172
  - spec/fixtures/members/members.fdoc.service
173
173
  - spec/fixtures/sample_group.fdoc.meta
174
174
  - spec/spec_helper.rb
175
+ has_rdoc: