useless-doc 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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>
|