mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-13 04:16:34 +03:00
feat: support multiple examples for parameters (#1470)
This commit is contained in:
parent
340a568262
commit
d12e410d99
|
@ -9,6 +9,8 @@ import {
|
||||||
TypePrefix,
|
TypePrefix,
|
||||||
TypeTitle,
|
TypeTitle,
|
||||||
ToggleButton,
|
ToggleButton,
|
||||||
|
FieldLabel,
|
||||||
|
ExampleValue,
|
||||||
} from '../../common-elements/fields';
|
} from '../../common-elements/fields';
|
||||||
import { serializeParameterValue } from '../../utils/openapi';
|
import { serializeParameterValue } from '../../utils/openapi';
|
||||||
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
|
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
|
||||||
|
@ -23,6 +25,8 @@ import { Badge } from '../../common-elements/';
|
||||||
|
|
||||||
import { l } from '../../services/Labels';
|
import { l } from '../../services/Labels';
|
||||||
import { OptionsContext } from '../OptionsProvider';
|
import { OptionsContext } from '../OptionsProvider';
|
||||||
|
import { FieldModel } from '../../services/models/Field';
|
||||||
|
import styled from '../../styled-components';
|
||||||
|
|
||||||
const MAX_PATTERN_LENGTH = 45;
|
const MAX_PATTERN_LENGTH = 45;
|
||||||
|
|
||||||
|
@ -44,20 +48,19 @@ export class FieldDetails extends React.PureComponent<FieldProps, { patternShown
|
||||||
const { patternShown } = this.state;
|
const { patternShown } = this.state;
|
||||||
const { enumSkipQuotes, hideSchemaTitles } = this.context;
|
const { enumSkipQuotes, hideSchemaTitles } = this.context;
|
||||||
|
|
||||||
const { schema, description, example, deprecated } = field;
|
const { schema, description, example, deprecated, examples } = field;
|
||||||
|
|
||||||
const rawDefault = !!enumSkipQuotes || field.in === 'header'; // having quotes around header field default values is confusing and inappropriate
|
const rawDefault = !!enumSkipQuotes || field.in === 'header'; // having quotes around header field default values is confusing and inappropriate
|
||||||
|
|
||||||
let exampleField: JSX.Element | null = null;
|
let renderedExamples: JSX.Element | null = null;
|
||||||
|
|
||||||
if (showExamples && example !== undefined) {
|
if (showExamples && (example !== undefined || examples !== undefined)) {
|
||||||
const label = l('example') + ':';
|
if (examples !== undefined) {
|
||||||
if (field.in && (field.style || field.serializationMime)) {
|
renderedExamples = <Examples field={field} />;
|
||||||
// decode for better readability in examples: see https://github.com/Redocly/redoc/issues/1138
|
|
||||||
const serializedValue = decodeURIComponent(serializeParameterValue(field, example));
|
|
||||||
exampleField = <FieldDetail label={label} value={serializedValue} raw={true} />;
|
|
||||||
} else {
|
} else {
|
||||||
exampleField = <FieldDetail label={label} value={example} />;
|
const label = l('example') + ':';
|
||||||
|
const raw = !!field.in;
|
||||||
|
renderedExamples = <FieldDetail label={label} value={getSerializedValue(field, field.example)} raw={raw} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +103,7 @@ export class FieldDetails extends React.PureComponent<FieldProps, { patternShown
|
||||||
)}
|
)}
|
||||||
<FieldDetail raw={rawDefault} label={l('default') + ':'} value={schema.default} />
|
<FieldDetail raw={rawDefault} label={l('default') + ':'} value={schema.default} />
|
||||||
{!renderDiscriminatorSwitch && <EnumValues type={schema.type} values={schema.enum} />}{' '}
|
{!renderDiscriminatorSwitch && <EnumValues type={schema.type} values={schema.enum} />}{' '}
|
||||||
{exampleField}
|
{renderedExamples}
|
||||||
{<Extensions extensions={{ ...field.extensions, ...schema.extensions }} />}
|
{<Extensions extensions={{ ...field.extensions, ...schema.extensions }} />}
|
||||||
<div>
|
<div>
|
||||||
<Markdown compact={true} source={description} />
|
<Markdown compact={true} source={description} />
|
||||||
|
@ -113,3 +116,40 @@ export class FieldDetails extends React.PureComponent<FieldProps, { patternShown
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Examples({ field }: { field: FieldModel }) {
|
||||||
|
if (!field.examples) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FieldLabel> {l('examples')}: </FieldLabel>
|
||||||
|
<ExamplesList>
|
||||||
|
{Object.values(field.examples).map((example, idx) => {
|
||||||
|
return (
|
||||||
|
<li key={idx}>
|
||||||
|
<ExampleValue>{getSerializedValue(field, example.value)}</ExampleValue> - {example.summary || example.description}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ExamplesList>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSerializedValue(field: FieldModel, example: any) {
|
||||||
|
if (field.in) {
|
||||||
|
// decode for better readability in examples: see https://github.com/Redocly/redoc/issues/1138
|
||||||
|
return decodeURIComponent(serializeParameterValue(field, example));
|
||||||
|
} else {
|
||||||
|
return example;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const ExamplesList = styled.ul`
|
||||||
|
margin-top: 1em;
|
||||||
|
padding-left: 0;
|
||||||
|
list-style-position: inside;
|
||||||
|
`;
|
||||||
|
|
|
@ -5,6 +5,7 @@ export interface LabelsConfig {
|
||||||
default: string;
|
default: string;
|
||||||
deprecated: string;
|
deprecated: string;
|
||||||
example: string;
|
example: string;
|
||||||
|
examples: string;
|
||||||
nullable: string;
|
nullable: string;
|
||||||
recursive: string;
|
recursive: string;
|
||||||
arrayOf: string;
|
arrayOf: string;
|
||||||
|
@ -20,6 +21,7 @@ const labels: LabelsConfig = {
|
||||||
default: 'Default',
|
default: 'Default',
|
||||||
deprecated: 'Deprecated',
|
deprecated: 'Deprecated',
|
||||||
example: 'Example',
|
example: 'Example',
|
||||||
|
examples: 'Examples',
|
||||||
nullable: 'Nullable',
|
nullable: 'Nullable',
|
||||||
recursive: 'Recursive',
|
recursive: 'Recursive',
|
||||||
arrayOf: 'Array of ',
|
arrayOf: 'Array of ',
|
||||||
|
|
|
@ -11,6 +11,8 @@ import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
import { extractExtensions } from '../../utils/openapi';
|
import { extractExtensions } from '../../utils/openapi';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
import { SchemaModel } from './Schema';
|
import { SchemaModel } from './Schema';
|
||||||
|
import { ExampleModel } from './Example';
|
||||||
|
import { mapValues } from '../../utils/helpers';
|
||||||
|
|
||||||
const DEFAULT_SERIALIZATION: Record<
|
const DEFAULT_SERIALIZATION: Record<
|
||||||
OpenAPIParameterLocation,
|
OpenAPIParameterLocation,
|
||||||
|
@ -46,6 +48,7 @@ export class FieldModel {
|
||||||
required: boolean;
|
required: boolean;
|
||||||
description: string;
|
description: string;
|
||||||
example?: string;
|
example?: string;
|
||||||
|
examples?: Record<string, ExampleModel>;
|
||||||
deprecated: boolean;
|
deprecated: boolean;
|
||||||
in?: OpenAPIParameterLocation;
|
in?: OpenAPIParameterLocation;
|
||||||
kind: string;
|
kind: string;
|
||||||
|
@ -81,6 +84,13 @@ export class FieldModel {
|
||||||
info.description === undefined ? this.schema.description || '' : info.description;
|
info.description === undefined ? this.schema.description || '' : info.description;
|
||||||
this.example = info.example || this.schema.example;
|
this.example = info.example || this.schema.example;
|
||||||
|
|
||||||
|
if (info.examples !== undefined) {
|
||||||
|
this.examples = mapValues(
|
||||||
|
info.examples,
|
||||||
|
example => new ExampleModel(parser, example, name, info.encoding),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (serializationMime) {
|
if (serializationMime) {
|
||||||
this.serializationMime = serializationMime;
|
this.serializationMime = serializationMime;
|
||||||
} else if (info.style) {
|
} else if (info.style) {
|
||||||
|
|
1
src/types/open-api.d.ts
vendored
1
src/types/open-api.d.ts
vendored
|
@ -95,6 +95,7 @@ export interface OpenAPIParameter {
|
||||||
example?: any;
|
example?: any;
|
||||||
examples?: { [media: string]: Referenced<OpenAPIExample> };
|
examples?: { [media: string]: Referenced<OpenAPIExample> };
|
||||||
content?: { [media: string]: OpenAPIMediaType };
|
content?: { [media: string]: OpenAPIMediaType };
|
||||||
|
encoding?: Record<string, OpenAPIEncoding>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OpenAPIExample {
|
export interface OpenAPIExample {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user