Merge branch 'develop_2.0' into JSONEditor

Conflicts:
	dist/index.html
	dist/swagger-ui.js
	dist/swagger-ui.min.js
This commit is contained in:
laurent lepinay
2015-03-27 02:15:29 -07:00
23 changed files with 162 additions and 37839 deletions

View File

@@ -1,4 +1,5 @@
node_modules node_modules
src/main/javascript/doc.js src/main/javascript/doc.js
dist dist
lib lib
.log

View File

@@ -17,6 +17,7 @@
"strict": true, "strict": true,
"trailing": true, "trailing": true,
"smarttabs": true, "smarttabs": true,
"validthis": true,
"globals": { "globals": {
// Libraries // Libraries
@@ -29,6 +30,7 @@
"SwaggerClient": false, "SwaggerClient": false,
"hljs": false, "hljs": false,
"SwaggerUi": false, "SwaggerUi": false,
"define": false,
// Global object // Global object
// TODO: remove these // TODO: remove these

View File

@@ -1,3 +1,4 @@
sudo: false
language: node_js language: node_js
node_js: node_js:
- '0.10' - '0.10'
@@ -7,7 +8,3 @@ install:
- sh -e /etc/init.d/xvfb start - sh -e /etc/init.d/xvfb start
- npm i -g jshint - npm i -g jshint
- npm install - npm install
script:
- jshint .
- npm test

View File

@@ -91,11 +91,13 @@ validatorUrl | By default, Swagger-UI attempts to validate specs against swagger
dom_id | The id of a dom element inside which SwaggerUi will put the user interface for swagger. dom_id | The id of a dom element inside which SwaggerUi will put the user interface for swagger.
booleanValues | SwaggerUI renders boolean data types as a dropdown. By default it provides a 'true' and 'false' string as the possible choices. You can use this parameter to change the values in dropdown to be something else, for example 0 and 1 by setting booleanValues to new Array(0, 1). booleanValues | SwaggerUI renders boolean data types as a dropdown. By default it provides a 'true' and 'false' string as the possible choices. You can use this parameter to change the values in dropdown to be something else, for example 0 and 1 by setting booleanValues to new Array(0, 1).
docExpansion | Controls how the API listing is displayed. It can be set to 'none' (default), 'list' (shows operations for each resource), or 'full' (fully expanded: shows operations and their details). docExpansion | Controls how the API listing is displayed. It can be set to 'none' (default), 'list' (shows operations for each resource), or 'full' (fully expanded: shows operations and their details).
sorter | Apply a sort to the API list. It can be 'alpha' (sort paths alphanumerically) or 'method' (sort operations by HTTP method). Default is the order returned by the server unchanged. apisSorter | Apply a sort to the API/tags list. It can be 'alpha' (sort by name) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged.
operationsSorter | Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged.
onComplete | This is a callback function parameter which can be passed to be notified of when SwaggerUI has completed rendering successfully. onComplete | This is a callback function parameter which can be passed to be notified of when SwaggerUI has completed rendering successfully.
onFailure | This is a callback function parameter which can be passed to be notified of when SwaggerUI encountered a failure was unable to render. onFailure | This is a callback function parameter which can be passed to be notified of when SwaggerUI encountered a failure was unable to render.
highlightSizeThreshold | Any size response below this threshold will be highlighted syntactically, attempting to highlight large responses can lead to browser hangs, not including a threshold will default to highlight all returned responses. highlightSizeThreshold | Any size response below this threshold will be highlighted syntactically, attempting to highlight large responses can lead to browser hangs, not including a threshold will default to highlight all returned responses.
supportedSubmitMethods | An array of of the HTTP operations that will have the 'Try it out!` option. An empty array disables all operations. This does not filter the operations from the display. supportedSubmitMethods | An array of of the HTTP operations that will have the 'Try it out!` option. An empty array disables all operations. This does not filter the operations from the display.
oauth2RedirectUrl | OAuth redirect URL
* All other parameters are explained in greater detail below * All other parameters are explained in greater detail below

4
dist/index.html vendored
View File

@@ -10,7 +10,6 @@
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/> <link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/> <link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>
<link href='css/print.css' media='print' rel='stylesheet' type='text/css'/> <link href='css/print.css' media='print' rel='stylesheet' type='text/css'/>
<script type="text/javascript" src="lib/shred.bundle.js"></script>
<script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script> <script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
<script src='lib/jquery.slideto.min.js' type='text/javascript'></script> <script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script> <script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
@@ -18,14 +17,11 @@
<script src='lib/handlebars-2.0.0.js' type='text/javascript'></script> <script src='lib/handlebars-2.0.0.js' type='text/javascript'></script>
<script src='lib/underscore-min.js' type='text/javascript'></script> <script src='lib/underscore-min.js' type='text/javascript'></script>
<script src='lib/backbone-min.js' type='text/javascript'></script> <script src='lib/backbone-min.js' type='text/javascript'></script>
<script src='lib/swagger-client.js' type='text/javascript'></script>
<script src='swagger-ui.js' type='text/javascript'></script> <script src='swagger-ui.js' type='text/javascript'></script>
<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script> <script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
<script src='lib/jsoneditor.min.js' type='text/javascript'></script> <script src='lib/jsoneditor.min.js' type='text/javascript'></script>
<script src='lib/marked.js' type='text/javascript'></script> <script src='lib/marked.js' type='text/javascript'></script>
<!-- enabling this will enable oauth2 implicit scope support -->
<script src='lib/swagger-oauth.js' type='text/javascript'></script>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
var url = window.location.search.match(/url=([^&]+)/); var url = window.location.search.match(/url=([^&]+)/);

2765
dist/lib/shred.bundle.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -97,7 +97,8 @@ function handleLogin() {
var authSchemes = window.swaggerUi.api.authSchemes; var authSchemes = window.swaggerUi.api.authSchemes;
var host = window.location; var host = window.location;
var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/")); var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/"));
var redirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html'; var defaultRedirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html';
var redirectUrl = window.oAuthRedirectUrl || defaultRedirectUrl;
var url = null; var url = null;
for (var key in authSchemes) { for (var key in authSchemes) {

75
dist/swagger-ui.js vendored
View File

@@ -38,6 +38,10 @@ window.SwaggerUi = Backbone.Router.extend({
]; ];
} }
if (typeof options.oauth2RedirectUrl === 'string') {
window.oAuthRedirectUrl = options.redirectUrl;
}
// Create an empty div which contains the dom_id // Create an empty div which contains the dom_id
if (! $('#' + this.dom_id).length){ if (! $('#' + this.dom_id).length){
$('body').append('<div id="' + this.dom_id + '"></div>') ; $('body').append('<div id="' + this.dom_id + '"></div>') ;
@@ -207,7 +211,7 @@ window.SwaggerUi.Views = {};
(function(){ (function(){
window.authorizations = { window.authorizations = {
add: function() { add: function() {
warn('using window.authorizations is depreciated. Please use waggerUi.api.clientAuthorizations.add().'); warn('Using window.authorizations is deprecated. Please use SwaggerUi.api.clientAuthorizations.add().');
if (typeof window.swaggerUi === 'undefined') { if (typeof window.swaggerUi === 'undefined') {
throw new TypeError('window.swaggerUi is not defined'); throw new TypeError('window.swaggerUi is not defined');
@@ -220,12 +224,12 @@ window.SwaggerUi.Views = {};
}; };
window.ApiKeyAuthorization = function() { window.ApiKeyAuthorization = function() {
warn('window.ApiKeyAuthorization is depreciated. Please use SwaggerClient.ApiKeyAuthorization.'); warn('window.ApiKeyAuthorization is deprecated. Please use SwaggerClient.ApiKeyAuthorization.');
SwaggerClient.ApiKeyAuthorization.apply(window, arguments); SwaggerClient.ApiKeyAuthorization.apply(window, arguments);
}; };
window.PasswordAuthorization = function() { window.PasswordAuthorization = function() {
warn('window.PasswordAuthorization is depreciated. Please use SwaggerClient.PasswordAuthorization.'); warn('window.PasswordAuthorization is deprecated. Please use SwaggerClient.PasswordAuthorization.');
SwaggerClient.PasswordAuthorization.apply(window, arguments); SwaggerClient.PasswordAuthorization.apply(window, arguments);
}; };
@@ -235,6 +239,27 @@ window.SwaggerUi.Views = {};
} }
} }
})(); })();
// UMD
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['b'], function (b) {
return (root.SwaggerUi = factory(b));
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory(require('b'));
} else {
// Browser globals
root.SwaggerUi = factory(root.b);
}
}(this, function () {
return SwaggerUi;
}));
this["Handlebars"] = this["Handlebars"] || {}; this["Handlebars"] = this["Handlebars"] || {};
this["Handlebars"]["templates"] = this["Handlebars"]["templates"] || {}; this["Handlebars"]["templates"] = this["Handlebars"]["templates"] || {};
this["Handlebars"]["templates"]["apikey_button_view"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { this["Handlebars"]["templates"]["apikey_button_view"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
@@ -1212,21 +1237,48 @@ SwaggerUi.Views.HeaderView = Backbone.View.extend({
'use strict'; 'use strict';
SwaggerUi.Views.MainView = Backbone.View.extend({ SwaggerUi.Views.MainView = Backbone.View.extend({
apisSorter : {
// TODO: sorters were not used in any place, do we need them? alpha : function(a,b){ return a.name.localeCompare(b.name); }
// sorters = { },
// alpha : function(a,b){ return a.path.localeCompare(b.path); }, operationsSorters : {
// method : function(a,b){ return a.method.localeCompare(b.method); }, alpha : function(a,b){ return a.path.localeCompare(b.path); },
// }, method : function(a,b){ return a.method.localeCompare(b.method); }
},
initialize: function(opts){ initialize: function(opts){
var sorterOption, sorterFn, key, value;
opts = opts || {}; opts = opts || {};
this.router = opts.router; this.router = opts.router;
// Sort APIs
if (opts.swaggerOptions.apisSorter) {
sorterOption = opts.swaggerOptions.apisSorter;
if (_.isFunction(sorterOption)) {
sorterFn = sorterOption;
} else {
sorterFn = this.apisSorter[sorterOption];
}
if (_.isFunction(sorterFn)) {
this.model.apisArray.sort(sorterFn);
}
}
// Sort operations of each API
if (opts.swaggerOptions.operationsSorter) {
sorterOption = opts.swaggerOptions.operationsSorter;
if (_.isFunction(sorterOption)) {
sorterFn = sorterOption;
} else {
sorterFn = this.operationsSorters[sorterOption];
}
if (_.isFunction(sorterFn)) {
for (key in this.model.apisArray) {
this.model.apisArray[key].operationsArray.sort(sorterFn);
}
}
}
// set up the UI for input // set up the UI for input
this.model.auths = []; this.model.auths = [];
var key, value;
for (key in this.model.securityDefinitions) { for (key in this.model.securityDefinitions) {
value = this.model.securityDefinitions[key]; value = this.model.securityDefinitions[key];
@@ -1334,6 +1386,7 @@ SwaggerUi.Views.MainView = Backbone.View.extend({
$(this.el).html(''); $(this.el).html('');
} }
}); });
'use strict'; 'use strict';
SwaggerUi.Views.OperationView = Backbone.View.extend({ SwaggerUi.Views.OperationView = Backbone.View.extend({

File diff suppressed because one or more lines are too long

View File

@@ -54,7 +54,10 @@ function templates() {
gulp.task('dist', ['clean'], function() { gulp.task('dist', ['clean'], function() {
return es.merge( return es.merge(
gulp.src('./src/main/javascript/**/*.js'), gulp.src([
'./src/main/javascript/**/*.js',
'./node_modules/swagger-client/browser/swagger-client.js'
]),
templates() templates()
) )
.pipe(order(['scripts.js', 'templates.js'])) .pipe(order(['scripts.js', 'templates.js']))

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -97,7 +97,8 @@ function handleLogin() {
var authSchemes = window.swaggerUi.api.authSchemes; var authSchemes = window.swaggerUi.api.authSchemes;
var host = window.location; var host = window.location;
var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/")); var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/"));
var redirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html'; var defaultRedirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html';
var redirectUrl = window.oAuthRedirectUrl || defaultRedirectUrl;
var url = null; var url = null;
for (var key in authSchemes) { for (var key in authSchemes) {

View File

@@ -6,9 +6,11 @@
"homepage": "http://swagger.io", "homepage": "http://swagger.io",
"license": "Apache 2.0", "license": "Apache 2.0",
"scripts": { "scripts": {
"build": "./node_modules/gulp/bin/gulp.js;", "build": "gulp.js;",
"serve": "./node_modules/gulp/bin/gulp.js serve;", "serve": "gulp.js serve;",
"test": "./node_modules/gulp/bin/gulp.js; ./node_modules/mocha/bin/mocha" "pretest": "jshint .",
"test": "gulp; mocha",
"postinstall": "cd node_modules/swagger-client/; npm install; gulp"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -43,6 +45,7 @@
"http-server": "git+https://github.com/nodeapps/http-server.git", "http-server": "git+https://github.com/nodeapps/http-server.git",
"less": "^2.4.0", "less": "^2.4.0",
"mocha": "^2.1.0", "mocha": "^2.1.0",
"selenium-webdriver": "^2.45.0" "selenium-webdriver": "^2.45.0",
"swagger-client": "git://github.com/swagger-api/swagger-js#develop_2.0"
} }
} }

View File

@@ -10,7 +10,6 @@
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/> <link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/> <link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>
<link href='css/print.css' media='print' rel='stylesheet' type='text/css'/> <link href='css/print.css' media='print' rel='stylesheet' type='text/css'/>
<script type="text/javascript" src="lib/shred.bundle.js"></script>
<script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script> <script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
<script src='lib/jquery.slideto.min.js' type='text/javascript'></script> <script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script> <script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
@@ -18,14 +17,11 @@
<script src='lib/handlebars-2.0.0.js' type='text/javascript'></script> <script src='lib/handlebars-2.0.0.js' type='text/javascript'></script>
<script src='lib/underscore-min.js' type='text/javascript'></script> <script src='lib/underscore-min.js' type='text/javascript'></script>
<script src='lib/backbone-min.js' type='text/javascript'></script> <script src='lib/backbone-min.js' type='text/javascript'></script>
<script src='lib/swagger-client.js' type='text/javascript'></script>
<script src='swagger-ui.js' type='text/javascript'></script> <script src='swagger-ui.js' type='text/javascript'></script>
<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script> <script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
<script src='lib/jsoneditor.min.js' type='text/javascript'></script> <script src='lib/jsoneditor.min.js' type='text/javascript'></script>
<script src='lib/marked.js' type='text/javascript'></script> <script src='lib/marked.js' type='text/javascript'></script>
<!-- enabling this will enable oauth2 implicit scope support -->
<script src='lib/swagger-oauth.js' type='text/javascript'></script>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
var url = window.location.search.match(/url=([^&]+)/); var url = window.location.search.match(/url=([^&]+)/);

View File

@@ -32,6 +32,10 @@ window.SwaggerUi = Backbone.Router.extend({
]; ];
} }
if (typeof options.oauth2RedirectUrl === 'string') {
window.oAuthRedirectUrl = options.redirectUrl;
}
// Create an empty div which contains the dom_id // Create an empty div which contains the dom_id
if (! $('#' + this.dom_id).length){ if (! $('#' + this.dom_id).length){
$('body').append('<div id="' + this.dom_id + '"></div>') ; $('body').append('<div id="' + this.dom_id + '"></div>') ;
@@ -201,7 +205,7 @@ window.SwaggerUi.Views = {};
(function(){ (function(){
window.authorizations = { window.authorizations = {
add: function() { add: function() {
warn('using window.authorizations is depreciated. Please use waggerUi.api.clientAuthorizations.add().'); warn('Using window.authorizations is deprecated. Please use SwaggerUi.api.clientAuthorizations.add().');
if (typeof window.swaggerUi === 'undefined') { if (typeof window.swaggerUi === 'undefined') {
throw new TypeError('window.swaggerUi is not defined'); throw new TypeError('window.swaggerUi is not defined');
@@ -214,12 +218,12 @@ window.SwaggerUi.Views = {};
}; };
window.ApiKeyAuthorization = function() { window.ApiKeyAuthorization = function() {
warn('window.ApiKeyAuthorization is depreciated. Please use SwaggerClient.ApiKeyAuthorization.'); warn('window.ApiKeyAuthorization is deprecated. Please use SwaggerClient.ApiKeyAuthorization.');
SwaggerClient.ApiKeyAuthorization.apply(window, arguments); SwaggerClient.ApiKeyAuthorization.apply(window, arguments);
}; };
window.PasswordAuthorization = function() { window.PasswordAuthorization = function() {
warn('window.PasswordAuthorization is depreciated. Please use SwaggerClient.PasswordAuthorization.'); warn('window.PasswordAuthorization is deprecated. Please use SwaggerClient.PasswordAuthorization.');
SwaggerClient.PasswordAuthorization.apply(window, arguments); SwaggerClient.PasswordAuthorization.apply(window, arguments);
}; };
@@ -228,4 +232,25 @@ window.SwaggerUi.Views = {};
console.warn(message); console.warn(message);
} }
} }
})(); })();
// UMD
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['b'], function (b) {
return (root.SwaggerUi = factory(b));
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory(require('b'));
} else {
// Browser globals
root.SwaggerUi = factory(root.b);
}
}(this, function () {
return SwaggerUi;
}));

View File

@@ -1,21 +1,48 @@
'use strict'; 'use strict';
SwaggerUi.Views.MainView = Backbone.View.extend({ SwaggerUi.Views.MainView = Backbone.View.extend({
apisSorter : {
// TODO: sorters were not used in any place, do we need them? alpha : function(a,b){ return a.name.localeCompare(b.name); }
// sorters = { },
// alpha : function(a,b){ return a.path.localeCompare(b.path); }, operationsSorters : {
// method : function(a,b){ return a.method.localeCompare(b.method); }, alpha : function(a,b){ return a.path.localeCompare(b.path); },
// }, method : function(a,b){ return a.method.localeCompare(b.method); }
},
initialize: function(opts){ initialize: function(opts){
var sorterOption, sorterFn, key, value;
opts = opts || {}; opts = opts || {};
this.router = opts.router; this.router = opts.router;
// Sort APIs
if (opts.swaggerOptions.apisSorter) {
sorterOption = opts.swaggerOptions.apisSorter;
if (_.isFunction(sorterOption)) {
sorterFn = sorterOption;
} else {
sorterFn = this.apisSorter[sorterOption];
}
if (_.isFunction(sorterFn)) {
this.model.apisArray.sort(sorterFn);
}
}
// Sort operations of each API
if (opts.swaggerOptions.operationsSorter) {
sorterOption = opts.swaggerOptions.operationsSorter;
if (_.isFunction(sorterOption)) {
sorterFn = sorterOption;
} else {
sorterFn = this.operationsSorters[sorterOption];
}
if (_.isFunction(sorterFn)) {
for (key in this.model.apisArray) {
this.model.apisArray[key].operationsArray.sort(sorterFn);
}
}
}
// set up the UI for input // set up the UI for input
this.model.auths = []; this.model.auths = [];
var key, value;
for (key in this.model.securityDefinitions) { for (key in this.model.securityDefinitions) {
value = this.model.securityDefinitions[key]; value = this.model.securityDefinitions[key];
@@ -122,4 +149,4 @@ SwaggerUi.Views.MainView = Backbone.View.extend({
clear: function(){ clear: function(){
$(this.el).html(''); $(this.el).html('');
} }
}); });

View File

@@ -20,7 +20,7 @@ describe('swagger 1.x spec tests', function () {
before(function (done) { before(function (done) {
this.timeout(25 * 1000); this.timeout(25 * 1000);
servers.start('/v1.2/petstore/api-docs', done); servers.start('/v1.2/petstore/api-docs.json', done);
}); });
afterEach(function(){ afterEach(function(){
@@ -57,7 +57,8 @@ describe('swagger 1.x spec tests', function () {
}); });
}); });
it('should find the contact name element', function(done){ // TODO: enable me
xit('should find the contact name element', function(done){
var locator = webdriver.By.css('.info_name'); var locator = webdriver.By.css('.info_name');
driver.isElementPresent(locator).then(function (isPresent) { driver.isElementPresent(locator).then(function (isPresent) {
expect(isPresent).to.be.true; expect(isPresent).to.be.true;
@@ -73,7 +74,8 @@ describe('swagger 1.x spec tests', function () {
}); });
}); });
it('should find the pet resource description', function(done){ // TODO: enable me
xit('should find the pet resource description', function(done){
var locator = webdriver.By.xpath('//div[contains(., "Operations about pets")]'); var locator = webdriver.By.xpath('//div[contains(., "Operations about pets")]');
driver.findElements(locator).then(function (elements) { driver.findElements(locator).then(function (elements) {
expect(elements.length).to.not.equal(0); expect(elements.length).to.not.equal(0);

View File

@@ -3,15 +3,15 @@
"swaggerVersion": "1.2", "swaggerVersion": "1.2",
"apis": [ "apis": [
{ {
"path": "http://localhost:8081/v1.2/petstore/pet", "path": "http://localhost:8081/v1.2/petstore/pet.json",
"description": "Operations about pets" "description": "Operations about pets"
}, },
{ {
"path": "http://localhost:8081/v1.2/petstore/user", "path": "http://localhost:8081/v1.2/petstore/user.json",
"description": "Operations about user" "description": "Operations about user"
}, },
{ {
"path": "http://localhost:8081/v1.2/petstore/store", "path": "http://localhost:8081/v1.2/petstore/store.json",
"description": "Operations about store" "description": "Operations about store"
} }
], ],