├── .eslintrc.json ├── .gitignore ├── LICENSE ├── README.md ├── bower.json ├── dist ├── auth.html ├── auth.json ├── index.html ├── plugins │ ├── after-explorer │ │ ├── xml-formatter.js │ │ └── xml-formatter.min.js │ ├── before-display │ │ ├── markdown.js │ │ ├── markdown.min.js │ │ ├── operations.js │ │ ├── operations.min.js │ │ ├── sort.js │ │ └── sort.min.js │ ├── before-explorer │ │ ├── auth.sample.js │ │ ├── auth.sample.min.js │ │ ├── transform.js │ │ └── transform.min.js │ ├── before-load │ │ ├── yaml.js │ │ └── yaml.min.js │ ├── before-parse │ │ ├── base.js │ │ ├── base.min.js │ │ ├── external-references.js │ │ ├── external-references.min.js │ │ ├── split.js │ │ ├── split.min.js │ │ ├── swagger-1-to-2.js │ │ └── swagger-1-to-2.min.js │ ├── plugins.js │ └── plugins.min.js ├── scripts │ ├── swagger-ui-material.core.js │ ├── swagger-ui-material.core.min.js │ ├── swagger-ui-material.full.js │ ├── swagger-ui-material.full.min.js │ ├── swagger-ui-material.js │ ├── swagger-ui-material.min.js │ ├── swagger-ui-material.templates.js │ └── swagger-ui-material.templates.min.js └── styles │ ├── swagger-ui-material.css │ └── swagger-ui-material.min.css ├── gulp_tasks ├── build │ ├── auth.js │ ├── build.js │ ├── core.js │ ├── dist.js │ ├── eslint.js │ ├── full.js │ ├── graph.js │ ├── hub.js │ ├── info.js │ ├── plugins.js │ ├── scripts.js │ ├── styles.js │ └── templates.js ├── demo │ ├── copy.js │ ├── demo.js │ └── styles.js ├── deploy │ └── publish.js └── examples │ └── gfm.js ├── gulpfile.js ├── index.js ├── lib ├── api-models-meta │ ├── api-models-meta.json │ ├── got │ │ ├── index.js │ │ ├── license │ │ ├── package.json │ │ └── readme.md │ ├── index.js │ └── package.json └── api-models-rainbows │ ├── api-models-rainbows.json │ ├── index.js │ └── package.json ├── package.json ├── protractor.conf.js ├── src ├── .eslintrc.json ├── auth.html ├── directives │ ├── directives.module.js │ ├── file-input │ │ └── file-input.js │ ├── toolbar-edit │ │ ├── toolbar-edit.css │ │ ├── toolbar-edit.html │ │ └── toolbar-edit.js │ ├── toolbar-search │ │ ├── toolbar-search.css │ │ ├── toolbar-search.html │ │ └── toolbar-search.js │ └── truncate │ │ └── truncate.js ├── hub │ ├── hub.json │ └── index.html ├── index.html ├── modules │ ├── content │ │ └── content.ctrl.js │ ├── description │ │ └── description.ctrl.js │ ├── detail │ │ ├── detail.ctrl.js │ │ ├── header.html │ │ ├── request │ │ │ ├── parameter.html │ │ │ └── request.html │ │ ├── response.html │ │ ├── result │ │ │ └── result.html │ │ └── scripts │ │ │ └── scripts.html │ ├── group │ │ └── group.html │ ├── meta │ │ ├── meta.ctrl.js │ │ └── meta.html │ ├── operation │ │ └── operation.html │ └── toolbar │ │ ├── toolbar.ctrl.js │ │ └── toolbar.html ├── plugins │ ├── README.md │ ├── after-explorer │ │ └── xml-formatter.js │ ├── before-display │ │ ├── markdown.js │ │ ├── operations.js │ │ └── sort.js │ ├── before-explorer │ │ ├── auth.sample.js │ │ └── transform.js │ ├── before-load │ │ └── yaml.js │ ├── before-parse │ │ ├── base.js │ │ ├── external-references.js │ │ ├── split.js │ │ └── swagger-1-to-2.js │ ├── parse │ │ └── parser.core.js │ └── plugins.js ├── styles │ └── swagger-ui-material.css ├── sw.ui.md │ ├── dialog.js │ ├── display.js │ ├── http-data.js │ ├── http-data.template │ ├── security.js │ ├── style.js │ ├── sw.ui.md.module.js │ ├── syntax.js │ ├── theme.js │ ├── tools.js │ └── utils.js ├── sw.ui │ ├── client.js │ ├── data.js │ ├── format.js │ ├── model.js │ └── sw.ui.module.js └── views │ ├── app.layout.html │ ├── info.dialog.html │ ├── proxy.dialog.html │ └── security.dialog.html └── test ├── e2e ├── .eslintrc.json ├── all.spec.js ├── back.spec.js ├── hub.spec.js └── lib │ ├── hub.js │ └── ui.js ├── fixtures ├── auth │ ├── auth.json │ └── auth.json.sample ├── examples │ ├── swagger-1.2.json │ ├── swagger-drupal.json │ ├── swagger-minimal.json │ ├── swagger-swashbuckle-odata.json │ └── swagger-swashbuckle.json ├── markdown │ ├── README.md │ └── swagger-gfm.json └── openapi-specification │ ├── README.md │ ├── json │ ├── api-with-examples.json │ ├── petstore-expanded.json │ ├── petstore-minimal.json │ ├── petstore-separate │ │ ├── common │ │ │ └── Error.json │ │ └── spec │ │ │ ├── NewPet.json │ │ │ ├── Pet.json │ │ │ ├── parameters.json │ │ │ └── swagger.json │ ├── petstore-simple.json │ ├── petstore-with-external-docs.json │ ├── petstore.json │ └── uber.json │ └── yaml │ ├── api-with-examples.yaml │ ├── petstore-expanded.yaml │ ├── petstore-minimal.yaml │ ├── petstore-separate │ ├── common │ │ └── Error.yaml │ └── spec │ │ ├── NewPet.yaml │ │ ├── Pet.yaml │ │ ├── parameters.yaml │ │ └── swagger.yaml │ ├── petstore-simple.yaml │ ├── petstore-with-external-docs.yaml │ ├── petstore.yaml │ └── uber.yaml └── manual └── manual.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [ 5 | 2, 6 | "always" 7 | ], 8 | "indent": [ 9 | 2, 10 | 4, 11 | { 12 | "SwitchCase": 1 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | bower_components/ 3 | demo/ 4 | 5 | src/auth.json 6 | !src/auth.json.sample 7 | 8 | .publish/ 9 | .architecture/ 10 | .formatted/ 11 | 12 | .idea/ 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Jan Forst (https://github.com/darosh/angular-swagger-ui-material) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-swagger-ui-material", 3 | "description": "Material Design template for angular-swager-ui", 4 | "main": [], 5 | "version": "0.2.3", 6 | "authors": [ 7 | "Jan Forst " 8 | ], 9 | "license": "MIT", 10 | "moduleType": [], 11 | "homepage": "https://github.com/darosh/angular-swagger-ui-material", 12 | "private": true, 13 | "ignore": [ 14 | "**/.*", 15 | "node_modules", 16 | "bower_components", 17 | "test", 18 | "tests", 19 | "demo", 20 | "examples", 21 | "gulp_tasks", 22 | "src" 23 | ], 24 | "dependencies": { 25 | "angular-material": "^1.0.5", 26 | "github-markdown-css": "^2.2.1", 27 | "showdown": "^1.3.0", 28 | "js-yaml": "^3.5.3" 29 | }, 30 | "resolutions": { 31 | "showdown": "^1.3.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dist/auth.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OAuth 2.0 Callback 6 | 7 | 29 | 30 | -------------------------------------------------------------------------------- /dist/auth.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Material Swagger UI Demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /dist/plugins/after-explorer/xml-formatter.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Orange angular-swagger-ui - v0.3.0 3 | * 4 | * (C) 2015 Orange, all right reserved 5 | * MIT Licensed 6 | */ 7 | 'use strict'; 8 | 9 | angular.module('sw.plugin.xmlFormater', ['sw.plugins']) 10 | .factory('xmlFormatter', function ($q, $log) { 11 | $log.debug('sw:plugin', 'xmlFormater'); 12 | 13 | return { 14 | execute: execute 15 | }; 16 | 17 | function execute (response) { 18 | $log.debug('sw:execute', 'xmlFormater'); 19 | 20 | var executed = false; 21 | var deferred = $q.defer(); 22 | var contentType = response.headers && response.headers()['content-type']; 23 | 24 | if (contentType && contentType.toLowerCase().indexOf('/xml') > 0) { 25 | response.data = formatXml(response.data); 26 | executed = true; 27 | } 28 | deferred.resolve(executed); 29 | return deferred.promise; 30 | } 31 | 32 | function formatXml (xml) { 33 | var formatted = ''; 34 | var reg = /(>)(<)(\/*)/g; 35 | var pad = 0; 36 | 37 | xml = xml.replace(reg, '$1\r\n$2$3'); 38 | angular.forEach(xml.split('\r\n'), function (node) { 39 | var indent = 0; 40 | var padding = ''; 41 | 42 | if (node.match(/.+<\/\w[^>]*>$/)) { 43 | indent = 0; 44 | } else if (node.match(/^<\/\w/)) { 45 | if (pad !== 0) { 46 | pad -= 1; 47 | } 48 | } else if (node.match(/^<\w[^>]*[^\/]>.*$/)) { 49 | indent = 1; 50 | } else { 51 | indent = 0; 52 | } 53 | 54 | for (var i = 0; i < pad; i++) { 55 | padding += ' '; 56 | } 57 | 58 | formatted += padding + node + '\r\n'; 59 | pad += indent; 60 | }); 61 | 62 | return formatted; 63 | } 64 | }) 65 | .run(function (plugins, xmlFormatter) { 66 | plugins.add(plugins.AFTER_EXPLORER_LOAD, xmlFormatter); 67 | }); 68 | -------------------------------------------------------------------------------- /dist/plugins/after-explorer/xml-formatter.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.xmlFormater",["sw.plugins"]).factory("xmlFormatter",["$q","$log",function(r,e){function t(t){e.debug("sw:execute","xmlFormater");var n=!1,u=r.defer(),o=t.headers&&t.headers()["content-type"];return o&&o.toLowerCase().indexOf("/xml")>0&&(t.data=a(t.data),n=!0),u.resolve(n),u.promise}function a(r){var e="",t=/(>)(<)(\/*)/g,a=0;return r=r.replace(t,"$1\r\n$2$3"),angular.forEach(r.split("\r\n"),function(r){var t=0,n="";r.match(/.+<\/\w[^>]*>$/)?t=0:r.match(/^<\/\w/)?0!==a&&(a-=1):t=r.match(/^<\w[^>]*[^\/]>.*$/)?1:0;for(var u=0;a>u;u++)n+=" ";e+=n+r+"\r\n",a+=t}),e}return e.debug("sw:plugin","xmlFormater"),{execute:t}}]).run(["plugins","xmlFormatter",function(r,e){r.add(r.AFTER_EXPLORER_LOAD,e)}]); -------------------------------------------------------------------------------- /dist/plugins/before-display/markdown.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.markdown', ['sw.plugins']) 4 | .factory('markdown', function ($q, $log, $window) { 5 | $log.debug('sw:plugin', 'markdown'); 6 | 7 | var showdown = new $window.showdown.Converter({ 8 | simplifiedAutoLink: true, 9 | tables: true, 10 | ghCodeBlocks: true, 11 | tasklists: true 12 | }); 13 | 14 | return { 15 | execute: execute 16 | }; 17 | 18 | function execute (parseResult) { 19 | $log.debug('sw:execute', 'markdown'); 20 | 21 | var deferred = $q.defer(); 22 | 23 | // TODO: is there any other GFM field to be transformed? Find "GFM" in http://swagger.io/specification/ page 24 | 25 | if (parseResult.info && parseResult.info.description) { 26 | parseResult.info.description = markdown(parseResult.info.description.replace(/^
/i, '')); 27 | } 28 | 29 | angular.forEach(parseResult.securityDefinitions, function (sec) { 30 | var d = sec.description || ''; 31 | 32 | // Obvious descriptions 33 | if (sec.type === 'apiKey' && d.toLowerCase() === 'API Key Authentication'.toLowerCase()) { 34 | delete sec.description; 35 | } else if (sec.type === 'basic' && d.toLowerCase() === 'Basic HTTP Authentication'.toLowerCase()) { 36 | delete sec.description; 37 | } else if (sec.type === 'oauth2' && d.toLowerCase() === 'OAuth 2.0 Authentication'.toLowerCase()) { 38 | delete sec.description; 39 | } else { 40 | sec.description = markdown(sec.description); 41 | } 42 | }); 43 | 44 | angular.forEach(parseResult.resources, function (resource) { 45 | resource.description = markdown(resource.description); 46 | 47 | angular.forEach(resource.operations, function (operation) { 48 | operation.description = markdown(operation.description); 49 | 50 | // TODO: remove workaround? http://darosh.github.io/angular-swagger-ui-material/#?url=https:%2F%2Fapi.apis.guru%2Fspecs%2Fwinning.email%2F1.0.0%2Fswagger.json 51 | operation.summary = operation.summary ? operation.summary.replace(/(
)+$/, '') : operation.summary; 52 | 53 | angular.forEach(operation.responses, function (response) { 54 | response.description = markdown(response.description); 55 | }); 56 | }); 57 | }); 58 | 59 | deferred.resolve(); 60 | 61 | return deferred.promise; 62 | } 63 | 64 | function markdown (text) { 65 | return showdown.makeHtml(text || ''); 66 | } 67 | }) 68 | .run(function (plugins, markdown) { 69 | plugins.add(plugins.BEFORE_DISPLAY, markdown); 70 | }); 71 | -------------------------------------------------------------------------------- /dist/plugins/before-display/markdown.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.markdown",["sw.plugins"]).factory("markdown",["$q","$log","$window",function(e,i,o){function n(o){i.debug("sw:execute","markdown");var n=e.defer();return o.info&&o.info.description&&(o.info.description=r(o.info.description.replace(/^
/i,""))),angular.forEach(o.securityDefinitions,function(e){var i=e.description||"";"apiKey"===e.type&&i.toLowerCase()==="API Key Authentication".toLowerCase()?delete e.description:"basic"===e.type&&i.toLowerCase()==="Basic HTTP Authentication".toLowerCase()?delete e.description:"oauth2"===e.type&&i.toLowerCase()==="OAuth 2.0 Authentication".toLowerCase()?delete e.description:e.description=r(e.description)}),angular.forEach(o.resources,function(e){e.description=r(e.description),angular.forEach(e.operations,function(e){e.description=r(e.description),e.summary=e.summary?e.summary.replace(/(
)+$/,""):e.summary,angular.forEach(e.responses,function(e){e.description=r(e.description)})})}),n.resolve(),n.promise}function r(e){return t.makeHtml(e||"")}i.debug("sw:plugin","markdown");var t=new o.showdown.Converter({simplifiedAutoLink:!0,tables:!0,ghCodeBlocks:!0,tasklists:!0});return{execute:n}}]).run(["plugins","markdown",function(e,i){e.add(e.BEFORE_DISPLAY,i)}]); -------------------------------------------------------------------------------- /dist/plugins/before-display/operations.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.operations', ['sw.plugins']) 4 | // List ungrouped operations 5 | .factory('operations', function ($q) { 6 | return { 7 | execute: function (parseResult) { 8 | var deferred = $q.defer(); 9 | 10 | parseResult.info.operations = []; 11 | 12 | angular.forEach(parseResult.resources, function (resource) { 13 | angular.forEach(resource.operations, function (operation) { 14 | parseResult.info.operations.push(operation); 15 | }); 16 | 17 | // TODO: allow configuration of minimum auto expanded endpoints 18 | if (parseResult.resources.length <= 8) { 19 | resource.open = true; 20 | } 21 | }); 22 | 23 | parseResult.info.operations.sort(function (a, b) { 24 | return (a.path.toLowerCase().replace(/[^a-z]+/gi, '') + '-' + a.httpMethod) 25 | .localeCompare(b.path.toLowerCase().replace(/[^a-z]+/gi, '') + '-' + b.httpMethod); 26 | }); 27 | 28 | deferred.resolve(); 29 | 30 | return deferred.promise; 31 | } 32 | }; 33 | }) 34 | .run(function (plugins, operations) { 35 | plugins.add(plugins.BEFORE_DISPLAY, operations); 36 | }); 37 | -------------------------------------------------------------------------------- /dist/plugins/before-display/operations.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.operations",["sw.plugins"]).factory("operations",["$q",function(o){return{execute:function(e){var r=o.defer();return e.info.operations=[],angular.forEach(e.resources,function(o){angular.forEach(o.operations,function(o){e.info.operations.push(o)}),e.resources.length<=8&&(o.open=!0)}),e.info.operations.sort(function(o,e){return(o.path.toLowerCase().replace(/[^a-z]+/gi,"")+"-"+o.httpMethod).localeCompare(e.path.toLowerCase().replace(/[^a-z]+/gi,"")+"-"+e.httpMethod)}),r.resolve(),r.promise}}}]).run(["plugins","operations",function(o,e){o.add(o.BEFORE_DISPLAY,e)}]); -------------------------------------------------------------------------------- /dist/plugins/before-display/sort.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.sort', ['sw.plugins']) 4 | .factory('sort', function ($q) { 5 | var order = { 6 | get: 1, 7 | head: 2, 8 | options: 3, 9 | post: 4, 10 | put: 5, 11 | patch: 6, 12 | delete: 7 13 | }; 14 | 15 | return { 16 | execute: function (parseResult) { 17 | var deferred = $q.defer(); 18 | 19 | angular.forEach(parseResult.resources, function (resource) { 20 | resource.operations.sort(function (a, b) { 21 | return (a.path.toLowerCase().replace(/[^a-z]+/gi, '') + '-' + (order[a.httpMethod] || 9)) 22 | .localeCompare(b.path.toLowerCase().replace(/[^a-z]+/gi, '') + '-' + (order[b.httpMethod] || 9)); 23 | }); 24 | }); 25 | 26 | deferred.resolve(true); 27 | 28 | return deferred.promise; 29 | } 30 | }; 31 | }) 32 | .run(function (plugins, sort) { 33 | plugins.add(plugins.BEFORE_DISPLAY, sort); 34 | }); 35 | -------------------------------------------------------------------------------- /dist/plugins/before-display/sort.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.sort",["sw.plugins"]).factory("sort",["$q",function(e){var t={get:1,head:2,options:3,post:4,put:5,patch:6,"delete":7};return{execute:function(r){var o=e.defer();return angular.forEach(r.resources,function(e){e.operations.sort(function(e,r){return(e.path.toLowerCase().replace(/[^a-z]+/gi,"")+"-"+(t[e.httpMethod]||9)).localeCompare(r.path.toLowerCase().replace(/[^a-z]+/gi,"")+"-"+(t[r.httpMethod]||9))})}),o.resolve(!0),o.promise}}}]).run(["plugins","sort",function(e,t){e.add(e.BEFORE_DISPLAY,t)}]); -------------------------------------------------------------------------------- /dist/plugins/before-explorer/auth.sample.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.auth', ['sw.plugins']) 4 | .factory('auth', function ($q/* , $window */) { 5 | return { 6 | execute: function (/* options */) { 7 | var deferred = $q.defer(); 8 | 9 | /* Add auth key to params 10 | 11 | options.params.auth_key = '...'; 12 | */ 13 | 14 | /* Basic HTTP Authentication 15 | 16 | var username = '...'; 17 | var password = '...'; 18 | var auth = $window.btoa(username + ':' + password); 19 | options.headers['Authorization'] = 'Basic ' + auth; 20 | */ 21 | 22 | deferred.resolve(); 23 | 24 | return deferred.promise; 25 | } 26 | }; 27 | }) 28 | .run(function (plugins, auth) { 29 | plugins.add(plugins.BEFORE_EXPLORER_LOAD, auth); 30 | }); 31 | -------------------------------------------------------------------------------- /dist/plugins/before-explorer/auth.sample.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.auth",["sw.plugins"]).factory("auth",["$q",function(u){return{execute:function(){var n=u.defer();return n.resolve(),n.promise}}}]).run(["plugins","auth",function(u,n){u.add(u.BEFORE_EXPLORER_LOAD,n)}]); -------------------------------------------------------------------------------- /dist/plugins/before-explorer/transform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.transform', ['sw.plugins']) 4 | // Catch default transform invalid JSON parse 5 | .factory('transform', function ($q, $http) { 6 | return { 7 | execute: function (config) { 8 | var deferred = $q.defer(); 9 | 10 | config.transformResponse = function (data, headersGetter, status) { 11 | try { 12 | return $http.defaults.transformResponse[0](data, headersGetter, status); 13 | } catch (ing) { 14 | return data; 15 | } 16 | }; 17 | 18 | deferred.resolve(); 19 | 20 | return deferred.promise; 21 | } 22 | }; 23 | }) 24 | .run(function (plugins, transform) { 25 | plugins.add(plugins.BEFORE_EXPLORER_LOAD, transform); 26 | }); 27 | -------------------------------------------------------------------------------- /dist/plugins/before-explorer/transform.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.transform",["sw.plugins"]).factory("transform",["$q","$http",function(r,n){return{execute:function(t){var e=r.defer();return t.transformResponse=function(r,t,e){try{return n.defaults.transformResponse[0](r,t,e)}catch(s){return r}},e.resolve(),e.promise}}}]).run(["plugins","transform",function(r,n){r.add(r.BEFORE_EXPLORER_LOAD,n)}]); -------------------------------------------------------------------------------- /dist/plugins/before-load/yaml.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.yaml', ['sw.plugins']) 4 | .factory('yaml', function ($q, $window) { 5 | return { 6 | execute: function (options) { 7 | var deferred = $q.defer(); 8 | 9 | options.transformResponse = function (data, headersGetter) { 10 | try { 11 | return angular.fromJson(data); 12 | } catch (ign) { 13 | try { 14 | var obj = $window.jsyaml.safeLoad(data); 15 | 16 | headersGetter()['content-type'] = 'application/json'; 17 | 18 | return obj; 19 | } catch (ign) { 20 | return data; 21 | } 22 | } 23 | }; 24 | 25 | deferred.resolve(); 26 | 27 | return deferred.promise; 28 | } 29 | }; 30 | }) 31 | .run(function (plugins, yaml) { 32 | plugins.add(plugins.BEFORE_LOAD, yaml); 33 | }); 34 | -------------------------------------------------------------------------------- /dist/plugins/before-load/yaml.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.yaml",["sw.plugins"]).factory("yaml",["$q","$window",function(n,r){return{execute:function(t){var e=n.defer();return t.transformResponse=function(n,t){try{return angular.fromJson(n)}catch(e){try{var a=r.jsyaml.safeLoad(n);return t()["content-type"]="application/json",a}catch(e){return n}}},e.resolve(),e.promise}}}]).run(["plugins","yaml",function(n,r){n.add(n.BEFORE_LOAD,r)}]); -------------------------------------------------------------------------------- /dist/plugins/before-parse/base.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.base', ['sw.plugins']) 4 | .factory('base', function ($q, $log) { 5 | return { 6 | execute: execute 7 | }; 8 | 9 | function execute (url, swagger) { 10 | $log.debug('sw:plugin', 'base'); 11 | 12 | var deferred = $q.defer(); 13 | 14 | if (swagger && swagger.paths) { 15 | var parts = {}; 16 | var min = Number.MAX_VALUE; 17 | 18 | angular.forEach(swagger.paths, function (path, key) { 19 | parts[key] = key.split('/'); 20 | 21 | if (key[0] === '/') { 22 | parts[key].shift(); 23 | } 24 | 25 | min = Math.min(min, parts[key].length); 26 | }); 27 | 28 | var paths = Object.keys(swagger.paths); 29 | var sames = []; 30 | 31 | for (var i = 0; i < min; i++) { 32 | var first = parts[paths[0]][i]; 33 | 34 | if (/\{.+\}/.test(first) || (parts[paths[0]].length <= 1)) { 35 | break; 36 | } 37 | 38 | var same = true; 39 | 40 | for (var j = 0; j < paths.length; j++) { 41 | if (parts[paths[j]][i] !== first) { 42 | same = false; 43 | break; 44 | } 45 | } 46 | 47 | if (same) { 48 | sames.push(first); 49 | } else { 50 | break; 51 | } 52 | } 53 | 54 | if (sames.length > 0) { 55 | var extracted = sames.join('/'); 56 | 57 | $log.debug('sw:plugin:base:extracted', extracted); 58 | 59 | swagger.basePath = (swagger.basePath || '/'); 60 | swagger.basePath = swagger.basePath + 61 | ((swagger.basePath[swagger.basePath.length - 1] === '/') ? '' : '/') + extracted; 62 | 63 | angular.forEach(paths, function (path) { 64 | swagger.paths['/' + parts[path].slice(sames.length).join('/')] = swagger.paths[path]; 65 | delete swagger.paths[path]; 66 | }); 67 | } 68 | } 69 | 70 | deferred.resolve(true); 71 | 72 | return deferred.promise; 73 | } 74 | }) 75 | .run(function (plugins, base) { 76 | plugins.add(plugins.BEFORE_PARSE, base); 77 | }); 78 | -------------------------------------------------------------------------------- /dist/plugins/before-parse/base.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.base",["sw.plugins"]).factory("base",["$q","$log",function(a,e){function t(t,s){e.debug("sw:plugin","base");var n=a.defer();if(s&&s.paths){var r={},h=Number.MAX_VALUE;angular.forEach(s.paths,function(a,e){r[e]=e.split("/"),"/"===e[0]&&r[e].shift(),h=Math.min(h,r[e].length)});for(var i=Object.keys(s.paths),u=[],l=0;h>l;l++){var b=r[i[0]][l];if(/\{.+\}/.test(b)||r[i[0]].length<=1)break;for(var f=!0,g=0;g0){var o=u.join("/");e.debug("sw:plugin:base:extracted",o),s.basePath=s.basePath||"/",s.basePath=s.basePath+("/"===s.basePath[s.basePath.length-1]?"":"/")+o,angular.forEach(i,function(a){s.paths["/"+r[a].slice(u.length).join("/")]=s.paths[a],delete s.paths[a]})}}return n.resolve(!0),n.promise}return{execute:t}}]).run(["plugins","base",function(a,e){a.add(a.BEFORE_PARSE,e)}]); -------------------------------------------------------------------------------- /dist/plugins/before-parse/external-references.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Orange angular-swagger-ui - v0.3.0 3 | * 4 | * (C) 2015 Orange, all right reserved 5 | * MIT Licensed 6 | */ 7 | 'use strict'; 8 | 9 | angular.module('sw.plugin.externalReferences', ['sw.plugins']) 10 | .factory('externalReferences', function ($http, $q, $window, plugins) { 11 | var deferred; 12 | 13 | return { 14 | /** 15 | * Module entry point 16 | */ 17 | execute: function (url, swagger) { 18 | deferred = $q.defer(); 19 | loadExternalReferences(url, swagger); 20 | 21 | return deferred.promise; 22 | } 23 | }; 24 | 25 | function onError (error) { 26 | deferred.reject(error); 27 | } 28 | 29 | /** 30 | * Load external definition 31 | */ 32 | function getUrl (externalUrl, callback) { 33 | var options = { 34 | method: 'GET', 35 | url: externalUrl 36 | }; 37 | 38 | plugins 39 | .execute(plugins.BEFORE_LOAD, options) 40 | .then(function () { 41 | $http(options).then(callback, onError); 42 | }) 43 | .catch(onError); 44 | } 45 | 46 | /** 47 | * Generate external URL 48 | */ 49 | function getExternalUrl (baseUrl, $ref) { 50 | if (!angular.isString($ref)) { 51 | return ''; 52 | } 53 | 54 | var parts = $ref.split('#/'); 55 | var externalUrl = parts[0]; 56 | 57 | if (externalUrl && (externalUrl.indexOf('http') !== 0)) { 58 | // relative url 59 | if (externalUrl.indexOf('/') === 0) { 60 | var swaggerUrlParts = $window.URL.parse(baseUrl); 61 | externalUrl = swaggerUrlParts.protocol + '//' + swaggerUrlParts.host + externalUrl; 62 | } else { 63 | var pos = baseUrl.lastIndexOf('/'); 64 | externalUrl = baseUrl.substring(0, pos) + '/' + externalUrl; 65 | } 66 | } 67 | 68 | return externalUrl; 69 | } 70 | 71 | /** 72 | * Find and resolve external definitions 73 | */ 74 | function loadExternalReferences (baseUrl, swagger) { 75 | var loading = 0; 76 | 77 | function load (url, obj) { 78 | loading++; 79 | 80 | getUrl(url, function (json) { 81 | loading--; 82 | 83 | var subPath = obj.$ref.split('#/')[1]; 84 | var subJson = subPath ? json.data[subPath] : json.data; 85 | 86 | angular.extend(obj, subJson); 87 | 88 | delete obj.$ref; 89 | 90 | if (loading === 0) { 91 | deferred.resolve(true); 92 | } 93 | }); 94 | } 95 | 96 | function iterate (obj) { 97 | angular.forEach(obj, function (v, k) { 98 | if (k === '$ref') { 99 | var externalUrl = getExternalUrl(baseUrl, v); 100 | 101 | if (externalUrl) { 102 | load(externalUrl, obj); 103 | } 104 | } else if (angular.isObject(v) || angular.isArray(v)) { 105 | iterate(v); 106 | } 107 | }); 108 | } 109 | 110 | iterate(swagger); 111 | 112 | if (!loading) { 113 | deferred.resolve(false); 114 | } 115 | } 116 | }) 117 | .run(function (plugins, externalReferences) { 118 | plugins.add(plugins.BEFORE_PARSE, externalReferences); 119 | }); 120 | -------------------------------------------------------------------------------- /dist/plugins/before-parse/external-references.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.externalReferences",["sw.plugins"]).factory("externalReferences",["$http","$q","$window","plugins",function(e,n,r,t){function a(e){c.reject(e)}function u(n,r){var u={method:"GET",url:n};t.execute(t.BEFORE_LOAD,u).then(function(){e(u).then(r,a)})["catch"](a)}function i(e,n){if(!angular.isString(n))return"";var t=n.split("#/"),a=t[0];if(a&&0!==a.indexOf("http"))if(0===a.indexOf("/")){var u=r.URL.parse(e);a=u.protocol+"//"+u.host+a}else{var i=e.lastIndexOf("/");a=e.substring(0,i)+"/"+a}return a}function f(e,n){function r(e,n){a++,u(e,function(e){a--;var r=n.$ref.split("#/")[1],t=r?e.data[r]:e.data;angular.extend(n,t),delete n.$ref,0===a&&c.resolve(!0)})}function t(n){angular.forEach(n,function(a,u){if("$ref"===u){var f=i(e,a);f&&r(f,n)}else(angular.isObject(a)||angular.isArray(a))&&t(a)})}var a=0;t(n),a||c.resolve(!1)}var c;return{execute:function(e,r){return c=n.defer(),f(e,r),c.promise}}}]).run(["plugins","externalReferences",function(e,n){e.add(e.BEFORE_PARSE,n)}]); -------------------------------------------------------------------------------- /dist/plugins/before-parse/split.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.split', ['sw.plugins']) 4 | .factory('split', function ($q) { 5 | return { 6 | execute: execute 7 | }; 8 | 9 | function execute (url, swagger) { 10 | var deferred = $q.defer(); 11 | 12 | if (swagger && swagger.swagger && !swagger.tags) { 13 | var tags = {}; 14 | 15 | angular.forEach(swagger.paths, function (path, key) { 16 | var t = key.replace(/^\/?([^\/]+).*$/g, '$1'); 17 | tags[t] = true; 18 | 19 | angular.forEach(path, function (method) { 20 | if (!method.tags || !method.tags.length) { 21 | method.tags = [t]; 22 | } 23 | }); 24 | }); 25 | 26 | swagger.tags = []; 27 | 28 | Object.keys(tags).forEach(function (tag) { 29 | swagger.tags.push({name: tag}); 30 | }); 31 | } 32 | 33 | deferred.resolve(true); 34 | 35 | return deferred.promise; 36 | } 37 | }) 38 | .run(function (plugins, split) { 39 | plugins.add(plugins.BEFORE_PARSE, split); 40 | }); 41 | -------------------------------------------------------------------------------- /dist/plugins/before-parse/split.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.split",["sw.plugins"]).factory("split",["$q",function(a){function t(t,n){var r=a.defer();if(n&&n.swagger&&!n.tags){var s={};angular.forEach(n.paths,function(a,t){var n=t.replace(/^\/?([^\/]+).*$/g,"$1");s[n]=!0,angular.forEach(a,function(a){a.tags&&a.tags.length||(a.tags=[n])})}),n.tags=[],Object.keys(s).forEach(function(a){n.tags.push({name:a})})}return r.resolve(!0),r.promise}return{execute:t}}]).run(["plugins","split",function(a,t){a.add(a.BEFORE_PARSE,t)}]); -------------------------------------------------------------------------------- /dist/plugins/before-parse/swagger-1-to-2.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugin.swagger1to2",["sw.plugins"]).factory("swagger1to2",["$q","$http","plugins",function(e,s,t){function r(r){var n=e.defer(),o={method:"GET",url:r};return t.execute(t.BEFORE_LOAD,o).then(function(){s(o).success(n.resolve).error(n.reject)})["catch"](n.reject),n.promise}function n(s,t,n){var i=n,c=i.info=i.info||{},f=[];c.contact={email:c.contact},c.license={name:c.license,url:c.licenseUrl},c.termsOfService=c.termsOfServiceUrl,i.paths={},i.definitions={},i.tags=[],angular.forEach(i.apis,function(e){f.push(r(t+e.path))}),e.all(f).then(function(e){angular.forEach(e,function(e){o(e,i),a(e,i),p(e,i)}),i.swagger="2.0",s.resolve(!0)})["catch"](s.reject)}function o(e,s){if(s.info.version=s.info.version||e.apiVersion,s.basePath=s.basePath||e.basePath,0===s.basePath.indexOf("http")){var t=angular.element('')[0];s.schemes=[t.protocol.replace(":","")],s.host=t.host,s.basePath=t.pathname}s.info.title=s.info.title||s.host,s.tags.push({name:e.resourcePath})}function a(e,s){var t,r;angular.forEach(e.apis,function(n){t=s.paths[n.path]=s.paths[n.path]||{},angular.forEach(n.operations,function(s){r={},t[s.method.toLowerCase()]={deprecated:s.deprecated,description:s.notes,summary:s.summary,operationId:s.nickname,produces:s.produces||e.produces,consumes:s.consumes||e.consumes,parameters:s.parameters,responses:r,tags:[e.resourcePath]},i(e,s),c(e,s,r)})})}function i(e,s){angular.forEach(s.parameters,function(s){s["in"]=s.paramType;var t=s.type||s.$ref;e.models&&t&&e.models[t]&&(s.schema={$ref:"#/definitions/"+t},delete s.type)})}function c(e,s,t){var r;angular.forEach(s.responseMessages,function(n){if(r=t[n.code]={description:n.message},n.responseModel)e.models&&e.models[n.responseModel]?r.schema={$ref:"#/definitions/"+n.responseModel}:r.type=n.responseModel;else if(200===n.code&&"void"!==s.type&&(e.models&&e.models[s.type]?r.schema={type:s.type,$ref:"#/definitions/"+s.type}:r.schema={type:s.type},"array"===s.type)){var o=s.items.type||s.items.$ref,a=r.schema.items={};e.models&&e.models[o]?a.$ref="#/definitions/"+o:a.type=o}})}function p(e,s){var t;angular.forEach(e.models,function(r,n){s.definitions[n]=r,r.subTypes&&(angular.forEach(r.subTypes,function(s){t=e.models&&e.models[s],t&&(r.required=(r.required||[]).concat(t.required||[]),angular.forEach(t.properties,function(e,s){r.properties[s]=e}))}),delete r.subTypes),angular.forEach(r.properties,function(s){var t=s.type||s.$ref;e.models&&t&&e.models[t]&&(s.$ref="#/definitions/"+t,delete s.type),s.items&&(t=s.items.type||s.items.$ref,e.models&&t&&e.models[t]&&(s.items.$ref="#/definitions/"+t),delete s.items.type)})})}return{execute:function(s,t){var r=e.defer(),o=t.swaggerVersion;return o&&0===o.indexOf("1.")?n(r,s,t):r.resolve(!1),r.promise}}}]).run(["plugins","swagger1to2",function(e,s){e.add(e.BEFORE_PARSE,s)}]); -------------------------------------------------------------------------------- /dist/plugins/plugins.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Orange angular-swagger-ui - v0.3.0 3 | * 4 | * (C) 2015 Orange, all right reserved 5 | * MIT Licensed 6 | */ 7 | 'use strict'; 8 | 9 | angular 10 | .module('sw.plugins', []).factory('plugins', function ($q) { 11 | var modules = {}; 12 | 13 | return { 14 | BEFORE_LOAD: 'BEFORE_LOAD', 15 | BEFORE_PARSE: 'BEFORE_PARSE', 16 | PARSE: 'PARSE', 17 | BEFORE_DISPLAY: 'BEFORE_DISPLAY', 18 | BEFORE_EXPLORER_LOAD: 'BEFORE_EXPLORER_LOAD', 19 | AFTER_EXPLORER_LOAD: 'AFTER_EXPLORER_LOAD', 20 | 21 | /** 22 | * Adds a new module to swagger-ui 23 | */ 24 | add: function (phase, module) { 25 | if (!modules[phase]) { 26 | modules[phase] = []; 27 | } 28 | if (modules[phase].indexOf(module) < 0) { 29 | modules[phase].push(module); 30 | } 31 | }, 32 | /** 33 | * Executes modules' phase 34 | */ 35 | execute: function () { 36 | var args = Array.prototype.slice.call(arguments); 37 | var phase = args.splice(0, 1); 38 | var deferred = $q.defer(); 39 | var phaseModules = modules[phase] || []; 40 | 41 | executeAll(deferred, [].concat(phaseModules), args); 42 | return deferred.promise; 43 | } 44 | }; 45 | 46 | /** 47 | * Runs modules' "execute" function one by one 48 | */ 49 | function executeAll (deferred, phaseModules, args, phaseExecuted) { 50 | var module = phaseModules.shift(); 51 | if (module) { 52 | module 53 | .execute.apply(module, args) 54 | .then(function (executed) { 55 | phaseExecuted = phaseExecuted || executed; 56 | executeAll(deferred, phaseModules, args, phaseExecuted); 57 | }) 58 | .catch(deferred.reject); 59 | } else { 60 | deferred.resolve(phaseExecuted); 61 | } 62 | } 63 | }); 64 | -------------------------------------------------------------------------------- /dist/plugins/plugins.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("sw.plugins",[]).factory("plugins",["$q",function(E){function e(E,R,t,O){var n=R.shift();n?n.execute.apply(n,t).then(function(n){O=O||n,e(E,R,t,O)})["catch"](E.reject):E.resolve(O)}var R={};return{BEFORE_LOAD:"BEFORE_LOAD",BEFORE_PARSE:"BEFORE_PARSE",PARSE:"PARSE",BEFORE_DISPLAY:"BEFORE_DISPLAY",BEFORE_EXPLORER_LOAD:"BEFORE_EXPLORER_LOAD",AFTER_EXPLORER_LOAD:"AFTER_EXPLORER_LOAD",add:function(E,e){R[E]||(R[E]=[]),R[E].indexOf(e)<0&&R[E].push(e)},execute:function(){var t=Array.prototype.slice.call(arguments),O=t.splice(0,1),n=E.defer(),c=R[O]||[];return e(n,[].concat(c),t),n.promise}}}]); -------------------------------------------------------------------------------- /dist/styles/swagger-ui-material.min.css: -------------------------------------------------------------------------------- 1 | .sw-ui-md .sum-http-method.md-button{height:24px;line-height:24px;min-height:24px;min-width:64px;padding:1px;margin:2px 6px 2px 2px;transition:none}.sw-ui-md .sum-http-code.md-button,.sw-ui-md .sum-http-header.md-button{height:18px;line-height:18px;min-height:18px;min-width:18px;margin:2px;border-radius:9px;font-family:monospace;padding:0 9px;text-transform:none}.sw-ui-md .sum-http-code.md-button.md-raised:not([disabled]),.sw-ui-md .sum-http-header.md-button.md-raised:not([disabled]),.sw-ui-md .sum-http-method.md-button.md-raised:not([disabled]){box-shadow:0 1px 3px 0 rgba(0,0,0,.2)}.sw-ui-md md-sidenav .md-subheader+.layout-padding,.sw-ui-md md-sidenav .md-subheader+.layout-padding>*:first-child,.sw-ui-md md-sidenav .sum-subheader+.layout-padding,.sw-ui-md md-sidenav .sum-subheader+.layout-padding>*:first-child{padding-top:0}.sw-ui-md .sum-tools .md-button,.sw-ui-md .sum-tools-in .md-button{margin-bottom:0;min-width:0;margin-left:0;margin-right:0}.sw-ui-md .sum-tools .md-button:last-child{margin-right:16px}.sw-ui-md md-sidenav md-input-container{margin-top:0;margin-bottom:0}.sw-ui-md .sum-link.md-button,.sw-ui-md md-list-item .md-button{margin:0 0 0 -4px;padding:0 4px;text-transform:none;min-height:0;line-height:1;min-width:inherit}.sw-ui-md .sum-link.md-button:focus,.sw-ui-md .sum-link.md-button:hover,.sw-ui-md md-list-item .md-button:focus,.sw-ui-md md-list-item .md-button:hover{background-color:transparent;text-decoration:underline}.sw-ui-md .md-body-1,.sw-ui-md .md-body-2{line-height:16px}.sw-ui-md [ng-click]{cursor:pointer}[swagger-ui-material],body{height:100%;width:100%;overflow:hidden}.sw-ui-md md-list{padding:0}.sw-ui-md md-list-item{min-height:64px}.sw-ui-md .sum-path{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;line-height:28px}.sw-ui-md .sum-path-wrap{line-height:20px;padding-top:4px}.sw-ui-md .sum-top,.sw-ui-md .sum-top>*{padding-top:0}.sw-ui-md textarea{font-family:monospace}.sw-ui-md .pad{margin-left:16px;text-indent:-8px;padding-left:8px}.sw-ui-md .sum-wrap{white-space:normal}.sw-ui-md .pad em,.sw-ui-md .sum-deprecated{opacity:.5}.sw-ui-md .sum-deprecated .sum-path{text-decoration:line-through}.sw-ui-md .sum-selected{background-color:#eee}.sw-ui-md .sum-delay.ng-enter{transition:.016s linear all .25s;opacity:0;width:0}.sw-ui-md .sum-delay.ng-enter-stagger{transition-delay:.25s;transition-duration:0s}.sw-ui-md .sum-delay.ng-enter.ng-enter-active{opacity:1}.sw-ui-md md-sidenav p{margin-top:0;margin-bottom:0}.sw-ui-md .md-errors-spacer{display:none}.sw-ui-md .sum-param-info{font-size:12px;line-height:14px}.sw-ui-md .sum-no-margin{margin:0}.sw-ui-md .md-toolbar-tools>.md-button:first-child{margin-right:8px}.sw-ui-md textarea{line-height:14px}.sw-ui-md pre.sum-pre{white-space:pre-wrap}.sw-ui-md .sum-ind{margin-left:0}.sw-ui-md md-input-container{margin-left:-2px}@media screen and (min-width:800px){.sw-ui-md md-sidenav{width:336px;max-width:336px}}.sw-ui-md .md-avatar-icon{opacity:.66}.sw-ui-md a.truncate{cursor:pointer}.sw-ui-md .sum-slide-disabled [role=tabpanel]{transition:none}.sw-ui-md .md-select-value :first-child{text-overflow:ellipsis;overflow:hidden;max-width:calc(100% - 24px)}.sw-ui-md .sum-fade.ng-hide{opacity:0}.sw-ui-md .sum-fade.ng-hide-remove{transition:all ease-in-out 150ms;transition-delay:15ms}.sum-sentence::first-letter,.sum-uppercase{text-transform:uppercase}md-dialog.sum-dialog{max-width:360px;min-width:280px}md-dialog.sum-dialog-wide{max-width:inherit;min-width:280px}.sum-dialog-wide .markdown-body{max-width:640px}.sw-ui-md span.md-button{display:inline;min-width:0;width:auto;margin:0;padding:0;line-height:normal;font-size:13px;font-weight:400;text-transform:none}.sum-hide-spacer .md-errors-spacer,.sum-hide-tabs md-tabs-wrapper{display:none}.sum-short-md p{margin:0}.markdown-body{font-family:inherit}.markdown-body.md-body-2{font-size:14px}md-tab-content:not(.md-active) *{white-space:nowrap!important}md-dialog md-toolbar{border-top-left-radius:4px;border-top-right-radius:4px}toolbar-edit input{background:0 0;border:none;color:#fff;margin-top:4px;vertical-align:middle;position:relative;top:-2px}toolbar-edit input:focus{outline:none}toolbar-search input{background:0 0;border:none;color:#fff;width:100px;margin-top:4px;vertical-align:middle;margin-left:-6px;margin-right:-12px;position:relative;top:-2px}toolbar-search input:focus{outline:none}toolbar-search .input-show-hide{-webkit-transition:all ease-out .25s;transition:all ease-out .25s}toolbar-search .input-show-hide.ng-hide{-webkit-transition:all ease-in .25s;transition:all ease-in .25s;width:0;opacity:0;margin-left:0;margin-right:0} -------------------------------------------------------------------------------- /gulp_tasks/build/auth.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('auth', function () { 4 | return gulp.src(['src/auth.html', 'src/auth.json']) 5 | .pipe(gulp.dest('dist')); 6 | }); 7 | -------------------------------------------------------------------------------- /gulp_tasks/build/build.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('build', ['scripts', 'full', 'plugins', 'styles', 'dist', 'auth', 'eslint']); 4 | -------------------------------------------------------------------------------- /gulp_tasks/build/core.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('core', function () { 4 | var ngAnnotate = require('gulp-ng-annotate'); 5 | var angularFilesort = require('gulp-angular-filesort'); 6 | var uglifyjs = require('gulp-uglifyjs'); 7 | var concat = require('gulp-concat'); 8 | 9 | return gulp.src( 10 | [ 11 | 'src/directives/**/*.js', 12 | 'src/services/**/*.js', 13 | 'src/sw.ui*/**/*.js', 14 | 'src/plugins/**/*.core.js', 15 | 'src/modules/**/*.js' 16 | ] 17 | ) 18 | .pipe(ngAnnotate()) 19 | .pipe(angularFilesort()) 20 | .pipe(concat('swagger-ui-material.core.js')) 21 | .pipe(gulp.dest('dist/scripts')) 22 | .pipe(uglifyjs('swagger-ui-material.core.min.js')) 23 | .pipe(gulp.dest('dist/scripts')); 24 | }); 25 | -------------------------------------------------------------------------------- /gulp_tasks/build/dist.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('dist', ['scripts', 'full', 'plugins', 'styles'], function () { 4 | var inject = require('gulp-inject'); 5 | 6 | function transform () { 7 | var args = arguments; 8 | 9 | args[0] = args[0].replace('/dist', '.'); 10 | 11 | return inject.transform.apply(inject.transform, args); 12 | } 13 | 14 | return gulp.src('src/index.html') 15 | .pipe(inject(gulp.src('dist/styles/swagger-ui-material.min.css', {read: false}), { 16 | transform: transform 17 | })) 18 | .pipe(inject(gulp.src(['dist/scripts/swagger-ui-material.full.min.js'], {read: false}), { 19 | transform: transform 20 | })) 21 | .pipe(gulp.dest('dist')); 22 | }); 23 | -------------------------------------------------------------------------------- /gulp_tasks/build/eslint.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('eslint', function () { 4 | var eslint = require('gulp-eslint'); 5 | 6 | return gulp.src(['src/**/*.js', 'gulpfile.js', 'gulp_tasks/**/*.js']) 7 | .pipe(eslint()) 8 | .pipe(eslint.format()) 9 | .pipe(eslint.failAfterError()); 10 | }); 11 | -------------------------------------------------------------------------------- /gulp_tasks/build/full.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('full', ['scripts'], function () { 4 | var concat = require('gulp-concat'); 5 | var uglifyjs = require('gulp-uglifyjs'); 6 | var ngAnnotate = require('gulp-ng-annotate'); 7 | 8 | return gulp.src( 9 | [ 10 | 'dist/scripts/swagger-ui-material.js', 11 | 'src/plugins/**/*.js', 12 | '!src/plugins/**/*.core.js', 13 | '!src/plugins/**/*.broken.js', 14 | '!src/plugins/**/*.sample.js' 15 | ]) 16 | .pipe(concat('swagger-ui-material.full.js')) 17 | .pipe(gulp.dest('dist/scripts')) 18 | .pipe(ngAnnotate()) 19 | .pipe(uglifyjs('swagger-ui-material.full.min.js')) 20 | .pipe(gulp.dest('dist/scripts')); 21 | }); 22 | -------------------------------------------------------------------------------- /gulp_tasks/build/graph.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('graph', function () { 4 | var ngGraph = require('gulp-angular-architecture-graph'); 5 | 6 | return gulp.src('src/**/*.js') 7 | .pipe(ngGraph({ 8 | dest: '.architecture' 9 | })); 10 | }); 11 | -------------------------------------------------------------------------------- /gulp_tasks/build/hub.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('hub', function (done) { 4 | var fs = require('fs'); 5 | var path = require('path'); 6 | var rainbows = require('../../lib/api-models-rainbows'); 7 | var meta = require('../../lib/api-models-meta'); 8 | var manual = require('../../test/manual/manual.json'); 9 | 10 | rainbows.load(function (rs) { 11 | meta.load(function (ms) { 12 | var data = {}; 13 | var keys = Object.keys(ms); 14 | 15 | for (var i = 0; i < keys.length; i++) { 16 | var k = keys[i]; 17 | 18 | data[k] = { 19 | colors: rs[k], 20 | security: ms[k].security, 21 | cors: ms[k].cors, 22 | operations: ms[k].operations 23 | }; 24 | 25 | if (manual[k] && (manual[k].tested !== undefined)) { 26 | data[k].tested = manual[k].tested; 27 | } 28 | 29 | if (manual[k] && manual[k].local) { 30 | data[k].security.push('local'); 31 | } 32 | 33 | // if (manual[k].notes !== undefined) { 34 | // data[k].notes = manual[k].notes; 35 | // } 36 | } 37 | 38 | fs.writeFile(path.join(__dirname, '../../src/hub.json'), JSON.stringify(data), function () { 39 | done(); 40 | }); 41 | }); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /gulp_tasks/build/info.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('info', function () { 4 | var GENERATE_ARRAY = true; 5 | 6 | var replace = require('gulp-replace'); 7 | var rename = require('gulp-rename'); 8 | var know = require('know-your-http-well'); 9 | 10 | var header = {}; 11 | 12 | know.headers.forEach(function (i) { 13 | if (GENERATE_ARRAY) { 14 | header[i.header.toLowerCase()] = [ 15 | i.header, 16 | i.description.replace(/^"(.*)"/, '$1'), 17 | i.spec_title, 18 | i.spec_href 19 | ]; 20 | } else { 21 | header[i.header.toLowerCase()] = { 22 | header: i.header, 23 | description: i.description.replace(/^"(.*)"/, '$1'), 24 | title: i.spec_title, 25 | url: i.spec_href 26 | }; 27 | } 28 | }); 29 | 30 | var status = {}; 31 | 32 | know.statusCodes.forEach(function (i) { 33 | if (GENERATE_ARRAY) { 34 | status[i.code] = [ 35 | i.phrase, 36 | i.description.replace(/^"(.*)"/, '$1'), 37 | i.spec_title, 38 | i.spec_href 39 | ]; 40 | } else { 41 | status[i.code] = { 42 | phrase: i.phrase, 43 | description: i.description.replace(/^"(.*)"/, '$1'), 44 | title: i.spec_title, 45 | url: i.spec_href 46 | }; 47 | } 48 | }); 49 | 50 | var method = {}; 51 | var swaggerMethods = ['DELETE', 'GET', 'POST', 'PUT', 'PATCH', 'HEAD', 'OPTIONS']; 52 | 53 | know.methods.forEach(function (i) { 54 | if (swaggerMethods.indexOf(i.method) > -1) { 55 | if (GENERATE_ARRAY) { 56 | method[i.method.toLowerCase()] = [ 57 | i.description.replace(/^"(.*)"/, '$1'), 58 | i.spec_title, 59 | i.spec_href, 60 | i.safe, 61 | i.idempotent, 62 | i.cacheable 63 | ]; 64 | } else { 65 | method[i.method.toLowerCase()] = { 66 | description: i.description.replace(/^"(.*)"/, '$1'), 67 | title: i.spec_title, 68 | url: i.spec_href, 69 | safe: i.safe, 70 | idempotent: i.idempotent, 71 | cacheable: i.cacheable 72 | }; 73 | } 74 | } 75 | }); 76 | 77 | function stringify (obj) { 78 | var space = ' '; 79 | 80 | return JSON.stringify(obj, null, 4) 81 | .replace(/^/gm, space) 82 | .replace(space + '{', '{') 83 | .replace(/^( *)"(([a-zA-Z]+[0-9]*)|([0-9]+))": (.*)(,?)$/gm, '$1$2: $5$6') 84 | .replace(/^( *)"([^"]+)": (.*)(,?)$/gm, '$1\'$2\': $3$4') 85 | .replace(/^( *)([^:]+): "(.*)"(,?)$/gm, function (whole, p1, p2, p3, p4) { 86 | return p1 + p2 + ': \'' + p3.replace(/'/g, '\\\'') + '\'' + p4; 87 | }) 88 | .replace(/^( *)"(.*)"(,?)$/gm, function (whole, p1, p2, p3) { 89 | return p1 + '\'' + p2.replace(/'/g, '\\\'') + '\'' + p3; 90 | }); 91 | } 92 | 93 | return gulp.src('src/sw.ui.md/http-data.template') 94 | .pipe(replace(/(method: ){.*}/, '$1' + stringify(method))) 95 | .pipe(replace(/(status: ){.*}/, '$1' + stringify(status))) 96 | .pipe(replace(/(header: ){.*}/, '$1' + stringify(header))) 97 | .pipe(rename('http-data.js')) 98 | .pipe(gulp.dest('src/sw.ui.md')); 99 | }); 100 | -------------------------------------------------------------------------------- /gulp_tasks/build/plugins.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('plugins', function () { 4 | var uglify = require('gulp-uglify'); 5 | var ngAnnotate = require('gulp-ng-annotate'); 6 | var rename = require('gulp-rename'); 7 | 8 | return gulp.src(['src/plugins/**/*.js', '!src/plugins/parse/*.js', '!src/plugins/**/*.broken.js']) 9 | .pipe(gulp.dest('dist/plugins')) 10 | .pipe(ngAnnotate()) 11 | .pipe(uglify()) 12 | .pipe(rename({suffix: '.min'})) 13 | .pipe(gulp.dest('dist/plugins')); 14 | }); 15 | -------------------------------------------------------------------------------- /gulp_tasks/build/scripts.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('scripts', ['core', 'templates'], function () { 4 | var angularFilesort = require('gulp-angular-filesort'); 5 | var concat = require('gulp-concat'); 6 | var uglifyjs = require('gulp-uglifyjs'); 7 | var ngAnnotate = require('gulp-ng-annotate'); 8 | 9 | return gulp.src(['dist/scripts/swagger-ui-material.core.js', 'dist/scripts/swagger-ui-material.templates.js']) 10 | .pipe(angularFilesort()) 11 | .pipe(concat('swagger-ui-material.js')) 12 | .pipe(gulp.dest('dist/scripts')) 13 | .pipe(ngAnnotate()) 14 | .pipe(uglifyjs('swagger-ui-material.min.js')) 15 | .pipe(gulp.dest('dist/scripts')); 16 | }); 17 | -------------------------------------------------------------------------------- /gulp_tasks/build/styles.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('styles', function () { 4 | var csso = require('gulp-csso'); 5 | var concat = require('gulp-concat'); 6 | var rename = require('gulp-rename'); 7 | 8 | return gulp.src('src/**/*.css') 9 | .pipe(concat('swagger-ui-material.css')) 10 | .pipe(gulp.dest('dist/styles')) 11 | .pipe(csso()) 12 | .pipe(rename('swagger-ui-material.min.css')) 13 | .pipe(gulp.dest('dist/styles')); 14 | }); 15 | -------------------------------------------------------------------------------- /gulp_tasks/build/templates.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('templates', function () { 4 | var angularTemplatecache = require('gulp-angular-templatecache'); 5 | var htmlmin = require('gulp-htmlmin'); 6 | var rename = require('gulp-rename'); 7 | var uglifyjs = require('gulp-uglifyjs'); 8 | var ngAnnotate = require('gulp-ng-annotate'); 9 | 10 | return gulp.src(['src/**/*.html', '!src/index.html']) 11 | .pipe(htmlmin({ 12 | removeComments: true, 13 | collapseWhitespace: true, 14 | conservativeCollapse: true, 15 | keepClosingSlash: true, 16 | caseSensitive: true 17 | })) 18 | .pipe(angularTemplatecache({ 19 | root: null, 20 | module: 'sw.ui.md' 21 | })) 22 | .pipe(rename('swagger-ui-material.templates.js')) 23 | .pipe(gulp.dest('dist/scripts')) 24 | .pipe(ngAnnotate()) 25 | .pipe(uglifyjs('swagger-ui-material.templates.min.js')) 26 | .pipe(gulp.dest('dist/scripts')); 27 | }); 28 | -------------------------------------------------------------------------------- /gulp_tasks/demo/copy.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('copy', ['build'], function () { 4 | return gulp.src(['dist/scripts/swagger-ui-material.full.min.js', 5 | 'dist/styles/swagger-ui-material.min.css', 6 | 'test/fixtures/auth/auth.json', 7 | 'src/auth.html', 8 | 'test/fixtures/examples/*.json', 9 | 'test/fixtures/markdown/*.json']).pipe(gulp.dest('demo')); 10 | }); 11 | 12 | gulp.task('copy:hub', function () { 13 | return gulp.src('src/hub/*.*').pipe(gulp.dest('demo/hub')); 14 | }); 15 | -------------------------------------------------------------------------------- /gulp_tasks/demo/demo.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('demo', ['copy', 'copy:hub', 'styles:gfm'], function () { 4 | var inject = require('gulp-inject'); 5 | 6 | function transform () { 7 | var args = arguments; 8 | 9 | args[0] = args[0].replace('/demo', '.'); 10 | 11 | return inject.transform.apply(inject.transform, args); 12 | } 13 | 14 | return gulp.src('src/index.html') 15 | .pipe(inject(gulp.src('demo/*.css', {read: false}), { 16 | transform: transform 17 | })) 18 | .pipe(inject(gulp.src(['demo/*.js'], {read: false}), { 19 | transform: transform 20 | })) 21 | .pipe(gulp.dest('demo')); 22 | }); 23 | -------------------------------------------------------------------------------- /gulp_tasks/demo/styles.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('styles:gfm', function () { 4 | var csso = require('gulp-csso'); 5 | var rename = require('gulp-rename'); 6 | 7 | return gulp.src('bower_components/github-markdown-css/github-markdown.css') 8 | .pipe(csso()) 9 | .pipe(rename('github-markdown.min.css')) 10 | .pipe(gulp.dest('demo')); 11 | }); 12 | -------------------------------------------------------------------------------- /gulp_tasks/deploy/publish.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('deploy', ['demo'], function () { 4 | var ghPages = require('gulp-gh-pages'); 5 | 6 | return gulp.src('demo/**/*') 7 | .pipe(ghPages()); 8 | }); 9 | -------------------------------------------------------------------------------- /gulp_tasks/examples/gfm.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('gfm', function (done) { 4 | var fs = require('fs'); 5 | var path = require('path'); 6 | var minimal = require('../../test/fixtures/examples/swagger-minimal.json'); 7 | 8 | fs.readFile(path.join(__dirname, '../../test/fixtures/markdown/README.md'), 'utf8', function (err, data) { 9 | if (err) { 10 | done(err); 11 | return; 12 | } 13 | 14 | minimal.info.title = 'GiHub Flavored Markdown Test'; 15 | minimal.info.description = data; 16 | 17 | fs.writeFile(path.join(__dirname, '../../test/fixtures/markdown/swagger-gfm.json'), JSON.stringify(minimal, null, 2), done); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | require('require-dir')('./gulp_tasks', {recurse: true}); 4 | 5 | gulp.task('default', ['build']); 6 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var pack = require('./package'); 4 | var path = require('path'); 5 | 6 | module.exports = { 7 | version: pack.version, 8 | dist: path.resolve(__dirname, 'dist') 9 | }; 10 | -------------------------------------------------------------------------------- /lib/api-models-meta/got/license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Sindre Sorhus (sindresorhus.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/api-models-meta/got/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_args": [ 3 | [ 4 | "got", 5 | "C:\\_DEVELOP\\api-colors" 6 | ] 7 | ], 8 | "_from": "got@*", 9 | "_id": "got@6.2.0", 10 | "_inCache": true, 11 | "_installable": true, 12 | "_location": "/got", 13 | "_nodeVersion": "4.2.4", 14 | "_npmOperationalInternal": { 15 | "host": "packages-13-west.internal.npmjs.com", 16 | "tmp": "tmp/got-6.2.0.tgz_1456991638863_0.8261470813304186" 17 | }, 18 | "_npmUser": { 19 | "email": "floatdrop@gmail.com", 20 | "name": "floatdrop" 21 | }, 22 | "_npmVersion": "2.14.12", 23 | "_phantomChildren": {}, 24 | "_requested": { 25 | "name": "got", 26 | "raw": "got", 27 | "rawSpec": "", 28 | "scope": null, 29 | "spec": "*", 30 | "type": "range" 31 | }, 32 | "_requiredBy": [ 33 | "/" 34 | ], 35 | "_resolved": "https://registry.npmjs.org/got/-/got-6.2.0.tgz", 36 | "_shasum": "eab52adb8b44fad77430ed828d0d531264afb2d7", 37 | "_shrinkwrap": null, 38 | "_spec": "got", 39 | "_where": "C:\\_DEVELOP\\api-colors", 40 | "browser": { 41 | "unzip-response": false 42 | }, 43 | "bugs": { 44 | "url": "https://github.com/sindresorhus/got/issues" 45 | }, 46 | "dependencies": { 47 | "create-error-class": "^3.0.0", 48 | "duplexer3": "^0.1.4", 49 | "get-stream": "^1.1.0", 50 | "is-plain-obj": "^1.0.0", 51 | "is-redirect": "^1.0.0", 52 | "is-retry-allowed": "^1.0.0", 53 | "is-stream": "^1.0.0", 54 | "lowercase-keys": "^1.0.0", 55 | "node-status-codes": "^2.0.0", 56 | "timed-out": "^2.0.0", 57 | "unzip-response": "^1.0.0", 58 | "url-parse-lax": "^1.0.0" 59 | }, 60 | "description": "Simplified HTTP/HTTPS requests", 61 | "devDependencies": { 62 | "ava": "^0.12.0", 63 | "coveralls": "^2.11.4", 64 | "get-port": "^2.0.0", 65 | "into-stream": "^2.0.0", 66 | "nyc": "^5.0.1", 67 | "pem": "^1.4.4", 68 | "pify": "^2.3.0", 69 | "tempfile": "^1.1.1", 70 | "xo": "*" 71 | }, 72 | "directories": {}, 73 | "dist": { 74 | "shasum": "eab52adb8b44fad77430ed828d0d531264afb2d7", 75 | "tarball": "http://registry.npmjs.org/got/-/got-6.2.0.tgz" 76 | }, 77 | "engines": { 78 | "node": ">=4" 79 | }, 80 | "files": [ 81 | "index.js" 82 | ], 83 | "gitHead": "fc86dcc8f100c6b93fe70e945807a4c68be90f4f", 84 | "homepage": "https://github.com/sindresorhus/got", 85 | "keywords": [ 86 | "curl", 87 | "fetch", 88 | "get", 89 | "got", 90 | "http", 91 | "https", 92 | "request", 93 | "simple", 94 | "uri", 95 | "url", 96 | "util", 97 | "utility", 98 | "wget" 99 | ], 100 | "license": "MIT", 101 | "maintainers": [ 102 | { 103 | "name": "sindresorhus", 104 | "email": "sindresorhus@gmail.com" 105 | }, 106 | { 107 | "name": "floatdrop", 108 | "email": "floatdrop@gmail.com" 109 | }, 110 | { 111 | "name": "kevva", 112 | "email": "kevinmartensson@gmail.com" 113 | } 114 | ], 115 | "name": "got", 116 | "optionalDependencies": {}, 117 | "readme": "ERROR: No README data found!", 118 | "repository": { 119 | "type": "git", 120 | "url": "git+https://github.com/sindresorhus/got.git" 121 | }, 122 | "scripts": { 123 | "coveralls": "nyc report --reporter=text-lcov | coveralls", 124 | "test": "xo && nyc ava" 125 | }, 126 | "version": "6.2.0", 127 | "xo": { 128 | "esnext": true 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /lib/api-models-meta/index.js: -------------------------------------------------------------------------------- 1 | var APIs = 'https://api.apis.guru/v2/list.json'; 2 | var DIR = __dirname; 3 | var DATA = DIR + '/api-models-meta.json'; 4 | var EXAMPLE = 'https://example.com'; 5 | var METHODS = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options']; 6 | var OPTS = { 7 | headers: { 8 | origin: EXAMPLE, 9 | referer: EXAMPLE, 10 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36' 11 | } 12 | }; 13 | 14 | const fs = require('fs'); 15 | const async = require('async'); 16 | const got = require('./got'); 17 | const url = require('url'); 18 | 19 | module.exports.download = download; 20 | module.exports.load = load; 21 | 22 | if (!module.parent) { 23 | download(); 24 | } 25 | 26 | function load (done) { 27 | try { 28 | done(require(DATA)); 29 | } catch (ign) { 30 | download(done); 31 | } 32 | } 33 | 34 | function download (done) { 35 | got(APIs).then(response => { 36 | var apis = JSON.parse(response.body); 37 | var data = {}; 38 | 39 | async.forEachOfLimit(apis, 32, 40 | (item, key, callback) => { 41 | var swaggerUrl = item.versions[item.preferred].swaggerUrl; 42 | data[key] = {}; 43 | 44 | got(swaggerUrl, OPTS).then(response => { 45 | var swagger = JSON.parse(response.body); 46 | 47 | data[key].security = []; 48 | 49 | if (swagger.securityDefinitions) { 50 | var sKeys = Object.keys(swagger.securityDefinitions); 51 | 52 | if (sKeys.length) { 53 | sKeys.forEach(function (sKey) { 54 | data[key].security.push(swagger.securityDefinitions[sKey].flow || swagger.securityDefinitions[sKey].type); 55 | }); 56 | } 57 | } 58 | 59 | if (!data[key].security.length) { 60 | // TODO: detect local security 61 | } 62 | 63 | data[key].operations = numOperations(swagger); 64 | 65 | var api = url.format({ 66 | protocol: swagger.schemes[0] || 'http', 67 | host: swagger.host, 68 | pathname: swagger.basePath 69 | }); 70 | 71 | got(api, OPTS).then(response => { 72 | var acal = response.headers['access-control-allow-origin']; 73 | data[key].cors = (acal === '*') || (acal === EXAMPLE); 74 | console.log(api, response.statusCode, response.statusMessage, data[key]); 75 | 76 | if (data[key]) { 77 | callback(); 78 | } else if (response.statusCode >= 404) { 79 | api = url.format({ 80 | protocol: swagger.schemes[0] || 'http', 81 | host: swagger.host, 82 | pathname: swagger.basePath + getPath(swagger) 83 | }); 84 | 85 | got(api, OPTS).then(response => { 86 | acal = response.headers['access-control-allow-origin']; 87 | data[key].cors = (acal === '*') || (acal === EXAMPLE); 88 | console.log(api, response.statusCode, response.statusMessage, data[key]); 89 | callback(); 90 | }, error => { 91 | console.error(api, 'ERROR', error.statusCode, error.message); 92 | callback() 93 | }); 94 | } else { 95 | callback(); 96 | } 97 | }, error => { 98 | console.error(api, 'ERROR', error.statusCode, error.message); 99 | data[key].cors = null; 100 | callback(); 101 | }); 102 | }); 103 | }, () => { 104 | fs.writeFile(DATA, JSON.stringify(data), function () { 105 | if (done) { 106 | done(data) 107 | } 108 | }); 109 | }) 110 | .catch(exception => { 111 | console.error('EXCEPTION', exception); 112 | }); 113 | }); 114 | 115 | function getPath (swagger) { 116 | var paths = Object.keys(swagger.paths); 117 | 118 | for (var i = 0; i < paths.length; i++) { 119 | var p = paths[i]; 120 | 121 | if (swagger.paths[p]['get']) { 122 | return p; 123 | } 124 | } 125 | 126 | return paths[0]; 127 | } 128 | 129 | function numOperations (swagger) { 130 | var paths = (swagger.paths || {}); 131 | var count = 0; 132 | 133 | for (var path in paths) { 134 | METHODS.forEach(function (m) { 135 | if (paths[path][m]) { 136 | count++; 137 | } 138 | }); 139 | } 140 | 141 | return count; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /lib/api-models-meta/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api-models-meta", 3 | "version": "1.0.0", 4 | "private": true, 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "MIT", 11 | "dependencies": { 12 | "async": "^1.5.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/api-models-rainbows/index.js: -------------------------------------------------------------------------------- 1 | var APIs = 'https://api.apis.guru/v2/list.json'; 2 | var COLORS = 3; 3 | var DIR = __dirname; 4 | var DATA = DIR + '/api-models-rainbows.json'; 5 | 6 | const fs = require('fs'); 7 | const async = require('async'); 8 | const got = require('got'); 9 | const url = require('url'); 10 | const PNG = require('pngjs').PNG; 11 | const colorgram = require('colorgram'); 12 | const gm = require('gm'); 13 | const d3Color = require('d3-color'); 14 | 15 | module.exports.download = download; 16 | module.exports.load = load; 17 | 18 | if (!module.parent) { 19 | download(); 20 | } 21 | 22 | function load (done) { 23 | try { 24 | done(require(DATA)); 25 | } catch (ign) { 26 | download(done); 27 | } 28 | } 29 | 30 | function download (done) { 31 | got(APIs).then(response => { 32 | var apis = JSON.parse(response.body); 33 | var colors = {}; 34 | 35 | async.forEachOfLimit(apis, 32, (item, key, callback) => { 36 | var info = item.versions[item.preferred].info; 37 | var logo = info['x-logo']; 38 | 39 | if (logo) { 40 | var bgColor = logo.backgroundColor; 41 | var ext = url.parse(logo.url).path.replace(/^.*(\.[a-z]+)$/gi, '$1'); 42 | var name = key + ext; 43 | var down = got.stream(logo.url); 44 | 45 | if (ext.toLowerCase() !== '.png') { 46 | down = gm(down, 'image.svg').stream('png'); 47 | } 48 | 49 | down.pipe(new PNG()) 50 | .on('error', ()=> { 51 | console.error('ERROR', name); 52 | callback(); 53 | }) 54 | .on('parsed', function () { 55 | console.log(name); 56 | colors[key] = colorgram.extract({ 57 | data: this.data, 58 | width: this.width, 59 | height: this.height, 60 | channels: 4 61 | }, bgColor ? (COLORS - 1) : COLORS); 62 | 63 | if (bgColor) { 64 | var r = d3Color.rgb(bgColor); 65 | colors[key].push([r.r, r.g, r.b, 1]); 66 | } 67 | 68 | colors[key].forEach(function (c) { 69 | c.pop(); 70 | 71 | var n = d3Color.rgb(c[0], c[1], c[2], 1); 72 | var h = d3Color.cubehelix(n); 73 | h.s = Math.max(h.s, 1); 74 | h.l = Math.max(h.l, 0.8); 75 | h.l = Math.min(h.l, 1.2); 76 | 77 | c[0] = h.h; 78 | c[1] = h.s; 79 | c[2] = h.l; 80 | }); 81 | 82 | colors[key].sort((b, a) => { 83 | return a[0] - b[0]; 84 | }); 85 | 86 | colors[key].forEach((c) => { 87 | var r = d3Color.rgb(d3Color.cubehelix(c[0], c[1], c[2], 1).rgb().toString()); 88 | 89 | c[0] = r.r; 90 | c[1] = r.g; 91 | c[2] = r.b; 92 | }); 93 | 94 | callback(); 95 | }); 96 | } else { 97 | callback(); 98 | } 99 | }, () => { 100 | fs.writeFile(DATA, JSON.stringify(colors), () => { 101 | console.log('DONE'); 102 | 103 | if(done) { 104 | done(colors); 105 | } 106 | }); 107 | }); 108 | }); 109 | } 110 | -------------------------------------------------------------------------------- /lib/api-models-rainbows/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api-models-rainbows", 3 | "version": "1.0.0", 4 | "private": true, 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "MIT", 11 | "dependencies": { 12 | "async": "^1.5.2", 13 | "colorgram": "^0.1.5", 14 | "d3-color": "^0.4.2", 15 | "gm": "^1.21.1", 16 | "got": "^6.2.0", 17 | "pngjs": "^2.2.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-swagger-ui-material", 3 | "description": "Material Design template for angular-swager-ui", 4 | "version": "0.2.3", 5 | "author": "Jan Forst ", 6 | "devDependencies": { 7 | "eslint-config-angular": "^0.5.0", 8 | "eslint-config-standard": "^5.1.0", 9 | "eslint-plugin-angular": "^1.0.0", 10 | "eslint-plugin-promise": "^1.0.8", 11 | "eslint-plugin-standard": "^1.3.2", 12 | "gulp": "^3.9.1", 13 | "gulp-angular-architecture-graph": "0.0.3", 14 | "gulp-angular-filesort": "^1.1.1", 15 | "gulp-angular-templatecache": "^1.8.0", 16 | "gulp-concat": "^2.6.0", 17 | "gulp-csso": "^1.1.0", 18 | "gulp-eslint": "^2.0.0", 19 | "gulp-gh-pages": "^0.5.4", 20 | "gulp-htmlmin": "^1.3.0", 21 | "gulp-inject": "^3.0.0", 22 | "gulp-merge": "^0.1.1", 23 | "gulp-ng-annotate": "^2.0.0", 24 | "gulp-rename": "^1.2.2", 25 | "gulp-replace": "^0.5.4", 26 | "gulp-uglify": "^1.5.3", 27 | "gulp-uglifyjs": "^0.6.2", 28 | "know-your-http-well": "^0.2.0", 29 | "require-dir": "^0.3.0" 30 | }, 31 | "license": "MIT", 32 | "private": true, 33 | "scripts": { 34 | "test": "echo \"Error: no test specified\" && exit 1" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | exports.config = { 2 | seleniumAddress: 'http://localhost:4444/wd/hub', 3 | capabilities: { 4 | 'browserName': 'chrome' 5 | }, 6 | jasmineNodeOpts: { 7 | showColors: true 8 | }, 9 | suites: { 10 | hub: 'test/e2e/hub.spec.js', 11 | all: 'test/e2e/all.spec.js' 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /src/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "angular", 3 | "rules": { 4 | "semi": [ 5 | 2, 6 | "always" 7 | ], 8 | "indent": [ 9 | 2, 10 | 4, 11 | { 12 | "SwitchCase": 1 13 | } 14 | ], 15 | "complexity": [ 16 | 2, 17 | 22 18 | ] 19 | }, 20 | "globals": { 21 | "angular": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/auth.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OAuth 2.0 Callback 6 | 7 | 29 | 30 | -------------------------------------------------------------------------------- /src/directives/directives.module.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.directives', []); 4 | -------------------------------------------------------------------------------- /src/directives/file-input/file-input.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Orange angular-swagger-ui - v0.3.0 3 | * 4 | * (C) 2015 Orange, all right reserved 5 | * MIT Licensed 6 | */ 7 | 'use strict'; 8 | 9 | angular 10 | .module('sw.ui.directives') 11 | .directive('fileInput', function () { 12 | // helper to be able to retrieve HTML5 File in ngModel from input 13 | return { 14 | restrict: 'A', 15 | require: 'ngModel', 16 | link: function (scope, element, attr, ngModel) { 17 | element.bind('change', function () { 18 | scope.$apply(function () { 19 | // TODO manage multiple files ? 20 | ngModel.$setViewValue(element[0].files[0]); 21 | }); 22 | }); 23 | } 24 | }; 25 | }); 26 | -------------------------------------------------------------------------------- /src/directives/toolbar-edit/toolbar-edit.css: -------------------------------------------------------------------------------- 1 | toolbar-edit input { 2 | background: transparent; 3 | border: none; 4 | /* TODO: themed color */ 5 | color: #fff; 6 | margin-top: 4px; 7 | vertical-align: middle; 8 | position: relative; 9 | top: -2px; 10 | } 11 | 12 | toolbar-edit input:focus { 13 | outline: none; 14 | } 15 | -------------------------------------------------------------------------------- /src/directives/toolbar-edit/toolbar-edit.html: -------------------------------------------------------------------------------- 1 | 2 | edit 3 | 4 |
8 | 9 | -------------------------------------------------------------------------------- /src/directives/toolbar-edit/toolbar-edit.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.directives') 4 | .directive('toolbarEdit', function ($timeout) { 5 | return { 6 | restrict: 'E', 7 | templateUrl: 'directives/toolbar-edit/toolbar-edit.html', 8 | scope: { 9 | ngModel: '=', 10 | ngChanged: '=', 11 | displayTitle: '=' 12 | }, 13 | link: function (scope, element) { 14 | var t; 15 | scope.open = false; 16 | scope.init = false; 17 | $timeout(function () { 18 | scope.init = true; 19 | }, 200); 20 | scope.focus = function () { 21 | $timeout.cancel(t); 22 | 23 | $timeout(function () { 24 | element.children().eq(1).children()[0].focus(); 25 | }, 200); 26 | }; 27 | scope.blur = function () { 28 | t = $timeout(function () { 29 | scope.open = false; 30 | scope.ngChanged(); 31 | }, 200); 32 | }; 33 | scope.toggle = function () { 34 | scope.open = !scope.open; 35 | 36 | if (scope.open) { 37 | scope.focus(); 38 | } else { 39 | scope.ngChanged(); 40 | } 41 | }; 42 | } 43 | }; 44 | }); 45 | -------------------------------------------------------------------------------- /src/directives/toolbar-search/toolbar-search.css: -------------------------------------------------------------------------------- 1 | toolbar-search input { 2 | background: transparent; 3 | border: none; 4 | /* TODO: themed color */ 5 | color: #fff; 6 | width: 100px; 7 | margin-top: 4px; 8 | vertical-align: middle; 9 | margin-left: -6px; 10 | margin-right: -12px; 11 | position: relative; 12 | top: -2px; 13 | } 14 | 15 | toolbar-search input:focus { 16 | outline: none; 17 | } 18 | 19 | toolbar-search .input-show-hide { 20 | -webkit-transition: all ease-out 0.25s; 21 | transition: all ease-out 0.25s; 22 | } 23 | 24 | toolbar-search .input-show-hide.ng-hide { 25 | -webkit-transition: all ease-in 0.25s; 26 | transition: all ease-in 0.25s; 27 | width: 0; 28 | opacity: 0; 29 | margin-left: 0; 30 | margin-right: 0; 31 | } 32 | -------------------------------------------------------------------------------- /src/directives/toolbar-search/toolbar-search.html: -------------------------------------------------------------------------------- 1 | 2 | search 3 | 4 | 6 | 7 | close 8 | 9 | -------------------------------------------------------------------------------- /src/directives/toolbar-search/toolbar-search.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.directives') 4 | .directive('toolbarSearch', function ($timeout) { 5 | return { 6 | restrict: 'E', 7 | templateUrl: 'directives/toolbar-search/toolbar-search.html', 8 | scope: { 9 | ngModel: '=', 10 | ngChanged: '=', 11 | open: '=' 12 | }, 13 | link: function (scope, element) { 14 | $timeout(function () { 15 | scope.init = true; 16 | }, 200); 17 | 18 | scope.focus = function () { 19 | $timeout(function () { 20 | element.children()[1].focus(); 21 | }, 200); 22 | }; 23 | 24 | scope.$watch('ngModel', scope.ngChanged); 25 | } 26 | }; 27 | }); 28 | -------------------------------------------------------------------------------- /src/directives/truncate/truncate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.directives') 4 | .directive('truncate', function (truncation) { 5 | return { 6 | restrict: 'A', 7 | scope: { 8 | ngBindHtml: '=', 9 | ngBind: '=' 10 | }, 11 | link: function (scope, element, attr) { 12 | scope.$watch('ngBind', update); 13 | scope.$watch('ngBindHtml', update); 14 | 15 | function update () { 16 | var more = angular.element('\u2026'); 17 | 18 | element.empty(); 19 | 20 | element.append(truncation( 21 | (scope.ngBind ? angular.element('
').text(scope.ngBind).html() : null) || scope.ngBindHtml, 22 | { 23 | length: attr.truncate || 144, 24 | words: true, 25 | ellipsis: more[0] 26 | } 27 | )); 28 | 29 | more.bind('click', function (event) { 30 | event.preventDefault(); 31 | event.stopPropagation(); 32 | if (scope.ngBind) { 33 | element[0].textContent = scope.ngBind; 34 | } else if (scope.ngBindHtml) { 35 | element[0].innerHTML = scope.ngBindHtml; 36 | } 37 | }); 38 | } 39 | } 40 | }; 41 | }) 42 | .factory('truncation', function () { 43 | var chop = /(\s*\S+|\s)$/; 44 | 45 | // based on https://github.com/pathable/truncate 46 | function truncate (root, opts) { 47 | var text = root.textContent; 48 | var excess = text.length - opts.length; 49 | 50 | if (opts.words && excess > 0) { 51 | excess = text.length - text.slice(0, opts.length).replace(chop, '').length - 1; 52 | } 53 | 54 | if (excess < 0 || !excess && !opts.truncated) return; 55 | 56 | for (var i = root.childNodes.length - 1; i >= 0; i--) { 57 | var el = root.childNodes[i]; 58 | text = el.textContent; 59 | var length = text.length; 60 | 61 | if (length <= excess) { 62 | opts.truncated = true; 63 | excess -= length; 64 | el.remove(); 65 | continue; 66 | } 67 | 68 | if (el.nodeType === 3) { 69 | var s = el.splitText(length - excess - 1); 70 | s.parentNode.replaceChild(opts.ellipsis, s); 71 | return; 72 | } 73 | 74 | truncate(el, angular.extend(opts, {length: length - excess})); 75 | return; 76 | } 77 | } 78 | 79 | return function (html, options) { 80 | var root = angular.element('
').append(html)[0]; 81 | truncate(root, options); 82 | return root; 83 | }; 84 | }); 85 | -------------------------------------------------------------------------------- /src/modules/content/content.ctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md') 4 | .controller('ContentController', function ($rootScope, data, theme) { 5 | var vm = this; 6 | 7 | vm.data = data; 8 | vm.theme = theme; 9 | 10 | vm.toggleGroup = toggleGroup; 11 | vm.selectOperation = selectOperation; 12 | 13 | function toggleGroup (group, $event) { 14 | $event.preventDefault(); 15 | $event.stopPropagation(); 16 | 17 | // Space bar does not stop propagation :-( 18 | if (($event.keyCode || $event.which) === 32) { 19 | return; 20 | } 21 | 22 | group.open = !group.open; 23 | } 24 | 25 | function selectOperation (op, $event) { 26 | $event.stopPropagation(); 27 | data.model.sop = op; 28 | $rootScope.$emit('sw:operation'); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /src/modules/description/description.ctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md') 4 | .controller('DescriptionController', function ($scope, $log, data) { 5 | var vm = this; 6 | 7 | $scope.$on('sw:changed', update); 8 | 9 | update(); 10 | 11 | function update () { 12 | $log.debug('sw:changed:description'); 13 | 14 | vm.description = data.model.info && data.model.info.description; 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /src/modules/detail/header.html: -------------------------------------------------------------------------------- 1 |
2 | 9 |
10 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /src/modules/detail/request/parameter.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 25 | 26 | 27 |
28 |
30 |
31 |
32 |
in:
33 |
34 |
35 |
36 |
type:
37 |
38 | 39 | 40 |
41 |
42 |
43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |
53 | Set 55 | 58 |
59 |
60 |

62 |     

64 | 
65 |     
66 |
67 |
(default)
68 |
69 | {{value}} or 70 |
71 |
(required)
72 |
73 |
74 |
75 | -------------------------------------------------------------------------------- /src/modules/detail/request/request.html: -------------------------------------------------------------------------------- 1 |
2 | Description 3 |
4 |
5 |
6 |
7 | 8 |
9 | 10 |
11 |
12 | Response class 13 |
14 |
15 | 18 |
19 |
20 | 21 | 22 |
23 |

26 |          

28 |     
29 | 30 |
31 | Response type 32 |
34 |
35 | 36 | 38 | 40 | 41 | 42 | 43 |
44 |
45 |
46 | 47 |
48 | Parameters 49 |
53 |
54 | 55 |
56 | Response messages 57 |
58 |
59 |
61 |
62 |
63 |
64 | 65 | 66 | 67 |
68 | -------------------------------------------------------------------------------- /src/modules/detail/response.html: -------------------------------------------------------------------------------- 1 |
2 | 8 | 9 |
10 | 11 | 12 | 13 | 22 | -------------------------------------------------------------------------------- /src/modules/detail/result/result.html: -------------------------------------------------------------------------------- 1 | Request URL 2 |
3 |
4 | 9 |
10 |
11 | Response status 12 |
13 |
14 |
16 |
17 |
18 | Timing 19 |
20 |
21 |
22 | {{t[0]}}: {{t[1] | number:2}} ms 23 |
24 |
25 |
26 |
27 | Response headers 28 |
29 |
30 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | Response body 39 |
40 |
41 | Open 42 |
43 |
44 |
45 |

49 |     
50 |
51 | -------------------------------------------------------------------------------- /src/modules/detail/scripts/scripts.html: -------------------------------------------------------------------------------- 1 | 21 |
22 |
23 | AngularJS 24 |
25 |
26 | Reference 28 |
29 |
30 |
31 |
$http({{vm.sop.mock | json}})
32 | .then(
33 |     function success(response) {
34 |     },
35 |     function error(response) {
36 |     }
37 | )
38 |
39 | 59 | -------------------------------------------------------------------------------- /src/modules/group/group.html: -------------------------------------------------------------------------------- 1 |
2 | 7 |
8 | 9 | 12 | 13 | 14 |
15 |
16 |
17 |
18 |
19 |
20 |
22 |
23 |
24 | -------------------------------------------------------------------------------- /src/modules/meta/meta.ctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md') 4 | .controller('MetaController', function ($scope, $log, data, tools, display) { 5 | var vm = this; 6 | 7 | $scope.$on('sw:changed', update); 8 | 9 | update(); 10 | 11 | function update () { 12 | $log.debug('sw:changed:meta'); 13 | 14 | vm.meta = data.model.info && display.meta( 15 | data.model.info, 16 | data.options.url, 17 | data.options.validatorUrl, 18 | tools.openFile 19 | ); 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /src/modules/meta/meta.html: -------------------------------------------------------------------------------- 1 |
2 |
10 | 11 | 12 | 13 |
14 | Contact 15 |

17 |

18 | 24 |

25 |

26 | 28 | 29 | 30 |

31 |
32 |
33 |
34 |
35 |
36 | -------------------------------------------------------------------------------- /src/modules/operation/operation.html: -------------------------------------------------------------------------------- 1 | 2 |
7 |
8 | 13 |
14 |
15 |
17 |
18 | 19 | -------------------------------------------------------------------------------- /src/modules/toolbar/toolbar.ctrl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md') 4 | .controller('ToolbarController', function ($scope, $log, $mdMedia, data, security, theme) { 5 | var vm = this; 6 | 7 | vm.data = data; 8 | vm.ui = data.ui; 9 | vm.search = null; 10 | vm.searchOpened = false; 11 | vm.editUrl = data.options.url; 12 | vm.loading = false; 13 | vm.$mdMedia = $mdMedia; 14 | 15 | vm.showSecurity = showSecurity; 16 | vm.showProxy = showProxy; 17 | vm.toggleGroups = toggleGroups; 18 | vm.editedUrl = editedUrl; 19 | vm.searchUpdated = searchUpdated; 20 | 21 | $scope.$on('sw:changed', update); 22 | 23 | update(); 24 | 25 | function update () { 26 | $log.debug('sw:changed:toolbar'); 27 | 28 | vm.loading = data.loading; 29 | } 30 | 31 | function editedUrl () { 32 | data.setUrl(vm.editUrl); 33 | } 34 | 35 | function searchUpdated () { 36 | $log.debug('sw:changed:search', vm.search); 37 | 38 | if (!vm.search) { 39 | data.model.search = {}; 40 | } else { 41 | var trimmed = vm.search.toLowerCase().trim(); 42 | var parts = trimmed.split(' '); 43 | var isMethod = ['get', 'post', 'put', 'patch', 'head', 'options', 'delete'].indexOf(parts[0]) > -1; 44 | var method = (parts.length > 1) ? parts[0] : (isMethod ? parts[0] : ''); 45 | var path = (parts.length > 1) ? parts[1] : (isMethod ? '' : parts[0]); 46 | 47 | data.model.search = {httpMethod: method, path: path}; 48 | } 49 | 50 | $log.debug('sw:changed:searching', data.model.search); 51 | } 52 | 53 | function toggleGroups (open) { 54 | angular.forEach(data.model.groups, function (group) { 55 | group.open = open; 56 | }); 57 | } 58 | 59 | function showSecurity ($event) { 60 | security.showSecurity($event, data.swagger); 61 | } 62 | 63 | function showProxy ($event) { 64 | security.showProxy($event, data.swagger); 65 | } 66 | }); 67 | -------------------------------------------------------------------------------- /src/modules/toolbar/toolbar.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 5 | Loading… 6 |
7 |
8 | 15 | 16 | 20 | 21 | 23 | keyboard_arrow_down 24 | 25 | 26 | 28 | keyboard_arrow_up 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | 42 | security 43 | 44 | 47 | vpn_key 48 | 49 | 50 | 51 | more_vert 52 | 53 | 54 | 55 | 56 | 57 | keyboard_arrow_down 58 | Expand 59 | 60 | 61 | 62 | 63 | keyboard_arrow_up 64 | Collapse 65 | 66 | 67 | 68 | 69 | 70 | Switch view 71 | 72 | 73 | 74 | 75 | 76 | Descriptions 77 | 78 | 79 | 80 | 82 | security 83 | Proxy 84 | 85 | 86 | 87 | 89 | vpn_key 90 | Security 91 | 92 | 93 | 94 | 95 |
96 |
97 | -------------------------------------------------------------------------------- /src/plugins/README.md: -------------------------------------------------------------------------------- 1 | # Plugins 2 | 3 | ## [before-load](./before-load) 4 | 5 | _Before Swagger JSON or YAML loaded._ 6 | 7 | Arguments: **options** object for $http(options) 8 | 9 | * [yaml](./before-load/yaml.js) 10 | * [yaml simple test](../#?url=../test/fixtures/openapi-specification/yaml/petstore.yaml) 11 | * [yaml external references test](../#?url=../test/fixtures/openapi-specification/yaml/petstore-separate/spec/swagger.yaml) 12 | 13 | ## [before-parse](./before-parse) 14 | 15 | _Before swagger object parsed_ 16 | 17 | Arguments: **swagger** object 18 | 19 | * [external-references](./before-parse/external-references.js) 20 | * [json external references test](../#?url=../test/fixtures/openapi-specification/json/petstore-separate/spec/swagger.json) 21 | * [split](./before-parse/split.js) 22 | * [swagger-1-to-2](./before-parse/swagger-1-to-2.js) 23 | 24 | ## [parse](./parse) 25 | 26 | * [json simple test](../#?url=../test/fixtures/openapi-specification/json/uber.json) 27 | 28 | Arguments: **parserType**, **url**, **contentType**, **data**, **isTrustedSources**, **parseResult** 29 | 30 | Output: **parseResult** 31 | 32 | Promise resolve: **false** or **true** 33 | 34 | * [parser](./parse/parser.js) 35 | 36 | ## [before-display](./before-display) 37 | 38 | * [markdown](./before-display/markdown.js) 39 | * [operations](./before-display/operations.js) 40 | * [sort](./before-display/sort.js) 41 | 42 | ## [before-explorer](./before-explorer) 43 | 44 | * [auth-key](./before-explorer/auth-key.js) 45 | * [transform](./before-explorer/transform.js) 46 | 47 | ## [after-explorer](./after-explorer) 48 | 49 | * [xml-formatter](./after-explorer/xml-formatter.js) 50 | -------------------------------------------------------------------------------- /src/plugins/after-explorer/xml-formatter.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Orange angular-swagger-ui - v0.3.0 3 | * 4 | * (C) 2015 Orange, all right reserved 5 | * MIT Licensed 6 | */ 7 | 'use strict'; 8 | 9 | angular.module('sw.plugin.xmlFormater', ['sw.plugins']) 10 | .factory('xmlFormatter', function ($q, $log) { 11 | $log.debug('sw:plugin', 'xmlFormater'); 12 | 13 | return { 14 | execute: execute 15 | }; 16 | 17 | function execute (response) { 18 | $log.debug('sw:execute', 'xmlFormater'); 19 | 20 | var executed = false; 21 | var deferred = $q.defer(); 22 | var contentType = response.headers && response.headers()['content-type']; 23 | 24 | if (contentType && contentType.toLowerCase().indexOf('/xml') > 0) { 25 | response.data = formatXml(response.data); 26 | executed = true; 27 | } 28 | deferred.resolve(executed); 29 | return deferred.promise; 30 | } 31 | 32 | function formatXml (xml) { 33 | var formatted = ''; 34 | var reg = /(>)(<)(\/*)/g; 35 | var pad = 0; 36 | 37 | xml = xml.replace(reg, '$1\r\n$2$3'); 38 | angular.forEach(xml.split('\r\n'), function (node) { 39 | var indent = 0; 40 | var padding = ''; 41 | 42 | if (node.match(/.+<\/\w[^>]*>$/)) { 43 | indent = 0; 44 | } else if (node.match(/^<\/\w/)) { 45 | if (pad !== 0) { 46 | pad -= 1; 47 | } 48 | } else if (node.match(/^<\w[^>]*[^\/]>.*$/)) { 49 | indent = 1; 50 | } else { 51 | indent = 0; 52 | } 53 | 54 | for (var i = 0; i < pad; i++) { 55 | padding += ' '; 56 | } 57 | 58 | formatted += padding + node + '\r\n'; 59 | pad += indent; 60 | }); 61 | 62 | return formatted; 63 | } 64 | }) 65 | .run(function (plugins, xmlFormatter) { 66 | plugins.add(plugins.AFTER_EXPLORER_LOAD, xmlFormatter); 67 | }); 68 | -------------------------------------------------------------------------------- /src/plugins/before-display/markdown.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.markdown', ['sw.plugins']) 4 | .factory('markdown', function ($q, $log, $window) { 5 | $log.debug('sw:plugin', 'markdown'); 6 | 7 | var showdown = new $window.showdown.Converter({ 8 | simplifiedAutoLink: true, 9 | tables: true, 10 | ghCodeBlocks: true, 11 | tasklists: true 12 | }); 13 | 14 | return { 15 | execute: execute 16 | }; 17 | 18 | function execute (parseResult) { 19 | $log.debug('sw:execute', 'markdown'); 20 | 21 | var deferred = $q.defer(); 22 | 23 | // TODO: is there any other GFM field to be transformed? Find "GFM" in http://swagger.io/specification/ page 24 | 25 | if (parseResult.info && parseResult.info.description) { 26 | parseResult.info.description = markdown(parseResult.info.description.replace(/^
/i, '')); 27 | } 28 | 29 | angular.forEach(parseResult.securityDefinitions, function (sec) { 30 | var d = sec.description || ''; 31 | 32 | // Obvious descriptions 33 | if (sec.type === 'apiKey' && d.toLowerCase() === 'API Key Authentication'.toLowerCase()) { 34 | delete sec.description; 35 | } else if (sec.type === 'basic' && d.toLowerCase() === 'Basic HTTP Authentication'.toLowerCase()) { 36 | delete sec.description; 37 | } else if (sec.type === 'oauth2' && d.toLowerCase() === 'OAuth 2.0 Authentication'.toLowerCase()) { 38 | delete sec.description; 39 | } else { 40 | sec.description = markdown(sec.description); 41 | } 42 | }); 43 | 44 | angular.forEach(parseResult.resources, function (resource) { 45 | resource.description = markdown(resource.description); 46 | 47 | angular.forEach(resource.operations, function (operation) { 48 | operation.description = markdown(operation.description); 49 | 50 | // TODO: remove workaround? http://darosh.github.io/angular-swagger-ui-material/#?url=https:%2F%2Fapi.apis.guru%2Fspecs%2Fwinning.email%2F1.0.0%2Fswagger.json 51 | 52 | operation.summary = operation.summary ? operation.summary.replace(/(
)+$/, '') : operation.summary; 53 | 54 | angular.forEach(operation.responses, function (response) { 55 | response.description = markdown(response.description); 56 | }); 57 | }); 58 | }); 59 | 60 | deferred.resolve(); 61 | 62 | return deferred.promise; 63 | } 64 | 65 | function markdown (text) { 66 | return showdown.makeHtml(text || ''); 67 | } 68 | }) 69 | .run(function (plugins, markdown) { 70 | plugins.add(plugins.BEFORE_DISPLAY, markdown); 71 | }); 72 | -------------------------------------------------------------------------------- /src/plugins/before-display/operations.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.operations', ['sw.plugins']) 4 | // List ungrouped operations 5 | .factory('operations', function ($q) { 6 | return { 7 | execute: function (parseResult) { 8 | var deferred = $q.defer(); 9 | 10 | parseResult.info.operations = []; 11 | 12 | angular.forEach(parseResult.resources, function (resource) { 13 | angular.forEach(resource.operations, function (operation) { 14 | parseResult.info.operations.push(operation); 15 | }); 16 | 17 | // TODO: allow configuration of minimum auto expanded endpoints 18 | if (parseResult.resources.length <= 8) { 19 | resource.open = true; 20 | } 21 | }); 22 | 23 | parseResult.info.operations.sort(function (a, b) { 24 | return (a.path.toLowerCase().replace(/[^a-z]+/gi, '') + '-' + a.httpMethod) 25 | .localeCompare(b.path.toLowerCase().replace(/[^a-z]+/gi, '') + '-' + b.httpMethod); 26 | }); 27 | 28 | deferred.resolve(); 29 | 30 | return deferred.promise; 31 | } 32 | }; 33 | }) 34 | .run(function (plugins, operations) { 35 | plugins.add(plugins.BEFORE_DISPLAY, operations); 36 | }); 37 | -------------------------------------------------------------------------------- /src/plugins/before-display/sort.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.sort', ['sw.plugins']) 4 | .factory('sort', function ($q) { 5 | var order = { 6 | get: 1, 7 | head: 2, 8 | options: 3, 9 | post: 4, 10 | put: 5, 11 | patch: 6, 12 | delete: 7 13 | }; 14 | 15 | return { 16 | execute: function (parseResult) { 17 | var deferred = $q.defer(); 18 | 19 | angular.forEach(parseResult.resources, function (resource) { 20 | resource.operations.sort(function (a, b) { 21 | return (a.path.toLowerCase().replace(/[^a-z]+/gi, '') + '-' + (order[a.httpMethod] || 9)) 22 | .localeCompare(b.path.toLowerCase().replace(/[^a-z]+/gi, '') + '-' + (order[b.httpMethod] || 9)); 23 | }); 24 | }); 25 | 26 | deferred.resolve(true); 27 | 28 | return deferred.promise; 29 | } 30 | }; 31 | }) 32 | .run(function (plugins, sort) { 33 | plugins.add(plugins.BEFORE_DISPLAY, sort); 34 | }); 35 | -------------------------------------------------------------------------------- /src/plugins/before-explorer/auth.sample.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.auth', ['sw.plugins']) 4 | .factory('auth', function ($q/* , $window */) { 5 | return { 6 | execute: function (/* options */) { 7 | var deferred = $q.defer(); 8 | 9 | /* Add auth key to params 10 | 11 | options.params.auth_key = '...'; 12 | */ 13 | 14 | /* Basic HTTP Authentication 15 | 16 | var username = '...'; 17 | var password = '...'; 18 | var auth = $window.btoa(username + ':' + password); 19 | options.headers['Authorization'] = 'Basic ' + auth; 20 | */ 21 | 22 | deferred.resolve(); 23 | 24 | return deferred.promise; 25 | } 26 | }; 27 | }) 28 | .run(function (plugins, auth) { 29 | plugins.add(plugins.BEFORE_EXPLORER_LOAD, auth); 30 | }); 31 | -------------------------------------------------------------------------------- /src/plugins/before-explorer/transform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.transform', ['sw.plugins']) 4 | // Catch default transform invalid JSON parse 5 | .factory('transform', function ($q, $http) { 6 | return { 7 | execute: function (config) { 8 | var deferred = $q.defer(); 9 | 10 | config.transformResponse = function (data, headersGetter, status) { 11 | try { 12 | return $http.defaults.transformResponse[0](data, headersGetter, status); 13 | } catch (ing) { 14 | return data; 15 | } 16 | }; 17 | 18 | deferred.resolve(); 19 | 20 | return deferred.promise; 21 | } 22 | }; 23 | }) 24 | .run(function (plugins, transform) { 25 | plugins.add(plugins.BEFORE_EXPLORER_LOAD, transform); 26 | }); 27 | -------------------------------------------------------------------------------- /src/plugins/before-load/yaml.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.yaml', ['sw.plugins']) 4 | .factory('yaml', function ($q, $window) { 5 | return { 6 | execute: function (options) { 7 | var deferred = $q.defer(); 8 | 9 | options.transformResponse = function (data, headersGetter) { 10 | try { 11 | return angular.fromJson(data); 12 | } catch (ign) { 13 | try { 14 | var obj = $window.jsyaml.safeLoad(data); 15 | 16 | headersGetter()['content-type'] = 'application/json'; 17 | 18 | return obj; 19 | } catch (ign) { 20 | return data; 21 | } 22 | } 23 | }; 24 | 25 | deferred.resolve(); 26 | 27 | return deferred.promise; 28 | } 29 | }; 30 | }) 31 | .run(function (plugins, yaml) { 32 | plugins.add(plugins.BEFORE_LOAD, yaml); 33 | }); 34 | -------------------------------------------------------------------------------- /src/plugins/before-parse/base.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.base', ['sw.plugins']) 4 | .factory('base', function ($q, $log) { 5 | return { 6 | execute: execute 7 | }; 8 | 9 | function execute (url, swagger) { 10 | $log.debug('sw:plugin', 'base'); 11 | 12 | var deferred = $q.defer(); 13 | 14 | if (swagger && swagger.paths) { 15 | var parts = {}; 16 | var min = Number.MAX_VALUE; 17 | 18 | angular.forEach(swagger.paths, function (path, key) { 19 | parts[key] = key.split('/'); 20 | 21 | if (key[0] === '/') { 22 | parts[key].shift(); 23 | } 24 | 25 | min = Math.min(min, parts[key].length); 26 | }); 27 | 28 | var paths = Object.keys(swagger.paths); 29 | var sames = []; 30 | 31 | for (var i = 0; i < min; i++) { 32 | var first = parts[paths[0]][i]; 33 | 34 | if (/\{.+\}/.test(first) || (parts[paths[0]].length <= 1)) { 35 | break; 36 | } 37 | 38 | var same = true; 39 | 40 | for (var j = 0; j < paths.length; j++) { 41 | if (parts[paths[j]][i] !== first) { 42 | same = false; 43 | break; 44 | } 45 | } 46 | 47 | if (same) { 48 | sames.push(first); 49 | } else { 50 | break; 51 | } 52 | } 53 | 54 | if (sames.length > 0) { 55 | var extracted = sames.join('/'); 56 | 57 | $log.debug('sw:plugin:base:extracted', extracted); 58 | 59 | swagger.basePath = (swagger.basePath || '/'); 60 | swagger.basePath = swagger.basePath + 61 | ((swagger.basePath[swagger.basePath.length - 1] === '/') ? '' : '/') + extracted; 62 | 63 | angular.forEach(paths, function (path) { 64 | swagger.paths['/' + parts[path].slice(sames.length).join('/')] = swagger.paths[path]; 65 | delete swagger.paths[path]; 66 | }); 67 | } 68 | } 69 | 70 | deferred.resolve(true); 71 | 72 | return deferred.promise; 73 | } 74 | }) 75 | .run(function (plugins, base) { 76 | plugins.add(plugins.BEFORE_PARSE, base); 77 | }); 78 | -------------------------------------------------------------------------------- /src/plugins/before-parse/external-references.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Orange angular-swagger-ui - v0.3.0 3 | * 4 | * (C) 2015 Orange, all right reserved 5 | * MIT Licensed 6 | */ 7 | 'use strict'; 8 | 9 | angular.module('sw.plugin.externalReferences', ['sw.plugins']) 10 | .factory('externalReferences', function ($http, $q, $window, plugins) { 11 | var deferred; 12 | 13 | return { 14 | /** 15 | * Module entry point 16 | */ 17 | execute: function (url, swagger) { 18 | deferred = $q.defer(); 19 | loadExternalReferences(url, swagger); 20 | 21 | return deferred.promise; 22 | } 23 | }; 24 | 25 | function onError (error) { 26 | deferred.reject(error); 27 | } 28 | 29 | /** 30 | * Load external definition 31 | */ 32 | function getUrl (externalUrl, callback) { 33 | var options = { 34 | method: 'GET', 35 | url: externalUrl 36 | }; 37 | 38 | plugins 39 | .execute(plugins.BEFORE_LOAD, options) 40 | .then(function () { 41 | $http(options).then(callback, onError); 42 | }) 43 | .catch(onError); 44 | } 45 | 46 | /** 47 | * Generate external URL 48 | */ 49 | function getExternalUrl (baseUrl, $ref) { 50 | if (!angular.isString($ref)) { 51 | return ''; 52 | } 53 | 54 | var parts = $ref.split('#/'); 55 | var externalUrl = parts[0]; 56 | 57 | if (externalUrl && (externalUrl.indexOf('http') !== 0)) { 58 | // relative url 59 | if (externalUrl.indexOf('/') === 0) { 60 | var swaggerUrlParts = $window.URL.parse(baseUrl); 61 | externalUrl = swaggerUrlParts.protocol + '//' + swaggerUrlParts.host + externalUrl; 62 | } else { 63 | var pos = baseUrl.lastIndexOf('/'); 64 | externalUrl = baseUrl.substring(0, pos) + '/' + externalUrl; 65 | } 66 | } 67 | 68 | return externalUrl; 69 | } 70 | 71 | /** 72 | * Find and resolve external definitions 73 | */ 74 | function loadExternalReferences (baseUrl, swagger) { 75 | var loading = 0; 76 | 77 | function load (url, obj) { 78 | loading++; 79 | 80 | getUrl(url, function (json) { 81 | loading--; 82 | 83 | var subPath = obj.$ref.split('#/')[1]; 84 | var subJson = subPath ? json.data[subPath] : json.data; 85 | 86 | angular.extend(obj, subJson); 87 | 88 | delete obj.$ref; 89 | 90 | if (loading === 0) { 91 | deferred.resolve(true); 92 | } 93 | }); 94 | } 95 | 96 | function iterate (obj) { 97 | angular.forEach(obj, function (v, k) { 98 | if (k === '$ref') { 99 | var externalUrl = getExternalUrl(baseUrl, v); 100 | 101 | if (externalUrl) { 102 | load(externalUrl, obj); 103 | } 104 | } else if (angular.isObject(v) || angular.isArray(v)) { 105 | iterate(v); 106 | } 107 | }); 108 | } 109 | 110 | iterate(swagger); 111 | 112 | if (!loading) { 113 | deferred.resolve(false); 114 | } 115 | } 116 | }) 117 | .run(function (plugins, externalReferences) { 118 | plugins.add(plugins.BEFORE_PARSE, externalReferences); 119 | }); 120 | -------------------------------------------------------------------------------- /src/plugins/before-parse/split.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.plugin.split', ['sw.plugins']) 4 | .factory('split', function ($q) { 5 | return { 6 | execute: execute 7 | }; 8 | 9 | function execute (url, swagger) { 10 | var deferred = $q.defer(); 11 | 12 | if (swagger && swagger.swagger && !swagger.tags) { 13 | var tags = {}; 14 | 15 | angular.forEach(swagger.paths, function (path, key) { 16 | var t = key.replace(/^\/?([^\/]+).*$/g, '$1'); 17 | tags[t] = true; 18 | 19 | angular.forEach(path, function (method) { 20 | if (!method.tags || !method.tags.length) { 21 | method.tags = [t]; 22 | } 23 | }); 24 | }); 25 | 26 | swagger.tags = []; 27 | 28 | Object.keys(tags).forEach(function (tag) { 29 | swagger.tags.push({name: tag}); 30 | }); 31 | } 32 | 33 | deferred.resolve(true); 34 | 35 | return deferred.promise; 36 | } 37 | }) 38 | .run(function (plugins, split) { 39 | plugins.add(plugins.BEFORE_PARSE, split); 40 | }); 41 | -------------------------------------------------------------------------------- /src/plugins/plugins.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Orange angular-swagger-ui - v0.3.0 3 | * 4 | * (C) 2015 Orange, all right reserved 5 | * MIT Licensed 6 | */ 7 | 'use strict'; 8 | 9 | angular 10 | .module('sw.plugins', []).factory('plugins', function ($q) { 11 | var modules = {}; 12 | 13 | return { 14 | BEFORE_LOAD: 'BEFORE_LOAD', 15 | BEFORE_PARSE: 'BEFORE_PARSE', 16 | PARSE: 'PARSE', 17 | BEFORE_DISPLAY: 'BEFORE_DISPLAY', 18 | BEFORE_EXPLORER_LOAD: 'BEFORE_EXPLORER_LOAD', 19 | AFTER_EXPLORER_LOAD: 'AFTER_EXPLORER_LOAD', 20 | 21 | /** 22 | * Adds a new module to swagger-ui 23 | */ 24 | add: function (phase, module) { 25 | if (!modules[phase]) { 26 | modules[phase] = []; 27 | } 28 | if (modules[phase].indexOf(module) < 0) { 29 | modules[phase].push(module); 30 | } 31 | }, 32 | /** 33 | * Executes modules' phase 34 | */ 35 | execute: function () { 36 | var args = Array.prototype.slice.call(arguments); 37 | var phase = args.splice(0, 1); 38 | var deferred = $q.defer(); 39 | var phaseModules = modules[phase] || []; 40 | 41 | executeAll(deferred, [].concat(phaseModules), args); 42 | return deferred.promise; 43 | } 44 | }; 45 | 46 | /** 47 | * Runs modules' "execute" function one by one 48 | */ 49 | function executeAll (deferred, phaseModules, args, phaseExecuted) { 50 | var module = phaseModules.shift(); 51 | if (module) { 52 | module 53 | .execute.apply(module, args) 54 | .then(function (executed) { 55 | phaseExecuted = phaseExecuted || executed; 56 | executeAll(deferred, phaseModules, args, phaseExecuted); 57 | }) 58 | .catch(deferred.reject); 59 | } else { 60 | deferred.resolve(phaseExecuted); 61 | } 62 | } 63 | }); 64 | -------------------------------------------------------------------------------- /src/sw.ui.md/dialog.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md') 4 | .factory('dialog', function ($mdDialog) { 5 | return { 6 | show: show 7 | }; 8 | 9 | function show ($event, locals, type) { 10 | return $mdDialog.show({ 11 | templateUrl: 'views/' + (type || 'info') + '.dialog.html', 12 | clickOutsideToClose: true, 13 | targetEvent: $event, 14 | controller: DialogCtrl, 15 | locals: {vm: locals} 16 | }); 17 | } 18 | 19 | function DialogCtrl ($scope, $mdDialog, vm) { 20 | $scope.vm = vm; 21 | $scope.vm.opened = true; 22 | $scope.closeDialog = function () { 23 | $scope.vm.opened = false; 24 | $mdDialog.hide(); 25 | }; 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /src/sw.ui.md/display.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md') 4 | .factory('display', function ($window) { 5 | return { 6 | meta: meta 7 | }; 8 | 9 | function meta (i, url, validatorUrl, download) { 10 | i.contact = i.contact || {}; 11 | i.license = i.license || {}; 12 | 13 | var validatorDebug = (validatorUrl && url) ? (validatorUrl + '/debug?url=' + url) : null; 14 | var validatorBadge = validatorUrl + '?url=' + url; 15 | 16 | return [ 17 | ['Contact', 'person', (i.contact.name && !i.contact.email) ? i.contact.name : null, null], 18 | ['Email', 'email', i.contact.email ? (i.contact.name || i.contact.email) : null, 'mailto:' + i.contact.email + '?subject=' + i.title], 19 | ['License', 'vpn_key', i.license.name || i.license.url, i.license.url], 20 | ['Terms of service', 'assignment', i.termsOfService, i.termsOfService], 21 | ['Client registration', 'assignment_ind', i['x-apiClientRegistration'] && i['x-apiClientRegistration'].url, i['x-apiClientRegistration'] && i['x-apiClientRegistration'].url], 22 | ['Documentation', 'help_outline', i.externalDocs && (i.externalDocs.description || i.externalDocs.url), i.externalDocs && i.externalDocs.url], 23 | ['Host', 'home', i.scheme + '://' + i.host, i.scheme + '://' + i.host], 24 | ['Base URL', 'link', i.basePath, (i.scheme ? (i.scheme + '://') : '') + i.host + i.basePath], 25 | ['API version', 'developer_board', i.version, null], 26 | ['JSON', 'file_download', 'swagger.json', '#', download], 27 | ['YAML', 'file_download', $window.jsyaml ? 'swagger.yaml' : null, '#', download], 28 | ['Origin', 'cloud_download', i['x-origin'] && i['x-origin'].url, i['x-origin'] && i['x-origin'].url], 29 | [null, 'code', validatorDebug, validatorBadge] 30 | ]; 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /src/sw.ui.md/http-data.template: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // noinspection HtmlDeprecatedTag 4 | angular.module('sw.ui.md') 5 | .value('httpData', { 6 | method: {}, 7 | status: {}, 8 | header: {} 9 | }); 10 | -------------------------------------------------------------------------------- /src/sw.ui.md/style.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md') 4 | .factory('style', function (theme, httpData) { 5 | return { 6 | header: header 7 | }; 8 | 9 | function header (title) { 10 | var i = httpData.header[title.toLowerCase()]; 11 | 12 | if (i) { 13 | return theme[i[1]] || theme.undefined; 14 | } else { 15 | return null; 16 | } 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /src/sw.ui.md/sw.ui.md.module.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md', 4 | [ 5 | 'ngMaterial', 6 | 'ngSanitize', 7 | 'sw.ui', 8 | 'sw.ui.directives' 9 | ]); 10 | -------------------------------------------------------------------------------- /src/sw.ui.md/syntax.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Orange angular-swagger-ui - v0.3.0 3 | * 4 | * (C) 2015 Orange, all right reserved 5 | * MIT Licensed 6 | */ 7 | 'use strict'; 8 | 9 | angular.module('sw.ui.md') 10 | .factory('syntax', function (theme) { 11 | var prefix = 'md-button '; 12 | 13 | return { 14 | json: json 15 | }; 16 | 17 | // from http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript 18 | function json (json) { 19 | json = json.replace(/&/g, '&').replace(//g, '>'); 20 | 21 | return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) { 22 | var cls = prefix + theme.number; 23 | 24 | if (/^"/.test(match)) { 25 | if (/:$/.test(match)) { 26 | cls = prefix + theme.key; 27 | } else { 28 | cls = prefix + theme.string; 29 | } 30 | } else if (/true|false/.test(match)) { 31 | cls = prefix + theme.boolean; 32 | } else if (/null/.test(match)) { 33 | cls = prefix + theme.null; 34 | } 35 | 36 | return '' + match + ''; 37 | }); 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /src/sw.ui.md/theme.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md') 4 | .factory('theme', function () { 5 | var defaults = { 6 | get: 'md-primary', 7 | head: 'md-primary md-hue-2', 8 | options: 'md-primary md-hue-3', 9 | post: 'md-accent', 10 | put: 'md-accent md-hue-2', 11 | patch: 'md-accent md-hue-2', 12 | delete: 'md-warn', 13 | 1: 'md-accent', 14 | 2: 'md-primary', 15 | 3: 'md-accent md-hue-2', 16 | 4: 'md-warn', 17 | 5: 'md-warn', 18 | 7: 'md-warn', 19 | standard: 'md-accent', 20 | obsoleted: 'md-warn', 21 | undefined: 'md-accent', 22 | key: '', 23 | string: 'md-primary', 24 | number: 'md-warn', 25 | boolean: 'md-accent md-hue-3', 26 | null: 'md-accent md-hue-2' 27 | }; 28 | 29 | var self = { 30 | $configure: configure 31 | }; 32 | 33 | angular.extend(self, defaults); 34 | 35 | return self; 36 | 37 | function configure (theme) { 38 | angular.extend(self, defaults); 39 | angular.extend(self, theme || {}); 40 | 41 | return self; 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /src/sw.ui.md/tools.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md') 4 | .factory('tools', function ($window, data) { 5 | return { 6 | openFile: openFile 7 | }; 8 | 9 | function openFile ($event, isSwagger) { 10 | var text; 11 | var type; 12 | 13 | if (isSwagger) { 14 | // TODO: fromJson is lazy fix for https://github.com/crucialfelix/supercolliderjs/issues/17 15 | var json = angular.toJson(data.swagger, true); 16 | 17 | text = (isSwagger === 'swagger.json') 18 | ? json : $window.jsyaml.safeDump(angular.fromJson(json)); 19 | type = (isSwagger === 'swagger.json') ? 'application/json' : 'text/yaml'; 20 | } else { 21 | text = data.model.sop.explorerResult.body; 22 | type = data.model.sop.explorerResult.headers('content-type') || 'text/plain'; 23 | } 24 | 25 | // noinspection JSUnresolvedFunction 26 | var out = new $window.Blob([text], {type: type}); 27 | 28 | // noinspection JSUnresolvedFunction 29 | $event.target.href = $window.URL.createObjectURL(out); 30 | } 31 | }); 32 | -------------------------------------------------------------------------------- /src/sw.ui.md/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui.md') 4 | .factory('utils', function (dialog, theme, httpData) { 5 | return { 6 | method: method, 7 | status: status, 8 | header: header, 9 | statusInfo: statusInfo 10 | }; 11 | 12 | function method (method, $event) { 13 | var i = httpData.method[method]; 14 | 15 | dialog.show($event, { 16 | title: method.toUpperCase(), 17 | subtitle: 'HTTP Method', 18 | header: null, 19 | description: i[0], 20 | link: i[2], 21 | section: rfc(i[1]), 22 | style: theme[method], 23 | meta: [i[3], i[4], i[5]] 24 | }); 25 | } 26 | 27 | function status (code, $event) { 28 | var i = statusInfo(code); 29 | 30 | dialog.show($event, { 31 | title: code, 32 | subtitle: 'HTTP Status', 33 | header: i[0], 34 | description: i[1], 35 | link: i[3], 36 | section: rfc(i[2]), 37 | style: theme[code[0]] || theme[7], 38 | meta: null 39 | }); 40 | } 41 | 42 | function header (title, $event) { 43 | var i = httpData.header[title.toLowerCase()] || [title, 'Unknown header.', '', null]; 44 | 45 | dialog.show($event, { 46 | title: i[0], 47 | subtitle: 'HTTP Header', 48 | header: null, 49 | description: i[1], 50 | link: i[3], 51 | section: rfc(i[2]), 52 | style: theme[i[1]] || theme.undefined, 53 | meta: null 54 | }); 55 | } 56 | 57 | function rfc (section) { 58 | return section.replace(/(RFC)(.*)(#)(.*)/i, '$1 $2 – $4'); 59 | } 60 | 61 | function statusInfo (code) { 62 | return httpData.status[code] || httpData.status[code[0] + 'xx'] || 63 | ['**Undefined**', 'no spec found.', '', null]; 64 | } 65 | }); 66 | -------------------------------------------------------------------------------- /src/sw.ui/data.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('sw.ui') 4 | .factory('data', function ($log, $rootScope, $http, plugins) { 5 | var self = { 6 | options: { 7 | url: null, 8 | validatorUrl: null, 9 | parser: 'auto', 10 | trustedSources: false, 11 | proxy: null, 12 | errorHandler: null 13 | }, 14 | ui: { 15 | grouped: true, 16 | descriptions: false, 17 | explorer: true, 18 | sidenavOpen: false, 19 | sidenavLocked: false 20 | }, 21 | model: { 22 | info: null, 23 | groups: null, 24 | operations: null, 25 | form: null, 26 | hasSecurity: false, 27 | securityDefinitions: null, 28 | search: {}, 29 | sop: null 30 | }, 31 | swagger: null, 32 | loading: false, 33 | setUrl: setUrl 34 | }; 35 | 36 | function reset () { 37 | self.swagger = null; 38 | 39 | self.model = { 40 | info: null, 41 | groups: null, 42 | form: null, 43 | security: null, 44 | securityDefinitions: null 45 | }; 46 | 47 | $log.debug('sw:reset'); 48 | $rootScope.$broadcast('sw:changed'); 49 | } 50 | 51 | function setUrl (url) { 52 | if (self.options.url === url) { 53 | return; 54 | } 55 | 56 | $log.debug('sw:url', url); 57 | 58 | reset(); 59 | 60 | self.options.url = url; 61 | 62 | if (!url) { 63 | return; 64 | } 65 | 66 | self.loading = true; 67 | 68 | load(url, function (response) { 69 | if (response.config.url !== self.options.url) { 70 | return; 71 | } 72 | 73 | self.swagger = response.data; 74 | plugins 75 | .execute(plugins.BEFORE_PARSE, url, self.swagger) 76 | .then(function () { 77 | var type = (response.headers()['content-type'] || 'application/json').split(';')[0]; 78 | loaded(url, type); 79 | self.loading = false; 80 | }) 81 | .catch(onError); 82 | }, onError); 83 | } 84 | 85 | function load (url, callback, onError) { 86 | var options = { 87 | method: 'GET', 88 | url: url 89 | }; 90 | 91 | plugins 92 | .execute(plugins.BEFORE_LOAD, options) 93 | .then(function () { 94 | $http(options).then(callback, onError); 95 | }) 96 | .catch(onError); 97 | } 98 | 99 | function loaded (url, type) { 100 | var parseResult = {}; 101 | var swaggerCopy = angular.copy(self.swagger); 102 | 103 | $log.debug('sw:loaded'); 104 | 105 | plugins 106 | .execute( 107 | plugins.PARSE, 108 | self.options.parser, 109 | url, 110 | type, 111 | swaggerCopy, 112 | self.options.trustedSources, 113 | parseResult) 114 | .then(function (executed) { 115 | if (executed) { 116 | parsed(parseResult); 117 | } else { 118 | onError({ 119 | message: 'no parser found' 120 | }); 121 | } 122 | }) 123 | .catch(onError); 124 | } 125 | 126 | function parsed (parseResult) { 127 | plugins 128 | .execute(plugins.BEFORE_DISPLAY, parseResult) 129 | .then(function () { 130 | self.model.info = parseResult.info; 131 | self.model.form = parseResult.form; 132 | self.model.groups = parseResult.resources; 133 | self.model.operations = parseResult.info.operations; 134 | self.model.securityDefinitions = parseResult.securityDefinitions; 135 | self.model.hasSecurity = hasSecurity(self.swagger); 136 | 137 | $log.debug('sw:parsed'); 138 | $rootScope.$broadcast('sw:changed'); 139 | }) 140 | .catch(onError); 141 | } 142 | 143 | function hasSecurity (swagger) { 144 | return Object.keys(swagger.securityDefinitions || {}).length; 145 | } 146 | 147 | function onError (error) { 148 | self.loading = false; 149 | 150 | if (angular.isFunction(self.options.errorHandler)) { 151 | self.options.errorHandler(error); 152 | } 153 | } 154 | 155 | return self; 156 | }) 157 | ; 158 | -------------------------------------------------------------------------------- /src/sw.ui/format.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Orange angular-swagger-ui - v0.3.0 3 | * 4 | * (C) 2015 Orange, all right reserved 5 | * MIT Licensed 6 | */ 7 | 'use strict'; 8 | 9 | angular.module('sw.ui') 10 | .factory('format', function () { 11 | return { 12 | fullUrl: fullUrl 13 | }; 14 | 15 | function fullUrl (response) { 16 | var query = ''; 17 | var config = response.config || {}; 18 | 19 | if (config.params) { 20 | var parts = []; 21 | 22 | angular.forEach(config.params, function (v, k) { 23 | parts.push(k + '=' + encodeURIComponent(v)); 24 | }); 25 | 26 | if (parts.length > 0) { 27 | query = '?' + parts.join('&'); 28 | } 29 | } 30 | 31 | return config.url + query; 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /src/sw.ui/sw.ui.module.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Orange angular-swagger-ui - v0.3.0 3 | * 4 | * (C) 2015 Orange, all right reserved 5 | * MIT Licensed 6 | */ 7 | 'use strict'; 8 | 9 | angular.module('sw.ui', [ 10 | 'sw.plugins' 11 | ]); 12 | -------------------------------------------------------------------------------- /src/views/info.dialog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 | 6 | 7 |
8 |
9 |
10 |
Safe 11 | 12 |
13 |
Idempotent 14 | 15 |
16 |
Cacheable 17 | 18 |
19 |
20 | 21 | 22 | 23 |

24 |

25 |
26 | 27 | 28 | 29 | 31 | Close 32 | 33 |
34 | -------------------------------------------------------------------------------- /src/views/proxy.dialog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

Proxy

5 |
6 |
7 | 8 |

warning Use only proxies you trust!

9 |
10 |
11 | 12 | 13 | 14 | 15 |
16 |
17 |
18 | 19 | Close 20 | 21 |
22 | -------------------------------------------------------------------------------- /src/views/security.dialog.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 |
6 |

Security

7 |
8 |
9 | 10 | 11 |
12 |
13 |

API Key 14 | Authentication

15 |
16 |

18 | 19 | 20 | 21 | 22 |
23 |

Basic HTTP 24 | Authentication

25 |
26 |

28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 |

OAuth 38 | 2.0 Authentication 39 | 40 | 41 |

42 |

44 |
45 | 46 | 47 | 48 | 49 |
50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
60 |
61 | 64 | : 66 | 67 |
68 |
69 | Authenticate 72 | 73 |
74 |
75 |
76 |
77 |
78 |
79 | 80 | Close 81 | 82 |
83 | -------------------------------------------------------------------------------- /test/e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [ 5 | 2, 6 | "always" 7 | ], 8 | "indent": [ 9 | 2, 10 | 4, 11 | { 12 | "SwitchCase": 1 13 | } 14 | ] 15 | }, 16 | "globals": { 17 | "browser": true, 18 | "protractor": true, 19 | "beforeEach": true, 20 | "describe": true, 21 | "it": true, 22 | "expect": true, 23 | "element": true, 24 | "by": true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/e2e/back.spec.js: -------------------------------------------------------------------------------- 1 | var HUB = 'http://localhost:8888/angular-swagger-ui-material/demo/hub/'; 2 | 3 | describe('all links on hub page', function () { 4 | it('should load', function () { 5 | browser.driver.manage().window().maximize(); 6 | 7 | // Open hub 8 | browser.get(HUB); 9 | 10 | // Sort by last updated 11 | var el = element(by.css('md-menu')); 12 | browser.driver.wait(protractor.until.elementIsVisible(el)); 13 | el.click(); 14 | element(by.buttonText('Last updated')).click(); 15 | 16 | // Count specs 17 | var list = element.all(by.repeater('api in vm.apis track by ::api.key')); 18 | var count = list.count(); 19 | expect(count).toBeGreaterThan(0); 20 | 21 | count.then(function (count) { 22 | for (var i = 0; i < count; i++) { 23 | // Open ui 24 | list.get(i).element(by.css('md-toolbar')).click(); 25 | 26 | // Count groups 27 | var apis = element.all(by.repeater('api in resources track by $index')); 28 | expect(apis.count()).toBeGreaterThan(0); 29 | 30 | // Click title edit 31 | element(by.binding('displayTitle')).click(); 32 | 33 | // Click search edit 34 | element(by.buttonText('search')).click(); 35 | 36 | // Close search edit 37 | element(by.buttonText('close')).click(); 38 | 39 | // Click expland all 40 | element.all(by.buttonText('keyboard_arrow_down')).get(0).click(); 41 | 42 | // Click collapse all 43 | element.all(by.buttonText('keyboard_arrow_up')).get(0).click(); 44 | 45 | // Click switch view 46 | element(by.buttonText('view_comfy')).click(); 47 | 48 | // Click show description 49 | element(by.buttonText('speaker_notes')).click(); 50 | 51 | // Open proxy dialog 52 | element(by.buttonText('security')).click(); 53 | 54 | // Close proxy dialog 55 | element(by.css('md-dialog button')).click(); 56 | 57 | element.all(by.buttonText('vpn_key')).count().then(function (count) { 58 | if (count) { 59 | // Open security dialog 60 | element(by.buttonText('vpn_key')).click(); 61 | 62 | // Close security dialog 63 | element(by.css('md-dialog button')).click(); 64 | } 65 | 66 | // Click first operations 67 | element.all(by.css('button.sum-http-method')).get(0).click(); 68 | 69 | // Pin sidenav locked open 70 | element(by.buttonText('chevron_left')).click(); 71 | 72 | // Scripts tab 73 | element.all(by.css('md-tab-item')).get(1).click(); 74 | 75 | // Open HTTP method info dialog 76 | element.all(by.css('md-sidenav button.sum-http-method')).get(0).click(); 77 | 78 | // Close dialog 79 | element(by.css('md-dialog button')).click(); 80 | 81 | element.all(by.css('.md-fab:not([disabled])')).count().then(function (count) { 82 | if (count) { 83 | // Submit 84 | element(by.css('.md-fab:not([disabled])')).click(); 85 | 86 | browser.driver.wait(protractor.until.elementIsVisible(element(by.css('#tab-content-2')))); 87 | } 88 | 89 | // Go back to hub 90 | browser.navigate().back(); 91 | }); 92 | }); 93 | } 94 | }); 95 | }, 1000 * 60 * 60); 96 | }); 97 | -------------------------------------------------------------------------------- /test/e2e/hub.spec.js: -------------------------------------------------------------------------------- 1 | var hub = new (require('./lib/hub'))(); 2 | 3 | beforeEach(function () { 4 | console.log(browser); 5 | browser.driver.manage().window().maximize(); 6 | hub.get(); 7 | }); 8 | 9 | describe('hub page', function () { 10 | it('should display list', function () { 11 | expect(hub.listCount()).toBeGreaterThan(0); 12 | }); 13 | 14 | it('should filter list', function () { 15 | hub.exampleNotGoogle(); 16 | }); 17 | 18 | it('should sort list', function () { 19 | hub.sortByLastUpdate(); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/e2e/lib/hub.js: -------------------------------------------------------------------------------- 1 | var HUB = 'http://localhost:8888/angular-swagger-ui-material/demo/hub/'; 2 | 3 | module.exports = function Hub () { 4 | var menu = element(by.css('md-menu')); 5 | var menuLastUpdate = element(by.buttonText('Last updated')); 6 | var list = element.all(by.repeater('api in vm.apisDelayed track by api.key')); 7 | var exampleNotGoogle = element(by.linkText('!google')); 8 | 9 | this.filters = element(by.buttonText('filter_list')); 10 | this.close = element(by.css('md-sidenav md-toolbar button')); 11 | 12 | this.get = function () { 13 | browser.get(HUB); 14 | browser.driver.wait(protractor.until.elementIsVisible(menu)); 15 | }; 16 | 17 | this.sortByLastUpdate = function () { 18 | menu.click(); 19 | menuLastUpdate.click(); 20 | }; 21 | 22 | this.exampleNotGoogle = function () { 23 | exampleNotGoogle.click(); 24 | }; 25 | 26 | this.list = list; 27 | 28 | this.listCount = function () { 29 | return list.count(); 30 | }; 31 | 32 | this.listItemToolbar = function (index) { 33 | return list.get(index).element(by.css('md-toolbar')); 34 | }; 35 | }; 36 | -------------------------------------------------------------------------------- /test/e2e/lib/ui.js: -------------------------------------------------------------------------------- 1 | var UI = 'http://localhost:8888/angular-swagger-ui-material/demo/'; 2 | 3 | module.exports = function Ui () { 4 | this.menu = element(by.css('md-menu')); 5 | this.apis = element.all(by.repeater('api in resources track by $index')); 6 | this.displayTitle = element(by.binding('displayTitle')); 7 | this.search = element(by.buttonText('search')); 8 | this.closeSearch = element(by.buttonText('close')); 9 | this.expand = element.all(by.buttonText('keyboard_arrow_down')).get(0); 10 | this.collapse = element.all(by.buttonText('keyboard_arrow_up')).get(0); 11 | this.view = element(by.buttonText('view_comfy')); 12 | this.description = element(by.buttonText('speaker_notes')); 13 | this.proxy = element(by.buttonText('security')); 14 | this.closeDialog = element(by.css('md-dialog-actions button[ng-click="closeDialog()"]')); 15 | this.security = element.all(by.buttonText('vpn_key')); 16 | this.operations = element.all(by.css('button.sum-http-method')); 17 | this.pin = element(by.buttonText('chevron_left')); 18 | this.tab = element.all(by.css('md-tab-item')); 19 | this.method = element.all(by.css('md-sidenav button.sum-http-method')).get(0); 20 | this.play = element.all(by.css('.md-fab:not([disabled])')); 21 | this.status = element.all(by.css('.sum-http-code:not([disabled])')); 22 | this.searchInput = element(by.css('toolbar-search input')); 23 | this.resultStatus = element.all(by.css('#tab-content-2 button.sum-http-code:not([disabled])')); 24 | this.resultHeader = element.all(by.css('#tab-content-2 button.sum-http-header:not([disabled])')); 25 | this.model = element.all(by.binding('vm.sop.responseClass.display ? \'Model\' : \'Example\'')); 26 | this.set = element.all(by.linkText('Set')); 27 | this.dialogTabs = element.all(by.css('md-dialog md-tab-item')); 28 | 29 | this.get = function () { 30 | browser.get(UI); 31 | }; 32 | 33 | this.waitForResult = function() { 34 | browser.driver.wait(protractor.until.elementIsVisible(element(by.css('#tab-content-2')))); 35 | }; 36 | 37 | this.waitForScripts = function() { 38 | browser.driver.wait(protractor.until.elementIsVisible(element(by.css('#tab-content-1')))); 39 | }; 40 | }; 41 | -------------------------------------------------------------------------------- /test/fixtures/auth/auth.json: -------------------------------------------------------------------------------- 1 | { 2 | "www.googleapis.com": { 3 | "oauth2": { 4 | "clientId": "66318893772-g5m4f8c44r8rvs3aig9n5f9pr84jd65s.apps.googleusercontent.com" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/auth/auth.json.sample: -------------------------------------------------------------------------------- 1 | { 2 | "www.googleapis.com": { 3 | "oauth2": { 4 | "clientId": "..." 5 | }, 6 | "apiKey": "..." 7 | }, 8 | "api.github.com": { 9 | "oauth2": { 10 | "clientId": "...", 11 | "clientSecret": "..." 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/fixtures/examples/swagger-1.2.json: -------------------------------------------------------------------------------- 1 | { 2 | "apiVersion": "1.0.0", 3 | "swaggerVersion": "1.2", 4 | "basePath": "http://petstore.swagger.wordnik.com/api", 5 | "resourcePath": "/store", 6 | "produces": [ 7 | "application/json" 8 | ], 9 | "authorizations": {}, 10 | "apis": [ 11 | { 12 | "path": "/store/order/{orderId}", 13 | "operations": [ 14 | { 15 | "method": "GET", 16 | "summary": "Find purchase order by ID", 17 | "notes": "For valid response try integer IDs with value <= 5. Anything above 5 or nonintegers will generate API errors", 18 | "type": "Order", 19 | "nickname": "getOrderById", 20 | "authorizations": {}, 21 | "parameters": [ 22 | { 23 | "name": "orderId", 24 | "description": "ID of pet that needs to be fetched", 25 | "required": true, 26 | "type": "string", 27 | "paramType": "path" 28 | } 29 | ], 30 | "responseMessages": [ 31 | { 32 | "code": 400, 33 | "message": "Invalid ID supplied" 34 | }, 35 | { 36 | "code": 404, 37 | "message": "Order not found" 38 | } 39 | ] 40 | }, 41 | { 42 | "method": "DELETE", 43 | "summary": "Delete purchase order by ID", 44 | "notes": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", 45 | "type": "void", 46 | "nickname": "deleteOrder", 47 | "authorizations": { 48 | "oauth2": [ 49 | { 50 | "scope": "test:anything", 51 | "description": "anything" 52 | } 53 | ] 54 | }, 55 | "parameters": [ 56 | { 57 | "name": "orderId", 58 | "description": "ID of the order that needs to be deleted", 59 | "required": true, 60 | "type": "string", 61 | "paramType": "path" 62 | } 63 | ], 64 | "responseMessages": [ 65 | { 66 | "code": 400, 67 | "message": "Invalid ID supplied" 68 | }, 69 | { 70 | "code": 404, 71 | "message": "Order not found" 72 | } 73 | ] 74 | } 75 | ] 76 | }, 77 | { 78 | "path": "/store/order", 79 | "operations": [ 80 | { 81 | "method": "POST", 82 | "summary": "Place an order for a pet", 83 | "notes": "", 84 | "type": "void", 85 | "nickname": "placeOrder", 86 | "authorizations": { 87 | "oauth2": [ 88 | { 89 | "scope": "test:anything", 90 | "description": "anything" 91 | } 92 | ] 93 | }, 94 | "parameters": [ 95 | { 96 | "name": "body", 97 | "description": "order placed for purchasing the pet", 98 | "required": true, 99 | "type": "Order", 100 | "paramType": "body" 101 | } 102 | ], 103 | "responseMessages": [ 104 | { 105 | "code": 400, 106 | "message": "Invalid order" 107 | } 108 | ] 109 | } 110 | ] 111 | } 112 | ], 113 | "models": { 114 | "Order": { 115 | "id": "Order", 116 | "properties": { 117 | "id": { 118 | "type": "integer", 119 | "format": "int64" 120 | }, 121 | "petId": { 122 | "type": "integer", 123 | "format": "int64" 124 | }, 125 | "quantity": { 126 | "type": "integer", 127 | "format": "int32" 128 | }, 129 | "status": { 130 | "type": "string", 131 | "description": "Order Status", 132 | "enum": [ 133 | "placed", 134 | "approved", 135 | "delivered" 136 | ] 137 | }, 138 | "shipDate": { 139 | "type": "string", 140 | "format": "date-time" 141 | } 142 | } 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /test/fixtures/examples/swagger-minimal.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "1.0.0", 5 | "title": "Minimal Swagger File", 6 | "description": "" 7 | }, 8 | "basePath": "/api", 9 | "consumes": [ 10 | "application/json" 11 | ], 12 | "produces": [ 13 | "application/json" 14 | ], 15 | "paths": { 16 | }, 17 | "definitions": { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/fixtures/markdown/README.md: -------------------------------------------------------------------------------- 1 | # GitHub Flavoured Markdown Test 2 | 3 | Compare [GitHub](https://github.com/darosh/angular-swagger-ui-material/blob/master/test/fixtures/markdown/README.md) and [Swagger](http://darosh.github.io/angular-swagger-ui-material/#?url=http://darosh.github.io/angular-swagger-ui-material/swagger-gfm.json) render powered by [Showdown](https://github.com/showdownjs/showdown). 4 | 5 | ## Header (level 2) 6 | 7 | ### Header (level 3) 8 | 9 | #### Header (level 4) 10 | 11 | ##### Table 12 | 13 | | Header | Header | Header | 14 | | --- | --- | --- | 15 | | Cell | Cell | Cell | 16 | | Cell | Cell | Cell | 17 | 18 | ##### Auto-link 19 | 20 | www.example.com 21 | 22 | ##### List 23 | 24 | * A 25 | * B 26 | * C 27 | 28 | ##### Block 29 | 30 | ``` 31 | Hello block! 32 | ``` 33 | 34 | ##### Blockquote 35 | 36 | > …in blockquote. 37 | 38 | ##### Horizontal Rule 39 | 40 | --- 41 | -------------------------------------------------------------------------------- /test/fixtures/markdown/swagger-gfm.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "1.0.0", 5 | "title": "GiHub Flavored Markdown Test", 6 | "description": "# GitHub Flavoured Markdown Test\r\n\r\nCompare [GitHub](https://github.com/darosh/angular-swagger-ui-material/blob/master/test/fixtures/markdown/README.md) and [Swagger](http://darosh.github.io/angular-swagger-ui-material/#?url=http://darosh.github.io/angular-swagger-ui-material/swagger-gfm.json) render powered by [Showdown](https://github.com/showdownjs/showdown).\r\n\r\n## Header (level 2)\r\n\r\n### Header (level 3)\r\n\r\n#### Header (level 4)\r\n\r\n##### Table\r\n\r\n| Header | Header | Header |\r\n| --- | --- | --- |\r\n| Cell | Cell | Cell |\r\n| Cell | Cell | Cell |\r\n\r\n##### Auto-link\r\n\r\nwww.example.com\r\n\r\n##### List\r\n\r\n* A\r\n* B\r\n* C\r\n\r\n##### Block\r\n\r\n```\r\nHello block!\r\n```\r\n\r\n##### Blockquote\r\n\r\n> …in blockquote.\r\n\r\n##### Horizontal Rule\r\n\r\n---\r\n" 7 | }, 8 | "basePath": "/api", 9 | "consumes": [ 10 | "application/json" 11 | ], 12 | "produces": [ 13 | "application/json" 14 | ], 15 | "paths": {}, 16 | "definitions": {} 17 | } -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/README.md: -------------------------------------------------------------------------------- 1 | Examples from [OAI/OpenAPI-Specification](https://github.com/OAI/OpenAPI-Specification). 2 | -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/json/api-with-examples.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "title": "Simple API overview", 5 | "version": "v2" 6 | }, 7 | "paths": { 8 | "/": { 9 | "get": { 10 | "operationId": "listVersionsv2", 11 | "summary": "List API versions", 12 | "produces": [ 13 | "application/json" 14 | ], 15 | "responses": { 16 | "200": { 17 | "description": "200 300 response", 18 | "examples": { 19 | "application/json": "{\n \"versions\": [\n {\n \"status\": \"CURRENT\",\n \"updated\": \"2011-01-21T11:33:21Z\",\n \"id\": \"v2.0\",\n \"links\": [\n {\n \"href\": \"http://127.0.0.1:8774/v2/\",\n \"rel\": \"self\"\n }\n ]\n },\n {\n \"status\": \"EXPERIMENTAL\",\n \"updated\": \"2013-07-23T11:33:21Z\",\n \"id\": \"v3.0\",\n \"links\": [\n {\n \"href\": \"http://127.0.0.1:8774/v3/\",\n \"rel\": \"self\"\n }\n ]\n }\n ]\n}" 20 | } 21 | }, 22 | "300": { 23 | "description": "200 300 response", 24 | "examples": { 25 | "application/json": "{\n \"versions\": [\n {\n \"status\": \"CURRENT\",\n \"updated\": \"2011-01-21T11:33:21Z\",\n \"id\": \"v2.0\",\n \"links\": [\n {\n \"href\": \"http://127.0.0.1:8774/v2/\",\n \"rel\": \"self\"\n }\n ]\n },\n {\n \"status\": \"EXPERIMENTAL\",\n \"updated\": \"2013-07-23T11:33:21Z\",\n \"id\": \"v3.0\",\n \"links\": [\n {\n \"href\": \"http://127.0.0.1:8774/v3/\",\n \"rel\": \"self\"\n }\n ]\n }\n ]\n}" 26 | } 27 | } 28 | } 29 | } 30 | }, 31 | "/v2": { 32 | "get": { 33 | "operationId": "getVersionDetailsv2", 34 | "summary": "Show API version details", 35 | "produces": [ 36 | "application/json" 37 | ], 38 | "responses": { 39 | "200": { 40 | "description": "200 203 response", 41 | "examples": { 42 | "application/json": "{\n \"version\": {\n \"status\": \"CURRENT\",\n \"updated\": \"2011-01-21T11:33:21Z\",\n \"media-types\": [\n {\n \"base\": \"application/xml\",\n \"type\": \"application/vnd.openstack.compute+xml;version=2\"\n },\n {\n \"base\": \"application/json\",\n \"type\": \"application/vnd.openstack.compute+json;version=2\"\n }\n ],\n \"id\": \"v2.0\",\n \"links\": [\n {\n \"href\": \"http://127.0.0.1:8774/v2/\",\n \"rel\": \"self\"\n },\n {\n \"href\": \"http://docs.openstack.org/api/openstack-compute/2/os-compute-devguide-2.pdf\",\n \"type\": \"application/pdf\",\n \"rel\": \"describedby\"\n },\n {\n \"href\": \"http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl\",\n \"type\": \"application/vnd.sun.wadl+xml\",\n \"rel\": \"describedby\"\n },\n {\n \"href\": \"http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl\",\n \"type\": \"application/vnd.sun.wadl+xml\",\n \"rel\": \"describedby\"\n }\n ]\n }\n}" 43 | } 44 | }, 45 | "203": { 46 | "description": "200 203 response", 47 | "examples": { 48 | "application/json": "{\n \"version\": {\n \"status\": \"CURRENT\",\n \"updated\": \"2011-01-21T11:33:21Z\",\n \"media-types\": [\n {\n \"base\": \"application/xml\",\n \"type\": \"application/vnd.openstack.compute+xml;version=2\"\n },\n {\n \"base\": \"application/json\",\n \"type\": \"application/vnd.openstack.compute+json;version=2\"\n }\n ],\n \"id\": \"v2.0\",\n \"links\": [\n {\n \"href\": \"http://23.253.228.211:8774/v2/\",\n \"rel\": \"self\"\n },\n {\n \"href\": \"http://docs.openstack.org/api/openstack-compute/2/os-compute-devguide-2.pdf\",\n \"type\": \"application/pdf\",\n \"rel\": \"describedby\"\n },\n {\n \"href\": \"http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl\",\n \"type\": \"application/vnd.sun.wadl+xml\",\n \"rel\": \"describedby\"\n }\n ]\n }\n}" 49 | } 50 | } 51 | } 52 | } 53 | } 54 | }, 55 | "consumes": [ 56 | "application/json" 57 | ] 58 | } -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/json/petstore-minimal.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "1.0.0", 5 | "title": "Swagger Petstore", 6 | "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", 7 | "termsOfService": "http://swagger.io/terms/", 8 | "contact": { 9 | "name": "Swagger API Team" 10 | }, 11 | "license": { 12 | "name": "MIT" 13 | } 14 | }, 15 | "host": "petstore.swagger.io", 16 | "basePath": "/api", 17 | "schemes": [ 18 | "http" 19 | ], 20 | "consumes": [ 21 | "application/json" 22 | ], 23 | "produces": [ 24 | "application/json" 25 | ], 26 | "paths": { 27 | "/pets": { 28 | "get": { 29 | "description": "Returns all pets from the system that the user has access to", 30 | "produces": [ 31 | "application/json" 32 | ], 33 | "responses": { 34 | "200": { 35 | "description": "A list of pets.", 36 | "schema": { 37 | "type": "array", 38 | "items": { 39 | "$ref": "#/definitions/Pet" 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | }, 47 | "definitions": { 48 | "Pet": { 49 | "type": "object", 50 | "required": [ 51 | "id", 52 | "name" 53 | ], 54 | "properties": { 55 | "id": { 56 | "type": "integer", 57 | "format": "int64" 58 | }, 59 | "name": { 60 | "type": "string" 61 | }, 62 | "tag": { 63 | "type": "string" 64 | } 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/json/petstore-separate/common/Error.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "required": [ 4 | "code", 5 | "message" 6 | ], 7 | "properties": { 8 | "code": { 9 | "type": "integer", 10 | "format": "int32" 11 | }, 12 | "message": { 13 | "type": "string" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/json/petstore-separate/spec/NewPet.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "allOf": [ 4 | { 5 | "$ref": "Pet.json" 6 | }, 7 | { 8 | "required": [ 9 | "name" 10 | ], 11 | "properties": { 12 | "description": { 13 | "type": "integer", 14 | "format": "int64" 15 | } 16 | } 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/json/petstore-separate/spec/Pet.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "required": [ 4 | "id", 5 | "name" 6 | ], 7 | "properties": { 8 | "id": { 9 | "type": "integer", 10 | "format": "int64" 11 | }, 12 | "name": { 13 | "type": "string" 14 | }, 15 | "tag": { 16 | "type": "string" 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/json/petstore-separate/spec/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "tagsParam": { 3 | "name": "tags", 4 | "in": "query", 5 | "description": "tags to filter by", 6 | "required": false, 7 | "type": "array", 8 | "collectionFormat": "csv", 9 | "items": { 10 | "type": "string" 11 | } 12 | }, 13 | "limitsParam": { 14 | "name": "limit", 15 | "in": "query", 16 | "description": "maximum number of results to return", 17 | "required": false, 18 | "type": "integer", 19 | "format": "int32" 20 | } 21 | } -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/json/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "1.0.0", 5 | "title": "Swagger Petstore", 6 | "license": { 7 | "name": "MIT" 8 | } 9 | }, 10 | "host": "petstore.swagger.io", 11 | "basePath": "/v1", 12 | "schemes": [ 13 | "http" 14 | ], 15 | "consumes": [ 16 | "application/json" 17 | ], 18 | "produces": [ 19 | "application/json" 20 | ], 21 | "paths": { 22 | "/pets": { 23 | "get": { 24 | "summary": "List all pets", 25 | "operationId": "listPets", 26 | "tags": [ 27 | "pets" 28 | ], 29 | "parameters": [ 30 | { 31 | "name": "limit", 32 | "in": "query", 33 | "description": "How many items to return at one time (max 100)", 34 | "required": false, 35 | "type": "integer", 36 | "format": "int32" 37 | } 38 | ], 39 | "responses": { 40 | "200": { 41 | "description": "An paged array of pets", 42 | "headers": { 43 | "x-next": { 44 | "type": "string", 45 | "description": "A link to the next page of responses" 46 | } 47 | }, 48 | "schema": { 49 | "$ref": "#/definitions/Pets" 50 | } 51 | }, 52 | "default": { 53 | "description": "unexpected error", 54 | "schema": { 55 | "$ref": "#/definitions/Error" 56 | } 57 | } 58 | } 59 | }, 60 | "post": { 61 | "summary": "Create a pet", 62 | "operationId": "createPets", 63 | "tags": [ 64 | "pets" 65 | ], 66 | "responses": { 67 | "201": { 68 | "description": "Null response" 69 | }, 70 | "default": { 71 | "description": "unexpected error", 72 | "schema": { 73 | "$ref": "#/definitions/Error" 74 | } 75 | } 76 | } 77 | } 78 | }, 79 | "/pets/{petId}": { 80 | "get": { 81 | "summary": "Info for a specific pet", 82 | "operationId": "showPetById", 83 | "tags": [ 84 | "pets" 85 | ], 86 | "parameters": [ 87 | { 88 | "name": "petId", 89 | "in": "path", 90 | "required": true, 91 | "description": "The id of the pet to retrieve", 92 | "type": "string" 93 | } 94 | ], 95 | "responses": { 96 | "200": { 97 | "description": "Expected response to a valid request", 98 | "schema": { 99 | "$ref": "#/definitions/Pets" 100 | } 101 | }, 102 | "default": { 103 | "description": "unexpected error", 104 | "schema": { 105 | "$ref": "#/definitions/Error" 106 | } 107 | } 108 | } 109 | } 110 | } 111 | }, 112 | "definitions": { 113 | "Pet": { 114 | "required": [ 115 | "id", 116 | "name" 117 | ], 118 | "properties": { 119 | "id": { 120 | "type": "integer", 121 | "format": "int64" 122 | }, 123 | "name": { 124 | "type": "string" 125 | }, 126 | "tag": { 127 | "type": "string" 128 | } 129 | } 130 | }, 131 | "Pets": { 132 | "type": "array", 133 | "items": { 134 | "$ref": "#/definitions/Pet" 135 | } 136 | }, 137 | "Error": { 138 | "required": [ 139 | "code", 140 | "message" 141 | ], 142 | "properties": { 143 | "code": { 144 | "type": "integer", 145 | "format": "int32" 146 | }, 147 | "message": { 148 | "type": "string" 149 | } 150 | } 151 | } 152 | } 153 | } -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/yaml/petstore-expanded.yaml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification 6 | termsOfService: http://swagger.io/terms/ 7 | contact: 8 | name: Swagger API Team 9 | email: foo@example.com 10 | url: http://madskristensen.net 11 | license: 12 | name: MIT 13 | url: http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT 14 | host: petstore.swagger.io 15 | basePath: /api 16 | schemes: 17 | - http 18 | consumes: 19 | - application/json 20 | produces: 21 | - application/json 22 | paths: 23 | /pets: 24 | get: 25 | description: | 26 | Returns all pets from the system that the user has access to 27 | Nam sed condimentum est. Maecenas tempor sagittis sapien, nec rhoncus sem sagittis sit amet. Aenean at gravida augue, ac iaculis sem. Curabitur odio lorem, ornare eget elementum nec, cursus id lectus. Duis mi turpis, pulvinar ac eros ac, tincidunt varius justo. In hac habitasse platea dictumst. Integer at adipiscing ante, a sagittis ligula. Aenean pharetra tempor ante molestie imperdiet. Vivamus id aliquam diam. Cras quis velit non tortor eleifend sagittis. Praesent at enim pharetra urna volutpat venenatis eget eget mauris. In eleifend fermentum facilisis. Praesent enim enim, gravida ac sodales sed, placerat id erat. Suspendisse lacus dolor, consectetur non augue vel, vehicula interdum libero. Morbi euismod sagittis libero sed lacinia. 28 | 29 | Sed tempus felis lobortis leo pulvinar rutrum. Nam mattis velit nisl, eu condimentum ligula luctus nec. Phasellus semper velit eget aliquet faucibus. In a mattis elit. Phasellus vel urna viverra, condimentum lorem id, rhoncus nibh. Ut pellentesque posuere elementum. Sed a varius odio. Morbi rhoncus ligula libero, vel eleifend nunc tristique vitae. Fusce et sem dui. Aenean nec scelerisque tortor. Fusce malesuada accumsan magna vel tempus. Quisque mollis felis eu dolor tristique, sit amet auctor felis gravida. Sed libero lorem, molestie sed nisl in, accumsan tempor nisi. Fusce sollicitudin massa ut lacinia mattis. Sed vel eleifend lorem. Pellentesque vitae felis pretium, pulvinar elit eu, euismod sapien. 30 | operationId: findPets 31 | parameters: 32 | - name: tags 33 | in: query 34 | description: tags to filter by 35 | required: false 36 | type: array 37 | collectionFormat: csv 38 | items: 39 | type: string 40 | - name: limit 41 | in: query 42 | description: maximum number of results to return 43 | required: false 44 | type: integer 45 | format: int32 46 | responses: 47 | 200: 48 | description: pet response 49 | schema: 50 | type: array 51 | items: 52 | $ref: '#/definitions/Pet' 53 | default: 54 | description: unexpected error 55 | schema: 56 | $ref: '#/definitions/Error' 57 | post: 58 | description: Creates a new pet in the store. Duplicates are allowed 59 | operationId: addPet 60 | parameters: 61 | - name: pet 62 | in: body 63 | description: Pet to add to the store 64 | required: true 65 | schema: 66 | $ref: '#/definitions/NewPet' 67 | responses: 68 | 200: 69 | description: pet response 70 | schema: 71 | $ref: '#/definitions/Pet' 72 | default: 73 | description: unexpected error 74 | schema: 75 | $ref: '#/definitions/Error' 76 | /pets/{id}: 77 | get: 78 | description: Returns a user based on a single ID, if the user does not have access to the pet 79 | operationId: find pet by id 80 | parameters: 81 | - name: id 82 | in: path 83 | description: ID of pet to fetch 84 | required: true 85 | type: integer 86 | format: int64 87 | responses: 88 | 200: 89 | description: pet response 90 | schema: 91 | $ref: '#/definitions/Pet' 92 | default: 93 | description: unexpected error 94 | schema: 95 | $ref: '#/definitions/Error' 96 | delete: 97 | description: deletes a single pet based on the ID supplied 98 | operationId: deletePet 99 | parameters: 100 | - name: id 101 | in: path 102 | description: ID of pet to delete 103 | required: true 104 | type: integer 105 | format: int64 106 | responses: 107 | 204: 108 | description: pet deleted 109 | default: 110 | description: unexpected error 111 | schema: 112 | $ref: '#/definitions/Error' 113 | definitions: 114 | Pet: 115 | allOf: 116 | - $ref: '#/definitions/NewPet' 117 | - required: 118 | - id 119 | properties: 120 | id: 121 | type: integer 122 | format: int64 123 | 124 | NewPet: 125 | required: 126 | - name 127 | properties: 128 | name: 129 | type: string 130 | tag: 131 | type: string 132 | 133 | Error: 134 | required: 135 | - code 136 | - message 137 | properties: 138 | code: 139 | type: integer 140 | format: int32 141 | message: 142 | type: string 143 | -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/yaml/petstore-minimal.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | version: "1.0.0" 5 | title: "Swagger Petstore" 6 | description: "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification" 7 | termsOfService: "http://swagger.io/terms/" 8 | contact: 9 | name: "Swagger API Team" 10 | license: 11 | name: "MIT" 12 | host: "petstore.swagger.io" 13 | basePath: "/api" 14 | schemes: 15 | - "http" 16 | consumes: 17 | - "application/json" 18 | produces: 19 | - "application/json" 20 | paths: 21 | /pets: 22 | get: 23 | description: "Returns all pets from the system that the user has access to" 24 | produces: 25 | - "application/json" 26 | responses: 27 | 200: 28 | description: "A list of pets." 29 | schema: 30 | type: "array" 31 | items: 32 | $ref: "#/definitions/Pet" 33 | definitions: 34 | Pet: 35 | type: "object" 36 | required: 37 | - "id" 38 | - "name" 39 | properties: 40 | id: 41 | type: "integer" 42 | format: "int64" 43 | name: 44 | type: "string" 45 | tag: 46 | type: "string" 47 | 48 | -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/yaml/petstore-separate/common/Error.yaml: -------------------------------------------------------------------------------- 1 | type: object 2 | required: 3 | - code 4 | - message 5 | properties: 6 | code: 7 | type: integer 8 | format: int32 9 | message: 10 | type: string 11 | -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/yaml/petstore-separate/spec/NewPet.yaml: -------------------------------------------------------------------------------- 1 | type: object 2 | allOf: 3 | - $ref: 'Pet.yaml' 4 | - required: 5 | - name 6 | properties: 7 | description: 8 | type: integer 9 | format: int64 -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/yaml/petstore-separate/spec/Pet.yaml: -------------------------------------------------------------------------------- 1 | type: object 2 | required: 3 | - id 4 | - name 5 | properties: 6 | id: 7 | type: integer 8 | format: int64 9 | name: 10 | type: string 11 | tag: 12 | type: string 13 | -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/yaml/petstore-separate/spec/parameters.yaml: -------------------------------------------------------------------------------- 1 | tagsParam: 2 | name: tags 3 | in: query 4 | description: tags to filter by 5 | required: false 6 | type: array 7 | collectionFormat: csv 8 | items: 9 | type: string 10 | limitsParam: 11 | name: limit 12 | in: query 13 | description: maximum number of results to return 14 | required: false 15 | type: integer 16 | format: int32 -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/yaml/petstore-separate/spec/swagger.yaml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification 6 | termsOfService: http://helloreverb.com/terms/ 7 | contact: 8 | name: Wordnik API Team 9 | email: foo@example.com 10 | url: http://madskristensen.net 11 | license: 12 | name: MIT 13 | url: http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT 14 | host: petstore.swagger.wordnik.com 15 | basePath: /api 16 | schemes: 17 | - http 18 | consumes: 19 | - application/json 20 | produces: 21 | - application/json 22 | paths: 23 | /pets: 24 | get: 25 | description: | 26 | Returns all pets from the system that the user has access to 27 | Nam sed condimentum est. Maecenas tempor sagittis sapien, nec rhoncus sem sagittis sit amet. Aenean at gravida augue, ac iaculis sem. Curabitur odio lorem, ornare eget elementum nec, cursus id lectus. Duis mi turpis, pulvinar ac eros ac, tincidunt varius justo. In hac habitasse platea dictumst. Integer at adipiscing ante, a sagittis ligula. Aenean pharetra tempor ante molestie imperdiet. Vivamus id aliquam diam. Cras quis velit non tortor eleifend sagittis. Praesent at enim pharetra urna volutpat venenatis eget eget mauris. In eleifend fermentum facilisis. Praesent enim enim, gravida ac sodales sed, placerat id erat. Suspendisse lacus dolor, consectetur non augue vel, vehicula interdum libero. Morbi euismod sagittis libero sed lacinia. 28 | 29 | Sed tempus felis lobortis leo pulvinar rutrum. Nam mattis velit nisl, eu condimentum ligula luctus nec. Phasellus semper velit eget aliquet faucibus. In a mattis elit. Phasellus vel urna viverra, condimentum lorem id, rhoncus nibh. Ut pellentesque posuere elementum. Sed a varius odio. Morbi rhoncus ligula libero, vel eleifend nunc tristique vitae. Fusce et sem dui. Aenean nec scelerisque tortor. Fusce malesuada accumsan magna vel tempus. Quisque mollis felis eu dolor tristique, sit amet auctor felis gravida. Sed libero lorem, molestie sed nisl in, accumsan tempor nisi. Fusce sollicitudin massa ut lacinia mattis. Sed vel eleifend lorem. Pellentesque vitae felis pretium, pulvinar elit eu, euismod sapien. 30 | operationId: findPets 31 | parameters: 32 | - $ref: 'parameters.yaml#/tagsParam' 33 | - $ref: 'parameters.yaml#/limitsParam' 34 | responses: 35 | 200: 36 | description: pet response 37 | schema: 38 | type: array 39 | items: 40 | $ref: 'Pet.yaml' 41 | default: 42 | description: unexpected error 43 | schema: 44 | $ref: '../common/Error.yaml' 45 | post: 46 | description: Creates a new pet in the store. Duplicates are allowed 47 | operationId: addPet 48 | parameters: 49 | - name: pet 50 | in: body 51 | description: Pet to add to the store 52 | required: true 53 | schema: 54 | $ref: 'NewPet.yaml' 55 | responses: 56 | 200: 57 | description: pet response 58 | schema: 59 | $ref: 'Pet.yaml' 60 | default: 61 | description: unexpected error 62 | schema: 63 | $ref: '../common/Error.yaml' 64 | /pets/{id}: 65 | get: 66 | description: Returns a user based on a single ID, if the user does not have access to the pet 67 | operationId: find pet by id 68 | parameters: 69 | - name: id 70 | in: path 71 | description: ID of pet to fetch 72 | required: true 73 | type: integer 74 | format: int64 75 | responses: 76 | 200: 77 | description: pet response 78 | schema: 79 | $ref: 'Pet.yaml' 80 | default: 81 | description: unexpected error 82 | schema: 83 | $ref: '../common/Error.yaml' 84 | delete: 85 | description: deletes a single pet based on the ID supplied 86 | operationId: deletePet 87 | parameters: 88 | - name: id 89 | in: path 90 | description: ID of pet to delete 91 | required: true 92 | type: integer 93 | format: int64 94 | responses: 95 | 204: 96 | description: pet deleted 97 | default: 98 | description: unexpected error 99 | schema: 100 | $ref: '../common/Error.yaml' -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/yaml/petstore-simple.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | version: "1.0.0" 5 | title: "Swagger Petstore" 6 | description: "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification" 7 | termsOfService: "http://swagger.io/terms/" 8 | contact: 9 | name: "Swagger API Team" 10 | license: 11 | name: "MIT" 12 | host: "petstore.swagger.io" 13 | basePath: "/api" 14 | schemes: 15 | - "http" 16 | consumes: 17 | - "application/json" 18 | produces: 19 | - "application/json" 20 | paths: 21 | /pets: 22 | get: 23 | description: "Returns all pets from the system that the user has access to" 24 | operationId: "findPets" 25 | produces: 26 | - "application/json" 27 | - "application/xml" 28 | - "text/xml" 29 | - "text/html" 30 | parameters: 31 | - 32 | name: "tags" 33 | in: "query" 34 | description: "tags to filter by" 35 | required: false 36 | type: "array" 37 | items: 38 | type: "string" 39 | collectionFormat: "csv" 40 | - 41 | name: "limit" 42 | in: "query" 43 | description: "maximum number of results to return" 44 | required: false 45 | type: "integer" 46 | format: "int32" 47 | responses: 48 | 200: 49 | description: "pet response" 50 | schema: 51 | type: "array" 52 | items: 53 | $ref: "#/definitions/Pet" 54 | default: 55 | description: "unexpected error" 56 | schema: 57 | $ref: "#/definitions/ErrorModel" 58 | post: 59 | description: "Creates a new pet in the store. Duplicates are allowed" 60 | operationId: "addPet" 61 | produces: 62 | - "application/json" 63 | parameters: 64 | - 65 | name: "pet" 66 | in: "body" 67 | description: "Pet to add to the store" 68 | required: true 69 | schema: 70 | $ref: "#/definitions/NewPet" 71 | responses: 72 | 200: 73 | description: "pet response" 74 | schema: 75 | $ref: "#/definitions/Pet" 76 | default: 77 | description: "unexpected error" 78 | schema: 79 | $ref: "#/definitions/ErrorModel" 80 | /pets/{id}: 81 | get: 82 | description: "Returns a user based on a single ID, if the user does not have access to the pet" 83 | operationId: "findPetById" 84 | produces: 85 | - "application/json" 86 | - "application/xml" 87 | - "text/xml" 88 | - "text/html" 89 | parameters: 90 | - 91 | name: "id" 92 | in: "path" 93 | description: "ID of pet to fetch" 94 | required: true 95 | type: "integer" 96 | format: "int64" 97 | responses: 98 | 200: 99 | description: "pet response" 100 | schema: 101 | $ref: "#/definitions/Pet" 102 | default: 103 | description: "unexpected error" 104 | schema: 105 | $ref: "#/definitions/ErrorModel" 106 | delete: 107 | description: "deletes a single pet based on the ID supplied" 108 | operationId: "deletePet" 109 | parameters: 110 | - 111 | name: "id" 112 | in: "path" 113 | description: "ID of pet to delete" 114 | required: true 115 | type: "integer" 116 | format: "int64" 117 | responses: 118 | 204: 119 | description: "pet deleted" 120 | default: 121 | description: "unexpected error" 122 | schema: 123 | $ref: "#/definitions/ErrorModel" 124 | definitions: 125 | Pet: 126 | type: "object" 127 | allOf: 128 | - 129 | $ref: "#/definitions/NewPet" 130 | - 131 | required: 132 | - "id" 133 | properties: 134 | id: 135 | type: "integer" 136 | format: "int64" 137 | NewPet: 138 | type: "object" 139 | required: 140 | - "name" 141 | properties: 142 | name: 143 | type: "string" 144 | tag: 145 | type: "string" 146 | ErrorModel: 147 | type: "object" 148 | required: 149 | - "code" 150 | - "message" 151 | properties: 152 | code: 153 | type: "integer" 154 | format: "int32" 155 | message: 156 | type: "string" 157 | 158 | -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/yaml/petstore-with-external-docs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | version: "1.0.0" 5 | title: "Swagger Petstore" 6 | description: "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification" 7 | termsOfService: "http://swagger.io/terms/" 8 | contact: 9 | name: "Swagger API Team" 10 | email: "apiteam@swagger.io" 11 | url: "http://swagger.io" 12 | license: 13 | name: "MIT" 14 | url: "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT" 15 | externalDocs: 16 | description: "find more info here" 17 | url: "https://swagger.io/about" 18 | host: "petstore.swagger.io" 19 | basePath: "/api" 20 | schemes: 21 | - "http" 22 | consumes: 23 | - "application/json" 24 | produces: 25 | - "application/json" 26 | paths: 27 | /pets: 28 | get: 29 | description: "Returns all pets from the system that the user has access to" 30 | operationId: "findPets" 31 | externalDocs: 32 | description: "find more info here" 33 | url: "https://swagger.io/about" 34 | produces: 35 | - "application/json" 36 | - "application/xml" 37 | - "text/xml" 38 | - "text/html" 39 | parameters: 40 | - 41 | name: "tags" 42 | in: "query" 43 | description: "tags to filter by" 44 | required: false 45 | type: "array" 46 | items: 47 | type: "string" 48 | collectionFormat: "csv" 49 | - 50 | name: "limit" 51 | in: "query" 52 | description: "maximum number of results to return" 53 | required: false 54 | type: "integer" 55 | format: "int32" 56 | responses: 57 | 200: 58 | description: "pet response" 59 | schema: 60 | type: "array" 61 | items: 62 | $ref: "#/definitions/Pet" 63 | default: 64 | description: "unexpected error" 65 | schema: 66 | $ref: "#/definitions/ErrorModel" 67 | post: 68 | description: "Creates a new pet in the store. Duplicates are allowed" 69 | operationId: "addPet" 70 | produces: 71 | - "application/json" 72 | parameters: 73 | - 74 | name: "pet" 75 | in: "body" 76 | description: "Pet to add to the store" 77 | required: true 78 | schema: 79 | $ref: "#/definitions/NewPet" 80 | responses: 81 | 200: 82 | description: "pet response" 83 | schema: 84 | $ref: "#/definitions/Pet" 85 | default: 86 | description: "unexpected error" 87 | schema: 88 | $ref: "#/definitions/ErrorModel" 89 | /pets/{id}: 90 | get: 91 | description: "Returns a user based on a single ID, if the user does not have access to the pet" 92 | operationId: "findPetById" 93 | produces: 94 | - "application/json" 95 | - "application/xml" 96 | - "text/xml" 97 | - "text/html" 98 | parameters: 99 | - 100 | name: "id" 101 | in: "path" 102 | description: "ID of pet to fetch" 103 | required: true 104 | type: "integer" 105 | format: "int64" 106 | responses: 107 | 200: 108 | description: "pet response" 109 | schema: 110 | $ref: "#/definitions/Pet" 111 | default: 112 | description: "unexpected error" 113 | schema: 114 | $ref: "#/definitions/ErrorModel" 115 | delete: 116 | description: "deletes a single pet based on the ID supplied" 117 | operationId: "deletePet" 118 | parameters: 119 | - 120 | name: "id" 121 | in: "path" 122 | description: "ID of pet to delete" 123 | required: true 124 | type: "integer" 125 | format: "int64" 126 | responses: 127 | 204: 128 | description: "pet deleted" 129 | default: 130 | description: "unexpected error" 131 | schema: 132 | $ref: "#/definitions/ErrorModel" 133 | definitions: 134 | Pet: 135 | type: "object" 136 | allOf: 137 | - 138 | $ref: "#/definitions/NewPet" 139 | - 140 | required: 141 | - "id" 142 | properties: 143 | id: 144 | type: "integer" 145 | format: "int64" 146 | NewPet: 147 | type: "object" 148 | required: 149 | - "name" 150 | properties: 151 | name: 152 | type: "string" 153 | tag: 154 | type: "string" 155 | ErrorModel: 156 | type: "object" 157 | required: 158 | - "code" 159 | - "message" 160 | properties: 161 | code: 162 | type: "integer" 163 | format: "int32" 164 | message: 165 | type: "string" 166 | 167 | -------------------------------------------------------------------------------- /test/fixtures/openapi-specification/yaml/petstore.yaml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | host: petstore.swagger.io 8 | basePath: /v1 9 | schemes: 10 | - http 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /pets: 17 | get: 18 | summary: List all pets 19 | operationId: listPets 20 | tags: 21 | - pets 22 | parameters: 23 | - name: limit 24 | in: query 25 | description: How many items to return at one time (max 100) 26 | required: false 27 | type: integer 28 | format: int32 29 | responses: 30 | 200: 31 | description: An paged array of pets 32 | headers: 33 | x-next: 34 | type: string 35 | description: A link to the next page of responses 36 | schema: 37 | $ref: '#/definitions/Pets' 38 | default: 39 | description: unexpected error 40 | schema: 41 | $ref: '#/definitions/Error' 42 | post: 43 | summary: Create a pet 44 | operationId: createPets 45 | tags: 46 | - pets 47 | responses: 48 | 201: 49 | description: Null response 50 | default: 51 | description: unexpected error 52 | schema: 53 | $ref: '#/definitions/Error' 54 | /pets/{petId}: 55 | get: 56 | summary: Info for a specific pet 57 | operationId: showPetById 58 | tags: 59 | - pets 60 | parameters: 61 | - name: petId 62 | in: path 63 | required: true 64 | description: The id of the pet to retrieve 65 | type: string 66 | responses: 67 | 200: 68 | description: Expected response to a valid request 69 | schema: 70 | $ref: '#/definitions/Pets' 71 | default: 72 | description: unexpected error 73 | schema: 74 | $ref: '#/definitions/Error' 75 | definitions: 76 | Pet: 77 | required: 78 | - id 79 | - name 80 | properties: 81 | id: 82 | type: integer 83 | format: int64 84 | name: 85 | type: string 86 | tag: 87 | type: string 88 | Pets: 89 | type: array 90 | items: 91 | $ref: '#/definitions/Pet' 92 | Error: 93 | required: 94 | - code 95 | - message 96 | properties: 97 | code: 98 | type: integer 99 | format: int32 100 | message: 101 | type: string 102 | --------------------------------------------------------------------------------