# An HtmlPresenter for a JSON Schema fragment. Like most JSON
# schema things, has a tendency to recurse.
class Fdoc::SchemaPresenter < Fdoc::HtmlPresenter
FORMATTED_KEYS = %w(
description
type
required
example
deprecated
default
format
enum
items
properties
)
def initialize(schema, options)
super(options)
@schema = schema
end
def request?
options[:request]
end
def nested?
options[:nested]
end
def to_html
html = StringIO.new
html << 'Deprecated' if deprecated?
html << '
'
html << render_markdown(@schema["description"])
html << '
'
begin
html << '- Required: %s
' % required? if nested?
html << '- Type: %s
' % type if type
html << '- Format: %s
' % format if format
html << '- Example: %s
' % example if example
html << enum_html
(@schema.keys - FORMATTED_KEYS).each do |key|
html << '- %s: %s
' % [ key, @schema[key] ]
end
html << items_html
html << properties_html
end
html << '
'
html << '
'
html.string
end
def type
t = @schema["type"]
if t.kind_of? Array
types = t.map do |type|
if type.kind_of? Hash
'%s' % self.class.new(type, options).to_html
else
'%s' % type
end
end.join('')
'' % types
elsif t != "object"
t
end
end
def format
@schema["format"]
end
def example
return unless e = @schema["example"]
render_json(e)
end
def deprecated?
@schema["deprecated"]
end
def required?
@schema["required"] ? "yes" : "no"
end
def enum_html
enum = @schema["enum"]
return unless enum
list = enum.map do |e|
'%s' % e
end.join(", ")
html = StringIO.new
html << 'Enum: '
html << list
html << ''
html.string
end
def items_html
return unless items = @schema["items"]
html = ""
html << 'Items'
sub_options = options.merge(:nested => true)
if items.kind_of? Array
item.compact.each do |item|
html << self.class.new(item, sub_options).to_html
end
else
html << self.class.new(items, sub_options).to_html
end
html << ''
html
end
def properties_html
return unless properties = @schema["properties"]
html = ""
properties.each do |key, property|
next if property.nil?
html << ''
html << tag_with_anchor(
'span',
'%s' % key,
schema_slug(key, property)
)
html << self.class.new(property, options.merge(:nested => true)).to_html
html << ''
end
html
end
def schema_slug(key, property)
"#{key}-#{property.hash}"
end
end