Compare commits

..

No commits in common. "main" and "v2.2.0" have entirely different histories.
main ... v2.2.0

44 changed files with 1097 additions and 1784 deletions

View File

@ -21,7 +21,7 @@ jobs:
- run: npm ci
- run: npm run bundle
- name: Store bundle artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: bundles
path: bundles
@ -39,7 +39,7 @@ jobs:
- uses: actions/checkout@v3
- run: npm ci
- name: Download bundled artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v3
with:
name: bundles
path: bundles
@ -73,7 +73,7 @@ jobs:
registry-url: 'https://registry.npmjs.org'
- uses: actions/checkout@v3
- name: Download bundled artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v3
with:
name: bundles
path: bundles
@ -107,7 +107,7 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Download all artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v3
- name: Publish to S3
run: npm run publish-cdn

View File

@ -1,48 +1,3 @@
# [2.5.0](https://github.com/Redocly/redoc/compare/v2.4.0...v2.5.0) (2025-04-14)
### Bug Fixes
* enhance accessibility for menu items with keyboard support ([#2655](https://github.com/Redocly/redoc/issues/2655)) ([2db293b](https://github.com/Redocly/redoc/commit/2db293bfb2973497dd33f31dc99e97f5bb90bbe8))
### Features
* add keyboard navigation support to JsonViewer component ([#2654](https://github.com/Redocly/redoc/issues/2654)) ([1b4126f](https://github.com/Redocly/redoc/commit/1b4126fde4531387f49c90f52efbd0c0e5f7b6ea))
# [2.4.0](https://github.com/Redocly/redoc/compare/v2.3.0...v2.4.0) (2025-02-07)
### Bug Fixes
* Prototype Pollution Vulnerability Affecting redoc <=2.2.0 ([#2638](https://github.com/Redocly/redoc/issues/2638)) ([153ec7a](https://github.com/Redocly/redoc/commit/153ec7a0b7245639f404c0b038b612ae7377c7db))
* unify redoc config ([#2647](https://github.com/Redocly/redoc/issues/2647)) ([53a6afc](https://github.com/Redocly/redoc/commit/53a6afc59624fe4591b0a0f1f20f41c0fbb5f1cf))
### Features
* add supporting react 19 in package.json ([#2652](https://github.com/Redocly/redoc/issues/2652)) ([3a74802](https://github.com/Redocly/redoc/commit/3a748022be3a7dc7f98669e1645dd5cda72f1abc))
# [2.3.0](https://github.com/Redocly/redoc/compare/v2.2.0...v2.3.0) (2025-01-16)
### Bug Fixes
* displaying json example when showObjectSchemaExamples enabled ([#2635](https://github.com/Redocly/redoc/issues/2635)) ([59ee73f](https://github.com/Redocly/redoc/commit/59ee73fefa8e8edb398940076bdd721fc284caa3))
* displaying nested items with type string ([#2634](https://github.com/Redocly/redoc/issues/2634)) ([85b622f](https://github.com/Redocly/redoc/commit/85b622fc581eb96303aeb85056aef36c74ea9f9d))
* passing inline parameters after support react 18 for response title ([#2640](https://github.com/Redocly/redoc/issues/2640)) ([d614d2d](https://github.com/Redocly/redoc/commit/d614d2d022df8bd1989cb0eaf76d087b52120d36))
### Features
* update pattern styling ([#2196](https://github.com/Redocly/redoc/issues/2196)) ([#2600](https://github.com/Redocly/redoc/issues/2600)) ([aa0879c](https://github.com/Redocly/redoc/commit/aa0879ca0235112918428fdff8f4c48d2c6c4adf))
# [2.2.0](https://github.com/Redocly/redoc/compare/v2.1.5...v2.2.0) (2024-10-16)

View File

@ -122,8 +122,10 @@ Redoc uses the following [specification extensions](https://redocly.com/docs/api
* [`x-displayName`](docs/redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories
* [`x-tagGroups`](docs/redoc-vendor-extensions.md#x-tagGroups) - group tags by categories in the side menu
* [`x-servers`](docs/redoc-vendor-extensions.md#x-servers) - ability to specify different servers for API (backported from OpenAPI 3.0)
* [`x-ignoredHeaderParameters`](docs/redoc-vendor-extensions.md#x-ignoredHeaderParameters) - ability to specify header parameter names to ignore
* [`x-additionalPropertiesName`](docs/redoc-vendor-extensions.md#x-additionalPropertiesName) - ability to supply a descriptive name for the additional property keys
* [`x-summary`](docs/redoc-vendor-extensions.md#x-summary) - for Response object, use as the response button text, with description rendered under the button
* [`x-extendedDiscriminator`](docs/redoc-vendor-extensions.md#x-extendedDiscriminator) - in Schemas, uses this to solve name-clash issues with the standard discriminator
* [`x-explicitMappingOnly`](docs/redoc-vendor-extensions.md#x-explicitMappingOnly) - in Schemas, display a more descriptive property name in objects with additionalProperties when viewing the property list with an object
## Releases

View File

@ -122,7 +122,7 @@ class DemoApp extends React.Component<
<RedocStandalone
spec={this.state.spec}
specUrl={proxiedUrl}
options={{ scrollYOffset: 'nav', sanitize: true }}
options={{ scrollYOffset: 'nav', untrustedSpec: true }}
/>
</>
);

View File

@ -309,9 +309,6 @@ components:
enum:
- event
- general
x-enumDescriptions:
event: Special event ticket
general: General museum entry ticket
example: event
Date:
type: string
@ -779,9 +776,6 @@ x-tagGroups:
- name: Purchases
tags:
- Tickets
- name: Entities
tags:
- Schemas
security:
- MuseumPlaceholderAuth: []

View File

@ -1083,10 +1083,6 @@ components:
- available
- pending
- sold
x-enumDescriptions:
available: Available status
pending: Pending status
sold: Sold status
petType:
description: Type of a pet
type: string

View File

@ -11,11 +11,7 @@ const userUrl = window.location.search.match(/url=(.*)$/);
const specUrl =
(userUrl && userUrl[1]) || (swagger ? 'museum.yaml' : big ? 'big-openapi.json' : 'museum.yaml');
const options: RedocRawOptions = {
nativeScrollbars: false,
maxDisplayedEnumValues: 3,
schemaDefinitionsTagName: 'schemas',
};
const options: RedocRawOptions = { nativeScrollbars: false, maxDisplayedEnumValues: 3 };
const container = document.getElementById('example');
const root = createRoot(container!);

View File

@ -26,19 +26,59 @@ Sets the minimum amount of characters that need to be typed into the search dial
_Default: 3_
### hideDownloadButtons
### expandDefaultServerVariables
Enables or disables expanding default server variables.
### expandResponses
Controls which responses to expand by default. Specify one or more responses by providing their response codes as a comma-separated list without spaces, for example `expandResponses='200,201'`. Special value 'all' expands all responses by default. Be careful: this option can slow down documentation rendering time.
### expandSingleSchemaField
Automatically expands the single field in a schema.
### hideDownloadButton
Hides the 'Download' button for saving the API definition source file. **This setting does not make the API definition private**; it just hides the button.
### hideHostname
If set to `true`, the protocol and hostname are not shown in the operation definition.
### hideLoading
Hides the loading animation. Does not apply to CLI or Workflows-rendered docs.
### hideRequestPayloadSample
Hides request payload examples.
### hideOneOfDescription
If set to `true`, the description for `oneOf`/`anyOf` object is not shown in the schema.
### hideSchemaPattern
If set to `true`, the pattern is not shown in the schema.
### hideSchemaTitles
Hides the schema title next to to the type.
### jsonSamplesExpandLevel
### hideSecuritySection
Hides the Security panel section.
### hideSingleRequestSampleTab
Hides the request sample tab for requests with only one sample.
### htmlTemplate
Sets the path to the optional HTML file used to modify the layout of the reference docs page.
### jsonSampleExpandLevel
Sets the default expand level for JSON payload samples (response and request body). The default value is 2, and the maximum supported value is '+Infinity'. It can also be configured as a string with the special value `all` that expands all levels.
@ -48,17 +88,35 @@ _Default: 2_
Displays only the specified number of enum values. The remaining values are hidden in an expandable area. If not set, all values are displayed.
### menuToggle
If set to `true`, selecting an expanded item in the sidebar twice collapses it.
_Default: true_
### nativeScrollbars
If set to `true`, the sidebar uses the native scrollbar instead of perfect-scroll. This setting is a scrolling performance optimization for big API definitions.
### onlyRequiredInSamples
Shows only required fields in request samples.
### sortRequiredPropsFirst
### pathInMiddlePanel
Shows the path link and HTTP verb in the middle panel instead of the right panel.
### payloadSampleIdx
If set, the payload sample is inserted at the specified index. If there are `N` payload samples and the value configured here is bigger than `N`, the payload sample is inserted last. Indexes start from 0.
### requiredPropsFirst
Shows required properties in schemas first, ordered in the same order as in the required array.
### schemasExpansionLevel
### schemaExpansionLevel
Specifies whether to automatically expand schemas in Reference docs. Set it to `all` to expand all schemas regardless of their level, or set it to a number to expand schemas up to the specified level. For example, `schemasExpansionLevel: 3` expands schemas up to three levels deep. The default value is `0`, meaning no schemas are expanded automatically.
Specifies whether to automatically expand schemas in Reference docs. Set it to `all` to expand all schemas regardless of their level, or set it to a number to expand schemas up to the specified level. For example, `schemaExpansionLevel: 3` expands schemas up to three levels deep. The default value is `0`, meaning no schemas are expanded automatically.
### scrollYOffset
@ -74,111 +132,6 @@ Note that you can specify the `scrollYOffset` value in any of the following ways
Shows specification extensions ('x-' fields). Extensions used by Redoc are ignored. The value can be boolean or an array of strings with names of extensions to display. When used as boolean and set to `true`, all specification extensions are shown.
### sanitize
If set to `true`, the API definition is considered untrusted and all HTML/Markdown is sanitized to prevent XSS.
### downloadUrls
Set the URLs used to download the OpenAPI description or other documentation related files from the API documentation page.
### schemaDefinitionsTagName
If a value is set, all of the schemas are rendered with the designated tag name. The schemas then render and display in the sidebar navigation (with that associated tag name).
### generatedSamplesMaxDepth
The generatedSamplesMaxDepth option controls how many schema levels automatically generated for payload samples. The default is 8 which works well for most APIs, but you can adjust it if necessary for your use case.
### hidePropertiesPrefix
In complex data structures or object schemas where properties are nested within parent objects the hidePropertiesPrefix option enables the hiding of parent names for nested properties within the documentation.
_Default: true_
## Deprecated Functional settings
### hideDownloadButton
Hides the 'Download' button for saving the API definition source file. **This setting does not make the API definition private**; it just hides the button.
### downloadFileName
Sets the filename for the downloaded API definition source file.
### downloadDefinitionUrl
Sets the URL for the downloaded API definition source file.
### requiredPropsFirst
Shows required properties in schemas first, ordered in the same order as in the required array.
### jsonSampleExpandLevel
Sets the default expand level for JSON payload samples (response and request body). The default value is 2, and the maximum supported value is '+Infinity'. It can also be configured as a string with the special value `all` that expands all levels.
_Default: 2_
### schemaExpansionLevel
Specifies whether to automatically expand schemas in Reference docs. Set it to `all` to expand all schemas regardless of their level, or set it to a number to expand schemas up to the specified level. For example, `schemaExpansionLevel: 3` expands schemas up to three levels deep. The default value is `0`, meaning no schemas are expanded automatically.
### expandDefaultServerVariables
Enables or disables expanding default server variables.
### expandResponses
Controls which responses to expand by default. Specify one or more responses by providing their response codes as a comma-separated list without spaces, for example `expandResponses='200,201'`. Special value 'all' expands all responses by default. Be careful: this option can slow down documentation rendering time.
### expandSingleSchemaField
Automatically expands the single field in a schema.
### hideHostname
If set to `true`, the protocol and hostname are not shown in the operation definition.
### hideRequestPayloadSample
Hides request payload examples.
### hideOneOfDescription
If set to `true`, the description for `oneOf`/`anyOf` object is not shown in the schema.
### hideSchemaPattern
If set to `true`, the pattern is not shown in the schema.
### hideSecuritySection
Hides the Security panel section.
### hideSingleRequestSampleTab
Hides the request sample tab for requests with only one sample.
### menuToggle
If set to `true`, selecting an expanded item in the sidebar twice collapses it.
_Default: true_
### nativeScrollbars
If set to `true`, the sidebar uses the native scrollbar instead of perfect-scroll. This setting is a scrolling performance optimization for big API definitions.
### pathInMiddlePanel
Shows the path link and HTTP verb in the middle panel instead of the right panel.
### payloadSampleIdx
If set, the payload sample is inserted at the specified index. If there are `N` payload samples and the value configured here is bigger than `N`, the payload sample is inserted last. Indexes start from 0.
### showObjectSchemaExamples
Shows object schema example in the properties; default `false`.
@ -209,12 +162,12 @@ When set to true, sorts tags in the navigation sidebar and in the middle panel a
_Default: false_
### untrustedSpec
### untrustedDefinition
If set to `true`, the API definition is considered untrusted and all HTML/Markdown is sanitized to prevent XSS.
## Theme settings
Change styles for the API documentation page. **Supported in Redoc CE 2.x**.
* `spacing`
* `unit`: 5 # main spacing unit used in autocomputed theme values later
* `sectionHorizontal`: 40 # Horizontal section padding. COMPUTED: spacing.unit * 8
@ -295,7 +248,7 @@ For more information, refer to [Security definitions injection](./security-defin
### OpenAPI specification extensions
Redoc uses the following [specification extensions](https://redocly.com/docs-legacy/api-reference-docs/spec-extensions/):
Redoc uses the following [specification extensions](https://redocly.com/docs/api-reference-docs/spec-extensions/):
* [`x-logo`](./redoc-vendor-extensions.md#x-logo) - is used to specify API logo
* [`x-traitTag`](./redoc-vendor-extensions.md#x-traittag) - useful for handling out common things like Pagination, Rate-Limits, etc
* [`x-codeSamples`](./redoc-vendor-extensions.md#x-codesamples) - specify operation code samples
@ -304,8 +257,10 @@ Redoc uses the following [specification extensions](https://redocly.com/docs-leg
* [`x-displayName`](./redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories
* [`x-tagGroups`](./redoc-vendor-extensions.md#x-taggroups) - group tags by categories in the side menu
* [`x-servers`](./redoc-vendor-extensions.md#x-servers) - ability to specify different servers for API (backported from OpenAPI 3.0)
* [`x-ignoredHeaderParameters`](./redoc-vendor-extensions.md#x-ignoredheaderparameters) - ability to specify header parameter names to ignore
* [`x-additionalPropertiesName`](./redoc-vendor-extensions.md#x-additionalpropertiesname) - ability to supply a descriptive name for the additional property keys
* [`x-summary`](./redoc-vendor-extensions.md#x-summary) - For Response object, use as the response button text, with description rendered under the button
* [`x-extendedDiscriminator`](./redoc-vendor-extensions.md#x-extendeddiscriminator) - In Schemas, uses this to solve name-clash issues with the standard discriminator
* [`x-explicitMappingOnly`](./redoc-vendor-extensions.md#x-explicitmappingonly) - In Schemas, display a more descriptive property name in objects with additionalProperties when viewing the property list with an object

View File

@ -67,7 +67,7 @@ theme:
openapi:
disableSearch: true
expandResponses: 200,202
jsonSamplesExpandLevel: 1
jsonSampleExpandLevel: 1
theme:
sidebar:

View File

@ -44,7 +44,7 @@ replace the `spec-url` attribute with the URL or local file address to your defi
</html>
```
{% admonition type="info" name="Redoc requires an HTTP server to run locally" %}
{% admonition type="attention" name="Redoc requires an HTTP server to run locally" %}
Loading local OpenAPI definitions is impossible without running a web server because of issues with
[same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy) and
other security reasons. Refer to [Running Redoc locally](./deployment/intro.md#how-to-run-redoc-locally) for more information.

View File

@ -10,6 +10,9 @@ You can use the following [vendor extensions](https://redocly.com/docs/openapi-v
- [Tag Group Object](#tag-group-object)
- [Fixed fields](#fixed-fields)
- [x-tagGroups example](#x-taggroups-example)
- [x-ignoredHeaderParameters](#x-ignoredheaderparameters)
- [How to use with Redoc](#how-to-use-with-redoc-1)
- [x-ignoredHeaderParameters example](#x-ignoredheaderparameters-example)
- [Info Object](#info-object)
- [x-logo](#x-logo)
- [How to use with Redoc](#how-to-use-with-redoc-2)
@ -36,21 +39,21 @@ You can use the following [vendor extensions](https://redocly.com/docs/openapi-v
- [Schema Object](#schema-object)
- [x-nullable](#x-nullable)
- [How to use with Redoc](#how-to-use-with-redoc-7)
- [x-extendedDiscriminator](#x-extendeddiscriminator)
- [How to use with Redoc](#how-to-use-with-redoc-8)
- [x-extendedDiscriminator example](#x-extendeddiscriminator-example)
- [x-additionalPropertiesName](#x-additionalpropertiesname)
- [How to use with Redoc](#how-to-use-with-redoc-9)
- [x-additionalPropertiesName example](#x-additionalpropertiesname-example)
- [x-explicitMappingOnly](#x-explicitmappingonly)
- [How to use with Redoc](#how-to-use-with-redoc-10)
- [x-explicitMappingOnly example](#x-explicitmappingonly-example)
- [x-enumDescriptions](#x-enumdescriptions)
- [How to use with Redoc](#how-to-use-with-redoc-11)
- [x-enumDescriptions example](#x-enumdescriptions-example)
## Swagger Object
Extends the OpenAPI root [OpenAPI Object](https://redocly.com/docs/openapi-visual-reference/openapi)
### x-servers
Backported from OpenAPI 3.0 [`servers`](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#server-object). Currently doesn't support templates.
Backported from OpenAPI 3.0 [`servers`](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#serverObject). Currently doesn't support templates.
### x-tagGroups
@ -102,6 +105,29 @@ x-tagGroups:
- Secondary Stats
```
### x-ignoredHeaderParameters
| Field Name | Type | Description |
| :-------------------------- | :-----------: | :---------- |
| x-ignoredHeaderParameters | [ string ] | A list of ignored headers |
#### How to use with Redoc
Use `x-ignoredHeaderParameters` to specify header parameter names which are ignored by Redoc.
#### x-ignoredHeaderParameters example
```yaml
swagger: '2.0'
info:
...
tags: [...]
x-ignoredHeaderParameters:
- Accept
- User-Agent
- X-Test-Header
```
## Info Object
Extends the OpenAPI [Info Object](https://redocly.com/docs/openapi-visual-reference/info/)
@ -264,6 +290,59 @@ Extends the OpenAPI [Schema Object](https://redocly.com/docs/openapi-visual-refe
#### How to use with Redoc
Schemas marked as `x-nullable` are marked in Redoc with the label Nullable.
### x-extendedDiscriminator
**ATTENTION**: This is a Redoc-specific vendor extension, and is not supported by other tools.
| Field Name | Type | Description |
| :------------- | :------: | :---------- |
| x-extendedDiscriminator | string | specifies extended discriminator |
#### How to use with Redoc
Redoc uses this vendor extension to solve name-clash issues with the standard `discriminator`.
Value of this field specifies the field which is used as an extended discriminator.
Redoc displays definition with selectpicker using which user can select value of the `x-extendedDiscriminator`-marked field.
Redoc displays the definition derived from the current (using `allOf`) and has `enum` with only one value which is the same as the selected value of the field specified as `x-extendedDiscriminator`.
#### x-extendedDiscriminator example
```yaml
Payment:
x-extendedDiscriminator: type
type: object
required:
- type
properties:
type:
type: string
name:
type: string
CashPayment:
allOf:
- $ref: "#/definitions/Payment"
- properties:
type:
type: string
enum:
- cash
currency:
type: string
PayPalPayment:
allOf:
- $ref: "#/definitions/Payment"
- properties:
type:
type: string
enum:
- paypal
userEmail:
type: string
```
In the example above, the names of definitions (`PayPalPayment`) are named differently than names in the payload (`paypal`) which is not supported by default `discriminator`.
### x-additionalPropertiesName
**Attention**: This is a Redoc-specific vendor extension, and is not supported by other tools.
@ -323,31 +402,3 @@ Pet:
```
Shows in the selectpicker only the items `cat` and `bee`, even though the `Dog` class inherits from the `Pet` class.
### x-enumDescriptions
| Field Name | Type | Description |
| :------------- | :------: | :---------- |
| x-enumDescriptions | [[Enum Description Object](https://redocly.com/docs/realm/author/reference/openapi-extensions/x-enum-descriptions#enum-description-object)] | A list of the enum values and descriptions to include in the documentation. |
#### How to use with Redoc
The enum (short for "enumeration") fields in OpenAPI allow you to restrict the value of a field to a list of allowed values. These values need to be short and machine-readable, but that can make them harder for humans to parse and work with.
Add x-enumDescriptions to your OpenAPI description to show a helpful table of enum options and an explanation of what each one means. This field supports Markdown.
#### x-enumDescriptions example
The following example shows a schema with two short-named options, and the x-enumDescriptions entry to list all enum entries and give additional context for each:
```yaml
components:
schemas:
TicketType:
description: Type of ticket being purchased. Use `general` for regular museum entry and `event` for tickets to special events.
type: string
enum:
- event
- general
x-enumDescriptions:
event: Event Tickets _(timed entry)_
general: General Admission
example: event
```

1741
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "redoc",
"version": "2.5.0",
"version": "2.2.0",
"description": "ReDoc",
"repository": {
"type": "git",
@ -61,7 +61,6 @@
"pre-commit": "pretty-quick --staged && npm run lint"
},
"devDependencies": {
"@cfaester/enzyme-adapter-react-18": "^0.8.0",
"@cypress/webpack-preprocessor": "^5.17.1",
"@size-limit/file": "^11.1.4",
"@types/chai": "^4.2.18",
@ -93,7 +92,7 @@
"cypress": "^13.8.1",
"enzyme": "^3.11.0",
"enzyme-to-json": "^3.6.2",
"esbuild-loader": "^4.3.0",
"esbuild-loader": "^3.0.1",
"eslint": "^7.27.0",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-react": "^7.34.2",
@ -124,7 +123,7 @@
"typescript": "^4.9.0",
"unfetch": "^4.2.0",
"url": "^0.11.1",
"webpack": "^5.94.0",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"webpack-node-externals": "^3.0.0",
@ -133,15 +132,16 @@
"peerDependencies": {
"core-js": "^3.1.4",
"mobx": "^6.0.4",
"react": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^16.8.4 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0",
"styled-components": "^4.1.1 || ^5.1.1 || ^6.0.5"
},
"dependencies": {
"@cfaester/enzyme-adapter-react-18": "^0.8.0",
"@redocly/openapi-core": "^1.4.0",
"classnames": "^2.3.2",
"decko": "^1.2.0",
"dompurify": "^3.2.4",
"dompurify": "^3.0.6",
"eventemitter3": "^5.0.1",
"json-pointer": "^0.6.2",
"lunr": "^2.3.9",

View File

@ -97,11 +97,9 @@ export const RecursiveLabel = styled(FieldLabel)`
export const PatternLabel = styled(FieldLabel)`
color: #0e7c86;
font-family: ${props => props.theme.typography.code.fontFamily};
font-size: 12px;
&::before,
&::after {
content: ' ';
font-weight: bold;
}
`;

View File

@ -22,13 +22,20 @@ export interface ApiInfoProps {
@observer
export class ApiInfo extends React.Component<ApiInfoProps> {
handleDownloadClick = e => {
if (!e.target.href) {
e.target.href = this.props.store.spec.info.downloadLink;
}
};
render() {
const { store } = this.props;
const { info, externalDocs } = store.spec;
const hideDownloadButtons = store.options.hideDownloadButtons;
const hideDownloadButton = store.options.hideDownloadButton;
const downloadFilename = info.downloadFileName;
const downloadLink = info.downloadLink;
const downloadUrls = info.downloadUrls;
const downloadFileName = info.downloadFileName;
const license =
(info.license && (
<InfoSpan>
@ -76,22 +83,17 @@ export class ApiInfo extends React.Component<ApiInfoProps> {
<ApiHeader>
{info.title} {version}
</ApiHeader>
{!hideDownloadButtons && (
{!hideDownloadButton && (
<p>
{l('downloadSpecification')}:
{downloadUrls?.map(({ title, url }) => {
return (
<DownloadButton
download={downloadFileName || true}
target="_blank"
href={url}
rel="noreferrer"
key={url}
>
{title}
</DownloadButton>
);
})}
<DownloadButton
download={downloadFilename || true}
target="_blank"
href={downloadLink}
onClick={this.handleDownloadClick}
>
{l('download')}
</DownloadButton>
</p>
)}
<StyledMarkdownBlock>

View File

@ -18,6 +18,14 @@ export function ArrayItemDetails({ schema }: { schema: SchemaModel }) {
return null;
}
if (schema.type === 'string' && schema.pattern) {
return (
<Wrapper>
[<Pattern schema={schema} />]
</Wrapper>
);
}
return (
<Wrapper>
[ items

View File

@ -5,29 +5,17 @@ import { l } from '../../services/Labels';
import { OptionsContext } from '../OptionsProvider';
import styled from '../../styled-components';
import { RedocRawOptions } from '../../services/RedocNormalizedOptions';
import { StyledMarkdownBlock } from '../Markdown/styled.elements';
import { Markdown } from '../Markdown/Markdown';
export interface EnumValuesProps {
values?: string[] | { [name: string]: string };
type: string | string[];
values: string[];
isArrayType: boolean;
}
export interface EnumValuesState {
collapsed: boolean;
}
const DescriptionEnumsBlock = styled(StyledMarkdownBlock)`
table {
margin-bottom: 0.2em;
}
`;
export class EnumValues extends React.PureComponent<EnumValuesProps, EnumValuesState> {
constructor(props: EnumValuesProps) {
super(props);
this.toggle = this.toggle.bind(this);
}
state: EnumValuesState = {
collapsed: true,
};
@ -39,94 +27,54 @@ export class EnumValues extends React.PureComponent<EnumValuesProps, EnumValuesS
}
render() {
const { values, type } = this.props;
const { values, isArrayType } = this.props;
const { collapsed } = this.state;
const isDescriptionEnum = !Array.isArray(values);
const enums =
(Array.isArray(values) && values) ||
Object.entries(values || {}).map(([value, description]) => ({
value,
description,
}));
// TODO: provide context interface in more elegant way
const { enumSkipQuotes, maxDisplayedEnumValues } = this.context as RedocRawOptions;
if (!enums.length) {
if (!values.length) {
return null;
}
const displayedItems =
this.state.collapsed && maxDisplayedEnumValues
? enums.slice(0, maxDisplayedEnumValues)
: enums;
? values.slice(0, maxDisplayedEnumValues)
: values;
const showToggleButton = maxDisplayedEnumValues ? enums.length > maxDisplayedEnumValues : false;
const showToggleButton = maxDisplayedEnumValues
? values.length > maxDisplayedEnumValues
: false;
const toggleButtonText = maxDisplayedEnumValues
? collapsed
? `${enums.length - maxDisplayedEnumValues} more`
? `${values.length - maxDisplayedEnumValues} more`
: 'Hide'
: '';
return (
<div>
{isDescriptionEnum ? (
<>
<DescriptionEnumsBlock>
<table>
<thead>
<tr>
<th>
<FieldLabel>
{type === 'array' ? l('enumArray') : ''}{' '}
{enums.length === 1 ? l('enumSingleValue') : l('enum')}
</FieldLabel>{' '}
</th>
<th>
<strong>Description</strong>
</th>
</tr>
</thead>
<tbody>
{(displayedItems as { value: string; description: string }[]).map(
({ description, value }) => {
return (
<tr key={value}>
<td>{value}</td>
<td>
<Markdown source={description} compact inline />
</td>
</tr>
);
},
)}
</tbody>
</table>
</DescriptionEnumsBlock>
{showToggleButton ? (
<ToggleButton onClick={this.toggle}>{toggleButtonText}</ToggleButton>
) : null}
</>
) : (
<>
<FieldLabel>
{type === 'array' ? l('enumArray') : ''}{' '}
{values.length === 1 ? l('enumSingleValue') : l('enum')}:
</FieldLabel>{' '}
{displayedItems.map((value, idx) => {
const exampleValue = enumSkipQuotes ? String(value) : JSON.stringify(value);
return (
<React.Fragment key={idx}>
<ExampleValue>{exampleValue}</ExampleValue>{' '}
</React.Fragment>
);
})}
{showToggleButton ? (
<ToggleButton onClick={this.toggle}>{toggleButtonText}</ToggleButton>
) : null}
</>
)}
<FieldLabel>
{isArrayType ? l('enumArray') : ''}{' '}
{values.length === 1 ? l('enumSingleValue') : l('enum')}:
</FieldLabel>{' '}
{displayedItems.map((value, idx) => {
const exampleValue = enumSkipQuotes ? String(value) : JSON.stringify(value);
return (
<React.Fragment key={idx}>
<ExampleValue>{exampleValue}</ExampleValue>{' '}
</React.Fragment>
);
})}
{showToggleButton ? (
<ToggleButton
onClick={() => {
this.toggle();
}}
>
{toggleButtonText}
</ToggleButton>
) : null}
</div>
);
}

View File

@ -19,8 +19,6 @@ import { Schema } from '../Schema/Schema';
import type { SchemaOptions } from '../Schema/Schema';
import type { FieldModel } from '../../services/models';
import { OptionsContext } from '../OptionsProvider';
import { RedocNormalizedOptions } from '../../services/RedocNormalizedOptions';
export interface FieldProps extends SchemaOptions {
className?: string;
@ -29,15 +27,12 @@ export interface FieldProps extends SchemaOptions {
field: FieldModel;
expandByDefault?: boolean;
fieldParentsName?: string[];
renderDiscriminatorSwitch?: (opts: FieldProps) => JSX.Element;
}
@observer
export class Field extends React.Component<FieldProps> {
static contextType = OptionsContext;
context: RedocNormalizedOptions;
toggle = () => {
if (this.props.field.expanded === undefined && this.props.expandByDefault) {
this.props.field.collapse();
@ -54,12 +49,12 @@ export class Field extends React.Component<FieldProps> {
};
render() {
const { hidePropertiesPrefix } = this.context;
const { className = '', field, isLast, expandByDefault, fieldParentsName = [] } = this.props;
const { className = '', field, isLast, expandByDefault } = this.props;
const { name, deprecated, required, kind } = field;
const withSubSchema = !field.schema.isPrimitive && !field.schema.isCircular;
const expanded = field.expanded === undefined ? expandByDefault : field.expanded;
const labels = (
<>
{kind === 'additionalProperties' && <PropertyLabel>additional property</PropertyLabel>}
@ -80,10 +75,6 @@ export class Field extends React.Component<FieldProps> {
onKeyPress={this.handleKeyPress}
aria-label={`expand ${name}`}
>
{!hidePropertiesPrefix &&
fieldParentsName.map(
name => name + '.\u200B', // zero-width space, a special character is used for correct line breaking
)}
<span className="property-name">{name}</span>
<ShelfIcon direction={expanded ? 'down' : 'right'} />
</button>
@ -92,10 +83,6 @@ export class Field extends React.Component<FieldProps> {
) : (
<PropertyNameCell className={deprecated ? 'deprecated' : undefined} kind={kind} title={name}>
<PropertyBullet />
{!hidePropertiesPrefix &&
fieldParentsName.map(
name => name + '.\u200B', // zero-width space, a special character is used for correct line breaking
)}
<span className="property-name">{name}</span>
{labels}
</PropertyNameCell>
@ -115,7 +102,6 @@ export class Field extends React.Component<FieldProps> {
<InnerPropertiesWrap>
<Schema
schema={field.schema}
fieldParentsName={[...(fieldParentsName || []), field.name]}
skipReadOnly={this.props.skipReadOnly}
skipWriteOnly={this.props.skipWriteOnly}
showTitle={this.props.showTitle}

View File

@ -8,7 +8,7 @@ import {
TypePrefix,
TypeTitle,
} from '../../common-elements/fields';
import { getSerializedValue, isArray, isObject } from '../../utils';
import { getSerializedValue, isObject } from '../../utils';
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
import { Markdown } from '../Markdown/Markdown';
import { EnumValues } from './EnumValues';
@ -30,8 +30,7 @@ export const FieldDetailsComponent = observer((props: FieldProps) => {
const { showExamples, field, renderDiscriminatorSwitch } = props;
const { schema, description, deprecated, extensions, in: _in, const: _const } = field;
const isArrayType =
schema.type === 'array' || (isArray(schema.type) && schema.type.includes('array'));
const isArrayType = schema.type === 'array';
const rawDefault = enumSkipQuotes || _in === 'header'; // having quotes around header field default values is confusing and inappropriate
@ -99,7 +98,7 @@ export const FieldDetailsComponent = observer((props: FieldProps) => {
)}
<FieldDetail raw={rawDefault} label={l('default') + ':'} value={defaultValue} />
{!renderDiscriminatorSwitch && (
<EnumValues type={schema.type} values={schema['x-enumDescriptions'] || schema.enum} />
<EnumValues isArrayType={isArrayType} values={schema.enum} />
)}{' '}
{renderedExamples}
<Extensions extensions={{ ...extensions, ...schema.extensions }} />

View File

@ -41,12 +41,11 @@ const Json = (props: JsonProps) => {
<OptionsContext.Consumer>
{options => (
<PrismDiv
tabIndex={0}
className={props.className}
// tslint:disable-next-line
ref={node => setNode(node!)}
dangerouslySetInnerHTML={{
__html: jsonToHTML(props.data, options.jsonSamplesExpandLevel),
__html: jsonToHTML(props.data, options.jsonSampleExpandLevel),
}}
/>
)}

View File

@ -6,14 +6,11 @@ import { StylingMarkdownProps } from './Markdown';
import { StyledMarkdownBlock } from './styled.elements';
import styled from 'styled-components';
// Workaround for DOMPurify type issues (https://github.com/cure53/DOMPurify/issues/1034)
const dompurify = DOMPurify['default'] as DOMPurify.DOMPurify;
const StyledMarkdownSpan = styled(StyledMarkdownBlock)`
const StyledMarkdownSpan = styled(props => <StyledMarkdownBlock {...props} />)`
display: inline;
`;
const sanitize = (sanitize, html) => (sanitize ? dompurify.sanitize(html) : html);
const sanitize = (untrustedSpec, html) => (untrustedSpec ? DOMPurify.sanitize(html) : html);
export function SanitizedMarkdownHTML({
inline,
@ -28,7 +25,7 @@ export function SanitizedMarkdownHTML({
<Wrap
className={'redoc-markdown ' + (rest.className || '')}
dangerouslySetInnerHTML={{
__html: sanitize(options.sanitize, rest.html),
__html: sanitize(options.untrustedSpec, rest.html),
}}
data-role={rest['data-role']}
{...rest}

View File

@ -16,24 +16,14 @@ export class ArraySchema extends React.PureComponent<SchemaProps> {
render() {
const schema = this.props.schema;
const itemsSchema = schema.items;
const fieldParentsName = this.props.fieldParentsName;
const minMaxItems =
schema.minItems === undefined && schema.maxItems === undefined
? ''
: `(${humanizeConstraints(schema)})`;
const updatedParentsArray = fieldParentsName
? [...fieldParentsName.slice(0, -1), fieldParentsName[fieldParentsName.length - 1] + '[]']
: fieldParentsName;
if (schema.fields) {
return (
<ObjectSchema
{...(this.props as any)}
level={this.props.level}
fieldParentsName={updatedParentsArray}
/>
);
return <ObjectSchema {...(this.props as any)} level={this.props.level} />;
}
if (schema.displayType && !itemsSchema && !minMaxItems.length) {
return (
@ -47,7 +37,7 @@ export class ArraySchema extends React.PureComponent<SchemaProps> {
<div>
<ArrayOpenningLabel> Array {minMaxItems}</ArrayOpenningLabel>
<PaddedSchema>
<Schema {...this.props} schema={itemsSchema} fieldParentsName={updatedParentsArray} />
<Schema {...this.props} schema={itemsSchema} />
</PaddedSchema>
<ArrayClosingLabel />
</div>

View File

@ -16,7 +16,6 @@ export interface ObjectSchemaProps extends SchemaProps {
fieldName: string;
parentSchema: SchemaModel;
};
fieldParentsName?: string[];
}
export const ObjectSchema = observer(
@ -27,9 +26,8 @@ export const ObjectSchema = observer(
skipReadOnly,
skipWriteOnly,
level,
fieldParentsName,
}: ObjectSchemaProps) => {
const { expandSingleSchemaField, showObjectSchemaExamples, schemasExpansionLevel } =
const { expandSingleSchemaField, showObjectSchemaExamples, schemaExpansionLevel } =
React.useContext(OptionsContext);
const filteredFields = React.useMemo(
@ -47,7 +45,7 @@ export const ObjectSchema = observer(
);
const expandByDefault =
(expandSingleSchemaField && filteredFields.length === 1) || schemasExpansionLevel >= level!;
(expandSingleSchemaField && filteredFields.length === 1) || schemaExpansionLevel >= level!;
return (
<PropertiesTable>
@ -60,7 +58,6 @@ export const ObjectSchema = observer(
isLast={isLast}
field={field}
expandByDefault={expandByDefault}
fieldParentsName={Number(level) > 1 ? fieldParentsName : []}
renderDiscriminatorSwitch={
discriminator?.fieldName === field.name
? () => (

View File

@ -21,7 +21,6 @@ export interface SchemaOptions {
export interface SchemaProps extends SchemaOptions {
schema: SchemaModel;
fieldParentsName?: string[];
}
@observer

View File

@ -2,14 +2,14 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { ShelfIcon } from '../../common-elements/shelfs';
import type { IMenuItem } from '../../services';
import { OperationModel } from '../../services';
import { l } from '../../services/Labels';
import { scrollIntoViewIfNeeded } from '../../utils';
import { shortenHTTPVerb } from '../../utils/openapi';
import { OptionsContext } from '../OptionsProvider';
import { MenuItems } from './MenuItems';
import { MenuItemLabel, MenuItemLi, MenuItemTitle, OperationBadge } from './styled.elements';
import { l } from '../../services/Labels';
import { scrollIntoViewIfNeeded } from '../../utils';
import { OptionsContext } from '../OptionsProvider';
import type { IMenuItem } from '../../services';
export interface MenuItemProps {
item: IMenuItem;
@ -47,18 +47,9 @@ export class MenuItem extends React.Component<MenuItemProps> {
<MenuItemLi
tabIndex={0}
onClick={this.activate}
onKeyDown={evt => {
// Space or Enter key will activate the menu item
if (evt.key === 'Enter' || evt.key === ' ') {
this.props.onActivate!(this.props.item);
evt.stopPropagation();
}
}}
depth={item.depth}
data-item-id={item.id}
role="menuitem"
aria-label={item.sidebarLabel}
aria-expanded={item.expanded}
>
{item.type === 'operation' ? (
<OperationMenuItemContent {...this.props} item={item as OperationModel} />

View File

@ -56,7 +56,6 @@ export function StoreBuilder(props: StoreBuilderProps) {
}
}
load();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [spec, specUrl]);
const store = React.useMemo(() => {

View File

@ -90,7 +90,7 @@ describe('FieldDetailsComponent', () => {
items: {
type: 'string',
pattern: '^see regex[0-9]$',
constraints: ['<= 128 characters'],
constraints: [''],
externalDocs: undefined,
},
} as any as SchemaModel,

View File

@ -2,7 +2,6 @@
import { mount, ReactWrapper } from 'enzyme';
import * as React from 'react';
import { act } from 'react';
import { JsonViewer } from '../';
import { withTheme } from '../testProviders';
@ -51,54 +50,5 @@ describe('Components', () => {
expect(flatDataComponent.html()).not.toContain('Expand all');
expect(flatDataComponent.html()).not.toContain('Collapse all');
});
describe('Keyboard Navigation', () => {
let component: ReactWrapper;
const data = {
a: 1,
b: {
c:
// Long string to test horizontal scrolling
Array(100).fill('hello').join(''),
},
};
beforeEach(() => {
component = mount(withTheme(<JsonViewer data={data} />));
ClipboardService.copySelected = origCopySelected;
});
test('should handle arrow key navigation', () => {
const prismDiv = component.find('div[tabIndex=0]');
const divElement = prismDiv.getDOMNode();
// Mock scrollLeft before events
Object.defineProperty(divElement, 'scrollLeft', {
get: jest.fn(() => 0),
set: jest.fn(),
});
// Trigger events inside act()
act(() => {
divElement.dispatchEvent(
new KeyboardEvent('keydown', {
key: 'ArrowRight',
bubbles: true,
}),
);
});
act(() => {
divElement.dispatchEvent(
new KeyboardEvent('keydown', {
key: 'ArrowLeft',
bubbles: true,
}),
);
});
expect(divElement.scrollLeft).toBe(0);
});
});
});
});

View File

@ -79,23 +79,21 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"downloadUrls": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": {},
"expandSingleSchemaField": false,
"generatedSamplesMaxDepth": 10,
"hideDownloadButtons": false,
"generatedPayloadSamplesMaxDepth": 10,
"hideDownloadButton": false,
"hideFab": false,
"hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false,
"hideSchemaPattern": false,
"hideSchemaTitles": false,
"hideSecuritySection": false,
"hideSingleRequestSampleTab": false,
"ignoreNamedSchemas": Set {},
"jsonSamplesExpandLevel": 2,
"jsonSampleExpandLevel": 2,
"maxDisplayedEnumValues": undefined,
"menuToggle": true,
"minCharacterLengthToInitSearch": 3,
@ -104,9 +102,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"onlyRequiredInSamples": false,
"pathInMiddlePanel": false,
"payloadSampleIdx": 0,
"sanitize": false,
"schemaDefinitionsTagName": undefined,
"schemasExpansionLevel": 0,
"requiredPropsFirst": false,
"schemaExpansionLevel": 0,
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
@ -117,7 +114,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"sortEnumValuesAlphabetically": false,
"sortOperationsAlphabetically": false,
"sortPropsAlphabetically": false,
"sortRequiredPropsFirst": false,
"sortTagsAlphabetically": false,
"theme": {
"breakpoints": {
@ -296,6 +292,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
},
},
"unstable_ignoreMimeParameters": false,
"untrustedSpec": false,
},
"pattern": undefined,
"pointer": "#/components/schemas/Dog/properties/packSize",
@ -316,7 +313,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"type": "number",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
},
FieldModel {
@ -355,23 +351,21 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"downloadUrls": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": {},
"expandSingleSchemaField": false,
"generatedSamplesMaxDepth": 10,
"hideDownloadButtons": false,
"generatedPayloadSamplesMaxDepth": 10,
"hideDownloadButton": false,
"hideFab": false,
"hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false,
"hideSchemaPattern": false,
"hideSchemaTitles": false,
"hideSecuritySection": false,
"hideSingleRequestSampleTab": false,
"ignoreNamedSchemas": Set {},
"jsonSamplesExpandLevel": 2,
"jsonSampleExpandLevel": 2,
"maxDisplayedEnumValues": undefined,
"menuToggle": true,
"minCharacterLengthToInitSearch": 3,
@ -380,9 +374,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"onlyRequiredInSamples": false,
"pathInMiddlePanel": false,
"payloadSampleIdx": 0,
"sanitize": false,
"schemaDefinitionsTagName": undefined,
"schemasExpansionLevel": 0,
"requiredPropsFirst": false,
"schemaExpansionLevel": 0,
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
@ -393,7 +386,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"sortEnumValuesAlphabetically": false,
"sortOperationsAlphabetically": false,
"sortPropsAlphabetically": false,
"sortRequiredPropsFirst": false,
"sortTagsAlphabetically": false,
"theme": {
"breakpoints": {
@ -572,6 +564,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
},
},
"unstable_ignoreMimeParameters": false,
"untrustedSpec": false,
},
"pattern": undefined,
"pointer": "#/components/schemas/Dog/properties/type",
@ -604,7 +597,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"type": "string",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
},
],
@ -618,23 +610,21 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"downloadUrls": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": {},
"expandSingleSchemaField": false,
"generatedSamplesMaxDepth": 10,
"hideDownloadButtons": false,
"generatedPayloadSamplesMaxDepth": 10,
"hideDownloadButton": false,
"hideFab": false,
"hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false,
"hideSchemaPattern": false,
"hideSchemaTitles": false,
"hideSecuritySection": false,
"hideSingleRequestSampleTab": false,
"ignoreNamedSchemas": Set {},
"jsonSamplesExpandLevel": 2,
"jsonSampleExpandLevel": 2,
"maxDisplayedEnumValues": undefined,
"menuToggle": true,
"minCharacterLengthToInitSearch": 3,
@ -643,9 +633,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"onlyRequiredInSamples": false,
"pathInMiddlePanel": false,
"payloadSampleIdx": 0,
"sanitize": false,
"schemaDefinitionsTagName": undefined,
"schemasExpansionLevel": 0,
"requiredPropsFirst": false,
"schemaExpansionLevel": 0,
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
@ -656,7 +645,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"sortEnumValuesAlphabetically": false,
"sortOperationsAlphabetically": false,
"sortPropsAlphabetically": false,
"sortRequiredPropsFirst": false,
"sortTagsAlphabetically": false,
"theme": {
"breakpoints": {
@ -835,6 +823,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
},
},
"unstable_ignoreMimeParameters": false,
"untrustedSpec": false,
},
"pattern": undefined,
"pointer": "#/components/schemas/Dog",
@ -889,7 +878,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"type": "object",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
SchemaModel {
"activeOneOf": 0,
@ -943,23 +931,21 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"downloadUrls": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": {},
"expandSingleSchemaField": false,
"generatedSamplesMaxDepth": 10,
"hideDownloadButtons": false,
"generatedPayloadSamplesMaxDepth": 10,
"hideDownloadButton": false,
"hideFab": false,
"hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false,
"hideSchemaPattern": false,
"hideSchemaTitles": false,
"hideSecuritySection": false,
"hideSingleRequestSampleTab": false,
"ignoreNamedSchemas": Set {},
"jsonSamplesExpandLevel": 2,
"jsonSampleExpandLevel": 2,
"maxDisplayedEnumValues": undefined,
"menuToggle": true,
"minCharacterLengthToInitSearch": 3,
@ -968,9 +954,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"onlyRequiredInSamples": false,
"pathInMiddlePanel": false,
"payloadSampleIdx": 0,
"sanitize": false,
"schemaDefinitionsTagName": undefined,
"schemasExpansionLevel": 0,
"requiredPropsFirst": false,
"schemaExpansionLevel": 0,
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
@ -981,7 +966,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"sortEnumValuesAlphabetically": false,
"sortOperationsAlphabetically": false,
"sortPropsAlphabetically": false,
"sortRequiredPropsFirst": false,
"sortTagsAlphabetically": false,
"theme": {
"breakpoints": {
@ -1160,6 +1144,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
},
},
"unstable_ignoreMimeParameters": false,
"untrustedSpec": false,
},
"pattern": undefined,
"pointer": "#/components/schemas/Cat/properties/type",
@ -1192,7 +1177,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"type": "string",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
},
FieldModel {
@ -1231,23 +1215,21 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"downloadUrls": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": {},
"expandSingleSchemaField": false,
"generatedSamplesMaxDepth": 10,
"hideDownloadButtons": false,
"generatedPayloadSamplesMaxDepth": 10,
"hideDownloadButton": false,
"hideFab": false,
"hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false,
"hideSchemaPattern": false,
"hideSchemaTitles": false,
"hideSecuritySection": false,
"hideSingleRequestSampleTab": false,
"ignoreNamedSchemas": Set {},
"jsonSamplesExpandLevel": 2,
"jsonSampleExpandLevel": 2,
"maxDisplayedEnumValues": undefined,
"menuToggle": true,
"minCharacterLengthToInitSearch": 3,
@ -1256,9 +1238,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"onlyRequiredInSamples": false,
"pathInMiddlePanel": false,
"payloadSampleIdx": 0,
"sanitize": false,
"schemaDefinitionsTagName": undefined,
"schemasExpansionLevel": 0,
"requiredPropsFirst": false,
"schemaExpansionLevel": 0,
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
@ -1269,7 +1250,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"sortEnumValuesAlphabetically": false,
"sortOperationsAlphabetically": false,
"sortPropsAlphabetically": false,
"sortRequiredPropsFirst": false,
"sortTagsAlphabetically": false,
"theme": {
"breakpoints": {
@ -1448,6 +1428,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
},
},
"unstable_ignoreMimeParameters": false,
"untrustedSpec": false,
},
"pattern": undefined,
"pointer": "#/components/schemas/Cat/properties/packSize",
@ -1476,7 +1457,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"type": "number",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
},
],
@ -1490,23 +1470,21 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"downloadUrls": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": {},
"expandSingleSchemaField": false,
"generatedSamplesMaxDepth": 10,
"hideDownloadButtons": false,
"generatedPayloadSamplesMaxDepth": 10,
"hideDownloadButton": false,
"hideFab": false,
"hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false,
"hideSchemaPattern": false,
"hideSchemaTitles": false,
"hideSecuritySection": false,
"hideSingleRequestSampleTab": false,
"ignoreNamedSchemas": Set {},
"jsonSamplesExpandLevel": 2,
"jsonSampleExpandLevel": 2,
"maxDisplayedEnumValues": undefined,
"menuToggle": true,
"minCharacterLengthToInitSearch": 3,
@ -1515,9 +1493,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"onlyRequiredInSamples": false,
"pathInMiddlePanel": false,
"payloadSampleIdx": 0,
"sanitize": false,
"schemaDefinitionsTagName": undefined,
"schemasExpansionLevel": 0,
"requiredPropsFirst": false,
"schemaExpansionLevel": 0,
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
@ -1528,7 +1505,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"sortEnumValuesAlphabetically": false,
"sortOperationsAlphabetically": false,
"sortPropsAlphabetically": false,
"sortRequiredPropsFirst": false,
"sortTagsAlphabetically": false,
"theme": {
"breakpoints": {
@ -1707,6 +1683,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
},
},
"unstable_ignoreMimeParameters": false,
"untrustedSpec": false,
},
"pattern": undefined,
"pointer": "#/components/schemas/Cat",
@ -1766,7 +1743,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"type": "object",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
],
"options": RedocNormalizedOptions {
@ -1774,23 +1750,21 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"downloadUrls": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": {},
"expandSingleSchemaField": false,
"generatedSamplesMaxDepth": 10,
"hideDownloadButtons": false,
"generatedPayloadSamplesMaxDepth": 10,
"hideDownloadButton": false,
"hideFab": false,
"hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false,
"hideSchemaPattern": false,
"hideSchemaTitles": false,
"hideSecuritySection": false,
"hideSingleRequestSampleTab": false,
"ignoreNamedSchemas": Set {},
"jsonSamplesExpandLevel": 2,
"jsonSampleExpandLevel": 2,
"maxDisplayedEnumValues": undefined,
"menuToggle": true,
"minCharacterLengthToInitSearch": 3,
@ -1799,9 +1773,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"onlyRequiredInSamples": false,
"pathInMiddlePanel": false,
"payloadSampleIdx": 0,
"sanitize": false,
"schemaDefinitionsTagName": undefined,
"schemasExpansionLevel": 0,
"requiredPropsFirst": false,
"schemaExpansionLevel": 0,
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
@ -1812,7 +1785,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"sortEnumValuesAlphabetically": false,
"sortOperationsAlphabetically": false,
"sortPropsAlphabetically": false,
"sortRequiredPropsFirst": false,
"sortTagsAlphabetically": false,
"theme": {
"breakpoints": {
@ -1991,6 +1963,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
},
},
"unstable_ignoreMimeParameters": false,
"untrustedSpec": false,
},
"pattern": undefined,
"pointer": "#/components/schemas/Pet",
@ -2030,7 +2003,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"type": "object",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
}
}
@ -2088,23 +2060,21 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"downloadUrls": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": {},
"expandSingleSchemaField": false,
"generatedSamplesMaxDepth": 10,
"hideDownloadButtons": false,
"generatedPayloadSamplesMaxDepth": 10,
"hideDownloadButton": false,
"hideFab": false,
"hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false,
"hideSchemaPattern": false,
"hideSchemaTitles": false,
"hideSecuritySection": false,
"hideSingleRequestSampleTab": false,
"ignoreNamedSchemas": Set {},
"jsonSamplesExpandLevel": 2,
"jsonSampleExpandLevel": 2,
"maxDisplayedEnumValues": undefined,
"menuToggle": true,
"minCharacterLengthToInitSearch": 3,
@ -2113,9 +2083,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"onlyRequiredInSamples": false,
"pathInMiddlePanel": false,
"payloadSampleIdx": 0,
"sanitize": false,
"schemaDefinitionsTagName": undefined,
"schemasExpansionLevel": 0,
"requiredPropsFirst": false,
"schemaExpansionLevel": 0,
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
@ -2126,7 +2095,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"sortEnumValuesAlphabetically": false,
"sortOperationsAlphabetically": false,
"sortPropsAlphabetically": false,
"sortRequiredPropsFirst": false,
"sortTagsAlphabetically": false,
"theme": {
"breakpoints": {
@ -2305,6 +2273,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
},
},
"unstable_ignoreMimeParameters": false,
"untrustedSpec": false,
},
"pattern": undefined,
"pointer": "#/components/schemas/Dog/properties/packSize",
@ -2325,7 +2294,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"type": "number",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
},
FieldModel {
@ -2364,23 +2332,21 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"downloadUrls": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": {},
"expandSingleSchemaField": false,
"generatedSamplesMaxDepth": 10,
"hideDownloadButtons": false,
"generatedPayloadSamplesMaxDepth": 10,
"hideDownloadButton": false,
"hideFab": false,
"hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false,
"hideSchemaPattern": false,
"hideSchemaTitles": false,
"hideSecuritySection": false,
"hideSingleRequestSampleTab": false,
"ignoreNamedSchemas": Set {},
"jsonSamplesExpandLevel": 2,
"jsonSampleExpandLevel": 2,
"maxDisplayedEnumValues": undefined,
"menuToggle": true,
"minCharacterLengthToInitSearch": 3,
@ -2389,9 +2355,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"onlyRequiredInSamples": false,
"pathInMiddlePanel": false,
"payloadSampleIdx": 0,
"sanitize": false,
"schemaDefinitionsTagName": undefined,
"schemasExpansionLevel": 0,
"requiredPropsFirst": false,
"schemaExpansionLevel": 0,
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
@ -2402,7 +2367,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"sortEnumValuesAlphabetically": false,
"sortOperationsAlphabetically": false,
"sortPropsAlphabetically": false,
"sortRequiredPropsFirst": false,
"sortTagsAlphabetically": false,
"theme": {
"breakpoints": {
@ -2581,6 +2545,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
},
},
"unstable_ignoreMimeParameters": false,
"untrustedSpec": false,
},
"pattern": undefined,
"pointer": "#/components/schemas/Dog/properties/type",
@ -2613,7 +2578,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"type": "string",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
},
],
@ -2627,23 +2591,21 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"disableSearch": false,
"downloadDefinitionUrl": undefined,
"downloadFileName": undefined,
"downloadUrls": undefined,
"enumSkipQuotes": false,
"expandDefaultServerVariables": false,
"expandResponses": {},
"expandSingleSchemaField": false,
"generatedSamplesMaxDepth": 10,
"hideDownloadButtons": false,
"generatedPayloadSamplesMaxDepth": 10,
"hideDownloadButton": false,
"hideFab": false,
"hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false,
"hideSchemaPattern": false,
"hideSchemaTitles": false,
"hideSecuritySection": false,
"hideSingleRequestSampleTab": false,
"ignoreNamedSchemas": Set {},
"jsonSamplesExpandLevel": 2,
"jsonSampleExpandLevel": 2,
"maxDisplayedEnumValues": undefined,
"menuToggle": true,
"minCharacterLengthToInitSearch": 3,
@ -2652,9 +2614,8 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"onlyRequiredInSamples": false,
"pathInMiddlePanel": false,
"payloadSampleIdx": 0,
"sanitize": false,
"schemaDefinitionsTagName": undefined,
"schemasExpansionLevel": 0,
"requiredPropsFirst": false,
"schemaExpansionLevel": 0,
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
@ -2665,7 +2626,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"sortEnumValuesAlphabetically": false,
"sortOperationsAlphabetically": false,
"sortPropsAlphabetically": false,
"sortRequiredPropsFirst": false,
"sortTagsAlphabetically": false,
"theme": {
"breakpoints": {
@ -2844,6 +2804,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
},
},
"unstable_ignoreMimeParameters": false,
"untrustedSpec": false,
},
"pattern": undefined,
"pointer": "#/components/schemas/Dog",
@ -2898,7 +2859,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"type": "object",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
}
}
/>
@ -2961,11 +2921,9 @@ exports[`Components SchemaView discriminator should correctly render discriminat
"type": "number",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
}
}
fieldParentsName={[]}
isLast={false}
key="packSize"
showExamples={false}
@ -3036,11 +2994,9 @@ exports[`Components SchemaView discriminator should correctly render discriminat
"type": "string",
"typePrefix": "",
"writeOnly": false,
"x-enumDescriptions": undefined,
},
}
}
fieldParentsName={[]}
isLast={true}
key="type"
renderDiscriminatorSwitch={[Function]}

View File

@ -159,23 +159,15 @@ exports[`FieldDetailsComponent renders correctly when field items have string ty
</span>
</span>
<span
class="sc-kpDqfm sc-dAlyuH sc-gvZAcH cGRfjn gHomYR eXivNJ"
class="sc-kpDqfm sc-dAlyuH sc-dxcDKg cGRfjn gHomYR gXntsr"
>
[ items
<span>
<span
class="sc-kpDqfm sc-gFqAkR cGRfjn fYEICH"
>
&lt;= 128 characters
</span>
</span>
[
<span
class="sc-kpDqfm sc-eDPEul cGRfjn cCKYVD"
class="sc-kpDqfm sc-eDPEul cGRfjn erJHow"
>
^see regex[0-9]$
</span>
]
]
</span>
</div>

View File

@ -3,21 +3,21 @@
exports[`SecurityRequirement should render SecurityDefs 1`] = `
"<div id="section/Authentication/petstore_auth" data-section-id="section/Authentication/petstore_auth" class="sc-dcJsrY bBkGhy"><div class="sc-kAyceB hBQWIZ"><div class="sc-fqkvVR oJKYx"><h2 class="sc-jXbUNg fWnwAh">petstore_auth</h2><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>Get access to data while protecting your account credentials.
OAuth2 is also a safer and more secure way to give you access.</p>
</div><div class="sc-iEXKAA ebCiwb"><div class="sc-ejfMa-d bdDYxc"><b>Security Scheme Type: </b><span>OAuth2</span></div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-ejfMa-d bdDYxc"><b>Flow type: </b><code>implicit </code></div><div class="sc-ejfMa-d bdDYxc"><strong> Authorization URL: </strong><code><a target="_blank" rel="noopener noreferrer" href="http://petstore.swagger.io/api/oauth/dialog">http://petstore.swagger.io/api/oauth/dialog</a></code></div><div class="sc-ejfMa-d bdDYxc"><b> Scopes: </b></div><div class="sc-EgOXT kRIdPi container" style="height: 4em;"><ul><li><code>write:pets</code> - <div class="sc-eeDRCY sc-eBMEME sc-fhzFiK gTGgei iCmQdS hXtrri redoc-markdown"><p>modify pets in your account</p>
</div></li><li><code>read:pets</code> - <div class="sc-eeDRCY sc-eBMEME sc-fhzFiK gTGgei iCmQdS hXtrri redoc-markdown"><p>read your pets</p>
</div></li></ul></div><div class="sc-eZYNyq dIKkVb"></div></div></div></div></div></div><div id="section/Authentication/GitLab_PersonalAccessToken" data-section-id="section/Authentication/GitLab_PersonalAccessToken" class="sc-dcJsrY bBkGhy"><div class="sc-kAyceB hBQWIZ"><div class="sc-fqkvVR oJKYx"><h2 class="sc-jXbUNg fWnwAh">GitLab_PersonalAccessToken</h2><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>GitLab Personal Access Token description</p>
</div><div class="sc-iEXKAA ebCiwb"><div class="sc-ejfMa-d bdDYxc"><b>Security Scheme Type: </b><span>API Key</span></div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-ejfMa-d bdDYxc"><b>Header parameter name: </b><code>PRIVATE-TOKEN</code></div></div></div></div></div></div><div id="section/Authentication/GitLab_OpenIdConnect" data-section-id="section/Authentication/GitLab_OpenIdConnect" class="sc-dcJsrY bBkGhy"><div class="sc-kAyceB hBQWIZ"><div class="sc-fqkvVR oJKYx"><h2 class="sc-jXbUNg fWnwAh">GitLab_OpenIdConnect</h2><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>GitLab OpenIdConnect description</p>
</div><div class="sc-iEXKAA ebCiwb"><div class="sc-ejfMa-d bdDYxc"><b>Security Scheme Type: </b><span>OpenID Connect</span></div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-ejfMa-d bdDYxc"><b>Connect URL: </b><code><a target="_blank" rel="noopener noreferrer" href="https://gitlab.com/.well-known/openid-configuration">https://gitlab.com/.well-known/openid-configuration</a></code></div></div></div></div></div></div><div id="section/Authentication/basicAuth" data-section-id="section/Authentication/basicAuth" class="sc-dcJsrY bBkGhy"><div class="sc-kAyceB hBQWIZ"><div class="sc-fqkvVR oJKYx"><h2 class="sc-jXbUNg fWnwAh">basicAuth</h2><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"></div><div class="sc-iEXKAA ebCiwb"><div class="sc-ejfMa-d bdDYxc"><b>Security Scheme Type: </b><span>HTTP</span></div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-ejfMa-d bdDYxc"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class="sc-ejfMa-d bdDYxc"></div></div></div></div></div></div>"
</div><div class="sc-ejfMa-d a-DjBE"><div class="sc-dkmUuB hFwAIA"><b>Security Scheme Type: </b><span>OAuth2</span></div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-dkmUuB hFwAIA"><b>Flow type: </b><code>implicit </code></div><div class="sc-dkmUuB hFwAIA"><strong> Authorization URL: </strong><code><a target="_blank" rel="noopener noreferrer" href="http://petstore.swagger.io/api/oauth/dialog">http://petstore.swagger.io/api/oauth/dialog</a></code></div><div class="sc-dkmUuB hFwAIA"><b> Scopes: </b></div><div class="sc-iEXKAA blExNw container" style="height: 4em;"><ul><li><code>write:pets</code> - <div class="sc-eeDRCY sc-eBMEME gTGgei fMmru sc-fhzFiK hXtrri redoc-markdown"><p>modify pets in your account</p>
</div></li><li><code>read:pets</code> - <div class="sc-eeDRCY sc-eBMEME gTGgei fMmru sc-fhzFiK hXtrri redoc-markdown"><p>read your pets</p>
</div></li></ul></div><div class="sc-EgOXT bNSpXO"></div></div></div></div></div></div><div id="section/Authentication/GitLab_PersonalAccessToken" data-section-id="section/Authentication/GitLab_PersonalAccessToken" class="sc-dcJsrY bBkGhy"><div class="sc-kAyceB hBQWIZ"><div class="sc-fqkvVR oJKYx"><h2 class="sc-jXbUNg fWnwAh">GitLab_PersonalAccessToken</h2><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>GitLab Personal Access Token description</p>
</div><div class="sc-ejfMa-d a-DjBE"><div class="sc-dkmUuB hFwAIA"><b>Security Scheme Type: </b><span>API Key</span></div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-dkmUuB hFwAIA"><b>Header parameter name: </b><code>PRIVATE-TOKEN</code></div></div></div></div></div></div><div id="section/Authentication/GitLab_OpenIdConnect" data-section-id="section/Authentication/GitLab_OpenIdConnect" class="sc-dcJsrY bBkGhy"><div class="sc-kAyceB hBQWIZ"><div class="sc-fqkvVR oJKYx"><h2 class="sc-jXbUNg fWnwAh">GitLab_OpenIdConnect</h2><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>GitLab OpenIdConnect description</p>
</div><div class="sc-ejfMa-d a-DjBE"><div class="sc-dkmUuB hFwAIA"><b>Security Scheme Type: </b><span>OpenID Connect</span></div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-dkmUuB hFwAIA"><b>Connect URL: </b><code><a target="_blank" rel="noopener noreferrer" href="https://gitlab.com/.well-known/openid-configuration">https://gitlab.com/.well-known/openid-configuration</a></code></div></div></div></div></div></div><div id="section/Authentication/basicAuth" data-section-id="section/Authentication/basicAuth" class="sc-dcJsrY bBkGhy"><div class="sc-kAyceB hBQWIZ"><div class="sc-fqkvVR oJKYx"><h2 class="sc-jXbUNg fWnwAh">basicAuth</h2><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"></div><div class="sc-ejfMa-d a-DjBE"><div class="sc-dkmUuB hFwAIA"><b>Security Scheme Type: </b><span>HTTP</span></div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-dkmUuB hFwAIA"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class="sc-dkmUuB hFwAIA"></div></div></div></div></div></div>"
`;
exports[`SecurityRequirement should render authDefinition 1`] = `"<div class="sc-dkmUuB fUBzjk"><div class="sc-dBmzty iDyBRL"><h5 class="sc-dAlyuH sc-bDumWk jbQuod feBYnB">Authorizations:</h5><svg class="sc-cwHptR iZRiKW" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></div><div class="sc-fifgRP eqIYDA"><span class="sc-sLsrZ jmro">(<span class="sc-kbousE iMnLRS">API Key: <i>GitLab_PersonalAccessToken</i></span><span class="sc-kbousE iMnLRS">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class="sc-kbousE iMnLRS">HTTP: <i>basicAuth</i></span>) </span><span class="sc-sLsrZ jmro"><span class="sc-kbousE iMnLRS">OAuth2: <i>petstore_auth</i></span></span></div></div>,"`;
exports[`SecurityRequirement should render authDefinition 1`] = `"<div class="sc-bDumWk iWBBny"><div class="sc-sLsrZ hgeUJn"><h5 class="sc-dAlyuH sc-fifgRP jbQuod kWJur">Authorizations:</h5><svg class="sc-cwHptR iZRiKW" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></div><div class="sc-dBmzty eoFcYg"><span class="sc-kbousE cpXQuZ">(<span class="sc-gfoqjT kbvnry">API Key: <i>GitLab_PersonalAccessToken</i></span><span class="sc-gfoqjT kbvnry">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class="sc-gfoqjT kbvnry">HTTP: <i>basicAuth</i></span>) </span><span class="sc-kbousE cpXQuZ"><span class="sc-gfoqjT kbvnry">OAuth2: <i>petstore_auth</i></span></span></div></div>,"`;
exports[`SecurityRequirement should render authDefinition 2`] = `
"<div class="sc-dkmUuB KTEsk"><div class="sc-dBmzty iDyBRL"><h5 class="sc-dAlyuH sc-bDumWk jbQuod feBYnB">Authorizations:</h5><svg class="sc-cwHptR dSJqIk" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></div><div class="sc-fifgRP gNcumo"><span class="sc-sLsrZ iTheFK">(<span class="sc-kbousE iMnLRS">API Key: <i>GitLab_PersonalAccessToken</i></span><span class="sc-kbousE iMnLRS">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class="sc-kbousE iMnLRS">HTTP: <i>basicAuth</i></span>) </span><span class="sc-sLsrZ iTheFK"><span class="sc-kbousE iMnLRS">OAuth2: <i>petstore_auth</i> (<code class="sc-gfoqjT dapMvh">write:pets</code><code class="sc-gfoqjT dapMvh">read:pets</code>) </span></span></div></div><div class="sc-iEXKAA ebCiwb"><h5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11"><path fill="currentColor" d="M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z"></path></svg> OAuth2: petstore_auth</h5><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>Get access to data while protecting your account credentials.
"<div class="sc-bDumWk gtsPcy"><div class="sc-sLsrZ hgeUJn"><h5 class="sc-dAlyuH sc-fifgRP jbQuod kWJur">Authorizations:</h5><svg class="sc-cwHptR dSJqIk" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></div><div class="sc-dBmzty llvZdI"><span class="sc-kbousE dOwJQz">(<span class="sc-gfoqjT kbvnry">API Key: <i>GitLab_PersonalAccessToken</i></span><span class="sc-gfoqjT kbvnry">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class="sc-gfoqjT kbvnry">HTTP: <i>basicAuth</i></span>) </span><span class="sc-kbousE dOwJQz"><span class="sc-gfoqjT kbvnry">OAuth2: <i>petstore_auth</i> (<code class="sc-eyvILC bzHwfc">write:pets</code><code class="sc-eyvILC bzHwfc">read:pets</code>) </span></span></div></div><div class="sc-ejfMa-d a-DjBE"><h5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11"><path fill="currentColor" d="M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z"></path></svg> OAuth2: petstore_auth</h5><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>Get access to data while protecting your account credentials.
OAuth2 is also a safer and more secure way to give you access.</p>
</div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-ejfMa-d bdDYxc"><b>Flow type: </b><code>implicit </code></div><div class="sc-ejfMa-d bdDYxc"><strong> Authorization URL: </strong><code><a target="_blank" rel="noopener noreferrer" href="http://petstore.swagger.io/api/oauth/dialog">http://petstore.swagger.io/api/oauth/dialog</a></code></div><div><b>Required scopes: </b><code>write:pets</code> <code>read:pets</code> </div><div class="sc-ejfMa-d bdDYxc"><b> Scopes: </b></div><div class="sc-EgOXT kRIdPi container" style="height: 4em;"><ul><li><code>write:pets</code> - <div class="sc-eeDRCY sc-eBMEME sc-fhzFiK gTGgei iCmQdS hXtrri redoc-markdown"><p>modify pets in your account</p>
</div></li><li><code>read:pets</code> - <div class="sc-eeDRCY sc-eBMEME sc-fhzFiK gTGgei iCmQdS hXtrri redoc-markdown"><p>read your pets</p>
</div></li></ul></div><div class="sc-eZYNyq dIKkVb"></div></div></div><div class="sc-iEXKAA ebCiwb"><h5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11"><path fill="currentColor" d="M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z"></path></svg> API Key: GitLab_PersonalAccessToken</h5><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>GitLab Personal Access Token description</p>
</div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-ejfMa-d bdDYxc"><b>Header parameter name: </b><code>PRIVATE-TOKEN</code></div></div></div><div class="sc-iEXKAA ebCiwb"><h5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11"><path fill="currentColor" d="M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z"></path></svg> OpenID Connect: GitLab_OpenIdConnect</h5><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>GitLab OpenIdConnect description</p>
</div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-ejfMa-d bdDYxc"><b>Connect URL: </b><code><a target="_blank" rel="noopener noreferrer" href="https://gitlab.com/.well-known/openid-configuration">https://gitlab.com/.well-known/openid-configuration</a></code></div></div></div><div class="sc-iEXKAA ebCiwb"><h5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11"><path fill="currentColor" d="M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z"></path></svg> HTTP: basicAuth</h5><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"></div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-ejfMa-d bdDYxc"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class="sc-ejfMa-d bdDYxc"></div></div></div>,"
</div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-dkmUuB hFwAIA"><b>Flow type: </b><code>implicit </code></div><div class="sc-dkmUuB hFwAIA"><strong> Authorization URL: </strong><code><a target="_blank" rel="noopener noreferrer" href="http://petstore.swagger.io/api/oauth/dialog">http://petstore.swagger.io/api/oauth/dialog</a></code></div><div><b>Required scopes: </b><code>write:pets</code> <code>read:pets</code> </div><div class="sc-dkmUuB hFwAIA"><b> Scopes: </b></div><div class="sc-iEXKAA blExNw container" style="height: 4em;"><ul><li><code>write:pets</code> - <div class="sc-eeDRCY sc-eBMEME gTGgei fMmru sc-fhzFiK hXtrri redoc-markdown"><p>modify pets in your account</p>
</div></li><li><code>read:pets</code> - <div class="sc-eeDRCY sc-eBMEME gTGgei fMmru sc-fhzFiK hXtrri redoc-markdown"><p>read your pets</p>
</div></li></ul></div><div class="sc-EgOXT bNSpXO"></div></div></div><div class="sc-ejfMa-d a-DjBE"><h5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11"><path fill="currentColor" d="M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z"></path></svg> API Key: GitLab_PersonalAccessToken</h5><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>GitLab Personal Access Token description</p>
</div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-dkmUuB hFwAIA"><b>Header parameter name: </b><code>PRIVATE-TOKEN</code></div></div></div><div class="sc-ejfMa-d a-DjBE"><h5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11"><path fill="currentColor" d="M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z"></path></svg> OpenID Connect: GitLab_OpenIdConnect</h5><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><p>GitLab OpenIdConnect description</p>
</div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-dkmUuB hFwAIA"><b>Connect URL: </b><code><a target="_blank" rel="noopener noreferrer" href="https://gitlab.com/.well-known/openid-configuration">https://gitlab.com/.well-known/openid-configuration</a></code></div></div></div><div class="sc-ejfMa-d a-DjBE"><h5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11"><path fill="currentColor" d="M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z"></path></svg> HTTP: basicAuth</h5><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"></div><div class="sc-eeDRCY sc-eBMEME gTGgei fMmru"><div class="sc-dkmUuB hFwAIA"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class="sc-dkmUuB hFwAIA"></div></div></div>,"
`;

View File

@ -1,4 +1,4 @@
import type { OpenAPIPaths, OpenAPITag, OpenAPISchema } from '../types';
import type { OpenAPISpec, OpenAPIPaths, OpenAPITag, OpenAPISchema } from '../types';
import { isOperationName, JsonPointer, alphabeticallyByProp } from '../utils';
import { MarkdownRenderer } from './MarkdownRenderer';
import { GroupModel, OperationModel } from './models';
@ -17,19 +17,9 @@ export class MenuBuilder {
options: RedocNormalizedOptions,
): ContentItemModel[] {
const spec = parser.spec;
const { schemaDefinitionsTagName } = options;
const items: ContentItemModel[] = [];
const tags = [...(spec.tags || [])];
const hasAutogenerated = tags.find(
tag => tag?.name === schemaDefinitionsTagName,
);
if (!hasAutogenerated && schemaDefinitionsTagName) {
tags.push({ name: schemaDefinitionsTagName });
}
const tagsMap = MenuBuilder.getTagsWithOperations(parser, tags);
const tagsMap = MenuBuilder.getTagsWithOperations(parser, spec);
items.push(...MenuBuilder.addMarkdownItems(spec.info.description || '', undefined, 1, options));
if (spec['x-tagGroups'] && spec['x-tagGroups'].length > 0) {
items.push(
@ -38,7 +28,6 @@ export class MenuBuilder {
} else {
items.push(...MenuBuilder.getTagsItems(parser, tagsMap, undefined, undefined, options));
}
return items;
}
@ -152,7 +141,6 @@ export class MenuBuilder {
parser,
tag,
parent: item,
schemaDefinitionsTagName: options.schemaDefinitionsTagName,
});
item.items = [
@ -207,11 +195,10 @@ export class MenuBuilder {
/**
* collects tags and maps each tag to list of operations belonging to this tag
*/
static getTagsWithOperations(parser: OpenAPIParser, explicitTags: OpenAPITag[]): TagsInfoMap {
const { spec } = parser;
static getTagsWithOperations(parser: OpenAPIParser, spec: OpenAPISpec): TagsInfoMap {
const tags: TagsInfoMap = {};
const webhooks = spec['x-webhooks'] || spec.webhooks;
for (const tag of explicitTags || []) {
for (const tag of spec.tags || []) {
tags[tag.name] = { ...tag, operations: [] };
}
@ -273,18 +260,14 @@ export class MenuBuilder {
parser,
tag,
parent,
schemaDefinitionsTagName,
}: {
parser: OpenAPIParser;
tag: TagInfo;
parent: GroupModel;
schemaDefinitionsTagName?: string;
}): GroupModel[] {
const defaultTags = schemaDefinitionsTagName ? [schemaDefinitionsTagName] : [];
return Object.entries(parser.spec.components?.schemas || {})
.map(([schemaName, schema]) => {
const schemaTags = schema['x-tags'] || defaultTags;
const schemaTags = schema['x-tags'];
if (!schemaTags?.includes(tag.name)) return null;
const item = new GroupModel(

View File

@ -6,32 +6,23 @@ import { setRedocLabels } from './Labels';
import { SideNavStyleEnum } from './types';
import type { LabelsConfigRaw, MDXComponentMeta } from './types';
export type DownloadUrlsConfig = {
title?: string;
url: string;
}[];
export interface RedocRawOptions {
theme?: ThemeInterface;
scrollYOffset?: number | string | (() => number);
hideHostname?: boolean | string;
expandResponses?: string | 'all';
requiredPropsFirst?: boolean | string; // remove in next major release
sortRequiredPropsFirst?: boolean | string;
requiredPropsFirst?: boolean | string;
sortPropsAlphabetically?: boolean | string;
sortEnumValuesAlphabetically?: boolean | string;
sortOperationsAlphabetically?: boolean | string;
sortTagsAlphabetically?: boolean | string;
nativeScrollbars?: boolean | string;
pathInMiddlePanel?: boolean | string;
untrustedSpec?: boolean | string; // remove in next major release
sanitize?: boolean | string;
untrustedSpec?: boolean | string;
hideLoading?: boolean | string;
hideDownloadButton?: boolean | string; // remove in next major release
hideDownloadButtons?: boolean | string;
hideDownloadButton?: boolean | string;
downloadFileName?: string;
downloadDefinitionUrl?: string;
downloadUrls?: DownloadUrlsConfig;
disableSearch?: boolean | string;
onlyRequiredInSamples?: boolean | string;
showExtensions?: boolean | string | string[];
@ -39,15 +30,12 @@ export interface RedocRawOptions {
hideSingleRequestSampleTab?: boolean | string;
hideRequestPayloadSample?: boolean;
menuToggle?: boolean | string;
jsonSampleExpandLevel?: number | string | 'all'; // remove in next major release
jsonSamplesExpandLevel?: number | string | 'all';
jsonSampleExpandLevel?: number | string | 'all';
hideSchemaTitles?: boolean | string;
simpleOneOfTypeLabel?: boolean | string;
payloadSampleIdx?: number;
expandSingleSchemaField?: boolean | string;
schemaExpansionLevel?: number | string | 'all'; // remove in next major release
schemasExpansionLevel?: number | string | 'all';
schemaDefinitionsTagName?: string;
schemaExpansionLevel?: number | string | 'all';
showObjectSchemaExamples?: boolean | string;
showSecuritySchemeType?: boolean;
hideSecuritySection?: boolean;
@ -64,13 +52,11 @@ export interface RedocRawOptions {
maxDisplayedEnumValues?: number;
ignoreNamedSchemas?: string[] | string;
hideSchemaPattern?: boolean;
generatedPayloadSamplesMaxDepth?: number; // remove in next major release
generatedSamplesMaxDepth?: number;
generatedPayloadSamplesMaxDepth?: number;
nonce?: string;
hideFab?: boolean;
minCharacterLengthToInitSearch?: number;
showWebhookVerb?: boolean;
hidePropertiesPrefix?: boolean;
}
export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): boolean {
@ -230,18 +216,17 @@ export class RedocNormalizedOptions {
scrollYOffset: () => number;
hideHostname: boolean;
expandResponses: { [code: string]: boolean } | 'all';
sortRequiredPropsFirst: boolean;
requiredPropsFirst: boolean;
sortPropsAlphabetically: boolean;
sortEnumValuesAlphabetically: boolean;
sortOperationsAlphabetically: boolean;
sortTagsAlphabetically: boolean;
nativeScrollbars: boolean;
pathInMiddlePanel: boolean;
sanitize: boolean;
hideDownloadButtons: boolean;
untrustedSpec: boolean;
hideDownloadButton: boolean;
downloadFileName?: string;
downloadDefinitionUrl?: string;
downloadUrls?: DownloadUrlsConfig;
disableSearch: boolean;
onlyRequiredInSamples: boolean;
showExtensions: boolean | string[];
@ -249,14 +234,13 @@ export class RedocNormalizedOptions {
hideSingleRequestSampleTab: boolean;
hideRequestPayloadSample: boolean;
menuToggle: boolean;
jsonSamplesExpandLevel: number;
jsonSampleExpandLevel: number;
enumSkipQuotes: boolean;
hideSchemaTitles: boolean;
simpleOneOfTypeLabel: boolean;
payloadSampleIdx: number;
expandSingleSchemaField: boolean;
schemasExpansionLevel: number;
schemaDefinitionsTagName?: string;
schemaExpansionLevel: number;
showObjectSchemaExamples: boolean;
showSecuritySchemeType?: boolean;
hideSecuritySection?: boolean;
@ -270,11 +254,10 @@ export class RedocNormalizedOptions {
ignoreNamedSchemas: Set<string>;
hideSchemaPattern: boolean;
generatedSamplesMaxDepth: number;
generatedPayloadSamplesMaxDepth: number;
hideFab: boolean;
minCharacterLengthToInitSearch: number;
showWebhookVerb: boolean;
hidePropertiesPrefix?: boolean;
nonce?: string;
@ -305,20 +288,17 @@ export class RedocNormalizedOptions {
this.scrollYOffset = RedocNormalizedOptions.normalizeScrollYOffset(raw.scrollYOffset);
this.hideHostname = RedocNormalizedOptions.normalizeHideHostname(raw.hideHostname);
this.expandResponses = RedocNormalizedOptions.normalizeExpandResponses(raw.expandResponses);
this.sortRequiredPropsFirst = argValueToBoolean(
raw.sortRequiredPropsFirst || raw.requiredPropsFirst,
);
this.requiredPropsFirst = argValueToBoolean(raw.requiredPropsFirst);
this.sortPropsAlphabetically = argValueToBoolean(raw.sortPropsAlphabetically);
this.sortEnumValuesAlphabetically = argValueToBoolean(raw.sortEnumValuesAlphabetically);
this.sortOperationsAlphabetically = argValueToBoolean(raw.sortOperationsAlphabetically);
this.sortTagsAlphabetically = argValueToBoolean(raw.sortTagsAlphabetically);
this.nativeScrollbars = argValueToBoolean(raw.nativeScrollbars);
this.pathInMiddlePanel = argValueToBoolean(raw.pathInMiddlePanel);
this.sanitize = argValueToBoolean(raw.sanitize || raw.untrustedSpec);
this.hideDownloadButtons = argValueToBoolean(raw.hideDownloadButtons || raw.hideDownloadButton);
this.untrustedSpec = argValueToBoolean(raw.untrustedSpec);
this.hideDownloadButton = argValueToBoolean(raw.hideDownloadButton);
this.downloadFileName = raw.downloadFileName;
this.downloadDefinitionUrl = raw.downloadDefinitionUrl;
this.downloadUrls = raw.downloadUrls;
this.disableSearch = argValueToBoolean(raw.disableSearch);
this.onlyRequiredInSamples = argValueToBoolean(raw.onlyRequiredInSamples);
this.showExtensions = RedocNormalizedOptions.normalizeShowExtensions(raw.showExtensions);
@ -326,18 +306,15 @@ export class RedocNormalizedOptions {
this.hideSingleRequestSampleTab = argValueToBoolean(raw.hideSingleRequestSampleTab);
this.hideRequestPayloadSample = argValueToBoolean(raw.hideRequestPayloadSample);
this.menuToggle = argValueToBoolean(raw.menuToggle, true);
this.jsonSamplesExpandLevel = RedocNormalizedOptions.normalizeJsonSampleExpandLevel(
raw.jsonSamplesExpandLevel || raw.jsonSampleExpandLevel,
this.jsonSampleExpandLevel = RedocNormalizedOptions.normalizeJsonSampleExpandLevel(
raw.jsonSampleExpandLevel,
);
this.enumSkipQuotes = argValueToBoolean(raw.enumSkipQuotes);
this.hideSchemaTitles = argValueToBoolean(raw.hideSchemaTitles);
this.simpleOneOfTypeLabel = argValueToBoolean(raw.simpleOneOfTypeLabel);
this.payloadSampleIdx = RedocNormalizedOptions.normalizePayloadSampleIdx(raw.payloadSampleIdx);
this.expandSingleSchemaField = argValueToBoolean(raw.expandSingleSchemaField);
this.schemasExpansionLevel = argValueToExpandLevel(
raw.schemasExpansionLevel || raw.schemaExpansionLevel,
);
this.schemaDefinitionsTagName = raw.schemaDefinitionsTagName;
this.schemaExpansionLevel = argValueToExpandLevel(raw.schemaExpansionLevel);
this.showObjectSchemaExamples = argValueToBoolean(raw.showObjectSchemaExamples);
this.showSecuritySchemeType = argValueToBoolean(raw.showSecuritySchemeType);
this.hideSecuritySection = argValueToBoolean(raw.hideSecuritySection);
@ -353,13 +330,13 @@ export class RedocNormalizedOptions {
: raw.ignoreNamedSchemas?.split(',').map(s => s.trim());
this.ignoreNamedSchemas = new Set(ignoreNamedSchemas);
this.hideSchemaPattern = argValueToBoolean(raw.hideSchemaPattern);
this.generatedSamplesMaxDepth = RedocNormalizedOptions.normalizeGeneratedPayloadSamplesMaxDepth(
raw.generatedSamplesMaxDepth || raw.generatedPayloadSamplesMaxDepth,
);
this.generatedPayloadSamplesMaxDepth =
RedocNormalizedOptions.normalizeGeneratedPayloadSamplesMaxDepth(
raw.generatedPayloadSamplesMaxDepth,
);
this.nonce = raw.nonce;
this.hideFab = argValueToBoolean(raw.hideFab);
this.minCharacterLengthToInitSearch = argValueToNumber(raw.minCharacterLengthToInitSearch) || 3;
this.showWebhookVerb = argValueToBoolean(raw.showWebhookVerb);
this.hidePropertiesPrefix = argValueToBoolean(raw.hidePropertiesPrefix, true);
}
}

View File

@ -1,24 +0,0 @@
{
"openapi": "3.0.0",
"info": {
"version": "1.0",
"title": "Test"
},
"components": {
"schemas": {
"Test": {
"type": "array",
"description": "test description",
"items": {
"type": "string",
"description": "test description",
"enum": ["authorize", "do-nothing"],
"x-enumDescriptions": {
"authorize-and-void": "Will create an authorize transaction in the amount/currency of the request, followed by a void",
"do-nothing": "Will do nothing, and return an approved `setup` transaction. This is the default behavior."
}
}
}
}
}
}

View File

@ -139,18 +139,10 @@ describe('Models', () => {
} as any;
const opts = new RedocNormalizedOptions({
downloadUrls: [{ title: 'Openapi description', url: 'https:test.com/filename.yaml' }],
downloadDefinitionUrl: 'https:test.com/filename.yaml',
});
const info = new ApiInfoModel(parser, opts);
expect(info.downloadUrls).toMatchInlineSnapshot(`
[
{
"title": "Openapi description",
"url": "https:test.com/filename.yaml",
},
]
`);
expect(info.downloadFileName).toMatchInlineSnapshot(`"openapi.json"`);
expect(info.downloadLink).toEqual('https:test.com/filename.yaml');
});
test('should correctly populate download link and download file name', () => {
@ -166,29 +158,8 @@ describe('Models', () => {
downloadFileName: 'test.yaml',
});
const info = new ApiInfoModel(parser, opts);
expect(info.downloadUrls).toMatchInlineSnapshot(`
[
{
"title": "Download",
"url": "https:test.com/filename.yaml",
},
]
`);
expect(info.downloadFileName).toMatchInlineSnapshot(`"test.yaml"`);
const opts2 = new RedocNormalizedOptions({
downloadUrls: [{ title: 'Download file', url: 'https:test.com/filename.yaml' }],
});
const info2 = new ApiInfoModel(parser, opts2);
expect(info2.downloadUrls).toMatchInlineSnapshot(`
[
{
"title": "Download file",
"url": "https:test.com/filename.yaml",
},
]
`);
expect(info2.downloadFileName).toMatchInlineSnapshot(`"openapi.json"`);
expect(info.downloadLink).toEqual('https:test.com/filename.yaml');
expect(info.downloadFileName).toEqual('test.yaml');
});
});
});

View File

@ -13,17 +13,6 @@ describe('Models', () => {
describe('Schema', () => {
let parser;
test('parsing nested x-enumDescription', () => {
const spec = require('../fixtures/nestedEnumDescroptionSample.json');
parser = new OpenAPIParser(spec, undefined, opts);
const testSchema = spec.components.schemas.Test;
const schemaModel = new SchemaModel(parser, testSchema, '', opts);
expect(schemaModel['x-enumDescriptions']).toStrictEqual(
testSchema.items['x-enumDescriptions'],
);
});
test('discriminator with one field', () => {
const spec = require('../fixtures/discriminator.json');
parser = new OpenAPIParser(spec, undefined, opts);

View File

@ -1,6 +1,5 @@
import type { OpenAPIContact, OpenAPIInfo, OpenAPILicense } from '../../types';
import { IS_BROWSER } from '../../utils/';
import { l } from '../Labels';
import type { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
@ -14,10 +13,7 @@ export class ApiInfoModel implements OpenAPIInfo {
contact?: OpenAPIContact;
license?: OpenAPILicense;
downloadUrls: {
title?: string;
url?: string;
}[];
downloadLink?: string;
downloadFileName?: string;
constructor(
@ -33,28 +29,13 @@ export class ApiInfoModel implements OpenAPIInfo {
this.description = this.description.substring(0, firstHeadingLinePos);
}
this.downloadUrls = this.getDownloadUrls();
this.downloadLink = this.getDownloadLink();
this.downloadFileName = this.getDownloadFileName();
}
private getDownloadUrls() {
return (
!this.options.downloadUrls
? [
{
title: l('download'),
url: this.getDownloadLink(this.options.downloadDefinitionUrl),
},
]
: this.options.downloadUrls.map(({ title, url }) => ({
title: title || l('download'),
url: this.getDownloadLink(url),
}))
).filter(({ title, url }) => title && url);
}
private getDownloadLink(url?: string): string | undefined {
if (url) {
return url;
private getDownloadLink(): string | undefined {
if (this.options.downloadDefinitionUrl) {
return this.options.downloadDefinitionUrl;
}
if (this.parser.specUrl) {

View File

@ -14,7 +14,7 @@ export class MediaTypeModel {
name: string;
isRequestType: boolean;
onlyRequiredInSamples: boolean;
generatedSamplesMaxDepth: number;
generatedPayloadSamplesMaxDepth: number;
/**
* @param isRequestType needed to know if skipe RO/RW fields in objects
@ -30,7 +30,7 @@ export class MediaTypeModel {
this.isRequestType = isRequestType;
this.schema = info.schema && new SchemaModel(parser, info.schema, '', options);
this.onlyRequiredInSamples = options.onlyRequiredInSamples;
this.generatedSamplesMaxDepth = options.generatedSamplesMaxDepth;
this.generatedPayloadSamplesMaxDepth = options.generatedPayloadSamplesMaxDepth;
if (info.examples !== undefined) {
this.examples = mapValues(
info.examples,
@ -55,7 +55,7 @@ export class MediaTypeModel {
skipReadOnly: this.isRequestType,
skipWriteOnly: !this.isRequestType,
skipNonRequired: this.isRequestType && this.onlyRequiredInSamples,
maxSampleDepth: this.generatedSamplesMaxDepth,
maxSampleDepth: this.generatedPayloadSamplesMaxDepth,
};
if (this.schema && this.schema.oneOf) {
this.examples = {};

View File

@ -247,7 +247,7 @@ export class OperationModel implements IMenuItem {
if (this.options.sortPropsAlphabetically) {
return sortByField(_parameters, 'name');
}
if (this.options.sortRequiredPropsFirst) {
if (this.options.requiredPropsFirst) {
return sortByRequired(_parameters);
}

View File

@ -65,7 +65,6 @@ export class SchemaModel {
rawSchema: OpenAPISchema;
schema: MergedOpenAPISchema;
extensions?: Record<string, any>;
'x-enumDescriptions': { [name: string]: string };
const: any;
contentEncoding?: string;
contentMediaType?: string;
@ -123,7 +122,6 @@ export class SchemaModel {
this.type = schema.type || detectType(schema);
this.format = schema.format;
this.enum = schema.enum || [];
this['x-enumDescriptions'] = schema['x-enumDescriptions'];
this.example = schema.example;
this.examples = schema.examples;
this.deprecated = !!schema.deprecated;
@ -223,7 +221,6 @@ export class SchemaModel {
}
if (this.items?.isPrimitive) {
this.enum = this.items.enum;
this['x-enumDescriptions'] = this.items['x-enumDescriptions'];
}
if (isArray(this.type)) {
const filteredType = this.type.filter(item => item !== 'array');
@ -466,7 +463,7 @@ function buildFields(
if (options.sortPropsAlphabetically) {
fields = sortByField(fields, 'name');
}
if (options.sortRequiredPropsFirst) {
if (options.requiredPropsFirst) {
// if not sort alphabetically sort in the order from required keyword
fields = sortByRequired(fields, !options.sortPropsAlphabetically ? schema.required : undefined);
}

View File

@ -311,11 +311,6 @@ exports[`#loadAndBundleSpec should load And Bundle Spec demo/openapi.yaml 1`] =
"sold",
],
"type": "string",
"x-enumDescriptions": {
"available": "Available status",
"pending": "Pending status",
"sold": "Sold status",
},
},
"tags": {
"description": "Tags attached to the pet",

View File

@ -71,30 +71,6 @@ describe('Utils', () => {
const obj2 = { a: ['C'], b: ['D'] };
expect(mergeObjects({}, obj1, obj2)).toEqual({ a: ['C'], b: ['D'] });
});
test('should prevent prototype pollution', () => {
const target = {};
const source = JSON.parse('{"__proto__": {"polluted": "yes"}}');
mergeObjects(target, source);
expect(({} as any).polluted).toBeUndefined();
});
test('should merge objects correctly', () => {
const target = { a: 1 };
const source = { b: 2 };
const result = mergeObjects(target, source);
expect(result).toEqual({ a: 1, b: 2 });
});
test('should handle nested objects', () => {
const target = { a: { b: 1 } };
const source = { a: { c: 2 } };
const result = mergeObjects(target, source);
expect(result).toEqual({ a: { b: 1, c: 2 } });
});
});
describe('titleize', () => {

View File

@ -81,6 +81,7 @@ export function appendToMdHeading(md: string, heading: string, content: string)
}
}
// credits https://stackoverflow.com/a/46973278/1749888
export const mergeObjects = (target: any, ...sources: any[]): any => {
if (!sources.length) {
return target;
@ -92,15 +93,13 @@ export const mergeObjects = (target: any, ...sources: any[]): any => {
if (isMergebleObject(target) && isMergebleObject(source)) {
Object.keys(source).forEach((key: string) => {
if (Object.prototype.hasOwnProperty.call(source, key) && key !== '__proto__') {
if (isMergebleObject(source[key])) {
if (!target[key]) {
target[key] = {};
}
mergeObjects(target[key], source[key]);
} else {
target[key] = source[key];
if (isMergebleObject(source[key])) {
if (!target[key]) {
target[key] = {};
}
mergeObjects(target[key], source[key]);
} else {
target[key] = source[key];
}
});
}

View File

@ -393,7 +393,7 @@ export function getSerializedValue(field: FieldModel, example: any) {
// decode for better readability in examples: see https://github.com/Redocly/redoc/issues/1138
return decodeURIComponent(serializeParameterValue(field, example));
} else {
return typeof example === 'object' ? example : String(example);
return String(example);
}
}
@ -654,7 +654,7 @@ export function isRedocExtension(key: string): boolean {
'x-codeSamples': true,
'x-displayName': true,
'x-examples': true,
'x-enumDescriptions': true,
'x-ignoredHeaderParameters': true,
'x-logo': true,
'x-nullable': true,
'x-servers': true,