UNPKG

json-strict

Version:

Json Specification & Validation & Document Generation

109 lines (98 loc) 3.33 kB
require 'coffee-mate/global' {typeclass, instance} = require '../typeclass' {shape, match, constraints, show, samples, sample, htmlInline, htmlBlock} = require '../typespec' {expandBlockHead} = require '../helpers' class NamedType constructor: ({name, spec, desc, check, samples}) -> unless name? and spec? throw Error "Bad NamedType Definition: name & spec Must Be Specified" unless spec? and typeclass('TypeSpec').hasInstance(spec.constructor) throw Error "Bad NamedType Definition: TypeSpec as spec Expected, But Got #{spec}\n\tname: #{name}" unless not samples? or all(match(spec))(take(100) samples) throw Error "Bad NamedType Definition: samples Should Match spec\n\tname: #{name}\n\tspec: #{spec}" return { constructor: NamedType name spec desc check samples } instance('TypeSpec')(NamedType).where shape: ({spec}) -> shape(spec) match: ({spec, check}) -> (v) -> match(spec)(v) and (if check? then check(v) else true) constraints: ({spec, check, name}) -> (v) -> [ { label: -> "#{name} Expected" #, But Got #{v}" sub: -> constraints(spec)(v) } { label: -> "#{name} Expected to Satisfy #{check}, But Got #{json v}" flag: -> if check? then check(v) else true } ] show: ({name, spec}) -> name or (show spec) samples: ({spec, samples: ls}) -> if ls? then concat repeat ls else samples spec htmlInline: ({name, spec}) -> if name? then "<span class='type-name'>#{name}</span>" else htmlInline spec htmlBlock: ({name, spec}) -> expandBlockHead((head) -> "<span><span class='type-name'>#{name}</span><span class='spliter'>spec:</span>#{head}</span>" )(spec) ? { head: "<span><span class='type-name'>#{name}</span><span class='spliter'>spec:</span>#{htmlInline spec}</span>" } showHtml: (t) -> {name, desc, spec, check} = t namePart = if not name? then '' else """ <div class='name'> <span class='meta-field'>name</span>: <span class='type-name'>#{name}</span> </div> """ descriptionPart = if not desc? then '' else do -> s = desc return """ <div class='desc'> <span class='meta-field'>desc</span>: #{ if /\n/.test s then "<pre class='text'>#{s}</pre>" else "<span class='text'>#{s}</span>" } </div> """ specPart = do -> block = htmlBlock spec return """ <div class='spec'> <div class='#{if block? then 'fold' else 'inline'}'><span class='meta-field'>spec</span>: #{htmlInline spec}</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> """ checkPart = if not check? then '' else do -> s = check.toString() return """ <div class='check'> <span class='meta-field'>constraint</span>: #{ if /\n/.test s then "<pre class='code'>#{s}</pre>" else "<span class='code'>#{s}</span>" } </div> """ return "<div class='typespec'>#{ namePart + descriptionPart + specPart + samplePart + checkPart }</div>" module.exports = {NamedType}