yard-api 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/LICENSE +674 -0
- data/README.md +27 -0
- data/lib/yard-api/markup/redcarpet.rb +42 -0
- data/lib/yard-api/options.rb +13 -0
- data/lib/yard-api/railtie.rb +11 -0
- data/lib/yard-api/tags.rb +16 -0
- data/lib/yard-api/templates/helpers/base_helper.rb +108 -0
- data/lib/yard-api/templates/helpers/html_helper.rb +87 -0
- data/lib/yard-api/templates/helpers/route_helper.rb +19 -0
- data/lib/yard-api/verifier.rb +34 -0
- data/lib/yard-api/version.rb +5 -0
- data/lib/yard-api/yardoc_task.rb +78 -0
- data/lib/yard-api.rb +48 -0
- data/spec/spec_helper.rb +44 -0
- data/tasks/yard_api.rake +13 -0
- data/templates/api/appendix/html/setup.rb +19 -0
- data/templates/api/docstring/html/setup.rb +3 -0
- data/templates/api/docstring/html/text.erb +6 -0
- data/templates/api/fulldoc/html/setup.rb +78 -0
- data/templates/api/layout/html/footer.erb +11 -0
- data/templates/api/layout/html/headers.erb +19 -0
- data/templates/api/layout/html/layout.erb +17 -0
- data/templates/api/layout/html/scripts.erb +35 -0
- data/templates/api/layout/html/setup.rb +63 -0
- data/templates/api/layout/html/sidebar.erb +29 -0
- data/templates/api/method_details/html/header.erb +12 -0
- data/templates/api/method_details/html/method_signature.erb +19 -0
- data/templates/api/method_details/html/setup.rb +35 -0
- data/templates/api/tags/html/_example_code_block.erb +8 -0
- data/templates/api/tags/html/argument.erb +32 -0
- data/templates/api/tags/html/emits.erb +7 -0
- data/templates/api/tags/html/example_request.erb +13 -0
- data/templates/api/tags/html/example_response.erb +14 -0
- data/templates/api/tags/html/generic_tag.erb +20 -0
- data/templates/api/tags/html/index.erb +3 -0
- data/templates/api/tags/html/no_content.erb +3 -0
- data/templates/api/tags/html/note.erb +6 -0
- data/templates/api/tags/html/returns.erb +10 -0
- data/templates/api/tags/html/see.erb +8 -0
- data/templates/api/tags/html/throws.erb +49 -0
- data/templates/api/tags/html/warning.erb +6 -0
- data/templates/api/tags/setup.rb +83 -0
- data/templates/api/topic/html/header.erb +7 -0
- data/templates/api/topic/html/method_details_list.erb +5 -0
- data/templates/api/topic/html/setup.rb +58 -0
- data/templates/api/topic/html/topic_doc.erb +27 -0
- data/yard-api.gemspec +22 -0
- metadata +149 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
<meta name="Content-Type" content="text/html;charset=UTF-8">
|
2
|
+
<meta charset="UTF-8">
|
3
|
+
|
4
|
+
<title><%= api_options['title'] %></title>
|
5
|
+
|
6
|
+
<link
|
7
|
+
rel="stylesheet"
|
8
|
+
href="<%= url_for("css/common.css") %>"
|
9
|
+
type="text/css"
|
10
|
+
media="screen"
|
11
|
+
charset="utf-8" />
|
12
|
+
|
13
|
+
<link
|
14
|
+
href="<%= url_for("css/highlight.css") %>"
|
15
|
+
rel="stylesheet"
|
16
|
+
type="text/css" />
|
17
|
+
|
18
|
+
<script src="<%= url_for("js/highlight/highlight.pack.js") %>" type="text/javascript"></script>
|
19
|
+
<script src="<%= url_for("js/jquery-1.11.1.min.js") %>" type="text/javascript"></script>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<%= erb(:headers) %>
|
5
|
+
</head>
|
6
|
+
|
7
|
+
<body>
|
8
|
+
<div id="sidebar">
|
9
|
+
<%= erb(:sidebar) %>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<div id="content"><%= yieldall %></div>
|
13
|
+
|
14
|
+
<%= erb(:footer) %>
|
15
|
+
<%= erb(:scripts) %>
|
16
|
+
</body>
|
17
|
+
</html>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<script type="text/javascript">
|
2
|
+
$('h2.api_method_name').each(function(i, el) {
|
3
|
+
var subtopic = $(el).data('subtopic');
|
4
|
+
var $a = $(el).find('a');
|
5
|
+
var anchorText = $.trim($a[0].innerHTML);
|
6
|
+
|
7
|
+
if (anchorText === '') {
|
8
|
+
return;
|
9
|
+
}
|
10
|
+
|
11
|
+
var $row = $('#quicklinks');
|
12
|
+
var $link = $('<a/>', {
|
13
|
+
href: '#'+$(el).attr('name')
|
14
|
+
}).html(anchorText);
|
15
|
+
|
16
|
+
$('<li>').append($link).appendTo($row);
|
17
|
+
});
|
18
|
+
|
19
|
+
$('#content pre.code').each(function(i, block) {
|
20
|
+
var code;
|
21
|
+
var $block = $(block);
|
22
|
+
var $codeEl = $block.find('> code');
|
23
|
+
|
24
|
+
// RedCarpet markdown renderer will convert fenced code blocks into
|
25
|
+
// <pre><code>...</code></pre> and we want to remove that <code /> el and
|
26
|
+
// use a plain <pre /> instead:
|
27
|
+
if ($block.children().length === 1 && $codeEl.length) {
|
28
|
+
code = $codeEl.text();
|
29
|
+
$codeEl.remove();
|
30
|
+
$block.html(code);
|
31
|
+
}
|
32
|
+
|
33
|
+
hljs.highlightBlock(block);
|
34
|
+
});
|
35
|
+
</script>
|
@@ -0,0 +1,63 @@
|
|
1
|
+
include Helpers::FilterHelper
|
2
|
+
|
3
|
+
def init
|
4
|
+
@breadcrumb = []
|
5
|
+
|
6
|
+
@page_title = options[:title]
|
7
|
+
|
8
|
+
if @file
|
9
|
+
if @file.is_a?(String)
|
10
|
+
@contents = File.read(@file)
|
11
|
+
@file = File.basename(@file)
|
12
|
+
else
|
13
|
+
@contents = @file.contents
|
14
|
+
@file = File.basename(@file.path)
|
15
|
+
end
|
16
|
+
def @object.source_type; nil; end
|
17
|
+
sections :layout, [:diskfile]
|
18
|
+
elsif options[:controllers]
|
19
|
+
sections :layout, [T('topic'), T('appendix')]
|
20
|
+
else
|
21
|
+
sections :layout, [:contents]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def contents
|
26
|
+
@contents
|
27
|
+
end
|
28
|
+
|
29
|
+
def index
|
30
|
+
legitimate_objects = @objects.reject {|o| o.root? || !is_class?(o) || !o.meths.find { |m| !m.tags('API').empty? } }
|
31
|
+
|
32
|
+
@resources = legitimate_objects.sort_by {|o| o.tags('API').first.text }
|
33
|
+
|
34
|
+
erb(:index)
|
35
|
+
end
|
36
|
+
|
37
|
+
def diskfile
|
38
|
+
content = "<div id='filecontents'>" +
|
39
|
+
case (File.extname(@file)[1..-1] || '').downcase
|
40
|
+
when 'htm', 'html'
|
41
|
+
@contents
|
42
|
+
when 'txt'
|
43
|
+
"<pre>#{@contents}</pre>"
|
44
|
+
when 'textile', 'txtile'
|
45
|
+
htmlify(@contents, :textile)
|
46
|
+
when 'markdown', 'md', 'mdown', 'mkd'
|
47
|
+
htmlify(@contents, :markdown)
|
48
|
+
else
|
49
|
+
htmlify(@contents, diskfile_shebang_or_default)
|
50
|
+
end +
|
51
|
+
"</div>"
|
52
|
+
options.delete(:no_highlight)
|
53
|
+
content
|
54
|
+
end
|
55
|
+
|
56
|
+
def diskfile_shebang_or_default
|
57
|
+
if @contents =~ /\A#!(\S+)\s*$/ # Shebang support
|
58
|
+
@contents = $'
|
59
|
+
$1.to_sym
|
60
|
+
else
|
61
|
+
options[:markup]
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<nav>
|
2
|
+
<h1>
|
3
|
+
<%= api_options['title'] %>
|
4
|
+
<%= api_options['version'] %>
|
5
|
+
</h1>
|
6
|
+
|
7
|
+
<h2 class='first'>Pages</h2>
|
8
|
+
<a
|
9
|
+
href="<%= url_for("index.html") %>"
|
10
|
+
class="<%= 'current' if options[:object] == 'index.html' %>">Home
|
11
|
+
</a>
|
12
|
+
|
13
|
+
<% static_pages.each do |page| %>
|
14
|
+
<a href="<%= url_for(page[:filename]) %>"
|
15
|
+
class="<%= 'current' if options[:object] == page[:filename] %>">
|
16
|
+
<%= page[:title] %>
|
17
|
+
</a>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<h2>Resources</h2>
|
21
|
+
<% options[:resources].each_with_index do |(resource, controllers), i| %>
|
22
|
+
<%
|
23
|
+
link = url_for("#{topicize resource}.html")
|
24
|
+
klass = []
|
25
|
+
klass << "current" if resource == options[:object]
|
26
|
+
%>
|
27
|
+
<a class="<%= klass.join(' ') %>" href="<%= link %>"><%= resource %></a>
|
28
|
+
<% end %>
|
29
|
+
</nav>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<div class="method_details <%= @index == 0 ? 'first' : '' %>">
|
2
|
+
<h2 class='api_method_name' name='<%= @method_link %>' data-subtopic='<%= @subtopic %>'>
|
3
|
+
<a name='<%= @method_link %>' href='#<%= @method_link %>'>
|
4
|
+
<%= object.tag("API").try(:text) %>
|
5
|
+
</a>
|
6
|
+
|
7
|
+
<% if @controller_path %>
|
8
|
+
<span class='defined-in'><a href="https://github.com/amireh/pibi/blob/master/<%= @controller_path %>"><%= "#{@route.requirements[:controller].camelize}Controller\##{@route.requirements[:action]}" %></a></span>
|
9
|
+
<% end %>
|
10
|
+
</h2>
|
11
|
+
<%= yieldall %>
|
12
|
+
</div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<% @routes.each do |route| %>
|
2
|
+
<% route_path = route.path.spec.to_s.gsub("(.:format)", "")
|
3
|
+
if route.verb.source =~ /\^?(\w*)\$/
|
4
|
+
verb = $1.upcase
|
5
|
+
else
|
6
|
+
verb = route.verb.source
|
7
|
+
end
|
8
|
+
%>
|
9
|
+
<h3 class='endpoint'>
|
10
|
+
<span class="verb <%= verb.downcase %>"><%= verb %></span>
|
11
|
+
<%
|
12
|
+
formatted_route_path = route_path.split('/').map do |fragment|
|
13
|
+
is_id = fragment =~ /^\:[\w|_]+/
|
14
|
+
"<span #{'class="id-fragment"' if is_id}>#{fragment}</span>"
|
15
|
+
end.join('/')
|
16
|
+
%>
|
17
|
+
<%= formatted_route_path %>
|
18
|
+
</h3>
|
19
|
+
<% end %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# require 'route_helper'
|
2
|
+
|
3
|
+
RouteHelper = YARD::Templates::Helpers::RouteHelper
|
4
|
+
def init
|
5
|
+
get_routes
|
6
|
+
sections :header, [:method_signature, T('docstring')]
|
7
|
+
end
|
8
|
+
|
9
|
+
def header
|
10
|
+
get_routes
|
11
|
+
@subtopic = (object.parent.tag('subtopic') || object.parent.tag('API')).text
|
12
|
+
|
13
|
+
unless route = @routes.first
|
14
|
+
puts "[error] Unable to find route for object: #{object}"
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
@method_link = "method.#{route.requirements[:controller]}.#{route.requirements[:action]}"
|
19
|
+
@beta = object.tag('beta') || object.parent.tag('beta')
|
20
|
+
erb(:header)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_routes
|
24
|
+
@controller = object.parent.path.underscore
|
25
|
+
@controller.sub!("_controller", '') unless @controller.include?('/')
|
26
|
+
|
27
|
+
@action = object.path.sub(/^.*#/, '')
|
28
|
+
@action = @action.sub(/_with_.*$/, '')
|
29
|
+
@routes = RouteHelper.api_methods_for_controller_and_action(@controller, @action)
|
30
|
+
@route = @routes.first
|
31
|
+
if @route.present?
|
32
|
+
@controller_path = "app/controllers/#{@route.requirements[:controller]}_controller.rb"
|
33
|
+
@controller_path = nil unless File.file?(Rails.root+@controller_path)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<section class="endpoint-arguments">
|
2
|
+
<h4>Parameters:</h4>
|
3
|
+
<ul class="argument">
|
4
|
+
<% @argument_tags.each do |tag| %>
|
5
|
+
<%
|
6
|
+
tag.text ||= ''
|
7
|
+
desc = tag.text.strip.sub(/^\[([^\]]+)\]/, '').strip
|
8
|
+
type = $1
|
9
|
+
desc = desc.sub(/(\(optional\))/, '').strip
|
10
|
+
is_optional = $1.present?
|
11
|
+
name, desc = desc.split(/\s/, 2).map(&:strip)
|
12
|
+
desc = desc.sub(/[A|a]ccepted values:\s*\[([^\]]+)\]/, '').strip
|
13
|
+
accepted_values = $1
|
14
|
+
%>
|
15
|
+
<li>
|
16
|
+
<code class="argument-name"><%= h name %></code>
|
17
|
+
<span class="argument-type"><%= type %></span>
|
18
|
+
<span class="argument-values fade">
|
19
|
+
<em><%= "[#{accepted_values}]" if accepted_values.present? %></em>
|
20
|
+
</span>
|
21
|
+
|
22
|
+
<% unless is_optional %>
|
23
|
+
<em class="argument-required">Required</em>
|
24
|
+
<% end %>
|
25
|
+
|
26
|
+
<% if !desc.empty? %>
|
27
|
+
<%= html_markup_markdown(desc) %>
|
28
|
+
<% end %>
|
29
|
+
</li>
|
30
|
+
<% end %>
|
31
|
+
</ul>
|
32
|
+
</section>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<% if object.has_tag?(:example_request) %>
|
2
|
+
<div class="examples">
|
3
|
+
<% if object.tags(:example_request).length > 1 %>
|
4
|
+
<h4>Example Requests:</h4>
|
5
|
+
<% else %>
|
6
|
+
<h4>Example Request:</h4>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% object.tags(:example_request).each do |tag| %>
|
10
|
+
<%= tag_partial '_example_code_block', tag %>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<% if object.has_tag?(:example_response) %>
|
2
|
+
<% tags = object.tags(:example_response) %>
|
3
|
+
<div class="examples example_response">
|
4
|
+
<% if tags.length > 1 %>
|
5
|
+
<h4>Example Responses:</h4>
|
6
|
+
<% else %>
|
7
|
+
<h4>Example Response:</h4>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% tags.each do |tag| %>
|
11
|
+
<%= tag_partial '_example_code_block', tag %>
|
12
|
+
<% end %>
|
13
|
+
</div>
|
14
|
+
<% end %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<h4><%= @label ? @label : YARD::Tags::Library.labels[@name] %>:</h4>
|
2
|
+
<ul class="<%= @name %>">
|
3
|
+
<% object.tags(@name).each do |tag| %>
|
4
|
+
|
5
|
+
<li>
|
6
|
+
<% unless @no_types %>
|
7
|
+
<span class='type'><%= format_types(tag.types) %></span>
|
8
|
+
<% end %>
|
9
|
+
<%
|
10
|
+
name, text = (tag.text || "").split(/\s/, 2)
|
11
|
+
%>
|
12
|
+
<% unless @no_names %>
|
13
|
+
<span class='name'><%= h name %></span>
|
14
|
+
<% end %>
|
15
|
+
<% if text && !text.empty? %>
|
16
|
+
<%= html_markup_markdown(text) %>
|
17
|
+
<% end %>
|
18
|
+
</li>
|
19
|
+
<% end %>
|
20
|
+
</ul>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<p class="returns-tag">
|
2
|
+
<% if @is_list %>
|
3
|
+
Returns a list of
|
4
|
+
<% else %>
|
5
|
+
Returns <%= %w[a e i o u].include?(@resource_name[0]) ? 'an' : 'a' %>
|
6
|
+
<% end %>
|
7
|
+
<a href='<%= @resource_name %>.html#<%= @object_name %>'>
|
8
|
+
<%= @is_list ? @object_name.pluralize : @object_name %>
|
9
|
+
</a>
|
10
|
+
</p>
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<h4>Possible Errors:</h4>
|
2
|
+
<p>
|
3
|
+
Your request may be rejected with a <code>400 Bad Request</code> HTTP status
|
4
|
+
code and an error from the following set:
|
5
|
+
</p>
|
6
|
+
|
7
|
+
<table class="endpoint-errors">
|
8
|
+
<thead>
|
9
|
+
<tr>
|
10
|
+
<!-- <th>Error</th> -->
|
11
|
+
<th>Code</th>
|
12
|
+
<th>Message</th>
|
13
|
+
</tr>
|
14
|
+
</thead>
|
15
|
+
|
16
|
+
<tbody>
|
17
|
+
<% @error_tags.each do |tag| %>
|
18
|
+
<%
|
19
|
+
tag.text ||= ''
|
20
|
+
error = {}
|
21
|
+
buf = tag.text.strip.sub(/^\[([^\]]+)\]/, '').strip
|
22
|
+
error[:status] = $1
|
23
|
+
buf = buf.sub(/"\[([^\]]+)\]([^"]+)"/, '').strip
|
24
|
+
error[:code] = $1.strip
|
25
|
+
error[:message] = $2
|
26
|
+
error[:cause] = buf.strip
|
27
|
+
%>
|
28
|
+
<tr>
|
29
|
+
<% if false %>
|
30
|
+
<td>
|
31
|
+
<%= error[:status] %>
|
32
|
+
<%= Rack::Utils::HTTP_STATUS_CODES[error[:status].to_i] %>
|
33
|
+
</td>
|
34
|
+
<% end %>
|
35
|
+
<td>
|
36
|
+
<code><%= error[:code] %></code>
|
37
|
+
</td>
|
38
|
+
<td>
|
39
|
+
<%= error[:message] %>
|
40
|
+
<% unless error[:cause].empty? %>
|
41
|
+
<hr />
|
42
|
+
<strong>Cause:</strong>
|
43
|
+
<%= error[:cause].sub(/^because /i, '').capitalize %>
|
44
|
+
<% end %>
|
45
|
+
</td>
|
46
|
+
</tr>
|
47
|
+
<% end %>
|
48
|
+
</tbody>
|
49
|
+
</table>
|
@@ -0,0 +1,83 @@
|
|
1
|
+
def init
|
2
|
+
super
|
3
|
+
sections *[
|
4
|
+
:emits,
|
5
|
+
:note,
|
6
|
+
:warning,
|
7
|
+
:argument,
|
8
|
+
:request_field,
|
9
|
+
:response_field,
|
10
|
+
:example_request,
|
11
|
+
:example_response,
|
12
|
+
:throws,
|
13
|
+
:see,
|
14
|
+
:returns,
|
15
|
+
:no_content,
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
def see
|
20
|
+
return unless object.has_tag?(:see)
|
21
|
+
erb(:see)
|
22
|
+
end
|
23
|
+
|
24
|
+
def request_field
|
25
|
+
generic_tag :request_field
|
26
|
+
end
|
27
|
+
|
28
|
+
def response_field
|
29
|
+
generic_tag :response_field
|
30
|
+
end
|
31
|
+
|
32
|
+
def throws
|
33
|
+
@error_tags = object.tags(:throws)
|
34
|
+
|
35
|
+
if @error_tags.any?
|
36
|
+
erb('throws')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def emits
|
41
|
+
@emits = object.tags(:emits)
|
42
|
+
|
43
|
+
if @emits.any?
|
44
|
+
erb('emits')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def argument
|
49
|
+
# generic_tag :argument, :no_types => false, :label => "Request Parameters"
|
50
|
+
@argument_tags = object.tags(:argument)
|
51
|
+
|
52
|
+
if @argument_tags.any?
|
53
|
+
erb('argument')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def returns
|
58
|
+
return unless object.has_tag?(:returns)
|
59
|
+
response_info = object.tag(:returns)
|
60
|
+
case response_info.text
|
61
|
+
when %r{\[(.*)\]}
|
62
|
+
@object_name = $1.strip
|
63
|
+
@is_list = true
|
64
|
+
else
|
65
|
+
@object_name = response_info.text.strip
|
66
|
+
@is_list = false
|
67
|
+
end
|
68
|
+
@resource_name = options[:json_objects_map][@object_name]
|
69
|
+
return unless @resource_name
|
70
|
+
erb(:returns)
|
71
|
+
end
|
72
|
+
|
73
|
+
def generic_tag(name, opts = {})
|
74
|
+
return unless object.has_tag?(name)
|
75
|
+
@no_names = true if opts[:no_names]
|
76
|
+
@no_types = true if opts[:no_types]
|
77
|
+
@label = opts[:label]
|
78
|
+
@name = name
|
79
|
+
out = erb('generic_tag')
|
80
|
+
@no_names, @no_types = nil, nil
|
81
|
+
out
|
82
|
+
end
|
83
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
def init
|
2
|
+
sections :header, [:topic_doc, :method_details_list, [T('method_details')]]
|
3
|
+
@resource = object
|
4
|
+
@beta = options[:controllers].any? { |c| c.tag('beta') }
|
5
|
+
end
|
6
|
+
|
7
|
+
def method_details_list
|
8
|
+
@meths = options[:controllers].map { |c| c.meths(:inherited => false, :included => false) }.flatten
|
9
|
+
@meths = run_verifier(@meths)
|
10
|
+
erb(:method_details_list)
|
11
|
+
end
|
12
|
+
|
13
|
+
def topic_doc
|
14
|
+
@docstring = options[:controllers].map { |c| c.docstring }.join("\n\n")
|
15
|
+
@object = @object.dup
|
16
|
+
def @object.source_type; nil; end
|
17
|
+
@json_objects = options[:json_objects][@resource] || []
|
18
|
+
erb(:topic_doc)
|
19
|
+
end
|
20
|
+
|
21
|
+
def properties_of_model(json)
|
22
|
+
require 'json'
|
23
|
+
JSON::parse(json)['properties']
|
24
|
+
rescue JSON::ParserError
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def word_wrap(text, col_width=80)
|
29
|
+
text.gsub!( /(\S{#{col_width}})(?=\S)/, '\1 ' )
|
30
|
+
text.gsub!( /(.{1,#{col_width}})(?:\s+|$)/, "\\1\n" )
|
31
|
+
text
|
32
|
+
end
|
33
|
+
|
34
|
+
def indent(str, amount = 2, char = ' ')
|
35
|
+
str.gsub(/^/, char * amount)
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_comment(string, wrap = 75)
|
39
|
+
indent(word_wrap(string), 2, '/')
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_value(value, type = 'string')
|
43
|
+
case type
|
44
|
+
when 'integer', 'double', 'number' then value.to_s
|
45
|
+
else %{"#{value}"}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def render_properties(json)
|
50
|
+
if properties = properties_of_model(json)
|
51
|
+
"{\n" + indent(
|
52
|
+
properties.map do |name, prop|
|
53
|
+
"\n" + render_comment(prop['description']) +
|
54
|
+
%{"#{name}": } + render_value(prop['example'], prop['type'])
|
55
|
+
end.join(",\n")) +
|
56
|
+
"\n}"
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<article>
|
2
|
+
<%= html_markup_markdown(@docstring.strip) %>
|
3
|
+
</article>
|
4
|
+
|
5
|
+
<% c = options[:controllers].detect { |c| c.has_tag?(:note) } %>
|
6
|
+
<% c && c.tags(:note).each do |tag| %>
|
7
|
+
<blockquote class="note">
|
8
|
+
<p><strong>Note</strong></p>
|
9
|
+
<%= html_markup_markdown tag.text %>
|
10
|
+
</blockquote>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<section>
|
14
|
+
<header><strong>Interfaces</strong></header>
|
15
|
+
<ul id="quicklinks">
|
16
|
+
</ul>
|
17
|
+
</section>
|
18
|
+
|
19
|
+
<% @json_objects.each do |name, json| %>
|
20
|
+
<% properties = render_properties(json) %>
|
21
|
+
<div class='object_definition'>
|
22
|
+
<h3>
|
23
|
+
<a name="<%= name %>"></a><%= name %> object synposis:
|
24
|
+
</h3>
|
25
|
+
<pre class="example code"><%= html_syntax_highlight(properties ? properties : json, :plain) %></pre>
|
26
|
+
</div>
|
27
|
+
<% end %>
|
data/yard-api.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.join(%W[#{File.dirname(__FILE__)} lib yard-api version])
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'yard-api'
|
5
|
+
s.summary = "A YARD plugin for documenting APIs in Rails projects."
|
6
|
+
s.description = <<-eof
|
7
|
+
TBD
|
8
|
+
eof
|
9
|
+
s.version = YARD::APIPlugin::VERSION
|
10
|
+
s.date = Time.now.strftime('%Y-%m-%d')
|
11
|
+
s.authors = ["Ahmad Amireh"]
|
12
|
+
s.email = 'ahmad@instructure.com'
|
13
|
+
s.homepage = 'https://github.com/amireh/yard-api'
|
14
|
+
s.files = Dir.glob("{lib,spec,templates,tasks}/**/*.{rb,erb,rake}") +
|
15
|
+
['LICENSE', 'README.md', '.rspec', __FILE__]
|
16
|
+
s.has_rdoc = 'yard'
|
17
|
+
s.license = 'AGPL3'
|
18
|
+
s.add_dependency 'yard', '0.8.7'
|
19
|
+
s.add_dependency 'yard-appendix', '>=0.1.8'
|
20
|
+
s.add_development_dependency 'rspec'
|
21
|
+
s.add_development_dependency 'gem-release'
|
22
|
+
end
|