diff --git a/.github/workflows/demo-deploy-s3.yml b/.github/workflows/demo-deploy-s3.yml
deleted file mode 100644
index efb2ca19..00000000
--- a/.github/workflows/demo-deploy-s3.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-name: Redoc demo CI/CD
-
-on:
- push:
- tags:
- - v[0-9]*.[0-9]*.[0-9]*
-
-jobs:
- build-and-unit:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v1
- - run: npm ci
- - run: npm run bundle
- - run: npm test
- deploy:
- needs: build-and-unit
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v1
- - name: cache node modules
- uses: actions/cache@v1
- with:
- path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
- key: npm-${{ hashFiles('package-lock.json') }}
- restore-keys: |
- npm-${{ hashFiles('package-lock.json') }}
- npm-
- - name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
- with:
- aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
- aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- aws-region: us-east-1
- - name: Install dependencies
- run: npm ci
- - name: Build package
- run: npm run build:demo
- - name: Deploy to S3 bucket
- run: npm run deploy:demo
- - name: Invalidate
- run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CF_DEMO_DISTRIBUTION_ID }} --paths "/*"
diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml
new file mode 100644
index 00000000..514a3193
--- /dev/null
+++ b/.github/workflows/e2e-tests.yml
@@ -0,0 +1,12 @@
+name: Tests e2e
+
+on: [push]
+
+jobs:
+ build-and-e2e:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - run: npm ci
+ - run: npm run bundle
+ - run: npm run e2e
diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml
new file mode 100644
index 00000000..9bfa3fff
--- /dev/null
+++ b/.github/workflows/publish-cli.yml
@@ -0,0 +1,115 @@
+name: Publish cli
+
+on:
+ push:
+ tags:
+ - v[0-9]*.[0-9]*.[0-9]*
+
+
+jobs:
+ bundle:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ - name: Cache node modules
+ uses: actions/cache@v2
+ with:
+ path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
+ key: npm-${{ hashFiles('package-lock.json') }}
+ restore-keys: |
+ npm-${{ hashFiles('package-lock.json') }}
+ npm-
+ - run: npm ci
+ - run: npm run bundle
+ - name: Store bundle artifact
+ uses: actions/upload-artifact@v2
+ with:
+ name: bundles-cli
+ path: bundles
+ retention-days: 1
+ unit-tests:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+ - run: npm ci
+ - run: npm test
+ e2e-tests:
+ needs: [bundle]
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+ - run: npm ci
+ - name: Download bundled artifact
+ uses: actions/download-artifact@v2
+ with:
+ name: bundles
+ path: bundles-cli
+ - run: npm run e2e
+ bundle-cli:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ - name: Cache node modules
+ uses: actions/cache@v2
+ with:
+ path: ~/.npm
+ key: npm-${{ hashFiles('package-lock.json') }}
+ restore-keys: |
+ npm-${{ hashFiles('package-lock.json') }}
+ npm-
+ - name: Install dependencies
+ run: npm ci
+ - name: Bundle
+ run: npm run compile:cli
+ - name: Store bundle artifact
+ uses: actions/upload-artifact@v2
+ with:
+ name: cli
+ path: cli
+ retention-days: 1
+ check-version-cli:
+ name: Check Version
+ runs-on: ubuntu-latest
+ needs: [bundle-cli, unit-tests, e2e-tests]
+ outputs:
+ changed: ${{ steps.check.outputs.changed }}
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+ - name: Set up Node.js
+ uses: actions/setup-node@v2
+ - name: Check if version has been updated
+ id: check
+ uses: EndBug/version-check@v2.0.1
+ with:
+ file-name: ./cli/package.json
+ file-url: https://unpkg.com/redoc-cli/package.json
+ static-checking: localIsNew
+ publish-cli:
+ needs: [ check-version-cli ]
+ if: needs.check-version-cli.outputs.changed == 'true'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/setup-node@v1
+ with:
+ node-version: "14.x"
+ - uses: actions/checkout@v2
+ - name: Download cli bundled artifact
+ uses: actions/download-artifact@v2
+ with:
+ name: cli
+ path: cli
+ - name: Cache node modules
+ uses: actions/cache@v2
+ with:
+ path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
+ key: npm-${{ hashFiles('package-lock.json') }}
+ restore-keys: |
+ npm-${{ hashFiles('package-lock.json') }}
+ npm-
+ - name: Publish to NPM
+ run: cd cli/ && npm publish
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 00000000..d1c9ccbf
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,100 @@
+name: Publish
+
+on:
+ push:
+ tags:
+ - v[0-9]*.[0-9]*.[0-9]*
+
+jobs:
+ bundle:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ - name: Cache node modules
+ uses: actions/cache@v2
+ with:
+ path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
+ key: npm-${{ hashFiles('package-lock.json') }}
+ restore-keys: |
+ npm-${{ hashFiles('package-lock.json') }}
+ npm-
+ - run: npm ci
+ - run: npm run bundle
+ - name: Store bundle artifact
+ uses: actions/upload-artifact@v2
+ with:
+ name: bundles
+ path: bundles
+ retention-days: 1
+ unit-tests:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+ - run: npm ci
+ - run: npm test
+ e2e-tests:
+ needs: [bundle]
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+ - run: npm ci
+ - name: Download bundled artifact
+ uses: actions/download-artifact@v2
+ with:
+ name: bundles
+ path: bundles
+ - run: npm run e2e
+ deploy-demo:
+ needs: [bundle, unit-tests, e2e-tests]
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v1
+ with:
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ aws-region: us-east-1
+ - name: Install dependencies
+ run: npm ci
+ - name: Download bundled artifacts
+ uses: actions/download-artifact@v2
+ with:
+ name: bundles
+ path: bundles
+ - name: Build package
+ run: npm run build:demo
+ - name: Deploy to S3 bucket
+ run: npm run deploy:demo
+ - name: Invalidate
+ run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CF_DEMO_DISTRIBUTION_ID }} --paths "/*"
+ publish:
+ needs: [bundle, unit-tests, e2e-tests]
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/setup-node@v1
+ with:
+ node-version: "14.x"
+ - uses: actions/checkout@v2
+ - name: Download bundled artifacts
+ uses: actions/download-artifact@v2
+ with:
+ name: bundles
+ path: bundles
+ - name: Cache node modules
+ uses: actions/cache@v2
+ with:
+ path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
+ key: npm-${{ hashFiles('package-lock.json') }}
+ restore-keys: |
+ npm-${{ hashFiles('package-lock.json') }}
+ npm-
+ - name: Before deploy
+ run: npm run declarations
+ - name: Publish to NPM
+ run: npm publish
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - name: After script
+ run: cat ./coverage/lcov.info | coveralls
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index 09e54a63..a0a0bbd1 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -9,4 +9,4 @@ jobs:
- uses: actions/checkout@v1
- run: npm ci
- run: npm run bundle
- - run: npm test
+ - run: npm test
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 03ac1fa4..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-language: node_js
-node_js:
-- '12'
-cache:
- directories:
- - "~/.cache"
-env:
- global:
- - GH_REF: github.com/Redocly/redoc.git
- - GIT_AUTHOR_EMAIL: redoc-bot@users.noreply.github.com
- - GIT_AUTHOR_NAME: RedocBot
- - secure: apiavCfCQngL9Een1m7MIXMf3bqO3rY4YY59TMBl/yFKi80CEsHPHhgVUkl6hC+aM5PeBt/vgjh37rHMX31j/pcSZ4Z8SO/4Bwr36iHfhSxSEuAQog8P07qWqH7wYYWGIVmF682stgl0fYF+GN92sx/6edFVzsWVECf2G7imtICKSTbhKGm3Dhn2JwGnhD7eyfgZ33omgiaswumdu0xABoXDfqSZR+16fC4Ap5rhv3fXO9ndvRNy1STn376nT+my6e86UrQL4aS/S+HNHgIe1BUs+5cOp6Jgw6t0ie7phY0EAiECsRxy9K4e3Dctv9m6+Wma4+vy65MS0zGyrqey6oyV4l827sCOjrD1qcqc9bX6FlMSouVoNfE4ZjINNAbgigTaiLSoDSPcf5I5smkkM2ezzFOMSZwZxNdaNL2LKb97vc8m/ZUkv0sKZyT7oqVL7aJweEivsSHj5l2KR8Z7XrVB1y2eI6GvyTSa/d+CL4dSRzjh8+IRN047YBrdTKD5IkdT0upfoBu14WPUfFmLKxX+iMCslXRWb6kwojhrWNYmZvL65KRAzJ6+eIPDG/W5QUOpYyYT77bLlBQjVo6NmVvl9v3HMECq9CHH0ivKFBGPiKMOx7cJkTax3FuyznOW2WCXB9kTb5Zk9toaiNlSp9L6ll/h2Eyxa6n6sWUgmmM=
- - secure: vVRg9BKGBwF2MbXQnEccFL+XW0/7RaBmge9k7jbGYScBwkP3XjnQ/Xaj0cvTz2CM2EqXsbpwfvr4Jo+enW/E3MGy5RiEzv5hUe/jIFRR0gfAFbZxSTvg5xiFhTDffqQk0fncO4jXu+wPO5lZ2CMRWzyXz3i1MZhjMcAgoDr1+TRss/EGXLNHxr2RM88tpUW0fV2prIRoyGqhCgnYZtrm7hmr41Ej+itg1MqZLml/Rjkt3KsNgI+z0O5Qn3QSAO8GtPZqeftQxAjevOmxZGcssxY8EJvqbjAujr4y51WncXpEmCRPSY2J9R5+fkgZurqwnJapbQpjwKYemok3ps7EHg2gWkAlmPdQO4LKpbffGkM/o5b+8+HdIuQZugsSWQD9hUSftTAFLcfA1isi7V2lHE1m8bX/vk9zIyDdcPSwIaFe9y+w3PexwFmTjPLq+nia/UY2kARFZMEIFAJby6gkA70DcAJ50QOM86InJu5DSzGbIssgTGAXCn0TPPyGveaurVLw8x61j3yh8LDF46gUHey3rqv6WjpCM9h/vg7X/gq5ve/5Q2KHscUKfs/sA53Mt7qPeqRZY1QCaaRjzqJO/ZraHqWWeKmPKaWhPGR0kYEnkvB+K9GZ+HNSWCltjCO4SJ1xeEl7CRqQxAwdiMATF5SKqyiC+bn5oc35mFgbRF8=
- - secure: ela1tn4wkJQZ8O4iv+4pIZi5cebxeCStVF1tEUe6qa6WWgJYVXmS2tEv3QQ36NUBFrP58Y6yl10XguPnvj/2BCqcZI4FUBHh3BfiBoUtXxDCVKI5LtlniNiOFGUwfzEeYka8T51zFlcUXSCCaxHkRZbmBsIzeJ39UwTi5fy0qwLv9GgL0czhwm8I8sZ8gyWdGmqpXNFEsb9JP4ZA3mw2qpWkGpGAqQPD9XSCkU3LmX1/ltwsBMAgGYKLLo7vU8d5KV2c8L1Gnxfl6BvfmqUD/dsas/1rnk08rU2nez5ekuQa2tJRkDLOv8bqvrGRLjHSUa3yPuisC6SsDGSU7/3DcozZyYsz7WQ6WI8tYabyjqqeJTF1N8a5T3IbZaZNV1J4JHOO9Cb/y7gIg4edANg6tbe7MzZpdEPRBnw6OkdTdirpNsWQ/jnfpY1hn6mraQZz/q8yaz3W21NjbBJhVnvfh5gWLKQ3YAAziCBhmmrThFhUu0czz+G920MuFo477TBcxvlrE7CaNJ0Q6yYkDehEPOv3jvEs1QVHPwuRrlaLTbBhrlTICKZ58gdX30O8N4i0Xgp/v6qrC03bplnMQc8E/uC61wcVLJixnlZVp8FODpUvPjsxVFkpuNSOIAaiqcERmoiPXx05Epzmr78hjU5rYCx/1MmVoeB4gs9YO+4guD4=
-addons:
- chrome: stable
- apt:
- packages:
- - libgconf-2-4
-before_script: npm run bundle
-script: npm test && ([ "${TRAVIS_PULL_REQUEST}" = "false" ] && npm run e2e-ci || npm
- run e2e)
-after_script: cat ./coverage/lcov.info | coveralls
-before_deploy: npm run compile:cli && npm run declarations
-deploy:
-- provider: npm
- skip_cleanup: true
- email: gotsijroman@gmail.com
- tag: next
- api_key: "$NPM_TOKEN"
- on:
- tags: true
diff --git a/README.md b/README.md
index 2bbdc134..6d3f335a 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-

+

- **OpenAPI/Swagger-generated API Reference Documentation**
+ # Generate interactive API documentation from OpenAPI definitions
[](https://travis-ci.com/Redocly/redoc) [](https://coveralls.io/github/Redocly/redoc?branch=master) [](https://david-dm.org/Redocly/redoc) [](https://david-dm.org/Redocly/redoc#info=devDependencies) [](https://www.npmjs.com/package/redoc) [](https://github.com/Redocly/redoc/blob/master/LICENSE)
@@ -11,30 +11,93 @@
**This is the README for the `2.x` version of Redoc (React-based).**
**The README for the `1.x` version is on the [v1.x](https://github.com/Redocly/redoc/tree/v1.x) branch**
-
+## About Redoc
-## [Live demo](http://redocly.github.io/redoc/)
+Redoc is an open-source tool for generating documentation from OpenAPI (fka Swagger) definitions.
-[

](https://github.com/Rebilly/generator-openapi-repo#generator-openapi-repo--) [

](https://redoc.ly) [

](https://redoc.ly/#services)
+By default Redoc offers a three-panel, responsive layout:
+
+- The left panel contains a search bar and navigation menu.
+- The central panel contains the documentation.
+- The right panel contains request and response examples.
+
+
+
+## Live demo
+
+If you want to see how Redoc will render your OpenAPI definition,
+you can try it out online at https://redocly.github.io/redoc/.
+
+A version of the Swagger Petstore API is displayed by default.
+To test it with your own OpenAPI definition,
+enter the URL for your definition and select **TRY IT**.
+
+## Redoc vs. Reference vs. Portals
+
+Redoc is Redocly's community-edition product. Looking for something more?
+Checkout the following feature comparison of Redocly's premium products versus Redoc:
+
+| Features | Redoc | Reference | Portals |
+|------------------------------|:---------:|:---------:|:-----------:|
+| **Specs** | | | |
+| Swagger 2.0 | √ | √ | √ |
+| OpenAPI 3.0 | √ | √ | √ |
+| OpenAPI 3.1 | √ (basic) | √ | √ |
+| | | | |
+| **Theming** | | | |
+| Fonts/colors | √ | √ | √ |
+| Extra theme options | | √ | √ |
+| | | | |
+| **Performance** | | | |
+| Pagination | | √ | √ |
+| Search (enhanced) | | √ | √ |
+| Search (server-side) | | | √ |
+| | | | |
+| **Multiple APIs** | | | |
+| Multiple versions | | √ | √ |
+| Multiple APIs | | | √ |
+| API catalog | | | √ |
+| | | | |
+| **Additional features** | | | |
+| Try-it console | | √ | √ |
+| Automated code samples | | √ | √ |
+| Deep links | | √ | √ |
+| More SEO control | | | √ |
+| Contextual docs | | | √ |
+| Landing pages | | | √ |
+| React hooks for more control | | | √ |
+| Personalization | | | √ |
+| Analytics integrations | | | √ |
+| Feedback | | | Coming Soon |
+
+Refer to the Redocly's documentation for more information on these products:
+
+- [Portals](https://redoc.ly/docs/developer-portal/introduction/)
+- [Reference](https://redoc.ly/docs/api-reference-docs/getting-started/)
+- [Redoc](https://redoc.ly/docs/redoc/quickstart/intro/)
## Features
+- Responsive three-panel design with menu/scrolling synchronization
- [Multiple deployment options](https://redoc.ly/docs/redoc/quickstart/intro/)
- [Server-side rendering (SSR) ready](https://redoc.ly/docs/redoc/quickstart/cli/#redoc-cli-commands)
-- [Simple integration with `create-react-app`](https://redoc.ly/docs/redoc/quickstart/react/)
-
- [See an example](https://github.com/APIs-guru/create-react-app-redoc)
-- [Command-line interface to bundle your docs into a **zero-dependency** HTML file](https://redoc.ly/docs/redoc/quickstart/cli/)
-- Responsive three-panel design with menu/scrolling synchronization
-- Deep linking support
- Ability to integrate your API introduction into the side menu
-- High-level grouping in side-menu with [`x-tagGroups`](https://redoc.ly/docs/api-reference-docs/specification-extensions/x-tag-groups/) specification extension
+- [Simple integration with `create-react-app`](https://redoc.ly/docs/redoc/quickstart/react/)
+
+ [Example repo](https://github.com/APIs-guru/create-react-app-redoc)
+- [Command-line interface to bundle your docs into a **zero-dependency** HTML file](https://redoc.ly/docs/redoc/quickstart/cli/)
+- Neat **interactive** documentation for nested objects
+ 
+
+## Customization options
+[

](https://redoc.ly/#services)
+- High-level grouping in side-menu with the [`x-tagGroups`](https://redoc.ly/docs/api-reference-docs/specification-extensions/x-tag-groups/) specification extension
- Branding/customizations using the [`theme` option](https://redoc.ly/docs/api-reference-docs/configuration/theming/)
+
+## Support
- OpenAPI v3.0 support
- Basic OpenAPI v3.1 support
- Broad OpenAPI v2.0 feature support (yes, it supports even `discriminator`)

-- Neat **interactive** documentation for nested objects
- 
- Code samples support (via vendor extension)

@@ -44,12 +107,12 @@
- `next` release: https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js
Additionally, all the 1.x releases are hosted on our GitHub Pages-based CDN **(deprecated)**:
-- particular release, e.g. `v1.2.0`: https://rebilly.github.io/ReDoc/releases/v1.2.0/redoc.min.js
+- particular release, for example `v1.2.0`: https://rebilly.github.io/ReDoc/releases/v1.2.0/redoc.min.js
- `v1.x.x` release: https://rebilly.github.io/ReDoc/releases/v1.x.x/redoc.min.js
- `latest` release: https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js - it will point to latest 1.x.x release since 2.x releases are not hosted on this CDN but on unpkg.
## Version Guidance
-| ReDoc Release | OpenAPI Specification |
+| Redoc Release | OpenAPI Specification |
|:--------------|:----------------------|
| 2.0.0-alpha.54| 3.1, 3.0.x, 2.0 |
| 2.0.0-alpha.x | 3.0, 2.0 |
@@ -66,16 +129,59 @@ Additionally, all the 1.x releases are hosted on our GitHub Pages-based CDN **(d
- [APIs.guru](https://apis.guru/api-doc/)
- [BoxKnight](https://www.docs.boxknight.com/)
+## Lint OpenAPI definitions
+
+Redocly's OpenAPI CLI is an open source command-line tool that you can use to lint
+your OpenAPI definition. Linting helps you to catch errors and inconsistencies in your
+OpenAPI definition before publishing.
+
+Refer to [Lint configuration](https://redoc.ly/docs/cli/guides/lint/) in the OpenAPI documentation for more information.
+
## Deployment
+
+### TL;DR final code example
+
+To render your OpenAPI definition using Redoc, use the following HTML code sample and
+replace the `spec-url` attribute with the url or local file address to your definition.
+
+```html
+
+
+
+
Redoc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
For step-by-step instructions for how to get started using Redoc
to render your OpenAPI definition, refer to the
-[Redoc quickstart guide](https://redoc.ly/docs/redoc/quickstart/intro/).
+[**Redoc quickstart guide**](https://redoc.ly/docs/redoc/quickstart/intro/).
-[**IE11 Support Notes**](docs/usage-with-ie11.md)
+See [**IE11 Support Notes**](docs/usage-with-ie11.md) for information on
+IE support for Redoc.
-## ReDoc CLI
+## Redoc CLI
For more information on Redoc's commmand-line interface, refer to
-[Using the Redoc CLI](https://redoc.ly/docs/redoc/quickstart/cli/).
+[**Using the Redoc CLI**](https://redoc.ly/docs/redoc/quickstart/cli/).
## Configuration
diff --git a/demo/openapi-3-1.yaml b/demo/openapi-3-1.yaml
index 31063d4b..ac89619d 100644
--- a/demo/openapi-3-1.yaml
+++ b/demo/openapi-3-1.yaml
@@ -533,6 +533,20 @@ paths:
subscriptionId:
type: string
example: AAA-123-BBB-456
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ type: array
+ maxItems: 999
+ minItems: 0
+ items:
+ type: array
+ maxItems: 777
+ minItems: 111
+ items:
+ type: number
callbacks:
orderInProgress:
'{$request.body#/callbackUrl}?event={$request.body#/eventName}':
diff --git a/demo/openapi.yaml b/demo/openapi.yaml
index c570cc60..5cf19340 100644
--- a/demo/openapi.yaml
+++ b/demo/openapi.yaml
@@ -377,7 +377,9 @@ paths:
application/xml:
schema:
type: array
+ maxItems: 999
items:
+ maxItems: 111
$ref: '#/components/schemas/Pet'
'400':
description: Invalid tag value
diff --git a/docs/images/redoc.png b/docs/images/redoc.png
new file mode 100644
index 00000000..15579760
Binary files /dev/null and b/docs/images/redoc.png differ
diff --git a/src/components/Schema/ArraySchema.tsx b/src/components/Schema/ArraySchema.tsx
index eab37595..0b555c07 100644
--- a/src/components/Schema/ArraySchema.tsx
+++ b/src/components/Schema/ArraySchema.tsx
@@ -13,15 +13,12 @@ const PaddedSchema = styled.div`
export class ArraySchema extends React.PureComponent
{
render() {
- const itemsSchema = this.props.schema.items!;
const schema = this.props.schema;
+ const itemsSchema = schema.items;
- const itemConstraintSchema = (
- min: number | undefined = undefined,
- max: number | undefined = undefined,
- ) => ({ type: 'array', minItems: min, maxItems: max });
-
- const minMaxItems = humanizeConstraints(itemConstraintSchema(itemsSchema?.schema?.minItems, itemsSchema?.schema?.maxItems));
+ const minMaxItems = schema.minItems === undefined && schema.maxItems === undefined ?
+ '' :
+ `(${humanizeConstraints(schema)})`;
if (schema.displayType && !itemsSchema && !minMaxItems.length) {
return (
@@ -31,7 +28,7 @@ export class ArraySchema extends React.PureComponent
{
return (
-
Array ({minMaxItems})
+
Array {minMaxItems}
diff --git a/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap b/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap
index fe5617ed..7af7b482 100644
--- a/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap
+++ b/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap
@@ -33,6 +33,8 @@ exports[`Components SchemaView discriminator should correctly render discriminat
"format": undefined,
"isCircular": undefined,
"isPrimitive": true,
+ "maxItems": undefined,
+ "minItems": undefined,
"options": "<<
>>",
"pattern": undefined,
"pointer": "#/components/schemas/Dog/properties/packSize",
@@ -86,6 +88,8 @@ exports[`Components SchemaView discriminator should correctly render discriminat
"format": undefined,
"isCircular": undefined,
"isPrimitive": true,
+ "maxItems": undefined,
+ "minItems": undefined,
"options": "<<>>",
"pattern": undefined,
"pointer": "#/components/schemas/Dog/properties/type",
diff --git a/src/services/OpenAPIParser.ts b/src/services/OpenAPIParser.ts
index 11a001aa..4881c99e 100644
--- a/src/services/OpenAPIParser.ts
+++ b/src/services/OpenAPIParser.ts
@@ -174,6 +174,18 @@ export class OpenAPIParser {
return obj;
}
+ shallowDeref(obj: OpenAPIRef | T): T {
+ if (this.isRef(obj)) {
+ const schemaName = getDefinitionName(obj.$ref);
+ if (schemaName && this.options.ignoreNamedSchemas.has(schemaName)) {
+ return { type: 'object', title: schemaName } as T;
+ }
+ const resolved = this.byRef(obj.$ref);
+ return this.allowMergeRefs ? this.mergeRefs(obj, resolved, false) : (resolved as T);
+ }
+ return obj;
+ }
+
mergeRefs(ref, resolved, mergeAsAllOf: boolean) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { $ref, ...rest } = ref;
@@ -183,7 +195,7 @@ export class OpenAPIParser {
}
if (mergeAsAllOf && keys.some((k) => k !== 'description' && k !== 'title' && k !== 'externalDocs')) {
return {
- allOf: [resolved, rest],
+ allOf: [rest, resolved],
};
} else {
// small optimization
@@ -194,13 +206,6 @@ export class OpenAPIParser {
}
}
- shalowDeref(obj: OpenAPIRef | T): T {
- if (this.isRef(obj)) {
- return this.byRef(obj.$ref)!;
- }
- return obj;
- }
-
/**
* Merge allOf constraints.
* @param schema schema with allOF
diff --git a/src/services/__tests__/OpenAPIParser.test.ts b/src/services/__tests__/OpenAPIParser.test.ts
index b79f61b4..b8b211ba 100644
--- a/src/services/__tests__/OpenAPIParser.test.ts
+++ b/src/services/__tests__/OpenAPIParser.test.ts
@@ -1,5 +1,6 @@
import { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
+import { OpenAPIParameter, Referenced } from '../../types';
const opts = new RedocNormalizedOptions({});
@@ -13,5 +14,18 @@ describe('Models', () => {
parser = new OpenAPIParser(spec, undefined, opts);
expect(parser.mergeAllOf(spec.components.schemas.test)).toMatchSnapshot();
});
+
+ test('should override description from $ref of the referenced component, when sibling description exists ', () => {
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
+ const spec = require('./fixtures/siblingRefDescription.json');
+ parser = new OpenAPIParser(spec, undefined, opts);
+ const schemaOrRef: Referenced = {
+ $ref: '#/components/schemas/Test',
+ description: 'Overriden description',
+ };
+
+ expect(parser.shallowDeref(schemaOrRef)).toMatchSnapshot();
+ });
+
});
});
diff --git a/src/services/__tests__/__snapshots__/OpenAPIParser.test.ts.snap b/src/services/__tests__/__snapshots__/OpenAPIParser.test.ts.snap
index 74a26ed0..ffbcbff5 100644
--- a/src/services/__tests__/__snapshots__/OpenAPIParser.test.ts.snap
+++ b/src/services/__tests__/__snapshots__/OpenAPIParser.test.ts.snap
@@ -86,3 +86,10 @@ Object {
],
}
`;
+
+exports[`Models Schema should override description from $ref of the referenced component, when sibling description exists 1`] = `
+Object {
+ "description": "Overriden description",
+ "type": "object",
+}
+`;
diff --git a/src/services/__tests__/fixtures/siblingRefDescription.json b/src/services/__tests__/fixtures/siblingRefDescription.json
new file mode 100644
index 00000000..b090a963
--- /dev/null
+++ b/src/services/__tests__/fixtures/siblingRefDescription.json
@@ -0,0 +1,39 @@
+{
+ "openapi": "3.1.0",
+ "info": {
+ "title": "AA",
+ "version": "1.0"
+ },
+ "paths": {
+ "/test": {
+ "get": {
+ "operationId": "test",
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "testAttr": {
+ "description": "Overriden description",
+ "$ref": "#/components/schemas/Test"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Test": {
+ "type": "object",
+ "description": "Refed description"
+ }
+ }
+ }
+}
diff --git a/src/services/models/MediaType.ts b/src/services/models/MediaType.ts
index 9e41d89a..25dae807 100644
--- a/src/services/models/MediaType.ts
+++ b/src/services/models/MediaType.ts
@@ -40,7 +40,7 @@ export class MediaTypeModel {
this.examples = {
default: new ExampleModel(
parser,
- { value: parser.shalowDeref(info.example) },
+ { value: parser.shallowDeref(info.example) },
name,
info.encoding,
),
diff --git a/src/services/models/Schema.ts b/src/services/models/Schema.ts
index d79d738b..b155d254 100644
--- a/src/services/models/Schema.ts
+++ b/src/services/models/Schema.ts
@@ -63,6 +63,8 @@ export class SchemaModel {
const: any;
contentEncoding?: string;
contentMediaType?: string;
+ minItems?: number;
+ maxItems?: number;
/**
* @param isChild if schema discriminator Child
@@ -128,6 +130,8 @@ export class SchemaModel {
this.const = schema.const || '';
this.contentEncoding = schema.contentEncoding;
this.contentMediaType = schema.contentMediaType;
+ this.minItems = schema.minItems;
+ this.maxItems = schema.maxItems;
if (!!schema.nullable || schema['x-nullable']) {
if (Array.isArray(this.type) && !this.type.some((value) => value === null || value === 'null')) {
@@ -359,7 +363,7 @@ function buildFields(
): FieldModel[] {
const props = schema.properties || {};
const additionalProps = schema.additionalProperties;
- const defaults = schema.default || {};
+ const defaults = schema.default;
let fields = Object.keys(props || []).map((fieldName) => {
let field = props[fieldName];
@@ -380,7 +384,7 @@ function buildFields(
required,
schema: {
...field,
- default: field.default === undefined ? defaults[fieldName] : field.default,
+ default: field.default === undefined && defaults ? defaults[fieldName] : field.default,
},
},
$ref + '/properties/' + fieldName,
diff --git a/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap b/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap
index 7807e39e..6cd0a034 100644
--- a/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap
+++ b/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap
@@ -729,7 +729,9 @@ try {
"schema": Object {
"items": Object {
"$ref": "#/components/schemas/Pet",
+ "maxItems": 111,
},
+ "maxItems": 999,
"type": "array",
},
},
@@ -3245,6 +3247,26 @@ culpa qui officia deserunt mollit anim id est laborum.
},
},
"responses": Object {
+ "200": Object {
+ "content": Object {
+ "application/json": Object {
+ "schema": Object {
+ "items": Object {
+ "items": Object {
+ "type": "number",
+ },
+ "maxItems": 777,
+ "minItems": 111,
+ "type": "array",
+ },
+ "maxItems": 999,
+ "minItems": 0,
+ "type": "array",
+ },
+ },
+ },
+ "description": "Successful operation",
+ },
"201": Object {
"content": Object {
"application/json": Object {
diff --git a/src/utils/__tests__/openapi.test.ts b/src/utils/__tests__/openapi.test.ts
index d4f23e02..6f40d974 100644
--- a/src/utils/__tests__/openapi.test.ts
+++ b/src/utils/__tests__/openapi.test.ts
@@ -412,10 +412,10 @@ describe('Utils', () => {
describe('openapi humanizeConstraints', () => {
const itemConstraintSchema = (
- min: number | undefined = undefined,
- max: number | undefined = undefined,
- multipleOf: number | undefined = undefined,
- uniqueItems?: boolean,
+ min?: number,
+ max?: number,
+ multipleOf?: number,
+ uniqueItems?: boolean
) => ({ type: 'array', minItems: min, maxItems: max, multipleOf, uniqueItems });
it('should not have a humanized constraint without schema constraints', () => {
diff --git a/src/utils/highlight.ts b/src/utils/highlight.ts
index 036b9129..23cdd43d 100644
--- a/src/utils/highlight.ts
+++ b/src/utils/highlight.ts
@@ -15,6 +15,7 @@ import 'prismjs/components/prism-objectivec.js';
import 'prismjs/components/prism-perl.js';
import 'prismjs/components/prism-php.js';
import 'prismjs/components/prism-python.js';
+import 'prismjs/components/prism-q.js';
import 'prismjs/components/prism-ruby.js';
import 'prismjs/components/prism-scala.js';
import 'prismjs/components/prism-sql.js';
diff --git a/src/utils/openapi.ts b/src/utils/openapi.ts
index ad267722..d0b081f5 100644
--- a/src/utils/openapi.ts
+++ b/src/utils/openapi.ts
@@ -505,13 +505,13 @@ export function mergeParams(
): Array> {
const operationParamNames = {};
operationParams.forEach(param => {
- param = parser.shalowDeref(param);
+ param = parser.shallowDeref(param);
operationParamNames[param.name + '_' + param.in] = true;
});
// filter out path params overridden by operation ones with the same name
pathParams = pathParams.filter(param => {
- param = parser.shalowDeref(param);
+ param = parser.shallowDeref(param);
return !operationParamNames[param.name + '_' + param.in];
});