# An BasePresenter for a JSON Schema fragment. Like most JSON
# schema things, has a tendency to recurse.
class Lurker::SchemaPresenter < Lurker::BasePresenter
attr_reader :schema
FORMATTED_KEYS = %w(
description
type
required
example
deprecated
default
format
enum
items
properties
$ref
)
def initialize(schema, options)
options[:nested] ||= 0
super(options)
@schema = schema
end
def request?
options[:request]
end
def nested?
options[:nested] > 0
end
def to_html(parent_key=nil)
html = StringIO.new
html << 'Deprecated' if deprecated?
html << '
'
html << @schema["description"]
html << '
'
begin
html << '- Required: %s
' % required?(parent_key) if nested?
html << '- Type: %s
' % type if type
html << '- Format: %s
' % format if format
html << '- Example: %s
' % example.to_html if example
html << enum_html
(@schema.keys - FORMATTED_KEYS).each do |key|
value = @schema[key]
value = value.to_hash if value.is_a?(Lurker::Json::Schema)
html << '- %s: %s
' % [key, value]
end
html << items_html
html << properties_html
end
html << '
'
html << '
'
html.string
end
def type
t = @schema["type"]
if t.is_a? Array
types = t.map do |type|
if type.is_a? Hash
'%s' % self.class.new(type, options.merge(parent: self)).to_html
else
'%s' % type
end
end.join('')
'' % types
elsif t != "object"
t
end
end
def format
@schema["format"]
end
def example
return unless @schema.key?("example")
Lurker::JsonPresenter.new(@schema["example"])
end
def deprecated?
@schema["deprecated"]
end
def required?(parent_key=nil)
((options[:parent].schema['required'] || []).include?(parent_key)) ? "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"]
return if items.size == 0
html = ""
html << 'Items'
sub_options = options.merge(:nested => options[:nested] + 1, :parent => self)
if items.respond_to?(:each_pair)
html << self.class.new(items, sub_options).to_html
else
items.each do |item|
html << self.class.new(item, sub_options).to_html if item
end
end
html << ''
html
end
def properties_html
properties = if (props = @schema["properties"]).present?
props
elsif (ref_path = @schema["$ref"]).present?
ref = Lurker::RefObject.new(ref_path, options[:root_path])
options[:root_path] = options[:root_path].merge(ref_path.sub(/#[^#]*?$/, ''))
ref.schema["properties"]
else
nil
end
return unless 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 => options[:nested] + 1, :parent => self)).to_html(key)
html << ''
end
html
end
def schema_slug(key, property)
"#{key}-#{options[:nested]}-#{property.hash}"
end
end