useless-doc 0.2.3 → 0.3.0

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.
Files changed (47) hide show
  1. data/lib/useless/doc/client.rb +62 -0
  2. data/lib/useless/doc/core/api.rb +6 -2
  3. data/lib/useless/doc/core/domain.rb +34 -0
  4. data/lib/useless/doc/dsl.rb +30 -0
  5. data/lib/useless/doc/rack/{stylesheet.rb → css.rb} +8 -8
  6. data/lib/useless/doc/rack/html.rb +26 -0
  7. data/lib/useless/doc/rack/subject.rb +40 -0
  8. data/lib/useless/doc/rack/ui.rb +12 -11
  9. data/lib/useless/doc/rack/url.rb +33 -0
  10. data/lib/useless/doc/rack.rb +46 -0
  11. data/lib/useless/doc/router.rb +62 -0
  12. data/lib/useless/doc/serialization/dump.rb +17 -0
  13. data/lib/useless/doc/serialization/load.rb +35 -0
  14. data/lib/useless/doc/sinatra.rb +4 -3
  15. data/lib/useless/doc/ui/godel/api.mustache +24 -24
  16. data/lib/useless/doc/ui/godel/domain.mustache +26 -0
  17. data/lib/useless/doc/ui/godel/resource.mustache +151 -155
  18. data/lib/useless/doc/ui/godel/stylesheet.css +156 -1
  19. data/lib/useless/doc/ui/godel.rb +54 -12
  20. data/lib/useless/doc/ui.rb +24 -0
  21. data/lib/useless/doc/version.rb +1 -1
  22. data/lib/useless/doc.rb +20 -2
  23. data/spec/config.ru +19 -0
  24. data/spec/documents/api.json +1 -0
  25. data/spec/documents/domain.json +17 -0
  26. data/spec/useless/doc/client_spec.rb +59 -0
  27. data/spec/useless/doc/dsl_spec.rb +28 -2
  28. data/spec/useless/doc/rack/{stylesheet_spec.rb → css_spec.rb} +3 -9
  29. data/spec/useless/doc/rack/html_spec.rb +39 -0
  30. data/spec/useless/doc/rack/subject_spec.rb +44 -0
  31. data/spec/useless/doc/rack/ui_spec.rb +1 -1
  32. data/spec/useless/doc/rack/url_spec.rb +35 -0
  33. data/spec/useless/doc/{rack/application_spec.rb → rack_spec.rb} +22 -11
  34. data/spec/useless/doc/router_spec.rb +38 -0
  35. data/spec/useless/doc/serialization/dump_spec.rb +29 -0
  36. data/spec/useless/doc/serialization/load_spec.rb +37 -0
  37. data/spec/useless/doc/sinatra_spec.rb +3 -1
  38. data/spec/useless/doc/ui/godel_spec.rb +136 -96
  39. data/useless-doc.gemspec +1 -1
  40. metadata +34 -21
  41. data/lib/useless/doc/rack/application.rb +0 -47
  42. data/lib/useless/doc/rack/proxy.rb +0 -62
  43. data/lib/useless/doc/rack/retriever.rb +0 -68
  44. data/lib/useless/doc/rack/transform.rb +0 -46
  45. data/spec/useless/doc/rack/proxy_spec.rb +0 -56
  46. data/spec/useless/doc/rack/retriever_spec.rb +0 -82
  47. data/spec/useless/doc/rack/transform_spec.rb +0 -57
@@ -6,167 +6,163 @@
6
6
  </head>
7
7
  <body>
8
8
 
9
- <h1>{{path}}</h1>
10
-
11
- <p>{{description}}</p>
12
-
13
- {{#requests}}
14
- <section>
15
- <h2>{{method}}</h2>
16
-
17
- <p>{{description}}</p>
18
-
19
- <ul>
20
- <li>{{authentication_requirement}}</li>
21
- </ul>
22
-
23
- {{#parameters?}}
24
- <section>
25
- <h4>Parameters</h4>
26
- <table>
27
- <th>
28
- <tr>
29
- <td>Name</td>
30
- <td>Type</td>
31
- <td>Required</td>
32
- <td>Default</td>
33
- <td>Description</td>
34
- <tr>
35
- </th>
36
- <tbody>
37
- {{#parameters}}
9
+ <header class="resource">
10
+ <h1>{{path}}</h1>
11
+
12
+ <p class="description resource">{{description}}</p>
13
+ </header>
14
+
15
+ <section class="main requests">
16
+ {{#requests}}
17
+ <article>
18
+ <h2 id="{{method}}">{{method}}</h2>
19
+
20
+ <p class="description request">{{description}}</p>
21
+
22
+ <ul class="attributes">
23
+ <li>{{authentication_requirement}}</li>
24
+ </ul>
25
+
26
+ {{#parameters?}}
27
+ <section class="parameters">
28
+ <h4>Parameters</h4>
29
+ <table>
30
+ <thead>
31
+ <tr>
32
+ <th>Name</th>
33
+ <th>Description</th>
34
+ <th>Type</th>
35
+ <th>Required</th>
36
+ <th>Default</th>
38
37
  <tr>
39
- <td>{{key}}</td>
40
- <td>{{type}}</td>
41
- <td>{{required}}</td>
42
- <td>{{default}}</td>
43
- <td>{{description}}</td>
44
- </tr>
45
- {{/parameters}}
46
- </tbody>
47
- </table>
48
- </section>
49
- {{/parameters?}}
50
-
51
- {{#headers?}}
52
- <section>
53
- <h4>Headers</h4>
54
- <table>
55
- <th>
56
- <tr>
57
- <td>Name</td>
58
- <td>Description</td>
59
- <tr>
60
- </th>
61
- <tbody>
62
- {{#headers}}
38
+ </thead>
39
+ <tbody>
40
+ {{#parameters}}
41
+ <tr>
42
+ <td>{{key}}</td>
43
+ <td>{{description}}</td>
44
+ <td>{{type}}</td>
45
+ <td>{{required}}</td>
46
+ <td>{{default}}</td>
47
+ </tr>
48
+ {{/parameters}}
49
+ </tbody>
50
+ </table>
51
+ </section> <!-- class="parameters" -->
52
+ {{/parameters?}}
53
+
54
+ {{#headers?}}
55
+ <section class="headers">
56
+ <h4>Headers</h4>
57
+ <table>
58
+ <thead>
63
59
  <tr>
64
- <td>{{key}}</td>
65
- <td>{{description}}</td>
66
- </tr>
67
- {{/headers}}
68
- </tbody>
69
- </table>
70
- </section>
71
- {{/headers?}}
72
-
73
- {{#body}}
74
- <section>
75
- <h4>Body</h4>
76
-
77
- <ul>
78
- <li>{{content_type}}</li>
79
- </ul>
80
-
81
- <table>
82
- <th>
83
- <tr>
84
- <td>Name</td>
85
- <td>Type</td>
86
- <td>Required</td>
87
- <td>Default</td>
88
- <td>Description</td>
89
- <tr>
90
- </th>
91
- <tbody>
92
- {{#attributes}}
60
+ <th>Name</th>
61
+ <th>Description</th>
93
62
  <tr>
94
- <td>{{key}}</td>
95
- <td>{{type}}</td>
96
- <td>{{required}}</td>
97
- <td>{{default}}</td>
98
- <td>{{description}}</td>
99
- </tr>
100
- {{/attributes}}
101
- </tbody>
102
- </table>
103
- </section>
104
- {{/body}}
105
-
106
- {{#responses}}
107
- <section>
108
- <h3>{{code}}</h3>
109
-
110
- <p>{{description}}</p>
111
-
112
- {{#headers?}}
113
- <section>
114
- <h4>Headers</h4>
115
- <table>
116
- <th>
63
+ </thead>
64
+ <tbody>
65
+ {{#headers}}
117
66
  <tr>
118
- <td>Name</td>
119
- <td>Description</td>
67
+ <td>{{key}}</td>
68
+ <td>{{description}}</td>
69
+ </tr>
70
+ {{/headers}}
71
+ </tbody>
72
+ </table>
73
+ </section> <!-- class="headers" -->
74
+ {{/headers?}}
75
+
76
+ {{#body}}
77
+ <section class="body">
78
+ <h4>Body <span class="content-type">{{content_type}}</span></h4>
79
+
80
+ <table>
81
+ <thead>
82
+ <tr>
83
+ <th>Name</th>
84
+ <th>Description</th>
85
+ <th>Type</th>
86
+ <th>Required</th>
87
+ <th>Default</th>
88
+ <tr>
89
+ </thead>
90
+ <tbody>
91
+ {{#attributes}}
120
92
  <tr>
121
- </th>
122
- <tbody>
123
- {{#headers}}
93
+ <td>{{key}}</td>
94
+ <td>{{description}}</td>
95
+ <td>{{type}}</td>
96
+ <td>{{required}}</td>
97
+ <td>{{default}}</td>
98
+ </tr>
99
+ {{/attributes}}
100
+ </tbody>
101
+ </table>
102
+ </section> <!-- class="body" -->
103
+ {{/body}}
104
+
105
+ {{#responses}}
106
+ <section class="response">
107
+ <h3>{{code}} <span class="status-message">{{status_message}}</h3>
108
+
109
+ <p class="description response">{{description}}</p>
110
+
111
+ {{#headers?}}
112
+ <section>
113
+ <h4>Headers</h4>
114
+ <table>
115
+ <thead>
124
116
  <tr>
125
- <td>{{key}}</td>
126
- <td>{{description}}</td>
127
- </tr>
128
- {{/headers}}
129
- </tbody>
130
- </table>
131
- </section>
132
- {{/headers?}}
133
-
134
- {{#body}}
135
- <section>
136
- <h4>Body</h4>
137
-
138
- <ul>
139
- <li>{{content_type}}</li>
140
- </ul>
141
-
142
- <table>
143
- <th>
144
- <tr>
145
- <td>Name</td>
146
- <td>Type</td>
147
- <td>Required</td>
148
- <td>Default</td>
149
- <td>Description</td>
150
- <tr>
151
- </th>
152
- <tbody>
153
- {{#attributes}}
117
+ <th>Name</th>
118
+ <th>Description</th>
119
+ <tr>
120
+ </thead>
121
+ <tbody>
122
+ {{#headers}}
123
+ <tr>
124
+ <td>{{key}}</td>
125
+ <td>{{description}}</td>
126
+ </tr>
127
+ {{/headers}}
128
+ </tbody>
129
+ </table>
130
+ </section>
131
+ {{/headers?}}
132
+
133
+ {{#body}}
134
+ <section>
135
+ <h4>Body <span class="content-type">{{content_type}}</span></h4>
136
+
137
+ <table>
138
+ <thead>
139
+ <tr>
140
+ <th>Name</th>
141
+ <th>Description</th>
142
+ <th>Type</th>
143
+ <th>Required</th>
144
+ <th>Default</th>
154
145
  <tr>
155
- <td>{{key}}</td>
156
- <td>{{type}}</td>
157
- <td>{{required}}</td>
158
- <td>{{default}}</td>
159
- <td>{{description}}</td>
160
- </tr>
161
- {{/attributes}}
162
- </tbody>
163
- </table>
164
- </section>
165
- {{/body}}
166
-
167
- </section>
168
- {{/responses}}
169
- </section>
170
- {{/requests}}
146
+ </thead>
147
+ <tbody>
148
+ {{#attributes}}
149
+ <tr>
150
+ <td>{{key}}</td>
151
+ <td>{{description}}</td>
152
+ <td>{{type}}</td>
153
+ <td>{{required}}</td>
154
+ <td>{{default}}</td>
155
+ </tr>
156
+ {{/attributes}}
157
+ </tbody>
158
+ </table>
159
+ </section>
160
+ {{/body}}
161
+
162
+ </section>
163
+ {{/responses}}
164
+ </article>
165
+ {{/requests}}
166
+ </section class="requests">
171
167
 
172
168
  </body>
@@ -1 +1,156 @@
1
- body { color: #333; }
1
+ @import url(http://fonts.googleapis.com/css?family=Open+Sans:300|Open+Sans+Condensed:300,700);
2
+
3
+ body {
4
+ font-family: 'Open Sans', sans-serif;
5
+ color: #333;
6
+ margin: 0;
7
+ }
8
+
9
+ h1, h2, h3, h4 {
10
+ font-family: 'Open Sans Condensed', sans-serif;
11
+ margin-top: 0;
12
+ margin-bottom: 0.25em;
13
+ }
14
+
15
+ h2 {
16
+ font-size: 2.5em;
17
+ margin-bottom: 0;
18
+ }
19
+
20
+ h3 {
21
+ font-size: 2em;
22
+ margin-bottom: 0;
23
+ }
24
+
25
+ h3 span.status-message {
26
+ color: #BBB;
27
+ font-weight: normal;
28
+ }
29
+
30
+ h4 span.content-type {
31
+ font-weight: normal;
32
+ font-family: 'Open Sans';
33
+ color: #999999;
34
+ margin-left: 1em;
35
+ font-size: 0.75em;
36
+ }
37
+
38
+ p.description {
39
+ color: #888;
40
+ margin-top: 0;
41
+ }
42
+
43
+ p.description.request {
44
+ margin-bottom: 0.5em;
45
+ }
46
+
47
+ header {
48
+ position: fixed;
49
+ min-height: 100%;
50
+ min-width: 260px;
51
+ padding: 10px 20px;
52
+ border-right: 3px double #DDD;
53
+ }
54
+
55
+ header h1,
56
+ header p {
57
+ width: 260px;
58
+ }
59
+
60
+ header.domain h1,
61
+ header.api h1 {
62
+ margin-bottom: 1em;
63
+ }
64
+
65
+ header section.header-section {
66
+ margin-bottom: 3em;
67
+ }
68
+
69
+ header section.header-section.api {
70
+ margin-bottom: 1.5em;
71
+ }
72
+
73
+ header section.header-section p {
74
+ margin-bottom: 0.75em;
75
+ }
76
+
77
+ header section.header-section a.header-section-title {
78
+ font-size: 1.5em;
79
+ font-family: 'Open Sans Condensed', sans-serif;
80
+ }
81
+
82
+ header section.header-section td.description {
83
+ font-size: 0.9em;
84
+ }
85
+
86
+ section.main {
87
+ position: relative;
88
+ margin-left: 313px;
89
+ min-width: 520px;
90
+ }
91
+
92
+ section.main article {
93
+ padding: 30px 40px 40px;
94
+ border-bottom: 3px double #DDD;
95
+ }
96
+
97
+ section.main article:last-child {
98
+ padding-bottom: 30px;
99
+ border-bottom: 0 none;
100
+ }
101
+
102
+ section.parameters,
103
+ section.headers,
104
+ section.body {
105
+ margin-bottom: 2em;
106
+ }
107
+
108
+ section.response {
109
+ margin-bottom: 1em;
110
+ }
111
+
112
+ ul.attributes {
113
+ overflow: hidden;
114
+ *zoom: 1;
115
+ padding: 0;
116
+ margin: 0;
117
+ list-style: none;
118
+ margin-bottom: 2em;
119
+ }
120
+
121
+ ul.attributes li {
122
+ float: left;
123
+ padding: 3px 10px;
124
+ border: 1px solid #DDD;
125
+ background-color: #EEE;
126
+ font-size: 0.8em;
127
+ }
128
+
129
+ table {
130
+ width: 100%;
131
+ border: 1px solid #DDD;
132
+ border-spacing: 0;
133
+ }
134
+
135
+ table th {
136
+ font-weight: inherit;
137
+ }
138
+
139
+ table td, th {
140
+ border-right: 1px solid #DDD;
141
+ border-bottom: 1px solid #DDD;
142
+ padding: 5px;
143
+ }
144
+
145
+ table th {
146
+ text-align: left;
147
+ color: #999;
148
+ }
149
+
150
+ table td:last-child, table th:last-child {
151
+ border-right-width: 0;
152
+ }
153
+
154
+ table tbody tr:last-child td, table tbody tr:last-child th {
155
+ border-bottom-width: 0;
156
+ }
@@ -1,39 +1,76 @@
1
1
  require 'mustache'
2
2
  require 'forwardable'
3
+ require 'rack/utils'
4
+
5
+ require 'useless/doc/core/domain'
6
+ require 'useless/doc/core/api'
7
+ require 'useless/doc/core/resource'
3
8
 
4
9
  module Useless
5
10
  module Doc
6
11
  module UI
7
12
  class Godel
8
- def self.api(api)
9
- API.new(api).render
13
+ include Doc::UI
14
+
15
+ def self.asset_path
16
+ File.dirname(__FILE__) + '/godel'
10
17
  end
11
18
 
12
- def self.resource(resource)
13
- Resource.new(resource).render
19
+ def initialize(router)
20
+ @router = router
14
21
  end
15
22
 
16
- def self.css
17
- File.read(asset_path + '/stylesheet.css')
23
+ def html(entity)
24
+ view = case entity
25
+ when Core::Domain then Godel::Domain
26
+ when Core::API then Godel::API
27
+ when Core::Resource then Godel::Resource
28
+ end
29
+
30
+ if view
31
+ view.new(entity, @router).render
32
+ end
18
33
  end
19
34
 
20
- def self.asset_path
21
- File.dirname(__FILE__) + '/godel'
35
+ def css(entity = nil)
36
+ File.read(Godel.asset_path + '/stylesheet.css')
37
+ end
38
+
39
+ class Domain < Mustache
40
+ extend Forwardable
41
+
42
+ def_delegators :@domain, :name, :description
43
+
44
+ self.template_file = Godel.asset_path + '/domain.mustache'
45
+
46
+ def initialize(domain, router = nil)
47
+ @domain = domain
48
+ @router = router
49
+ end
50
+
51
+ def apis
52
+ @domain.apis.map{ |api| Godel::API.new(api, @router) }
53
+ end
22
54
  end
23
55
 
24
56
  class API < Mustache
25
57
  extend Forwardable
26
58
 
27
- def_delegators :@api, :url, :description
59
+ def_delegators :@api, :name, :url, :description
28
60
 
29
61
  self.template_file = Godel.asset_path + '/api.mustache'
30
62
 
31
- def initialize(api)
63
+ def initialize(api, router)
32
64
  @api = api
65
+ @router = router
66
+ end
67
+
68
+ def doc_url
69
+ @router.doc_for_api(@api.url)
33
70
  end
34
71
 
35
72
  def resources
36
- @api.resources.map{ |resource| Godel::Resource.new(resource) }
73
+ @api.resources.map{ |resource| Godel::Resource.new(resource, @router) }
37
74
  end
38
75
  end
39
76
 
@@ -44,8 +81,9 @@ module Useless
44
81
 
45
82
  self.template_file = Godel.asset_path + '/resource.mustache'
46
83
 
47
- def initialize(resource)
84
+ def initialize(resource, router)
48
85
  @resource = resource
86
+ @router = router
49
87
  end
50
88
 
51
89
  def requests
@@ -97,6 +135,10 @@ module Useless
97
135
  @response = response
98
136
  end
99
137
 
138
+ def status_message
139
+ ::Rack::Utils::HTTP_STATUS_CODES[code]
140
+ end
141
+
100
142
  def headers?
101
143
  headers.any?
102
144
  end
@@ -0,0 +1,24 @@
1
+ module Useless
2
+ module Doc
3
+
4
+ # A +Doc::UI+ is a class that has two methods: +#html+ and +#css+. It is
5
+ # initialized with an instance of +Doc::Router+.
6
+ #
7
+ # +#html+ takes a +Doc::Core+ entity and returns a corresponding HTML
8
+ # representation.
9
+ #
10
+ # +#css+ returns a CSS document suitable for the HTML returned by +#html+.
11
+ #
12
+ module UI
13
+ def initialize(router)
14
+ @router = router
15
+ end
16
+
17
+ def html(entity)
18
+ end
19
+
20
+ def css(entity = nil)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,5 +1,5 @@
1
1
  module Useless
2
2
  module Doc
3
- VERSION = '0.2.3'
3
+ VERSION = '0.3.0'
4
4
  end
5
5
  end
data/lib/useless/doc.rb CHANGED
@@ -1,9 +1,27 @@
1
1
  require 'useless/doc/dsl'
2
+ require 'useless/doc/serialization/load'
3
+ require 'useless/doc/serialization/dump'
2
4
 
3
5
  module Useless
4
6
  module Doc
5
- def self.api(url, &block)
6
- DSL::API.build url: url, &block
7
+ def self.domain(name = nil, &block)
8
+ DSL::Domain.build name: name, &block
9
+ end
10
+
11
+ def self.api(name = nil, &block)
12
+ DSL::API.build name: name, &block
13
+ end
14
+
15
+ def self.resource(path = nil, &block)
16
+ DSL::Resource.build path: path, &block
17
+ end
18
+
19
+ def self.load
20
+ Useless::Doc::Serialization::Load
21
+ end
22
+
23
+ def self.dump
24
+ Useless::Doc::Serialization::Dump
7
25
  end
8
26
  end
9
27
  end
data/spec/config.ru ADDED
@@ -0,0 +1,19 @@
1
+ lib = File.expand_path('../../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'uri'
5
+ require 'useless/doc/router'
6
+ require 'useless/doc/rack'
7
+
8
+ class TestRouter
9
+ include Useless::Doc::Router
10
+
11
+ def api_for_doc(url)
12
+ if uri = URI(url)
13
+ path = uri.path == '/' ? '/domain' : uri.path
14
+ "#{uri.scheme}://#{uri.host}#{path}"
15
+ end
16
+ end
17
+ end
18
+
19
+ run Useless::Doc::Rack.new(TestRouter.new)
@@ -1,4 +1,5 @@
1
1
  {
2
+ "name": "Twonk API",
2
3
  "url": "twonk.useless.io",
3
4
  "description": "Twonk information. Duh.",
4
5
  "resources": [