mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-10 19:06:34 +03:00
add section menus for tags and object description
This commit is contained in:
parent
7db7d4fc91
commit
4359724434
|
@ -58,9 +58,21 @@ externalDocs:
|
|||
url: 'https://github.com/Rebilly/generator-openapi-repo'
|
||||
tags:
|
||||
- name: pet
|
||||
description: Everything about your Pets
|
||||
description: |
|
||||
Everything about your Pets
|
||||
|
||||
## The Pet Object
|
||||
|
||||
<object-description schemaRef="#/components/schemas/Pet" />
|
||||
|
||||
- name: store
|
||||
description: Access to Petstore orders
|
||||
description: |
|
||||
Access to Petstore orders
|
||||
|
||||
## The Order Object
|
||||
|
||||
<object-description schemaRef="#/components/schemas/Order" examplesRef="#/components/examples/Order" />
|
||||
|
||||
- name: user
|
||||
description: Operations about user
|
||||
x-tagGroups:
|
||||
|
@ -926,3 +938,10 @@ components:
|
|||
type: apiKey
|
||||
name: api_key
|
||||
in: header
|
||||
examples:
|
||||
Order:
|
||||
value:
|
||||
quantity: 1,
|
||||
shipDate: 2018-10-19T16:46:45Z,
|
||||
status: placed,
|
||||
complete: false
|
||||
|
|
64
src/components/ObjectDescription/ObjectDescription.tsx
Normal file
64
src/components/ObjectDescription/ObjectDescription.tsx
Normal file
|
@ -0,0 +1,64 @@
|
|||
import * as React from 'react';
|
||||
import { Schema } from '../Schema';
|
||||
|
||||
import { MiddlePanel, Row, Section, DarkRightPanel } from '../../common-elements';
|
||||
import { OpenAPIParser, RedocNormalizedOptions, MediaTypeModel } from '../../services';
|
||||
import { MediaTypeSamples } from '../PayloadSamples/MediaTypeSamples';
|
||||
import { OpenAPIMediaType } from '../../types';
|
||||
|
||||
export interface ObjectDescriptionProps {
|
||||
schemaRef: string;
|
||||
examplesRef?: string;
|
||||
parser: OpenAPIParser;
|
||||
options: RedocNormalizedOptions;
|
||||
}
|
||||
|
||||
export class ObjectDescription extends React.PureComponent<ObjectDescriptionProps> {
|
||||
private mediaModel: MediaTypeModel;
|
||||
|
||||
constructor(props: ObjectDescriptionProps) {
|
||||
super(props);
|
||||
this.mediaModel = ObjectDescription.getMediaModel(this.props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Section>
|
||||
<Row>
|
||||
<MiddlePanel>
|
||||
<Schema skipWriteOnly={true} key="schema" schema={this.mediaModel.schema} />
|
||||
</MiddlePanel>
|
||||
<DarkRightPanel>
|
||||
<MediaTypeSamples mediaType={this.mediaModel} />
|
||||
</DarkRightPanel>
|
||||
</Row>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
private static getMediaType(schemaRef, examplesRef): OpenAPIMediaType {
|
||||
if (!schemaRef) return {};
|
||||
|
||||
const info: OpenAPIMediaType = {
|
||||
schema: { $ref: schemaRef },
|
||||
};
|
||||
|
||||
if (examplesRef) info.examples = { object: { $ref: examplesRef } };
|
||||
return info;
|
||||
}
|
||||
|
||||
private static getMediaModel({
|
||||
schemaRef,
|
||||
examplesRef,
|
||||
parser,
|
||||
options,
|
||||
}: ObjectDescriptionProps) {
|
||||
return new MediaTypeModel(
|
||||
parser,
|
||||
'json',
|
||||
false,
|
||||
ObjectDescription.getMediaType(schemaRef, examplesRef),
|
||||
options,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -10,8 +10,12 @@ import { RedocNormalizedOptions, RedocRawOptions } from './RedocNormalizedOption
|
|||
import { ScrollService } from './ScrollService';
|
||||
import { SearchStore } from './SearchStore';
|
||||
|
||||
import { ObjectDescription } from '../components/ObjectDescription/ObjectDescription';
|
||||
import { SecurityDefs } from '../components/SecuritySchemes/SecuritySchemes';
|
||||
import { SECURITY_DEFINITIONS_COMPONENT_NAME } from '../utils/openapi';
|
||||
import {
|
||||
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
||||
OBJECT_DEFINTION_COMPONENT_NAME,
|
||||
} from '../utils/openapi';
|
||||
|
||||
export interface StoreState {
|
||||
menu: {
|
||||
|
@ -151,5 +155,13 @@ const DEFAULT_OPTIONS: RedocRawOptions = {
|
|||
securitySchemes: store.spec.securitySchemes,
|
||||
}),
|
||||
},
|
||||
[OBJECT_DEFINTION_COMPONENT_NAME]: {
|
||||
component: ObjectDescription,
|
||||
propsSelector: (store: AppStore) => ({
|
||||
securitySchemes: store.spec.securitySchemes,
|
||||
parser: store.spec.parser,
|
||||
options: store.options,
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -42,7 +42,7 @@ export class MenuBuilder {
|
|||
|
||||
const items: ContentItemModel[] = [];
|
||||
const tagsMap = MenuBuilder.getTagsWithOperations(spec);
|
||||
items.push(...MenuBuilder.addMarkdownItems(spec.info.description || '', options));
|
||||
items.push(...MenuBuilder.addMarkdownItems(spec.info.description || '', undefined, options));
|
||||
if (spec['x-tagGroups'] && spec['x-tagGroups'].length > 0) {
|
||||
items.push(
|
||||
...MenuBuilder.getTagGroupsItems(parser, undefined, spec['x-tagGroups'], tagsMap, options),
|
||||
|
@ -59,6 +59,7 @@ export class MenuBuilder {
|
|||
*/
|
||||
static addMarkdownItems(
|
||||
description: string,
|
||||
parent: GroupModel | undefined,
|
||||
options: RedocNormalizedOptions,
|
||||
): ContentItemModel[] {
|
||||
const renderer = new MarkdownRenderer(options);
|
||||
|
@ -82,7 +83,7 @@ export class MenuBuilder {
|
|||
return group;
|
||||
});
|
||||
|
||||
return mapHeadingsDeep(undefined, headings);
|
||||
return mapHeadingsDeep(parent, headings, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,15 +145,22 @@ export class MenuBuilder {
|
|||
}
|
||||
const item = new GroupModel('tag', tag, parent);
|
||||
item.depth = GROUP_DEPTH + 1;
|
||||
item.items = this.getOperationsItems(parser, item, tag, item.depth + 1, options);
|
||||
|
||||
// don't put empty tag into content, instead put its operations
|
||||
if (tag.name === '') {
|
||||
const items = this.getOperationsItems(parser, undefined, tag, item.depth + 1, options);
|
||||
const items = [
|
||||
...MenuBuilder.addMarkdownItems(tag.description || '', item, options),
|
||||
...this.getOperationsItems(parser, undefined, tag, item.depth + 1, options),
|
||||
];
|
||||
res.push(...items);
|
||||
continue;
|
||||
}
|
||||
|
||||
item.items = [
|
||||
...MenuBuilder.addMarkdownItems(tag.description || '', item, options),
|
||||
...this.getOperationsItems(parser, item, tag, item.depth + 1, options),
|
||||
];
|
||||
|
||||
res.push(item);
|
||||
}
|
||||
return res;
|
||||
|
|
|
@ -40,7 +40,14 @@ export class GroupModel implements IMenuItem {
|
|||
this.type = type;
|
||||
this.name = tagOrGroup['x-displayName'] || tagOrGroup.name;
|
||||
this.level = (tagOrGroup as MarkdownHeading).level || 1;
|
||||
|
||||
// remove sections from markdown, same as in ApiInfo
|
||||
this.description = tagOrGroup.description || '';
|
||||
const firstHeadingLinePos = this.description.search(/^##?\s+/m);
|
||||
if (firstHeadingLinePos > -1) {
|
||||
this.description = this.description.substring(0, firstHeadingLinePos);
|
||||
}
|
||||
|
||||
this.parent = parent;
|
||||
this.externalDocs = (tagOrGroup as OpenAPITag).externalDocs;
|
||||
|
||||
|
|
|
@ -495,6 +495,7 @@ export function normalizeServers(
|
|||
});
|
||||
}
|
||||
|
||||
export const OBJECT_DEFINTION_COMPONENT_NAME = 'object-description';
|
||||
export const SECURITY_DEFINITIONS_COMPONENT_NAME = 'security-definitions';
|
||||
export let SECURITY_SCHEMES_SECTION_PREFIX = 'section/Authentication/';
|
||||
export function setSecuritySchemePrefix(prefix: string) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user