fix: simplified section spliting and added side menu top margin to side menu item if tag groups

This commit is contained in:
Roberto Fernández 2020-06-29 17:48:54 +02:00
parent 2996e947e9
commit 01910e0622
6 changed files with 33 additions and 21 deletions

View File

@ -40,7 +40,12 @@ export class MenuItem extends React.Component<MenuItemProps> {
render() { render() {
const { item, withoutChildren } = this.props; const { item, withoutChildren } = this.props;
return ( return (
<MenuItemLi onClick={this.activate} depth={item.depth} data-item-id={item.id}> <MenuItemLi
onClick={this.activate}
depth={item.depth}
data-item-id={item.id}
topMargin={item.topMargin}
>
{item.type === 'operation' ? ( {item.type === 'operation' ? (
<OperationMenuItemContent {...this.props} item={item as OperationModel} /> <OperationMenuItemContent {...this.props} item={item as OperationModel} />
) : ( ) : (

View File

@ -83,12 +83,12 @@ export const MenuItemUl = styled.ul<{ expanded: boolean }>`
${props => (props.expanded ? '' : 'display: none;')}; ${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; list-style: none inside none;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
padding: 0; padding: 0;
${props => (props.depth === 0 ? 'margin-top: 15px' : '')}; ${props => (props.depth === 0 || props.topMargin ? 'margin-top: 15px' : '')};
`; `;
export const menuItemDepth = { export const menuItemDepth = {

View File

@ -12,7 +12,6 @@ import {
setSecuritySchemePrefix, setSecuritySchemePrefix,
JsonPointer, JsonPointer,
extractContent, extractContent,
removeContent,
} from '../utils'; } from '../utils';
import { MarkdownRenderer } from './MarkdownRenderer'; import { MarkdownRenderer } from './MarkdownRenderer';
import { GroupModel, OperationModel } from './models'; import { GroupModel, OperationModel } from './models';
@ -55,14 +54,18 @@ export class MenuBuilder {
const items: ContentItemModel[] = []; const items: ContentItemModel[] = [];
const tagsMap = MenuBuilder.getTagsWithOperations(spec); const tagsMap = MenuBuilder.getTagsWithOperations(spec);
let setionToTheEnd = ''; let sectionsBefore = '';
let sectionsAfter = '';
options.sectionsAtTheEnd.forEach(function(s) { new MarkdownRenderer(options).extractHeadings(spec.info.description || '').forEach(function(h) {
setionToTheEnd += extractContent(spec.info.description || '', s); if (options.sectionsAtTheEnd.includes(h.name)) {
spec.info.description = removeContent(spec.info.description || '', s); 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) { if (spec['x-tagGroups'] && spec['x-tagGroups'].length > 0) {
items.push( items.push(
...MenuBuilder.getTagGroupsItems(parser, undefined, spec['x-tagGroups'], tagsMap, options), ...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.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; return items;
} }
@ -85,6 +96,7 @@ export class MenuBuilder {
parent: GroupModel | undefined, parent: GroupModel | undefined,
initialDepth: number, initialDepth: number,
options: RedocNormalizedOptions, options: RedocNormalizedOptions,
topMargin: boolean = false,
): ContentItemModel[] { ): ContentItemModel[] {
const renderer = new MarkdownRenderer(options); const renderer = new MarkdownRenderer(options);
const headings = renderer.extractHeadings(description || ''); const headings = renderer.extractHeadings(description || '');
@ -99,6 +111,10 @@ export class MenuBuilder {
const mapHeadingsDeep = (_parent, items, depth = 1) => const mapHeadingsDeep = (_parent, items, depth = 1) =>
items.map(heading => { items.map(heading => {
const group = new GroupModel('section', heading, _parent); const group = new GroupModel('section', heading, _parent);
if (topMargin) {
group.topMargin = true;
topMargin = false;
}
group.depth = depth; group.depth = depth;
if (heading.items) { if (heading.items) {
group.items = mapHeadingsDeep(group, heading.items, depth + 1); group.items = mapHeadingsDeep(group, heading.items, depth + 1);

View File

@ -24,6 +24,7 @@ export interface IMenuItem {
parent?: IMenuItem; parent?: IMenuItem;
deprecated?: boolean; deprecated?: boolean;
type: MenuItemType; type: MenuItemType;
topMargin?: boolean;
deactivate(): void; deactivate(): void;
activate(): void; activate(): void;

View File

@ -28,6 +28,7 @@ export class GroupModel implements IMenuItem {
depth: number; depth: number;
level: number; level: number;
topMargin: boolean;
//#endregion //#endregion
constructor( constructor(

View File

@ -94,17 +94,6 @@ export function extractContent(md: string, heading: string): string {
return ''; 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 // credits https://stackoverflow.com/a/46973278/1749888
export const mergeObjects = (target: any, ...sources: any[]): any => { export const mergeObjects = (target: any, ...sources: any[]): any => {
if (!sources.length) { if (!sources.length) {