cabbage_doc 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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 }