diff --git a/src/components/Schema/__tests__/DiscriminatorDropdown.test.tsx b/src/components/Schema/__tests__/DiscriminatorDropdown.test.tsx
index 609403ec..40757339 100644
--- a/src/components/Schema/__tests__/DiscriminatorDropdown.test.tsx
+++ b/src/components/Schema/__tests__/DiscriminatorDropdown.test.tsx
@@ -8,30 +8,31 @@ import { Schema } from '../Schema';
import { ObjectSchema } from '../ObjectSchema';
import * as simpleDiscriminatorFixture from './fixtures/simple-discriminator.json';
+const options = new RedocNormalizedOptions({});
describe('Components', () => {
describe('SchemaView', () => {
describe('discriminator', () => {
it('should correctly render SchemaView', () => {
- const parser = new OpenAPIParser(simpleDiscriminatorFixture);
+ const parser = new OpenAPIParser(simpleDiscriminatorFixture, undefined, options);
const schema = new SchemaModel(
parser,
{ $ref: '#/components/schemas/Pet' },
'#/components/schemas/Pet',
- new RedocNormalizedOptions({}),
+ options,
);
const schemaView = shallow();
expect(toJson(schemaView)).toMatchSnapshot();
});
it('should correctly render discriminator dropdown', () => {
- const parser = new OpenAPIParser(simpleDiscriminatorFixture);
+ const parser = new OpenAPIParser(simpleDiscriminatorFixture, undefined, options);
const schema = new SchemaModel(
parser,
{ $ref: '#/components/schemas/Pet' },
'#/components/schemas/Pet',
- new RedocNormalizedOptions({}),
+ options,
);
const schemaView = shallow(
-->`;
+}
type MarkdownHeading = {
name: string;
diff --git a/src/services/OpenAPIParser.ts b/src/services/OpenAPIParser.ts
index 34beccb7..98d8bca0 100644
--- a/src/services/OpenAPIParser.ts
+++ b/src/services/OpenAPIParser.ts
@@ -5,6 +5,9 @@ import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types';
import { JsonPointer } from '../utils/JsonPointer';
import { isNamedDefinition } from '../utils/openapi';
+import { COMPONENT_REGEXP, buildComponentComment } from './MarkdownRenderer';
+import { RedocNormalizedOptions } from './RedocNormalizedOptions';
+import { appendToMdHeading } from '../utils/index';
export type MergedOpenAPISchema = OpenAPISchema & { namedParents?: string[] };
@@ -39,8 +42,13 @@ export class OpenAPIParser {
@observable specUrl: string;
@observable.ref spec: OpenAPISpec;
- constructor(spec: OpenAPISpec, specUrl?: string) {
+ constructor(
+ spec: OpenAPISpec,
+ specUrl: string | undefined,
+ private options: RedocNormalizedOptions,
+ ) {
this.validate(spec);
+ this.preprocess(spec);
this.spec = spec;
@@ -59,6 +67,22 @@ export class OpenAPIParser {
}
}
+ preprocess(spec: OpenAPISpec) {
+ if (!this.options.noAutoAuth && spec.info) {
+ // Automatically inject Authentication section with SecurityDefinitions component
+ const description = spec.info.description || '';
+ const securityRegexp = new RegExp(
+ COMPONENT_REGEXP.replace('{component}', ''),
+ 'gmi',
+ );
+ debugger;
+ if (!securityRegexp.test(description)) {
+ const comment = buildComponentComment('security-definitions');
+ spec.info.description = appendToMdHeading(description, 'Authentication', comment);
+ }
+ }
+ }
+
/**
* get spec part by JsonPointer ($ref)
*/
diff --git a/src/services/RedocNormalizedOptions.ts b/src/services/RedocNormalizedOptions.ts
index 4a1b98c8..8bce7980 100644
--- a/src/services/RedocNormalizedOptions.ts
+++ b/src/services/RedocNormalizedOptions.ts
@@ -8,6 +8,7 @@ export interface RedocRawOptions {
hideHostname?: boolean | string;
expandResponses?: string | 'all';
requiredPropsFirst?: boolean | string;
+ noAutoAuth?: boolean | string;
}
function argValueToBoolean(val?: string | boolean): boolean {
@@ -22,6 +23,7 @@ export class RedocNormalizedOptions {
hideHostname: boolean;
expandResponses: { [code: string]: boolean } | 'all';
requiredPropsFirst: boolean;
+ noAutoAuth: boolean;
constructor(raw: RedocRawOptions) {
this.theme = { ...(raw.theme || {}), ...defaultTheme }; // todo: merge deep
@@ -29,6 +31,7 @@ export class RedocNormalizedOptions {
this.hideHostname = RedocNormalizedOptions.normalizeHideHostname(raw.hideHostname);
this.expandResponses = RedocNormalizedOptions.normalizeExpandResponses(raw.expandResponses);
this.requiredPropsFirst = argValueToBoolean(raw.requiredPropsFirst);
+ this.noAutoAuth = argValueToBoolean(raw.noAutoAuth);
}
static normalizeExpandResponses(value: RedocRawOptions['expandResponses']) {
diff --git a/src/services/SpecStore.ts b/src/services/SpecStore.ts
index 69a8ee22..33fbdd95 100644
--- a/src/services/SpecStore.ts
+++ b/src/services/SpecStore.ts
@@ -19,7 +19,7 @@ export class SpecStore {
specUrl: string | undefined,
private options: RedocNormalizedOptions,
) {
- this.parser = new OpenAPIParser(spec, specUrl);
+ this.parser = new OpenAPIParser(spec, specUrl, options);
}
@computed
diff --git a/src/services/__tests__/models/Response.test.ts b/src/services/__tests__/models/Response.test.ts
index 5f433012..77b861bb 100644
--- a/src/services/__tests__/models/Response.test.ts
+++ b/src/services/__tests__/models/Response.test.ts
@@ -8,7 +8,7 @@ describe('Models', () => {
let parser;
beforeEach(() => {
- parser = new OpenAPIParser({ openapi: '3.0.0' } as any);
+ parser = new OpenAPIParser({ openapi: '3.0.0' } as any, undefined, opts);
});
test('should calculate response type based on code', () => {
diff --git a/src/utils/__tests__/helpers.test.ts b/src/utils/__tests__/helpers.test.ts
index 0d3e3947..8a18b84a 100644
--- a/src/utils/__tests__/helpers.test.ts
+++ b/src/utils/__tests__/helpers.test.ts
@@ -1,4 +1,4 @@
-import { mapWithLast } from '../helpers';
+import { mapWithLast, appendToMdHeading } from '../helpers';
describe('Utils', () => {
describe('helpers', () => {
@@ -19,5 +19,24 @@ describe('Utils', () => {
const expected = [];
expect(actual).toEqual(expected);
});
+
+ test('appendToMdHeading heading exists not last', () => {
+ const val = appendToMdHeading(
+ '# Authentication\n Hello\n# Next heading',
+ 'Authentication',
+ '',
+ );
+ expect(val).toEqual('# Authentication\n Hello\n\n\n\n# Next heading');
+ });
+
+ test('appendToMdHeading heading exists last', () => {
+ const val = appendToMdHeading('# Authentication\n Hello', 'Authentication', '');
+ expect(val).toEqual('# Authentication\n Hello\n\n\n');
+ });
+
+ test('appendToMdHeading empty string', () => {
+ const val = appendToMdHeading('', 'Authentication', '');
+ expect(val).toEqual('# Authentication\n\n');
+ });
});
});
diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts
index ccd39562..8452669f 100644
--- a/src/utils/helpers.ts
+++ b/src/utils/helpers.ts
@@ -67,3 +67,16 @@ export function isAbsolutePath(path: string): boolean {
export function isNumeric(n: any): n is Number {
return !isNaN(parseFloat(n)) && isFinite(n);
}
+
+export function appendToMdHeading(md: string, heading: string, content: string) {
+ // if heading is already in md and append to the end of it
+ const testRegex = new RegExp(`(^|\\n)#\\s?${heading}\\s*\\n`, 'i');
+ const replaceRegex = new RegExp(`((\\n|^)#\\s*${heading}\\s*(\\n|$)(?:.|\\n)*?)(\\n#|$)`, 'i');
+ if (testRegex.test(md)) {
+ return md.replace(replaceRegex, `$1\n\n${content}\n$4`);
+ } else {
+ // else append heading itself
+ const br = md === '' || md.endsWith('\n\n') ? '' : md.endsWith('\n') ? '\n' : '\n\n';
+ return `${md}${br}# ${heading}\n\n${content}`;
+ }
+}