'use strict'; /* jshint -W122 */ SwaggerUi.partials.signature = (function () { // copy-pasted from swagger-js var resolveSchema = function (schema) { if (_.isPlainObject(schema.schema)) { schema = resolveSchema(schema.schema); } return schema; }; // copy-pasted from swagger-js var simpleRef = function (name) { if (typeof name === 'undefined') { return null; } if (name.indexOf('#/definitions/') === 0) { return name.substring('#/definitions/'.length); } else { return name; } }; // copy-pasted from swagger-js var getInlineModel = function(inlineStr) { if(/^Inline Model \d+$/.test(inlineStr)) { var id = parseInt(inlineStr.substr('Inline Model'.length).trim(),10); // var model = this.inlineModels[id]; return model; } // I'm returning null here, should I rather throw an error? return null; }; // copy-pasted from swagger-js var formatXml = function(xml) { var contexp, fn, formatted, indent, l, lastType, len, lines, ln, pad, reg, transitions, wsexp; reg = /(>)(<)(\/*)/g; wsexp = /[ ]*(.*)[ ]+\n/g; contexp = /(<.+>)(.+\n)/g; xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2'); pad = 0; formatted = ''; lines = xml.split('\n'); indent = 0; lastType = 'other'; transitions = { 'single->single': 0, 'single->closing': -1, 'single->opening': 0, 'single->other': 0, 'closing->single': 0, 'closing->closing': -1, 'closing->opening': 0, 'closing->other': 0, 'opening->single': 1, 'opening->closing': 0, 'opening->opening': 1, 'opening->other': 1, 'other->single': 0, 'other->closing': -1, 'other->opening': 0, 'other->other': 0 }; fn = function(ln) { var fromTo, j, key, padding, type, types, value; types = { single: Boolean(ln.match(/<.+\/>/)), closing: Boolean(ln.match(/<\/.+>/)), opening: Boolean(ln.match(/<[^!?].*>/)) }; type = ((function() { var results; results = []; for (key in types) { value = types[key]; if (value) { results.push(key); } } return results; })())[0]; type = type === void 0 ? 'other' : type; fromTo = lastType + '->' + type; lastType = type; padding = ''; indent += transitions[fromTo]; padding = ((function() { var m, ref1, results; results = []; for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) { results.push(' '); } return results; })()).join(''); if (fromTo === 'opening->closing') { formatted = formatted.substr(0, formatted.length - 1) + ln + '\n'; } else { formatted += padding + ln + '\n'; } }; for (l = 0, len = lines.length; l < len; l++) { ln = lines[l]; fn(ln); } return formatted; }; // copy-pasted from swagger-js var getModelSignature = function (name, schema, models, modelPropertyMacro) { var strongOpen = ''; var strongClose = ''; var optionHtml = function (label, value) { return '' + label + ':' + value + ''; }; // Allow for ignoring the 'name' argument.... shifting the rest if(_.isObject(arguments[0])) { name = void 0; schema = arguments[0]; models = arguments[1]; modelPropertyMacro = arguments[2]; } models = models || {}; // Resolve the schema (Handle nested schemas) schema = resolveSchema(schema); // Return for empty object if(_.isEmpty(schema)) { return strongOpen + 'Empty' + strongClose; } // Dereference $ref from 'models' if(typeof schema.$ref === 'string') { name = simpleRef(schema.$ref); schema = models[name]; if(typeof schema === 'undefined') { return strongOpen + name + ' is not defined!' + strongClose; } } if(typeof name !== 'string') { name = schema.title || 'Inline Model'; } // If we are a Model object... adjust accordingly if(schema.definition) { schema = schema.definition; } if(typeof modelPropertyMacro !== 'function') { modelPropertyMacro = function(prop){ return (prop || {}).default; }; } var references = {}; var seenModels = []; var inlineModels = 0; // Generate current HTML var html = processModel(schema, name); // Generate references HTML while (_.keys(references).length > 0) { /* jshint ignore:start */ _.forEach(references, function (schema, name) { var seenModel = _.indexOf(seenModels, name) > -1; delete references[name]; if (!seenModel) { seenModels.push(name); html += '
' + processModel(schema, name); } }); /* jshint ignore:end */ } return html; function addReference(schema, name, skipRef) { var modelName = name; var model; if (schema.$ref) { modelName = schema.title || simpleRef(schema.$ref); model = models[simpleRef(schema.$ref)]; } else if (_.isUndefined(name)) { modelName = schema.title || 'Inline Model ' + (++inlineModels); model = {definition: schema}; } if (skipRef !== true) { references[modelName] = _.isUndefined(model) ? {} : model.definition; } return modelName; } function primitiveToHTML(schema) { var html = ''; var type = schema.type || 'object'; if (schema.$ref) { html += addReference(schema, simpleRef(schema.$ref)); } else if (type === 'object') { if (!_.isUndefined(schema.properties)) { html += addReference(schema); } else { html += 'object'; } } else if (type === 'array') { html += 'Array['; if (_.isArray(schema.items)) { html += _.map(schema.items, addReference).join(','); } else if (_.isPlainObject(schema.items)) { if (_.isUndefined(schema.items.$ref)) { if (!_.isUndefined(schema.items.type) && _.indexOf(['array', 'object'], schema.items.type) === -1) { html += schema.items.type; } else { html += addReference(schema.items); } } else { html += addReference(schema.items, simpleRef(schema.items.$ref)); } } else { console.log('Array type\'s \'items\' schema is not an array or an object, cannot process'); html += 'object'; } html += ']'; } else { html += schema.type; } html += ''; return html; } function primitiveToOptionsHTML(schema, html) { var options = ''; var type = schema.type || 'object'; var isArray = type === 'array'; if (isArray) { if (_.isPlainObject(schema.items) && !_.isUndefined(schema.items.type)) { type = schema.items.type; } else { type = 'object'; } } if (!_.isUndefined(schema.default)) { options += optionHtml('Default', schema.default); } switch (type) { case 'string': if (schema.minLength) { options += optionHtml('Min. Length', schema.minLength); } if (schema.maxLength) { options += optionHtml('Max. Length', schema.maxLength); } if (schema.pattern) { options += optionHtml('Reg. Exp.', schema.pattern); } break; case 'integer': case 'number': if (schema.minimum) { options += optionHtml('Min. Value', schema.minimum); } if (schema.exclusiveMinimum) { options += optionHtml('Exclusive Min.', 'true'); } if (schema.maximum) { options += optionHtml('Max. Value', schema.maximum); } if (schema.exclusiveMaximum) { options += optionHtml('Exclusive Max.', 'true'); } if (schema.multipleOf) { options += optionHtml('Multiple Of', schema.multipleOf); } break; } if (isArray) { if (schema.minItems) { options += optionHtml('Min. Items', schema.minItems); } if (schema.maxItems) { options += optionHtml('Max. Items', schema.maxItems); } if (schema.uniqueItems) { options += optionHtml('Unique Items', 'true'); } if (schema.collectionFormat) { options += optionHtml('Coll. Format', schema.collectionFormat); } } if (_.isUndefined(schema.items)) { if (_.isArray(schema.enum)) { var enumString; if (type === 'number' || type === 'integer') { enumString = schema.enum.join(', '); } else { enumString = '"' + schema.enum.join('", "') + '"'; } options += optionHtml('Enum', enumString); } } if (options.length > 0) { html = '' + html + '' + options + '
' + type + '
'; } return html; } function processModel(schema, name) { var type = schema.type || 'object'; var isArray = schema.type === 'array'; var html = strongOpen + name + ' ' + (isArray ? '[' : '{') + strongClose; var contents; if (name) { seenModels.push(name); } if (isArray) { if (_.isArray(schema.items)) { html += '
' + _.map(schema.items, function (item) { var type = item.type || 'object'; if (_.isUndefined(item.$ref)) { if (_.indexOf(['array', 'object'], type) > -1) { if (type === 'object' && _.isUndefined(item.properties)) { return 'object'; } else { return addReference(item); } } else { return primitiveToOptionsHTML(item, type); } } else { return addReference(item, simpleRef(item.$ref)); } }).join(',
'); } else if (_.isPlainObject(schema.items)) { if (_.isUndefined(schema.items.$ref)) { if (_.indexOf(['array', 'object'], schema.items.type || 'object') > -1) { if ((_.isUndefined(schema.items.type) || schema.items.type === 'object') && _.isUndefined(schema.items.properties)) { html += '
object
'; } else { html += '
' + addReference(schema.items) + '
'; } } else { html += '
' + primitiveToOptionsHTML(schema.items, schema.items.type) + '
'; } } else { html += '
' + addReference(schema.items, simpleRef(schema.items.$ref)) + '
'; } } else { console.log('Array type\'s \'items\' property is not an array or an object, cannot process'); html += '
object
'; } } else { if (schema.$ref) { html += '
' + addReference(schema, name) + '
'; } else if (type === 'object') { if (_.isPlainObject(schema.properties)) { contents = _.map(schema.properties, function (property, name) { var propertyIsRequired = (_.indexOf(schema.required, name) >= 0); var cProperty = _.cloneDeep(property); var requiredClass = propertyIsRequired ? 'required' : ''; var html = '' + name + ' ('; var model; var propDescription; // Allow macro to set the default value cProperty.default = modelPropertyMacro(cProperty); // Resolve the schema (Handle nested schemas) cProperty = resolveSchema(cProperty); propDescription = property.description || cProperty.description; // We need to handle property references to primitives (Issue 339) if (!_.isUndefined(cProperty.$ref)) { model = models[simpleRef(cProperty.$ref)]; if (!_.isUndefined(model) && _.indexOf([undefined, 'array', 'object'], model.definition.type) === -1) { // Use referenced schema cProperty = resolveSchema(model.definition); } } html += primitiveToHTML(cProperty); if(!propertyIsRequired) { html += ', optional'; } if(property.readOnly) { html += ', read only'; } html += ')'; if (!_.isUndefined(propDescription)) { html += ': ' + '' + propDescription + ''; } if (cProperty.enum) { html += ' = [\'' + cProperty.enum.join('\', \'') + '\']'; } return '' + primitiveToOptionsHTML(cProperty, html); }).join(',
'); } if (contents) { html += contents + ''; } } else { html += '
' + primitiveToOptionsHTML(schema, type) + '
'; } } return html + strongOpen + (isArray ? ']' : '}') + strongClose; } }; // copy-pasted from swagger-js var schemaToJSON = function (schema, models, modelsToIgnore, modelPropertyMacro) { // Resolve the schema (Handle nested schemas) schema = resolveSchema(schema); if(typeof modelPropertyMacro !== 'function') { modelPropertyMacro = function(prop){ return (prop || {}).default; }; } modelsToIgnore= modelsToIgnore || {}; var type = schema.type || 'object'; var format = schema.format; var model; var output; if (!_.isUndefined(schema.example)) { output = schema.example; } else if (_.isUndefined(schema.items) && _.isArray(schema.enum)) { output = schema.enum[0]; } if (_.isUndefined(output)) { if (schema.$ref) { model = models[simpleRef(schema.$ref)]; if (!_.isUndefined(model)) { if (_.isUndefined(modelsToIgnore[model.name])) { modelsToIgnore[model.name] = model; output = schemaToJSON(model.definition, models, modelsToIgnore, modelPropertyMacro); delete modelsToIgnore[model.name]; } else { if (model.type === 'array') { output = []; } else { output = {}; } } } } else if (!_.isUndefined(schema.default)) { output = schema.default; } else if (type === 'string') { if (format === 'date-time') { output = new Date().toISOString(); } else if (format === 'date') { output = new Date().toISOString().split('T')[0]; } else { output = 'string'; } } else if (type === 'integer') { output = 0; } else if (type === 'number') { output = 0.0; } else if (type === 'boolean') { output = true; } else if (type === 'object') { output = {}; _.forEach(schema.properties, function (property, name) { var cProperty = _.cloneDeep(property); // Allow macro to set the default value cProperty.default = modelPropertyMacro(property); output[name] = schemaToJSON(cProperty, models, modelsToIgnore, modelPropertyMacro); }); } else if (type === 'array') { output = []; if (_.isArray(schema.items)) { _.forEach(schema.items, function (item) { output.push(schemaToJSON(item, models, modelsToIgnore, modelPropertyMacro)); }); } else if (_.isPlainObject(schema.items)) { output.push(schemaToJSON(schema.items, models, modelsToIgnore, modelPropertyMacro)); } else if (_.isUndefined(schema.items)) { output.push({}); } else { console.log('Array type\'s \'items\' property is not an array or an object, cannot process'); } } } return output; }; // copy-pasted from swagger-js var createJSONSample = function (value, modelsToIgnore) { modelsToIgnore = modelsToIgnore || {}; modelsToIgnore[value.name] = value; // Response support if (value.examples && _.isPlainObject(value.examples) && value.examples['application/json']) { value.definition.example = value.examples['application/json']; if (_.isString(value.definition.example)) { value.definition.example = jsyaml.safeLoad(value.definition.example); } } else if (!value.definition.example) { value.definition.example = value.examples; } return schemaToJSON(value.definition, value.models, modelsToIgnore, value.modelPropertyMacro); }; // copy-pasted from swagger-js var getParameterModelSignature = function (type, definitions) { var isPrimitive, listType; if (type instanceof Array) { listType = true; type = type[0]; } // Convert undefined to string of 'undefined' if (typeof type === 'undefined') { type = 'undefined'; isPrimitive = true; } else if (definitions[type]){ // a model def exists? type = definitions[type]; /* Model */ isPrimitive = false; } else if (getInlineModel(type)) { type = getInlineModel(type); /* Model */ isPrimitive = false; } else { // We default to primitive isPrimitive = true; } if (isPrimitive) { if (listType) { return 'Array[' + type + ']'; } else { return type.toString(); } } else { if (listType) { return 'Array[' + getModelSignature(type.name, type.definition, type.models, type.modelPropertyMacro) + ']'; } else { return getModelSignature(type.name, type.definition, type.models, type.modelPropertyMacro); } } }; // copy-pasted from swagger-js var createParameterJSONSample = function (type, models) { var listType, sampleJson, innerType; models = models || {}; listType = (type instanceof Array); innerType = listType ? type[0] : type; if(models[innerType]) { sampleJson = createJSONSample(models[innerType]); } else if (getInlineModel(innerType)){ sampleJson = createJSONSample(getInlineModel(innerType)); // may return null, if type isn't correct } if (sampleJson) { sampleJson = listType ? [sampleJson] : sampleJson; if (typeof sampleJson === 'string') { return sampleJson; } else if (_.isObject(sampleJson)) { var t = sampleJson; if (sampleJson instanceof Array && sampleJson.length > 0) { t = sampleJson[0]; } if (t.nodeName && typeof t === 'Node') { var xmlString = new XMLSerializer().serializeToString(t); return formatXml(xmlString); } else { return JSON.stringify(sampleJson, null, 2); } } else { return sampleJson; } } }; var wrapTag = function (name, value, attrs) { var str, attributes; attrs = attrs || []; attributes = attrs.map(function (attr) { return ' ' + attr.name + '="' + attr.value + '"'; }).join(''); if (!name) { return getErrorMessage('Node name is not provided'); } str = [ '<', name, attributes, '>', value, '' ]; return str.join(''); }; var getName = function (name, xml) { var result = name || ''; xml = xml || {}; if (xml.name) { result = xml.name; } if (xml.prefix) { result = xml.prefix + ':' + result; } return result; }; var getNamespace = function (xml) { var namespace = ''; var name = 'xmlns'; xml = xml || {}; if (xml.namespace) { namespace = xml.namespace; } else { return namespace; } if (xml.prefix) { name += ':' + xml.prefix; } return { name: name, value: namespace }; }; var createArrayXML = function (descriptor) { var name = descriptor.name; var config = descriptor.config; var definition = descriptor.definition; var models = descriptor.models; var value; var items = definition.items; var xml = definition.xml || {}; if (!items) { return getErrorMessage(); } value = createSchemaXML(name, items, models, config); xml = xml || {}; if (xml.wrapped) { value = wrapTag(name, value); } return value; }; var getPrimitiveSignature = function (schema) { var type, items; schema = schema || {}; items = schema.items || {}; type = schema.type || ''; switch (type) { case 'object': return 'Object is not a primitive'; case 'array' : return 'Array[' + (items.format || items.type) + ']'; default: return schema.format || type; } }; var createPrimitiveXML = function (descriptor) { var name = descriptor.name; var definition = descriptor.definition; var primitivesMap = { 'string': { 'date': new Date(1).toISOString().split('T')[0], 'date-time' : new Date(1).toISOString(), 'default': 'string' }, 'integer': { 'default': 1 }, 'number': { 'default': 1.1 }, 'boolean': { 'default': true } }; var type = definition.type; var format = definition.format; var xml = definition.xml || {}; var namespace = getNamespace(xml); var attributes = []; var value; if (_.keys(primitivesMap).indexOf(type) < 0) { return getErrorMessage(); } if (_.isArray(definition.enum)){ value = definition.enum[0]; } else { value = definition.example || primitivesMap[type][format] || primitivesMap[type].default; } if (xml.attribute) { return {name: name, value: value}; } if (namespace) { attributes.push(namespace); } return wrapTag(name, value, attributes); }; function createObjectXML (descriptor) { var name = descriptor.name; var definition = descriptor.definition; var config = descriptor.config; var models = descriptor.models; var isParam = descriptor.config.isParam; var serializedProperties; var attrs = []; var properties = definition.properties; var additionalProperties = definition.additionalProperties; var xml = definition.xml; var namespace = getNamespace(xml); if (namespace) { attrs.push(namespace); } if (!properties && !additionalProperties) { return getErrorMessage(); } properties = properties || {}; serializedProperties = _.map(properties, function (prop, key) { var xml, result; if (isParam && prop.readOnly) { return ''; } xml = prop.xml || {}; result = createSchemaXML(key, prop, models, config); if (xml.attribute) { attrs.push(result); return ''; } return result; }).join(''); if (additionalProperties) { serializedProperties += ''; } return wrapTag(name, serializedProperties, attrs); } function getInfiniteLoopMessage (name) { return ''; } function getErrorMessage (details) { details = details ? ': ' + details : ''; return ''; } function createSchemaXML (name, definition, models, config) { var $ref = _.isObject(definition) ? definition.$ref : null; var output, index; config = config || {}; config.modelsToIgnore = config.modelsToIgnore || []; var descriptor = _.isString($ref) ? getDescriptorByRef($ref, name, models, config) : getDescriptor(name, definition, models, config); if (!descriptor) { return getErrorMessage(); } switch (descriptor.type) { case 'array': output = createArrayXML(descriptor); break; case 'object': output = createObjectXML(descriptor); break; case 'loop': output = getInfiniteLoopMessage(descriptor.name); break; default: output = createPrimitiveXML(descriptor); } if ($ref) { index = config.modelsToIgnore.indexOf($ref); if (index > -1) { config.modelsToIgnore.splice(index, 1); } } return output; } function Descriptor (name, type, definition, models, config) { if (arguments.length < 4) { throw new Error(); } this.config = config || {}; this.config.modelsToIgnore = this.config.modelsToIgnore || []; this.name = getName(name, definition.xml); this.definition = definition; this.models = models; this.type = type; } function getDescriptorByRef($ref, name, models, config) { var modelType = simpleRef($ref); var model = models[modelType] || {}; var type = model.type || 'object'; name = name || model.name; if (config.modelsToIgnore.indexOf($ref) > -1) { type = 'loop'; name = modelType; } else { config.modelsToIgnore.push($ref); } if (!model.definition) { return null; } return new Descriptor(name, type, model.definition, models, config); } function getDescriptor (name, definition, models, config){ var type = definition.type || 'object'; if (!definition) { return null; } return new Descriptor(name, type, definition, models, config); } function createXMLSample (definition, models, isParam) { var prolog = ''; return formatXml(prolog + createSchemaXML('', definition, models, { isParam: isParam } )); } return { getModelSignature: getModelSignature, createJSONSample: createJSONSample, getParameterModelSignature: getParameterModelSignature, createParameterJSONSample: createParameterJSONSample, createSchemaXML: createSchemaXML, createXMLSample: createXMLSample, getPrimitiveSignature: getPrimitiveSignature }; })();