From f903406c14cfc0410c32aefd1ca1fa9851e385ce Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Fri, 17 Aug 2018 14:17:16 +0300 Subject: [PATCH] fix: use correct parent section for security definition --- src/services/MenuBuilder.ts | 23 ++++++++++++++++++---- src/services/MenuStore.ts | 5 ++++- src/services/OpenAPIParser.ts | 6 +++--- src/services/models/SecurityRequirement.ts | 4 ++-- src/services/models/SecuritySchemes.ts | 4 ++-- src/utils/openapi.ts | 6 +++++- 6 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/services/MenuBuilder.ts b/src/services/MenuBuilder.ts index f1791bf8..6dab0cb8 100644 --- a/src/services/MenuBuilder.ts +++ b/src/services/MenuBuilder.ts @@ -1,5 +1,9 @@ import { OpenAPIOperation, OpenAPIParameter, OpenAPISpec, OpenAPITag, Referenced } from '../types'; -import { isOperationName } from '../utils'; +import { + isOperationName, + SECURITY_DEFINITIONS_COMPONENT_NAME, + setSecuritySchemePrefix, +} from '../utils'; import { MarkdownRenderer } from './MarkdownRenderer'; import { GroupModel, OperationModel } from './models'; import { OpenAPIParser } from './OpenAPIParser'; @@ -38,7 +42,7 @@ export class MenuBuilder { const items: ContentItemModel[] = []; const tagsMap = MenuBuilder.getTagsWithOperations(spec); - items.push(...MenuBuilder.addMarkdownItems(spec.info.description || '')); + items.push(...MenuBuilder.addMarkdownItems(spec.info.description || '', options)); if (spec['x-tagGroups']) { items.push( ...MenuBuilder.getTagGroupsItems(parser, undefined, spec['x-tagGroups'], tagsMap, options), @@ -53,8 +57,11 @@ export class MenuBuilder { * extracts items from markdown description * @param description - markdown source */ - static addMarkdownItems(description: string): ContentItemModel[] { - const renderer = new MarkdownRenderer(); + static addMarkdownItems( + description: string, + options: RedocNormalizedOptions, + ): ContentItemModel[] { + const renderer = new MarkdownRenderer(options); const headings = renderer.extractHeadings(description || ''); const mapHeadingsDeep = (parent, items, depth = 1) => @@ -64,6 +71,14 @@ export class MenuBuilder { if (heading.items) { group.items = mapHeadingsDeep(group, heading.items, depth + 1); } + if ( + MarkdownRenderer.containsComponent( + group.description || '', + SECURITY_DEFINITIONS_COMPONENT_NAME, + ) + ) { + setSecuritySchemePrefix(group.id + '/'); + } return group; }); diff --git a/src/services/MenuStore.ts b/src/services/MenuStore.ts index e4fd4d43..3595e152 100644 --- a/src/services/MenuStore.ts +++ b/src/services/MenuStore.ts @@ -145,9 +145,12 @@ export class MenuStore { if (item) { this.activateAndScroll(item, false); } else { + if (hash.startsWith(SECURITY_SCHEMES_SECTION_PREFIX)) { + item = this.flatItems.find(i => SECURITY_SCHEMES_SECTION_PREFIX.startsWith(i.id)); + this.activate(item); + } this.scroll.scrollIntoViewBySelector(`[${SECTION_ATTR}="${hash}"]`); } - return item !== undefined; }; /** diff --git a/src/services/OpenAPIParser.ts b/src/services/OpenAPIParser.ts index 654cfcdb..b4f67335 100644 --- a/src/services/OpenAPIParser.ts +++ b/src/services/OpenAPIParser.ts @@ -4,7 +4,7 @@ import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types'; import { appendToMdHeading, IS_BROWSER } from '../utils/'; import { JsonPointer } from '../utils/JsonPointer'; -import { isNamedDefinition } from '../utils/openapi'; +import { isNamedDefinition, SECURITY_DEFINITIONS_COMPONENT_NAME } from '../utils/openapi'; import { buildComponentComment, MarkdownRenderer } from './MarkdownRenderer'; import { RedocNormalizedOptions } from './RedocNormalizedOptions'; @@ -74,8 +74,8 @@ export class OpenAPIParser { ) { // Automatically inject Authentication section with SecurityDefinitions component const description = spec.info.description || ''; - if (!MarkdownRenderer.containsComponent(description, 'security-definitions')) { - const comment = buildComponentComment('security-definitions'); + if (!MarkdownRenderer.containsComponent(description, SECURITY_DEFINITIONS_COMPONENT_NAME)) { + const comment = buildComponentComment(SECURITY_DEFINITIONS_COMPONENT_NAME); spec.info.description = appendToMdHeading(description, 'Authentication', comment); } } diff --git a/src/services/models/SecurityRequirement.ts b/src/services/models/SecurityRequirement.ts index e7c57663..0fc62a79 100644 --- a/src/services/models/SecurityRequirement.ts +++ b/src/services/models/SecurityRequirement.ts @@ -1,5 +1,5 @@ import { OpenAPISecurityRequirement, OpenAPISecurityScheme } from '../../types'; -import { SECURITY_SCHEMES_SECTION } from '../../utils/openapi'; +import { SECURITY_SCHEMES_SECTION_PREFIX } from '../../utils/openapi'; import { OpenAPIParser } from '../OpenAPIParser'; export interface SecurityScheme extends OpenAPISecurityScheme { @@ -27,7 +27,7 @@ export class SecurityRequirementModel { return { ...scheme, id, - sectionId: SECURITY_SCHEMES_SECTION + id, + sectionId: SECURITY_SCHEMES_SECTION_PREFIX + id, scopes, }; }) diff --git a/src/services/models/SecuritySchemes.ts b/src/services/models/SecuritySchemes.ts index 7b8452be..fc5deda8 100644 --- a/src/services/models/SecuritySchemes.ts +++ b/src/services/models/SecuritySchemes.ts @@ -1,5 +1,5 @@ import { OpenAPISecurityScheme, Referenced } from '../../types'; -import { SECURITY_SCHEMES_SECTION } from '../../utils/openapi'; +import { SECURITY_SCHEMES_SECTION_PREFIX } from '../../utils/openapi'; import { OpenAPIParser } from '../OpenAPIParser'; export class SecuritySchemeModel { @@ -25,7 +25,7 @@ export class SecuritySchemeModel { constructor(parser: OpenAPIParser, id: string, scheme: Referenced) { const info = parser.deref(scheme); this.id = id; - this.sectionId = SECURITY_SCHEMES_SECTION + id; + this.sectionId = SECURITY_SCHEMES_SECTION_PREFIX + id; this.type = info.type; this.description = info.description || ''; if (info.type === 'apiKey') { diff --git a/src/utils/openapi.ts b/src/utils/openapi.ts index 080d010f..7cc6618b 100644 --- a/src/utils/openapi.ts +++ b/src/utils/openapi.ts @@ -275,4 +275,8 @@ export function normalizeServers( }); } -export const SECURITY_SCHEMES_SECTION = 'section/Authentication/'; +export const SECURITY_DEFINITIONS_COMPONENT_NAME = 'security-definitions'; +export let SECURITY_SCHEMES_SECTION_PREFIX = 'section/Authentication/'; +export function setSecuritySchemePrefix(prefix: string) { + SECURITY_SCHEMES_SECTION_PREFIX = prefix; +}