cabbage_doc 0.0.7 → 0.0.8
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.
- checksums.yaml +4 -4
- data/lib/cabbage_doc.rb +7 -2
- data/lib/cabbage_doc/action.rb +1 -1
- data/lib/cabbage_doc/authentication.rb +13 -4
- data/lib/cabbage_doc/client.rb +2 -0
- data/lib/cabbage_doc/collection.rb +23 -6
- data/lib/cabbage_doc/configuration.rb +14 -4
- data/lib/cabbage_doc/controller.rb +15 -9
- data/lib/cabbage_doc/example.rb +1 -1
- data/lib/cabbage_doc/{processor.rb → generator.rb} +41 -21
- data/lib/cabbage_doc/generators/api.rb +39 -0
- data/lib/cabbage_doc/generators/pages.rb +33 -0
- data/lib/cabbage_doc/parameter.rb +1 -1
- data/lib/cabbage_doc/params.rb +6 -2
- data/lib/cabbage_doc/parser.rb +3 -3
- data/lib/cabbage_doc/request.rb +24 -7
- data/lib/cabbage_doc/response.rb +1 -1
- data/lib/cabbage_doc/task.rb +55 -23
- data/lib/cabbage_doc/version.rb +1 -1
- data/lib/cabbage_doc/web.rb +17 -3
- data/lib/cabbage_doc/web_helper.rb +13 -3
- data/web/public/css/application.css +1 -25
- data/web/public/css/base.css +23 -0
- data/web/public/js/application.js +6 -5
- data/web/views/action.haml +3 -3
- data/web/views/api.haml +14 -0
- data/web/views/controller.haml +1 -1
- data/web/views/controllers.haml +3 -0
- data/web/views/index.haml +5 -2
- data/web/views/layout.haml +1 -0
- data/web/views/page.haml +1 -0
- data/web/views/page_layout.haml +13 -0
- metadata +24 -5
- data/lib/cabbage_doc/processors/documentation.rb +0 -17
- data/web/views/documentation.haml +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7bdad905798e6ed0c5e62b8ec075359acf0eb78c
|
4
|
+
data.tar.gz: 40c4b70fdaebe890f108ecd2cfc94c8e82608782
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 493affb4f721afd804dfb7fcfb251d8bf22d36a8754452f727e0cc98816f5bc9aca235f308623435aac67a74ff45bffab1586188627d470e95c220a31614894a
|
7
|
+
data.tar.gz: 3410ed1938d0e208c1a61a1fb4918725fe922125269a36dbdfd2892a7cc44a89cbfe748d91bdeab4cf70f48f007ba3352866ced565f776529d3b98ea418f6119
|
data/lib/cabbage_doc.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module CabbageDoc
|
2
|
+
TAG = :api
|
2
3
|
MARKER = ':cabbagedoc:'.freeze
|
3
|
-
VISIBILITY = %i(public private internal beta).freeze
|
4
|
+
VISIBILITY = %i(public private internal beta unreleased).freeze
|
4
5
|
VISIBILITY_REGEXP = VISIBILITY.map(&:to_s).map(&:capitalize).join('|').freeze
|
5
6
|
|
6
7
|
autoload :Path, 'cabbage_doc/path'
|
@@ -20,7 +21,7 @@ module CabbageDoc
|
|
20
21
|
autoload :Collection, 'cabbage_doc/collection'
|
21
22
|
autoload :WebHelper, 'cabbage_doc/web_helper'
|
22
23
|
autoload :Web, 'cabbage_doc/web'
|
23
|
-
autoload :
|
24
|
+
autoload :Generator, 'cabbage_doc/generator'
|
24
25
|
autoload :Customizer, 'cabbage_doc/customizer'
|
25
26
|
autoload :Task, 'cabbage_doc/task'
|
26
27
|
autoload :Worker, 'cabbage_doc/worker'
|
@@ -33,5 +34,9 @@ module CabbageDoc
|
|
33
34
|
config.validate!
|
34
35
|
end
|
35
36
|
end
|
37
|
+
|
38
|
+
def glob(*args)
|
39
|
+
proc { Dir.glob(File.join(*args)).sort.reverse }
|
40
|
+
end
|
36
41
|
end
|
37
42
|
end
|
data/lib/cabbage_doc/action.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
module CabbageDoc
|
2
2
|
class Authentication
|
3
3
|
class << self
|
4
|
-
def new(request = nil)
|
4
|
+
def new(request = nil, tag = nil)
|
5
5
|
super().tap do |auth|
|
6
|
+
auth.tag = tag if tag
|
6
7
|
yield(auth) if block_given?
|
7
8
|
Configuration.instance.authentication.call(auth, request)
|
8
9
|
end
|
@@ -21,7 +22,9 @@ module CabbageDoc
|
|
21
22
|
:user_agent,
|
22
23
|
:configurable,
|
23
24
|
:verbose,
|
24
|
-
:visibility
|
25
|
+
:visibility,
|
26
|
+
:tag,
|
27
|
+
:json
|
25
28
|
|
26
29
|
def initialize
|
27
30
|
Configuration.instance.tap do |config|
|
@@ -31,6 +34,8 @@ module CabbageDoc
|
|
31
34
|
@user_agent = config.title
|
32
35
|
@verbose = config.verbose
|
33
36
|
@visibility = config.visibility.dup
|
37
|
+
@tag = config.tags.first
|
38
|
+
@json = config.json
|
34
39
|
end
|
35
40
|
|
36
41
|
@subdomains = []
|
@@ -53,9 +58,9 @@ module CabbageDoc
|
|
53
58
|
def valid?
|
54
59
|
case type
|
55
60
|
when :basic
|
56
|
-
username && password
|
61
|
+
username && password && valid_subdomain?
|
57
62
|
else
|
58
|
-
!token.nil?
|
63
|
+
!token.nil? && valid_subdomain?
|
59
64
|
end
|
60
65
|
end
|
61
66
|
|
@@ -65,6 +70,10 @@ module CabbageDoc
|
|
65
70
|
|
66
71
|
private
|
67
72
|
|
73
|
+
def valid_subdomain?
|
74
|
+
!configurable.include?(:subdomain) || subdomain
|
75
|
+
end
|
76
|
+
|
68
77
|
def root_uri
|
69
78
|
if subdomain
|
70
79
|
"#{scheme}://#{subdomain}.#{domain}"
|
data/lib/cabbage_doc/client.rb
CHANGED
@@ -32,22 +32,26 @@ module CabbageDoc
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
def parse!(filename)
|
35
|
+
def parse!(filename, tag = TAG)
|
36
36
|
text = File.read(filename) rescue nil
|
37
37
|
return false unless text
|
38
38
|
|
39
|
-
controller = Controller.parse(text)
|
39
|
+
controller = Controller.parse(text, tag)
|
40
40
|
return false unless controller
|
41
41
|
|
42
|
-
controllers = controller.eval(text)
|
42
|
+
controllers = controller.eval(text, tag)
|
43
43
|
|
44
44
|
@_controllers.concat(controllers)
|
45
45
|
|
46
46
|
controllers.any?
|
47
47
|
end
|
48
48
|
|
49
|
-
def clear!
|
50
|
-
|
49
|
+
def clear!(tag = nil)
|
50
|
+
if tag && config.tags.size > 1
|
51
|
+
@_controllers.reject! { |controller| tag == controller.tag }
|
52
|
+
else
|
53
|
+
@_controllers = []
|
54
|
+
end
|
51
55
|
end
|
52
56
|
|
53
57
|
def load!
|
@@ -55,13 +59,26 @@ module CabbageDoc
|
|
55
59
|
end
|
56
60
|
|
57
61
|
def save!
|
62
|
+
sort!
|
58
63
|
open(filename, 'w') { |f| f.write(YAML.dump(@_controllers)) } rescue nil
|
59
64
|
end
|
60
65
|
|
61
66
|
private
|
62
67
|
|
68
|
+
def sort!
|
69
|
+
return unless config.tags.size > 1
|
70
|
+
|
71
|
+
@_controllers.sort! do |controller|
|
72
|
+
-config.tags.index(controller.tag)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def config
|
77
|
+
@_config ||= Configuration.instance
|
78
|
+
end
|
79
|
+
|
63
80
|
def filename
|
64
|
-
@_filename ||= Path.join(
|
81
|
+
@_filename ||= Path.join(config.root, FILENAME)
|
65
82
|
end
|
66
83
|
end
|
67
84
|
end
|
@@ -30,7 +30,8 @@ module CabbageDoc
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
DEFAULTS =
|
33
|
+
DEFAULTS =
|
34
|
+
{
|
34
35
|
path: 'api/v1',
|
35
36
|
title: 'Cabbage Doc',
|
36
37
|
scheme: 'https',
|
@@ -41,10 +42,18 @@ module CabbageDoc
|
|
41
42
|
request: proc { |request| request.perform },
|
42
43
|
theme: 'github',
|
43
44
|
examples: false,
|
44
|
-
format_example: method(:format_example)
|
45
|
+
format_example: method(:format_example),
|
46
|
+
page_root: 'pages',
|
47
|
+
page_ext: 'md',
|
48
|
+
auto_generate: true,
|
49
|
+
generators: [:api],
|
50
|
+
tags: [TAG],
|
51
|
+
json: false
|
45
52
|
}.freeze
|
46
53
|
|
47
|
-
OPTIONAL_ATTRIBUTES = %i(welcome path scheme title verbose authentication dev request cache
|
54
|
+
OPTIONAL_ATTRIBUTES = %i(welcome path scheme title verbose authentication dev request cache
|
55
|
+
theme visibility examples format_example page_root page_ext
|
56
|
+
asset_path auto_generate generators tags json).freeze
|
48
57
|
REQUIRED_ATTRIBUTES = %i(domain controllers root).freeze
|
49
58
|
ATTRIBUTES = (OPTIONAL_ATTRIBUTES + REQUIRED_ATTRIBUTES).freeze
|
50
59
|
CALLABLE_ATTRIBUTES = %i(controllers authentication request format_example).freeze
|
@@ -87,7 +96,8 @@ module CabbageDoc
|
|
87
96
|
def validate_visibility!
|
88
97
|
self.visibility = Array(visibility)
|
89
98
|
self.visibility.each do |v|
|
90
|
-
|
99
|
+
valid = VISIBILITY.include?(v) || tags.include?(v)
|
100
|
+
raise ArgumentError, "#{v} invalid visibility" unless valid
|
91
101
|
end
|
92
102
|
end
|
93
103
|
end
|
@@ -3,15 +3,16 @@ module CabbageDoc
|
|
3
3
|
include Parser
|
4
4
|
include Cloneable
|
5
5
|
|
6
|
-
attr_reader :label, :klass, :name, :path, :actions, :visibility
|
6
|
+
attr_reader :label, :klass, :name, :path, :actions, :visibility, :tag
|
7
7
|
|
8
|
-
def initialize
|
8
|
+
def initialize(tag = TAG)
|
9
9
|
@actions = []
|
10
10
|
@visibility = VISIBILITY.first
|
11
|
+
@tag = tag
|
11
12
|
end
|
12
13
|
|
13
|
-
def parse(text)
|
14
|
-
@label, @path, @klass, @visibility =
|
14
|
+
def parse(text, tag = TAG)
|
15
|
+
@label, @path, @klass, @visibility, @tag = parse_label_path_class_visibility_and_tag(text, tag)
|
15
16
|
return false unless @label && @klass
|
16
17
|
|
17
18
|
@name = compose_name(klass)
|
@@ -31,7 +32,7 @@ module CabbageDoc
|
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
34
|
-
def eval(text)
|
35
|
+
def eval(text, tag)
|
35
36
|
return [self] unless template?
|
36
37
|
|
37
38
|
templates = []
|
@@ -50,7 +51,7 @@ module CabbageDoc
|
|
50
51
|
template_text.gsub!(template[:text], template[:values].shift.to_s)
|
51
52
|
end
|
52
53
|
|
53
|
-
self.class.parse(template_text)
|
54
|
+
self.class.parse(template_text, tag)
|
54
55
|
end.compact
|
55
56
|
end
|
56
57
|
|
@@ -69,10 +70,14 @@ module CabbageDoc
|
|
69
70
|
end
|
70
71
|
|
71
72
|
def compose_visbility(metadata)
|
72
|
-
metadata[:visibility] ||
|
73
|
+
metadata[:visibility] || VISIBILITY.first
|
73
74
|
end
|
74
75
|
|
75
|
-
def
|
76
|
+
def compose_tag(metadata, tag = TAG)
|
77
|
+
metadata[:tag]&.to_sym || tag
|
78
|
+
end
|
79
|
+
|
80
|
+
def parse_label_path_class_visibility_and_tag(text, tag = TAG)
|
76
81
|
klass = parse_class(text)
|
77
82
|
return unless klass
|
78
83
|
|
@@ -82,7 +87,8 @@ module CabbageDoc
|
|
82
87
|
compose_label(metadata, klass),
|
83
88
|
compose_path(metadata, klass),
|
84
89
|
klass,
|
85
|
-
compose_visbility(metadata)
|
90
|
+
compose_visbility(metadata),
|
91
|
+
compose_tag(metadata, tag)
|
86
92
|
]
|
87
93
|
end
|
88
94
|
|
data/lib/cabbage_doc/example.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module CabbageDoc
|
2
|
-
class
|
2
|
+
class Generator
|
3
3
|
class Error < StandardError; end
|
4
4
|
class InvalidType < Error; end
|
5
5
|
class InvalidPriority < Error; end
|
@@ -11,6 +11,14 @@ module CabbageDoc
|
|
11
11
|
all[klass.to_s.split('::').last.downcase.to_sym] = klass
|
12
12
|
end
|
13
13
|
|
14
|
+
def tags(value = nil)
|
15
|
+
if value.nil?
|
16
|
+
@_tags
|
17
|
+
else
|
18
|
+
@_tags = !!value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
14
22
|
def priority(value = nil)
|
15
23
|
if value.is_a?(Symbol)
|
16
24
|
raise InvalidPriority, value unless PRIORITIES.include?(value)
|
@@ -24,40 +32,48 @@ module CabbageDoc
|
|
24
32
|
@_all ||= {}
|
25
33
|
end
|
26
34
|
|
27
|
-
def
|
28
|
-
|
35
|
+
def supports?(type, what)
|
36
|
+
!!find(type).public_send(what)
|
37
|
+
end
|
29
38
|
|
30
|
-
|
31
|
-
|
39
|
+
def exists?(type)
|
40
|
+
all.has_key?(type)
|
41
|
+
end
|
42
|
+
|
43
|
+
def perform(type, tag = nil)
|
44
|
+
if type == :all
|
45
|
+
all.map { |_, klass| klass.new(tag).perform }
|
32
46
|
else
|
33
|
-
|
47
|
+
find(type).new(tag).perform
|
34
48
|
end
|
35
49
|
end
|
36
50
|
|
51
|
+
def find(type)
|
52
|
+
klass = all[type]
|
53
|
+
|
54
|
+
raise InvalidType, type unless klass
|
55
|
+
|
56
|
+
klass
|
57
|
+
end
|
58
|
+
|
37
59
|
def load!
|
38
|
-
Dir.glob(File.join(File.dirname(__FILE__), '
|
39
|
-
require(
|
60
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'generators', '*.rb')).sort.each do |generator|
|
61
|
+
require(generator)
|
40
62
|
end
|
41
63
|
end
|
42
64
|
end
|
43
65
|
|
44
|
-
|
45
|
-
raise NotImplementedError
|
46
|
-
end
|
47
|
-
|
48
|
-
protected
|
66
|
+
attr_accessor :tag
|
49
67
|
|
50
|
-
def
|
51
|
-
|
68
|
+
def initialize(tag = nil)
|
69
|
+
self.tag = tag
|
52
70
|
end
|
53
71
|
|
54
|
-
def
|
55
|
-
|
72
|
+
def perform
|
73
|
+
raise NotImplementedError
|
56
74
|
end
|
57
75
|
|
58
|
-
|
59
|
-
@_auth ||= Authentication.new
|
60
|
-
end
|
76
|
+
protected
|
61
77
|
|
62
78
|
def collection
|
63
79
|
@_collection ||= Collection.instance.tap do |collection|
|
@@ -65,10 +81,14 @@ module CabbageDoc
|
|
65
81
|
end
|
66
82
|
end
|
67
83
|
|
84
|
+
def controllers
|
85
|
+
@_controllers ||= config.controllers.call
|
86
|
+
end
|
87
|
+
|
68
88
|
def config
|
69
89
|
@_config ||= Configuration.instance
|
70
90
|
end
|
71
91
|
end
|
72
92
|
|
73
|
-
|
93
|
+
Generator.load!
|
74
94
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module CabbageDoc
|
2
|
+
module Generators
|
3
|
+
class Api < Generator
|
4
|
+
priority :high
|
5
|
+
tags true
|
6
|
+
|
7
|
+
def perform
|
8
|
+
collection.clear!(tag)
|
9
|
+
|
10
|
+
if controllers.is_a?(Hash)
|
11
|
+
parse_with_tag!
|
12
|
+
else
|
13
|
+
parse_without_tag!
|
14
|
+
end
|
15
|
+
|
16
|
+
collection.save!
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def parse_with_tag!
|
22
|
+
controllers.each do |tag, filenames|
|
23
|
+
next if self.tag && self.tag != tag
|
24
|
+
next unless filenames.respond_to?(:call)
|
25
|
+
|
26
|
+
filenames.call.each do |filename|
|
27
|
+
collection.parse!(filename, tag)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_without_tag!
|
33
|
+
controllers.each do |filename|
|
34
|
+
collection.parse!(filename)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module CabbageDoc
|
2
|
+
module Generators
|
3
|
+
class Pages < Generator
|
4
|
+
priority :low
|
5
|
+
|
6
|
+
def perform
|
7
|
+
pages.each do |file|
|
8
|
+
generate(file)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def generate(file)
|
15
|
+
open(file.sub(/#{config.page_ext}$/, 'html'), 'w') do |f|
|
16
|
+
f.write(helper.markdown.render(File.read(file)))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def pages
|
21
|
+
@_pages ||= Dir.glob(File.join(config.root, config.page_root, "*.#{config.page_ext}"))
|
22
|
+
end
|
23
|
+
|
24
|
+
class Helper
|
25
|
+
include CabbageDoc::WebHelper
|
26
|
+
end
|
27
|
+
|
28
|
+
def helper
|
29
|
+
@_helper ||= Helper.new
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/cabbage_doc/params.rb
CHANGED
@@ -2,6 +2,10 @@ module CabbageDoc
|
|
2
2
|
class Params
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
+
ACTION = '__action'.freeze
|
6
|
+
METHOD = '__method'.freeze
|
7
|
+
TAG = '__tag'.freeze
|
8
|
+
|
5
9
|
def initialize(params, collection)
|
6
10
|
@_params = convert(params, collection)
|
7
11
|
end
|
@@ -41,8 +45,8 @@ module CabbageDoc
|
|
41
45
|
private
|
42
46
|
|
43
47
|
def convert(params, collection)
|
44
|
-
method = params[
|
45
|
-
action = params[
|
48
|
+
method = params[METHOD]
|
49
|
+
action = params[ACTION]
|
46
50
|
|
47
51
|
return {} unless action && method
|
48
52
|
|
data/lib/cabbage_doc/parser.rb
CHANGED
@@ -7,13 +7,13 @@ module CabbageDoc
|
|
7
7
|
end
|
8
8
|
|
9
9
|
module ClassMethods
|
10
|
-
def parse(text)
|
10
|
+
def parse(text, tag = TAG)
|
11
11
|
instance = new
|
12
|
-
instance if instance.parse(text)
|
12
|
+
instance if instance.parse(text, tag)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def parse(text)
|
16
|
+
def parse(text, tag = TAG)
|
17
17
|
raise NotImplementedError
|
18
18
|
end
|
19
19
|
|
data/lib/cabbage_doc/request.rb
CHANGED
@@ -9,11 +9,11 @@ module CabbageDoc
|
|
9
9
|
attr_reader :raw_request, :collection
|
10
10
|
|
11
11
|
class << self
|
12
|
-
def parse(s)
|
12
|
+
def parse(s, tag = TAG)
|
13
13
|
variables = YAML.load(s)
|
14
14
|
|
15
15
|
new(OpenStruct.new(params: {}, env: {}), Collection.instance).tap do |instance|
|
16
|
-
[:@_id, :@_auth, :@_action, :@_method, :@_params].each_with_index do |k, i|
|
16
|
+
[:@_id, :@_auth, :@_action, :@_method, :@_tag, :@_params].each_with_index do |k, i|
|
17
17
|
instance.instance_variable_set(k, variables[i])
|
18
18
|
end
|
19
19
|
end
|
@@ -30,7 +30,7 @@ module CabbageDoc
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def valid?
|
33
|
-
action && method && METHODS.include?(method)
|
33
|
+
action && method && METHODS.include?(method) && auth.valid?
|
34
34
|
end
|
35
35
|
|
36
36
|
def to_yaml
|
@@ -39,6 +39,7 @@ module CabbageDoc
|
|
39
39
|
auth,
|
40
40
|
action,
|
41
41
|
method,
|
42
|
+
tag,
|
42
43
|
params
|
43
44
|
])
|
44
45
|
end
|
@@ -56,7 +57,11 @@ module CabbageDoc
|
|
56
57
|
|
57
58
|
def perform_request
|
58
59
|
key = (method == :get) ? :query : :body
|
59
|
-
|
60
|
+
|
61
|
+
data = params.to_hash
|
62
|
+
data = data.to_json if key == :body && auth.json
|
63
|
+
|
64
|
+
client.public_send(method, action, key => data)
|
60
65
|
end
|
61
66
|
|
62
67
|
def url
|
@@ -64,11 +69,15 @@ module CabbageDoc
|
|
64
69
|
end
|
65
70
|
|
66
71
|
def action
|
67
|
-
@_action ||= compose_action(raw_request.params[
|
72
|
+
@_action ||= compose_action(raw_request.params[Params::ACTION])
|
68
73
|
end
|
69
74
|
|
70
75
|
def method
|
71
|
-
@_method ||= compose_method(raw_request.params[
|
76
|
+
@_method ||= compose_method(raw_request.params[Params::METHOD])
|
77
|
+
end
|
78
|
+
|
79
|
+
def tag
|
80
|
+
@_tag ||= compose_tag(raw_request.params[Params::TAG])
|
72
81
|
end
|
73
82
|
|
74
83
|
def compose_method(method)
|
@@ -90,12 +99,20 @@ module CabbageDoc
|
|
90
99
|
action
|
91
100
|
end
|
92
101
|
|
102
|
+
def compose_tag(tag)
|
103
|
+
if tag
|
104
|
+
tag.downcase.to_sym
|
105
|
+
else
|
106
|
+
TAG
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
93
110
|
def params
|
94
111
|
@_params ||= Params.new(raw_params, collection)
|
95
112
|
end
|
96
113
|
|
97
114
|
def auth
|
98
|
-
@_auth ||= Authentication.new(raw_request)
|
115
|
+
@_auth ||= Authentication.new(raw_request, tag)
|
99
116
|
end
|
100
117
|
|
101
118
|
def raw_params
|
data/lib/cabbage_doc/response.rb
CHANGED
data/lib/cabbage_doc/task.rb
CHANGED
@@ -3,7 +3,7 @@ require 'rake/tasklib'
|
|
3
3
|
|
4
4
|
module CabbageDoc
|
5
5
|
class Task < Rake::TaskLib
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :generators, :tags, :name, :customize
|
7
7
|
|
8
8
|
def self.define
|
9
9
|
new.tap do |instance|
|
@@ -15,45 +15,77 @@ module CabbageDoc
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def initialize
|
18
|
-
|
19
|
-
|
18
|
+
self.generators = config.generators.dup
|
19
|
+
self.tags = config.tags.dup
|
20
|
+
self.name = :cabbagedoc
|
21
|
+
self.customize = true
|
22
|
+
end
|
23
|
+
|
24
|
+
def config
|
25
|
+
@_config ||= Configuration.instance
|
20
26
|
end
|
21
27
|
|
22
28
|
def sort!
|
23
|
-
|
29
|
+
generators.sort! { |generator| Generator::PRIORITIES.index(Generator.all[generator].priority) }
|
24
30
|
end
|
25
31
|
|
26
32
|
def define!
|
27
33
|
namespace name do
|
28
|
-
|
29
|
-
|
30
|
-
namespace :process do
|
31
|
-
task processor.to_s => :environment do
|
32
|
-
Processor.all[processor].new.perform
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
desc "Customize Web UI"
|
38
|
-
task :customize => :environment do
|
39
|
-
Customizer.new.perform
|
40
|
-
end
|
34
|
+
define_generators!
|
35
|
+
define_customizer!
|
41
36
|
end
|
42
37
|
|
43
|
-
desc "Run all
|
38
|
+
desc "Run all generators"
|
44
39
|
task name => :environment do
|
45
|
-
|
46
|
-
|
40
|
+
generators.each do |type|
|
41
|
+
Generator.perform(type)
|
47
42
|
end
|
48
43
|
end
|
49
44
|
end
|
50
45
|
|
51
46
|
def validate!
|
52
47
|
fail "Invalid 'name'" unless name.is_a?(Symbol)
|
53
|
-
fail "No '
|
48
|
+
fail "No 'generators' configured" unless generators.any?
|
49
|
+
|
50
|
+
generators.each do |generator|
|
51
|
+
fail "Invalid 'generator' #{generator}" unless Generator.exists?(generator)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def define_generators!
|
58
|
+
generators.each do |type|
|
59
|
+
desc "Generate #{type}"
|
60
|
+
task type => :environment do
|
61
|
+
Generator.perform(type)
|
62
|
+
end
|
63
|
+
|
64
|
+
define_generators_by_tag!(type)
|
65
|
+
define_customizer!
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def define_generators_by_tag!(type)
|
70
|
+
return unless Generator.supports?(type, :tags)
|
71
|
+
return unless tags.size > 1
|
72
|
+
|
73
|
+
namespace type do
|
74
|
+
tags.each do |tag|
|
75
|
+
desc "Generate #{type} for #{tag}"
|
76
|
+
task tag => :environment do
|
77
|
+
Generator.perform(type, tag)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def define_customizer!
|
84
|
+
return unless customize
|
54
85
|
|
55
|
-
|
56
|
-
|
86
|
+
desc "Customize Web UI"
|
87
|
+
task :customize => :environment do
|
88
|
+
Customizer.new.perform
|
57
89
|
end
|
58
90
|
end
|
59
91
|
end
|
data/lib/cabbage_doc/version.rb
CHANGED
data/lib/cabbage_doc/web.rb
CHANGED
@@ -36,12 +36,12 @@ module CabbageDoc
|
|
36
36
|
haml :index
|
37
37
|
end
|
38
38
|
|
39
|
-
get '/:id' do
|
39
|
+
get '/api/:id' do
|
40
40
|
response_by_id(params[:id])
|
41
41
|
end
|
42
42
|
|
43
|
-
post '/' do
|
44
|
-
response =
|
43
|
+
post '/api' do
|
44
|
+
response = config.request.call(post_request) if post_request.valid?
|
45
45
|
|
46
46
|
if response.is_a?(Response)
|
47
47
|
content_type :json
|
@@ -52,5 +52,19 @@ module CabbageDoc
|
|
52
52
|
halt 500
|
53
53
|
end
|
54
54
|
end
|
55
|
+
|
56
|
+
get '/:slug' do
|
57
|
+
slug = params[:slug].to_s.gsub(/[^a-z\-_]/, '')
|
58
|
+
filename = File.join(config.root, config.page_root, "#{slug}.html") unless slug.empty?
|
59
|
+
|
60
|
+
content = if !filename.empty? && File.exists?(filename)
|
61
|
+
File.read(filename)
|
62
|
+
else
|
63
|
+
status 404
|
64
|
+
"Page not found."
|
65
|
+
end
|
66
|
+
|
67
|
+
haml :page, layout: :page_layout, locals: { content: content }
|
68
|
+
end
|
55
69
|
end
|
56
70
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
require 'redcarpet'
|
2
|
+
|
1
3
|
module CabbageDoc
|
2
4
|
module WebHelper
|
3
5
|
def asset_path(path)
|
4
|
-
[request.path, path].join('/').gsub(/\/\/+/, '/')
|
6
|
+
[config.asset_path || request.path, path].join('/').gsub(/\/\/+/, '/')
|
5
7
|
end
|
6
8
|
|
7
9
|
def theme_path
|
@@ -13,8 +15,8 @@ module CabbageDoc
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def collection
|
16
|
-
if config.dev
|
17
|
-
|
18
|
+
if config.dev && config.auto_generate
|
19
|
+
Generator.perform(:all)
|
18
20
|
@_collection = nil
|
19
21
|
end
|
20
22
|
|
@@ -44,10 +46,18 @@ module CabbageDoc
|
|
44
46
|
auth.visibility.include?(o.visibility)
|
45
47
|
end
|
46
48
|
|
49
|
+
def tag_visible?(tag)
|
50
|
+
config.tags.size <= 1 || auth.visibility.include?(tag)
|
51
|
+
end
|
52
|
+
|
47
53
|
def format_visibility(o)
|
48
54
|
o.visibility.to_s.capitalize if o.visibility != VISIBILITY.first
|
49
55
|
end
|
50
56
|
|
57
|
+
def format_tag(tag)
|
58
|
+
tag.to_s.capitalize
|
59
|
+
end
|
60
|
+
|
51
61
|
def post_request
|
52
62
|
@_post_request ||= Request.new(request, collection)
|
53
63
|
end
|
@@ -1,9 +1,3 @@
|
|
1
|
-
body
|
2
|
-
{
|
3
|
-
margin: 0;
|
4
|
-
padding: 0;
|
5
|
-
}
|
6
|
-
|
7
1
|
pre, code, .authentication form
|
8
2
|
{
|
9
3
|
font-family: monospace;
|
@@ -32,18 +26,6 @@ input[type=button], input[type=submit]
|
|
32
26
|
min-width: 98px;
|
33
27
|
}
|
34
28
|
|
35
|
-
a, a:active, a:visited, a:hover
|
36
|
-
{
|
37
|
-
color: #000000;
|
38
|
-
text-decoration: none;
|
39
|
-
font-weight: bold;
|
40
|
-
}
|
41
|
-
|
42
|
-
a:hover
|
43
|
-
{
|
44
|
-
text-decoration: underline;
|
45
|
-
}
|
46
|
-
|
47
29
|
.hidden
|
48
30
|
{
|
49
31
|
display: none !important;
|
@@ -70,13 +52,7 @@ a:hover
|
|
70
52
|
float: right;
|
71
53
|
}
|
72
54
|
|
73
|
-
.
|
74
|
-
{
|
75
|
-
margin: 10px auto;
|
76
|
-
width: 1024px;
|
77
|
-
}
|
78
|
-
|
79
|
-
.welcome, .documentation, .authentication
|
55
|
+
.welcome, .api, .authentication
|
80
56
|
{
|
81
57
|
width: 100%;
|
82
58
|
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
body
|
2
|
+
{
|
3
|
+
margin: 0;
|
4
|
+
padding: 0;
|
5
|
+
}
|
6
|
+
|
7
|
+
a, a:active, a:visited, a:hover
|
8
|
+
{
|
9
|
+
color: #000000;
|
10
|
+
text-decoration: none;
|
11
|
+
font-weight: bold;
|
12
|
+
}
|
13
|
+
|
14
|
+
a:hover
|
15
|
+
{
|
16
|
+
text-decoration: underline;
|
17
|
+
}
|
18
|
+
|
19
|
+
.application, .page
|
20
|
+
{
|
21
|
+
margin: 10px auto;
|
22
|
+
width: 1024px;
|
23
|
+
}
|
@@ -116,8 +116,9 @@ $(document).ready(function()
|
|
116
116
|
|
117
117
|
var data = $('.authentication form').serializeArray().concat(form.serializeArray());
|
118
118
|
|
119
|
-
data.push({'name': '
|
120
|
-
data.push({'name': '
|
119
|
+
data.push({'name': '__method', 'value': form.attr('method') || ''});
|
120
|
+
data.push({'name': '__action', 'value': form.attr('action') || ''});
|
121
|
+
data.push({'name': '__tag', 'value': form.attr('data-tag') || 'api'});
|
121
122
|
|
122
123
|
data = $.grep(data, function(v, i)
|
123
124
|
{
|
@@ -144,7 +145,7 @@ $(document).ready(function()
|
|
144
145
|
|
145
146
|
setTimeout(function()
|
146
147
|
{
|
147
|
-
$.ajax(compose_path('/' + id), {
|
148
|
+
$.ajax(compose_path('/api/' + id), {
|
148
149
|
method: 'GET',
|
149
150
|
dataType: 'json',
|
150
151
|
complete: function(data)
|
@@ -158,7 +159,7 @@ $(document).ready(function()
|
|
158
159
|
}, 1000);
|
159
160
|
}
|
160
161
|
|
161
|
-
$.ajax(compose_path('/'), {
|
162
|
+
$.ajax(compose_path('/api'), {
|
162
163
|
data: $.param(data),
|
163
164
|
method: 'POST',
|
164
165
|
dataType: 'json',
|
@@ -167,7 +168,7 @@ $(document).ready(function()
|
|
167
168
|
var json = data.responseJSON || {};
|
168
169
|
|
169
170
|
if(data.status == 503 && typeof json.id != 'undefined')
|
170
|
-
retry_later(form, json.id,
|
171
|
+
retry_later(form, json.id, 5);
|
171
172
|
else
|
172
173
|
display_response(form, data);
|
173
174
|
}
|
data/web/views/action.haml
CHANGED
@@ -6,10 +6,10 @@
|
|
6
6
|
%span= " : #{action.label}"
|
7
7
|
%span.visibility= format_visibility(action)
|
8
8
|
.clear
|
9
|
-
%form.hidden{ action: action.path, method: action.method }
|
9
|
+
%form.hidden{ action: action.path, method: action.method, :'data-tag' => tag }
|
10
10
|
- if action.description
|
11
11
|
.description= markdown.render(action.description)
|
12
|
-
- if action.visibility
|
12
|
+
- if %i(unreleased beta).include?(action.visibility)
|
13
13
|
.warning= 'This API is still under development and will continue to evolve.'
|
14
14
|
- if config.examples && action.examples.any?
|
15
15
|
.examples
|
@@ -24,4 +24,4 @@
|
|
24
24
|
%th='Description'
|
25
25
|
- action.parameters.each do |parameter|
|
26
26
|
= haml :parameter, locals: { parameter: parameter }
|
27
|
-
|
27
|
+
= haml :response
|
data/web/views/api.haml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
.controllers
|
2
|
+
- if config.tags.size > 1
|
3
|
+
- grouped = collection.group_by(&:tag)
|
4
|
+
- config.tags.each { |tag| grouped.delete(tag) unless tag_visible?(tag) }
|
5
|
+
- if grouped.size > 1
|
6
|
+
- collection.group_by(&:tag).each do |tag, controllers|
|
7
|
+
.tag
|
8
|
+
.resource
|
9
|
+
= format_tag(tag)
|
10
|
+
= haml :controllers, locals: { controllers: controllers }
|
11
|
+
- else
|
12
|
+
= haml :controllers, locals: { controllers: grouped.values.first }
|
13
|
+
- else
|
14
|
+
= haml :controllers, locals: { controllers: collection }
|
data/web/views/controller.haml
CHANGED
data/web/views/index.haml
CHANGED
data/web/views/layout.haml
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
%html
|
3
3
|
%head
|
4
4
|
%link{ rel: :stylesheet, href: theme_path, type: 'text/css' }
|
5
|
+
%link{ rel: :stylesheet, href: asset_path('css/base.css'), type: 'text/css' }
|
5
6
|
%link{ rel: :stylesheet, href: asset_path('css/application.css'), type: 'text/css' }
|
6
7
|
%script{ src: asset_path('js/jquery-1.12.3.min.js'), type: 'text/javascript' }
|
7
8
|
%script{ src: asset_path('js/highlight.min.js'), type: 'text/javascript' }
|
data/web/views/page.haml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
= markdown.render(content) unless content.empty?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cabbage_doc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mihail Szabolcs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redcarpet
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: haml
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: sinatra
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -139,12 +153,13 @@ files:
|
|
139
153
|
- lib/cabbage_doc/controller.rb
|
140
154
|
- lib/cabbage_doc/customizer.rb
|
141
155
|
- lib/cabbage_doc/example.rb
|
156
|
+
- lib/cabbage_doc/generator.rb
|
157
|
+
- lib/cabbage_doc/generators/api.rb
|
158
|
+
- lib/cabbage_doc/generators/pages.rb
|
142
159
|
- lib/cabbage_doc/parameter.rb
|
143
160
|
- lib/cabbage_doc/params.rb
|
144
161
|
- lib/cabbage_doc/parser.rb
|
145
162
|
- lib/cabbage_doc/path.rb
|
146
|
-
- lib/cabbage_doc/processor.rb
|
147
|
-
- lib/cabbage_doc/processors/documentation.rb
|
148
163
|
- lib/cabbage_doc/request.rb
|
149
164
|
- lib/cabbage_doc/response.rb
|
150
165
|
- lib/cabbage_doc/singleton.rb
|
@@ -155,6 +170,7 @@ files:
|
|
155
170
|
- lib/cabbage_doc/worker.rb
|
156
171
|
- web/helpers/helper.rb
|
157
172
|
- web/public/css/application.css
|
173
|
+
- web/public/css/base.css
|
158
174
|
- web/public/css/highlight/agate.css
|
159
175
|
- web/public/css/highlight/androidstudio.css
|
160
176
|
- web/public/css/highlight/arduino-light.css
|
@@ -194,14 +210,17 @@ files:
|
|
194
210
|
- web/public/js/highlight.min.js
|
195
211
|
- web/public/js/jquery-1.12.3.min.js
|
196
212
|
- web/views/action.haml
|
213
|
+
- web/views/api.haml
|
197
214
|
- web/views/array.haml
|
198
215
|
- web/views/authentication.haml
|
199
216
|
- web/views/controller.haml
|
200
|
-
- web/views/
|
217
|
+
- web/views/controllers.haml
|
201
218
|
- web/views/enumeration.haml
|
202
219
|
- web/views/example.haml
|
203
220
|
- web/views/index.haml
|
204
221
|
- web/views/layout.haml
|
222
|
+
- web/views/page.haml
|
223
|
+
- web/views/page_layout.haml
|
205
224
|
- web/views/parameter.haml
|
206
225
|
- web/views/response.haml
|
207
226
|
- web/views/text.haml
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module CabbageDoc
|
2
|
-
module Processors
|
3
|
-
class Documentation < Processor
|
4
|
-
priority :high
|
5
|
-
|
6
|
-
def perform
|
7
|
-
collection.clear!
|
8
|
-
|
9
|
-
config.controllers.call.each do |filename|
|
10
|
-
collection.parse!(filename)
|
11
|
-
end
|
12
|
-
|
13
|
-
collection.save!
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|