From f212145d8340014235667b98c47a9dc6294c066b Mon Sep 17 00:00:00 2001 From: Vincent Bailleau Date: Wed, 27 Sep 2017 10:48:52 +0200 Subject: [PATCH 1/5] Add support of x-permissions vendor extension --- docs/redoc-vendor-extensions.md | 45 +++++++++++++++ lib/components/Operation/operation.html | 4 ++ lib/components/Operation/operation.scss | 24 ++++++++ lib/components/Operation/operation.spec.ts | 4 +- lib/components/Operation/operation.ts | 17 +++++- lib/components/Permissions/x-permissions.html | 5 ++ lib/components/Permissions/x-permissions.scss | 36 ++++++++++++ lib/components/Permissions/x-permissions.ts | 48 ++++++++++++++++ lib/components/index.ts | 5 +- lib/redoc.module.ts | 8 +-- lib/utils/spec-manager.ts | 24 ++++++++ tests/schemas/extended-petstore.yml | 55 +++++++++++++++++++ tests/spec-bundle.js | 3 +- 13 files changed, 267 insertions(+), 11 deletions(-) create mode 100644 lib/components/Permissions/x-permissions.html create mode 100644 lib/components/Permissions/x-permissions.scss create mode 100644 lib/components/Permissions/x-permissions.ts diff --git a/docs/redoc-vendor-extensions.md b/docs/redoc-vendor-extensions.md index 8985bf6b..079b36b5 100644 --- a/docs/redoc-vendor-extensions.md +++ b/docs/redoc-vendor-extensions.md @@ -157,6 +157,51 @@ description: Pagination description (can use markdown syntax) x-traitTag: true ``` +### Permission Object vendor extensions + +#### x-permissions + +| Field Name | Type | Description | +| :------------- | :------: | :---------- | +| x-permissions | Object | Define the several permissions available for the API and associated to the operations | + +###### Usage in ReDoc +`x-permissions` are rendered bellow the API description of ReDoc + +###### x-permissions example (main declaration) + +yaml +```yaml +swagger: '2.0' +info: + ... +tags: [...] +x-permissions: + admin: + title: Pet store admin + description: 'Pet store Admin have special privileges on PetStore API allowing them to manage their store and users from their company ' + user: + title: Pet Store user + description: 'Pet store user' +``` + +##### Usage in Redoc operations +`x-permissions` are rendered above the Operation description of ReDoc +###### x-permissions example (operation declaration) + +yaml +```yaml +/user/logout: + get: + tags: + - "user" + x-permissions: + - name: "admin" + - name: "user" +``` + + + ### Operation Object vendor extensions Extends OpenAPI [Operation Object](http://swagger.io/specification/#operationObject) #### x-code-samples diff --git a/lib/components/Operation/operation.html b/lib/components/Operation/operation.html index 3ddea4f5..57bc24f2 100644 --- a/lib/components/Operation/operation.html +++ b/lib/components/Operation/operation.html @@ -8,6 +8,10 @@
{{tag}}
+
+ Permissions: {{permission.title}} + +

diff --git a/lib/components/Operation/operation.scss b/lib/components/Operation/operation.scss index 708b71c8..8fabebfe 100644 --- a/lib/components/Operation/operation.scss +++ b/lib/components/Operation/operation.scss @@ -53,6 +53,30 @@ } } +.operation-permissions { + margin-top: 20px; + + font-size: 14px; + padding: 0.2em 0; + margin: 3em 0 1.1em; + color: #253137; + font-weight: normal; + + a { + font-size: 12px; + font-family: Courier, monospace; + background-color: rgba(38, 50, 56, 0.02); + border: 1px solid rgba(38, 50, 56, 0.1); + margin: 2px 3px; + padding: 0px 5px; + border-radius: 2px; + color: #263238; + display: inline-block; + min-width: 20px; + text-align: center; + } +} + .operation-content, .operation-samples { display: block; box-sizing: border-box; diff --git a/lib/components/Operation/operation.spec.ts b/lib/components/Operation/operation.spec.ts index 44be2aae..40ba98c5 100644 --- a/lib/components/Operation/operation.spec.ts +++ b/lib/components/Operation/operation.spec.ts @@ -10,8 +10,8 @@ import { import { getChildDebugElement } from '../../../tests/helpers'; import { Operation } from './operation'; -import { SpecManager } from '../../utils/spec-manager';; -import { LazyTasksService } from '../../shared/components/LazyFor/lazy-for';; +import { SpecManager } from '../../utils/spec-manager'; +import { LazyTasksService } from '../../shared/components/LazyFor/lazy-for'; describe('Redoc components', () => { beforeEach(() => { diff --git a/lib/components/Operation/operation.ts b/lib/components/Operation/operation.ts index dc86e7e6..92ee79f1 100644 --- a/lib/components/Operation/operation.ts +++ b/lib/components/Operation/operation.ts @@ -12,6 +12,7 @@ export interface OperationInfo { path: string; info: { tags: string[]; + permissions: string[]; description: string; }; bodyParam: any; @@ -20,7 +21,7 @@ export interface OperationInfo { externalDocs?: { url: string; description?: string; - } + }; } @Component({ @@ -56,7 +57,8 @@ export class Operation extends BaseComponent implements OnInit { path: JsonPointer.baseName(this.pointer, 2), info: { description: this.componentSchema.description, - tags: this.filterMainTags(this.componentSchema.tags) + tags: this.filterMainTags(this.componentSchema.tags), + permissions: this.reduceMainPermissions(this.componentSchema['x-permissions']) }, bodyParam: this.findBodyParam(), summary: SchemaHelper.operationSummary(this.componentSchema), @@ -77,6 +79,17 @@ export class Operation extends BaseComponent implements OnInit { return tags.filter(tag => tagsMap[tag] && tagsMap[tag]['x-traitTag']); } + reduceMainPermissions(permissions) { + var permissionsMap = this.specMgr.getPermissionsMap(); + if (!permissions) return []; + return permissions.reduce(( filtered, permission) => { + if( permissionsMap[permission.name] ) { + filtered.push(permissionsMap[permission.name]); + } + return filtered; + }, []); + } + findBodyParam():SwaggerBodyParameter { let params = this.specMgr.getOperationParams(this.pointer); let bodyParam = params.find(param => param.in === 'body'); diff --git a/lib/components/Permissions/x-permissions.html b/lib/components/Permissions/x-permissions.html new file mode 100644 index 00000000..dc6916a2 --- /dev/null +++ b/lib/components/Permissions/x-permissions.html @@ -0,0 +1,5 @@ +
+

+ {{def.title}}

+
+
diff --git a/lib/components/Permissions/x-permissions.scss b/lib/components/Permissions/x-permissions.scss new file mode 100644 index 00000000..2d2a1da8 --- /dev/null +++ b/lib/components/Permissions/x-permissions.scss @@ -0,0 +1,36 @@ +@import '../../shared/styles/variables'; + +:host { + display: block; +} + +.security-definition:not(:last-of-type) { + border-bottom: 1px solid rgba($text-color, .3); + padding-bottom: 20px; +} + +:host h2 { + padding-top: $section-spacing; +} + +h3 { + margin: 1em 0; + font-size: 1em; +} + +:host .security-scopes-details, :host .security-details { + margin-top: 20px; +} + +table.details th, table.details td { + font-weight: bold; + width: 200px; + max-width: 50%; +} + +table.details th { + text-align: left; + padding: 6px; + text-transform: capitalize; + font-weight: normal; +} diff --git a/lib/components/Permissions/x-permissions.ts b/lib/components/Permissions/x-permissions.ts new file mode 100644 index 00000000..588a1dd8 --- /dev/null +++ b/lib/components/Permissions/x-permissions.ts @@ -0,0 +1,48 @@ +'use strict'; +import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core'; +import { SpecManager, BaseComponent } from '../base'; + +import { ComponentParser } from '../../services/component-parser.service'; + + + +@Component({ + selector: 'x-permissions', + styleUrls: ['./x-permissions.css'], + templateUrl: './x-permissions.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class XPermissions extends BaseComponent implements OnInit { + info: any = {}; + specUrl: String; + defs: any[]; + + static insertTagIntoDescription(md:string) { + if (ComponentParser.contains(md, 'x-permissions')) return md; + if (/^#\s?Permissions\s*$/mi.test(md)) return md; + return md + '\n\n# Permissions \n' + ComponentParser.build('x-permissions'); + } + + constructor(specMgr:SpecManager) { + super(specMgr); + } + + init() { + this.componentSchema = this.componentSchema['x-permissions']; + this.defs = Object.keys(this.componentSchema).map(name => { + let details = this.componentSchema[name]; + let title = details.title ? details.title : name; + details.description = details.description ? details.description : 'none'; + return { + name, + title, + details + }; + }); + + } + + ngOnInit() { + this.preinit(); + } +} diff --git a/lib/components/index.ts b/lib/components/index.ts index 719d20d6..547330a2 100644 --- a/lib/components/index.ts +++ b/lib/components/index.ts @@ -14,6 +14,7 @@ import { OperationsList } from './OperationsList/operations-list'; import { Operation } from './Operation/operation'; import { Warnings } from './Warnings/warnings'; import { SecurityDefinitions } from './SecurityDefinitions/security-definitions'; +import { XPermissions } from './Permissions/x-permissions'; import { LoadingBar } from './LoadingBar/loading-bar'; import { RedocSearch } from './Search/redoc-search'; import { ExternalDocs } from './ExternalDocs/external-docs'; @@ -24,9 +25,9 @@ import { Redoc } from './Redoc/redoc'; export const REDOC_DIRECTIVES = [ ApiInfo, ApiLogo, JsonSchema, JsonSchemaLazy, ParamsList, RequestSamples, ResponsesList, ResponsesSamples, SchemaSample, SideMenu, OperationsList, Operation, Warnings, Redoc, SecurityDefinitions, - LoadingBar, SideMenuItems, RedocSearch, ExternalDocs, EndpointLink + XPermissions, LoadingBar, SideMenuItems, RedocSearch, ExternalDocs, EndpointLink ]; export { ApiInfo, ApiLogo, JsonSchema, JsonSchemaLazy, ParamsList, RequestSamples, ResponsesList, ResponsesSamples, SchemaSample, SideMenu, OperationsList, Operation, Warnings, Redoc, SecurityDefinitions, -LoadingBar, SideMenuItems, ExternalDocs, EndpointLink }; +XPermissions, LoadingBar, SideMenuItems, ExternalDocs, EndpointLink }; diff --git a/lib/redoc.module.ts b/lib/redoc.module.ts index 8fd0372a..9a2bcb82 100644 --- a/lib/redoc.module.ts +++ b/lib/redoc.module.ts @@ -5,10 +5,10 @@ import { CommonModule } from '@angular/common'; import { SpecManager } from './utils/spec-manager'; -import { Redoc, SecurityDefinitions, Operation, REDOC_DIRECTIVES } from './components/index'; +import { Redoc, SecurityDefinitions, XPermissions, Operation, REDOC_DIRECTIVES } from './components/index'; import { REDOC_COMMON_DIRECTIVES, DynamicNg2Wrapper, DropDown } from './shared/components/index'; import { REDOC_PIPES } from './utils/pipes'; -import { CustomErrorHandler } from './utils/' +import { CustomErrorHandler } from './utils/'; import { LazyTasksService } from './shared/components/LazyFor/lazy-for'; import { @@ -31,7 +31,7 @@ import { imports: [ CommonModule ], declarations: [ REDOC_DIRECTIVES, REDOC_COMMON_DIRECTIVES, REDOC_PIPES ], bootstrap: [ Redoc ], - entryComponents: [ SecurityDefinitions, DynamicNg2Wrapper, Operation ], + entryComponents: [ SecurityDefinitions, XPermissions, DynamicNg2Wrapper, Operation ], providers: [ ScrollService, Hash, @@ -42,7 +42,7 @@ import { ContentProjector, { provide: APP_ID, useValue: 'redoc' }, { provide: ErrorHandler, useClass: CustomErrorHandler }, - { provide: COMPONENT_PARSER_ALLOWED, useValue: { 'security-definitions': SecurityDefinitions} } + { provide: COMPONENT_PARSER_ALLOWED, useValue: { 'security-definitions': SecurityDefinitions, 'x-permissions': XPermissions} }, ], exports: [Redoc, REDOC_DIRECTIVES, REDOC_COMMON_DIRECTIVES, REDOC_PIPES] }) diff --git a/lib/utils/spec-manager.ts b/lib/utils/spec-manager.ts index 6a399da4..f8053d3d 100644 --- a/lib/utils/spec-manager.ts +++ b/lib/utils/spec-manager.ts @@ -101,6 +101,13 @@ export class SpecManager { require('../components/SecurityDefinitions/security-definitions').SecurityDefinitions; mdRender.addPreprocessor(SecurityDefinitions.insertTagIntoDescription); } + + if( this._schema['x-permissions']) { + let permissions = + require('../components/Permissions/x-permissions').XPermissions; + mdRender.addPreprocessor(permissions.insertTagIntoDescription); + } + this._schema.info['x-redoc-html-description'] = mdRender.renderMd(this._schema.info.description); this._schema.info['x-redoc-markdown-headers'] = mdRender.headings; } @@ -185,6 +192,23 @@ export class SpecManager { return tagsMap; } + getPermissionsMap() { + let permissions = this._schema['x-permissions'] || []; + var permissionsMap = {}; + for (let key in permissions) { + if( !permissions.hasOwnProperty(key) ) { + continue; + } + permissionsMap[key] = { + name: key, + description: permissions[key].description, + title: permissions[key].title ? permissions[key].title : key + }; + } + + return permissionsMap; + } + findDerivedDefinitions(defPointer: string, schema?: any): DescendantInfo[] { let definition = schema || this.byPointer(defPointer); if (!definition) throw new Error(`Can't load schema at ${defPointer}`); diff --git a/tests/schemas/extended-petstore.yml b/tests/schemas/extended-petstore.yml index ebaf3700..32fffd4b 100644 --- a/tests/schemas/extended-petstore.yml +++ b/tests/schemas/extended-petstore.yml @@ -77,6 +77,8 @@ post: tags: - "pet" + x-permissions: + - name: "admin" summary: "Add a new pet to the store" description: "" operationId: "addPet" @@ -138,6 +140,8 @@ put: tags: - "pet" + x-permissions: + - name: "admin" summary: "Update an existing pet" description: "" operationId: "updatePet" @@ -173,6 +177,9 @@ - "pet" - "Pagination" - "JSONP" + x-permissions: + - name: "admin" + - name: "user" summary: "Finds Pets by status" description: "Multiple status values can be provided with comma seperated strings" operationId: "findPetsByStatus" @@ -214,6 +221,9 @@ - "pet" - "Pagination" - "JSONP" + x-permissions: + - name: "admin" + - name: "user" summary: "Finds Pets by tags" description: "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing." operationId: "findPetsByTags" @@ -249,6 +259,9 @@ tags: - "pet" - "JSONP" + x-permissions: + - name: "admin" + - name: "user" summary: "Find pet by ID" description: "Returns a single pet" operationId: "getPetById" @@ -278,6 +291,8 @@ post: tags: - "pet" + x-permissions: + - name: "admin" summary: "Updates a pet in the store with form data" description: "" operationId: "updatePetWithForm" @@ -317,6 +332,8 @@ delete: tags: - "pet" + x-permissions: + - name: "admin" summary: "Deletes a pet" description: "" operationId: "deletePet" @@ -348,6 +365,8 @@ post: tags: - "pet" + x-permissions: + - name: "admin" summary: "uploads an image" description: "" operationId: "uploadFile" @@ -390,6 +409,8 @@ tags: - "store" - "JSONP" + x-permissions: + - name: "admin" summary: "Returns pet inventories by status" description: "Returns a map of status codes to quantities" operationId: "getInventory" @@ -411,6 +432,8 @@ post: tags: - "store" + x-permissions: + - name: "admin" summary: "Place an order for a pet" description: "" operationId: "placeOrder" @@ -437,6 +460,8 @@ tags: - "store" - "JSONP" + x-permissions: + - name: "admin" summary: "Find purchase order by ID" description: "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions" operationId: "getOrderById" @@ -465,6 +490,8 @@ delete: tags: - "store" + x-permissions: + - name: "admin" summary: "Delete purchase order by ID" description: "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors" operationId: "deleteOrder" @@ -488,6 +515,8 @@ post: tags: - "user" + x-permissions: + - name: "admin" summary: "Create user" description: "This can only be done by the logged in user." operationId: "createUser" @@ -509,6 +538,8 @@ post: tags: - "user" + x-permissions: + - name: "admin" summary: "Creates list of users with given input array" description: "" operationId: "createUsersWithArrayInput" @@ -532,6 +563,8 @@ post: tags: - "user" + x-permissions: + - name: "admin" summary: "Creates list of users with given input array" description: "" operationId: "createUsersWithListInput" @@ -555,6 +588,9 @@ get: tags: - "user" + x-permissions: + - name: "admin" + - name: "user" summary: "Logs user into the system" description: "" operationId: "loginUser" @@ -594,6 +630,9 @@ get: tags: - "user" + x-permissions: + - name: "admin" + - name: "user" summary: "Logs out current logged in user session" description: "" operationId: "logoutUser" @@ -609,6 +648,9 @@ tags: - "user" - "JSONP" + x-permissions: + - name: "admin" + - name: "user" summary: "Get user by user name" description: "" operationId: "getUserByName" @@ -634,6 +676,9 @@ put: tags: - "user" + x-permissions: + - name: "admin" + - name: "user" summary: "Updated user" description: "This can only be done by the logged in user." operationId: "updateUser" @@ -662,6 +707,8 @@ delete: tags: - "user" + x-permissions: + - name: "admin" summary: "Delete user" description: "This can only be done by the logged in user." operationId: "deleteUser" @@ -853,3 +900,11 @@ externalDocs: description: "Find out more about Swagger" url: "http://swagger.io" + x-permissions: + admin: + title: Pet store admin + description: 'Pet store Admin have special privileges on PetStore API allowing them to manage their store and users from their company ' + user: + title: Pet Store user + description: 'Pet store user' + diff --git a/tests/spec-bundle.js b/tests/spec-bundle.js index a3d61d46..bfc3130b 100644 --- a/tests/spec-bundle.js +++ b/tests/spec-bundle.js @@ -52,7 +52,8 @@ beforeEach(function() { services.SearchService, { provide: sharedComponents.LazyTasksService, useClass: sharedComponents.LazyTasksServiceSync }, //{ provide: ErrorHandler, useClass: forwardRef(function() {return services.CustomErrorHandler}) }, - { provide: services.COMPONENT_PARSER_ALLOWED, useValue: { 'security-definitions': components.SecurityDefinitions }} + { provide: services.COMPONENT_PARSER_ALLOWED, useValue: { 'security-definitions': components.SecurityDefinitions }}, + { provide: services.COMPONENT_PARSER_ALLOWED, useValue: { 'x-permissions': components.XPermissions }} ], declarations: [REDOC_PIPES, REDOC_DIRECTIVES, REDOC_COMMON_DIRECTIVES] }); From 88242a06245e1cedc239baaab3a8f869ddc0ac53 Mon Sep 17 00:00:00 2001 From: Vincent Bailleau Date: Wed, 27 Sep 2017 11:13:31 +0200 Subject: [PATCH 2/5] Fix tests injection --- tests/spec-bundle.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/spec-bundle.js b/tests/spec-bundle.js index bfc3130b..1806b358 100644 --- a/tests/spec-bundle.js +++ b/tests/spec-bundle.js @@ -52,14 +52,13 @@ beforeEach(function() { services.SearchService, { provide: sharedComponents.LazyTasksService, useClass: sharedComponents.LazyTasksServiceSync }, //{ provide: ErrorHandler, useClass: forwardRef(function() {return services.CustomErrorHandler}) }, - { provide: services.COMPONENT_PARSER_ALLOWED, useValue: { 'security-definitions': components.SecurityDefinitions }}, - { provide: services.COMPONENT_PARSER_ALLOWED, useValue: { 'x-permissions': components.XPermissions }} + { provide: services.COMPONENT_PARSER_ALLOWED, useValue: { 'security-definitions': components.SecurityDefinitions, 'x-permissions': components.XPermissions }}, ], declarations: [REDOC_PIPES, REDOC_DIRECTIVES, REDOC_COMMON_DIRECTIVES] }); TestBed.overrideModule(BrowserDynamicTestingModule, { set: { - entryComponents: [ sharedComponents.DynamicNg2Wrapper, components.SecurityDefinitions ] + entryComponents: [ sharedComponents.DynamicNg2Wrapper, components.SecurityDefinitions, components.XPermissions ] }, }); }); From a9f6b6c69ba23f6696d958abfc5132a2df4cee51 Mon Sep 17 00:00:00 2001 From: Vincent Bailleau Date: Wed, 25 Oct 2017 13:15:33 +0200 Subject: [PATCH 3/5] Allow a wided range of text content types --- lib/components/SchemaSample/schema-sample.html | 4 ++-- lib/components/SchemaSample/schema-sample.ts | 7 ++++++- lib/utils/helpers.ts | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/components/SchemaSample/schema-sample.html b/lib/components/SchemaSample/schema-sample.html index 27357ef8..baaa3055 100644 --- a/lib/components/SchemaSample/schema-sample.html +++ b/lib/components/SchemaSample/schema-sample.html @@ -11,7 +11,7 @@ - + @@ -23,7 +23,7 @@

     
   
-  
+  
     
Copy diff --git a/lib/components/SchemaSample/schema-sample.ts b/lib/components/SchemaSample/schema-sample.ts index 4bbbe4d9..16737737 100644 --- a/lib/components/SchemaSample/schema-sample.ts +++ b/lib/components/SchemaSample/schema-sample.ts @@ -22,6 +22,7 @@ export class SchemaSample extends BaseComponent implements OnInit { sample: any; xmlSample: string; textSample: string; + textSampleType: string; enableButtons: boolean = false; private _normalizer:SchemaNormalizer; @@ -53,7 +54,11 @@ export class SchemaSample extends BaseComponent implements OnInit { } this.xmlSample = base.examples && getXmlLikeSample(base.examples); - this.textSample = base.examples && getTextLikeSample(base.examples); + let textResult = base.examples && getTextLikeSample(base.examples); + if( textResult ) { + this.textSample = textResult.sample; + this.textSampleType = textResult.type; + } let jsonLikeSample = base.examples && getJsonLikeSample(base.examples); if (jsonLikeSample) { diff --git a/lib/utils/helpers.ts b/lib/utils/helpers.ts index 44f8e4df..e37f602d 100644 --- a/lib/utils/helpers.ts +++ b/lib/utils/helpers.ts @@ -148,7 +148,7 @@ export function isXmlLike(contentType: string): boolean { } export function isTextLike(contentType: string): boolean { - return contentType.search(/text\/plain/i) !== -1; + return contentType.search(/text/i) !== -1; } export function getJsonLikeSample(samples: Object = {}) { @@ -179,5 +179,5 @@ export function getTextLikeSample(samples: Object = {}) { return false; } - return samples[textLikeKeys[0]]; + return { type:textLikeKeys[0], sample: samples[textLikeKeys[0]]}; } From 419788b94e523c63125d1b4b5bf763c7f772e83c Mon Sep 17 00:00:00 2001 From: zucher Date: Tue, 21 Nov 2017 18:21:22 +0100 Subject: [PATCH 4/5] Temporary workaround an issue on slugify See https://github.com/simov/slugify/issues/16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 10f0d117..9d88fcc7 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,7 @@ "prismjs": "^1.8.1", "remarkable": "1.7.1", "scrollparent": "^2.0.1", - "slugify": "^1.2.1", + "slugify": "1.2.1", "stream-http": "^2.6.1", "ts-helpers": "^1.1.2", "zone.js": "^0.8.17" From d466f157fc07d6aadc0e8d8632ddca14d4b8c0c4 Mon Sep 17 00:00:00 2001 From: zucher Date: Tue, 16 Jan 2018 10:37:32 +0100 Subject: [PATCH 5/5] Fix compilation failure --- lib/utils/spec-manager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/spec-manager.ts b/lib/utils/spec-manager.ts index f8053d3d..fb4c3e30 100644 --- a/lib/utils/spec-manager.ts +++ b/lib/utils/spec-manager.ts @@ -66,7 +66,7 @@ export class SpecManager { /* calculate common used values */ init() { - let urlParts = this.specUrl ? urlParse(urlResolve(window.location.href, this.specUrl)) : {}; + let urlParts = this.specUrl ? urlParse(urlResolve(window.location.href, this.specUrl)) : { "protocol" : null, "host": null }; let schemes = this._schema.schemes; let protocol; if (!schemes || !schemes.length) {