require 'builder'
# Generates Markdown/HTML documentation about a single API action.
#
# Formats route parameters and request/QS parameters as a neat HTML
# table, listing types, requirements and descriptions.
#
# Is used by AppDocumentation to compile a document on the entire app's API
# structure in one go.
class Apiculture::MethodDocumentation
def initialize(action_definition, mountpoint = '')
@definition = action_definition
@mountpoint = mountpoint
end
# Compose a Markdown definition of the action
def to_markdown
m = MDBuf.new
m << "## #{@definition.http_verb.upcase} #{@mountpoint}#{@definition.path}"
m << @definition.description
m << route_parameters_table
m << request_parameters_table
m << possible_responses_table
m.to_s
end
# Compose an HTML string by converting the result of +to_markdown+
def to_html_fragment
require 'rdiscount'
RDiscount.new(to_markdown).to_html
end
private
class StringBuf #:nodoc:
def initialize; @blocks = []; end
def <<(block); @blocks << block.to_s; self; end
def to_s; @blocks.join; end
end
class MDBuf < StringBuf #:nodoc:
def to_s; @blocks.join("\n\n"); end
end
def route_parameters_table
return '' unless @definition.defines_route_params?
m = MDBuf.new
b = StringBuf.new
m << '### URL parameters'
html = Builder::XmlMarkup.new(:target => b)
html.table(class: 'apiculture-table') do
html.tr do
html.th 'Name'
html.th 'Description'
end
@definition.route_parameters.each do | param |
html.tr do
html.td { html.tt(':%s' % param.name) }
html.td(param.description)
end
end
end
m << b.to_s
end
def body_example(for_response_definition)
if for_response_definition.no_body?
'(empty)'
else
JSON.pretty_generate(for_response_definition.jsonable_object_example)
end
end
def possible_responses_table
return '' unless @definition.defines_responses?
m = MDBuf.new
b = StringBuf.new
m << '### Possible responses'
html = Builder::XmlMarkup.new(:target => b)
html.table(class: 'apiculture-table') do
html.tr do
html.th('HTTP status code')
html.th('What happened')
html.th('Example response body')
end
@definition.responses.each do | resp |
html.tr do
html.td { html.b(resp.http_status_code) }
html.td resp.description
html.td { html.pre { html.code(body_example(resp)) }}
end
end
end
m << b.to_s
end
def request_parameters_table
return '' unless @definition.defines_request_params?
m = MDBuf.new
m << '### Request parameters'
b = StringBuf.new
html = Builder::XmlMarkup.new(:target => b)
html.table(class: 'apiculture-table') do
html.tr do
html.th 'Name'
html.th 'Required'
html.th 'Type after cast'
html.th 'Description'
end
@definition.parameters.each do | param |
html.tr do
html.td { html.tt(param.name.to_s) }
html.td(param.required ? 'Yes' : 'No')
html.td(param.ruby_type.to_s)
html.td(param.description.to_s)
end
end
end
m << b
end
end