@@ -34,7 +34,7 @@ interface Props { | |||
noCopy?: boolean; | |||
render?: string; | |||
snippet: string | Array<string | undefined>; | |||
wrap?: boolean; | |||
wrap?: boolean | 'words'; | |||
} | |||
// keep this "useless" concatenation for the readability reason |
@@ -43,7 +43,7 @@ interface Props { | |||
className?: string; | |||
htmlAsString: string; | |||
language?: string; | |||
wrap?: boolean; | |||
wrap?: boolean | 'words'; | |||
} | |||
const CODE_REGEXP = '<(code|pre)\\b([^>]*?)>(.+?)<\\/\\1>'; | |||
@@ -93,7 +93,11 @@ export function CodeSyntaxHighlighter(props: Props) { | |||
return ( | |||
<StyledSpan | |||
className={classNames(`hljs ${className ?? ''}`, { 'code-wrap': wrap })} | |||
className={classNames( | |||
`hljs ${className ?? ''}`, | |||
{ 'code-wrap': wrap }, | |||
{ 'wrap-words': wrap === 'words' }, | |||
)} | |||
// Safe: value is escaped by highlight.js | |||
// eslint-disable-next-line react/no-danger | |||
dangerouslySetInnerHTML={{ __html: highlightedHtmlAsString }} | |||
@@ -153,6 +157,11 @@ const StyledSpan = styled.span` | |||
&.code-wrap { | |||
${tw`sw-whitespace-pre-wrap`} | |||
${tw`sw-break-all`} | |||
&.wrap-words { | |||
word-break: normal; | |||
${tw`sw-break-words`} | |||
} | |||
} | |||
mark { |
@@ -158,6 +158,11 @@ exports[`should highlight code content correctly 1`] = ` | |||
word-break: break-all; | |||
} | |||
.emotion-6.code-wrap.wrap-words { | |||
word-break: normal; | |||
overflow-wrap: break-word; | |||
} | |||
.emotion-6 mark { | |||
font-weight: 400; | |||
padding: 0.25rem; | |||
@@ -365,6 +370,11 @@ exports[`should show full size when multiline with no editing 1`] = ` | |||
word-break: break-all; | |||
} | |||
.emotion-6.code-wrap.wrap-words { | |||
word-break: normal; | |||
overflow-wrap: break-word; | |||
} | |||
.emotion-6 mark { | |||
font-weight: 400; | |||
padding: 0.25rem; | |||
@@ -576,6 +586,11 @@ exports[`should show reduced size when single line with no editing 1`] = ` | |||
word-break: break-all; | |||
} | |||
.emotion-6.code-wrap.wrap-words { | |||
word-break: normal; | |||
overflow-wrap: break-word; | |||
} | |||
.emotion-6 mark { | |||
font-weight: 400; | |||
padding: 0.25rem; |
@@ -155,7 +155,9 @@ it('should navigate between apis', async () => { | |||
expect(ui.requestHeader.query()).not.toBeInTheDocument(); | |||
expect(ui.requestBody.query()).not.toBeInTheDocument(); | |||
expect(ui.queryParameter.getAll()).toHaveLength(1); | |||
expect(ui.queryParameter.getAt(0)).toHaveTextContent('status ["available","pending","sold"]'); | |||
expect(ui.queryParameter.getAt(0)).toHaveTextContent( | |||
'status Enum (string): available, pending, sold', | |||
); | |||
expect(ui.queryParameter.getAt(0)).not.toHaveTextContent('default: available'); | |||
await user.click(ui.queryParameter.byRole('button').getAt(0)); | |||
expect(ui.queryParameter.getAt(0)).toHaveTextContent('default: available'); |
@@ -235,5 +235,5 @@ it('should map open api response schema', () => { | |||
type: 'string', | |||
enum: ['GREEN', 'YELLOW', 'RED'], | |||
}), | |||
).toStrictEqual(['GREEN', 'YELLOW', 'RED']); | |||
).toStrictEqual('Enum (string): GREEN, YELLOW, RED'); | |||
}); |
@@ -22,6 +22,7 @@ import { Accordion, Badge, SubHeading, SubTitle, TextMuted } from 'design-system | |||
import { groupBy } from 'lodash'; | |||
import { OpenAPIV3 } from 'openapi-types'; | |||
import React from 'react'; | |||
import { FormattedMessage } from 'react-intl'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { ExcludeReferences } from '../types'; | |||
import { mapOpenAPISchema } from '../utils'; | |||
@@ -89,6 +90,20 @@ export default function ApiParameters({ data }: Props) { | |||
open={openParameters.includes(parameter.name)} | |||
> | |||
<div>{parameter.description}</div> | |||
{parameter.schema?.enum && ( | |||
<div className="sw-mt-2"> | |||
<FormattedMessage | |||
id="api_documentation.v2.enum_description" | |||
values={{ | |||
values: ( | |||
<div className="sw-body-sm-highlight"> | |||
{parameter.schema.enum.join(', ')} | |||
</div> | |||
), | |||
}} | |||
/> | |||
</div> | |||
)} | |||
{parameter.schema?.maximum && ( | |||
<TextMuted | |||
className="sw-mt-2 sw-block" |
@@ -22,6 +22,7 @@ import { Accordion, Badge, TextMuted } from 'design-system'; | |||
import { isEmpty } from 'lodash'; | |||
import { OpenAPIV3 } from 'openapi-types'; | |||
import React from 'react'; | |||
import { FormattedMessage } from 'react-intl'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { ExcludeReferences } from '../types'; | |||
@@ -86,6 +87,16 @@ export default function ApiRequestBodyParameters({ content }: Readonly<Props>) { | |||
open={openParameters.includes(key)} | |||
> | |||
<div>{parameters[key].description}</div> | |||
{parameters[key].enum && ( | |||
<div className="sw-mt-2"> | |||
<FormattedMessage | |||
id="api_documentation.v2.enum_description" | |||
values={{ | |||
values: <i>{parameters[key].enum?.join(', ')}</i>, | |||
}} | |||
/> | |||
</div> | |||
)} | |||
{parameters[key].maxLength && ( | |||
<TextMuted | |||
className="sw-mt-2 sw-block" |
@@ -29,7 +29,7 @@ interface Props extends Omit<HtmlHTMLAttributes<HTMLDivElement>, 'content'> { | |||
content?: Exclude<ExcludeReferences<OpenAPIV3.ResponseObject>['content'], undefined>; | |||
} | |||
export default function ApiResponseSchema(props: Props) { | |||
export default function ApiResponseSchema(props: Readonly<Props>) { | |||
const { content, ...other } = props; | |||
const schema = | |||
content && | |||
@@ -43,7 +43,7 @@ export default function ApiResponseSchema(props: Props) { | |||
language="json" | |||
className="sw-p-6" | |||
snippet={JSON.stringify(mapOpenAPISchema(schema), null, 2)} | |||
wrap | |||
wrap="words" | |||
{...other} | |||
/> | |||
); |
@@ -36,8 +36,8 @@ export const mapOpenAPISchema = ( | |||
if (schema.type === 'array') { | |||
return [mapOpenAPISchema(schema.items)]; | |||
} | |||
if (schema.type === 'string' && schema.enum) { | |||
return schema.enum as ConvertedSchema; | |||
if (schema.enum) { | |||
return `Enum (${schema.type}): ${(schema.enum as ConvertedSchema[]).join(', ')}`; | |||
} | |||
if (schema.format) { | |||
return `${schema.type} (${schema.format})`; |
@@ -4045,6 +4045,7 @@ api_documentation.v2.request_subheader.query=Query Parameters | |||
api_documentation.v2.request_subheader.path=Path Parameters | |||
api_documentation.v2.request_subheader.header=Headers | |||
api_documentation.v2.request_subheader.request_body=Request Body | |||
api_documentation.v2.enum_description=Valid values: {values} | |||
#------------------------------------------------------------------------------ |