feat: Add download file option (#1699)

Co-authored-by: Zach Whaley <zachbwhaley@gmail.com>
Co-authored-by: Roman Hotsiy <gotsijroman@gmail.com>
Co-authored-by: anastasiia-developer <anastasiia@redocly.com>
Co-authored-by: Ivana Isadora Devcic <33730345+skadinna@users.noreply.github.com>
This commit is contained in:
Zach Whaley 2022-05-10 12:09:01 -05:00 committed by GitHub
parent 494122f93e
commit b601c9ae9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 116 additions and 5 deletions

View File

@ -213,6 +213,8 @@ You can use all of the following options with the standalone version of the <red
* `generatedPayloadSamplesMaxDepth` - set the maximum render depth for JSON payload samples (responses and request body). The default value is `10`.
* `maxDisplayedEnumValues` - display only specified number of enum values. hide rest values under spoiler.
* `hideDownloadButton` - do not show "Download" spec button. **THIS DOESN'T MAKE YOUR SPEC PRIVATE**, it just hides the button.
* `downloadFileName` - set a custom file name for the downloaded API definition file.
* `downloadDefinitionUrl` - If the 'Download' button is visible in the API reference documentation (hideDownloadButton=false), the URL configured here will open when that button is selected. Provide it as an absolute URL with the full URI scheme.
* `hideHostname` - if set, the protocol and hostname is not shown in the operation definition.
* `hideLoading` - do not show loading animation. Useful for small docs.
* `hideFab` - do not show FAB in mobile view. Useful for implementing a custom floating action button.

View File

@ -77,6 +77,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"options": RedocNormalizedOptions {
"allowedMdComponents": Object {},
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": Object {},
@ -329,6 +331,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"options": RedocNormalizedOptions {
"allowedMdComponents": Object {},
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": Object {},
@ -556,6 +560,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"options": RedocNormalizedOptions {
"allowedMdComponents": Object {},
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": Object {},
@ -850,6 +856,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"options": RedocNormalizedOptions {
"allowedMdComponents": Object {},
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": Object {},
@ -1102,6 +1110,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"options": RedocNormalizedOptions {
"allowedMdComponents": Object {},
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": Object {},
@ -1329,6 +1339,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"options": RedocNormalizedOptions {
"allowedMdComponents": Object {},
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": Object {},
@ -1579,6 +1591,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"options": RedocNormalizedOptions {
"allowedMdComponents": Object {},
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": Object {},
@ -1870,6 +1884,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"options": RedocNormalizedOptions {
"allowedMdComponents": Object {},
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": Object {},
@ -2122,6 +2138,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"options": RedocNormalizedOptions {
"allowedMdComponents": Object {},
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": Object {},
@ -2349,6 +2367,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"options": RedocNormalizedOptions {
"allowedMdComponents": Object {},
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": Object {},

View File

@ -27,6 +27,8 @@ export interface RedocRawOptions {
untrustedSpec?: boolean | string;
hideLoading?: boolean | string;
hideDownloadButton?: boolean | string;
downloadFileName?: string;
downloadDefinitionUrl?: string;
disableSearch?: boolean | string;
onlyRequiredInSamples?: boolean | string;
showExtensions?: boolean | string | string[];
@ -226,6 +228,8 @@ export class RedocNormalizedOptions {
pathInMiddlePanel: boolean;
untrustedSpec: boolean;
hideDownloadButton: boolean;
downloadFileName?: string;
downloadDefinitionUrl?: string;
disableSearch: boolean;
onlyRequiredInSamples: boolean;
showExtensions: boolean | string[];
@ -293,6 +297,8 @@ export class RedocNormalizedOptions {
this.pathInMiddlePanel = argValueToBoolean(raw.pathInMiddlePanel);
this.untrustedSpec = argValueToBoolean(raw.untrustedSpec);
this.hideDownloadButton = argValueToBoolean(raw.hideDownloadButton);
this.downloadFileName = raw.downloadFileName;
this.downloadDefinitionUrl = raw.downloadDefinitionUrl;
this.disableSearch = argValueToBoolean(raw.disableSearch);
this.onlyRequiredInSamples = argValueToBoolean(raw.onlyRequiredInSamples);
this.showExtensions = RedocNormalizedOptions.normalizeShowExtensions(raw.showExtensions);

View File

@ -24,7 +24,7 @@ export class SpecStore {
private options: RedocNormalizedOptions,
) {
this.parser = new OpenAPIParser(spec, specUrl, options);
this.info = new ApiInfoModel(this.parser);
this.info = new ApiInfoModel(this.parser, this.options);
this.externalDocs = this.parser.spec.externalDocs;
this.contentItems = MenuBuilder.buildStructure(this.parser, this.options);
this.securitySchemes = new SecuritySchemesModel(this.parser);

View File

@ -62,5 +62,80 @@ describe('Models', () => {
const { license = { identifier: null } } = new ApiInfoModel(parser);
expect(license.identifier).toEqual('MIT');
});
test('should correctly populate default download file name', () => {
parser.spec = {
openapi: '3.0.0',
info: {
description: 'Test description',
},
} as any;
const info = new ApiInfoModel(parser);
expect(info.downloadFileName).toEqual('openapi.json');
});
test('should correctly populate default download file is undefined when using specUrl', () => {
parser = new OpenAPIParser(
{
openapi: '3.0.0',
info: {
description: 'Test description',
},
} as any,
'/demo/openapi.yaml',
opts,
);
const info = new ApiInfoModel(parser);
expect(info.downloadFileName).toEqual(undefined);
});
test('should correctly populate download file name', () => {
parser.spec = {
info: {
description: 'Test description',
},
} as any;
const opts = new RedocNormalizedOptions({
downloadFileName: 'test.yaml',
});
const info = new ApiInfoModel(parser, opts);
expect(info.downloadFileName).toEqual('test.yaml');
});
test('should correctly populate download link', () => {
parser.spec = {
openapi: '3.0.0',
info: {
description: 'Test description',
},
} as any;
const opts = new RedocNormalizedOptions({
downloadDefinitionUrl: 'https:test.com/filename.yaml',
});
const info = new ApiInfoModel(parser, opts);
expect(info.downloadLink).toEqual('https:test.com/filename.yaml');
});
test('should correctly populate download link and download file name', () => {
parser.spec = {
openapi: '3.0.0',
info: {
description: 'Test description',
},
} as any;
const opts = new RedocNormalizedOptions({
downloadDefinitionUrl: 'https:test.com/filename.yaml',
downloadFileName: 'test.yaml',
});
const info = new ApiInfoModel(parser, opts);
expect(info.downloadLink).toEqual('https:test.com/filename.yaml');
expect(info.downloadFileName).toEqual('test.yaml');
});
});
});

View File

@ -1,6 +1,7 @@
import { OpenAPIContact, OpenAPIInfo, OpenAPILicense } from '../../types';
import { IS_BROWSER } from '../../utils/';
import { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
export class ApiInfoModel implements OpenAPIInfo {
title: string;
@ -15,7 +16,10 @@ export class ApiInfoModel implements OpenAPIInfo {
downloadLink?: string;
downloadFileName?: string;
constructor(private parser: OpenAPIParser) {
constructor(
private parser: OpenAPIParser,
private options: RedocNormalizedOptions = new RedocNormalizedOptions({}),
) {
Object.assign(this, parser.spec.info);
this.description = parser.spec.info.description || '';
this.summary = parser.spec.info.summary || '';
@ -30,6 +34,10 @@ export class ApiInfoModel implements OpenAPIInfo {
}
private getDownloadLink(): string | undefined {
if (this.options.downloadDefinitionUrl) {
return this.options.downloadDefinitionUrl;
}
if (this.parser.specUrl) {
return this.parser.specUrl;
}
@ -43,9 +51,9 @@ export class ApiInfoModel implements OpenAPIInfo {
}
private getDownloadFileName(): string | undefined {
if (!this.parser.specUrl) {
return 'swagger.json';
if (!this.parser.specUrl && !this.options.downloadDefinitionUrl) {
return this.options.downloadFileName || 'openapi.json';
}
return undefined;
return this.options.downloadFileName;
}
}