diff --git a/lib/components/JsonSchema/json-schema-common.scss b/lib/components/JsonSchema/json-schema-common.scss index a939c365..d4ae7d5a 100644 --- a/lib/components/JsonSchema/json-schema-common.scss +++ b/lib/components/JsonSchema/json-schema-common.scss @@ -47,6 +47,10 @@ $sub-schema-offset: ($bullet-size/2) + $bullet-margin; width: 75%; } +.param-range { + color: rgba($primary-color, .7); +} + .param-description { font-size: 13px; } diff --git a/lib/components/JsonSchema/json-schema.html b/lib/components/JsonSchema/json-schema.html index c43fe903..c22bc7e8 100644 --- a/lib/components/JsonSchema/json-schema.html +++ b/lib/components/JsonSchema/json-schema.html @@ -11,7 +11,9 @@
{{prop._displayType}} {{prop._displayFormat}} + title="{{prop._displayTypeHint}}"> {{prop._displayType}} {{prop._displayFormat}} + {{prop._range}} + Required
{{enumItem.val | json}} diff --git a/lib/components/JsonSchema/json-schema.js b/lib/components/JsonSchema/json-schema.js index 29b547d9..efb2be8a 100644 --- a/lib/components/JsonSchema/json-schema.js +++ b/lib/components/JsonSchema/json-schema.js @@ -71,11 +71,13 @@ export default class JsonSchema extends BaseComponent { let discriminatorFieldIdx = -1; let props = Object.keys(schema.properties).map((prop, idx) => { - let propData = schema.properties[prop]; + let propertySchema = schema.properties[prop]; let propPointer = JsonPointer.join(this.pointer, ['properties', prop]); - propData = JsonSchema.injectPropData(propData, prop, propPointer, this.requiredMap, schema); - if (propData.isDiscriminator) discriminatorFieldIdx = idx; - return propData; + propertySchema = JsonSchema.injectPropertyData(propertySchema, prop, propPointer); + propertySchema.required = !!this.requiredMap[prop]; + propertySchema.isDiscriminator = (schema.discriminator === prop); + if (propertySchema.isDiscriminator) discriminatorFieldIdx = idx; + return propertySchema; }); // Move discriminator field to the end of properties list if (discriminatorFieldIdx > -1) { @@ -85,49 +87,104 @@ export default class JsonSchema extends BaseComponent { this.data.properties = props; } - static injectPropData(propData, propName, propPointer, requiredMap, schema) { - let propEnum; + static injectPropertyData(propertySchema, propertyName, propPointer) { + propertySchema = Object.assign({}, propertySchema); - propData = Object.assign({}, propData); - propData._name = propName; - propData.required = propData.required || (requiredMap && requiredMap[propName]); - propData._displayType = propData.type; - propData.isDiscriminator = (schema && schema.discriminator === propName); - propEnum = propData.enum; - if (propData.type === 'array') { - let itemType = propData.items.type; - let itemFormat = propData.items.format; - propEnum = propData.items.enum; - if (itemType === 'object' || !itemType) { - itemType = propData.items.title || 'object'; - propData._pointer = propData.items._pointer - || JsonPointer.join(propPointer, ['items']); - } - propData._displayType = `${itemType}`; - propData.format = itemFormat; - propData._isArray = true; - propData.type = 'array ' + propData.items.type; - } else if (propData.type === 'object' && propData.properties) { - propData._displayType = propData.title || 'object'; - } else if (!propData.type) { - propData._displayType = '< * >'; - propData._displayTypeHint = 'This field may contain data of any type'; - } else { - // here we are sure that property has simple type (integer, string, object withou properties) - // delete pointer for simple types to not show it as subschema - if (propData._pointer) { - propData._pointer = undefined; - propData._displayType = propData.title ? `${propData.title} (${propData.type})` : propData.type; - } - } + propertySchema._name = propertyName; + runInjectors(propertySchema, propertySchema, propPointer); - if (propData.format) propData._displayFormat = `<${propData.format}>`; - if (propEnum) { - propData.enum = propEnum.map((value) => { - return {val: value, type: typeof value}; - }); - } - - return propData; + return propertySchema; } } + +function runInjectors(injectTo, propertySchema, propertyPointer) { + for (var injName in injectors) { + let injector = injectors[injName]; + if (injector.check(propertySchema)) { + injector.inject(injectTo, propertySchema, propertyPointer); + } + } +} + +const injectors = { + general: { + check: () => true, + inject: (injectTo, propertySchema) => { + injectTo._displayType = propertySchema.type; + if (propertySchema.format) injectTo._displayFormat = `<${propertySchema.format}>`; + if (propertySchema.enum) { + injectTo.enum = propertySchema.enum.map((value) => { + return {val: value, type: typeof value}; + }); + } + } + }, + + array: { + check: (propertySchema) => { + return propertySchema.type === 'array'; + }, + inject: (injectTo, propertySchema = injectTo, propPointer) => { + injectTo._isArray = true; + injectTo._pointer = propertySchema.items._pointer + || JsonPointer.join(propertySchema._pointer || propPointer, ['items']); + + runInjectors(injectTo, propertySchema.items, propPointer); + } + }, + + object: { + check: (propertySchema) => { + return propertySchema.type === 'object' && propertySchema.properties; + }, + inject: (injectTo, propertySchema = injectTo) => { + injectTo._displayType = propertySchema.title || 'object'; + } + }, + noType: { + check: (propertySchema) => !propertySchema.type, + inject: (injectTo) => { + injectTo._displayType = '< * >'; + injectTo._displayTypeHint = 'This field may contain data of any type'; + } + }, + + simpleType: { + check: (propertySchema) => { + if (propertySchema.type === 'object') { + return !propertySchema.properties; + } + return (propertySchema.type !== 'array') && propertySchema.type; + }, + inject: (injectTo, propertySchema = injectTo) => { + if (injectTo._pointer) { + injectTo._pointer = undefined; + injectTo._displayType = propertySchema.title ? + `${propertySchema.title} (${propertySchema.type})` : propertySchema.type; + } + } + }, + integer: { + check: (propertySchema) => (propertySchema.type === 'integer' || propertySchema.type === 'number'), + inject: (injectTo, propertySchema = injectTo) => { + var range = ''; + if (propertySchema.minimum && propertySchema.maximum) { + range += propertySchema.exclusiveMinimum ? '( ' : '[ '; + range += propertySchema.minimum; + range += ' .. '; + range += propertySchema.maximum; + range += propertySchema.exclusiveMaximum ? ' )' : ' ]'; + } else if (propertySchema.maximum) { + range += propertySchema.exclusiveMaximum? '< ' : '<= '; + range += propertySchema.maximum; + } else if (propertySchema.minimum) { + range += propertySchema.exclusiveMinimum ? '> ' : '>= '; + range += propertySchema.minimum; + } + + if (range) { + injectTo._range = range; + } + } + } +}; diff --git a/lib/components/ParamsList/params-list.js b/lib/components/ParamsList/params-list.js index 957d18b4..57dbeeeb 100644 --- a/lib/components/ParamsList/params-list.js +++ b/lib/components/ParamsList/params-list.js @@ -27,7 +27,7 @@ export default class ParamsList extends BaseComponent { paramsList = paramsList.map((paramData) => { let propPointer = paramData._pointer; if (paramData.in === 'body') return paramData; - return JsonSchema.injectPropData(paramData, paramData.name, propPointer); + return JsonSchema.injectPropertyData(paramData, paramData.name, propPointer); }); let paramsMap = this.orderParams(paramsList); diff --git a/package.json b/package.json index 243c79ca..197f16d2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "redoc", "description": "Swagger-generated API Reference Documentation", - "version": "0.7.3", + "version": "0.7.4", "repository": { "type": "git", "url": "git://github.com/Rebilly/ReDoc"