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.
- data/lib/useless/doc/client.rb +62 -0
- data/lib/useless/doc/core/api.rb +6 -2
- data/lib/useless/doc/core/domain.rb +34 -0
- data/lib/useless/doc/dsl.rb +30 -0
- data/lib/useless/doc/rack/{stylesheet.rb → css.rb} +8 -8
- data/lib/useless/doc/rack/html.rb +26 -0
- data/lib/useless/doc/rack/subject.rb +40 -0
- data/lib/useless/doc/rack/ui.rb +12 -11
- data/lib/useless/doc/rack/url.rb +33 -0
- data/lib/useless/doc/rack.rb +46 -0
- data/lib/useless/doc/router.rb +62 -0
- data/lib/useless/doc/serialization/dump.rb +17 -0
- data/lib/useless/doc/serialization/load.rb +35 -0
- data/lib/useless/doc/sinatra.rb +4 -3
- data/lib/useless/doc/ui/godel/api.mustache +24 -24
- data/lib/useless/doc/ui/godel/domain.mustache +26 -0
- data/lib/useless/doc/ui/godel/resource.mustache +151 -155
- data/lib/useless/doc/ui/godel/stylesheet.css +156 -1
- data/lib/useless/doc/ui/godel.rb +54 -12
- data/lib/useless/doc/ui.rb +24 -0
- data/lib/useless/doc/version.rb +1 -1
- data/lib/useless/doc.rb +20 -2
- data/spec/config.ru +19 -0
- data/spec/documents/api.json +1 -0
- data/spec/documents/domain.json +17 -0
- data/spec/useless/doc/client_spec.rb +59 -0
- data/spec/useless/doc/dsl_spec.rb +28 -2
- data/spec/useless/doc/rack/{stylesheet_spec.rb → css_spec.rb} +3 -9
- data/spec/useless/doc/rack/html_spec.rb +39 -0
- data/spec/useless/doc/rack/subject_spec.rb +44 -0
- data/spec/useless/doc/rack/ui_spec.rb +1 -1
- data/spec/useless/doc/rack/url_spec.rb +35 -0
- data/spec/useless/doc/{rack/application_spec.rb → rack_spec.rb} +22 -11
- data/spec/useless/doc/router_spec.rb +38 -0
- data/spec/useless/doc/serialization/dump_spec.rb +29 -0
- data/spec/useless/doc/serialization/load_spec.rb +37 -0
- data/spec/useless/doc/sinatra_spec.rb +3 -1
- data/spec/useless/doc/ui/godel_spec.rb +136 -96
- data/useless-doc.gemspec +1 -1
- metadata +34 -21
- data/lib/useless/doc/rack/application.rb +0 -47
- data/lib/useless/doc/rack/proxy.rb +0 -62
- data/lib/useless/doc/rack/retriever.rb +0 -68
- data/lib/useless/doc/rack/transform.rb +0 -46
- data/spec/useless/doc/rack/proxy_spec.rb +0 -56
- data/spec/useless/doc/rack/retriever_spec.rb +0 -82
- data/spec/useless/doc/rack/transform_spec.rb +0 -57
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'typhoeus'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
require 'useless/doc/serialization/load'
|
6
|
+
|
7
|
+
module Useless
|
8
|
+
module Doc
|
9
|
+
module Client
|
10
|
+
def self.standard
|
11
|
+
@standard ||= Standard.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.stub
|
15
|
+
@stub ||= Stub.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(url)
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
class Standard
|
23
|
+
include Client
|
24
|
+
|
25
|
+
NotModified = 304
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@cache = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def get(url)
|
32
|
+
headers = { 'Accept' => 'application/json' }
|
33
|
+
|
34
|
+
if @cache[url]
|
35
|
+
headers['If-Modified-Since'] = @cache[url][:timestamp].httpdate()
|
36
|
+
end
|
37
|
+
|
38
|
+
response = Typhoeus.options url, headers: headers
|
39
|
+
|
40
|
+
unless response.response_code == NotModified
|
41
|
+
@cache[url] = { response_body: response.response_body, timestamp: Time.now }
|
42
|
+
end
|
43
|
+
|
44
|
+
Useless::Doc::Serialization::Load.load(@cache[url][:response_body])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Stub
|
49
|
+
include Client
|
50
|
+
|
51
|
+
def get(url)
|
52
|
+
uri = URI(url)
|
53
|
+
path = File.dirname(__FILE__) + "/../../../spec/documents#{uri.path}.json"
|
54
|
+
|
55
|
+
if File.exists?(path)
|
56
|
+
Useless::Doc::Serialization::Load.load(File.read(path))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/useless/doc/core/api.rb
CHANGED
@@ -4,6 +4,9 @@ module Useless
|
|
4
4
|
|
5
5
|
# Documentation for an entire API.
|
6
6
|
#
|
7
|
+
# @!attribute [r] name
|
8
|
+
# @return [String] nameof the API.
|
9
|
+
#
|
7
10
|
# @!attribute [r] url
|
8
11
|
# @return [String] a the URL of the API.
|
9
12
|
#
|
@@ -18,15 +21,16 @@ module Useless
|
|
18
21
|
#
|
19
22
|
class API
|
20
23
|
|
21
|
-
attr_accessor :url, :description, :timestamp, :resources
|
24
|
+
attr_accessor :name, :url, :description, :timestamp, :resources
|
22
25
|
|
23
26
|
# @param [Hash] attrs corresponds to the class's instance attributes.
|
24
27
|
#
|
25
28
|
def initialize(attrs = {})
|
29
|
+
@name = attrs[:name]
|
26
30
|
@url = attrs[:url]
|
27
31
|
@description = attrs[:description]
|
28
32
|
@timestamp = attrs[:timestamp]
|
29
|
-
@resources = attrs[:resources]
|
33
|
+
@resources = attrs[:resources] || []
|
30
34
|
end
|
31
35
|
end
|
32
36
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Useless
|
2
|
+
module Doc
|
3
|
+
module Core
|
4
|
+
|
5
|
+
# Documentation for a domain - a group of APIs.
|
6
|
+
#
|
7
|
+
# @!attribute [r] name
|
8
|
+
# @return [String] a name of the domain.
|
9
|
+
#
|
10
|
+
# @!attribute [r] url
|
11
|
+
# @return [String] a the URL of the domain.
|
12
|
+
#
|
13
|
+
# @!attribute [r] description
|
14
|
+
# @return [String] a description of the domain.
|
15
|
+
#
|
16
|
+
# @!attribute [r] apis
|
17
|
+
# @return [Array<API>] the APIs included in this domain.
|
18
|
+
#
|
19
|
+
class Domain
|
20
|
+
|
21
|
+
attr_accessor :name, :url, :description, :apis
|
22
|
+
|
23
|
+
# @param [Hash] attrs corresponds to the class's instance attributes.
|
24
|
+
#
|
25
|
+
def initialize(attrs = {})
|
26
|
+
@name = attrs[:name]
|
27
|
+
@url = attrs[:url]
|
28
|
+
@description = attrs[:description]
|
29
|
+
@apis = attrs[:apis]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/useless/doc/dsl.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'useless/doc/core/api'
|
2
2
|
require 'useless/doc/core/body'
|
3
|
+
require 'useless/doc/core/domain'
|
3
4
|
require 'useless/doc/core/header'
|
4
5
|
require 'useless/doc/core/request'
|
5
6
|
require 'useless/doc/core/resource'
|
@@ -64,6 +65,31 @@ module Useless
|
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
68
|
+
class Domain
|
69
|
+
include DSL::Member
|
70
|
+
|
71
|
+
def default_attributes
|
72
|
+
{ apis: [] }
|
73
|
+
end
|
74
|
+
|
75
|
+
def name
|
76
|
+
@attributes[:name] = name
|
77
|
+
end
|
78
|
+
|
79
|
+
def url(url)
|
80
|
+
@attributes[:url] = url
|
81
|
+
end
|
82
|
+
|
83
|
+
def description(description)
|
84
|
+
@attributes[:description] = description
|
85
|
+
end
|
86
|
+
|
87
|
+
def api(name, &block)
|
88
|
+
api = API.build name: name, &block
|
89
|
+
@attributes[:apis] << api
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
67
93
|
class API
|
68
94
|
include DSL::Member
|
69
95
|
|
@@ -84,6 +110,10 @@ module Useless
|
|
84
110
|
super
|
85
111
|
end
|
86
112
|
|
113
|
+
def name
|
114
|
+
@attributes[:name] = name
|
115
|
+
end
|
116
|
+
|
87
117
|
def url(url)
|
88
118
|
@attributes[:url] = url
|
89
119
|
end
|
@@ -1,22 +1,22 @@
|
|
1
1
|
module Useless
|
2
2
|
module Doc
|
3
|
-
|
3
|
+
class Rack
|
4
4
|
|
5
|
-
# +Doc::Rack::
|
5
|
+
# +Doc::Rack::CSS+ serves the stylesheet for the current +Doc::UI+
|
6
6
|
# iff the request path is '/doc.css'. Otherwise, it passes the request
|
7
|
-
#
|
7
|
+
# down the stack.
|
8
8
|
#
|
9
|
-
class
|
9
|
+
class CSS
|
10
10
|
def initialize(app)
|
11
11
|
@app = app
|
12
12
|
end
|
13
13
|
|
14
14
|
def call(env)
|
15
|
-
unless env['useless.doc.ui']
|
16
|
-
raise 'No UI specified.'
|
17
|
-
end
|
18
|
-
|
19
15
|
if env["PATH_INFO"].to_s == '/doc.css'
|
16
|
+
if env['useless.doc.logger']
|
17
|
+
env['useless.doc.logger'].info "serving CSS for #{env['useless.doc.ui'].class.name}"
|
18
|
+
end
|
19
|
+
|
20
20
|
[200, {'Content-Type' => 'text/css'}, [env['useless.doc.ui'].css]]
|
21
21
|
else
|
22
22
|
@app.call(env)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Useless
|
2
|
+
module Doc
|
3
|
+
class Rack
|
4
|
+
|
5
|
+
# +Doc::Rack::HTML+ is the base application for +Useless::Doc::Rack+.
|
6
|
+
# It expects a +Doc::UI+ instance to be set as 'useless.doc.ui', and a
|
7
|
+
# +Doc::Core+ entity to be set as 'useless.doc.subject', and then simply
|
8
|
+
# passes the latter to the former's +#html+ method.
|
9
|
+
#
|
10
|
+
module HTML
|
11
|
+
def self.call(env)
|
12
|
+
if html = env['useless.doc.ui'].html(env['useless.doc.subject'])
|
13
|
+
if env['useless.doc.logger']
|
14
|
+
env['useless.doc.logger'].info "rendered subject HTML for #{env['useless.doc.url']}"
|
15
|
+
env['useless.doc.logger'].debug "rendered HTML: #{html}"
|
16
|
+
end
|
17
|
+
|
18
|
+
[200, {'Content-Type' => 'text/html'}, [html]]
|
19
|
+
else
|
20
|
+
[404, {'Content-Type' => 'text/plain'}, ['Could not render documentation.']]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'useless/doc/client'
|
2
|
+
|
3
|
+
module Useless
|
4
|
+
module Doc
|
5
|
+
class Rack
|
6
|
+
|
7
|
+
# +Doc::Rack::Subject+ retrieves a +Doc::Core+ entity based upon
|
8
|
+
# 'useless.doc.url', from a environment-appropriate +Doc::Client+,
|
9
|
+
# and sets it to 'useless.doc.subject'.
|
10
|
+
#
|
11
|
+
class Subject
|
12
|
+
def initialize(app)
|
13
|
+
@app = app
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
client = case ENV['RACK_ENV']
|
18
|
+
when 'production'; Useless::Doc::Client.standard
|
19
|
+
else Useless::Doc::Client.stub
|
20
|
+
end
|
21
|
+
|
22
|
+
if env['useless.doc.logger']
|
23
|
+
env['useless.doc.logger'].debug "selected Client: #{client.inspect}"
|
24
|
+
end
|
25
|
+
|
26
|
+
if env['useless.doc.subject'] = client.get(env['useless.doc.url'])
|
27
|
+
if env['useless.doc.logger']
|
28
|
+
env['useless.doc.logger'].info "retrieved subject for #{env['useless.doc.url']}"
|
29
|
+
env['useless.doc.logger'].debug "retrieved subject: #{env['useless.doc.subject'].inspect}"
|
30
|
+
end
|
31
|
+
|
32
|
+
@app.call(env)
|
33
|
+
else
|
34
|
+
[404, {'Content-Type' => 'text/plain'}, ['Could not retrieve documentation.']]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/useless/doc/rack/ui.rb
CHANGED
@@ -3,17 +3,15 @@ require 'useless/doc/ui/godel'
|
|
3
3
|
|
4
4
|
module Useless
|
5
5
|
module Doc
|
6
|
-
|
6
|
+
class Rack
|
7
7
|
|
8
8
|
# +Doc::Rack::UI+ chooses which UI should be used to render the
|
9
|
-
# documentation
|
10
|
-
#
|
9
|
+
# documentation and sets it to 'useless.doc.ui'.
|
10
|
+
#
|
11
|
+
# It could theoretically be chosen via the 'ui' parameter,
|
12
|
+
# but until there are other UIs, it will alway choose +UI::Godel+.
|
11
13
|
#
|
12
14
|
class UI
|
13
|
-
def self.default
|
14
|
-
Useless::Doc::UI::Godel
|
15
|
-
end
|
16
|
-
|
17
15
|
def initialize(app)
|
18
16
|
@app = app
|
19
17
|
end
|
@@ -21,12 +19,15 @@ module Useless
|
|
21
19
|
def call(env)
|
22
20
|
request = ::Rack::Request.new(env)
|
23
21
|
|
24
|
-
ui = case request.params['ui']
|
25
|
-
|
26
|
-
|
22
|
+
env['useless.doc.ui'] = case request.params['ui']
|
23
|
+
when 'godel'; Useless::Doc::UI::Godel.new(env['useless.doc.router'])
|
24
|
+
else Useless::Doc::UI::Godel.new(env['useless.doc.router'])
|
25
|
+
end
|
26
|
+
|
27
|
+
if env['useless.doc.logger']
|
28
|
+
env['useless.doc.logger'].debug "selected UI: #{env['useless.doc.ui'].class.name}"
|
27
29
|
end
|
28
30
|
|
29
|
-
env['useless.doc.ui'] = ui
|
30
31
|
@app.call(env)
|
31
32
|
end
|
32
33
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rack/request'
|
2
|
+
|
3
|
+
module Useless
|
4
|
+
module Doc
|
5
|
+
class Rack
|
6
|
+
|
7
|
+
# +Doc::Rack::URL+ translates the request URL into the corresponding
|
8
|
+
# API URL using the specified 'useless.doc.router'.
|
9
|
+
#
|
10
|
+
class URL
|
11
|
+
def initialize(app)
|
12
|
+
@app = app
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
request = ::Rack::Request.new(env)
|
17
|
+
|
18
|
+
if url = env['useless.doc.router'].api_for_doc(request.url)
|
19
|
+
env['useless.doc.url'] = url
|
20
|
+
|
21
|
+
if env['useless.doc.logger']
|
22
|
+
env['useless.doc.logger'].info "routing #{request.url} to #{env['useless.doc.url']}"
|
23
|
+
end
|
24
|
+
|
25
|
+
@app.call(env)
|
26
|
+
else
|
27
|
+
[404, {'Content-Type' => 'text/plain'}, ['Unknown documentation.']]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rack/builder'
|
2
|
+
require 'rack/commonlogger'
|
3
|
+
require 'low/rack/rack_errors'
|
4
|
+
require 'low/rack/log_level'
|
5
|
+
require 'low/rack/request_logger'
|
6
|
+
|
7
|
+
require 'useless/doc/router'
|
8
|
+
require 'useless/doc/rack/ui'
|
9
|
+
require 'useless/doc/rack/css'
|
10
|
+
require 'useless/doc/rack/url'
|
11
|
+
require 'useless/doc/rack/subject'
|
12
|
+
require 'useless/doc/rack/html'
|
13
|
+
|
14
|
+
module Useless
|
15
|
+
module Doc
|
16
|
+
class Rack
|
17
|
+
def initialize(router = nil)
|
18
|
+
@router = router || Useless::Doc::Router.default
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(env)
|
22
|
+
env['useless.doc.router'] ||= @router
|
23
|
+
app.call(env)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def app
|
29
|
+
@app ||= begin
|
30
|
+
::Rack::Builder.app do
|
31
|
+
use Low::Rack::RackErrors
|
32
|
+
use Low::Rack::LogLevel
|
33
|
+
use Low::Rack::RequestLogger, key: 'useless.doc.logger'
|
34
|
+
use ::Rack::CommonLogger
|
35
|
+
|
36
|
+
use Useless::Doc::Rack::UI
|
37
|
+
use Useless::Doc::Rack::CSS
|
38
|
+
use Useless::Doc::Rack::URL
|
39
|
+
use Useless::Doc::Rack::Subject
|
40
|
+
run Useless::Doc::Rack::HTML
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Useless
|
4
|
+
module Doc
|
5
|
+
|
6
|
+
# +Doc::Router+ determines the doc URL for an API and vice versa via
|
7
|
+
# the #doc_for_api and #api_for_doc methods, respectively.
|
8
|
+
#
|
9
|
+
module Router
|
10
|
+
def self.default
|
11
|
+
@default ||= Doc::Router::Default.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def doc_for_api(url)
|
15
|
+
end
|
16
|
+
|
17
|
+
def api_for_doc(url)
|
18
|
+
end
|
19
|
+
|
20
|
+
class Default
|
21
|
+
include Doc::Router
|
22
|
+
|
23
|
+
def initialize(*supported_urls)
|
24
|
+
@supported_urls = supported_urls
|
25
|
+
end
|
26
|
+
|
27
|
+
def doc_for_api(url)
|
28
|
+
return nil unless supported_url?(url)
|
29
|
+
uri = URI(url)
|
30
|
+
host = uri.host
|
31
|
+
new_host = host.
|
32
|
+
split('.').
|
33
|
+
insert(-3, 'doc').
|
34
|
+
join('.')
|
35
|
+
"#{uri.scheme}://#{new_host}#{uri.path}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def api_for_doc(url)
|
39
|
+
uri = URI(url)
|
40
|
+
host = uri.host
|
41
|
+
parts = host.split('.')
|
42
|
+
parts.slice!(-3) if parts[-3] == 'doc'
|
43
|
+
new_host = parts.join('.')
|
44
|
+
new_url = "#{uri.scheme}://#{new_host}#{uri.path}"
|
45
|
+
new_url if supported_url?(new_url)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def supported_url?(url)
|
51
|
+
if @supported_urls.nil? or @supported_urls.empty?
|
52
|
+
true
|
53
|
+
else
|
54
|
+
@supported_urls.any? do |supported_url|
|
55
|
+
url =~ Regexp.new(supported_url)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -18,6 +18,22 @@ module Useless
|
|
18
18
|
hash.is_a?(String) ? hash : Oj.dump(hash)
|
19
19
|
end
|
20
20
|
|
21
|
+
# Converts +Core::Domain+ instance to a JSON representation.
|
22
|
+
#
|
23
|
+
# @param [Core::Domain] domain the domain to be converted to JSON.
|
24
|
+
#
|
25
|
+
# @return [String] a JSON representation of the specified domain.
|
26
|
+
#
|
27
|
+
def self.domain(domain)
|
28
|
+
if domain
|
29
|
+
hash_to_json \
|
30
|
+
'name' => domain.name,
|
31
|
+
'url' => domain.url,
|
32
|
+
'description' => domain.description,
|
33
|
+
'apis' => domain.apis.map { |api| api(api) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
21
37
|
# Converts +Core::API+ instance to a JSON representation.
|
22
38
|
#
|
23
39
|
# @param [Core::API] api the API to be converted to JSON.
|
@@ -27,6 +43,7 @@ module Useless
|
|
27
43
|
def self.api(api)
|
28
44
|
if api
|
29
45
|
hash_to_json \
|
46
|
+
'name' => api.name,
|
30
47
|
'url' => api.url,
|
31
48
|
'description' => api.description,
|
32
49
|
'resources' => api.resources.map { |resource| resource(resource) }
|
@@ -24,6 +24,40 @@ module Useless
|
|
24
24
|
json.is_a?(Hash) ? json : Oj.load(json)
|
25
25
|
end
|
26
26
|
|
27
|
+
def self.load(json)
|
28
|
+
hash = json_to_hash json
|
29
|
+
|
30
|
+
if hash['apis']
|
31
|
+
self.domain(hash)
|
32
|
+
elsif hash['url']
|
33
|
+
self.api(hash)
|
34
|
+
elsif hash['path']
|
35
|
+
self.resource(hash)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Converts a JSON represntation to an instance of +Core::Domain+
|
40
|
+
#
|
41
|
+
# @param [String, Hash] json the JSON representation to be converted to
|
42
|
+
# a domain.
|
43
|
+
#
|
44
|
+
# @return [Core::Domain] the domain corresponding to the specified
|
45
|
+
# JSON.
|
46
|
+
#
|
47
|
+
def self.domain(json)
|
48
|
+
hash = json_to_hash json
|
49
|
+
|
50
|
+
apis = (hash['apis'] || []).map do |json|
|
51
|
+
api json
|
52
|
+
end
|
53
|
+
|
54
|
+
Useless::Doc::Core::Domain.new \
|
55
|
+
name: hash['name'],
|
56
|
+
url: hash['url'],
|
57
|
+
description: hash['description'],
|
58
|
+
apis: apis
|
59
|
+
end
|
60
|
+
|
27
61
|
# Converts a JSON represntation to an instance of +Core::API+
|
28
62
|
#
|
29
63
|
# @param [String, Hash] json the JSON representation to be converted to
|
@@ -40,6 +74,7 @@ module Useless
|
|
40
74
|
end
|
41
75
|
|
42
76
|
Useless::Doc::Core::API.new \
|
77
|
+
name: hash['name'],
|
43
78
|
url: hash['url'],
|
44
79
|
description: hash['description'],
|
45
80
|
resources: resources
|
data/lib/useless/doc/sinatra.rb
CHANGED
@@ -15,7 +15,8 @@ module Useless
|
|
15
15
|
# class ResourceApp < Sinatra::Base
|
16
16
|
# register Useless::Doc::Sinatra
|
17
17
|
#
|
18
|
-
# doc '
|
18
|
+
# doc 'Resouces API' do
|
19
|
+
# url 'resources.useless.io'
|
19
20
|
# description 'A place with resources'
|
20
21
|
# end
|
21
22
|
#
|
@@ -42,8 +43,8 @@ module Useless
|
|
42
43
|
@doc = doc
|
43
44
|
end
|
44
45
|
|
45
|
-
def doc(
|
46
|
-
@dsl ||= Useless::Doc::DSL::API.new(
|
46
|
+
def doc(name = nil, &block)
|
47
|
+
@dsl ||= Useless::Doc::DSL::API.new(name: name)
|
47
48
|
@dsl.instance_eval(&block) if block_given?
|
48
49
|
@dsl
|
49
50
|
end
|
@@ -1,38 +1,38 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
|
-
<title>{{
|
4
|
+
<title>{{name}} | doc.useless.io</title>
|
5
5
|
<link href="/doc.css" media="screen" rel="stylesheet" type="text/css" />
|
6
6
|
</head>
|
7
7
|
<body>
|
8
8
|
|
9
|
-
<
|
9
|
+
<header class="api">
|
10
|
+
<h1>{{name}}</h1>
|
10
11
|
|
11
|
-
|
12
|
+
{{#resources}}
|
13
|
+
<section class="resource header-section">
|
14
|
+
<a class="path header-section-title" href="{{path}}">{{path}}</a>
|
12
15
|
|
13
|
-
|
14
|
-
<section>
|
15
|
-
<h2>{{path}}</h2>
|
16
|
+
<p class="description">{{description}}</p>
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
<table>
|
20
|
-
<th>
|
21
|
-
<tr>
|
22
|
-
<td>Method</td>
|
23
|
-
<td>Description</td>
|
24
|
-
<tr>
|
25
|
-
</th>
|
26
|
-
<tbody>
|
18
|
+
<table>
|
27
19
|
{{#requests}}
|
28
|
-
<
|
29
|
-
<
|
30
|
-
|
31
|
-
|
20
|
+
<tbody>
|
21
|
+
<tr>
|
22
|
+
<td><a href="{{doc_path}}">{{method}}</a></td>
|
23
|
+
<td class="description">{{description}}</td>
|
24
|
+
</tr>
|
25
|
+
</tbody>
|
32
26
|
{{/requests}}
|
33
|
-
</
|
34
|
-
</
|
35
|
-
|
36
|
-
|
27
|
+
</table>
|
28
|
+
</section>
|
29
|
+
{{/resources}}
|
30
|
+
</header>
|
31
|
+
|
32
|
+
<section class="main description">
|
33
|
+
<article>
|
34
|
+
<p class="description api">{{description}}</p>
|
35
|
+
</article>
|
36
|
+
</section>
|
37
37
|
|
38
38
|
</body>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>doc.useless.io</title>
|
5
|
+
<link href="/doc.css" media="screen" rel="stylesheet" type="text/css" />
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
|
9
|
+
<header class="domain">
|
10
|
+
<h1>{{name}}</h1>
|
11
|
+
|
12
|
+
{{#apis}}
|
13
|
+
<section class="api header-section">
|
14
|
+
<a class="name header-section-title" href="{{doc_url}}">{{name}}</a>
|
15
|
+
|
16
|
+
<p class="description">{{description}}</p>
|
17
|
+
</section>
|
18
|
+
{{/apis}}
|
19
|
+
</header>
|
20
|
+
|
21
|
+
<section class="main description">
|
22
|
+
<article>
|
23
|
+
<p class="description domain">{{description}}</p>
|
24
|
+
</article>
|
25
|
+
</section>
|
26
|
+
</body>
|