diff --git a/src/components/ApiInfo/ApiInfo.tsx b/src/components/ApiInfo/ApiInfo.tsx index 8b5708467d..e3df998b51 100644 --- a/src/components/ApiInfo/ApiInfo.tsx +++ b/src/components/ApiInfo/ApiInfo.tsx @@ -20,9 +20,16 @@ export interface ApiInfoProps { @observer export class ApiInfo extends React.Component { + handleDownloadClick = e => { + if (!e.target.href) { + e.target.href = this.props.store.spec.info.downloadLink; + } + }; + render() { const { store } = this.props; const { info, externalDocs } = store.spec; + const hideDownloadButton = store.options.hideDownloadButton; const downloadFilename = info.downloadFileName; const downloadLink = info.downloadLink; @@ -68,10 +75,15 @@ export class ApiInfo extends React.Component { {info.title} ({info.version}) - {downloadLink && ( + {!hideDownloadButton && (

Download OpenAPI specification: - + Download

diff --git a/src/services/AppStore.ts b/src/services/AppStore.ts index 27603752d2..3ec3433f35 100644 --- a/src/services/AppStore.ts +++ b/src/services/AppStore.ts @@ -15,7 +15,7 @@ export interface StoreState { activeItemIdx: number; }; spec: { - url: string; + url?: string; data: any; }; searchIndex: any; diff --git a/src/services/OpenAPIParser.ts b/src/services/OpenAPIParser.ts index 84a2fc6d11..d757598201 100644 --- a/src/services/OpenAPIParser.ts +++ b/src/services/OpenAPIParser.ts @@ -39,7 +39,7 @@ class RefCounter { * Loads and keeps spec. Provides raw spec operations */ export class OpenAPIParser { - @observable specUrl: string; + @observable specUrl?: string; @observable.ref spec: OpenAPISpec; private _refCounter: RefCounter = new RefCounter(); @@ -57,8 +57,6 @@ export class OpenAPIParser { const href = IS_BROWSER ? window.location.href : ''; if (typeof specUrl === 'string') { this.specUrl = urlResolve(href, specUrl); - } else { - this.specUrl = href; } } diff --git a/src/services/SpecStore.ts b/src/services/SpecStore.ts index 1f9bb1d3d9..b2f210edf6 100644 --- a/src/services/SpecStore.ts +++ b/src/services/SpecStore.ts @@ -22,7 +22,7 @@ export class SpecStore { @computed get info(): ApiInfoModel { - return new ApiInfoModel(this.parser, this.options); + return new ApiInfoModel(this.parser); } @computed diff --git a/src/services/models/ApiInfo.ts b/src/services/models/ApiInfo.ts index 61ba28fec9..6e78b5e131 100644 --- a/src/services/models/ApiInfo.ts +++ b/src/services/models/ApiInfo.ts @@ -11,29 +11,20 @@ export class ApiInfoModel implements OpenAPIInfo { contact?: OpenAPIContact; license?: OpenAPILicense; - constructor(private parser: OpenAPIParser, private options: RedocNormalizedOptions) { + constructor(private parser: OpenAPIParser) { Object.assign(this, parser.spec.info); } - get downloadLink() { - if (this.options.hideDownloadButton) { - return undefined; - } - + get downloadLink(): string | undefined { if (this.parser.specUrl) { return this.parser.specUrl; } - if (IS_BROWSER && window.Blob && window.URL) { + if (IS_BROWSER && window.Blob && window.URL && window.URL.createObjectURL) { const blob = new Blob([JSON.stringify(this.parser.spec, null, 2)], { type: 'application/json', }); return window.URL.createObjectURL(blob); - } else if (!IS_BROWSER) { - return ( - 'data:application/octet-stream;base64,' + - new Buffer(JSON.stringify(this.parser.spec, null, 2)).toString('base64') - ); } } diff --git a/src/services/models/Operation.ts b/src/services/models/Operation.ts index 2db8fad6db..d88059a0ca 100644 --- a/src/services/models/Operation.ts +++ b/src/services/models/Operation.ts @@ -11,6 +11,7 @@ import { OpenAPIExternalDocumentation, OpenAPIServer } from '../../types'; import { getOperationSummary, getStatusCodeType, + IS_BROWSER, isAbsolutePath, isStatusCode, JsonPointer, @@ -148,25 +149,23 @@ export class OperationModel implements IMenuItem { } } -function isNumeric(n) { - return !isNaN(parseFloat(n)) && isFinite(n); -} +function normalizeServers(specUrl: string | undefined, servers: OpenAPIServer[]): OpenAPIServer[] { + const baseUrl = specUrl === undefined ? (IS_BROWSER ? window.location.href : '') : specUrl; -function normalizeServers(specUrl: string, servers: OpenAPIServer[]): OpenAPIServer[] { if (servers.length === 0) { return [ { - url: specUrl, + url: baseUrl, }, ]; } function normalizeUrl(url: string): string { - url = isAbsolutePath(url) ? url : joinPaths(specUrl, url); + url = isAbsolutePath(url) ? url : joinPaths(baseUrl, url); return stripTrailingSlash(url.startsWith('//') ? `${specProtocol}${url}` : url); } - const { protocol: specProtocol } = urlParse(specUrl); + const { protocol: specProtocol } = urlParse(baseUrl); return servers.map(server => { return {