calamum 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/calamum +3 -3
- data/lib/calamum.rb +13 -7
- data/lib/calamum/config.rb +15 -7
- data/lib/calamum/doc_generator.rb +20 -49
- data/lib/calamum/doc_parser.rb +49 -0
- data/lib/calamum/helpers.rb +31 -0
- data/lib/calamum/resource.rb +47 -0
- data/lib/calamum/runner.rb +82 -57
- data/lib/calamum/templates/bootstrap/assets/stylesheets/main.css +15 -0
- data/lib/calamum/templates/bootstrap/index.html.erb +12 -8
- data/lib/calamum/templates/twitter/assets/css/main.css +1055 -0
- data/lib/calamum/templates/twitter/assets/javascripts/bootstrap.js +2276 -0
- data/lib/calamum/templates/twitter/assets/javascripts/jquery-1.7.2.min.js +4 -0
- data/lib/calamum/templates/twitter/index.html.erb +63 -0
- data/lib/calamum/templates/twitter/view.html.erb +94 -0
- data/lib/calamum/version.rb +1 -1
- metadata +19 -64
- data/.gitignore +0 -18
- data/Gemfile +0 -5
- data/Gemfile.lock +0 -44
- data/LICENSE.txt +0 -7
- data/README.md +0 -39
- data/Rakefile +0 -0
- data/calamum.gemspec +0 -25
- data/lib/calamum/calamum_helper.rb +0 -10
- data/lib/calamum/definition_parser.rb +0 -75
- data/lib/calamum/request.rb +0 -40
- data/sample/sample.yml +0 -83
- data/spec/data/my_definition.yml +0 -41
- data/spec/definition_parser_spec.rb +0 -17
- data/spec/request_spec.rb +0 -13
- data/spec/spec_helper.rb +0 -3
data/bin/calamum
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
#
|
3
|
-
#
|
4
|
-
|
5
|
-
$: << File.join(File.dirname(__FILE__),
|
3
|
+
# Calamum is a simple REST API documentation generator.
|
4
|
+
# This is a fork, that allows you to work with JSON format.
|
5
|
+
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
6
6
|
|
7
7
|
require 'rubygems'
|
8
8
|
require 'calamum/runner'
|
data/lib/calamum.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'yajl'
|
1
3
|
require 'yaml'
|
4
|
+
require 'fileutils'
|
2
5
|
require 'pry'
|
3
|
-
|
4
|
-
|
5
|
-
require 'calamum/
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
6
|
+
|
7
|
+
module Calamum
|
8
|
+
require 'calamum/config'
|
9
|
+
require 'calamum/helpers'
|
10
|
+
require 'calamum/resource'
|
11
|
+
require 'calamum/doc_parser'
|
12
|
+
require 'calamum/doc_generator'
|
13
|
+
require 'calamum/version'
|
14
|
+
VALID_TEMPLATES = %{twitter bootstrap}
|
15
|
+
end
|
data/lib/calamum/config.rb
CHANGED
@@ -1,13 +1,21 @@
|
|
1
1
|
require 'calamum'
|
2
2
|
require 'mixlib/config'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
# Provides a class-based configuration object.
|
5
|
+
# See https://github.com/opscode/mixlib-config
|
6
|
+
class Calamum::Config
|
7
|
+
extend Mixlib::Config
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def self.inspect
|
10
|
+
configuration.inspect
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.apply(config)
|
14
|
+
merge!(config)
|
15
|
+
|
16
|
+
self.doc_path = File.join(config[:path], 'docs')
|
17
|
+
self.tpl_path = File.join(File.dirname(__FILE__), 'templates', config[:template])
|
18
|
+
raise "Unknown template #{config[:template]}" unless Calamum::VALID_TEMPLATES.include?(config[:template])
|
19
|
+
end
|
11
20
|
|
12
|
-
end
|
13
21
|
end
|
@@ -1,62 +1,33 @@
|
|
1
|
-
|
2
1
|
class Calamum::DocGenerator
|
3
|
-
|
4
|
-
attr_accessor :resources, :template, :name, :url, :description
|
2
|
+
attr_accessor :template
|
5
3
|
|
6
|
-
def initialize(
|
7
|
-
|
8
|
-
|
9
|
-
@name = name
|
10
|
-
@url = url
|
11
|
-
@description = descr
|
12
|
-
end
|
4
|
+
def initialize(tpl_name)
|
5
|
+
tpl_path = Calamum::Config[:tpl_path]
|
6
|
+
filename = "#{tpl_path}/#{tpl_name}.html.erb"
|
13
7
|
|
14
|
-
|
15
|
-
ERB.new(@template).result(binding)
|
8
|
+
@template = ERB.new(File.read(filename))
|
16
9
|
end
|
17
10
|
|
18
|
-
def self.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
initialize_doc_dir
|
24
|
-
File.open(file, "w+") do |f|
|
25
|
-
f.write(render)
|
26
|
-
end
|
27
|
-
end
|
11
|
+
def self.init_base_dir
|
12
|
+
tpl_path = Calamum::Config[:tpl_path]
|
13
|
+
doc_path = Calamum::Config[:doc_path]
|
14
|
+
FileUtils.rm_r(doc_path, :force => true)
|
15
|
+
Dir.mkdir(doc_path)
|
28
16
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
17
|
+
# copy assets from template directory
|
18
|
+
source = File.join(tpl_path, 'assets')
|
19
|
+
target = File.join(doc_path, 'assets')
|
20
|
+
FileUtils.copy_entry(source, target)
|
33
21
|
end
|
34
22
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
begin
|
39
|
-
FileUtils.copy_entry(src, dst)
|
40
|
-
rescue => e
|
41
|
-
puts_error e.message
|
23
|
+
def save_template(filename, values)
|
24
|
+
values.each do |k, v|
|
25
|
+
instance_variable_set("@#{k}", v)
|
42
26
|
end
|
43
|
-
end
|
44
27
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
while true
|
49
|
-
print "The filename directoy #{doc_dir} already exists. Do you want to overwrite it? [Y/N]: "
|
50
|
-
case $stdin.gets.chomp!.downcase
|
51
|
-
when 'y'
|
52
|
-
FileUtils.rm_r(doc_dir, :force => true)
|
53
|
-
break
|
54
|
-
when 'n'
|
55
|
-
exit(1)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
Dir.mkdir doc_dir
|
28
|
+
html_data = @template.result(binding)
|
29
|
+
filename = File.join(Calamum::Config[:doc_path], filename)
|
30
|
+
File.open(filename, 'w+') { |file| file.write(html_data) }
|
60
31
|
end
|
61
32
|
|
62
33
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class Calamum::DocParser
|
2
|
+
attr_accessor :resources, :definition
|
3
|
+
|
4
|
+
def initialize(definition)
|
5
|
+
@resources = Hash.new
|
6
|
+
@definition = definition
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_url
|
10
|
+
@definition['url']
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_name
|
14
|
+
@definition['name']
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_version
|
18
|
+
@definition['version']
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_description
|
22
|
+
@definition['description']
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_resources
|
26
|
+
Calamum::Config[:sort]? @definition['resources'].sort : @definition['resources']
|
27
|
+
end
|
28
|
+
|
29
|
+
def load_resources
|
30
|
+
get_resources.each do |name, methods|
|
31
|
+
list = []
|
32
|
+
methods.each do |resource|
|
33
|
+
if validate_resource?(resource)
|
34
|
+
list << Calamum::Resource.new(resource)
|
35
|
+
puts_info "#{resource['action']}: #{resource['uri']}"
|
36
|
+
else
|
37
|
+
puts_warning "Resource #{resource['action']}: #{resource['uri']} has incorrect definition"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
@resources[name] = list if list.any?
|
41
|
+
end
|
42
|
+
@resources
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_resource?(resource)
|
46
|
+
resource['uri'] && resource['action'] && resource['description'] && %{GET POST PUT DELETE}.include?(resource['action'].upcase)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Returns a formatted JSON string.
|
2
|
+
#
|
3
|
+
# @param json [String] JSON string to format
|
4
|
+
# @param indent [String] indent that used in formatting
|
5
|
+
# @return [String] prettier form of the given JSON string
|
6
|
+
def pj(json, indent = ' ')
|
7
|
+
require 'json'
|
8
|
+
JSON.pretty_generate(json, :indent => indent * 4).gsub!(/\n/, '<br/>')
|
9
|
+
end
|
10
|
+
|
11
|
+
# Output info message to console.
|
12
|
+
#
|
13
|
+
# @param msg [String] message to output
|
14
|
+
def puts_info(msg)
|
15
|
+
$stdout.puts "\e[32m[INFO] #{msg}\e[0m" if Calamum::Config[:debug]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Output warning message to console.
|
19
|
+
#
|
20
|
+
# @param msg [String] message to output
|
21
|
+
def puts_warning(msg)
|
22
|
+
$stdout.puts "\e[33m[WARNING] #{msg}\e[0m" if Calamum::Config[:debug]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Output error message to console.
|
26
|
+
#
|
27
|
+
# @param msg [String] message to output
|
28
|
+
def puts_error(msg)
|
29
|
+
$stderr.puts "\e[31m[ERROR] #{msg}\e[0m" if Calamum::Config[:debug]
|
30
|
+
exit(1)
|
31
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# This class represents a single resource.
|
2
|
+
# It contains attributes from parsed definition.
|
3
|
+
# So anywhere in view template we can use this object.
|
4
|
+
class Calamum::Resource
|
5
|
+
attr_accessor :uri, :action, :headers,
|
6
|
+
:auth, :params, :errors, :description, :response
|
7
|
+
|
8
|
+
# Initialize object from attributes.
|
9
|
+
#
|
10
|
+
# @param attrs [Hash] attributes to set
|
11
|
+
def initialize(attrs)
|
12
|
+
@uri = attrs['uri']
|
13
|
+
@action = attrs['action'].upcase
|
14
|
+
@headers = attrs['headers'] || {}
|
15
|
+
@auth = !!attrs['authentication']
|
16
|
+
@params = attrs['params'] || {}
|
17
|
+
@errors = attrs['errors'] || {}
|
18
|
+
@description = attrs['description']
|
19
|
+
@response = attrs['response']
|
20
|
+
end
|
21
|
+
|
22
|
+
# @override
|
23
|
+
# Returns a string representing a label css class.
|
24
|
+
#
|
25
|
+
# @return [String] css class
|
26
|
+
def action_label
|
27
|
+
case @action
|
28
|
+
when 'GET'
|
29
|
+
'label-info'
|
30
|
+
when 'POST'
|
31
|
+
'label-success'
|
32
|
+
when 'PUT'
|
33
|
+
'label-warning'
|
34
|
+
when 'DELETE'
|
35
|
+
'label-important'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @override
|
40
|
+
# Returns a string representing a resource.
|
41
|
+
#
|
42
|
+
# @return [String] resource in a form (action: uri)
|
43
|
+
def to_s
|
44
|
+
"#{action}: #{uri}"
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/lib/calamum/runner.rb
CHANGED
@@ -3,89 +3,114 @@ require 'calamum/config'
|
|
3
3
|
require 'calamum/doc_generator'
|
4
4
|
require 'mixlib/cli'
|
5
5
|
|
6
|
+
# Provides a class-based command line opts.
|
7
|
+
# See https://github.com/opscode/mixlib-cli
|
6
8
|
class Calamum::Runner
|
7
9
|
include Mixlib::CLI
|
8
|
-
CMD_NAME = "calamum"
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
super
|
12
|
-
end
|
13
10
|
|
14
11
|
option :help,
|
15
|
-
:short =>
|
16
|
-
:long =>
|
17
|
-
:description =>
|
12
|
+
:short => '-h',
|
13
|
+
:long => '--help',
|
14
|
+
:description => 'Show this help',
|
18
15
|
:on => :tail,
|
19
16
|
:boolean => true,
|
20
17
|
:show_options => true,
|
21
18
|
:exit => 0
|
22
19
|
|
23
|
-
option :
|
24
|
-
:short =>
|
25
|
-
:long =>
|
26
|
-
:description =>
|
27
|
-
:
|
28
|
-
:proc => lambda {|v| puts "Calamum: #{Calamum::VERSION}"},
|
29
|
-
:exit => 0
|
30
|
-
|
31
|
-
option :debug,
|
32
|
-
:short => "-d",
|
33
|
-
:long => "--debug",
|
34
|
-
:description => "Show actions to do (default)",
|
35
|
-
:boolean => true,
|
36
|
-
:default => true,
|
37
|
-
:proc => lambda { |p| true }
|
38
|
-
|
39
|
-
option :definition,
|
40
|
-
:short => "-f DEFINITION",
|
41
|
-
:long => "--file DEFINITION",
|
42
|
-
:description => "Definition YAML file",
|
43
|
-
:required => true
|
20
|
+
option :source,
|
21
|
+
:short => '-f DEFINITION',
|
22
|
+
:long => '--file DEFINITION',
|
23
|
+
:description => 'Path to the file with JSON API definition',
|
24
|
+
:required => true
|
44
25
|
|
45
26
|
option :template,
|
46
|
-
:short =>
|
47
|
-
:long =>
|
48
|
-
:description =>
|
49
|
-
:default =>
|
27
|
+
:short => '-t TEMPLATE',
|
28
|
+
:long => '--template TEMPLATE',
|
29
|
+
:description => 'Name of HTML template [twitter, bootstrap](twitter by default)',
|
30
|
+
:default => 'twitter'
|
50
31
|
|
51
32
|
option :path,
|
52
|
-
:short =>
|
53
|
-
:long =>
|
54
|
-
:description =>
|
55
|
-
:default =>
|
33
|
+
:short => '-p PATH',
|
34
|
+
:long => '--path PATH',
|
35
|
+
:description => 'Path to the directory where docs will be generated',
|
36
|
+
:default => ENV['HOME']
|
56
37
|
|
38
|
+
option :debug,
|
39
|
+
:short => '-d',
|
40
|
+
:long => '--debug',
|
41
|
+
:description => 'Show actions to do (true by default)',
|
42
|
+
:default => true,
|
43
|
+
:boolean => true,
|
44
|
+
:proc => lambda { |x| true }
|
45
|
+
|
46
|
+
option :version,
|
47
|
+
:short => '-v',
|
48
|
+
:long => '--version',
|
49
|
+
:description => 'Show version number',
|
50
|
+
:proc => lambda { |x| puts Calamum::VERSION },
|
51
|
+
:exit => 0
|
52
|
+
|
57
53
|
option :sort,
|
58
54
|
:short => "-s",
|
59
55
|
:long => "--sort",
|
60
56
|
:description => "Sort the resources alphabetically",
|
61
57
|
:boolean => true,
|
62
58
|
:default => false
|
63
|
-
|
59
|
+
|
60
|
+
# Parses command line options and generates API documentation.
|
61
|
+
# See samples for details how to define meta-data for your API.
|
64
62
|
def run
|
65
|
-
|
66
|
-
Calamum::Config.
|
67
|
-
|
68
|
-
@definition
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
63
|
+
parse_options
|
64
|
+
Calamum::Config.apply(config)
|
65
|
+
@definition = Calamum::DocParser.new(load_source)
|
66
|
+
@definition.load_resources
|
67
|
+
Calamum::DocGenerator.init_base_dir
|
68
|
+
process_index
|
69
|
+
process_pages if config[:template] == 'twitter'
|
70
|
+
rescue => ex
|
71
|
+
puts_error ex.message
|
74
72
|
end
|
75
73
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
74
|
+
# Open and load the source file of api definition
|
75
|
+
def load_source
|
76
|
+
case File.extname(config[:source])
|
77
|
+
when '.json'
|
78
|
+
Yajl.load(File.open(config[:source]))
|
79
|
+
when '.yml'
|
80
|
+
YAML.load(File.open(config[:source]))
|
81
|
+
else
|
82
|
+
raise 'unknown source file extension'
|
81
83
|
end
|
82
84
|
end
|
85
|
+
|
86
|
+
# Bind values to index page and save it.
|
87
|
+
def process_index
|
88
|
+
bindings = {
|
89
|
+
:url => @definition.get_url,
|
90
|
+
:name => @definition.get_name,
|
91
|
+
:resources => @definition.resources,
|
92
|
+
:description => @definition.get_description,
|
93
|
+
:version => @definition.get_version
|
94
|
+
}
|
95
|
+
|
96
|
+
page = Calamum::DocGenerator.new(:index)
|
97
|
+
page.save_template('index.html', bindings)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Bind values to view pages and save them.
|
101
|
+
def process_pages
|
102
|
+
bindings = {
|
103
|
+
:name => @definition.get_name,
|
104
|
+
:version => @definition.get_version
|
105
|
+
}
|
83
106
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
107
|
+
page = Calamum::DocGenerator.new(:view)
|
108
|
+
@definition.resources.each do |methods|
|
109
|
+
methods[1].each do |resource|
|
110
|
+
bindings.merge!(:resource => resource)
|
111
|
+
filename = "#{resource.object_id}.html"
|
112
|
+
page.save_template(filename, bindings)
|
113
|
+
end
|
89
114
|
end
|
90
115
|
end
|
91
116
|
|