diff --git a/demo/openapi.yaml b/demo/openapi.yaml
index 790a76c7..4dc5f229 100644
--- a/demo/openapi.yaml
+++ b/demo/openapi.yaml
@@ -112,6 +112,9 @@ paths:
summary: Add a new pet to the store
description: Add new pet to the store inventory.
operationId: addPet
+ x-badges:
+ - name: Global
+ type: global
responses:
'405':
description: Invalid input
@@ -156,6 +159,9 @@ paths:
summary: Update an existing pet
description: ''
operationId: updatePet
+ x-badges:
+ - name: US Only
+ type: usonly
responses:
'400':
description: Invalid ID supplied
@@ -186,6 +192,9 @@ paths:
get:
description: Retrieve the history information associated with an order.
operationId: GetOrderHistory
+ x-badges:
+ - name: Success
+ type: success
parameters:
- description: ''
in: path
diff --git a/src/components/Operation/Operation.tsx b/src/components/Operation/Operation.tsx
index e135c31e..2f743597 100644
--- a/src/components/Operation/Operation.tsx
+++ b/src/components/Operation/Operation.tsx
@@ -28,7 +28,15 @@ export interface OperationProps {
}
export const Operation = observer(({ operation }: OperationProps): JSX.Element => {
- const { name: summary, description, deprecated, externalDocs, isWebhook, httpVerb } = operation;
+ const {
+ name: summary,
+ description,
+ deprecated,
+ badges,
+ externalDocs,
+ isWebhook,
+ httpVerb,
+ } = operation;
const hasDescription = !!(description || externalDocs);
const { showWebhookVerb } = React.useContext(OptionsContext);
return (
@@ -45,6 +53,16 @@ export const Operation = observer(({ operation }: OperationProps): JSX.Element =
Webhook {showWebhookVerb && httpVerb && '| ' + httpVerb.toUpperCase()}
)}
+ {badges.map(badge => {
+ return (
+ badge && (
+
+ {' '}
+ {badge.name}{' '}
+
+ )
+ );
+ })}
{options.pathInMiddlePanel && !isWebhook && (
diff --git a/src/services/models/Operation.ts b/src/services/models/Operation.ts
index e26b4a4c..96fbb43a 100644
--- a/src/services/models/Operation.ts
+++ b/src/services/models/Operation.ts
@@ -20,7 +20,12 @@ import { RequestBodyModel } from './RequestBody';
import { ResponseModel } from './Response';
import { SideNavStyleEnum } from '../types';
-import type { OpenAPIExternalDocumentation, OpenAPIServer, OpenAPIXCodeSample } from '../../types';
+import type {
+ OpenAPIExternalDocumentation,
+ OpenAPIServer,
+ OpenAPIXCodeSample,
+ OperationCustomBadge,
+} from '../../types';
import type { OpenAPIParser } from '../OpenAPIParser';
import type { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import type { MediaContentModel } from './MediaContent';
@@ -72,6 +77,7 @@ export class OperationModel implements IMenuItem {
operationHash?: string;
httpVerb: string;
deprecated: boolean;
+ badges: OperationCustomBadge[];
path: string;
servers: OpenAPIServer[];
security: SecurityRequirementModel[];
@@ -96,6 +102,7 @@ export class OperationModel implements IMenuItem {
this.externalDocs = operationSpec.externalDocs;
this.deprecated = !!operationSpec.deprecated;
+ this.badges = operationSpec['x-badges'] ? operationSpec['x-badges'] : [];
this.httpVerb = operationSpec.httpVerb;
this.deprecated = !!operationSpec.deprecated;
this.operationId = operationSpec.operationId;
diff --git a/src/theme.ts b/src/theme.ts
index e11209b6..4fca8a65 100644
--- a/src/theme.ts
+++ b/src/theme.ts
@@ -37,6 +37,24 @@ const defaultTheme: ThemeInterface = {
dark: ({ colors }) => darken(colors.tonalOffset, colors.error.main),
contrastText: ({ colors }) => readableColor(colors.error.main),
},
+ global: {
+ main: '#7c1cfc',
+ light: ({ colors }) => lighten(colors.tonalOffset, colors.global.main),
+ dark: ({ colors }) => darken(colors.tonalOffset, colors.global.main),
+ contrastText: ({ colors }) => readableColor(colors.global.main),
+ },
+ usonly: {
+ main: '#079cee',
+ light: ({ colors }) => lighten(colors.tonalOffset, colors.usonly.main),
+ dark: ({ colors }) => darken(colors.tonalOffset, colors.usonly.main),
+ contrastText: ({ colors }) => readableColor(colors.global.main),
+ },
+ experimental: {
+ main: '#8c03fc',
+ light: ({ colors }) => lighten(colors.tonalOffset, colors.experimental.main),
+ dark: ({ colors }) => darken(colors.tonalOffset, colors.experimental.main),
+ contrastText: ({ colors }) => readableColor(colors.experimental.main),
+ },
gray: {
50: '#FAFAFA',
100: '#F5F5F5',
@@ -267,6 +285,9 @@ export interface ResolvedThemeInterface {
success: ColorSetting;
warning: ColorSetting;
error: ColorSetting;
+ global: ColorSetting;
+ usonly: ColorSetting;
+ experimental: ColorSetting;
gray: {
50: string;
100: string;
diff --git a/src/types/open-api.ts b/src/types/open-api.ts
index fd80bf8d..dab3729c 100644
--- a/src/types/open-api.ts
+++ b/src/types/open-api.ts
@@ -64,6 +64,20 @@ export interface OpenAPIPath {
$ref?: string;
}
+export type OperationCustomBadgeType =
+ | 'primary'
+ | 'success'
+ | 'warning'
+ | 'error'
+ | 'global'
+ | 'usonly'
+ | 'experimental';
+
+export interface OperationCustomBadge {
+ name: string;
+ type: OperationCustomBadgeType;
+}
+
export interface OpenAPIXCodeSample {
lang: string;
label?: string;
@@ -83,6 +97,7 @@ export interface OpenAPIOperation {
deprecated?: boolean;
security?: OpenAPISecurityRequirement[];
servers?: OpenAPIServer[];
+ 'x-badges'?: OperationCustomBadge[];
'x-codeSamples'?: OpenAPIXCodeSample[];
'x-code-samples'?: OpenAPIXCodeSample[]; // deprecated
}
diff --git a/src/utils/openapi.ts b/src/utils/openapi.ts
index 22424e90..561811c7 100644
--- a/src/utils/openapi.ts
+++ b/src/utils/openapi.ts
@@ -662,6 +662,7 @@ export function isRedocExtension(key: string): boolean {
'x-traitTag': true,
'x-additionalPropertiesName': true,
'x-explicitMappingOnly': true,
+ 'x-badges': true,
};
return key in redocExtensions;