Merge remote-tracking branch 'upstream/master' into feat/callbacks-support

This commit is contained in:
Oleksiy Kachynskyy 2020-04-02 16:55:54 +03:00
commit 727eb19995
17 changed files with 180 additions and 59 deletions

View File

@ -1,3 +1,29 @@
# [2.0.0-rc.26](https://github.com/Redocly/redoc/compare/v2.0.0-rc.25...v2.0.0-rc.26) (2020-03-29)
### Bug Fixes
* crash to wrong spelling in localeCompare ([3908a7c](https://github.com/Redocly/redoc/commit/3908a7c46448d277b82318659cdea65db52f9e70)), closes [#1218](https://github.com/Redocly/redoc/issues/1218)
# [2.0.0-rc.25](https://github.com/Redocly/redoc/compare/v2.0.0-rc.24...v2.0.0-rc.25) (2020-03-27)
### Bug Fixes
* do not collapse top level on Collapse All in json samples ([#1209](https://github.com/Redocly/redoc/issues/1209)) ([830371b](https://github.com/Redocly/redoc/commit/830371b5d1edf4ba7a138b3b3d78148d020e0349))
* fix passing boolean value to showExtensions options ([#1211](https://github.com/Redocly/redoc/issues/1211)) ([c6eaa02](https://github.com/Redocly/redoc/commit/c6eaa0281bb0f62b019c865e4aefb863ce84d628))
* improve names for some theme settings ([a0bd27c](https://github.com/Redocly/redoc/commit/a0bd27c75427a39abc9c753b0654678eed2f3851))
* sort discriminator entries by mapping order ([#1216](https://github.com/Redocly/redoc/issues/1216)) ([ac4f915](https://github.com/Redocly/redoc/commit/ac4f915494f289d1c97ffdfe3af59efd94734f8c))
### Features
* add x-explicitMappingOnly extension ([#1215](https://github.com/Redocly/redoc/issues/1215)) ([ea5b0aa](https://github.com/Redocly/redoc/commit/ea5b0aabf9133d11d3a8fcb79f9515d21e0d7ac0))
# [2.0.0-rc.24](https://github.com/Redocly/redoc/compare/v2.0.0-rc.23...v2.0.0-rc.24) (2020-03-17) # [2.0.0-rc.24](https://github.com/Redocly/redoc/compare/v2.0.0-rc.23...v2.0.0-rc.24) (2020-03-17)

View File

@ -306,3 +306,37 @@ Player:
x-additionalPropertiesName: attribute-name x-additionalPropertiesName: attribute-name
type: string type: string
``` ```
#### x-explicitMappingOnly
**ATTENTION**: This is ReDoc-specific vendor extension. It won't be supported by other tools.
Extends the `discriminator` property of the schema object.
| Field Name | Type | Description |
| :------------- | :------: | :---------- |
| x-explicitMappingOnly | boolean | limit the discriminator selectpicker to the explicit mappings only |
###### Usage in ReDoc
ReDoc uses this extension to filter the `discriminator` mappings shown in the selectpicker.
When set to `true`, the selectpicker will only list the the explicitly defined mappings. When `false`,
the default behavior is kept, i.e. explicit and implicit mappings will be shown.
###### x-explicitMappingOnly example
```yaml
Pet:
type: object
required:
- name
- photoUrls
discriminator:
propertyName: petType
x-explicitMappingOnly: true
mapping:
cat: "#/components/schemas/Cat"
bee: "#/components/schemas/HoneyBee"
```
Will show in the selectpicker only the items `cat` and `bee`, even though the `Dog` class inherits from
the `Pet` class.

View File

@ -1,6 +1,6 @@
{ {
"name": "redoc", "name": "redoc",
"version": "2.0.0-rc.24", "version": "2.0.0-rc.26",
"description": "ReDoc", "description": "ReDoc",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -16,7 +16,7 @@ export const Tabs = styled(ReactTabs)`
padding: 5px 10px; padding: 5px 10px;
display: inline-block; display: inline-block;
background-color: ${({ theme }) => theme.codeSample.backgroundColor}; background-color: ${({ theme }) => theme.codeBlock.backgroundColor};
border-bottom: 1px solid rgba(0, 0, 0, 0.5); border-bottom: 1px solid rgba(0, 0, 0, 0.5);
cursor: pointer; cursor: pointer;
text-align: center; text-align: center;
@ -24,7 +24,7 @@ export const Tabs = styled(ReactTabs)`
color: ${({ theme }) => darken(theme.colors.tonalOffset, theme.rightPanel.textColor)}; color: ${({ theme }) => darken(theme.colors.tonalOffset, theme.rightPanel.textColor)};
margin: 0 margin: 0
${({ theme }) => `${theme.spacing.unit}px ${theme.spacing.unit}px ${theme.spacing.unit}px`}; ${({ theme }) => `${theme.spacing.unit}px ${theme.spacing.unit}px ${theme.spacing.unit}px`};
border: 1px solid ${({ theme }) => darken(0.05, theme.codeSample.backgroundColor)}; border: 1px solid ${({ theme }) => darken(0.05, theme.codeBlock.backgroundColor)};
border-radius: 5px; border-radius: 5px;
min-width: 60px; min-width: 60px;
font-size: 0.9em; font-size: 0.9em;
@ -58,7 +58,7 @@ export const Tabs = styled(ReactTabs)`
} }
} }
> .react-tabs__tab-panel { > .react-tabs__tab-panel {
background: ${({ theme }) => theme.codeSample.backgroundColor}; background: ${({ theme }) => theme.codeBlock.backgroundColor};
& > div, & > div,
& > pre { & > pre {
padding: ${props => props.theme.spacing.unit * 4}px; padding: ${props => props.theme.spacing.unit * 4}px;

View File

@ -18,7 +18,7 @@ export const EndpointInfo = styled.div<{ expanded?: boolean; inverted?: boolean
padding: 10px 30px 10px ${props => (props.inverted ? '10px' : '20px')}; padding: 10px 30px 10px ${props => (props.inverted ? '10px' : '20px')};
border-radius: ${props => (props.inverted ? '0' : '4px 4px 0 0')}; border-radius: ${props => (props.inverted ? '0' : '4px 4px 0 0')};
background-color: ${props => background-color: ${props =>
props.inverted ? 'transparent' : props.theme.codeSample.backgroundColor}; props.inverted ? 'transparent' : props.theme.codeBlock.backgroundColor};
display: flex; display: flex;
white-space: nowrap; white-space: nowrap;
align-items: center; align-items: center;

View File

@ -57,11 +57,10 @@ class Json extends React.PureComponent<JsonProps> {
collapseAll = () => { collapseAll = () => {
const elements = this.node.getElementsByClassName('collapsible'); const elements = this.node.getElementsByClassName('collapsible');
for (const expanded of Array.prototype.slice.call(elements)) { // skip first item to avoid collapsing whole object/array
// const collapsed = elements[i]; const elementsArr = Array.prototype.slice.call(elements, 1);
if ((expanded.parentNode as Element)!.classList.contains('redoc-json')) {
continue; for (const expanded of elementsArr) {
}
(expanded.parentNode as Element)!.classList.add('collapsed'); (expanded.parentNode as Element)!.classList.add('collapsed');
} }
}; };

View File

@ -82,7 +82,7 @@ export const StyledMarkdownBlock = styled(
pre { pre {
font-family: ${props => props.theme.typography.code.fontFamily}; font-family: ${props => props.theme.typography.code.fontFamily};
white-space:${({ theme }) => (theme.typography.code.wrap ? 'pre-wrap' : 'pre')}; white-space:${({ theme }) => (theme.typography.code.wrap ? 'pre-wrap' : 'pre')};
background-color: #263238; background-color: ${({ theme }) => theme.codeBlock.backgroundColor};
color: white; color: white;
padding: ${props => props.theme.spacing.unit * 4}px; padding: ${props => props.theme.spacing.unit * 4}px;
overflow-x: auto; overflow-x: auto;

View File

@ -29,7 +29,7 @@ export const ApiContentWrap = styled.div`
z-index: 1; z-index: 1;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
width: calc(100% - ${props => props.theme.menu.width}); width: calc(100% - ${props => props.theme.sidebar.width});
${media.lessThan('small', true)` ${media.lessThan('small', true)`
width: 100%; width: 100%;
`}; `};
@ -46,7 +46,7 @@ export const BackgroundStub = styled.div`
width: ${({ theme }) => { width: ${({ theme }) => {
if (theme.rightPanel.width.endsWith('%')) { if (theme.rightPanel.width.endsWith('%')) {
const percents = parseInt(theme.rightPanel.width, 10); const percents = parseInt(theme.rightPanel.width, 10);
return `calc((100% - ${theme.menu.width}) * ${percents / 100})`; return `calc((100% - ${theme.sidebar.width}) * ${percents / 100})`;
} else { } else {
return theme.rightPanel.width; return theme.rightPanel.width;
} }

View File

@ -80,7 +80,7 @@ export class SchemaDefinition extends React.PureComponent<ObjectDescriptionProps
} }
const MediaSamplesWrap = styled.div` const MediaSamplesWrap = styled.div`
background: ${({ theme }) => theme.codeSample.backgroundColor}; background: ${({ theme }) => theme.codeBlock.backgroundColor};
& > div, & > div,
& > pre { & > pre {
padding: ${props => props.theme.spacing.unit * 4}px; padding: ${props => props.theme.spacing.unit * 4}px;

View File

@ -19,14 +19,14 @@ export const SearchInput = styled.input.attrs(() => ({
border: 0; border: 0;
border-bottom: 1px solid border-bottom: 1px solid
${({ theme }) => ${({ theme }) =>
(getLuminance(theme.menu.backgroundColor) > 0.5 ? darken : lighten)( (getLuminance(theme.sidebar.backgroundColor) > 0.5 ? darken : lighten)(
0.1, 0.1,
theme.menu.backgroundColor, theme.sidebar.backgroundColor,
)}; )};
font-family: ${({ theme }) => theme.typography.fontFamily}; font-family: ${({ theme }) => theme.typography.fontFamily};
font-weight: bold; font-weight: bold;
font-size: 13px; font-size: 13px;
color: ${props => props.theme.menu.textColor}; color: ${props => props.theme.sidebar.textColor};
background-color: transparent; background-color: transparent;
outline: none; outline: none;
`; `;
@ -51,18 +51,18 @@ export const SearchIcon = styled((props: { className?: string }) => (
width: 0.9em; width: 0.9em;
path { path {
fill: ${props => props.theme.menu.textColor}; fill: ${props => props.theme.sidebar.textColor};
} }
`; `;
export const SearchResultsBox = styled.div` export const SearchResultsBox = styled.div`
padding: ${props => props.theme.spacing.unit}px 0; padding: ${props => props.theme.spacing.unit}px 0;
background-color: ${({ theme }) => darken(0.05, theme.menu.backgroundColor)}}; background-color: ${({ theme }) => darken(0.05, theme.sidebar.backgroundColor)}};
color: ${props => props.theme.menu.textColor}; color: ${props => props.theme.sidebar.textColor};
min-height: 150px; min-height: 150px;
max-height: 250px; max-height: 250px;
border-top: ${({ theme }) => darken(0.1, theme.menu.backgroundColor)}}; border-top: ${({ theme }) => darken(0.1, theme.sidebar.backgroundColor)}};
border-bottom: ${({ theme }) => darken(0.1, theme.menu.backgroundColor)}}; border-bottom: ${({ theme }) => darken(0.1, theme.sidebar.backgroundColor)}};
margin-top: 10px; margin-top: 10px;
line-height: 1.4; line-height: 1.4;
font-size: 0.9em; font-size: 0.9em;
@ -73,7 +73,7 @@ export const SearchResultsBox = styled.div`
&:hover, &:hover,
&.active { &.active {
background-color: ${({ theme }) => darken(0.1, theme.menu.backgroundColor)}; background-color: ${({ theme }) => darken(0.1, theme.sidebar.backgroundColor)};
} }
> svg { > svg {

View File

@ -2,7 +2,7 @@ import * as classnames from 'classnames';
import { darken } from 'polished'; import { darken } from 'polished';
import { deprecatedCss, ShelfIcon } from '../../common-elements'; import { deprecatedCss, ShelfIcon } from '../../common-elements';
import styled, { css } from '../../styled-components'; import styled, { css, ResolvedThemeInterface } from '../../styled-components';
export const OperationBadge = styled.span.attrs((props: { type: string }) => ({ export const OperationBadge = styled.span.attrs((props: { type: string }) => ({
className: `operation-type ${props.type}`, className: `operation-type ${props.type}`,
@ -62,11 +62,11 @@ export const OperationBadge = styled.span.attrs((props: { type: string }) => ({
} }
`; `;
function menuItemActiveBg(depth, { theme }): string { function menuItemActiveBg(depth, { theme }: { theme: ResolvedThemeInterface }): string {
if (depth > 1) { if (depth > 1) {
return darken(0.1, theme.menu.backgroundColor); return darken(0.1, theme.sidebar.backgroundColor);
} else if (depth === 1) { } else if (depth === 1) {
return darken(0.05, theme.menu.backgroundColor); return darken(0.05, theme.sidebar.backgroundColor);
} else { } else {
return ''; return '';
} }
@ -94,21 +94,21 @@ export const MenuItemLi = styled.li<{ depth: number }>`
export const menuItemDepth = { export const menuItemDepth = {
0: css` 0: css`
opacity: 0.7; opacity: 0.7;
text-transform: ${({ theme }) => theme.menu.groupItems.textTransform}; text-transform: ${({ theme }) => theme.sidebar.groupItems.textTransform};
font-size: 0.8em; font-size: 0.8em;
padding-bottom: 0; padding-bottom: 0;
cursor: default; cursor: default;
color: ${props => props.theme.menu.textColor}; color: ${props => props.theme.sidebar.textColor};
`, `,
1: css` 1: css`
font-size: 0.929em; font-size: 0.929em;
text-transform: ${({ theme }) => theme.menu.level1Items.textTransform}; text-transform: ${({ theme }) => theme.sidebar.level1Items.textTransform};
&:hover { &:hover {
color: ${props => props.theme.menu.activeTextColor}; color: ${props => props.theme.sidebar.activeTextColor};
} }
`, `,
2: css` 2: css`
color: ${props => props.theme.menu.textColor}; color: ${props => props.theme.sidebar.textColor};
`, `,
}; };
@ -126,7 +126,8 @@ export const MenuItemLabel = styled.label.attrs((props: MenuItemLabelType) => ({
}), }),
}))<MenuItemLabelType>` }))<MenuItemLabelType>`
cursor: pointer; cursor: pointer;
color: ${props => (props.active ? props.theme.menu.activeTextColor : props.theme.menu.textColor)}; color: ${props =>
props.active ? props.theme.sidebar.activeTextColor : props.theme.sidebar.textColor};
margin: 0; margin: 0;
padding: 12.5px ${props => props.theme.spacing.unit * 4}px; padding: 12.5px ${props => props.theme.spacing.unit * 4}px;
${({ depth, type, theme }) => ${({ depth, type, theme }) =>
@ -144,10 +145,10 @@ export const MenuItemLabel = styled.label.attrs((props: MenuItemLabelType) => ({
} }
${ShelfIcon} { ${ShelfIcon} {
height: ${({ theme }) => theme.menu.arrow.size}; height: ${({ theme }) => theme.sidebar.arrow.size};
width: ${({ theme }) => theme.menu.arrow.size}; width: ${({ theme }) => theme.sidebar.arrow.size};
polygon { polygon {
fill: ${({ theme }) => theme.menu.arrow.color}; fill: ${({ theme }) => theme.sidebar.arrow.color};
} }
} }
`; `;
@ -172,8 +173,8 @@ export const RedocAttribution = styled.div`
a, a,
a:visited, a:visited,
a:hover { a:hover {
color: ${theme.menu.textColor} !important; color: ${theme.sidebar.textColor} !important;
border-top: 1px solid ${darken(0.1, theme.menu.backgroundColor)}; border-top: 1px solid ${darken(0.1, theme.sidebar.backgroundColor)};
padding: ${theme.spacing.unit}px 0; padding: ${theme.spacing.unit}px 0;
display: block; display: block;
} }

View File

@ -26,8 +26,8 @@ export interface StickySidebarState {
const stickyfill = Stickyfill && Stickyfill(); const stickyfill = Stickyfill && Stickyfill();
const StyledStickySidebar = styled.div<{ open?: boolean }>` const StyledStickySidebar = styled.div<{ open?: boolean }>`
width: ${props => props.theme.menu.width}; width: ${props => props.theme.sidebar.width};
background-color: ${props => props.theme.menu.backgroundColor}; background-color: ${props => props.theme.sidebar.backgroundColor};
overflow: hidden; overflow: hidden;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -44,7 +44,7 @@ const StyledStickySidebar = styled.div<{ open?: boolean }>`
position: fixed; position: fixed;
z-index: 20; z-index: 20;
width: 100%; width: 100%;
background: ${({ theme }) => theme.menu.backgroundColor}; background: ${({ theme }) => theme.sidebar.backgroundColor};
display: ${props => (props.open ? 'flex' : 'none')}; display: ${props => (props.open ? 'flex' : 'none')};
`}; `};

View File

@ -112,11 +112,18 @@ export class RedocNormalizedOptions {
return true; return true;
} }
if (typeof value === 'string') { if (typeof value !== 'string') {
return value.split(',').map(ext => ext.trim()); return value;
} }
return value; switch (value) {
case 'true':
return true;
case 'false':
return false;
default:
return value.split(',').map(ext => ext.trim());
}
} }
static normalizePayloadSampleIdx(value: RedocRawOptions['payloadSampleIdx']): number { static normalizePayloadSampleIdx(value: RedocRawOptions['payloadSampleIdx']): number {
@ -172,6 +179,18 @@ export class RedocNormalizedOptions {
constructor(raw: RedocRawOptions, defaults: RedocRawOptions = {}) { constructor(raw: RedocRawOptions, defaults: RedocRawOptions = {}) {
raw = { ...defaults, ...raw }; raw = { ...defaults, ...raw };
const hook = raw.theme && raw.theme.extensionsHook; const hook = raw.theme && raw.theme.extensionsHook;
// migrate from old theme
if ((raw.theme as any)?.menu && !raw.theme?.sidebar) {
console.warn('Theme setting "menu" is deprecated. Rename to "sidebar"');
raw.theme!.sidebar = (raw.theme as any).menu;
}
if ((raw.theme as any)?.codeSample && !raw.theme?.codeBlock) {
console.warn('Theme setting "codeSample" is deprecated. Rename to "codeBlock"');
raw.theme!.codeBlock = (raw.theme as any).codeSample;
}
this.theme = resolveTheme( this.theme = resolveTheme(
mergeObjects({} as any, defaultTheme, { ...raw.theme, extensionsHook: undefined }), mergeObjects({} as any, defaultTheme, { ...raw.theme, extensionsHook: undefined }),
); );

View File

@ -240,6 +240,15 @@ export class SchemaModel {
} }
const mapping = discriminator.mapping || {}; const mapping = discriminator.mapping || {};
// Defines if the mapping is exhaustive. This avoids having references
// that overlap with the mapping entries
let isLimitedToMapping = discriminator['x-explicitMappingOnly'] || false;
// if there are no mappings, assume non-exhaustive
if (Object.keys(mapping).length === 0) {
isLimitedToMapping = false;
}
const explicitInversedMapping = {}; const explicitInversedMapping = {};
for (const name in mapping) { for (const name in mapping) {
const $ref = mapping[name]; const $ref = mapping[name];
@ -252,9 +261,11 @@ export class SchemaModel {
} }
} }
const inversedMapping = { ...implicitInversedMapping, ...explicitInversedMapping }; const inversedMapping = isLimitedToMapping
? { ...explicitInversedMapping }
: { ...implicitInversedMapping, ...explicitInversedMapping };
const refs: Array<{ $ref; name }> = []; let refs: Array<{ $ref; name }> = [];
for (const $ref of Object.keys(inversedMapping)) { for (const $ref of Object.keys(inversedMapping)) {
const names = inversedMapping[$ref]; const names = inversedMapping[$ref];
@ -267,6 +278,35 @@ export class SchemaModel {
} }
} }
// Make the listing respects the mapping
// in case a mapping is defined, the user usually wants to have the order shown
// as it was defined in the yaml. This will sort the names given the provided
// mapping (if provided).
// The logic is:
// - If a name is among the mapping, promote it to first
// - Names among the mapping are sorted by their order in the mapping
// - Names outside the mapping are sorted alphabetically
const names = Object.keys(mapping);
if (names.length !== 0) {
refs = refs.sort((left, right) => {
const indexLeft = names.indexOf(left.name);
const indexRight = names.indexOf(right.name);
if (indexLeft < 0 && indexRight < 0) {
// out of mapping, order by name
return left.name.localeCompare(right.name);
} else if (indexLeft < 0) {
// the right is found, so mapping wins
return 1;
} else if (indexRight < 0) {
// left wins as it's in mapping
return -1;
} else {
return indexLeft - indexRight;
}
});
}
this.oneOf = refs.map(({ $ref, name }) => { this.oneOf = refs.map(({ $ref, name }) => {
const innerSchema = new SchemaModel(parser, parser.byRef($ref)!, $ref, this.options, true); const innerSchema = new SchemaModel(parser, parser.byRef($ref)!, $ref, this.options, true);
innerSchema.title = name; innerSchema.title = name;

View File

@ -20,13 +20,13 @@ const defaultTheme: ThemeInterface = {
contrastText: ({ colors }) => readableColor(colors.primary.main), contrastText: ({ colors }) => readableColor(colors.primary.main),
}, },
success: { success: {
main: '#00aa13', main: '#37d247',
light: ({ colors }) => lighten(colors.tonalOffset, colors.success.main), light: ({ colors }) => lighten(colors.tonalOffset * 2, colors.success.main),
dark: ({ colors }) => darken(colors.tonalOffset, colors.success.main), dark: ({ colors }) => darken(colors.tonalOffset, colors.success.main),
contrastText: ({ colors }) => readableColor(colors.success.main), contrastText: ({ colors }) => readableColor(colors.success.main),
}, },
warning: { warning: {
main: '#d4ad03', main: '#ffa500',
light: ({ colors }) => lighten(colors.tonalOffset, colors.warning.main), light: ({ colors }) => lighten(colors.tonalOffset, colors.warning.main),
dark: ({ colors }) => darken(colors.tonalOffset, colors.warning.main), dark: ({ colors }) => darken(colors.tonalOffset, colors.warning.main),
contrastText: '#ffffff', contrastText: '#ffffff',
@ -55,7 +55,7 @@ const defaultTheme: ThemeInterface = {
backgroundColor: ({ colors }) => transparentize(0.9, colors.error.main), backgroundColor: ({ colors }) => transparentize(0.9, colors.error.main),
}, },
redirect: { redirect: {
color: '#ffa500', color: ({ colors }) => colors.warning.main,
backgroundColor: ({ colors }) => transparentize(0.9, colors.responses.redirect.color), backgroundColor: ({ colors }) => transparentize(0.9, colors.responses.redirect.color),
}, },
info: { info: {
@ -122,13 +122,13 @@ const defaultTheme: ThemeInterface = {
hover: ({ typography }) => lighten(0.2, typography.links.color), hover: ({ typography }) => lighten(0.2, typography.links.color),
}, },
}, },
menu: { sidebar: {
width: '260px', width: '260px',
backgroundColor: '#fafafa', backgroundColor: '#fafafa',
textColor: '#333333', textColor: '#333333',
activeTextColor: theme => activeTextColor: theme =>
theme.menu.textColor !== defaultTheme.menu!.textColor theme.sidebar.textColor !== defaultTheme.sidebar!.textColor
? theme.menu.textColor ? theme.sidebar.textColor
: theme.colors.primary.main, : theme.colors.primary.main,
groupItems: { groupItems: {
textTransform: 'uppercase', textTransform: 'uppercase',
@ -138,12 +138,12 @@ const defaultTheme: ThemeInterface = {
}, },
arrow: { arrow: {
size: '1.5em', size: '1.5em',
color: theme => theme.menu.textColor, color: theme => theme.sidebar.textColor,
}, },
}, },
logo: { logo: {
maxHeight: ({ menu }) => menu.width, maxHeight: ({ sidebar: menu }) => menu.width,
maxWidth: ({ menu }) => menu.width, maxWidth: ({ sidebar: menu }) => menu.width,
gutter: '2px', gutter: '2px',
}, },
rightPanel: { rightPanel: {
@ -151,7 +151,7 @@ const defaultTheme: ThemeInterface = {
width: '40%', width: '40%',
textColor: '#ffffff', textColor: '#ffffff',
}, },
codeSample: { codeBlock: {
backgroundColor: ({ rightPanel }) => darken(0.1, rightPanel.backgroundColor), backgroundColor: ({ rightPanel }) => darken(0.1, rightPanel.backgroundColor),
}, },
}; };
@ -296,7 +296,7 @@ export interface ResolvedThemeInterface {
hover: string; hover: string;
}; };
}; };
menu: { sidebar: {
width: string; width: string;
backgroundColor: string; backgroundColor: string;
textColor: string; textColor: string;
@ -322,7 +322,7 @@ export interface ResolvedThemeInterface {
textColor: string; textColor: string;
width: string; width: string;
}; };
codeSample: { codeBlock: {
backgroundColor: string; backgroundColor: string;
}; };

View File

@ -144,6 +144,7 @@ export interface OpenAPISchema {
export interface OpenAPIDiscriminator { export interface OpenAPIDiscriminator {
propertyName: string; propertyName: string;
mapping?: { [name: string]: string }; mapping?: { [name: string]: string };
'x-explicitMappingOnly'?: boolean;
} }
export interface OpenAPIMediaType { export interface OpenAPIMediaType {

View File

@ -579,6 +579,7 @@ export function isRedocExtension(key: string): boolean {
'x-tagGroups': true, 'x-tagGroups': true,
'x-traitTag': true, 'x-traitTag': true,
'x-additionalPropertiesName': true, 'x-additionalPropertiesName': true,
'x-explicitMappingOnly': true,
}; };
return key in redocExtensions; return key in redocExtensions;