json-strict
Version:
Json Specification & Validation & Document Generation
78 lines (71 loc) • 1.79 kB
text/coffeescript
require 'coffee-mate/global'
{typeclass} = require './typeclass'
{Any} = require './prim/any'
TypeSpec = typeclass('TypeSpec').where
match: null
shape: (t) -> Any
constraints: (t) -> (v) => [
{
label: => "#{@show(t)} Expected, But Got #{json v}"
flag: => @match(t)(v)
}
]
withSpec: (t) -> (v) ->
if not @match(t)(v)
throw TypeError {expected: @show(t), got: v}
else
return v
show: (t) ->
t.name or 'UnnamedType'
samples: null
sample: (t) -> head @samples(t)
htmlInline: (t) ->
"<span class='type-maker'>#{@show t}</span>"
htmlBlock: (t) -> null
showHtml: (t) ->
specPart = do =>
block = @htmlBlock t
return """
<div class='spec'>
<div class='#{if block? then 'fold' else 'inline'}'><span class='meta-field'>spec</span>: #{@htmlInline t}</div>
#{if block? then (
"""
<div class='unfold'>
<span class='meta-field'>spec</span>: #{block.head}
#{block.body ? ''}
#{block.tail ? ''}
</div>
"""
) else ''}
</div>
""".replace(/(\t|\n)/g, '')
samplePart = do =>
s = prettyJson(@sample(t))
return """
<div class='sample'>
<span class='meta-field'>sample</span>: #{
if /\n/.test s then "<pre class='code'>#{s}</pre>" else "<span class='code'>#{s}</span>"
}
</div>
"""
return "<div class='typespec'>#{specPart + samplePart}</div>"
constraints = TypeSpec.constraints
unmatchMessages = (spec) -> (v) ->
r = []
rec = (ls) ->
rst = true
foreach ls, ({label, flag, sub}) ->
if flag?
if flag() is false
r.push label()
rst = false
foreach.break
else if sub?
if rec(sub()) is false
r.push label()
rst = false
foreach.break
return rst
rec(constraints(spec)(v))
return r.reverse()
module.exports = extend({unmatchMessages})(TypeSpec)