mirror of
https://github.com/Redocly/redoc.git
synced 2025-07-24 23:19:57 +03:00
feat: Optionally render object schema title and descriptions
This commit is contained in:
parent
21b961dffa
commit
eb7227f85f
|
@ -6,7 +6,7 @@ Each deployment type has documentation on how to configure options for that type
|
|||
|
||||
**Versions: 2.x**
|
||||
|
||||
{% admonition type="success" name="Client-side configuration" %}
|
||||
{% admonition type="success" name="Client-side configuration" %}
|
||||
|
||||
Using Redoc as a standalone (HTML or React) tool, these options must be presented in [kebab case](https://en.wikipedia.org/wiki/Letter_case#Kebab_case).
|
||||
For example, `scrollYOffset` becomes `scroll-y-offset`, and `expandResponses` becomes `expand-responses`.
|
||||
|
@ -66,6 +66,14 @@ If set to `true`, the pattern is not shown in the schema.
|
|||
|
||||
Hides the schema title next to to the type.
|
||||
|
||||
### hideObjectTitle
|
||||
|
||||
Hides the object title in the schema.
|
||||
|
||||
### hideObjectDescription
|
||||
|
||||
Hides the object description in the schema.
|
||||
|
||||
### hideSecuritySection
|
||||
|
||||
Hides the Security panel section.
|
||||
|
|
|
@ -104,7 +104,8 @@ export class Field extends React.Component<FieldProps> {
|
|||
schema={field.schema}
|
||||
skipReadOnly={this.props.skipReadOnly}
|
||||
skipWriteOnly={this.props.skipWriteOnly}
|
||||
showTitle={this.props.showTitle}
|
||||
hideObjectTitle={this.props.hideObjectTitle}
|
||||
hideObjectDescription={this.props.hideObjectDescription}
|
||||
level={this.props.level}
|
||||
/>
|
||||
</InnerPropertiesWrap>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import * as React from 'react';
|
||||
import { DropdownOrLabel, DropdownOrLabelProps } from '../DropdownOrLabel/DropdownOrLabel';
|
||||
import { ParametersGroup } from './ParametersGroup';
|
||||
import { OptionsContext } from '../OptionsProvider';
|
||||
|
||||
import { UnderlinedHeader } from '../../common-elements';
|
||||
|
||||
|
@ -29,6 +30,8 @@ export interface ParametersProps {
|
|||
const PARAM_PLACES = ['path', 'query', 'cookie', 'header'];
|
||||
|
||||
export class Parameters extends React.PureComponent<ParametersProps> {
|
||||
static contextType = OptionsContext;
|
||||
|
||||
orderParams(params: FieldModel[]): Record<string, FieldModel[]> {
|
||||
const res = {};
|
||||
params.forEach(param => {
|
||||
|
@ -38,6 +41,7 @@ export class Parameters extends React.PureComponent<ParametersProps> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { hideObjectTitle, hideObjectDescription } = this.context;
|
||||
const { body, parameters = [] } = this.props;
|
||||
if (body === undefined && parameters === undefined) {
|
||||
return null;
|
||||
|
@ -63,6 +67,8 @@ export class Parameters extends React.PureComponent<ParametersProps> {
|
|||
content={bodyContent}
|
||||
description={bodyDescription}
|
||||
bodyRequired={bodyRequired}
|
||||
hideObjectTitle={hideObjectTitle}
|
||||
hideObjectDescription={hideObjectDescription}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
@ -90,8 +96,10 @@ export function BodyContent(props: {
|
|||
content: MediaContentModel;
|
||||
description?: string;
|
||||
bodyRequired?: boolean;
|
||||
hideObjectTitle?: boolean;
|
||||
hideObjectDescription?: boolean;
|
||||
}): JSX.Element {
|
||||
const { content, description, bodyRequired } = props;
|
||||
const { content, description, bodyRequired, hideObjectTitle, hideObjectDescription } = props;
|
||||
const { isRequestType } = content;
|
||||
return (
|
||||
<MediaTypesSwitch
|
||||
|
@ -108,6 +116,8 @@ export function BodyContent(props: {
|
|||
<Schema
|
||||
skipReadOnly={isRequestType}
|
||||
skipWriteOnly={!isRequestType}
|
||||
hideObjectTitle={hideObjectTitle}
|
||||
hideObjectDescription={hideObjectDescription}
|
||||
key="schema"
|
||||
schema={schema}
|
||||
/>
|
||||
|
|
|
@ -11,9 +11,13 @@ import { Extensions } from '../Fields/Extensions';
|
|||
import { Markdown } from '../Markdown/Markdown';
|
||||
import { ResponseHeaders } from './ResponseHeaders';
|
||||
import { ConstraintsView } from '../Fields/FieldConstraints';
|
||||
import { OptionsContext } from '../OptionsProvider';
|
||||
|
||||
export class ResponseDetails extends React.PureComponent<{ response: ResponseModel }> {
|
||||
static contextType = OptionsContext;
|
||||
|
||||
render() {
|
||||
const { hideObjectTitle, hideObjectDescription } = this.context;
|
||||
const { description, extensions, headers, content } = this.props.response;
|
||||
return (
|
||||
<>
|
||||
|
@ -27,7 +31,13 @@ export class ResponseDetails extends React.PureComponent<{ response: ResponseMod
|
|||
{schema?.type === 'object' && (
|
||||
<ConstraintsView constraints={schema?.constraints || []} />
|
||||
)}
|
||||
<Schema skipWriteOnly={true} key="schema" schema={schema} />
|
||||
<Schema
|
||||
hideObjectTitle={hideObjectTitle}
|
||||
hideObjectDescription={hideObjectDescription}
|
||||
skipWriteOnly={true}
|
||||
key="schema"
|
||||
schema={schema}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
|
||||
import styled from '../../styled-components';
|
||||
import { H3 } from '../../common-elements/headers';
|
||||
import { Markdown } from '../Markdown/Markdown';
|
||||
|
||||
import { SchemaModel } from '../../services/models';
|
||||
|
||||
import { PropertiesTable, PropertiesTableCaption } from '../../common-elements/fields-layout';
|
||||
import { PropertiesTable } from '../../common-elements/fields-layout';
|
||||
import { Field } from '../Fields/Field';
|
||||
import { DiscriminatorDropdown } from './DiscriminatorDropdown';
|
||||
import { SchemaProps } from './Schema';
|
||||
|
@ -18,13 +22,26 @@ export interface ObjectSchemaProps extends SchemaProps {
|
|||
};
|
||||
}
|
||||
|
||||
export const ObjectSchemaDetails = styled.div`
|
||||
margin: 0 0 0.5em 0;
|
||||
`;
|
||||
|
||||
export const ObjectSchemaTitle = styled(H3)`
|
||||
margin: 0.5em 0 0 0;
|
||||
`;
|
||||
|
||||
export const ObjectSchemaDescription = styled.div`
|
||||
margin: 0.5em 0 0 0;
|
||||
`;
|
||||
|
||||
export const ObjectSchema = observer(
|
||||
({
|
||||
schema: { fields = [], title },
|
||||
showTitle,
|
||||
schema: { fields = [], title, description },
|
||||
discriminator,
|
||||
skipReadOnly,
|
||||
skipWriteOnly,
|
||||
hideObjectTitle,
|
||||
hideObjectDescription,
|
||||
level,
|
||||
}: ObjectSchemaProps) => {
|
||||
const { expandSingleSchemaField, showObjectSchemaExamples, schemaExpansionLevel } =
|
||||
|
@ -48,37 +65,48 @@ export const ObjectSchema = observer(
|
|||
(expandSingleSchemaField && filteredFields.length === 1) || schemaExpansionLevel >= level!;
|
||||
|
||||
return (
|
||||
<PropertiesTable>
|
||||
{showTitle && <PropertiesTableCaption>{title}</PropertiesTableCaption>}
|
||||
<tbody>
|
||||
{mapWithLast(filteredFields, (field, isLast) => {
|
||||
return (
|
||||
<Field
|
||||
key={field.name}
|
||||
isLast={isLast}
|
||||
field={field}
|
||||
expandByDefault={expandByDefault}
|
||||
renderDiscriminatorSwitch={
|
||||
discriminator?.fieldName === field.name
|
||||
? () => (
|
||||
<DiscriminatorDropdown
|
||||
parent={discriminator!.parentSchema}
|
||||
enumValues={field.schema.enum}
|
||||
/>
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
className={field.expanded ? 'expanded' : undefined}
|
||||
showExamples={showObjectSchemaExamples}
|
||||
skipReadOnly={skipReadOnly}
|
||||
skipWriteOnly={skipWriteOnly}
|
||||
showTitle={showTitle}
|
||||
level={level}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</PropertiesTable>
|
||||
<div>
|
||||
<ObjectSchemaDetails>
|
||||
{!hideObjectTitle && <ObjectSchemaTitle>{title}</ObjectSchemaTitle>}
|
||||
{!hideObjectDescription && (
|
||||
<ObjectSchemaDescription>
|
||||
<Markdown compact={true} source={description} />
|
||||
</ObjectSchemaDescription>
|
||||
)}
|
||||
</ObjectSchemaDetails>
|
||||
|
||||
<PropertiesTable>
|
||||
<tbody>
|
||||
{mapWithLast(filteredFields, (field, isLast) => {
|
||||
return (
|
||||
<Field
|
||||
key={field.name}
|
||||
isLast={isLast}
|
||||
field={field}
|
||||
expandByDefault={expandByDefault}
|
||||
renderDiscriminatorSwitch={
|
||||
discriminator?.fieldName === field.name
|
||||
? () => (
|
||||
<DiscriminatorDropdown
|
||||
parent={discriminator!.parentSchema}
|
||||
enumValues={field.schema.enum}
|
||||
/>
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
className={field.expanded ? 'expanded' : undefined}
|
||||
showExamples={showObjectSchemaExamples}
|
||||
skipReadOnly={skipReadOnly}
|
||||
skipWriteOnly={skipWriteOnly}
|
||||
hideObjectTitle={hideObjectTitle}
|
||||
hideObjectDescription={hideObjectDescription}
|
||||
level={level}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</PropertiesTable>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -13,9 +13,10 @@ import { RecursiveSchema } from './RecursiveSchema';
|
|||
import { isArray } from '../../utils/helpers';
|
||||
|
||||
export interface SchemaOptions {
|
||||
showTitle?: boolean;
|
||||
skipReadOnly?: boolean;
|
||||
skipWriteOnly?: boolean;
|
||||
hideObjectTitle?: boolean;
|
||||
hideObjectDescription?: boolean;
|
||||
level?: number;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@ export interface ObjectDescriptionProps {
|
|||
exampleRef?: string;
|
||||
showReadOnly?: boolean;
|
||||
showWriteOnly?: boolean;
|
||||
showObjectTitle?: boolean;
|
||||
showObjectDescription?: boolean;
|
||||
showExample?: boolean;
|
||||
parser: OpenAPIParser;
|
||||
options: RedocNormalizedOptions;
|
||||
|
@ -54,7 +56,13 @@ export class SchemaDefinition extends React.PureComponent<ObjectDescriptionProps
|
|||
}
|
||||
|
||||
render() {
|
||||
const { showReadOnly = true, showWriteOnly = false, showExample = true } = this.props;
|
||||
const {
|
||||
showReadOnly = true,
|
||||
showWriteOnly = false,
|
||||
showExample = true,
|
||||
showObjectTitle = false,
|
||||
showObjectDescription = false,
|
||||
} = this.props;
|
||||
return (
|
||||
<Section>
|
||||
<Row>
|
||||
|
@ -62,6 +70,8 @@ export class SchemaDefinition extends React.PureComponent<ObjectDescriptionProps
|
|||
<Schema
|
||||
skipWriteOnly={!showWriteOnly}
|
||||
skipReadOnly={!showReadOnly}
|
||||
hideObjectTitle={!showObjectTitle}
|
||||
hideObjectDescription={!showObjectDescription}
|
||||
schema={this.mediaModel.schema}
|
||||
/>
|
||||
</MiddlePanel>
|
||||
|
|
|
@ -2865,143 +2865,156 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
`;
|
||||
|
||||
exports[`Components SchemaView discriminator should correctly render discriminator dropdown 1`] = `
|
||||
<styled.table>
|
||||
<tbody>
|
||||
<Field
|
||||
expandByDefault={false}
|
||||
field={
|
||||
FieldModel {
|
||||
"const": "",
|
||||
"deprecated": false,
|
||||
"description": "",
|
||||
"example": undefined,
|
||||
"expanded": undefined,
|
||||
"explode": false,
|
||||
"in": undefined,
|
||||
"kind": "field",
|
||||
"name": "packSize",
|
||||
"required": false,
|
||||
"schema": SchemaModel {
|
||||
"activeOneOf": 0,
|
||||
<div>
|
||||
<styled.div>
|
||||
<Styled(styled.h2)>
|
||||
Dog
|
||||
</Styled(styled.h2)>
|
||||
<styled.div>
|
||||
<Markdown
|
||||
compact={true}
|
||||
source=""
|
||||
/>
|
||||
</styled.div>
|
||||
</styled.div>
|
||||
<styled.table>
|
||||
<tbody>
|
||||
<Field
|
||||
expandByDefault={false}
|
||||
field={
|
||||
FieldModel {
|
||||
"const": "",
|
||||
"constraints": Array [],
|
||||
"contentEncoding": undefined,
|
||||
"contentMediaType": undefined,
|
||||
"default": undefined,
|
||||
"deprecated": false,
|
||||
"description": "",
|
||||
"displayFormat": undefined,
|
||||
"displayType": "number",
|
||||
"enum": Array [],
|
||||
"example": undefined,
|
||||
"examples": undefined,
|
||||
"externalDocs": undefined,
|
||||
"format": undefined,
|
||||
"isCircular": false,
|
||||
"isPrimitive": true,
|
||||
"maxItems": undefined,
|
||||
"minItems": undefined,
|
||||
"options": "<<<filtered>>>",
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog/properties/packSize",
|
||||
"rawSchema": Object {
|
||||
"expanded": undefined,
|
||||
"explode": false,
|
||||
"in": undefined,
|
||||
"kind": "field",
|
||||
"name": "packSize",
|
||||
"required": false,
|
||||
"schema": SchemaModel {
|
||||
"activeOneOf": 0,
|
||||
"const": "",
|
||||
"constraints": Array [],
|
||||
"contentEncoding": undefined,
|
||||
"contentMediaType": undefined,
|
||||
"default": undefined,
|
||||
"deprecated": false,
|
||||
"description": "",
|
||||
"displayFormat": undefined,
|
||||
"displayType": "number",
|
||||
"enum": Array [],
|
||||
"example": undefined,
|
||||
"examples": undefined,
|
||||
"externalDocs": undefined,
|
||||
"format": undefined,
|
||||
"isCircular": false,
|
||||
"isPrimitive": true,
|
||||
"maxItems": undefined,
|
||||
"minItems": undefined,
|
||||
"options": "<<<filtered>>>",
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog/properties/packSize",
|
||||
"rawSchema": Object {
|
||||
"default": undefined,
|
||||
"type": "number",
|
||||
},
|
||||
"readOnly": false,
|
||||
"refsStack": Array [
|
||||
"#/components/schemas/Dog",
|
||||
"#/components/schemas/Dog/properties/packSize",
|
||||
],
|
||||
"schema": Object {
|
||||
"default": undefined,
|
||||
"type": "number",
|
||||
},
|
||||
"title": "",
|
||||
"type": "number",
|
||||
"typePrefix": "",
|
||||
"writeOnly": false,
|
||||
},
|
||||
"readOnly": false,
|
||||
"refsStack": Array [
|
||||
"#/components/schemas/Dog",
|
||||
"#/components/schemas/Dog/properties/packSize",
|
||||
],
|
||||
"schema": Object {
|
||||
"default": undefined,
|
||||
"type": "number",
|
||||
},
|
||||
"title": "",
|
||||
"type": "number",
|
||||
"typePrefix": "",
|
||||
"writeOnly": false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
isLast={false}
|
||||
key="packSize"
|
||||
showExamples={false}
|
||||
/>
|
||||
<Field
|
||||
expandByDefault={false}
|
||||
field={
|
||||
FieldModel {
|
||||
"const": "",
|
||||
"deprecated": false,
|
||||
"description": "",
|
||||
"example": undefined,
|
||||
"expanded": undefined,
|
||||
"explode": false,
|
||||
"in": undefined,
|
||||
"kind": "field",
|
||||
"name": "type",
|
||||
"required": true,
|
||||
"schema": SchemaModel {
|
||||
"activeOneOf": 0,
|
||||
isLast={false}
|
||||
key="packSize"
|
||||
showExamples={false}
|
||||
/>
|
||||
<Field
|
||||
expandByDefault={false}
|
||||
field={
|
||||
FieldModel {
|
||||
"const": "",
|
||||
"constraints": Array [],
|
||||
"contentEncoding": undefined,
|
||||
"contentMediaType": undefined,
|
||||
"default": undefined,
|
||||
"deprecated": false,
|
||||
"description": "",
|
||||
"displayFormat": undefined,
|
||||
"displayType": "string",
|
||||
"enum": Array [],
|
||||
"example": undefined,
|
||||
"examples": undefined,
|
||||
"externalDocs": undefined,
|
||||
"format": undefined,
|
||||
"isCircular": false,
|
||||
"isPrimitive": true,
|
||||
"maxItems": undefined,
|
||||
"minItems": undefined,
|
||||
"options": "<<<filtered>>>",
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog/properties/type",
|
||||
"rawSchema": Object {
|
||||
"expanded": undefined,
|
||||
"explode": false,
|
||||
"in": undefined,
|
||||
"kind": "field",
|
||||
"name": "type",
|
||||
"required": true,
|
||||
"schema": SchemaModel {
|
||||
"activeOneOf": 0,
|
||||
"const": "",
|
||||
"constraints": Array [],
|
||||
"contentEncoding": undefined,
|
||||
"contentMediaType": undefined,
|
||||
"default": undefined,
|
||||
"type": "string",
|
||||
"x-refsStack": Array [
|
||||
"deprecated": false,
|
||||
"description": "",
|
||||
"displayFormat": undefined,
|
||||
"displayType": "string",
|
||||
"enum": Array [],
|
||||
"example": undefined,
|
||||
"examples": undefined,
|
||||
"externalDocs": undefined,
|
||||
"format": undefined,
|
||||
"isCircular": false,
|
||||
"isPrimitive": true,
|
||||
"maxItems": undefined,
|
||||
"minItems": undefined,
|
||||
"options": "<<<filtered>>>",
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog/properties/type",
|
||||
"rawSchema": Object {
|
||||
"default": undefined,
|
||||
"type": "string",
|
||||
"x-refsStack": Array [
|
||||
"#/components/schemas/Dog",
|
||||
"#/components/schemas/Pet",
|
||||
],
|
||||
},
|
||||
"readOnly": false,
|
||||
"refsStack": Array [
|
||||
"#/components/schemas/Dog",
|
||||
"#/components/schemas/Dog",
|
||||
"#/components/schemas/Pet",
|
||||
],
|
||||
},
|
||||
"readOnly": false,
|
||||
"refsStack": Array [
|
||||
"#/components/schemas/Dog",
|
||||
"#/components/schemas/Dog",
|
||||
"#/components/schemas/Pet",
|
||||
"#/components/schemas/Dog",
|
||||
"#/components/schemas/Pet",
|
||||
"#/components/schemas/Dog/properties/type",
|
||||
],
|
||||
"schema": Object {
|
||||
"default": undefined,
|
||||
"type": "string",
|
||||
"x-refsStack": Array [
|
||||
"#/components/schemas/Dog",
|
||||
"#/components/schemas/Pet",
|
||||
"#/components/schemas/Dog/properties/type",
|
||||
],
|
||||
"schema": Object {
|
||||
"default": undefined,
|
||||
"type": "string",
|
||||
"x-refsStack": Array [
|
||||
"#/components/schemas/Dog",
|
||||
"#/components/schemas/Pet",
|
||||
],
|
||||
},
|
||||
"title": "",
|
||||
"type": "string",
|
||||
"typePrefix": "",
|
||||
"writeOnly": false,
|
||||
},
|
||||
"title": "",
|
||||
"type": "string",
|
||||
"typePrefix": "",
|
||||
"writeOnly": false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
isLast={true}
|
||||
key="type"
|
||||
renderDiscriminatorSwitch={[Function]}
|
||||
showExamples={false}
|
||||
/>
|
||||
</tbody>
|
||||
</styled.table>
|
||||
isLast={true}
|
||||
key="type"
|
||||
renderDiscriminatorSwitch={[Function]}
|
||||
showExamples={false}
|
||||
/>
|
||||
</tbody>
|
||||
</styled.table>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -39,6 +39,8 @@ export interface RedocRawOptions {
|
|||
showObjectSchemaExamples?: boolean | string;
|
||||
showSecuritySchemeType?: boolean;
|
||||
hideSecuritySection?: boolean;
|
||||
hideObjectTitle?: boolean | string;
|
||||
hideObjectDescription?: boolean | string;
|
||||
|
||||
unstable_ignoreMimeParameters?: boolean;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user