mirror of
				https://github.com/Redocly/redoc.git
				synced 2025-10-31 15:57:30 +03:00 
			
		
		
		
	
						commit
						8011affd00
					
				
							
								
								
									
										8
									
								
								.github/workflows/e2e-tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/e2e-tests.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -1,12 +1,16 @@ | |||
| name: E2E Tests | ||||
| 
 | ||||
| on: [push, pull_request] | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'main' | ||||
|   pull_request: | ||||
| 
 | ||||
| jobs: | ||||
|   build-and-e2e: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|       - run: npm ci && npm ci --prefix cli | ||||
|       - run: npm ci | ||||
|       - run: npm run bundle | ||||
|       - run: npm run e2e | ||||
|  |  | |||
							
								
								
									
										22
									
								
								.github/workflows/publish.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								.github/workflows/publish.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -26,7 +26,7 @@ jobs: | |||
|             npm- | ||||
| 
 | ||||
|       - name: Clean Install | ||||
|         run: npm ci && npm ci --prefix cli | ||||
|         run: npm ci | ||||
| 
 | ||||
|       - name: Bundle | ||||
|         run: npm run bundle | ||||
|  | @ -37,7 +37,7 @@ jobs: | |||
|           name: bundles | ||||
|           path: bundles | ||||
|           retention-days: 1 | ||||
|    | ||||
| 
 | ||||
|   unit-tests: | ||||
|     name: Unit Tests | ||||
|     runs-on: ubuntu-latest | ||||
|  | @ -46,11 +46,11 @@ jobs: | |||
|         uses: actions/checkout@v3 | ||||
| 
 | ||||
|       - name: Clean Install | ||||
|         run: npm ci && npm ci --prefix cli | ||||
|         run: npm ci | ||||
| 
 | ||||
|       - name: Unit Test | ||||
|         run: npm test | ||||
|    | ||||
| 
 | ||||
|   e2e-tests: | ||||
|     name: E2E Tests | ||||
|     needs: [bundle] | ||||
|  | @ -60,7 +60,7 @@ jobs: | |||
|         uses: actions/checkout@v3 | ||||
| 
 | ||||
|       - name: Clean Install | ||||
|         run: npm ci && npm ci --prefix cli | ||||
|         run: npm ci | ||||
| 
 | ||||
|       - name: Download bundled artifact | ||||
|         uses: actions/download-artifact@v3 | ||||
|  | @ -70,7 +70,7 @@ jobs: | |||
| 
 | ||||
|       - name: E2E Test | ||||
|         run: npm run e2e | ||||
|    | ||||
| 
 | ||||
|   publish: | ||||
|     name: Publish | ||||
|     needs: [unit-tests, e2e-tests] | ||||
|  | @ -109,11 +109,11 @@ jobs: | |||
| 
 | ||||
|       - name: Publish npm Package | ||||
|         run: | | ||||
|               npm version $RELEASE_VERSION --no-git-tag-version | ||||
|               npm publish --access public | ||||
|           npm version $RELEASE_VERSION --no-git-tag-version | ||||
|           npm publish --access public | ||||
|         env: | ||||
|           NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} | ||||
|    | ||||
| 
 | ||||
|   publish-beta: | ||||
|     name: Publish Beta to NPM | ||||
|     needs: [unit-tests, e2e-tests] | ||||
|  | @ -172,7 +172,7 @@ jobs: | |||
| 
 | ||||
|       - name: Publish npm Package | ||||
|         run: | | ||||
|               npm version $RELEASE_VERSION --no-git-tag-version | ||||
|               npm publish --access public --tag beta | ||||
|           npm version $RELEASE_VERSION --no-git-tag-version | ||||
|           npm publish --access public --tag beta | ||||
|         env: | ||||
|           NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} | ||||
|  |  | |||
							
								
								
									
										8
									
								
								.github/workflows/unit-tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/unit-tests.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -1,12 +1,16 @@ | |||
| name: Unit Tests | ||||
| 
 | ||||
| on: [push, pull_request] | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'main' | ||||
|   pull_request: | ||||
| 
 | ||||
| jobs: | ||||
|   build-and-unit: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|       - run: npm ci && npm ci --prefix cli | ||||
|       - run: npm ci | ||||
|       - run: npm run bundle | ||||
|       - run: npm test | ||||
|  |  | |||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -27,8 +27,6 @@ cypress/ | |||
| bundles/ | ||||
| typings/* | ||||
| !typings/styled-patch.d.ts | ||||
| cli/index.js | ||||
| cli/__test__/*/**/*.html | ||||
| 
 | ||||
| /benchmark/revisions | ||||
| 
 | ||||
|  |  | |||
|  | @ -89,7 +89,7 @@ Refer to the Redocly's documentation for more information on these products: | |||
| - [Simple integration with `create-react-app`](https://redocly.com/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/) | ||||
| - [Command-line interface to bundle your docs into a **zero-dependency** HTML file](https://redocly.com/docs/cli/commands/build-docs/) | ||||
| - Neat **interactive** documentation for nested objects <br> | ||||
|    | ||||
| 
 | ||||
|  | @ -182,7 +182,7 @@ to render your OpenAPI definition, refer to the | |||
| [**Redoc quickstart guide**](https://redocly.com/docs/redoc/quickstart/) and [**How to use the HTML element**](https://redocly.com/docs/redoc/deployment/html/). | ||||
| 
 | ||||
| ## Redoc CLI | ||||
| For more information on Redoc's commmand-line interface, refer to | ||||
| For more information on Redoc's command-line interface, refer to | ||||
| [**Using the Redoc CLI**](https://redocly.com/docs/redoc/deployment/cli/). | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +0,0 @@ | |||
| */ | ||||
| !index.js | ||||
| !package.json | ||||
| !README.md | ||||
|  | @ -1,23 +0,0 @@ | |||
| # Package the 'redoc-cli' as a docker image. | ||||
| # | ||||
| # To build: | ||||
| # $ cd <Redoc project directory> | ||||
| # $ docker build -t redoc-cli -f cli/Dockerfile . | ||||
| # | ||||
| # To run: | ||||
| # To display the command line options: | ||||
| # $ docker run --rm -it redoc-cli --help | ||||
| # .. will display the command line help | ||||
| # | ||||
| # To turn `swagger.yml` file in the current directory, to html documentation 'redoc-static.html' | ||||
| # $  docker run --rm -it  -v $PWD:/data redoc-cli bundle swagger.yml | ||||
| 
 | ||||
| FROM node:alpine | ||||
| 
 | ||||
| RUN npm install -g redoc-cli | ||||
| 
 | ||||
| WORKDIR /data | ||||
| EXPOSE 8080 | ||||
| 
 | ||||
| ENTRYPOINT ["redoc-cli"] | ||||
| CMD [] | ||||
|  | @ -1,40 +0,0 @@ | |||
| # redoc-cli | ||||
| 
 | ||||
| **[ReDoc](https://github.com/Redocly/redoc)'s Command Line Interface** | ||||
| 
 | ||||
| ## Installation | ||||
| 
 | ||||
| You can use `redoc-cli` by installing [the package](https://www.npmjs.com/package/redoc-cli) globally, | ||||
| or using [npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b). | ||||
| 
 | ||||
| ## Usage | ||||
| 
 | ||||
| The two following commands are available: | ||||
| 
 | ||||
| - `redoc-cli serve [spec]` - starts the server with `spec` rendered with ReDoc. | ||||
|   Supports a server-side rendering mode (`--ssr`) | ||||
|   and can watch the spec (`--watch`) to automatically reload the page whenever it changes.\ | ||||
|   Deprecated. Use `npx @redocly/cli preview-docs [spec]` | ||||
| - `redoc-cli bundle [spec]` - bundles `spec` and Redoc into a **zero-dependency** HTML file.\ | ||||
|   Deprecated. Use Use "build" command instead. | ||||
| - `redoc-cli build [spec]` - build `spec` and Redoc into a **zero-dependency** HTML file. | ||||
| 
 | ||||
| Some examples: | ||||
| 
 | ||||
| - Bundle with the main color changed to `orange`:<br/> | ||||
|   `$ redoc-cli build [spec] --options.theme.colors.primary.main=orange` | ||||
| - Serve with the `nativeScrollbars` option set to true:<br/> | ||||
|   `$ redoc-cli serve [spec] --options.nativeScrollbars` | ||||
| - Bundle using a custom [Handlebars](https://handlebarsjs.com/) template | ||||
|   (check the [default template](https://github.com/Redocly/redoc/blob/main/cli/template.hbs) for an example):<br/> | ||||
|   `$ redoc-cli build [spec] -t custom.hbs` | ||||
| - Bundle using a custom template and add custom `templateOptions`:<br/> | ||||
|   `$ redoc-cli build [spec] -t custom.hbs --templateOptions.metaDescription "Page meta description"` | ||||
| 
 | ||||
| #### With a Redocly configuration file ([more info](https://redocly.com/docs/cli/configuration/#redocly-configuration-file)): | ||||
| 
 | ||||
| 1. Go to folder with your Redocly configuration file (`.redocly.yaml` or `redocly.yaml`) and your OpenAPI definition file. | ||||
| 2. Build the site using the `build` command (options from the Redocly configuration file will be automatically fetched):   | ||||
|    `redoc build openapi.yaml` | ||||
| 
 | ||||
| For more details, run `redoc-cli --help`. | ||||
|  | @ -1,2 +0,0 @@ | |||
| features.openapi: | ||||
|   disableSearch: true | ||||
|  | @ -1,30 +0,0 @@ | |||
| import { spawnSync } from 'child_process'; | ||||
| import { readFileSync } from 'fs'; | ||||
| 
 | ||||
| describe('build', () => { | ||||
|   it('should use .redocly.yaml', () => { | ||||
|     const r = spawnSync( | ||||
|       'ts-node', | ||||
|       ['../../../index.ts', 'build', ' ../../../../demo/openapi.yaml', '--output=redoc-test.html'], | ||||
|       { | ||||
|         cwd: __dirname, | ||||
|         shell: true, | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     const out = r.stdout.toString('utf-8'); | ||||
|     const err = r.stderr.toString('utf-8'); | ||||
|     const result = `${out}\n${err}`; | ||||
| 
 | ||||
|     try { | ||||
|       const redocStaticFile = readFileSync(`${__dirname}/redoc-test.html`, 'utf8'); | ||||
|       expect(redocStaticFile).toContain('"options":{"disableSearch":true}'); | ||||
|       expect(redocStaticFile).not.toContain('role="search"'); | ||||
|     } catch (err) { | ||||
|       expect(err.toString()).toContain('{"options":{"disableSearch":"true"}'); | ||||
|     } | ||||
| 
 | ||||
|     expect(result).toContain('Found .redocly.yaml and using features.openapi options'); | ||||
|     expect(result).toContain('bundled successfully'); | ||||
|   }); | ||||
| }); | ||||
|  | @ -1,34 +0,0 @@ | |||
| import { spawnSync } from 'child_process'; | ||||
| import { readFileSync } from 'fs'; | ||||
| 
 | ||||
| describe('build with inline options', () => { | ||||
|   it('should use inline options and ignore .redocly.yaml', () => { | ||||
|     const r = spawnSync( | ||||
|       'ts-node', | ||||
|       [ | ||||
|         '../../../index.ts', | ||||
|         'build', | ||||
|         ' ../../../../demo/openapi.yaml', | ||||
|         '--options.disableSearch="false" ', | ||||
|       ], | ||||
|       { | ||||
|         cwd: __dirname, | ||||
|         shell: true, | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     const out = r.stdout.toString('utf-8'); | ||||
|     const err = r.stderr.toString('utf-8'); | ||||
|     const result = `${out}\n${err}`; | ||||
|     expect(result).not.toContain('Found .redocly.yaml and using features.openapi options'); | ||||
|     expect(result).toContain('bundled successfully'); | ||||
| 
 | ||||
|     try { | ||||
|       const redocStaticFile = readFileSync(`${__dirname}/redoc-static.html`, 'utf8'); | ||||
|       expect(redocStaticFile).toContain('"options":{"disableSearch":"false"}'); | ||||
|       expect(redocStaticFile).toContain('role="search"'); | ||||
|     } catch (err) { | ||||
|       expect(err.toString()).toContain('"options":{"disableSearch":"false"}'); | ||||
|     } | ||||
|   }); | ||||
| }); | ||||
|  | @ -1,24 +0,0 @@ | |||
| import { spawnSync } from 'child_process'; | ||||
| 
 | ||||
| describe('build with url', () => { | ||||
|   it('should not fail on resolving url', () => { | ||||
|     const r = spawnSync( | ||||
|       'ts-node', | ||||
|       [ | ||||
|         '../../../index.ts', | ||||
|         'build', | ||||
|         'http://petstore.swagger.io/v2/swagger.json', | ||||
|         '--output=url-test.html', | ||||
|       ], | ||||
|       { | ||||
|         cwd: __dirname, | ||||
|         shell: true, | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     const out = r.stdout.toString('utf-8'); | ||||
|     const err = r.stderr.toString('utf-8'); | ||||
|     const result = `${out}\n${err}`; | ||||
|     expect(result).toContain('bundled successfully'); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										486
									
								
								cli/index.ts
									
									
									
									
									
								
							
							
						
						
									
										486
									
								
								cli/index.ts
									
									
									
									
									
								
							|  | @ -1,486 +0,0 @@ | |||
| #!/usr/bin/env node | ||||
| /* tslint:disable:no-implicit-dependencies */ | ||||
| import * as React from 'react'; | ||||
| import * as updateNotifier from 'update-notifier'; | ||||
| import { renderToString } from 'react-dom/server'; | ||||
| import { ServerStyleSheet } from 'styled-components'; | ||||
| 
 | ||||
| import { compile } from 'handlebars'; | ||||
| import { createServer, IncomingMessage, ServerResponse } from 'http'; | ||||
| import { dirname, join, resolve, extname as getExtName } from 'path'; | ||||
| 
 | ||||
| import * as zlib from 'zlib'; | ||||
| 
 | ||||
| // @ts-ignore
 | ||||
| import { createStore, loadAndBundleSpec, Redoc } from 'redoc'; | ||||
| 
 | ||||
| import { watch } from 'chokidar'; | ||||
| import { | ||||
|   createReadStream, | ||||
|   existsSync, | ||||
|   lstatSync, | ||||
|   readFileSync, | ||||
|   ReadStream, | ||||
|   writeFileSync, | ||||
| } from 'fs'; | ||||
| import * as mkdirp from 'mkdirp'; | ||||
| 
 | ||||
| import * as YargsParser from 'yargs'; | ||||
| // eslint-disable-next-line import/no-extraneous-dependencies
 | ||||
| import { findConfig } from '@redocly/openapi-core'; | ||||
| // eslint-disable-next-line import/no-extraneous-dependencies
 | ||||
| import { parseYaml } from '@redocly/openapi-core'; | ||||
| // eslint-disable-next-line import/no-extraneous-dependencies
 | ||||
| import { Config } from '@redocly/openapi-core'; | ||||
| 
 | ||||
| interface Options { | ||||
|   ssr?: boolean; | ||||
|   watch?: boolean; | ||||
|   cdn?: boolean; | ||||
|   output?: string; | ||||
|   title?: string; | ||||
|   disableGoogleFont?: boolean; | ||||
|   port?: number; | ||||
|   templateFileName?: string; | ||||
|   templateOptions?: any; | ||||
|   redocOptions?: any; | ||||
| } | ||||
| 
 | ||||
| export const mimeTypes = { | ||||
|   '.html': 'text/html', | ||||
|   '.js': 'text/javascript', | ||||
|   '.css': 'text/css', | ||||
|   '.json': 'application/json', | ||||
|   '.png': 'image/png', | ||||
|   '.jpg': 'image/jpg', | ||||
|   '.gif': 'image/gif', | ||||
|   '.svg': 'image/svg+xml', | ||||
|   '.wav': 'audio/wav', | ||||
|   '.mp4': 'video/mp4', | ||||
|   '.woff': 'application/font-woff', | ||||
|   '.ttf': 'application/font-ttf', | ||||
|   '.eot': 'application/vnd.ms-fontobject', | ||||
|   '.otf': 'application/font-otf', | ||||
|   '.wasm': 'application/wasm', | ||||
| }; | ||||
| 
 | ||||
| const BUNDLES_DIR = dirname(require.resolve('redoc')); | ||||
| 
 | ||||
| const builderForBuildCommand = yargs => { | ||||
|   yargs.positional('spec', { | ||||
|     describe: 'path or URL to your spec', | ||||
|   }); | ||||
| 
 | ||||
|   yargs.option('o', { | ||||
|     describe: 'Output file', | ||||
|     alias: 'output', | ||||
|     type: 'string', | ||||
|     default: 'redoc-static.html', | ||||
|   }); | ||||
| 
 | ||||
|   yargs.options('title', { | ||||
|     describe: 'Page Title', | ||||
|     type: 'string', | ||||
|   }); | ||||
| 
 | ||||
|   yargs.options('disableGoogleFont', { | ||||
|     describe: 'Disable Google Font', | ||||
|     type: 'boolean', | ||||
|     default: false, | ||||
|   }); | ||||
| 
 | ||||
|   yargs.option('cdn', { | ||||
|     describe: 'Do not include ReDoc source code into html page, use link to CDN instead', | ||||
|     type: 'boolean', | ||||
|     default: false, | ||||
|   }); | ||||
| 
 | ||||
|   yargs.demandOption('spec'); | ||||
|   return yargs; | ||||
| }; | ||||
| 
 | ||||
| const handlerForBuildCommand = async (argv: any) => { | ||||
|   const config = { | ||||
|     ssr: true, | ||||
|     output: argv.o as string, | ||||
|     cdn: argv.cdn as boolean, | ||||
|     title: argv.title as string, | ||||
|     disableGoogleFont: argv.disableGoogleFont as boolean, | ||||
|     templateFileName: argv.template as string, | ||||
|     templateOptions: argv.templateOptions || {}, | ||||
|     redocOptions: getObjectOrJSON(argv.options), | ||||
|   }; | ||||
| 
 | ||||
|   try { | ||||
|     notifyUpdateCliVersion(); | ||||
|     await bundle(argv.spec, config); | ||||
|   } catch (e) { | ||||
|     handleError(e); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| YargsParser.command( | ||||
|   'serve <spec>', | ||||
|   'start the server', | ||||
|   yargs => { | ||||
|     yargs.positional('spec', { | ||||
|       describe: 'path or URL to your spec', | ||||
|     }); | ||||
| 
 | ||||
|     yargs.options('title', { | ||||
|       describe: 'Page Title', | ||||
|       type: 'string', | ||||
|     }); | ||||
| 
 | ||||
|     yargs.option('s', { | ||||
|       alias: 'ssr', | ||||
|       describe: 'Enable server-side rendering', | ||||
|       type: 'boolean', | ||||
|     }); | ||||
| 
 | ||||
|     yargs.option('h', { | ||||
|       alias: 'host', | ||||
|       type: 'string', | ||||
|       default: '127.0.0.1', | ||||
|     }); | ||||
| 
 | ||||
|     yargs.option('p', { | ||||
|       alias: 'port', | ||||
|       type: 'number', | ||||
|       default: 8080, | ||||
|     }); | ||||
| 
 | ||||
|     yargs.option('w', { | ||||
|       alias: 'watch', | ||||
|       type: 'boolean', | ||||
|     }); | ||||
| 
 | ||||
|     yargs.options('disable-google-font', { | ||||
|       describe: 'Disable Google Font', | ||||
|       type: 'boolean', | ||||
|       default: false, | ||||
|     }); | ||||
| 
 | ||||
|     yargs.demandOption('spec'); | ||||
|     return yargs; | ||||
|   }, | ||||
|   async argv => { | ||||
|     const config: Options = { | ||||
|       ssr: argv.ssr as boolean, | ||||
|       title: argv.title as string, | ||||
|       watch: argv.watch as boolean, | ||||
|       disableGoogleFont: argv.disableGoogleFont as boolean, | ||||
|       templateFileName: argv.template as string, | ||||
|       templateOptions: argv.templateOptions || {}, | ||||
|       redocOptions: getObjectOrJSON(argv.options), | ||||
|     }; | ||||
| 
 | ||||
|     try { | ||||
|       notifyUpdateCliVersion(); | ||||
|       await serve(argv.host as string, argv.port as number, argv.spec as string, config); | ||||
|     } catch (e) { | ||||
|       handleError(e); | ||||
|     } | ||||
|   }, | ||||
|   [ | ||||
|     res => { | ||||
|       console.log( | ||||
|         `\n⚠️ This command is deprecated. Use "npx @redocly/cli preview-docs petstore.yaml"\n`, | ||||
|       ); | ||||
|       return res; | ||||
|     }, | ||||
|   ], | ||||
| ) | ||||
|   .command( | ||||
|     'build <spec>', | ||||
|     'build definition into zero-dependency HTML-file', | ||||
|     builderForBuildCommand, | ||||
|     handlerForBuildCommand, | ||||
|   ) | ||||
|   .command( | ||||
|     'bundle <spec>', | ||||
|     'bundle spec into zero-dependency HTML-file [deprecated]', | ||||
|     builderForBuildCommand, | ||||
|     handlerForBuildCommand, | ||||
|     [ | ||||
|       res => { | ||||
|         console.log(`\n⚠️ This command is deprecated. Use "build" command instead.\n`); | ||||
|         return res; | ||||
|       }, | ||||
|     ], | ||||
|   ) | ||||
|   .demandCommand() | ||||
|   .options('t', { | ||||
|     alias: 'template', | ||||
|     describe: 'Path to handlebars page template, see https://git.io/vh8fP for the example ', | ||||
|     type: 'string', | ||||
|   }) | ||||
|   .options('templateOptions', { | ||||
|     describe: | ||||
|       'Additional options that you want pass to template. Use dot notation, e.g. templateOptions.metaDescription', | ||||
|   }) | ||||
|   .options('options', { | ||||
|     describe: 'ReDoc options, use dot notation, e.g. options.nativeScrollbars', | ||||
|   }).argv; | ||||
| 
 | ||||
| async function serve(host: string, port: number, pathToSpec: string, options: Options = {}) { | ||||
|   let spec = await loadAndBundleSpec(isURL(pathToSpec) ? pathToSpec : resolve(pathToSpec)); | ||||
|   let pageHTML = await getPageHTML(spec, pathToSpec, options); | ||||
|   const server = createServer((request, response) => { | ||||
|     console.time('GET ' + request.url); | ||||
|     if (request.url === '/redoc.standalone.js') { | ||||
|       respondWithGzip( | ||||
|         createReadStream(join(BUNDLES_DIR, 'redoc.standalone.js'), 'utf8'), | ||||
|         request, | ||||
|         response, | ||||
|         { | ||||
|           'Content-Type': 'application/javascript', | ||||
|         }, | ||||
|       ); | ||||
|     } else if (request.url === '/') { | ||||
|       respondWithGzip(pageHTML, request, response, { | ||||
|         'Content-Type': 'text/html', | ||||
|       }); | ||||
|     } else if (request.url === '/spec.json') { | ||||
|       const specStr = JSON.stringify(spec, null, 2); | ||||
|       respondWithGzip(specStr, request, response, { | ||||
|         'Content-Type': 'application/json', | ||||
|       }); | ||||
|     } else { | ||||
|       try { | ||||
|         const filePath = join(dirname(pathToSpec), request.url || ''); | ||||
|         const extname = String(getExtName(filePath)).toLowerCase() as keyof typeof mimeTypes; | ||||
| 
 | ||||
|         const contentType = mimeTypes[extname] || 'application/octet-stream'; | ||||
|         respondWithGzip(createReadStream(filePath), request, response, { | ||||
|           'Content-Type': contentType, | ||||
|         }); | ||||
|       } catch (e) { | ||||
|         response.writeHead(404); | ||||
|         response.write('Not found'); | ||||
|         response.end(); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     console.timeEnd('GET ' + request.url); | ||||
|   }); | ||||
| 
 | ||||
|   console.log(); | ||||
| 
 | ||||
|   server.listen(port, host, () => console.log(`Server started: http://${host}:${port}`)); | ||||
| 
 | ||||
|   if (options.watch && existsSync(pathToSpec)) { | ||||
|     const pathToSpecDirectory = resolve(dirname(pathToSpec)); | ||||
|     const watchOptions = { | ||||
|       ignored: [/(^|[\/\\])\../, /___jb_[a-z]+___$/], | ||||
|       ignoreInitial: true, | ||||
|     }; | ||||
| 
 | ||||
|     const watcher = watch(pathToSpecDirectory, watchOptions); | ||||
|     const log = console.log.bind(console); | ||||
| 
 | ||||
|     const handlePath = async _path => { | ||||
|       try { | ||||
|         spec = await loadAndBundleSpec(resolve(pathToSpec)); | ||||
|         pageHTML = await getPageHTML(spec, pathToSpec, options); | ||||
|         log('Updated successfully'); | ||||
|       } catch (e) { | ||||
|         console.error('Error while updating: ', e.message); | ||||
|       } | ||||
|     }; | ||||
| 
 | ||||
|     watcher | ||||
|       .on('change', async path => { | ||||
|         log(`${path} changed, updating docs`); | ||||
|         handlePath(path); | ||||
|       }) | ||||
|       .on('add', async path => { | ||||
|         log(`File ${path} added, updating docs`); | ||||
|         handlePath(path); | ||||
|       }) | ||||
|       .on('addDir', path => { | ||||
|         log(`↗  Directory ${path} added. Files in here will trigger reload.`); | ||||
|       }) | ||||
|       .on('error', error => console.error(`Watcher error: ${error}`)) | ||||
|       .on('ready', () => log(`👀  Watching ${pathToSpecDirectory} for changes...`)); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| async function bundle(pathToSpec, options: Options = {}) { | ||||
|   const start = Date.now(); | ||||
|   const spec = await loadAndBundleSpec(isURL(pathToSpec) ? pathToSpec : resolve(pathToSpec)); | ||||
|   const pageHTML = await getPageHTML(spec, pathToSpec, { ...options, ssr: true }); | ||||
| 
 | ||||
|   mkdirp.sync(dirname(options.output!)); | ||||
|   writeFileSync(options.output!, pageHTML); | ||||
|   const sizeInKiB = Math.ceil(Buffer.byteLength(pageHTML) / 1024); | ||||
|   const time = Date.now() - start; | ||||
|   console.log( | ||||
|     `\n🎉 bundled successfully in: ${options.output!} (${sizeInKiB} KiB) [⏱ ${time / 1000}s]`, | ||||
|   ); | ||||
| } | ||||
| 
 | ||||
| async function getPageHTML( | ||||
|   spec: any, | ||||
|   pathToSpec: string, | ||||
|   { | ||||
|     ssr, | ||||
|     cdn, | ||||
|     title, | ||||
|     disableGoogleFont, | ||||
|     templateFileName, | ||||
|     templateOptions, | ||||
|     redocOptions = {}, | ||||
|   }: Options, | ||||
| ) { | ||||
|   let html; | ||||
|   let css; | ||||
|   let state; | ||||
|   let redocStandaloneSrc; | ||||
|   if (ssr) { | ||||
|     console.log('Prerendering docs'); | ||||
| 
 | ||||
|     const specUrl = redocOptions.specUrl || (isURL(pathToSpec) ? pathToSpec : undefined); | ||||
|     const store = await createStore(spec, specUrl, redocOptions); | ||||
|     const sheet = new ServerStyleSheet(); | ||||
|     // @ts-ignore
 | ||||
|     html = renderToString(sheet.collectStyles(React.createElement(Redoc, { store }))); | ||||
|     css = sheet.getStyleTags(); | ||||
|     state = await store.toJS(); | ||||
| 
 | ||||
|     if (!cdn) { | ||||
|       redocStandaloneSrc = readFileSync(join(BUNDLES_DIR, 'redoc.standalone.js')); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   templateFileName = templateFileName ? templateFileName : join(__dirname, './template.hbs'); | ||||
|   const template = compile(readFileSync(templateFileName).toString()); | ||||
|   return template({ | ||||
|     redocHTML: ` | ||||
|     <div id="redoc">${(ssr && html) || ''}</div> | ||||
|     <script> | ||||
|     ${(ssr && `const __redoc_state = ${sanitizeJSONString(JSON.stringify(state))};`) || ''} | ||||
| 
 | ||||
|     var container = document.getElementById('redoc'); | ||||
|     Redoc.${ | ||||
|       ssr | ||||
|         ? 'hydrate(__redoc_state, container)' | ||||
|         : `init("spec.json", ${JSON.stringify(redocOptions)}, container)` | ||||
|     }; | ||||
| 
 | ||||
|     </script>`,
 | ||||
|     redocHead: ssr | ||||
|       ? (cdn | ||||
|           ? '<script src="https://unpkg.com/redoc@latest/bundles/redoc.standalone.js"></script>' | ||||
|           : `<script>${redocStandaloneSrc}</script>`) + css | ||||
|       : '<script src="redoc.standalone.js"></script>', | ||||
|     title: title || spec.info.title || 'ReDoc documentation', | ||||
|     disableGoogleFont, | ||||
|     templateOptions, | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| // credits: https://stackoverflow.com/a/9238214/1749888
 | ||||
| function respondWithGzip( | ||||
|   contents: string | ReadStream, | ||||
|   request: IncomingMessage, | ||||
|   response: ServerResponse, | ||||
|   headers = {}, | ||||
| ) { | ||||
|   let compressedStream; | ||||
|   const acceptEncoding = (request.headers['accept-encoding'] as string) || ''; | ||||
|   if (acceptEncoding.match(/\bdeflate\b/)) { | ||||
|     response.writeHead(200, { ...headers, 'content-encoding': 'deflate' }); | ||||
|     compressedStream = zlib.createDeflate(); | ||||
|   } else if (acceptEncoding.match(/\bgzip\b/)) { | ||||
|     response.writeHead(200, { ...headers, 'content-encoding': 'gzip' }); | ||||
|     compressedStream = zlib.createGzip(); | ||||
|   } else { | ||||
|     response.writeHead(200, headers); | ||||
|     if (typeof contents === 'string') { | ||||
|       response.write(contents); | ||||
|       response.end(); | ||||
|     } else { | ||||
|       contents.pipe(response); | ||||
|     } | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   if (typeof contents === 'string') { | ||||
|     compressedStream.write(contents); | ||||
|     compressedStream.pipe(response); | ||||
|     compressedStream.end(); | ||||
|     return; | ||||
|   } else { | ||||
|     contents.pipe(compressedStream).pipe(response); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function isURL(str: string): boolean { | ||||
|   return /^(https?:)\/\//m.test(str); | ||||
| } | ||||
| 
 | ||||
| function sanitizeJSONString(str: string) { | ||||
|   return escapeClosingScriptTag(escapeUnicode(str)); | ||||
| } | ||||
| 
 | ||||
| // see http://www.thespanner.co.uk/2011/07/25/the-json-specification-is-now-wrong/
 | ||||
| function escapeClosingScriptTag(str) { | ||||
|   return str.replace(/<\/script>/g, '<\\/script>'); | ||||
| } | ||||
| 
 | ||||
| // see http://www.thespanner.co.uk/2011/07/25/the-json-specification-is-now-wrong/
 | ||||
| function escapeUnicode(str) { | ||||
|   return str.replace(/\u2028|\u2029/g, m => '\\u202' + (m === '\u2028' ? '8' : '9')); | ||||
| } | ||||
| 
 | ||||
| function handleError(error: Error) { | ||||
|   console.error(error.stack); | ||||
|   process.exit(1); | ||||
| } | ||||
| 
 | ||||
| function getObjectOrJSON(options) { | ||||
|   switch (typeof options) { | ||||
|     case 'object': | ||||
|       return options; | ||||
|     case 'string': | ||||
|       try { | ||||
|         if (existsSync(options) && lstatSync(options).isFile()) { | ||||
|           return JSON.parse(readFileSync(options, 'utf-8')); | ||||
|         } else { | ||||
|           return JSON.parse(options); | ||||
|         } | ||||
|       } catch (e) { | ||||
|         console.log( | ||||
|           `Encountered error:\n\n${options}\n\nis neither a file with a valid JSON object neither a stringified JSON object.`, | ||||
|         ); | ||||
|         handleError(e); | ||||
|       } | ||||
|     default: | ||||
|       const configFile = findConfig(); | ||||
|       if (configFile) { | ||||
|         console.log(`Found ${configFile} and using features.openapi options`); | ||||
|         try { | ||||
|           const config = parseYaml(readFileSync(configFile, 'utf-8')) as Config; | ||||
| 
 | ||||
|           return config['features.openapi']; | ||||
|         } catch (e) { | ||||
|           console.warn(`Found ${configFile} but failed to parse: ${e.message}`); | ||||
|         } | ||||
|       } | ||||
|       return {}; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function notifyUpdateCliVersion() { | ||||
|   const pkg = require('./package.json'); | ||||
|   const notifier = updateNotifier({ | ||||
|     pkg, | ||||
|     updateCheckInterval: 0, | ||||
|     shouldNotifyInNpmScript: true, | ||||
|   }); | ||||
|   notifier.notify({ | ||||
|     message: | ||||
|       'Run `{updateCommand}` to update.\nChangelog: https://github.com/Redocly/redoc/releases/tag/{latestVersion}', | ||||
|   }); | ||||
| } | ||||
							
								
								
									
										6912
									
								
								cli/npm-shrinkwrap.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6912
									
								
								cli/npm-shrinkwrap.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,33 +0,0 @@ | |||
| { | ||||
|   "name": "redoc-cli", | ||||
|   "version": "0.13.20", | ||||
|   "description": "ReDoc's Command Line Interface", | ||||
|   "main": "index.js", | ||||
|   "bin": "index.js", | ||||
|   "repository": "https://github.com/Redocly/redoc", | ||||
|   "author": "Roman Hotsiy <gotsijroman@gmail.com>", | ||||
|   "license": "MIT", | ||||
|   "engines": { | ||||
|     "node": ">=12.0.0" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "chokidar": "^3.5.1", | ||||
|     "handlebars": "^4.7.7", | ||||
|     "isarray": "^2.0.5", | ||||
|     "mkdirp": "^1.0.4", | ||||
|     "mobx": "^6.3.2", | ||||
|     "node-libs-browser": "^2.2.1", | ||||
|     "react": "^17.0.1", | ||||
|     "react-dom": "^17.0.1", | ||||
|     "redoc": "2.0.0-rc.77", | ||||
|     "styled-components": "^5.3.0", | ||||
|     "update-notifier": "^5.0.1", | ||||
|     "yargs": "^17.3.1" | ||||
|   }, | ||||
|   "publishConfig": { | ||||
|     "access": "public" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@types/mkdirp": "^1.0.1" | ||||
|   } | ||||
| } | ||||
|  | @ -1,23 +0,0 @@ | |||
| <!DOCTYPE html> | ||||
| <html> | ||||
| 
 | ||||
| <head> | ||||
|   <meta charset="utf8" /> | ||||
|   <title>{{title}}</title> | ||||
|   <!-- needed for adaptive design --> | ||||
|   <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
|   <style> | ||||
|     body { | ||||
|       padding: 0; | ||||
|       margin: 0; | ||||
|     } | ||||
|   </style> | ||||
|   {{{redocHead}}} | ||||
|   {{#unless disableGoogleFont}}<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">{{/unless}} | ||||
| </head> | ||||
| 
 | ||||
| <body> | ||||
|   {{{redocHTML}}} | ||||
| </body> | ||||
| 
 | ||||
| </html> | ||||
|  | @ -86,7 +86,7 @@ class DemoApp extends React.Component< | |||
|     let proxiedUrl = specUrl; | ||||
|     if (specUrl !== DEFAULT_SPEC) { | ||||
|       proxiedUrl = cors | ||||
|         ? '\\\\cors.redoc.ly/' + new URL(specUrl, window.location.href).href | ||||
|         ? 'https://cors.redoc.ly/' + new URL(specUrl, window.location.href).href | ||||
|         : specUrl; | ||||
|     } | ||||
|     return ( | ||||
|  |  | |||
|  | @ -805,11 +805,17 @@ paths: | |||
|       parameters: | ||||
|         - name: username | ||||
|           in: path | ||||
|           description: name that need to be deleted | ||||
|           description: name that need to be updated | ||||
|           required: true | ||||
|           schema: | ||||
|             type: string | ||||
|       responses: | ||||
|         '200': | ||||
|           description: User is updated successfully | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/User' | ||||
|         '400': | ||||
|           description: Invalid user supplied | ||||
|         '404': | ||||
|  | @ -835,6 +841,8 @@ paths: | |||
|           schema: | ||||
|             type: string | ||||
|       responses: | ||||
|         '204': | ||||
|           description: User is deleted | ||||
|         '400': | ||||
|           description: Invalid username supplied | ||||
|         '404': | ||||
|  |  | |||
|  | @ -4,111 +4,33 @@ redirectFrom: | |||
|   - /docs/redoc/quickstart/cli/ | ||||
| --- | ||||
| 
 | ||||
| # How to use the Redoc CLI | ||||
| # How to use the Redocly CLI | ||||
| 
 | ||||
| With Redoc's command-line interface you can bundle your OpenAPI definition and API documentation | ||||
| (made with Redoc) into a zero-dependency HTML file and locally render your | ||||
| OpenAPI definition with Redoc. | ||||
| With Redocly CLI, you can bundle your OpenAPI definition and API documentation | ||||
| (made with Redoc) into a zero-dependency HTML file and render it locally. | ||||
| 
 | ||||
| ## Step 1 - Install Redoc CLI | ||||
| ## Step 1 - Install Redocly CLI | ||||
| 
 | ||||
| You can install the `redoc-cli` package globally using one of the following package managers: | ||||
| First, you need to install the `@redocly/cli` package. | ||||
| 
 | ||||
| - [npm](https://docs.npmjs.com/about-npm) | ||||
| - [yarn](https://classic.yarnpkg.com/en/docs/getting-started) | ||||
| You can install it [globally](/docs/cli/installation.md#install-globally) using npm or Yarn. | ||||
| 
 | ||||
| Or you can install `redoc-cli` using [npx](https://www.freecodecamp.org/news/npm-vs-npx-whats-the-difference/). | ||||
| Or you can install it during [runtime](/docs/cli/installation.md#use-npx-at-runtime) using npx or Docker. | ||||
| 
 | ||||
| ### Install Redoc CLI with yarn | ||||
| ## Step 2 - Build the HTML file | ||||
| 
 | ||||
| To install the `redoc-cli` package globally with yarn: | ||||
| The Redocly CLI `build-docs` command builds Redoc into a zero-dependency HTML file. | ||||
| 
 | ||||
| To build a zero-dependency HTML file using Redocly CLI, enter the following command, | ||||
| replacing `apis/openapi.yaml` with your API definition file's name and path: | ||||
| 
 | ||||
| ```bash | ||||
| yarn global add redoc-cli | ||||
| redocly build-docs apis/openapi.yaml | ||||
| ``` | ||||
| 
 | ||||
| ### Install Redoc with npm | ||||
| See the [build-docs](../../cli/commands/build-docs.md) documentation for more information | ||||
| on the different options and ways you can use the command. | ||||
| 
 | ||||
| To install the `redoc-cli` package globally with npm: | ||||
| 
 | ||||
| ```bash | ||||
| npm i -g redoc-cli | ||||
| ``` | ||||
| 
 | ||||
| ### Install with `npx` | ||||
| 
 | ||||
| To install the `redoc-cli` package locally with `npx`, navigate to your project | ||||
| directory in your terminal, then use the following command: | ||||
| 
 | ||||
| ```bash | ||||
| npx redoc-cli | ||||
| ``` | ||||
| 
 | ||||
| ## Step 2 - Use the CLI | ||||
| 
 | ||||
| ### Redoc CLI commands | ||||
| 
 | ||||
| The CLI includes the following commands: | ||||
| 
 | ||||
| - **`redoc-cli serve [spec]`:** Starts a local server with Redoc. You must include the required parameter, spec, which is | ||||
|   a reference to an OpenAPI definition. Options include: | ||||
|     - `--ssr`: Implements a server-side rendering model. | ||||
|     - `--watch`: Automatically reloads the server while you edit your OpenAPI definition. | ||||
|     - `--options`: Customizes your output using [Redoc functionality options](https://redocly.com/docs/api-reference-docs/configuration/functionality) or [Redoc theming options](https://redocly.com/docs/api-reference-docs/configuration/theming). | ||||
|       To add nested options, use dot notation. | ||||
| - **`redoc-cli build [spec]`:** Builds `spec` and Redoc into a zero-dependency HTML file. Options include: | ||||
|     - `-t` or `--template`: Uses custom [Handlebars](https://handlebarsjs.com/) templates to render your OpenAPI definition. | ||||
|     - `--templateOptions`: Adds template options you want to pass to your | ||||
|       custom Handlebars template. To add options, use dot notation. | ||||
| - **`--help`:** Prints help text for the Redoc CLI commands and options. | ||||
| - **`--version`:** Prints the version of the `redoc-cli` package you have installed. | ||||
| 
 | ||||
| ### Redoc CLI examples | ||||
| 
 | ||||
| #### Bundle | ||||
| 
 | ||||
| Bundle with the main color changed to `orange`: | ||||
| 
 | ||||
| ```bash | ||||
| redoc-cli build openapi.yaml --options.theme.colors.primary.main=orange | ||||
| ``` | ||||
| 
 | ||||
| Bundle using a custom Handlebars template and add custom `templateOptions`: | ||||
| 
 | ||||
| ```bash | ||||
| redoc-cli build http://petstore.swagger.io/v2/swagger.json -t custom.hbs --templateOptions.metaDescription "Page meta description" | ||||
| ``` | ||||
| 
 | ||||
| Sample Handlebars template: | ||||
| 
 | ||||
| ```handlebars | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
|     <head> | ||||
|         <meta charset="utf8" /> | ||||
|         <title>{{title}}</title> | ||||
|         <!-- needed for adaptive design --> | ||||
|         <meta description="{{{templateOptions.metaDescription}}}"> | ||||
|         <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
|         <style> | ||||
|             body { | ||||
|             padding: 0; | ||||
|             margin: 0; | ||||
|             } | ||||
|         </style> | ||||
|         {{{redocHead}}} | ||||
|         {{#unless disableGoogleFont}}<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">{{/unless}} | ||||
|     </head> | ||||
|     <body> | ||||
|       {{{redocHTML}}} | ||||
|     </body> | ||||
| </html> | ||||
| ``` | ||||
| 
 | ||||
| #### Serve | ||||
| 
 | ||||
| Serve with the `nativeScrollbars` option set to `true`: | ||||
| 
 | ||||
| ```bash | ||||
| redoc-cli serve  openapi/dist.yaml --options.nativeScrollbars | ||||
| ``` | ||||
| Also, check out [Redocly CLI commands](../../cli/commands/index.md), for more | ||||
| information on the different things you can do with Redocly CLI including | ||||
| linting, splitting, and bundling your API definition file. | ||||
|  |  | |||
|  | @ -21,8 +21,8 @@ The following options are supported: | |||
|   Using the React component is an option for users with a React-based application. | ||||
| - **[Docker image](./docker.md):** | ||||
|   Using the Docker image works in a container-based deployment. | ||||
| - **[CLI](./cli.md):** | ||||
|   Using the CLI is an option for users who prefer to use a command-line interface. | ||||
| - **[Redocly CLI](./cli.md):** | ||||
|   Using the Redocly CLI is an option for users who prefer to use a command-line interface. | ||||
| 
 | ||||
| ## Before you start | ||||
| 
 | ||||
|  | @ -55,7 +55,7 @@ If you have [Redocly CLI](https://redocly.com/docs/cli/#installation-and-usage) | |||
| project directory and run the following command: | ||||
| 
 | ||||
| ```bash | ||||
| openapi preview-docs openapi.yaml | ||||
| redocly preview-docs openapi.yaml | ||||
| ``` | ||||
| 
 | ||||
| Replace `openapi.yaml` in the example command with the file path to your OpenAPI definition. | ||||
|  | @ -66,7 +66,7 @@ To exit the preview, use `control+C`. | |||
| You can alter the port if you are using 8080 already, for example: | ||||
| 
 | ||||
| ```bash | ||||
| openapi preview-docs -p 8888 openapi.yaml | ||||
| redocly preview-docs -p 8888 openapi.yaml | ||||
| ``` | ||||
| 
 | ||||
| Replace `openapi.yaml` in the example command with the file path to your OpenAPI definition. | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| describe('Search', () => { | ||||
|   const getSearchInput = () => cy.get('[role="search"] input'); | ||||
|   const getSearchResults = () => cy.get('[data-role="search:results"]'); | ||||
|   const getResult = i => cy.get('[role=search] [role=menuitem]').eq(i); | ||||
|   const getResult = i => cy.get('[role=search] label').eq(i); | ||||
| 
 | ||||
|   beforeEach(() => { | ||||
|     cy.visit('e2e/standalone.html'); | ||||
|  | @ -45,7 +45,7 @@ describe('Search', () => { | |||
| 
 | ||||
|     getSearchInput().type('{enter}', { force: true }); | ||||
| 
 | ||||
|     cy.contains('[role=menu] [role=menuitem]', 'Introduction').should('have.class', 'active'); | ||||
|     cy.contains('[role=menu] label', 'Introduction').should('have.class', 'active'); | ||||
|   }); | ||||
| 
 | ||||
|   it('should mark search results', () => { | ||||
|  |  | |||
							
								
								
									
										753
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										753
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -44,15 +44,14 @@ | |||
|     "bundle:standalone": "webpack --env production --env standalone --mode=production", | ||||
|     "bundle:lib": "webpack --mode=production && npm run declarations", | ||||
|     "bundle:browser": "webpack --env production --env browser --mode=production", | ||||
|     "bundle": "npm run bundle:clean && npm run bundle:lib && npm run bundle:browser && npm run bundle:standalone && npm run compile:cli", | ||||
|     "bundle": "npm run bundle:clean && npm run bundle:lib && npm run bundle:browser && npm run bundle:standalone", | ||||
|     "declarations": "tsc --emitDeclarationOnly -p tsconfig.lib.json && cp -R src/types typings/", | ||||
|     "stats": "webpack --env production --env standalone --json --profile --mode=production > stats.json", | ||||
|     "prettier": "prettier --write \"cli/index.ts\" \"src/**/*.{ts,tsx}\"", | ||||
|     "prettier": "prettier --write \"src/**/*.{ts,tsx}\"", | ||||
|     "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1", | ||||
|     "lint": "eslint --fix 'src/**/*.{js,ts,tsx}' --cache", | ||||
|     "benchmark": "node ./benchmark/benchmark.js", | ||||
|     "start:demo": "webpack serve --hot --config demo/webpack.config.ts --mode=development", | ||||
|     "compile:cli": "tsc custom.d.ts cli/index.ts --target es6 --module commonjs --types yargs", | ||||
|     "build:demo": "webpack --mode=production --config demo/webpack.config.ts", | ||||
|     "publish-cdn": "scripts/publish-cdn.sh", | ||||
|     "deploy:demo": "aws s3 sync demo/dist s3://production-redoc-demo --acl=public-read", | ||||
|  | @ -151,7 +150,7 @@ | |||
|     "mark.js": "^8.11.1", | ||||
|     "marked": "^4.0.15", | ||||
|     "mobx-react": "^7.2.0", | ||||
|     "openapi-sampler": "^1.3.0", | ||||
|     "openapi-sampler": "^1.3.1", | ||||
|     "path-browserify": "^1.0.1", | ||||
|     "perfect-scrollbar": "^1.5.5", | ||||
|     "polished": "^4.1.3", | ||||
|  |  | |||
|  | @ -73,7 +73,7 @@ export class Field extends React.Component<FieldProps> { | |||
|         <button | ||||
|           onClick={this.toggle} | ||||
|           onKeyPress={this.handleKeyPress} | ||||
|           aria-label="expand properties" | ||||
|           aria-label={`expand ${name}`} | ||||
|         > | ||||
|           <span className="property-name">{name}</span> | ||||
|           <ShelfIcon direction={expanded ? 'down' : 'right'} /> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| import * as React from 'react'; | ||||
| import { DropdownOrLabel } from '../DropdownOrLabel/DropdownOrLabel'; | ||||
| import { DropdownOrLabel, DropdownOrLabelProps } from '../DropdownOrLabel/DropdownOrLabel'; | ||||
| import { ParametersGroup } from './ParametersGroup'; | ||||
| 
 | ||||
| import { UnderlinedHeader } from '../../common-elements'; | ||||
|  | @ -11,6 +11,8 @@ import { Schema } from '../Schema'; | |||
| 
 | ||||
| import { Markdown } from '../Markdown/Markdown'; | ||||
| import { ConstraintsView } from '../Fields/FieldContstraints'; | ||||
| import { RequiredLabel } from '../../common-elements/fields'; | ||||
| import styled from '../../styled-components'; | ||||
| 
 | ||||
| function safePush(obj, prop, item) { | ||||
|   if (!obj[prop]) { | ||||
|  | @ -49,21 +51,37 @@ export class Parameters extends React.PureComponent<ParametersProps> { | |||
| 
 | ||||
|     const bodyDescription = body && body.description; | ||||
| 
 | ||||
|     const bodyRequired = body && body.required; | ||||
| 
 | ||||
|     return ( | ||||
|       <> | ||||
|         {paramsPlaces.map(place => ( | ||||
|           <ParametersGroup key={place} place={place} parameters={paramsMap[place]} /> | ||||
|         ))} | ||||
|         {bodyContent && <BodyContent content={bodyContent} description={bodyDescription} />} | ||||
|         {bodyContent && ( | ||||
|           <BodyContent | ||||
|             content={bodyContent} | ||||
|             description={bodyDescription} | ||||
|             bodyRequired={bodyRequired} | ||||
|           /> | ||||
|         )} | ||||
|       </> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function DropdownWithinHeader(props) { | ||||
| function DropdownWithinHeader({ | ||||
|   bodyRequired, | ||||
|   ...props | ||||
| }: DropdownOrLabelProps & { bodyRequired?: boolean }) { | ||||
|   const isRequired = typeof bodyRequired === 'boolean' && !!bodyRequired; | ||||
|   const isOptional = typeof bodyRequired === 'boolean' && !bodyRequired; | ||||
| 
 | ||||
|   return ( | ||||
|     <UnderlinedHeader key="header"> | ||||
|       Request Body schema: <DropdownOrLabel {...props} /> | ||||
|       {isRequired && <RequiredBody>required</RequiredBody>} | ||||
|       {isOptional && <OptionalBody>optional</OptionalBody>} | ||||
|     </UnderlinedHeader> | ||||
|   ); | ||||
| } | ||||
|  | @ -71,11 +89,15 @@ function DropdownWithinHeader(props) { | |||
| export function BodyContent(props: { | ||||
|   content: MediaContentModel; | ||||
|   description?: string; | ||||
|   bodyRequired?: boolean; | ||||
| }): JSX.Element { | ||||
|   const { content, description } = props; | ||||
|   const { content, description, bodyRequired } = props; | ||||
|   const { isRequestType } = content; | ||||
|   return ( | ||||
|     <MediaTypesSwitch content={content} renderDropdown={DropdownWithinHeader}> | ||||
|     <MediaTypesSwitch | ||||
|       content={content} | ||||
|       renderDropdown={props => <DropdownWithinHeader bodyRequired={bodyRequired} {...props} />} | ||||
|     > | ||||
|       {({ schema }) => { | ||||
|         return ( | ||||
|           <> | ||||
|  | @ -97,3 +119,19 @@ export function BodyContent(props: { | |||
|     </MediaTypesSwitch> | ||||
|   ); | ||||
| } | ||||
| 
 | ||||
| const commonStyles = ` | ||||
|   text-transform: lowercase; | ||||
|   margin-left: 0; | ||||
|   line-height: 1.5em; | ||||
| `;
 | ||||
| 
 | ||||
| const RequiredBody = styled(RequiredLabel)` | ||||
|   ${commonStyles} | ||||
| `;
 | ||||
| 
 | ||||
| const OptionalBody = styled('div')` | ||||
|   ${commonStyles} | ||||
|   color: ${({ theme }) => theme.colors.text.secondary}; | ||||
|   font-size: ${props => props.theme.schema.labelsTextSize}; | ||||
| `;
 | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ export class MenuItem extends React.Component<MenuItemProps> { | |||
|   render() { | ||||
|     const { item, withoutChildren } = this.props; | ||||
|     return ( | ||||
|       <MenuItemLi onClick={this.activate} depth={item.depth} data-item-id={item.id}> | ||||
|       <MenuItemLi onClick={this.activate} depth={item.depth} data-item-id={item.id} role="menuitem"> | ||||
|         {item.type === 'operation' ? ( | ||||
|           <OperationMenuItemContent {...this.props} item={item as OperationModel} /> | ||||
|         ) : ( | ||||
|  |  | |||
|  | @ -125,7 +125,6 @@ export interface MenuItemLabelType { | |||
| } | ||||
| 
 | ||||
| export const MenuItemLabel = styled.label.attrs((props: MenuItemLabelType) => ({ | ||||
|   role: 'menuitem', | ||||
|   className: classnames('-depth' + props.depth, { | ||||
|     active: props.active, | ||||
|   }), | ||||
|  |  | |||
|  | @ -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-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">petstore_auth</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><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-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>OAuth2</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Flow type: </b><code>implicit </code></div><div class=\\"sc-fXgAZx gZCyoW\\"><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-fXgAZx gZCyoW\\"><b> Scopes: </b></div><div class=\\"sc-jXcxbT blWOKY container\\" style=\\"height: 4em;\\"><ul><li><code>write:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>modify pets in your account</p> | ||||
| </div><div class=\\"sc-eEVmNe lmbHgE\\"><div class=\\"sc-jXcxbT gllWlr\\"><b>Security Scheme Type: </b><span>OAuth2</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-jXcxbT gllWlr\\"><b>Flow type: </b><code>implicit </code></div><div class=\\"sc-jXcxbT gllWlr\\"><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-jXcxbT gllWlr\\"><b> Scopes: </b></div><div class=\\"sc-fmdNqN eKoRDV container\\" style=\\"height: 4em;\\"><ul><li><code>write:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>modify pets in your account</p> | ||||
| </span></li><li><code>read:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>read your pets</p> | ||||
| </span></li></ul></div><div class=\\"sc-eEVmNe gbLbHj\\"></div></div></div></div></div></div><div id=\\"section/Authentication/GitLab_PersonalAccessToken\\" data-section-id=\\"section/Authentication/GitLab_PersonalAccessToken\\" class=\\"sc-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">GitLab_PersonalAccessToken</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab Personal Access Token description</p> | ||||
| </div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>API Key</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><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-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">GitLab_OpenIdConnect</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab OpenIdConnect description</p> | ||||
| </div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>OpenID Connect</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><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-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">basicAuth</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"></div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>HTTP</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class=\\"sc-fXgAZx gZCyoW\\"></div></div></div></div></div></div>" | ||||
| </span></li></ul></div><div class=\\"sc-ljsmAU blhEdv\\"></div></div></div></div></div></div><div id=\\"section/Authentication/GitLab_PersonalAccessToken\\" data-section-id=\\"section/Authentication/GitLab_PersonalAccessToken\\" class=\\"sc-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">GitLab_PersonalAccessToken</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab Personal Access Token description</p> | ||||
| </div><div class=\\"sc-eEVmNe lmbHgE\\"><div class=\\"sc-jXcxbT gllWlr\\"><b>Security Scheme Type: </b><span>API Key</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-jXcxbT gllWlr\\"><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-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">GitLab_OpenIdConnect</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab OpenIdConnect description</p> | ||||
| </div><div class=\\"sc-eEVmNe lmbHgE\\"><div class=\\"sc-jXcxbT gllWlr\\"><b>Security Scheme Type: </b><span>OpenID Connect</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-jXcxbT gllWlr\\"><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-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">basicAuth</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"></div><div class=\\"sc-eEVmNe lmbHgE\\"><div class=\\"sc-jXcxbT gllWlr\\"><b>Security Scheme Type: </b><span>HTTP</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-jXcxbT gllWlr\\"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class=\\"sc-jXcxbT gllWlr\\"></div></div></div></div></div></div>" | ||||
| `; | ||||
| 
 | ||||
| exports[`SecurityRequirement should render authDefinition 1`] = `"<div class=\\"sc-bQCEYZ eDdCgW operation-security\\"><div class=\\"sc-xGAEC femyTb\\"><h5 class=\\"sc-iqAclL sc-jHcXXw eONCmm keQLTh\\">Authorizations:</h5><svg class=\\"sc-dIsUp iPqByX\\" 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-dWBRfb kJFNCL\\"><span class=\\"sc-kYPZxB irJeRy\\">(<span class=\\"sc-hzUIXc gcouO\\">API Key: <i>GitLab_PersonalAccessToken</i></span><span class=\\"sc-hzUIXc gcouO\\">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class=\\"sc-hzUIXc gcouO\\">HTTP: <i>basicAuth</i></span>) </span><span class=\\"sc-kYPZxB irJeRy\\"><span class=\\"sc-hzUIXc gcouO\\">OAuth2: <i>petstore_auth</i></span></span></div></div>,"`; | ||||
| exports[`SecurityRequirement should render authDefinition 1`] = `"<div class=\\"sc-EZqKI eriJMk operation-security\\"><div class=\\"sc-jHcXXw kurgNF\\"><h5 class=\\"sc-iqAclL sc-fXgAZx eONCmm xiVXt\\">Authorizations:</h5><svg class=\\"sc-dIsUp iPqByX\\" 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-bQCEYZ cCwYjG\\"><span class=\\"sc-dWBRfb hoKBYz\\">(<span class=\\"sc-xGAEC bCFTJj\\">API Key: <i>GitLab_PersonalAccessToken</i></span><span class=\\"sc-xGAEC bCFTJj\\">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class=\\"sc-xGAEC bCFTJj\\">HTTP: <i>basicAuth</i></span>) </span><span class=\\"sc-dWBRfb hoKBYz\\"><span class=\\"sc-xGAEC bCFTJj\\">OAuth2: <i>petstore_auth</i></span></span></div></div>,"`; | ||||
| 
 | ||||
| exports[`SecurityRequirement should render authDefinition 2`] = ` | ||||
| "<div class=\\"sc-bQCEYZ dSwEDq operation-security\\"><div class=\\"sc-xGAEC femyTb\\"><h5 class=\\"sc-iqAclL sc-jHcXXw eONCmm keQLTh\\">Authorizations:</h5><svg class=\\"sc-dIsUp fVWtGJ\\" 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-dWBRfb ekRdav\\"><span class=\\"sc-kYPZxB fhGdrc\\">(<span class=\\"sc-hzUIXc gcouO\\">API Key: <i>GitLab_PersonalAccessToken</i></span><span class=\\"sc-hzUIXc gcouO\\">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class=\\"sc-hzUIXc gcouO\\">HTTP: <i>basicAuth</i></span>) </span><span class=\\"sc-kYPZxB fhGdrc\\"><span class=\\"sc-hzUIXc gcouO\\">OAuth2: <i>petstore_auth</i> (<code class=\\"sc-eHEENL fwFTyL\\">write:pets</code><code class=\\"sc-eHEENL fwFTyL\\">read:pets</code>) </span></span></div></div><div class=\\"sc-EZqKI aOkZE security-details\\"><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-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>Get access to data while protecting your account credentials. | ||||
| "<div class=\\"sc-EZqKI hSmRqE operation-security\\"><div class=\\"sc-jHcXXw kurgNF\\"><h5 class=\\"sc-iqAclL sc-fXgAZx eONCmm xiVXt\\">Authorizations:</h5><svg class=\\"sc-dIsUp fVWtGJ\\" 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-bQCEYZ gvMhNy\\"><span class=\\"sc-dWBRfb eLEzSd\\">(<span class=\\"sc-xGAEC bCFTJj\\">API Key: <i>GitLab_PersonalAccessToken</i></span><span class=\\"sc-xGAEC bCFTJj\\">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class=\\"sc-xGAEC bCFTJj\\">HTTP: <i>basicAuth</i></span>) </span><span class=\\"sc-dWBRfb eLEzSd\\"><span class=\\"sc-xGAEC bCFTJj\\">OAuth2: <i>petstore_auth</i> (<code class=\\"sc-kYPZxB beMTTe\\">write:pets</code><code class=\\"sc-kYPZxB beMTTe\\">read:pets</code>) </span></span></div></div><div class=\\"sc-eEVmNe lmbHgE security-details\\"><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-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><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-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Flow type: </b><code>implicit </code></div><div class=\\"sc-fXgAZx gZCyoW\\"><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-fXgAZx gZCyoW\\"><b> Scopes: </b></div><div class=\\"sc-jXcxbT blWOKY container\\" style=\\"height: 4em;\\"><ul><li><code>write:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>modify pets in your account</p> | ||||
| </div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-jXcxbT gllWlr\\"><b>Flow type: </b><code>implicit </code></div><div class=\\"sc-jXcxbT gllWlr\\"><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-jXcxbT gllWlr\\"><b> Scopes: </b></div><div class=\\"sc-fmdNqN eKoRDV container\\" style=\\"height: 4em;\\"><ul><li><code>write:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>modify pets in your account</p> | ||||
| </span></li><li><code>read:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>read your pets</p> | ||||
| </span></li></ul></div><div class=\\"sc-eEVmNe gbLbHj\\"></div></div></div><div class=\\"sc-EZqKI aOkZE security-details\\"><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-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab Personal Access Token description</p> | ||||
| </div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Header parameter name: </b><code>PRIVATE-TOKEN</code></div></div></div><div class=\\"sc-EZqKI aOkZE security-details\\"><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-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab OpenIdConnect description</p> | ||||
| </div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><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-EZqKI aOkZE security-details\\"><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-iJCRrE sc-ciSkZP jCdxGr QGruV\\"></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class=\\"sc-fXgAZx gZCyoW\\"></div></div></div>," | ||||
| </span></li></ul></div><div class=\\"sc-ljsmAU blhEdv\\"></div></div></div><div class=\\"sc-eEVmNe lmbHgE security-details\\"><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-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab Personal Access Token description</p> | ||||
| </div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-jXcxbT gllWlr\\"><b>Header parameter name: </b><code>PRIVATE-TOKEN</code></div></div></div><div class=\\"sc-eEVmNe lmbHgE security-details\\"><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-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab OpenIdConnect description</p> | ||||
| </div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-jXcxbT gllWlr\\"><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-eEVmNe lmbHgE security-details\\"><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-iJCRrE sc-ciSkZP jCdxGr QGruV\\"></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-jXcxbT gllWlr\\"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class=\\"sc-jXcxbT gllWlr\\"></div></div></div>," | ||||
| `; | ||||
|  |  | |||
|  | @ -23,6 +23,14 @@ describe('Models', () => { | |||
|       const consoleError = jest.spyOn(global.console, 'error'); | ||||
|       const req = new RequestBodyModel(props); | ||||
|       expect(consoleError).not.toHaveBeenCalled(); | ||||
|       expect(req).toEqual({ description: '', required: undefined }); | ||||
|     }); | ||||
| 
 | ||||
|     test('should work with set required', () => { | ||||
|       const consoleError = jest.spyOn(global.console, 'error'); | ||||
|       props.infoOrRef.required = false; | ||||
|       const req = new RequestBodyModel(props); | ||||
|       expect(consoleError).not.toHaveBeenCalled(); | ||||
|       expect(req).toEqual({ description: '', required: false }); | ||||
|     }); | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,14 +14,14 @@ type RequestBodyProps = { | |||
| 
 | ||||
| export class RequestBodyModel { | ||||
|   description: string; | ||||
|   required: boolean; | ||||
|   required?: boolean; | ||||
|   content?: MediaContentModel; | ||||
| 
 | ||||
|   constructor({ parser, infoOrRef, options, isEvent }: RequestBodyProps) { | ||||
|     const isRequest = !isEvent; | ||||
|     const { resolved: info } = parser.deref(infoOrRef); | ||||
|     this.description = info.description || ''; | ||||
|     this.required = !!info.required; | ||||
|     this.required = info.required; | ||||
| 
 | ||||
|     const mediaContent = getContentWithLegacyExamples(info); | ||||
|     if (mediaContent !== undefined) { | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| import { Omit } from './index'; | ||||
| import type { Omit } from './index'; | ||||
| 
 | ||||
| export interface OpenAPISpec { | ||||
|   openapi: string; | ||||
|  |  | |||
|  | @ -4211,6 +4211,9 @@ culpa qui officia deserunt mollit anim id est laborum. | |||
|           }, | ||||
|         ], | ||||
|         "responses": Object { | ||||
|           "204": Object { | ||||
|             "description": "User is deleted", | ||||
|           }, | ||||
|           "400": Object { | ||||
|             "description": "Invalid username supplied", | ||||
|           }, | ||||
|  | @ -4270,7 +4273,7 @@ culpa qui officia deserunt mollit anim id est laborum. | |||
|         "operationId": "updateUser", | ||||
|         "parameters": Array [ | ||||
|           Object { | ||||
|             "description": "name that need to be deleted", | ||||
|             "description": "name that need to be updated", | ||||
|             "in": "path", | ||||
|             "name": "username", | ||||
|             "required": true, | ||||
|  | @ -4291,6 +4294,16 @@ culpa qui officia deserunt mollit anim id est laborum. | |||
|           "required": true, | ||||
|         }, | ||||
|         "responses": Object { | ||||
|           "200": Object { | ||||
|             "content": Object { | ||||
|               "application/json": Object { | ||||
|                 "schema": Object { | ||||
|                   "$ref": "#/components/schemas/User", | ||||
|                 }, | ||||
|               }, | ||||
|             }, | ||||
|             "description": "User is updated successfully", | ||||
|           }, | ||||
|           "400": Object { | ||||
|             "description": "Invalid user supplied", | ||||
|           }, | ||||
|  |  | |||
|  | @ -20,7 +20,6 @@ | |||
|   "compileOnSave": false, | ||||
|   "exclude": ["node_modules", ".tmp", "lib", "e2e/**"], | ||||
|   "include": [ | ||||
|     "cli/index.ts", | ||||
|     "./custom.d.ts", | ||||
|     "./demo/playground/hmr-playground.tsx", | ||||
|     "./src/**/*.ts?", | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user