diff --git a/src/components/SideMenu/MenuItem.tsx b/src/components/SideMenu/MenuItem.tsx index 8b418aad..6f836fff 100644 --- a/src/components/SideMenu/MenuItem.tsx +++ b/src/components/SideMenu/MenuItem.tsx @@ -40,7 +40,12 @@ export class MenuItem extends React.Component { render() { const { item, withoutChildren } = this.props; return ( - + {item.type === 'operation' ? ( ) : ( diff --git a/src/components/SideMenu/styled.elements.ts b/src/components/SideMenu/styled.elements.ts index f400b170..7a8786e7 100644 --- a/src/components/SideMenu/styled.elements.ts +++ b/src/components/SideMenu/styled.elements.ts @@ -83,12 +83,12 @@ export const MenuItemUl = styled.ul<{ expanded: boolean }>` ${props => (props.expanded ? '' : 'display: none;')}; `; -export const MenuItemLi = styled.li<{ depth: number }>` +export const MenuItemLi = styled.li<{ depth: number; topMargin?: boolean }>` list-style: none inside none; overflow: hidden; text-overflow: ellipsis; padding: 0; - ${props => (props.depth === 0 ? 'margin-top: 15px' : '')}; + ${props => (props.depth === 0 || props.topMargin ? 'margin-top: 15px' : '')}; `; export const menuItemDepth = { diff --git a/src/services/MenuBuilder.ts b/src/services/MenuBuilder.ts index 203b5fa6..dd1104d1 100644 --- a/src/services/MenuBuilder.ts +++ b/src/services/MenuBuilder.ts @@ -12,7 +12,6 @@ import { setSecuritySchemePrefix, JsonPointer, extractContent, - removeContent, } from '../utils'; import { MarkdownRenderer } from './MarkdownRenderer'; import { GroupModel, OperationModel } from './models'; @@ -55,14 +54,18 @@ export class MenuBuilder { const items: ContentItemModel[] = []; const tagsMap = MenuBuilder.getTagsWithOperations(spec); - let setionToTheEnd = ''; + let sectionsBefore = ''; + let sectionsAfter = ''; - options.sectionsAtTheEnd.forEach(function(s) { - setionToTheEnd += extractContent(spec.info.description || '', s); - spec.info.description = removeContent(spec.info.description || '', s); + new MarkdownRenderer(options).extractHeadings(spec.info.description || '').forEach(function(h) { + if (options.sectionsAtTheEnd.includes(h.name)) { + sectionsAfter += extractContent(spec.info.description || '', h.name); + } else { + sectionsBefore += extractContent(spec.info.description || '', h.name); + } }); - items.push(...MenuBuilder.addMarkdownItems(spec.info.description || '', undefined, 1, options)); + items.push(...MenuBuilder.addMarkdownItems(sectionsBefore, undefined, 1, options)); if (spec['x-tagGroups'] && spec['x-tagGroups'].length > 0) { items.push( ...MenuBuilder.getTagGroupsItems(parser, undefined, spec['x-tagGroups'], tagsMap, options), @@ -71,7 +74,15 @@ export class MenuBuilder { items.push(...MenuBuilder.getTagsItems(parser, tagsMap, undefined, undefined, options)); } - items.push(...MenuBuilder.addMarkdownItems(setionToTheEnd, undefined, 1, options)); + items.push( + ...MenuBuilder.addMarkdownItems( + sectionsAfter, + undefined, + 1, + options, + spec['x-tagGroups'] && spec['x-tagGroups'].length > 0, // If tagGroups, add topMargin to side menu item + ), + ); return items; } @@ -85,6 +96,7 @@ export class MenuBuilder { parent: GroupModel | undefined, initialDepth: number, options: RedocNormalizedOptions, + topMargin: boolean = false, ): ContentItemModel[] { const renderer = new MarkdownRenderer(options); const headings = renderer.extractHeadings(description || ''); @@ -99,6 +111,10 @@ export class MenuBuilder { const mapHeadingsDeep = (_parent, items, depth = 1) => items.map(heading => { const group = new GroupModel('section', heading, _parent); + if (topMargin) { + group.topMargin = true; + topMargin = false; + } group.depth = depth; if (heading.items) { group.items = mapHeadingsDeep(group, heading.items, depth + 1); diff --git a/src/services/MenuStore.ts b/src/services/MenuStore.ts index 2a619af6..40f09860 100644 --- a/src/services/MenuStore.ts +++ b/src/services/MenuStore.ts @@ -24,6 +24,7 @@ export interface IMenuItem { parent?: IMenuItem; deprecated?: boolean; type: MenuItemType; + topMargin?: boolean; deactivate(): void; activate(): void; diff --git a/src/services/models/Group.model.ts b/src/services/models/Group.model.ts index be3fc479..cd5ef038 100644 --- a/src/services/models/Group.model.ts +++ b/src/services/models/Group.model.ts @@ -28,6 +28,7 @@ export class GroupModel implements IMenuItem { depth: number; level: number; + topMargin: boolean; //#endregion constructor( diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index bc37ad38..9d318ad3 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -94,17 +94,6 @@ export function extractContent(md: string, heading: string): string { return ''; } -export function removeContent(md: string, heading: string): string { - // remove the content of section with given heading - 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, ''); - } - - return md; -} - // credits https://stackoverflow.com/a/46973278/1749888 export const mergeObjects = (target: any, ...sources: any[]): any => { if (!sources.length) {