diff --git a/Cakefile b/Cakefile index 3261c70c..2640d69b 100644 --- a/Cakefile +++ b/Cakefile @@ -10,6 +10,7 @@ sourceFiles = [ 'view/OperationView' 'view/StatusCodeView' 'view/ParameterView' + 'view/SignatureView' ] diff --git a/lib/highlight.7.3.pack.js b/lib/highlight.7.3.pack.js new file mode 100644 index 00000000..9a95a75e --- /dev/null +++ b/lib/highlight.7.3.pack.js @@ -0,0 +1 @@ +var hljs=new function(){function l(o){return o.replace(/&/gm,"&").replace(//gm,">")}function b(p){for(var o=p.firstChild;o;o=o.nextSibling){if(o.nodeName=="CODE"){return o}if(!(o.nodeType==3&&o.nodeValue.match(/\s+/))){break}}}function h(p,o){return Array.prototype.map.call(p.childNodes,function(q){if(q.nodeType==3){return o?q.nodeValue.replace(/\n/g,""):q.nodeValue}if(q.nodeName=="BR"){return"\n"}return h(q,o)}).join("")}function a(q){var p=(q.className+" "+q.parentNode.className).split(/\s+/);p=p.map(function(r){return r.replace(/^language-/,"")});for(var o=0;o"}while(x.length||v.length){var u=t().splice(0,1)[0];y+=l(w.substr(p,u.offset-p));p=u.offset;if(u.event=="start"){y+=s(u.node);r.push(u.node)}else{if(u.event=="stop"){var o,q=r.length;do{q--;o=r[q];y+=("")}while(o!=u.node);r.splice(q,1);while(q'+L[0]+""}else{r+=L[0]}N=A.lR.lastIndex;L=A.lR.exec(K)}return r+K.substr(N)}function z(){if(A.sL&&!e[A.sL]){return l(w)}var r=A.sL?d(A.sL,w):g(w);if(A.r>0){v+=r.keyword_count;B+=r.r}return''+r.value+""}function J(){return A.sL!==undefined?z():G()}function I(L,r){var K=L.cN?'':"";if(L.rB){x+=K;w=""}else{if(L.eB){x+=l(r)+K;w=""}else{x+=K;w=r}}A=Object.create(L,{parent:{value:A}});B+=L.r}function C(K,r){w+=K;if(r===undefined){x+=J();return 0}var L=o(r,A);if(L){x+=J();I(L,r);return L.rB?0:r.length}var M=s(A,r);if(M){if(!(M.rE||M.eE)){w+=r}x+=J();do{if(A.cN){x+=""}A=A.parent}while(A!=M.parent);if(M.eE){x+=l(r)}w="";if(M.starts){I(M.starts,"")}return M.rE?0:r.length}if(t(r,A)){throw"Illegal"}w+=r;return r.length||1}var F=e[D];f(F);var A=F;var w="";var B=0;var v=0;var x="";try{var u,q,p=0;while(true){A.t.lastIndex=p;u=A.t.exec(E);if(!u){break}q=C(E.substr(p,u.index-p),u[0]);p=u.index+q}C(E.substr(p));return{r:B,keyword_count:v,value:x,language:D}}catch(H){if(H=="Illegal"){return{r:0,keyword_count:0,value:l(E)}}else{throw H}}}function g(s){var o={keyword_count:0,r:0,value:l(s)};var q=o;for(var p in e){if(!e.hasOwnProperty(p)){continue}var r=d(p,s);r.language=p;if(r.keyword_count+r.r>q.keyword_count+q.r){q=r}if(r.keyword_count+r.r>o.keyword_count+o.r){q=o;o=r}}if(q.language){o.second_best=q}return o}function i(q,p,o){if(p){q=q.replace(/^((<[^>]+>|\t)+)/gm,function(r,v,u,t){return v.replace(/\t/g,p)})}if(o){q=q.replace(/\n/g,"
")}return q}function m(r,u,p){var v=h(r,p);var t=a(r);if(t=="no-highlight"){return}var w=t?d(t,v):g(v);t=w.language;var o=c(r);if(o.length){var q=document.createElement("pre");q.innerHTML=w.value;w.value=j(o,c(q),v)}w.value=i(w.value,u,p);var s=r.className;if(!s.match("(\\s|^)(language-)?"+t+"(\\s|$)")){s=s?(s+" "+t):t}r.innerHTML=w.value;r.className=s;r.result={language:t,kw:w.keyword_count,re:w.r};if(w.second_best){r.second_best={language:w.second_best.language,kw:w.second_best.keyword_count,re:w.second_best.r}}}function n(){if(n.called){return}n.called=true;Array.prototype.map.call(document.getElementsByTagName("pre"),b).filter(Boolean).forEach(function(o){m(o,hljs.tabReplace)})}function k(){window.addEventListener("DOMContentLoaded",n,false);window.addEventListener("load",n,false)}var e={};this.LANGUAGES=e;this.highlight=d;this.highlightAuto=g;this.fixMarkup=i;this.highlightBlock=m;this.initHighlighting=n;this.initHighlightingOnLoad=k;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.inherit=function(q,r){var o={};for(var p in q){o[p]=q[p]}if(r){for(var p in r){o[p]=r[p]}}return o}}();hljs.LANGUAGES.xml=function(a){var c="[A-Za-z0-9\\._:-]+";var b={eW:true,c:[{cN:"attribute",b:c,r:0},{b:'="',rB:true,e:'"',c:[{cN:"value",b:'"',eW:true}]},{b:"='",rB:true,e:"'",c:[{cN:"value",b:"'",eW:true}]},{b:"=",c:[{cN:"value",b:"[^\\s/>]+"}]}]};return{cI:true,c:[{cN:"pi",b:"<\\?",e:"\\?>",r:10},{cN:"doctype",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},{cN:"comment",b:"",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"|$)",e:">",k:{title:"style"},c:[b],starts:{e:"",rE:true,sL:"css"}},{cN:"tag",b:"|$)",e:">",k:{title:"script"},c:[b],starts:{e:"<\/script>",rE:true,sL:"javascript"}},{b:"<%",e:"%>",sL:"vbscript"},{cN:"tag",b:"",c:[{cN:"title",b:"[^ />]+"},b]}]}}(hljs);hljs.LANGUAGES.json=function(a){var e={literal:"true false null"};var d=[a.QSM,a.CNM];var c={cN:"value",e:",",eW:true,eE:true,c:d,k:e};var b={b:"{",e:"}",c:[{cN:"attribute",b:'\\s*"',e:'"\\s*:\\s*',eB:true,eE:true,c:[a.BE],i:"\\n",starts:c}],i:"\\S"};var f={b:"\\[",e:"\\]",c:[a.inherit(c,{cN:null})],i:"\\S"};d.splice(d.length,0,b,f);return{c:d,k:e,i:"\\S"}}(hljs); \ No newline at end of file diff --git a/lib/swagger.js b/lib/swagger.js index 30deb25f..5afba7e5 100644 --- a/lib/swagger.js +++ b/lib/swagger.js @@ -334,6 +334,17 @@ return returnVal; }; + SwaggerModel.prototype.createJSONSample = function(modelToIgnore) { + var prop, result, _i, _len, _ref; + result = {}; + _ref = this.properties; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + prop = _ref[_i]; + result[prop.name] = prop.getSampleValue(modelToIgnore); + } + return result; + }; + return SwaggerModel; })(); @@ -363,6 +374,24 @@ } } + SwaggerModelProperty.prototype.getSampleValue = function(modelToIgnore) { + var result; + if ((this.refModel != null) && (!(this.refModel === modelToIgnore))) { + result = this.refModel.createJSONSample(this.refModel); + } else { + if (this.isArray) { + result = this.refDataType; + } else { + result = this.dataType; + } + } + if (this.isArray) { + return [result]; + } else { + return result; + } + }; + SwaggerModelProperty.prototype.toString = function() { var str; str = this.name + ': ' + this.dataTypeWithRef; @@ -424,6 +453,7 @@ parameter.allowableValues.values = this.resource.api.booleanValues; } parameter.signature = this.getSignature(parameter.dataType, this.resource.models); + parameter.sampleJSON = this.getSampleJSON(parameter.dataType, this.resource.models); if (parameter.allowableValues != null) { if (parameter.allowableValues.valueType === "RANGE") { parameter.isRange = true; @@ -478,6 +508,17 @@ } }; + SwaggerOperation.prototype.getSampleJSON = function(dataType, models) { + var isPrimitive, listType, val; + listType = this.isListType(dataType); + isPrimitive = ((listType != null) && models[listType]) || (models[dataType] != null) ? false : true; + val = isPrimitive ? void 0 : (listType != null ? models[listType].createJSONSample() : models[dataType].createJSONSample()); + if (val) { + val = listType ? [val] : val; + return JSON.stringify(val, null, 2); + } + }; + SwaggerOperation.prototype["do"] = function(args, callback, error) { var body, headers; if (args == null) { diff --git a/src/main/coffeescript/view/OperationView.coffee b/src/main/coffeescript/view/OperationView.coffee index 4df219f5..ded9f063 100644 --- a/src/main/coffeescript/view/OperationView.coffee +++ b/src/main/coffeescript/view/OperationView.coffee @@ -134,7 +134,7 @@ class OperationView extends Backbone.View # puts the response data in UI showStatus: (data) -> try - response_body = "
" + JSON.stringify(JSON.parse(data.responseText), null, 2).replace(/\n/g, "
") + "
" + response_body = '
' + JSON.stringify(JSON.parse(data.responseText), null, 2) + "
" catch error response_body = "   [unable to parse as json; raw response below]
" + data.responseText + "
" $(".response_code", $(@el)).html "
" + data.status + "
" @@ -143,6 +143,7 @@ class OperationView extends Backbone.View $(".response", $(@el)).slideDown() $(".response_hider", $(@el)).show() $(".response_throbber", $(@el)).hide() + hljs.highlightBlock($('.response_body', $(@el))[0]) toggleOperationContent: -> elem = $('#' + @model.resourceName + "_" + @model.nickname + "_" + @model.httpMethod + "_content"); diff --git a/src/main/coffeescript/view/ParameterView.coffee b/src/main/coffeescript/view/ParameterView.coffee index a7c4361a..69f12e20 100644 --- a/src/main/coffeescript/view/ParameterView.coffee +++ b/src/main/coffeescript/view/ParameterView.coffee @@ -8,6 +8,12 @@ class ParameterView extends Backbone.View template = @template() $(@el).html(template(@model)) + if @model.sampleJSON + signatureView = new SignatureView({model: @model, tagName: 'div'}) + $('.model-signature', $(@el)).append signatureView.render().el + else + $('.model-signature', $(@el)).html(@model.signature) + @ # Return an appropriate template based on if the parameter is a list, readonly, required diff --git a/src/main/coffeescript/view/SignatureView.coffee b/src/main/coffeescript/view/SignatureView.coffee new file mode 100644 index 00000000..c867b960 --- /dev/null +++ b/src/main/coffeescript/view/SignatureView.coffee @@ -0,0 +1,43 @@ +class SignatureView extends Backbone.View + events: { + 'click a.description-link' : 'switchToDescription' + 'click a.snippet-link' : 'switchToSnippet' + 'mousedown .snippet' : 'snippetToTextArea' + } + + initialize: -> + + render: -> + template = @template() + $(@el).html(template(@model)) + + @switchToDescription() + + @ + + template: -> + Handlebars.templates.signature + + # handler for show signature + switchToDescription: (e) -> + e?.preventDefault() + $(".snippet", $(@el)).hide() + $(".description", $(@el)).show() + $('.description-link', $(@el)).addClass('selected') + $('.snippet-link', $(@el)).removeClass('selected') + + # handler for show sample + switchToSnippet: (e) -> + e?.preventDefault() + $(".description", $(@el)).hide() + $(".snippet", $(@el)).show() + $('.snippet-link', $(@el)).addClass('selected') + $('.description-link', $(@el)).removeClass('selected') + + # handler for snippet to text area + snippetToTextArea: (e) -> + e?.preventDefault() + textArea = $('textarea', $(@el.parentNode.parentNode.parentNode)) + if $.trim(textArea.val()) == '' + textArea.val(@model.sampleJSON) + diff --git a/src/main/html/css/hightlight.default.css b/src/main/html/css/hightlight.default.css new file mode 100644 index 00000000..e417fc17 --- /dev/null +++ b/src/main/html/css/hightlight.default.css @@ -0,0 +1,135 @@ +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +pre code { + display: block; padding: 0.5em; + background: #F0F0F0; +} + +pre code, +pre .subst, +pre .tag .title, +pre .lisp .title, +pre .clojure .built_in, +pre .nginx .title { + color: black; +} + +pre .string, +pre .title, +pre .constant, +pre .parent, +pre .tag .value, +pre .rules .value, +pre .rules .value .number, +pre .preprocessor, +pre .ruby .symbol, +pre .ruby .symbol .string, +pre .aggregate, +pre .template_tag, +pre .django .variable, +pre .smalltalk .class, +pre .addition, +pre .flow, +pre .stream, +pre .bash .variable, +pre .apache .tag, +pre .apache .cbracket, +pre .tex .command, +pre .tex .special, +pre .erlang_repl .function_or_atom, +pre .markdown .header { + color: #800; +} + +pre .comment, +pre .annotation, +pre .template_comment, +pre .diff .header, +pre .chunk, +pre .markdown .blockquote { + color: #888; +} + +pre .number, +pre .date, +pre .regexp, +pre .literal, +pre .smalltalk .symbol, +pre .smalltalk .char, +pre .go .constant, +pre .change, +pre .markdown .bullet, +pre .markdown .link_url { + color: #080; +} + +pre .label, +pre .javadoc, +pre .ruby .string, +pre .decorator, +pre .filter .argument, +pre .localvars, +pre .array, +pre .attr_selector, +pre .important, +pre .pseudo, +pre .pi, +pre .doctype, +pre .deletion, +pre .envvar, +pre .shebang, +pre .apache .sqbracket, +pre .nginx .built_in, +pre .tex .formula, +pre .erlang_repl .reserved, +pre .prompt, +pre .markdown .link_label, +pre .vhdl .attribute, +pre .clojure .attribute, +pre .coffeescript .property { + color: #88F +} + +pre .keyword, +pre .id, +pre .phpdoc, +pre .title, +pre .built_in, +pre .aggregate, +pre .css .tag, +pre .javadoctag, +pre .phpdoc, +pre .yardoctag, +pre .smalltalk .class, +pre .winutils, +pre .bash .variable, +pre .apache .tag, +pre .go .typename, +pre .tex .command, +pre .markdown .strong, +pre .request, +pre .status { + font-weight: bold; +} + +pre .markdown .emphasis { + font-style: italic; +} + +pre .nginx .built_in { + font-weight: normal; +} + +pre .coffeescript .javascript, +pre .javascript .xml, +pre .tex .formula, +pre .xml .javascript, +pre .xml .vbscript, +pre .xml .css, +pre .xml .cdata { + opacity: 0.5; +} diff --git a/src/main/html/css/screen.css b/src/main/html/css/screen.css index 1f6d21c0..ea3ac3f0 100644 --- a/src/main/html/css/screen.css +++ b/src/main/html/css/screen.css @@ -1509,9 +1509,73 @@ body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operatio font-size: 1em; line-height: 1.5em; } -.model-signature span { +.model-signature .description span { font-size: 0.9em; line-height: 1.5em; } -.model-signature span:nth-child(odd) { color:#333; } -.model-signature span:nth-child(even) { color:#C5862B; } +.model-signature .description span:nth-child(odd) { color:#333; } +.model-signature .description span:nth-child(even) { color:#C5862B; } +.model-signature .signature-nav a { + text-decoration: none; + color: #AAA; +} + +.model-signature pre { + font-size: .85em; + line-height: 1.2em; + overflow: auto; + max-height: 200px; + cursor: pointer; +} + +.model-signature pre:hover { + background-color: #ffffdd; +} + +.model-signature .snippet small { + font-size: 0.75em; +} + +.model-signature .signature-container { + clear: both; +} + +.model-signature .signature-nav a:hover { + text-decoration: underline; + color: black; +} + +.model-signature .signature-nav .selected { + color: black; + text-decoration: none; +} + +.model-signature ul.signature-nav { + float: none; + clear: both; + overflow: hidden; + margin: 0; + padding: 0; + display: block; + clear: none; + float: right; + margin-right: 5px; + margin-bottom: 5px; +} + +.model-signature ul.signature-nav li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + border-right: 1px solid #dddddd; +} + +.model-signature ul.signature-nav li:last-child { + padding-right: 0; + border-right: none; +} + +pre code { + background: none; +} diff --git a/src/main/html/index.html b/src/main/html/index.html index a94d8f7d..cab4ad3d 100644 --- a/src/main/html/index.html +++ b/src/main/html/index.html @@ -3,6 +3,7 @@ Swagger UI + @@ -13,6 +14,7 @@ +