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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 91e6336597672b91cdc338a24ad44aa2856e8cfa
4
- data.tar.gz: 1ccc5abce46f5a6a37dae2665c9def1fcce02130
3
+ metadata.gz: 7bdad905798e6ed0c5e62b8ec075359acf0eb78c
4
+ data.tar.gz: 40c4b70fdaebe890f108ecd2cfc94c8e82608782
5
5
  SHA512:
6
- metadata.gz: 4474ce6a1de2aaecfc981d344cafe6ebe794d0d4f2dfd9ead19a9d970caeb1e4dd5f18045d2211d0d40b8f5c0e89eaedb06ba978bd5453c13fb54f4ca3b8a86a
7
- data.tar.gz: 55d173af4aed9f1cef47583c9b63def698741f3b173b28fd99fb6ba21f1b57fb98603da7e23b1aa7f0fc99c2c7f32c6e1c21eada54673ead26d831462eb4b013
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 :Processor, 'cabbage_doc/processor'
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
@@ -13,7 +13,7 @@ module CabbageDoc
13
13
  @visibility = VISIBILITY.first
14
14
  end
15
15
 
16
- def parse(text)
16
+ def parse(text, tag = TAG)
17
17
  @method, @path = parse_method_and_path(text)
18
18
  return unless valid?
19
19
 
@@ -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}"
@@ -1,3 +1,5 @@
1
+ require 'httparty'
2
+
1
3
  module CabbageDoc
2
4
  class Client
3
5
  include HTTParty
@@ -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
- @_controllers = []
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(Configuration.instance.root, FILENAME)
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 theme visibility examples format_example).freeze
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
- raise ArgumentError, "#{v} invalid visibility" unless VISIBILITY.include?(v)
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 = parse_label_path_class_and_visibility(text)
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] || :public
73
+ metadata[:visibility] || VISIBILITY.first
73
74
  end
74
75
 
75
- def parse_label_path_class_and_visibility(text)
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
 
@@ -10,7 +10,7 @@ module CabbageDoc
10
10
  @params = {}
11
11
  end
12
12
 
13
- def parse(text)
13
+ def parse(text, tag = TAG)
14
14
  m = text.match(/^(.*?)\s+-\s+(\(.*?\))$/)
15
15
  return false unless m
16
16
 
@@ -1,5 +1,5 @@
1
1
  module CabbageDoc
2
- class Processor
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 perform(type)
28
- klass = all[type]
35
+ def supports?(type, what)
36
+ !!find(type).public_send(what)
37
+ end
29
38
 
30
- if klass
31
- klass.new.perform
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
- raise InvalidType, type
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__), 'processors', '*.rb')).sort.each do |processor|
39
- require(processor)
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
- def perform
45
- raise NotImplementedError
46
- end
47
-
48
- protected
66
+ attr_accessor :tag
49
67
 
50
- def cache
51
- @_cache ||= Cache.new
68
+ def initialize(tag = nil)
69
+ self.tag = tag
52
70
  end
53
71
 
54
- def client
55
- @_client ||= Client.new(auth)
72
+ def perform
73
+ raise NotImplementedError
56
74
  end
57
75
 
58
- def auth
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
- Processor.load!
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
@@ -10,7 +10,7 @@ module CabbageDoc
10
10
  @values = []
11
11
  end
12
12
 
13
- def parse(text)
13
+ def parse(text, tag = TAG)
14
14
  m = text.match(/^(.*?\s+\(.*?\).*?)\s+-\s+(.*?)$/)
15
15
  return false unless m
16
16
 
@@ -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['method']
45
- action = params['action']
48
+ method = params[METHOD]
49
+ action = params[ACTION]
46
50
 
47
51
  return {} unless action && method
48
52
 
@@ -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
 
@@ -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
- client.send(method, action, key => params.to_hash)
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['action'])
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['method'])
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
@@ -5,7 +5,7 @@ module CabbageDoc
5
5
  attr_reader :url, :headers, :params, :code, :body
6
6
 
7
7
  class << self
8
- def parse(s)
8
+ def parse(s, tag = TAG)
9
9
  YAML.load(s)
10
10
  end
11
11
  end
@@ -3,7 +3,7 @@ require 'rake/tasklib'
3
3
 
4
4
  module CabbageDoc
5
5
  class Task < Rake::TaskLib
6
- attr_accessor :processors, :name
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
- @processors = [:documentation]
19
- @name = :cabbagedoc
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
- processors.sort! { |processor| Processor::PRIORITIES.index(Processor.all[processor].priority) }
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
- processors.each do |processor|
29
- desc "Process #{processor}"
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 processors"
38
+ desc "Run all generators"
44
39
  task name => :environment do
45
- processors.each do |name|
46
- Processor.all[name].new.perform
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 'processors' configured" unless processors.any?
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
- processors.each do |processor|
56
- fail "Invalid 'processor' #{processor}" unless Processor.all.has_key?(processor)
86
+ desc "Customize Web UI"
87
+ task :customize => :environment do
88
+ Customizer.new.perform
57
89
  end
58
90
  end
59
91
  end
@@ -1,3 +1,3 @@
1
1
  module CabbageDoc
2
- VERSION = "0.0.7".freeze
2
+ VERSION = "0.0.8".freeze
3
3
  end
@@ -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 = Configuration.instance.request.call(post_request) if post_request.valid?
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
- Processor.perform(:documentation)
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
- .application
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': 'method', 'value': form.attr('method') || ''});
120
- data.push({'name': 'action', 'value': form.attr('action') || ''});
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, 30);
171
+ retry_later(form, json.id, 5);
171
172
  else
172
173
  display_response(form, data);
173
174
  }
@@ -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 == :beta
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
- = haml :response
27
+ = haml :response
@@ -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 }
@@ -7,4 +7,4 @@
7
7
  .actions.hidden
8
8
  - controller.actions.each do |action|
9
9
  - if visible?(action)
10
- = haml :action, locals: { action: action }
10
+ = haml :action, locals: { action: action, tag: controller.tag }
@@ -0,0 +1,3 @@
1
+ - controllers.each do |controller|
2
+ - if visible?(controller)
3
+ = haml :controller, locals: { controller: controller }
data/web/views/index.haml CHANGED
@@ -1,8 +1,11 @@
1
+ .title
2
+ %h1=title
3
+
1
4
  .welcome
2
5
  = haml :welcome
3
6
 
4
7
  .authentication
5
8
  = haml :authentication
6
9
 
7
- .documentation
8
- = haml :documentation
10
+ .api
11
+ = haml :api
@@ -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' }
@@ -0,0 +1 @@
1
+ = markdown.render(content) unless content.empty?
@@ -0,0 +1,13 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %link{ rel: :stylesheet, href: asset_path('css/base.css'), type: 'text/css' }
5
+
6
+ %title= title
7
+ %body
8
+ .page
9
+ .title
10
+ %h1=title
11
+ %a{href: '/'}="&lt; Back"
12
+ .body
13
+ = yield
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.7
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: 2016-11-03 00:00:00.000000000 Z
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/documentation.haml
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
@@ -1,4 +0,0 @@
1
- .controllers
2
- - collection.each do |controller|
3
- - if visible?(controller)
4
- = haml :controller, locals: { controller: controller }