merged
This commit is contained in:
@@ -10,6 +10,7 @@ SwaggerUi.Views.OperationView = Backbone.View.extend({
|
||||
'click .toggleOperation' : 'toggleOperationContent',
|
||||
'mouseenter .api-ic' : 'mouseEnter',
|
||||
'dblclick .curl' : 'selectText',
|
||||
'change [name=responseContentType]' : 'showSnippet'
|
||||
},
|
||||
|
||||
initialize: function(opts) {
|
||||
@@ -84,7 +85,7 @@ SwaggerUi.Views.OperationView = Backbone.View.extend({
|
||||
// Note: copied from CoffeeScript compiled file
|
||||
// TODO: redactor
|
||||
render: function() {
|
||||
var a, auth, auths, code, contentTypeModel, isMethodSubmissionSupported, k, key, l, len, len1, len2, len3, len4, m, modelAuths, n, o, p, param, q, ref, ref1, ref2, ref3, ref4, ref5, responseContentTypeView, responseSignatureView, schema, schemaObj, scopeIndex, signatureModel, statusCode, successResponse, type, v, value;
|
||||
var a, auth, auths, code, contentTypeModel, isMethodSubmissionSupported, k, key, l, len, len1, len2, len3, len4, m, modelAuths, n, o, p, param, q, ref, ref1, ref2, ref3, ref4, ref5, responseContentTypeView, responseSignatureView, schema, schemaObj, scopeIndex, signatureModel, statusCode, successResponse, type, v, value, produces, isXML, isJSON;
|
||||
isMethodSubmissionSupported = jQuery.inArray(this.model.method, this.model.supportedSubmitMethods()) >= 0;
|
||||
if (!isMethodSubmissionSupported) {
|
||||
this.model.isReadOnly = true;
|
||||
@@ -163,6 +164,10 @@ SwaggerUi.Views.OperationView = Backbone.View.extend({
|
||||
this.model.responseMessages = [];
|
||||
}
|
||||
signatureModel = null;
|
||||
produces = this.model.produces;
|
||||
isXML = this.contains(produces, 'xml');
|
||||
isJSON = isXML ? this.contains(produces, 'json') : true;
|
||||
|
||||
if (this.model.successResponse) {
|
||||
successResponse = this.model.successResponse;
|
||||
for (key in successResponse) {
|
||||
@@ -172,9 +177,10 @@ SwaggerUi.Views.OperationView = Backbone.View.extend({
|
||||
this.model.successDescription = value.description;
|
||||
this.model.headers = this.parseResponseHeaders(value.headers);
|
||||
signatureModel = {
|
||||
sampleJSON: JSON.stringify(value.createJSONSample(), void 0, 2),
|
||||
sampleJSON: isJSON ? JSON.stringify(SwaggerUi.partials.signature.createJSONSample(value), void 0, 2) : false,
|
||||
isParam: false,
|
||||
signature: value.getMockSignature()
|
||||
sampleXML: isXML ? SwaggerUi.partials.signature.createXMLSample(value.definition, value.models) : false,
|
||||
signature: SwaggerUi.partials.signature.getModelSignature(value.name, value.definition, value.models, value.modelPropertyMacro)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -230,6 +236,7 @@ SwaggerUi.Views.OperationView = Backbone.View.extend({
|
||||
router: this.router
|
||||
});
|
||||
$('.response-content-type', $(this.el)).append(responseContentTypeView.render().el);
|
||||
this.showSnippet();
|
||||
ref4 = this.model.parameters;
|
||||
for (p = 0, len3 = ref4.length; p < len3; p++) {
|
||||
param = ref4[p];
|
||||
@@ -243,6 +250,14 @@ SwaggerUi.Views.OperationView = Backbone.View.extend({
|
||||
return this;
|
||||
},
|
||||
|
||||
contains: function (produces, type) {
|
||||
return produces.filter(function (val) {
|
||||
if (val.indexOf(type) > -1) {
|
||||
return true;
|
||||
}
|
||||
}).length;
|
||||
},
|
||||
|
||||
parseResponseHeaders: function (data) {
|
||||
var HEADERS_SEPARATOR = '; ';
|
||||
var headers = _.clone(data);
|
||||
@@ -757,6 +772,22 @@ SwaggerUi.Views.OperationView = Backbone.View.extend({
|
||||
}
|
||||
},
|
||||
|
||||
showSnippet: function () {
|
||||
var contentTypeEl = this.$('[name=responseContentType]');
|
||||
var contentType;
|
||||
|
||||
if (!contentTypeEl.length) { return; }
|
||||
contentType = contentTypeEl.val();
|
||||
|
||||
if (contentType.indexOf('xml') > -1) {
|
||||
this.$('.snippet_xml').show();
|
||||
this.$('.snippet_json').hide();
|
||||
} else {
|
||||
this.$('.snippet_json').show();
|
||||
this.$('.snippet_xml').hide();
|
||||
}
|
||||
},
|
||||
|
||||
getParamByName: function(name) {
|
||||
var i;
|
||||
if (this.model.parameters) {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
SwaggerUi.Views.ParameterView = Backbone.View.extend({
|
||||
events: {
|
||||
'change [name=parameterContentType]' : 'toggleParameterSnippet'
|
||||
},
|
||||
|
||||
initialize: function(){
|
||||
Handlebars.registerHelper('isArray', function(param, opts) {
|
||||
if (param.type.toLowerCase() === 'array' || param.allowMultiple) {
|
||||
@@ -13,10 +17,14 @@ SwaggerUi.Views.ParameterView = Backbone.View.extend({
|
||||
|
||||
render: function() {
|
||||
var type = this.model.type || this.model.dataType;
|
||||
var modelType = this.model.modelSignature.type;
|
||||
var modelDefinitions = this.model.modelSignature.definitions;
|
||||
var schema = this.model.schema || {};
|
||||
var consumes = this.model.consumes || [];
|
||||
|
||||
|
||||
if (typeof type === 'undefined') {
|
||||
var schema = this.model.schema;
|
||||
if (schema && schema.$ref) {
|
||||
if (schema.$ref) {
|
||||
var ref = schema.$ref;
|
||||
if (ref.indexOf('#/definitions/') === 0) {
|
||||
type = ref.substring('#/definitions/'.length);
|
||||
@@ -43,13 +51,17 @@ SwaggerUi.Views.ParameterView = Backbone.View.extend({
|
||||
this.model.isList = true;
|
||||
}
|
||||
|
||||
var isXML = this.contains(consumes, 'xml');
|
||||
var isJSON = isXML ? this.contains(consumes, 'json') : true;
|
||||
|
||||
var template = this.template();
|
||||
$(this.el).html(template(this.model));
|
||||
|
||||
var signatureModel = {
|
||||
sampleJSON: this.model.sampleJSON,
|
||||
sampleJSON: isJSON ? SwaggerUi.partials.signature.createParameterJSONSample(modelType, modelDefinitions) : false,
|
||||
sampleXML: isXML ? SwaggerUi.partials.signature.createXMLSample(schema, modelDefinitions, true) : false,
|
||||
isParam: true,
|
||||
signature: this.model.signature,
|
||||
signature: SwaggerUi.partials.signature.getParameterModelSignature(modelType, modelDefinitions),
|
||||
defaultRendering: this.model.defaultRendering
|
||||
};
|
||||
|
||||
@@ -65,12 +77,12 @@ SwaggerUi.Views.ParameterView = Backbone.View.extend({
|
||||
|
||||
if( this.options.swaggerOptions.jsonEditor && this.model.isBody && this.model.schema){
|
||||
var $self = $(this.el);
|
||||
this.model.jsonEditor =
|
||||
this.model.jsonEditor =
|
||||
/* global JSONEditor */
|
||||
new JSONEditor($('.editor_holder', $self)[0],
|
||||
{schema: this.model.schema, startval : this.model.default,
|
||||
ajax:true,
|
||||
disable_properties:true,
|
||||
{schema: this.model.schema, startval : this.model.default,
|
||||
ajax:true,
|
||||
disable_properties:true,
|
||||
disable_edit_json:true,
|
||||
iconlib: 'swagger' });
|
||||
// This is so that the signature can send back the sample to the json editor
|
||||
@@ -107,16 +119,50 @@ SwaggerUi.Views.ParameterView = Backbone.View.extend({
|
||||
if (isParam) {
|
||||
var parameterContentTypeView = new SwaggerUi.Views.ParameterContentTypeView({model: contentTypeModel});
|
||||
$('.parameter-content-type', $(this.el)).append(parameterContentTypeView.render().el);
|
||||
this.toggleParameterSnippet();
|
||||
}
|
||||
|
||||
else {
|
||||
var responseContentTypeView = new SwaggerUi.Views.ResponseContentTypeView({model: contentTypeModel});
|
||||
$('.response-content-type', $(this.el)).append(responseContentTypeView.render().el);
|
||||
this.toggleResponseSnippet();
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
contains: function (consumes, type) {
|
||||
return consumes.filter(function (val) {
|
||||
if (val.indexOf(type) > -1) {
|
||||
return true;
|
||||
}
|
||||
}).length;
|
||||
},
|
||||
|
||||
toggleParameterSnippet: function () {
|
||||
var contentType = this.$('[name=parameterContentType]').val();
|
||||
|
||||
this.toggleSnippet(contentType);
|
||||
},
|
||||
|
||||
toggleResponseSnippet: function () {
|
||||
var contentEl = this.$('[name=responseContentType]');
|
||||
|
||||
if (!contentEl.length) { return; }
|
||||
|
||||
this.toggleSnippet(contentEl.val());
|
||||
},
|
||||
|
||||
toggleSnippet: function (type) {
|
||||
if (type.indexOf('xml') > -1) {
|
||||
this.$('.snippet_xml').show();
|
||||
this.$('.snippet_json').hide();
|
||||
} else {
|
||||
this.$('.snippet_json').show();
|
||||
this.$('.snippet_xml').hide();
|
||||
}
|
||||
},
|
||||
|
||||
// Return an appropriate template based on if the parameter is a list, readonly, required
|
||||
template: function(){
|
||||
if (this.model.isList) {
|
||||
|
||||
@@ -4,7 +4,8 @@ SwaggerUi.Views.SignatureView = Backbone.View.extend({
|
||||
events: {
|
||||
'click a.description-link' : 'switchToDescription',
|
||||
'click a.snippet-link' : 'switchToSnippet',
|
||||
'mousedown .snippet' : 'snippetToTextArea'
|
||||
'mousedown .snippet_json' : 'jsonSnippetMouseDown',
|
||||
'mousedown .snippet_xml' : 'xmlSnippetMouseDown'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
@@ -20,12 +21,6 @@ SwaggerUi.Views.SignatureView = Backbone.View.extend({
|
||||
} else {
|
||||
this.switchToSnippet();
|
||||
}
|
||||
|
||||
this.isParam = this.model.isParam;
|
||||
|
||||
if (this.isParam) {
|
||||
$('.notice', $(this.el)).text('Click to set as parameter value');
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
@@ -44,27 +39,39 @@ SwaggerUi.Views.SignatureView = Backbone.View.extend({
|
||||
switchToSnippet: function(e){
|
||||
if (e) { e.preventDefault(); }
|
||||
|
||||
$('.description', $(this.el)).hide();
|
||||
$('.snippet', $(this.el)).show();
|
||||
$('.description', $(this.el)).hide();
|
||||
$('.snippet-link', $(this.el)).addClass('selected');
|
||||
$('.description-link', $(this.el)).removeClass('selected');
|
||||
},
|
||||
|
||||
// handler for snippet to text area
|
||||
snippetToTextArea: function(e) {
|
||||
if (this.isParam) {
|
||||
snippetToTextArea: function(val) {
|
||||
var textArea = $('textarea', $(this.el.parentNode.parentNode.parentNode));
|
||||
|
||||
// Fix for bug in IE 10/11 which causes placeholder text to be copied to "value"
|
||||
if ($.trim(textArea.val()) === '' || textArea.prop('placeholder') === textArea.val()) {
|
||||
textArea.val(val);
|
||||
// TODO move this code outside of the view and expose an event instead
|
||||
if( this.model.jsonEditor && this.model.jsonEditor.isEnabled()){
|
||||
this.model.jsonEditor.setValue(JSON.parse(this.model.sampleJSON));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
jsonSnippetMouseDown: function (e) {
|
||||
if (this.model.isParam) {
|
||||
if (e) { e.preventDefault(); }
|
||||
|
||||
var textArea = $('textarea', $(this.el.parentNode.parentNode.parentNode));
|
||||
this.snippetToTextArea(this.model.sampleJSON);
|
||||
}
|
||||
},
|
||||
|
||||
// Fix for bug in IE 10/11 which causes placeholder text to be copied to "value"
|
||||
if ($.trim(textArea.val()) === '' || textArea.prop('placeholder') === textArea.val()) {
|
||||
textArea.val(this.model.sampleJSON);
|
||||
// TODO move this code outside of the view and expose an event instead
|
||||
if( this.model.jsonEditor && this.model.jsonEditor.isEnabled()){
|
||||
this.model.jsonEditor.setValue(JSON.parse(this.model.sampleJSON));
|
||||
}
|
||||
}
|
||||
xmlSnippetMouseDown: function (e) {
|
||||
if (this.model.isParam) {
|
||||
if (e) { e.preventDefault(); }
|
||||
|
||||
this.snippetToTextArea(this.model.sampleXML);
|
||||
}
|
||||
}
|
||||
});
|
||||
899
src/main/javascript/view/partials/signature.js
Normal file
899
src/main/javascript/view/partials/signature.js
Normal file
@@ -0,0 +1,899 @@
|
||||
'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 = '<span class="strong">';
|
||||
var strongClose = '</span>';
|
||||
|
||||
var optionHtml = function (label, value) {
|
||||
return '<tr><td class="optionName">' + label + ':</td><td>' + value + '</td></tr>';
|
||||
};
|
||||
|
||||
|
||||
// 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 += '<br />' + 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[modelName];
|
||||
} 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 = '<span class="propType">';
|
||||
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 += '</span>';
|
||||
|
||||
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 = '<span class="propWrap">' + html + '<table class="optionsWrapper"><tr><th colspan="2">' + type + '</th></tr>' + options + '</table></span>';
|
||||
}
|
||||
|
||||
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 += '<div>' + _.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(',</div><div>');
|
||||
} 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 += '<div>object</div>';
|
||||
} else {
|
||||
html += '<div>' + addReference(schema.items) + '</div>';
|
||||
}
|
||||
} else {
|
||||
html += '<div>' + primitiveToOptionsHTML(schema.items, schema.items.type) + '</div>';
|
||||
}
|
||||
} else {
|
||||
html += '<div>' + addReference(schema.items, simpleRef(schema.items.$ref)) + '</div>';
|
||||
}
|
||||
} else {
|
||||
console.log('Array type\'s \'items\' property is not an array or an object, cannot process');
|
||||
html += '<div>object</div>';
|
||||
}
|
||||
} else {
|
||||
if (schema.$ref) {
|
||||
html += '<div>' + addReference(schema, name) + '</div>';
|
||||
} 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 = '<span class="propName ' + requiredClass + '">' + name + '</span> (';
|
||||
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 += ', <span class="propOptKey">optional</span>';
|
||||
}
|
||||
|
||||
if(property.readOnly) {
|
||||
html += ', <span class="propReadOnly">read only</span>';
|
||||
}
|
||||
|
||||
html += ')';
|
||||
|
||||
if (!_.isUndefined(propDescription)) {
|
||||
html += ': ' + '<span class="propDesc">' + propDescription + '</span>';
|
||||
}
|
||||
|
||||
if (cProperty.enum) {
|
||||
html += ' = <span class="propVals">[\'' + cProperty.enum.join('\', \'') + '\']</span>';
|
||||
}
|
||||
|
||||
return '<div' + (property.readOnly ? ' class="readOnly"' : '') + '>' + primitiveToOptionsHTML(cProperty, html);
|
||||
}).join(',</div>');
|
||||
}
|
||||
|
||||
if (contents) {
|
||||
html += contents + '</div>';
|
||||
}
|
||||
} else {
|
||||
html += '<div>' + primitiveToOptionsHTML(schema, type) + '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
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('');
|
||||
|
||||
str = [
|
||||
'<', name,
|
||||
attributes,
|
||||
'>',
|
||||
value,
|
||||
'</', name, '>'
|
||||
];
|
||||
|
||||
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 = 'xlmns';
|
||||
|
||||
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 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);
|
||||
value += value;
|
||||
|
||||
xml = xml || {};
|
||||
|
||||
if (xml.wrapped) {
|
||||
value = wrapTag(name, value);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
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 models = descriptor.models;
|
||||
var isParam = descriptor.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);
|
||||
|
||||
if (xml.attribute) {
|
||||
attrs.push(result);
|
||||
return '';
|
||||
}
|
||||
|
||||
return result;
|
||||
}).join('');
|
||||
|
||||
if (additionalProperties) {
|
||||
serializedProperties += '<!-- additional elements allowed -->';
|
||||
}
|
||||
|
||||
return wrapTag(name, serializedProperties, attrs);
|
||||
}
|
||||
|
||||
function getErrorMessage () {
|
||||
return '<!-- invalid XML -->';
|
||||
}
|
||||
|
||||
function createSchemaXML (name, definition, models, isParam) {
|
||||
var $ref = definition.$ref;
|
||||
var descriptor = _.isString($ref) ? getDescriptorByRef($ref, models)
|
||||
: getDescriptor(name, definition, models, isParam);
|
||||
|
||||
if (!descriptor) {
|
||||
return getErrorMessage();
|
||||
}
|
||||
|
||||
switch (descriptor.type) {
|
||||
case 'array':
|
||||
return createArrayXML(descriptor);
|
||||
case 'object':
|
||||
return createObjectXML(descriptor);
|
||||
default:
|
||||
return createPrimitiveXML(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
function Descriptor (name, type, definition, models, isParam) {
|
||||
if (arguments.length < 4) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
this.definition = definition;
|
||||
this.models = models;
|
||||
this.type = type;
|
||||
this.isParam = isParam;
|
||||
}
|
||||
|
||||
function getDescriptorByRef($ref, models) {
|
||||
var modelType = simpleRef($ref);
|
||||
var model = models[modelType] || {};
|
||||
var name = model.name || modelType;
|
||||
var type = model.type || 'object';
|
||||
|
||||
if (!model.definition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Descriptor (name, type, model.definition, models);
|
||||
}
|
||||
|
||||
function getDescriptor (name, definition, models, isParam){
|
||||
var type = definition.type || 'object';
|
||||
var xml = definition.xml || {};
|
||||
|
||||
if (!definition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
name = getName(name, xml);
|
||||
|
||||
return new Descriptor(name, type, definition, models,isParam);
|
||||
}
|
||||
|
||||
function createXMLSample (definition, models, isParam) {
|
||||
var prolog = '<?xml version="1.0"?>';
|
||||
|
||||
return formatXml(prolog + createSchemaXML('', definition, models, isParam));
|
||||
}
|
||||
|
||||
return {
|
||||
getModelSignature: getModelSignature,
|
||||
createJSONSample: createJSONSample,
|
||||
getParameterModelSignature: getParameterModelSignature,
|
||||
createParameterJSONSample: createParameterJSONSample,
|
||||
createSchemaXML: createSchemaXML,
|
||||
createXMLSample: createXMLSample
|
||||
};
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user