feat: initialize release candidate for v3.0.0
Co-authored-by: Roman Hotsiy <gotsijroman@gmail.com> Co-authored-by: Alex Varchuk <olexandr.varchuk@gmail.com> Co-authored-by: Oprysk Vyacheslav <vyacheslav@redocly.com> Co-authored-by: Ivan Kropyvnytskyi <130547411+ivankropyvnytskyi@users.noreply.github.com> Co-authored-by: Yevhen Pylyp <yevhen.pylyp@redocly.com> Co-authored-by: Vladyslav Makarenko <vladyslav.makarenko@redocly.com> Co-authored-by: Yevhenii Medviediev <yevhenii.medviediev@redocly.com> Co-authored-by: Oleksii Horbachevskyi <oleksii.horbachevskyi@redocly.com> Co-authored-by: volodymyr-rutskyi <rutskyi.v@gmail.com> Co-authored-by: Adam Altman <adam@redoc.ly> Co-authored-by: Andrew Tatomyr <andrew.tatomyr@redocly.com> Co-authored-by: Anastasiia Derymarko <anastasiia@redocly.com> Co-authored-by: Roman Marshevskyy <roman.marshevskyy@redoc.ly> Co-authored-by: Lorna Mitchell <lorna.mitchell@redocly.com> Co-authored-by: Taylor Krusen <taylor.krusen@redocly.com>
10
.changeset/config.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://unpkg.com/@changesets/config@2.2.0/schema.json",
|
||||||
|
"changelog": "@changesets/cli/changelog",
|
||||||
|
"commit": false,
|
||||||
|
"fixed": [["redoc"]],
|
||||||
|
"linked": [],
|
||||||
|
"access": "public",
|
||||||
|
"baseBranch": "main",
|
||||||
|
"updateInternalDependencies": "patch"
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
*
|
*
|
||||||
!src/
|
!src/
|
||||||
!config
|
!scripts/
|
||||||
!demo/favicon.png
|
|
||||||
|
|
||||||
!custom.d.ts
|
|
||||||
!typings/styled-patch.d.ts
|
|
||||||
!tsconfig.json
|
|
||||||
!webpack.config.ts
|
|
||||||
|
|
||||||
!package.json
|
!package.json
|
||||||
!package-lock.json
|
!package-lock.json
|
||||||
|
!vite.config.ts
|
||||||
|
!tsconfig.json
|
||||||
|
!config/
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
end_of_line = lf
|
|
||||||
charset = utf-8
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
insert_final_newline = true
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
54
.eslintrc.js
|
|
@ -1,54 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
},
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
extends: ['plugin:react/recommended', 'plugin:@typescript-eslint/recommended'],
|
|
||||||
parserOptions: {
|
|
||||||
project: 'tsconfig.json',
|
|
||||||
sourceType: 'module',
|
|
||||||
createDefaultProgram: true,
|
|
||||||
ecmaFeatures: {
|
|
||||||
jsx: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
react: {
|
|
||||||
version: 'detect',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: ['react', 'react-hooks', '@typescript-eslint', 'import'],
|
|
||||||
rules: {
|
|
||||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
||||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
|
||||||
'@typescript-eslint/no-use-before-define': 'off',
|
|
||||||
'@typescript-eslint/interface-name-prefix': 'off',
|
|
||||||
'@typescript-eslint/no-inferrable-types': 'off',
|
|
||||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
||||||
'@typescript-eslint/ban-ts-ignore': 'off',
|
|
||||||
'@typescript-eslint/ban-types': ['error', { types: { object: false }, extendDefaults: true }],
|
|
||||||
'@typescript-eslint/no-var-requires': 'off',
|
|
||||||
|
|
||||||
'react/prop-types': 'off',
|
|
||||||
'react-hooks/rules-of-hooks': 'error',
|
|
||||||
'react-hooks/exhaustive-deps': 'warn',
|
|
||||||
|
|
||||||
'import/no-extraneous-dependencies': 'error',
|
|
||||||
'import/no-internal-modules': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
allow: [
|
|
||||||
'prismjs/**',
|
|
||||||
'perfect-scrollbar/**',
|
|
||||||
'react-dom/*',
|
|
||||||
'core-js/**',
|
|
||||||
'memoize-one/**',
|
|
||||||
'unfetch/**',
|
|
||||||
'raf/polyfill',
|
|
||||||
'**/fixtures/**', // for tests
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
3
.github/CODEOWNERS
vendored
|
|
@ -1,2 +1 @@
|
||||||
* @Redocly/keyboard-warriors
|
* @Redocly/keyboard-warriors
|
||||||
/docs/ @Redocly/technical-writers
|
|
||||||
44
.github/CONTRIBUTING.md
vendored
|
|
@ -20,11 +20,11 @@ Before submitting a pull request, please make sure the following is done:
|
||||||
2. Run `npm install` in the repository root.
|
2. Run `npm install` in the repository root.
|
||||||
3. If you’ve fixed a bug or added code that should be tested, add tests!
|
3. If you’ve fixed a bug or added code that should be tested, add tests!
|
||||||
4. Ensure the test suite passes (`npm test`). Tip: `npm test -- --watch TestName` is helpful in development.
|
4. Ensure the test suite passes (`npm test`). Tip: `npm test -- --watch TestName` is helpful in development.
|
||||||
5. Format your code with prettier (`npm run prettier`).
|
5. Lint your code with eslint (`npm run lint`).
|
||||||
|
|
||||||
## Development Setup
|
## Development Setup
|
||||||
|
|
||||||
You need [Node.js](http://nodejs.org) at `v12.0.0+`.
|
You need [Node.js](http://nodejs.org) at `Node LTS+`.
|
||||||
|
|
||||||
After cloning the repo, run:
|
After cloning the repo, run:
|
||||||
|
|
||||||
|
|
@ -38,14 +38,11 @@ $ npm install # or npm
|
||||||
# dev-server, watch and auto reload playground
|
# dev-server, watch and auto reload playground
|
||||||
$ npm start
|
$ npm start
|
||||||
|
|
||||||
# start playground app in production environment
|
# run tslint
|
||||||
$ npm run start:prod
|
|
||||||
|
|
||||||
# runt tslint
|
|
||||||
$ npm run lint
|
$ npm run lint
|
||||||
|
|
||||||
# try autofix tslint issues
|
# try autofix tslint issues
|
||||||
$ npm run lint -- --fix
|
$ npm run lint:fix
|
||||||
|
|
||||||
# run unit tests
|
# run unit tests
|
||||||
$ npm run unit
|
$ npm run unit
|
||||||
|
|
@ -53,46 +50,37 @@ $ npm run unit
|
||||||
# run e2e tests
|
# run e2e tests
|
||||||
$ npm run e2e
|
$ npm run e2e
|
||||||
# Make sure you have created bundle before running e2e test
|
# Make sure you have created bundle before running e2e test
|
||||||
# E.g. run `npm run bundle` and wait for the finishing process.
|
# E.g. run `npm run build` and wait for the finishing process.
|
||||||
|
|
||||||
# open cypress UI to debug e2e test
|
# open Playwright UI to debug e2e test
|
||||||
$ npm run cy:open
|
$ npm run e2e:ui
|
||||||
|
|
||||||
# run the unit tests (includes linting and license checks)
|
# run the unit tests (includes linting and license checks)
|
||||||
$ npm test
|
$ npm test
|
||||||
|
|
||||||
# prepare bundles
|
# prepare bundles
|
||||||
$ npm run bundle
|
$ npm run build
|
||||||
|
|
||||||
# format the code using prettier
|
|
||||||
$ npm run prettier
|
|
||||||
|
|
||||||
# auto-generate changelog
|
|
||||||
$ npm run changelog
|
|
||||||
```
|
```
|
||||||
|
|
||||||
There are some other scripts available in the `scripts` section of the `package.json` file.
|
There are some other scripts available in the `scripts` section of the `package.json` file.
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
- **`benchmark`**: contains basic perf benchmark. Not fully ready yet
|
- **`examples`**: contains project demos
|
||||||
|
|
||||||
- **`demo`**: contains project demo with demo specs and HMR playground used in development
|
- **`playground`**: HMR Playground used in development
|
||||||
|
|
||||||
- `demo/playground`: HMR Playground used in development
|
|
||||||
|
|
||||||
- **`docs`**: contains extra docs (linked from README.md)
|
- **`docs`**: contains extra docs (linked from README.md)
|
||||||
|
|
||||||
- **`e2e`**: contains e2e tests. The e2e tests are written and run with [Cypress](https://www.cypress.io/).
|
- **`playwright`**: contains e2e tests. The e2e tests are written and run with [Playwright](https://playwright.dev/).
|
||||||
|
|
||||||
|
- **`src`**: contains the source code. The codebase is written in Typescript. CSS styles are managed with [Styled components](https://www.styled-components.com/). State is managed by [Jotai](https://github.com/pmndrs/jotai)
|
||||||
|
|
||||||
- **`src`**: contains the source code. The codebase is written in Typescript. CSS styles are managed with [Styled components](https://www.styled-components.com/). State is managed by [MobX](https://github.com/mobxjs/mobx)
|
|
||||||
|
|
||||||
- **`src/common-elements`**: contains common Styled elements or components used in multiple places
|
|
||||||
- **`src/components`**: contains main visual components
|
- **`src/components`**: contains main visual components
|
||||||
- **`src/services`**: contains different services used by Redoc including MobX stores
|
- **`src/services`**: contains different services used by Redoc including Jotai stores
|
||||||
- **`src/services/models`**: contains classes for OpenAPI entities (e.g. Response, Operations, etc)
|
- **`src/models`**: contains classes for OpenAPI entities (e.g. Response, Operations, etc)
|
||||||
- **`src/types`**: contains extra typescript typings including OpenAPI doc typings
|
- **`src/types`**: contains extra typescript typings including OpenAPI doc typings
|
||||||
- **`src/utils`**: utility functions
|
- **`src/utils`**: utility functions
|
||||||
- **`src/styled-components.ts`**: - reexports styled-components with proper typescript annotations using theme
|
- **`src/jotai`**: - contains Jotai store files
|
||||||
- **`src/theme.ts`**: - default theme (colors, fonts, etc) used by all the components
|
- **`src/hooks`**: - contains global react hooks for application
|
||||||
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -15,8 +15,12 @@ A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
**Minimal reproducible OpenAPI snippet(if possible)**
|
**Minimal reproducible OpenAPI snippet(if possible)**
|
||||||
|
|
||||||
|
|
||||||
|
**Version (of Redoc, Node, OS, Browser)**
|
||||||
|
|
||||||
|
|
||||||
**Screenshots**
|
**Screenshots**
|
||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
|
@ -17,4 +17,4 @@ A clear and concise description of what you want to happen.
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
||||||
14
.github/actions/get-package-version/action.yml
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
name: Get version from package.json
|
||||||
|
description: Get version from package.json
|
||||||
|
outputs:
|
||||||
|
value:
|
||||||
|
description: "Version from package.json"
|
||||||
|
value: ${{ steps.package_version.outputs.value }}
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Get version
|
||||||
|
shell: bash
|
||||||
|
id: package_version
|
||||||
|
run: |
|
||||||
|
echo "value=$(jq -r .version package.json)" >> "$GITHUB_OUTPUT"
|
||||||
21
.github/actions/setup-node/action.yml
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
name: Node setup
|
||||||
|
description: Setup Node
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: 🚀 Starting Node setup
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo -e "\033[32m----- setup Node started -----\033[0m"
|
||||||
|
echo "START_TIME=$(date +%s)" >> $GITHUB_ENV
|
||||||
|
- name: 📦 Install Node
|
||||||
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||||
|
with:
|
||||||
|
node-version: 22.17.1
|
||||||
|
cache: npm
|
||||||
|
- name: ✅ Finished Node setup
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
END_TIME=$(date +%s)
|
||||||
|
DURATION=$((END_TIME - START_TIME))
|
||||||
|
echo -e "\033[32m----- setup Node finished in ${DURATION}s -----\033[0m"
|
||||||
36
.github/actions/setup-playwright/action.yml
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
name: Playwright setup
|
||||||
|
description: Setup Playwright
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: 🚀 Starting Playwright setup
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo -e "\033[32m----- setup Playwright started -----\033[0m"
|
||||||
|
echo "START_TIME=$(date +%s)" >> $GITHUB_ENV
|
||||||
|
- name: Get Playwright version
|
||||||
|
id: playwright-version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "PLAYWRIGHT_VERSION=$(jq -r '.devDependencies["@playwright/test"]' package.json)" >> $GITHUB_OUTPUT
|
||||||
|
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
|
||||||
|
name: Check if Playwright browser is cached
|
||||||
|
id: playwright-cache
|
||||||
|
with:
|
||||||
|
path: ${{ runner.os == 'Windows' && 'C:\Users\runneradmin\AppData\Local\ms-playwright' || runner.os == 'Linux' && '~/.cache/ms-playwright' || runner.os == 'macOS' && '~/Library/Caches/ms-playwright' || '' }}
|
||||||
|
key: ${{ runner.os }}-Playwright-${{steps.playwright-version.outputs.PLAYWRIGHT_VERSION}}
|
||||||
|
- name: 📦 Install Playwright browser if not cached
|
||||||
|
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "Installing Playwright in root"
|
||||||
|
echo "Installing @playwright/test@${{ steps.playwright-version.outputs.PLAYWRIGHT_VERSION }} (no-save)"
|
||||||
|
npm install -D @playwright/test@${{ steps.playwright-version.outputs.PLAYWRIGHT_VERSION }} --no-save
|
||||||
|
npx playwright install --with-deps
|
||||||
|
- name: ✅ Finished Playwright setup
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
END_TIME=$(date +%s)
|
||||||
|
DURATION=$((END_TIME - START_TIME))
|
||||||
|
echo -e "\033[32m----- setup Playwright finished in ${DURATION}s -----\033[0m"
|
||||||
2
.github/pull_request_template.md
vendored
|
|
@ -10,4 +10,4 @@
|
||||||
|
|
||||||
- [ ] Code is linted
|
- [ ] Code is linted
|
||||||
- [ ] Tested
|
- [ ] Tested
|
||||||
- [ ] All new/updated code is covered with tests
|
- [ ] All new/updated code is covered with tests
|
||||||
110
.github/styles/Rules/BritishEnglish.yml
vendored
|
|
@ -1,110 +0,0 @@
|
||||||
extends: substitution
|
|
||||||
message: 'Use the US spelling "%s" instead of British "%s".'
|
|
||||||
link: https://docs.microsoft.com/en-us/style-guide/word-choice/use-us-spelling-avoid-non-english-words
|
|
||||||
level: error
|
|
||||||
ignorecase: true
|
|
||||||
swap:
|
|
||||||
aeon: eon
|
|
||||||
aeroplane: airplane
|
|
||||||
ageing: aging
|
|
||||||
aluminium: aluminum
|
|
||||||
anaemia: anemia
|
|
||||||
anaesthesia: anesthesia
|
|
||||||
analyse: analyze
|
|
||||||
annexe: annex
|
|
||||||
apologise: apologize
|
|
||||||
behaviour: behavior
|
|
||||||
busses: buses
|
|
||||||
calibre: caliber
|
|
||||||
cancelled: canceled
|
|
||||||
cancellation: cancelation
|
|
||||||
catalogue: catalog
|
|
||||||
categorise: categorize
|
|
||||||
categorised: categorized
|
|
||||||
categorises: categorizes
|
|
||||||
categorising: categorizing
|
|
||||||
centre: center
|
|
||||||
cheque: check
|
|
||||||
civilisation: civilization
|
|
||||||
civilise: civilize
|
|
||||||
colour: color
|
|
||||||
cosy: cozy
|
|
||||||
cypher: cipher
|
|
||||||
dependant: dependent
|
|
||||||
defence: defense
|
|
||||||
distil: distill
|
|
||||||
draught: draft
|
|
||||||
encyclopaedia: encyclopedia
|
|
||||||
enquiry: inquiry
|
|
||||||
enrol: enroll
|
|
||||||
enrolment: enrollment
|
|
||||||
enthral: enthrall
|
|
||||||
expiry: expiration
|
|
||||||
favourite: favorite
|
|
||||||
fibre: fiber
|
|
||||||
fillet: filet
|
|
||||||
flavour: flavor
|
|
||||||
furore: furor
|
|
||||||
fulfil: fulfill
|
|
||||||
gaol: jail
|
|
||||||
grey: gray
|
|
||||||
humour: humor
|
|
||||||
honour: honor
|
|
||||||
initialled: initialed
|
|
||||||
initialling: initialing
|
|
||||||
instil: instill
|
|
||||||
jewellery: jewelry
|
|
||||||
labelling: labeling
|
|
||||||
labelled: labeled
|
|
||||||
labour: labor
|
|
||||||
libellous: libelous
|
|
||||||
licence: license
|
|
||||||
likeable: likable
|
|
||||||
liveable: livable
|
|
||||||
lustre: luster
|
|
||||||
manoeuvre: maneuver
|
|
||||||
marvellous: marvelous
|
|
||||||
matt: matte
|
|
||||||
meagre: meager
|
|
||||||
metre: meter
|
|
||||||
modelling: modeling
|
|
||||||
moustache: mustache
|
|
||||||
neighbour: neighbor
|
|
||||||
normalise: normalize
|
|
||||||
offence: offense
|
|
||||||
organise: organize
|
|
||||||
organisation: organization
|
|
||||||
orientated: oriented
|
|
||||||
paralyse: paralyze
|
|
||||||
plough: plow
|
|
||||||
pretence: pretense
|
|
||||||
programme: program
|
|
||||||
pyjamas: pajamas
|
|
||||||
rateable: ratable
|
|
||||||
realise: realize
|
|
||||||
recognise: recognize
|
|
||||||
reconnoitre: reconnoiter
|
|
||||||
rumour: rumor
|
|
||||||
sabre: saber
|
|
||||||
saleable: salable
|
|
||||||
saltpetre: saltpeter
|
|
||||||
sceptic: skeptic
|
|
||||||
sepulchre: sepulcher
|
|
||||||
signalling: signaling
|
|
||||||
sizeable: sizable
|
|
||||||
skilful: skillful
|
|
||||||
sombre: somber
|
|
||||||
smoulder: smolder
|
|
||||||
speciality: specialty
|
|
||||||
spectre: specter
|
|
||||||
splendour: splendor
|
|
||||||
standardise: standardize
|
|
||||||
standardised: standardized
|
|
||||||
sulphur: sulfur
|
|
||||||
theatre: theater
|
|
||||||
travelled: traveled
|
|
||||||
traveller: traveler
|
|
||||||
travelling: traveling
|
|
||||||
unshakeable: unshakable
|
|
||||||
wilful: willful
|
|
||||||
yoghurt: yogurt
|
|
||||||
10
.github/styles/Rules/FutureTense.yml
vendored
|
|
@ -1,10 +0,0 @@
|
||||||
extends: existence
|
|
||||||
message: 'Avoid using future tense: "%s". Use present tense instead.'
|
|
||||||
link: https://intranet.redoc.ly/contributing/documentation-style-guide/#tone-and-audience
|
|
||||||
ignorecase: true
|
|
||||||
level: error
|
|
||||||
raw:
|
|
||||||
- "(going to( |\n|[[:punct:]])[a-zA-Z]*|"
|
|
||||||
- "will( |\n|[[:punct:]])[a-zA-Z]*|"
|
|
||||||
- "won't( |\n|[[:punct:]])[a-zA-Z]*|"
|
|
||||||
- "[a-zA-Z]*'ll( |\n|[[:punct:]])[a-zA-Z]*)"
|
|
||||||
11
.github/styles/Rules/HeaderGerunds.yml
vendored
|
|
@ -1,11 +0,0 @@
|
||||||
extends: existence
|
|
||||||
message: 'Do not start headings with with a gerund (ing word). Use an imperative verb instead.'
|
|
||||||
link: https://intranet.redoc.ly/contributing/documentation-style-guide/#content-organization
|
|
||||||
level: error
|
|
||||||
scope: heading
|
|
||||||
tokens:
|
|
||||||
- '^\w*ing.*'
|
|
||||||
exceptions:
|
|
||||||
- expandSingleSchemaField
|
|
||||||
- hideLoading
|
|
||||||
- hideSingleRequestSampleTab
|
|
||||||
16
.github/styles/Rules/InclusionGenderCulture.yml
vendored
|
|
@ -1,16 +0,0 @@
|
||||||
extends: substitution
|
|
||||||
message: 'Use inclusive language. Consider "%s" instead of "%s".'
|
|
||||||
link: https://intranet.redoc.ly/contributing/documentation-style-guide/#grammar-and-syntax
|
|
||||||
level: error
|
|
||||||
ignorecase: true
|
|
||||||
swap:
|
|
||||||
he: they
|
|
||||||
his: their
|
|
||||||
she: they
|
|
||||||
hers: their
|
|
||||||
blacklist(?:ed|ing|s)?: blocklist
|
|
||||||
whitelist(?:ed|ing|s)?: allowlist
|
|
||||||
master: primary, main
|
|
||||||
slave: replica
|
|
||||||
he/she: they
|
|
||||||
s/he: they
|
|
||||||
8
.github/styles/Rules/OxfordComma.yml
vendored
|
|
@ -1,8 +0,0 @@
|
||||||
extends: existence
|
|
||||||
message: "Use the Oxford comma in '%s'."
|
|
||||||
link: https://docs.microsoft.com/en-us/style-guide/punctuation/commas
|
|
||||||
scope: sentence
|
|
||||||
level: error
|
|
||||||
nonword: true
|
|
||||||
tokens:
|
|
||||||
- '(?:[^\s,]+,){1,} \w+ (?:and|or) \w+[.?!]'
|
|
||||||
150
.github/styles/config/vocabularies/Rules/accept.txt
vendored
|
|
@ -1,150 +0,0 @@
|
||||||
[Aa]nsible
|
|
||||||
[Aa]utostart
|
|
||||||
[Bb]locklist
|
|
||||||
[Bb]locklists
|
|
||||||
[Bb]oolean
|
|
||||||
[Bb]reakpoint
|
|
||||||
[B]reakpoints
|
|
||||||
[Cc]ancelation
|
|
||||||
[Cc]lassloading
|
|
||||||
[Cc]hargeback
|
|
||||||
[Cc]hargebacks
|
|
||||||
[Cc]he
|
|
||||||
[Cc]rypto
|
|
||||||
[Cc]ryptocurrency
|
|
||||||
[Dd]evfile|[Dd]evfiles
|
|
||||||
[Dd]ownstream
|
|
||||||
[Dd]ownstreaming
|
|
||||||
[Ff]actories|[Ff]actory
|
|
||||||
[Gg]it
|
|
||||||
[Gg]rafana
|
|
||||||
[Hh]eatmap
|
|
||||||
[Hh]elm
|
|
||||||
[Hh]ostname
|
|
||||||
[Ii]tem
|
|
||||||
[Jj]etbrains
|
|
||||||
[Kk]eycloak
|
|
||||||
[Ll]iveness
|
|
||||||
[Ll]ombok
|
|
||||||
[Ll]oopback
|
|
||||||
[Mm]aven
|
|
||||||
[Mm]inikube
|
|
||||||
[Mm]inishift
|
|
||||||
[Mm]ixin|[Mm]ixins
|
|
||||||
[Mm]odularization
|
|
||||||
[Mm]ulticluster
|
|
||||||
[Mm]ultihost
|
|
||||||
[Mm]ultinode
|
|
||||||
[Mm]ultitenant
|
|
||||||
[Mm]ultiuser
|
|
||||||
[Mm]ultizone
|
|
||||||
[Nn]amespace|[Nn]amespaces
|
|
||||||
[Nn]etcoredebug[Oo]utput
|
|
||||||
[Nn]ginx
|
|
||||||
[Oo]nboarding
|
|
||||||
[Pp]podman
|
|
||||||
[Pp]reconfigured
|
|
||||||
[Rr]eadonly
|
|
||||||
[Rr]epresentment
|
|
||||||
[Rr]ollout|[Rr]ollouts
|
|
||||||
[Rr]untime|[Rr]untimes
|
|
||||||
[Ss]erializer
|
|
||||||
[Ss]erverless
|
|
||||||
[Ss]ubnetwork
|
|
||||||
[Ss]ubpath|[Ss]ubpaths
|
|
||||||
[Tt]heia
|
|
||||||
[Tt]olerations
|
|
||||||
[Tt]ruststore
|
|
||||||
[Uu]ninstallation
|
|
||||||
[Uu]nstaged
|
|
||||||
[Uu]ntrusted
|
|
||||||
[Ww]orkspace|[Ww]orkspaces
|
|
||||||
[Yy]eoman
|
|
||||||
\.NET
|
|
||||||
adoc
|
|
||||||
Antora
|
|
||||||
API
|
|
||||||
Apigee
|
|
||||||
AsciiDoc
|
|
||||||
AWS|aws
|
|
||||||
Azure
|
|
||||||
Bierner
|
|
||||||
Bitbucket
|
|
||||||
btn
|
|
||||||
Btrfs
|
|
||||||
CentOS
|
|
||||||
Ceph
|
|
||||||
Che-Theia
|
|
||||||
CLI
|
|
||||||
ConfigMap|ConfigMaps
|
|
||||||
Ctrl
|
|
||||||
DaemonSet
|
|
||||||
Dev Workspace
|
|
||||||
Developer Perspective
|
|
||||||
DNS
|
|
||||||
Docker
|
|
||||||
Dockerfile
|
|
||||||
Dotnet
|
|
||||||
Endevor
|
|
||||||
endif
|
|
||||||
GitHub|github
|
|
||||||
GitLab
|
|
||||||
Gluster
|
|
||||||
Gradle
|
|
||||||
Grafana
|
|
||||||
GUI
|
|
||||||
HTTPS|https
|
|
||||||
I/O
|
|
||||||
IDE|ide|IDEs
|
|
||||||
Intelephense
|
|
||||||
IntelliJ IDEA
|
|
||||||
Java
|
|
||||||
Java Lombok
|
|
||||||
JSON|json
|
|
||||||
JVM|jvm
|
|
||||||
kbd
|
|
||||||
Kubespray
|
|
||||||
Laravel
|
|
||||||
Let\'s Encrypt
|
|
||||||
Mattermost
|
|
||||||
mebibytes
|
|
||||||
Microsoft Azure
|
|
||||||
millicores
|
|
||||||
Mulesoft
|
|
||||||
MySQL
|
|
||||||
Netlify
|
|
||||||
Node.js
|
|
||||||
npm
|
|
||||||
NuGet
|
|
||||||
OAuth
|
|
||||||
ocp
|
|
||||||
OmniSharp
|
|
||||||
OpenShift
|
|
||||||
OpenTracing
|
|
||||||
Operator
|
|
||||||
OperatorHub
|
|
||||||
OpenAPI
|
|
||||||
osd
|
|
||||||
PHP
|
|
||||||
PostgreSQL
|
|
||||||
Quarkus
|
|
||||||
Rebilly
|
|
||||||
Redoc
|
|
||||||
Redocly
|
|
||||||
Redocly-cli
|
|
||||||
SCM
|
|
||||||
Sharding
|
|
||||||
SonarLint
|
|
||||||
Spring Boot
|
|
||||||
SVG
|
|
||||||
Uber
|
|
||||||
URI|URIs
|
|
||||||
URL|url|URLs
|
|
||||||
Velero
|
|
||||||
Vercel
|
|
||||||
Visual Studio Code
|
|
||||||
vsix
|
|
||||||
Webview|Webviews
|
|
||||||
Woopra
|
|
||||||
YAML|yaml
|
|
||||||
Zowe
|
|
||||||
48
.github/workflows/docker.yml
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
name: Build and Publish Docker container on Dockerhub
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
secrets:
|
||||||
|
DOCKERHUB_USERNAME:
|
||||||
|
description: 'DockerHub username'
|
||||||
|
required: true
|
||||||
|
DOCKERHUB_TOKEN:
|
||||||
|
description: 'DockerHub token'
|
||||||
|
required: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repo
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
- name: Get package version
|
||||||
|
id: get_version
|
||||||
|
uses: ./.github/actions/get-package-version
|
||||||
|
- name: Docker meta
|
||||||
|
id: docker_meta
|
||||||
|
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
redocly/redoc
|
||||||
|
tags: |
|
||||||
|
${{ steps.get_version.outputs.value }}
|
||||||
|
latest
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./config/docker/Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||||
37
.github/workflows/docs-tests.yaml
vendored
|
|
@ -1,37 +0,0 @@
|
||||||
name: Documentation tests
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
markdownlint:
|
|
||||||
name: markdownlint
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: DavidAnson/markdownlint-cli2-action@v15
|
|
||||||
with:
|
|
||||||
config: .markdownlint.yaml
|
|
||||||
globs: |
|
|
||||||
docs/**/*.md
|
|
||||||
README.md
|
|
||||||
|
|
||||||
vale:
|
|
||||||
name: vale action
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: errata-ai/vale-action@reviewdog
|
|
||||||
with:
|
|
||||||
files: '["README.md", "docs"]'
|
|
||||||
filter_mode: file
|
|
||||||
|
|
||||||
linkcheck:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Markup Link Checker (mlc)
|
|
||||||
uses: becheran/mlc@v0.16.1
|
|
||||||
with:
|
|
||||||
args: ./docs
|
|
||||||
12
.github/workflows/e2e-tests.yml
vendored
|
|
@ -1,12 +0,0 @@
|
||||||
name: Tests e2e
|
|
||||||
|
|
||||||
on: [push]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-e2e:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- run: npm ci
|
|
||||||
- run: npm run bundle
|
|
||||||
- run: npm run e2e
|
|
||||||
29
.github/workflows/e2e.yml
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
name: Tests e2e
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-e2e:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repo
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||||
|
with:
|
||||||
|
node-version: 22.17
|
||||||
|
cache: 'npm'
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm ci --ignore-scripts --no-fund
|
||||||
|
- name: Bundle
|
||||||
|
run: npm run build:standalone
|
||||||
|
- name: Prepare Playwright
|
||||||
|
uses: ./.github/actions/setup-playwright
|
||||||
|
- name: Run e2e tests
|
||||||
|
run: npm run e2e:prepare && npm run e2e
|
||||||
39
.github/workflows/main.yml
vendored
|
|
@ -1,39 +0,0 @@
|
||||||
name: Publish Docker image
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
jobs:
|
|
||||||
dockerhub:
|
|
||||||
name: Publish redoc image to DockerHub
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Docker meta
|
|
||||||
id: docker_meta
|
|
||||||
uses: crazy-max/ghaction-docker-meta@v1
|
|
||||||
with:
|
|
||||||
images: redocly/redoc
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v1
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v1
|
|
||||||
|
|
||||||
- name: Login to DockerHub
|
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push
|
|
||||||
uses: docker/build-push-action@v3
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./config/docker/Dockerfile
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
|
||||||
132
.github/workflows/publish.yml
vendored
|
|
@ -1,132 +0,0 @@
|
||||||
name: Publish
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
bundle:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
- name: Cache node modules
|
|
||||||
uses: actions/cache@v3
|
|
||||||
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@v4
|
|
||||||
with:
|
|
||||||
name: bundles
|
|
||||||
path: bundles
|
|
||||||
retention-days: 1
|
|
||||||
unit-tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- run: npm ci
|
|
||||||
- run: npm test
|
|
||||||
e2e-tests:
|
|
||||||
needs: [bundle]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- run: npm ci
|
|
||||||
- name: Download bundled artifact
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: bundles
|
|
||||||
path: bundles
|
|
||||||
- run: npm run e2e
|
|
||||||
check-version:
|
|
||||||
name: Check Version
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [bundle, unit-tests, e2e-tests]
|
|
||||||
outputs:
|
|
||||||
changed: ${{ steps.check.outputs.changed }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Set up Node.js
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
- name: Check if version has been updated
|
|
||||||
id: check
|
|
||||||
uses: EndBug/version-check@v2.0.1
|
|
||||||
with:
|
|
||||||
file-url: https://cdn.jsdelivr.net/npm/redoc/package.json
|
|
||||||
static-checking: localIsNew
|
|
||||||
publish:
|
|
||||||
name: Publish to NPM
|
|
||||||
needs: [check-version]
|
|
||||||
if: needs.check-version.outputs.changed == 'true'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: '14.x'
|
|
||||||
registry-url: 'https://registry.npmjs.org'
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Download bundled artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: bundles
|
|
||||||
path: bundles
|
|
||||||
- name: Cache node modules
|
|
||||||
uses: actions/cache@v3
|
|
||||||
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 ci && npm run declarations
|
|
||||||
- name: Publish to NPM
|
|
||||||
run: npm publish
|
|
||||||
env:
|
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
publish-cdn:
|
|
||||||
name: Publish to CDN
|
|
||||||
needs: [check-version]
|
|
||||||
if: needs.check-version.outputs.changed == 'true'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Configure AWS
|
|
||||||
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: Download all artifact
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
- name: Publish to S3
|
|
||||||
run: npm run publish-cdn
|
|
||||||
|
|
||||||
invalidate-cache:
|
|
||||||
name: Clear cache
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [check-version, publish, publish-cdn]
|
|
||||||
if: needs.check-version.outputs.changed == 'true'
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Configure AWS
|
|
||||||
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: Invalidate cache
|
|
||||||
run: ./scripts/invalidate-cache.sh
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
DISTRIBUTION: ${{ secrets.DISTRIBUTION }}
|
|
||||||
90
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
# permissions:
|
||||||
|
# id-token: write
|
||||||
|
# contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
published: ${{ steps.changesets.outputs.published }}
|
||||||
|
publishedPackages: ${{ steps.changesets.outputs.publishedPackages }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repo
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||||
|
with:
|
||||||
|
node-version: 22.17
|
||||||
|
cache: 'npm'
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Create Release Pull Request or Publish to npm
|
||||||
|
id: changesets
|
||||||
|
uses: RomanHotsiy/changesets-action@v1
|
||||||
|
with:
|
||||||
|
publish: npm run release
|
||||||
|
commit: 'chore: 🔖 release new versions'
|
||||||
|
title: 'chore: 🔖 release new versions'
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
|
dockerhub:
|
||||||
|
needs: [release]
|
||||||
|
if: needs.release.outputs.published == 'true'
|
||||||
|
uses: ./.github/workflows/docker.yml
|
||||||
|
secrets:
|
||||||
|
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
publish-cdn:
|
||||||
|
name: Publish to CDN
|
||||||
|
needs: [release]
|
||||||
|
if: needs.release.outputs.published == 'true'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Configure AWS
|
||||||
|
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: Download all artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
- name: Publish to S3
|
||||||
|
run: npm run publish-cdn
|
||||||
|
|
||||||
|
invalidate-cache:
|
||||||
|
name: Clear cache
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [release, publish-cdn]
|
||||||
|
if: needs.release.outputs.published == 'true'
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Configure AWS
|
||||||
|
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: Invalidate cache
|
||||||
|
run: ./scripts/clear-cache.sh
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
DISTRIBUTION: ${{ secrets.DISTRIBUTION }}
|
||||||
22
.github/workflows/unit-tests.yml
vendored
|
|
@ -1,12 +1,24 @@
|
||||||
name: Unit Tests
|
name: Unit Tests
|
||||||
|
|
||||||
on: [push]
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-unit:
|
build-and-unit:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- name: Checkout Repo
|
||||||
- run: npm ci
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||||
- run: npm run bundle
|
- name: Setup Node.js
|
||||||
- run: npm test
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||||
|
with:
|
||||||
|
node-version: 22.17
|
||||||
|
cache: 'npm'
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm ci --ignore-scripts --no-fund
|
||||||
|
- name: Run unit tests
|
||||||
|
run: npm run unit
|
||||||
|
|
|
||||||
51
.gitignore
vendored
|
|
@ -1,39 +1,16 @@
|
||||||
### Linux ###
|
node_modules
|
||||||
*~
|
bin
|
||||||
|
stats.json
|
||||||
# KDE directory preferences
|
scripts/*.pem
|
||||||
.directory
|
scripts/*.pem.pub
|
||||||
# OS X folder attributes
|
lib/
|
||||||
|
bundle/
|
||||||
|
coverage/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Linux trash folder which might appear on any partition or disk
|
licenses-list.json
|
||||||
.Trash-*
|
cli-zip
|
||||||
|
/test-results/
|
||||||
demo/dist/
|
/playwright-report/
|
||||||
|
/blob-report/
|
||||||
### Node ###
|
/playwright/.cache/
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
|
|
||||||
# Dependency directory
|
|
||||||
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
lib/
|
|
||||||
stats.json
|
|
||||||
cypress/
|
|
||||||
bundles/
|
|
||||||
typings/*
|
|
||||||
!typings/styled-patch.d.ts
|
|
||||||
|
|
||||||
/benchmark/revisions
|
|
||||||
|
|
||||||
/coverage
|
|
||||||
.ghpages-tmp
|
|
||||||
stats.json
|
|
||||||
yarn.lock
|
|
||||||
.idea
|
|
||||||
.vscode
|
|
||||||
.eslintcache
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
. "$(dirname "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
npm run pre-commit
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
---
|
|
||||||
# Default rules: https://github.com/github/super-linter/blob/master/TEMPLATES/.markdown-lint.yml
|
|
||||||
|
|
||||||
# Rules by id
|
|
||||||
|
|
||||||
# Unordered list style
|
|
||||||
MD004: false
|
|
||||||
|
|
||||||
# Unordered list indentation
|
|
||||||
MD007:
|
|
||||||
indent: 2
|
|
||||||
|
|
||||||
MD013:
|
|
||||||
# TODO: Consider to decrease allowed line length
|
|
||||||
line_length: 800
|
|
||||||
tables: false
|
|
||||||
|
|
||||||
## Allow same headers in siblings
|
|
||||||
MD024:
|
|
||||||
siblings_only: true
|
|
||||||
|
|
||||||
# Multiple top level headings in the same document
|
|
||||||
MD025:
|
|
||||||
front_matter_title: ''
|
|
||||||
|
|
||||||
# Trailing punctuation in heading
|
|
||||||
MD026:
|
|
||||||
punctuation: '.,;:。,;:'
|
|
||||||
|
|
||||||
# Ordered list item prefix
|
|
||||||
MD029: false
|
|
||||||
|
|
||||||
# Unordered lists inside of ordered lists
|
|
||||||
MD030: false
|
|
||||||
|
|
||||||
# Inline HTML
|
|
||||||
MD033: false
|
|
||||||
|
|
||||||
# No bare urls
|
|
||||||
MD034: false
|
|
||||||
|
|
||||||
# Emphasis used instead of a heading
|
|
||||||
MD036: false
|
|
||||||
|
|
||||||
# Disable "First line in file should be a top level heading"
|
|
||||||
# We use uncommon format to add metadata.
|
|
||||||
# TODO: Consider to use "YAML front matter".
|
|
||||||
MD041: false
|
|
||||||
|
|
||||||
# Rules by tags
|
|
||||||
blank_lines: false
|
|
||||||
|
|
||||||
MD046: false
|
|
||||||
# code-block-style
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
# Ignore these links, we can't check them from this subproject
|
|
||||||
ignore-links=["../*", "/docs/*"]
|
|
||||||
# Path to the root folder used to resolve all relative paths
|
|
||||||
root-dir="./docs"
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
*
|
*
|
||||||
!bundles/*
|
|
||||||
!typings/**/*
|
|
||||||
!package.json
|
!package.json
|
||||||
!README.md
|
!bundle/**/*.{js,d.ts}
|
||||||
!LICENSE
|
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
*.md
|
|
||||||
48
.vale.ini
|
|
@ -1,48 +0,0 @@
|
||||||
# Vale configuration file.
|
|
||||||
# See: https://docs.errata.ai/vale/config
|
|
||||||
|
|
||||||
# The relative path to the folder containing linting rules (styles).
|
|
||||||
StylesPath = .github/styles
|
|
||||||
|
|
||||||
# Vocab define the exceptions to use in *all* `BasedOnStyles`.
|
|
||||||
# spelling-exceptions.txt triggers `Vale.Terms`
|
|
||||||
# reject.txt triggers `Vale.Avoid`
|
|
||||||
# See: https://docs.errata.ai/vale/vocab
|
|
||||||
Vocab = Rules
|
|
||||||
|
|
||||||
# Minimum alert level
|
|
||||||
# -------------------
|
|
||||||
# The minimum alert level in the output (suggestion, warning, or error).
|
|
||||||
# If integrated into CI, builds fail by default on error-level alerts, unless you run Vale with the --no-exit flag
|
|
||||||
MinAlertLevel = suggestion
|
|
||||||
|
|
||||||
# IgnoredScopes specifies inline-level HTML tags to ignore.
|
|
||||||
# These tags may occur in an active scope (unlike SkippedScopes, skipped entirely) but their content still won't raise any alerts.
|
|
||||||
# Default: ignore `code` and `tt`.
|
|
||||||
IgnoredScopes = code, tt, img, url, a, body.id
|
|
||||||
# SkippedScopes specifies block-level HTML tags to ignore. Ignore any content in these scopes.
|
|
||||||
# Default: ignore `script`, `style`, `pre`, and `figure`.
|
|
||||||
# For AsciiDoc: by default, listingblock, and literalblock.
|
|
||||||
SkippedScopes = script, style, pre, figure, code, tt, listingblock, literalblock
|
|
||||||
|
|
||||||
# Rules for matching file types. See: https://docs.errata.ai/vale/scoping
|
|
||||||
|
|
||||||
[formats]
|
|
||||||
properties = md
|
|
||||||
mdx = md
|
|
||||||
|
|
||||||
# Rules for .MD, .MDX
|
|
||||||
[*.{md,mdx}]
|
|
||||||
|
|
||||||
BasedOnStyles = Rules
|
|
||||||
# Ignore code surrounded by backticks or plus sign, parameters defaults, URLs.
|
|
||||||
TokenIgnores = (\x60[^\n\x60]+\x60), ([^\n]+=[^\n]*), (\+[^\n]+\+), (http[^\n]+\[)
|
|
||||||
Vale.Repetition = NO
|
|
||||||
Vale.SentenceSpacing = NO
|
|
||||||
Vale.Spelling = NO
|
|
||||||
|
|
||||||
# /End of rules for .MD, .MDX
|
|
||||||
|
|
||||||
|
|
||||||
# Process .ini files
|
|
||||||
[*.ini]
|
|
||||||
2354
CHANGELOG.md
4
LICENSE
|
|
@ -1,6 +1,7 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015-present, Rebilly, Inc.
|
Copyright (c) 2015-present, Rebilly, Inc.
|
||||||
|
Copyright (c) 2021-present, Redocly Inc.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,4 +20,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
|
|
|
||||||
36
README.md
|
|
@ -26,7 +26,7 @@ By default Redoc offers a three-panel, responsive layout:
|
||||||
If you want to see how Redoc renders your OpenAPI definition,
|
If you want to see how Redoc renders your OpenAPI definition,
|
||||||
you can try it out online at https://redocly.github.io/redoc/.
|
you can try it out online at https://redocly.github.io/redoc/.
|
||||||
|
|
||||||
A version of the Swagger Petstore API is displayed by default.
|
A version of the Redocly Museum API is displayed by default.
|
||||||
To test it with your own OpenAPI definition,
|
To test it with your own OpenAPI definition,
|
||||||
enter the URL for your definition and select **TRY IT**.
|
enter the URL for your definition and select **TRY IT**.
|
||||||
|
|
||||||
|
|
@ -37,12 +37,12 @@ enter the URL for your definition and select **TRY IT**.
|
||||||
- Ability to integrate your API introduction into the side menu
|
- Ability to integrate your API introduction into the side menu
|
||||||
- High-level grouping in side menu with the [`x-tagGroups`](https://redocly.com/docs/api-reference-docs/specification-extensions/x-tag-groups/) specification extension
|
- High-level grouping in side menu with the [`x-tagGroups`](https://redocly.com/docs/api-reference-docs/specification-extensions/x-tag-groups/) specification extension
|
||||||
- [Simple integration with `create-react-app`](https://redocly.com/docs/redoc/quickstart/react/)
|
- [Simple integration with `create-react-app`](https://redocly.com/docs/redoc/quickstart/react/)
|
||||||
- Code samples support (with vendor extension) <br>
|
- Code samples support (with the `x-codeSamples` specification extension) <br>
|
||||||

|

|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Redoc is provided as a CLI tool (also distributed as a Docker image), HTML tag, and React component.
|
Redoc Community Edition is available as an HTML tag, a React component, and via the Redocly CLI (also distributed as a Docker image).
|
||||||
|
|
||||||
### Generate documentation from the CLI
|
### Generate documentation from the CLI
|
||||||
|
|
||||||
|
|
@ -73,20 +73,23 @@ Add your own `spec-url` to the `<redoc>` tag; this attribute can also be a local
|
||||||
|
|
||||||
Check out the [deployment documentation](./docs/deployment/intro.md) for more options, and detailed documentation for each.
|
Check out the [deployment documentation](./docs/deployment/intro.md) for more options, and detailed documentation for each.
|
||||||
|
|
||||||
## Redoc vs. Redocly API Reference
|
## Redoc CE vs. Redoc
|
||||||
|
|
||||||
Redoc is Redocly's community-edition product. Looking for something more?
|
Redoc CE is Redocly's community-edition product. Looking for something more?
|
||||||
We also offer [hosted API reference documentation](https://redocly.com/docs/api-registry/guides/api-registry-quickstart/)
|
We also offer [Redoc](https://redocly.com/redoc)
|
||||||
with additional features including:
|
with support specifications like GraphQL/AsyncAPI/SOAP and additional features including:
|
||||||
|
|
||||||
* Try-it console
|
* Try-it panel(Replay)
|
||||||
* Automated code samples
|
* Automated code samples
|
||||||
* Pagination
|
* Mock server
|
||||||
* Extra theme options
|
* Full customization
|
||||||
|
* Lint
|
||||||
|
|
||||||
|
For a detailed comparison of premium vs open source, see [Premium vs Open Source features](https://redocly.com/blog/premium-vs-open-source).
|
||||||
|
|
||||||
### Documentation and resources
|
### Documentation and resources
|
||||||
|
|
||||||
- [Reference docs](https://redocly.com/docs/api-reference-docs/getting-started/) - we take care of the hosting
|
- [Realm + Reunite](https://redocly.com/docs/realm) - we take care of the hosting, which includes everything you need for documentation.
|
||||||
- [Redoc](https://redocly.com/docs/redoc/) - detailed documentation for this open source project (also in the `docs/` folder)
|
- [Redoc](https://redocly.com/docs/redoc/) - detailed documentation for this open source project (also in the `docs/` folder)
|
||||||
- [Command-line interface to bundle your docs into a web-ready HTML file](https://redocly.com/docs/cli/commands/build-docs/)
|
- [Command-line interface to bundle your docs into a web-ready HTML file](https://redocly.com/docs/cli/commands/build-docs/)
|
||||||
- API linting, bundling, and much more with open source [Redocly CLI](https://redocly.com/docs/cli)
|
- API linting, bundling, and much more with open source [Redocly CLI](https://redocly.com/docs/cli)
|
||||||
|
|
@ -117,6 +120,7 @@ Redoc uses the following [specification extensions](https://redocly.com/docs/api
|
||||||
* [`x-traitTag`](docs/redoc-vendor-extensions.md#x-traitTag) - useful for tags that refer to non-navigation properties like Pagination, Rate-Limits, etc
|
* [`x-traitTag`](docs/redoc-vendor-extensions.md#x-traitTag) - useful for tags that refer to non-navigation properties like Pagination, Rate-Limits, etc
|
||||||
* [`x-codeSamples`](docs/redoc-vendor-extensions.md#x-codeSamples) - specify operation code samples
|
* [`x-codeSamples`](docs/redoc-vendor-extensions.md#x-codeSamples) - specify operation code samples
|
||||||
* [`x-badges`](docs/redoc-vendor-extensions.md#x-badges) - specify operation badges
|
* [`x-badges`](docs/redoc-vendor-extensions.md#x-badges) - specify operation badges
|
||||||
|
* ['x-enumDescriptions'](docs/redoc-vendor-extensions.md#x-enumDescriptions) - list of the enum values and descriptions to include in the documentation
|
||||||
* [`x-examples`](docs/redoc-vendor-extensions.md#x-examples) - specify JSON example for requests
|
* [`x-examples`](docs/redoc-vendor-extensions.md#x-examples) - specify JSON example for requests
|
||||||
* [`x-nullable`](docs/redoc-vendor-extensions.md#x-nullable) - mark schema param as a nullable
|
* [`x-nullable`](docs/redoc-vendor-extensions.md#x-nullable) - mark schema param as a nullable
|
||||||
* [`x-displayName`](docs/redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories
|
* [`x-displayName`](docs/redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories
|
||||||
|
|
@ -130,8 +134,12 @@ Redoc uses the following [specification extensions](https://redocly.com/docs/api
|
||||||
|
|
||||||
**The README for the `1.x` version is on the [v1.x](https://github.com/Redocly/redoc/tree/v1.x) branch.**
|
**The README for the `1.x` version is on the [v1.x](https://github.com/Redocly/redoc/tree/v1.x) branch.**
|
||||||
|
|
||||||
All the 2.x releases are deployed to npm and can be used with Redocly-cdn:
|
**The README for the `2.x` version is on the [v2.x](https://github.com/Redocly/redoc/tree/v2.x) branch.**
|
||||||
- particular release, for example, `v2.0.0`: https://cdn.redoc.ly/redoc/v2.0.0/bundles/redoc.standalone.js
|
|
||||||
|
All the 2.x and 3.x releases are deployed to npm and can be used with Redocly-cdn:
|
||||||
|
- particular release, for example:
|
||||||
|
- `v2.0.0`: https://cdn.redoc.ly/redoc/v2.0.0/bundles/redoc.standalone.js
|
||||||
|
- `v3.0.0`: https://cdn.redoc.ly/redoc/v3.0.0/bundles/redoc.standalone.js
|
||||||
- `latest` release: https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js
|
- `latest` release: https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js
|
||||||
|
|
||||||
Additionally, all the 1.x releases are hosted on our GitHub Pages-based CDN **(deprecated)**:
|
Additionally, all the 1.x releases are hosted on our GitHub Pages-based CDN **(deprecated)**:
|
||||||
|
|
|
||||||
40
api-extractor.json
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||||
|
"mainEntryPointFilePath": "<projectFolder>/lib/index.d.ts",
|
||||||
|
"compiler": {
|
||||||
|
"tsconfigFilePath": "<projectFolder>/tsconfig.json"
|
||||||
|
},
|
||||||
|
"apiReport": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"docModel": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"dtsRollup": {
|
||||||
|
"enabled": true,
|
||||||
|
"untrimmedFilePath": "<projectFolder>/bundle/redoc.d.ts"
|
||||||
|
},
|
||||||
|
"tsdocMetadata": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"messages": {
|
||||||
|
"compilerMessageReporting": {
|
||||||
|
"default": {
|
||||||
|
"logLevel": "warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extractorMessageReporting": {
|
||||||
|
"default": {
|
||||||
|
"logLevel": "warning"
|
||||||
|
},
|
||||||
|
"ae-missing-release-tag": {
|
||||||
|
"logLevel": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tsdocMessageReporting": {
|
||||||
|
"default": {
|
||||||
|
"logLevel": "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
const beautifyBenchmark = require('beautify-benchmark');
|
|
||||||
const sh = require('shelljs');
|
|
||||||
const fs = require('fs');
|
|
||||||
const pathJoin = require('path').join;
|
|
||||||
const spawn = require('child_process').spawn;
|
|
||||||
const puppeteer = require('puppeteer');
|
|
||||||
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
args[0] = args[0] || 'HEAD';
|
|
||||||
args[1] = args[1] || 'local';
|
|
||||||
|
|
||||||
let started = false;
|
|
||||||
|
|
||||||
console.log('Benchmarking revisions: ' + args.join(', '));
|
|
||||||
|
|
||||||
const localDistDir = './benchmark/revisions/local/bundles';
|
|
||||||
sh.rm('-rf', localDistDir);
|
|
||||||
console.log(`Building local dist: ${localDistDir}`);
|
|
||||||
sh.mkdir('-p', localDistDir);
|
|
||||||
exec(`npm run bundle:lib --output-path ${localDistDir}`);
|
|
||||||
|
|
||||||
const revisions = [];
|
|
||||||
for (const arg of args) {
|
|
||||||
revisions.push({ name: arg, path: buildRevisionDist(arg) });
|
|
||||||
}
|
|
||||||
|
|
||||||
const configFile = `
|
|
||||||
export const revisions = [ ${revisions.map(rev => JSON.stringify(rev)).join(', ')} ];
|
|
||||||
`;
|
|
||||||
|
|
||||||
const configDir = './benchmark/revisions/config.js';
|
|
||||||
console.log(`Writing config "${configDir}"`);
|
|
||||||
fs.writeFileSync(configDir, configFile);
|
|
||||||
|
|
||||||
console.log('Starting benchmark server');
|
|
||||||
const proc = spawn('npm', ['run', 'start:benchmark']);
|
|
||||||
|
|
||||||
proc.stdout.on('data', data => {
|
|
||||||
if (data.toString().indexOf('Compiled successfully') > -1) {
|
|
||||||
console.log('Server started');
|
|
||||||
startBenchmark();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
proc.stderr.on('data', data => {
|
|
||||||
console.error(data.toString());
|
|
||||||
});
|
|
||||||
|
|
||||||
proc.on('close', code => {
|
|
||||||
console.log(`Benchmark server stopped with code ${code}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function runPuppeteer() {
|
|
||||||
return await puppeteer
|
|
||||||
.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] })
|
|
||||||
.then(async browser => {
|
|
||||||
const page = await browser.newPage();
|
|
||||||
let resolve;
|
|
||||||
const prom = new Promise(_resolve => {
|
|
||||||
resolve = _resolve;
|
|
||||||
});
|
|
||||||
page.on('console', async msg => {
|
|
||||||
const args = msg.args();
|
|
||||||
const obj = args.length > 0 && (await args[0].jsonValue());
|
|
||||||
if (!obj) return;
|
|
||||||
|
|
||||||
if (obj.done) {
|
|
||||||
beautifyBenchmark.log();
|
|
||||||
// resolve(obj);
|
|
||||||
} else if (obj.cycle) {
|
|
||||||
beautifyBenchmark.add(obj.cycle);
|
|
||||||
} else if (obj.allDone) {
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
console.log(obj);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await page.goto('http://127.0.0.1:9090', { timeout: 0 });
|
|
||||||
const res = await prom;
|
|
||||||
await browser.close();
|
|
||||||
return res;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function startBenchmark() {
|
|
||||||
if (started) return;
|
|
||||||
started = true;
|
|
||||||
console.log('Starting benchmarks');
|
|
||||||
await runPuppeteer();
|
|
||||||
|
|
||||||
console.log('Killing benchmark server');
|
|
||||||
proc.kill('SIGINT');
|
|
||||||
}
|
|
||||||
|
|
||||||
function exec(command) {
|
|
||||||
const { code, stdout, stderr } = sh.exec(command, { silent: true });
|
|
||||||
if (code !== 0) {
|
|
||||||
console.error(stdout);
|
|
||||||
console.error(stderr);
|
|
||||||
sh.exit(code);
|
|
||||||
}
|
|
||||||
return stdout.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildRevisionDist(revision) {
|
|
||||||
if (revision === 'local') {
|
|
||||||
return localDistDir;
|
|
||||||
}
|
|
||||||
const hash = exec(`git log -1 --format=%h "${revision}"`);
|
|
||||||
const buildDir = './benchmark/revisions/' + hash;
|
|
||||||
const distDir = buildDir + '/bundles';
|
|
||||||
if (sh.test('-d', distDir)) {
|
|
||||||
console.log(`Using prebuilt "${revision}"(${hash}) revision: ${buildDir}`);
|
|
||||||
return distDir;
|
|
||||||
}
|
|
||||||
console.log(`Building "${revision}"(${hash}) revision: ${buildDir}`);
|
|
||||||
sh.mkdir('-p', buildDir);
|
|
||||||
exec(`git archive "${hash}" | tar -xC "${buildDir}"`);
|
|
||||||
|
|
||||||
const pwd = sh.pwd();
|
|
||||||
sh.cd(buildDir);
|
|
||||||
exec('npm uninstall cypress puppeteer && npm install && npm run bundle:lib');
|
|
||||||
sh.cd(pwd);
|
|
||||||
return distDir;
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>ReDoc</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
redoc {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<redoc id="example"></redoc>
|
|
||||||
<!-- <redoc spec-url="./openapi.yaml"></redoc> -->
|
|
||||||
<script src="https://unpkg.com/lodash@4.17.4/lodash.js"></script>
|
|
||||||
<script src="https://unpkg.com/benchmark@2.1.4/benchmark.js"></script>
|
|
||||||
<!-- <script src="../bundles/redoc.standalone.js"></script> -->
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { render, unmountComponentAtNode } from 'react-dom';
|
|
||||||
|
|
||||||
import { Redoc, RedocProps } from '../src/components';
|
|
||||||
|
|
||||||
import { loadAndBundleSpec } from '../src/utils';
|
|
||||||
|
|
||||||
import { revisions } from './revisions/config';
|
|
||||||
import { configure } from 'mobx';
|
|
||||||
|
|
||||||
declare var Benchmark;
|
|
||||||
|
|
||||||
configure({
|
|
||||||
isolateGlobalState: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const node = document.getElementById('example');
|
|
||||||
|
|
||||||
const renderRoot = (Component: typeof Redoc, props: RedocProps) =>
|
|
||||||
render(<Component {...props} />, node!);
|
|
||||||
|
|
||||||
async function importRedocs() {
|
|
||||||
return Promise.all(
|
|
||||||
revisions.map(rev => {
|
|
||||||
return import('./' + rev.path.substring(12) + '/redoc.lib.js');
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function startFullTime(redocs, resolvedSpec) {
|
|
||||||
return new Promise(async resolve => {
|
|
||||||
const suite = new Benchmark.Suite('Full time', {
|
|
||||||
maxTime: 20,
|
|
||||||
initCount: 2,
|
|
||||||
onStart(event) {
|
|
||||||
console.log(' ⏱️ ' + event.currentTarget.name);
|
|
||||||
},
|
|
||||||
onCycle(event) {
|
|
||||||
console.log({ cycle: event.target });
|
|
||||||
},
|
|
||||||
onComplete() {
|
|
||||||
console.log({ done: true });
|
|
||||||
setTimeout(() => resolve(), 10);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
revisions.forEach((rev, idx) => {
|
|
||||||
const redoc = redocs[idx];
|
|
||||||
suite.add(rev.name, () => {
|
|
||||||
const store = new redoc.AppStore(resolvedSpec, 'openapi.yaml');
|
|
||||||
renderRoot(redoc.Redoc, { store });
|
|
||||||
unmountComponentAtNode(node!);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.run({ async: true });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function startInitStore(redocs, resolvedSpec) {
|
|
||||||
return new Promise(async resolve => {
|
|
||||||
const suite = new Benchmark.Suite('Create Store Time', {
|
|
||||||
maxTime: 20,
|
|
||||||
initCount: 2,
|
|
||||||
onStart(event) {
|
|
||||||
console.log(' ⏱️ ' + event.currentTarget.name);
|
|
||||||
},
|
|
||||||
onCycle(event) {
|
|
||||||
console.log({ cycle: event.target });
|
|
||||||
},
|
|
||||||
onComplete() {
|
|
||||||
console.log({ done: true });
|
|
||||||
setTimeout(() => resolve(), 10);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
revisions.forEach((rev, idx) => {
|
|
||||||
const redoc = redocs[idx];
|
|
||||||
suite.add(rev.name, () => {
|
|
||||||
const store = new redoc.AppStore(resolvedSpec, 'openapi.yaml');
|
|
||||||
store.dispose();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.run({ async: true });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function startRenderTime(redocs, resolvedSpec) {
|
|
||||||
return new Promise(async resolve => {
|
|
||||||
const suite = new Benchmark.Suite('Render time', {
|
|
||||||
maxTime: 20,
|
|
||||||
initCount: 2,
|
|
||||||
onStart(event) {
|
|
||||||
console.log(' ⏱️ ' + event.currentTarget.name);
|
|
||||||
},
|
|
||||||
onCycle(event) {
|
|
||||||
console.log({ cycle: event.target });
|
|
||||||
unmountComponentAtNode(node!);
|
|
||||||
},
|
|
||||||
onComplete() {
|
|
||||||
console.log({ done: true });
|
|
||||||
setTimeout(() => resolve(), 10);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
revisions.forEach((rev, idx) => {
|
|
||||||
const redoc = redocs[idx];
|
|
||||||
const store = new redoc.AppStore(resolvedSpec, 'openapi.yaml');
|
|
||||||
suite.add(rev.name, () => {
|
|
||||||
renderRoot(redoc.Redoc, { store });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.run({ async: true });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runBenchmarks() {
|
|
||||||
const redocs: any[] = await importRedocs();
|
|
||||||
const resolvedSpec = await loadAndBundleSpec('openapi.yaml');
|
|
||||||
await startInitStore(redocs, resolvedSpec);
|
|
||||||
await startRenderTime(redocs, resolvedSpec);
|
|
||||||
await startFullTime(redocs, resolvedSpec);
|
|
||||||
console.log({ allDone: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
runBenchmarks();
|
|
||||||
|
|
@ -5,52 +5,47 @@
|
||||||
# npm i -g http-server
|
# npm i -g http-server
|
||||||
# http-server -p 8000 --cors
|
# http-server -p 8000 --cors
|
||||||
|
|
||||||
FROM node:18-alpine
|
FROM node:22.20.0-alpine@sha256:dbcedd8aeab47fbc0f4dd4bffa55b7c3c729a707875968d467aaaea42d6225af AS build
|
||||||
|
|
||||||
RUN apk update && apk add --no-cache git
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
COPY package.json package-lock.json /build/
|
|
||||||
RUN npm ci --no-optional --ignore-scripts
|
|
||||||
RUN npm explore esbuild -- npm run postinstall
|
|
||||||
|
|
||||||
# copy only required for the build files
|
COPY . .
|
||||||
COPY src /build/src
|
|
||||||
COPY webpack.config.ts tsconfig.json custom.d.ts /build/
|
|
||||||
COPY config/webpack-utils.ts /build/config/
|
|
||||||
COPY typings/styled-patch.d.ts /build/typings/styled-patch.d.ts
|
|
||||||
|
|
||||||
RUN npm run bundle:standalone
|
RUN npm ci --no-optional --ignore-scripts --no-fund --omit=dev \
|
||||||
|
&& npm install --no-save vite
|
||||||
|
|
||||||
FROM nginx:alpine
|
RUN npm run build:standalone && npm run minify
|
||||||
|
|
||||||
|
FROM nginx:1.28-alpine@sha256:8f2bcf97c473dfe311e79a510ee540ee02e28ce1e6a64e1ef89bfad32574ef10
|
||||||
|
|
||||||
ENV PAGE_TITLE="ReDoc"
|
ENV PAGE_TITLE="ReDoc"
|
||||||
ENV PAGE_FAVICON="favicon.png"
|
ENV PAGE_FAVICON="favicon.png"
|
||||||
ENV BASE_PATH=
|
ENV BASE_PATH=
|
||||||
ENV SPEC_URL="http://petstore.swagger.io/v2/swagger.json"
|
ENV SPEC_URL="https://cdn.redocly.com/redoc/museum-api.yaml"
|
||||||
ENV PORT=80
|
ENV PORT=80
|
||||||
|
ENV HOST=localhost
|
||||||
ENV REDOC_OPTIONS=
|
ENV REDOC_OPTIONS=
|
||||||
|
|
||||||
# copy files to the nginx folder
|
# add docker-entrypoint scripts
|
||||||
COPY --from=0 build/bundles /usr/share/nginx/html
|
COPY config/docker/docker-entrypoint.d/ /docker-entrypoint.d/
|
||||||
COPY config/docker/index.tpl.html /usr/share/nginx/html/index.html
|
RUN chmod -R +x /docker-entrypoint.d/
|
||||||
COPY demo/favicon.png /usr/share/nginx/html/
|
|
||||||
COPY config/docker/nginx.conf /etc/nginx/
|
# copy nginx config
|
||||||
COPY config/docker/docker-run.sh /usr/local/bin
|
COPY config/docker/nginx/templates/ /etc/nginx/templates/
|
||||||
|
COPY config/docker/nginx/nginx.conf config/docker/nginx/handle_options.conf config/docker/nginx/security.conf /etc/nginx/
|
||||||
|
|
||||||
|
# copy static files
|
||||||
|
COPY config/docker/static/ /usr/share/nginx/html/
|
||||||
|
COPY --from=build /build/bundle/redoc.standalone.js /usr/share/nginx/html/
|
||||||
|
|
||||||
# Provide rights to the root group to write to nginx repositories (needed to run in OpenShift)
|
# Provide rights to the root group to write to nginx repositories (needed to run in OpenShift)
|
||||||
RUN chgrp -R 0 /etc/nginx && \
|
RUN chgrp -R 0 /etc/nginx \
|
||||||
chgrp -R 0 /usr/share/nginx/html && \
|
&& chgrp -R 0 /usr/share/nginx/html \
|
||||||
chgrp -R 0 /var/cache/nginx && \
|
&& chgrp -R 0 /var/cache/nginx \
|
||||||
chgrp -R 0 /var/log/nginx && \
|
&& chgrp -R 0 /var/log/nginx \
|
||||||
chgrp -R 0 /var/run && \
|
&& chgrp -R 0 /var/run \
|
||||||
chmod -R g+rwX /etc/nginx && \
|
&& chmod -R g+rwX /etc/nginx \
|
||||||
chmod -R g+rwX /usr/share/nginx/html && \
|
&& chmod -R g+rwX /usr/share/nginx/html \
|
||||||
chmod -R g+rwX /var/cache/nginx && \
|
&& chmod -R g+rwX /var/cache/nginx \
|
||||||
chmod -R g+rwX /var/log/nginx && \
|
&& chmod -R g+rwX /var/log/nginx \
|
||||||
chmod -R g+rwX /var/run
|
&& chmod -R g+rwX /var/run
|
||||||
|
|
||||||
EXPOSE 80
|
|
||||||
|
|
||||||
CMD ["sh", "/usr/local/bin/docker-run.sh"]
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Official ReDoc Docker Image
|
# Official Redoc Docker Image
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|
@ -45,8 +45,9 @@ Another issue with OpenShift is that the default exposed port `80` cannot be use
|
||||||
|
|
||||||
- `PAGE_TITLE` (default `"ReDoc"`) - page title
|
- `PAGE_TITLE` (default `"ReDoc"`) - page title
|
||||||
- `PAGE_FAVICON` (default `"favicon.png"`) - URL to page favicon
|
- `PAGE_FAVICON` (default `"favicon.png"`) - URL to page favicon
|
||||||
- `BASE_PATH` (optional) - prepend favicon & standalone bundle with this path
|
- `BASE_PATH` (optional) - path prefix
|
||||||
- `SPEC_URL` (default `"http://petstore.swagger.io/v2/swagger.json"`) - URL to spec
|
- `SPEC_URL` (default `"http://petstore.swagger.io/v2/swagger.json"`) – URL to the spec (if mounted as a file inside the container and `BASE_PATH` is used, the spec should contain the prefix, e.g., for `"/v1/swagger.json"`)
|
||||||
|
- `HOST` (default `localhost`) - nginx server_name
|
||||||
- `PORT` (default `80`) - nginx port
|
- `PORT` (default `80`) - nginx port
|
||||||
- `REDOC_OPTIONS` (optional) - [`<redoc>` tag attributes](https://github.com/Redocly/redoc#redoc-tag-attributes)
|
- `REDOC_OPTIONS` (optional) - [`<redoc>` tag attributes](https://github.com/Redocly/redoc#redoc-tag-attributes)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Loop through all *.tpl.html files and transform them
|
||||||
|
for tpl in /usr/share/nginx/html/*.tpl.html; do
|
||||||
|
target="/usr/share/nginx/html/$(basename "$tpl" .tpl.html).html"
|
||||||
|
envsubst < "$tpl" > "$target"
|
||||||
|
done
|
||||||
13
config/docker/docker-entrypoint.d/95-clean-up.sh
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# remove template files
|
||||||
|
rm -f /usr/share/nginx/html/index.prefix.tpl.html /usr/share/nginx/html/index.tpl.html
|
||||||
|
|
||||||
|
if [ -n "$BASE_PATH" ]; then
|
||||||
|
rm -f /etc/nginx/conf.d/default.conf
|
||||||
|
rm -f /usr/share/nginx/html/index.html
|
||||||
|
mv /usr/share/nginx/html/index.prefix.html /usr/share/nginx/html/index.html
|
||||||
|
else
|
||||||
|
rm -f /etc/nginx/conf.d/default.prefix.conf
|
||||||
|
rm -f /usr/share/nginx/html/index.prefix.html
|
||||||
|
fi
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
sed -i -e "s|%PAGE_TITLE%|$PAGE_TITLE|g" /usr/share/nginx/html/index.html
|
|
||||||
sed -i -e "s|%PAGE_FAVICON%|$PAGE_FAVICON|g" /usr/share/nginx/html/index.html
|
|
||||||
sed -i -e "s|%BASE_PATH%|$BASE_PATH|g" /usr/share/nginx/html/index.html
|
|
||||||
sed -i -e "s|%SPEC_URL%|$SPEC_URL|g" /usr/share/nginx/html/index.html
|
|
||||||
sed -i -e "s|%REDOC_OPTIONS%|${REDOC_OPTIONS}|g" /usr/share/nginx/html/index.html
|
|
||||||
sed -i -e "s|\(listen\s*\) [0-9]*|\1 ${PORT}|g" /etc/nginx/nginx.conf
|
|
||||||
|
|
||||||
exec nginx -g 'daemon off;'
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# DockerHub cd into Dockerfile location before build
|
|
||||||
# So we have to undo this.
|
|
||||||
cd ../..
|
|
||||||
docker build -f config/docker/Dockerfile -t $IMAGE_NAME .
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<title>%PAGE_TITLE%</title>
|
|
||||||
<link rel="icon" href="%BASE_PATH%%PAGE_FAVICON%" />
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
redoc {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<redoc spec-url="%SPEC_URL%" %REDOC_OPTIONS%></redoc>
|
|
||||||
<script src="%BASE_PATH%redoc.standalone.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
worker_processes 1;
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
sendfile on;
|
|
||||||
|
|
||||||
keepalive_timeout 65;
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name localhost;
|
|
||||||
index index.html index.htm;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
alias /usr/share/nginx/html/;
|
|
||||||
|
|
||||||
if ($request_method = 'OPTIONS') {
|
|
||||||
# Add security headers
|
|
||||||
add_header 'X-Frame-Options' 'deny always';
|
|
||||||
add_header 'X-XSS-Protection' '"1; mode=block" always';
|
|
||||||
add_header 'X-Content-Type-Options' 'nosniff always';
|
|
||||||
add_header 'Referrer-Policy' 'strict-origin-when-cross-origin';
|
|
||||||
|
|
||||||
# Set access control header
|
|
||||||
add_header 'Access-Control-Allow-Origin' '*';
|
|
||||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
|
||||||
#
|
|
||||||
# Custom headers and headers various browsers *should* be OK with but aren't
|
|
||||||
#
|
|
||||||
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
|
|
||||||
#
|
|
||||||
# Tell client that this pre-flight info is valid for 20 days
|
|
||||||
#
|
|
||||||
add_header 'Access-Control-Max-Age' 1728000;
|
|
||||||
add_header 'Content-Type' 'text/plain charset=UTF-8';
|
|
||||||
add_header 'Content-Length' 0;
|
|
||||||
return 204;
|
|
||||||
}
|
|
||||||
if ($request_method = 'POST') {
|
|
||||||
# Add security headers
|
|
||||||
add_header 'X-Frame-Options' 'deny always';
|
|
||||||
add_header 'X-XSS-Protection' '"1; mode=block" always';
|
|
||||||
add_header 'X-Content-Type-Options' 'nosniff always';
|
|
||||||
add_header 'Referrer-Policy' 'strict-origin-when-cross-origin';
|
|
||||||
|
|
||||||
# Set access control header
|
|
||||||
add_header 'Access-Control-Allow-Origin' '*';
|
|
||||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
|
||||||
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
|
|
||||||
}
|
|
||||||
if ($request_method = 'GET') {
|
|
||||||
# Add security headers
|
|
||||||
add_header 'X-Frame-Options' 'deny always';
|
|
||||||
add_header 'X-XSS-Protection' '"1; mode=block" always';
|
|
||||||
add_header 'X-Content-Type-Options' 'nosniff always';
|
|
||||||
add_header 'Referrer-Policy' 'strict-origin-when-cross-origin';
|
|
||||||
|
|
||||||
# Set access control header
|
|
||||||
add_header 'Access-Control-Allow-Origin' '*';
|
|
||||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
|
||||||
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
9
config/docker/nginx/handle_options.conf
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
if ($request_method = 'OPTIONS') {
|
||||||
|
include /etc/nginx/security.conf;
|
||||||
|
# Tell client that this pre-flight info is valid for 20 days
|
||||||
|
#
|
||||||
|
add_header 'Access-Control-Max-Age' 1728000;
|
||||||
|
add_header 'Content-Type' 'text/plain charset=UTF-8';
|
||||||
|
add_header 'Content-Length' 0;
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
18
config/docker/nginx/nginx.conf
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
worker_processes 1;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
|
||||||
|
keepalive_timeout 65;
|
||||||
|
|
||||||
|
|
||||||
|
include /etc/nginx/security.conf;
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
}
|
||||||
9
config/docker/nginx/security.conf
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Add security headers
|
||||||
|
add_header 'X-Frame-Options' 'deny always' always;
|
||||||
|
add_header 'X-XSS-Protection' '"1; mode=block" always' always;
|
||||||
|
add_header 'X-Content-Type-Options' 'nosniff always' always;
|
||||||
|
add_header 'Referrer-Policy' 'strict-origin-when-cross-origin' always;
|
||||||
|
# Set access control header
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;
|
||||||
16
config/docker/nginx/templates/default.conf.template
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
server {
|
||||||
|
listen ${PORT};
|
||||||
|
server_name ${HOST};
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
include /etc/nginx/handle_options.conf;
|
||||||
|
try_files /index.html =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* ^/(.+\.[^/]+)$ {
|
||||||
|
include /etc/nginx/handle_options.conf;
|
||||||
|
try_files /$1 =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
config/docker/nginx/templates/default.prefix.conf.template
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
server {
|
||||||
|
listen ${PORT};
|
||||||
|
server_name ${HOST};
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
include /etc/nginx/handle_options.conf;
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /${BASE_PATH} {
|
||||||
|
include /etc/nginx/handle_options.conf;
|
||||||
|
try_files /index.html =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /${BASE_PATH}/ {
|
||||||
|
include /etc/nginx/handle_options.conf;
|
||||||
|
try_files /index.html =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* ^/${BASE_PATH}/(.+\.[^/]+)$ {
|
||||||
|
include /etc/nginx/handle_options.conf;
|
||||||
|
alias /usr/share/nginx/html/;
|
||||||
|
try_files /$1 =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
24
config/docker/static/index.prefix.tpl.html
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>${PAGE_TITLE}</title>
|
||||||
|
<link rel="icon" href="/${BASE_PATH}/${PAGE_FAVICON}" />
|
||||||
|
<link rel="stylesheet" href="/${BASE_PATH}/styles.css" />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<redoc
|
||||||
|
spec-url="${SPEC_URL}"
|
||||||
|
type-of-usage="docker"
|
||||||
|
routing-base-path="/${BASE_PATH}"
|
||||||
|
${REDOC_OPTIONS}
|
||||||
|
></redoc>
|
||||||
|
<script type="module" src="/${BASE_PATH}/redoc.standalone.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -1,19 +1,11 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>Redoc</title>
|
<title>${PAGE_TITLE}</title>
|
||||||
<style>
|
<link rel="icon" href="/${PAGE_FAVICON}" />
|
||||||
body {
|
<link rel="stylesheet" href="/styles.css" />
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
redoc {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700"
|
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
|
|
@ -21,6 +13,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<redoc id="example"></redoc>
|
<redoc spec-url="${SPEC_URL}" type-of-usage="docker" ${REDOC_OPTIONS}></redoc>
|
||||||
|
<script type="module" src="/redoc.standalone.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
8
config/docker/static/styles.css
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
redoc {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
import * as webpack from 'webpack';
|
|
||||||
|
|
||||||
export function webpackIgnore(regexp) {
|
|
||||||
return new webpack.NormalModuleReplacementPlugin(regexp, require.resolve('lodash.noop'));
|
|
||||||
}
|
|
||||||
27
custom.d.ts
vendored
|
|
@ -1,27 +0,0 @@
|
||||||
/// <reference path="typings/styled-patch.d.ts" />
|
|
||||||
|
|
||||||
declare module '*.json' {
|
|
||||||
const content: any;
|
|
||||||
export = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '*.svg' {
|
|
||||||
const content: string;
|
|
||||||
export default content;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '*.css' {
|
|
||||||
const content: string;
|
|
||||||
export default content;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare var __REDOC_VERSION__: string;
|
|
||||||
declare var __REDOC_REVISION__: string;
|
|
||||||
|
|
||||||
declare var reactHotLoaderGlobal: any;
|
|
||||||
|
|
||||||
interface Element {
|
|
||||||
scrollIntoViewIfNeeded(centerIfNeeded?: boolean): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
type GenericObject = Record<string, any>;
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
import { defineConfig } from 'cypress';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
fixturesFolder: false,
|
|
||||||
fileServerFolder: '.',
|
|
||||||
video: true,
|
|
||||||
projectId: 'z6eb6h',
|
|
||||||
viewportWidth: 1440,
|
|
||||||
viewportHeight: 720,
|
|
||||||
e2e: {
|
|
||||||
// We've imported your old cypress plugins here.
|
|
||||||
// You may want to clean this up later by importing these.
|
|
||||||
setupNodeEvents(on, config) {
|
|
||||||
return require('./e2e/plugins/index.js')(on, config);
|
|
||||||
},
|
|
||||||
excludeSpecPattern: '*.js.map',
|
|
||||||
specPattern: 'e2e/integration/**/*.{js,jsx,ts,tsx}',
|
|
||||||
supportFile: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
@ -1,221 +0,0 @@
|
||||||
/**
|
|
||||||
* Could not find ready-to-use component with required behaviour so
|
|
||||||
* I quickly hacked my own. Will refactor into separate npm package later
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as React from 'react';
|
|
||||||
import styled from '../src/styled-components';
|
|
||||||
|
|
||||||
const DropDownItem = styled.li<{ $active?: boolean }>`
|
|
||||||
${(props: any) => (props.$active ? 'background-color: #eee' : '')};
|
|
||||||
padding: 13px 16px;
|
|
||||||
&:hover {
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
cursor: pointer;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const DropDownList = styled.ul`
|
|
||||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12),
|
|
||||||
0 3px 1px -2px rgba(0, 0, 0, 0.2);
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 0 0 2px 2px;
|
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 200;
|
|
||||||
overflow: hidden;
|
|
||||||
position: absolute;
|
|
||||||
list-style: none;
|
|
||||||
margin: 4px 0 0 0;
|
|
||||||
padding: 5px 0;
|
|
||||||
font-family: Roboto, sans-serif;
|
|
||||||
overflow: hidden;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ComboBoxWrap = styled.div`
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
display: flex;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Input = styled.input`
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0 10px;
|
|
||||||
color: #555;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
|
|
||||||
font-size: 16px;
|
|
||||||
height: 28px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
vertical-align: middle;
|
|
||||||
line-height: 1;
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
|
||||||
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
border-color: #66afe9;
|
|
||||||
outline: 0;
|
|
||||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Button = styled.button`
|
|
||||||
background-color: #fff;
|
|
||||||
color: #333;
|
|
||||||
padding: 2px 10px;
|
|
||||||
touch-action: manipulation;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-left: 0;
|
|
||||||
font-size: 16px;
|
|
||||||
height: 28px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
vertical-align: middle;
|
|
||||||
line-height: 1;
|
|
||||||
outline: none;
|
|
||||||
width: 80px;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
@media screen and (max-width: 450px) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export interface ComboBoxProps {
|
|
||||||
onChange?: (val: string) => void;
|
|
||||||
options: Array<{ value: string; label: string }>;
|
|
||||||
placeholder?: string;
|
|
||||||
value?: string;
|
|
||||||
}
|
|
||||||
export interface ComboBoxState {
|
|
||||||
open: boolean;
|
|
||||||
value: string;
|
|
||||||
activeItemIdx: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class ComboBox extends React.Component<ComboBoxProps, ComboBoxState> {
|
|
||||||
state = {
|
|
||||||
open: false,
|
|
||||||
value: this.props.value || '',
|
|
||||||
activeItemIdx: -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
open = () => {
|
|
||||||
this.setState({
|
|
||||||
open: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
close = () => {
|
|
||||||
this.setState({
|
|
||||||
open: false,
|
|
||||||
activeItemIdx: -1,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = e => {
|
|
||||||
this.updateValue(e.currentTarget.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
updateValue(value) {
|
|
||||||
this.setState({
|
|
||||||
value,
|
|
||||||
activeItemIdx: -1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSelect(value: string) {
|
|
||||||
this.updateValue(value);
|
|
||||||
if (this.props.onChange) {
|
|
||||||
this.props.onChange(value);
|
|
||||||
}
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTryItClick = () => {
|
|
||||||
this.handleSelect(this.state.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
||||||
if (e.keyCode === 13) {
|
|
||||||
this.handleSelect(e.currentTarget.value);
|
|
||||||
} else if (e.keyCode === 40) {
|
|
||||||
const activeItemIdx = Math.min(this.props.options.length - 1, ++this.state.activeItemIdx);
|
|
||||||
this.setState({
|
|
||||||
open: true,
|
|
||||||
activeItemIdx,
|
|
||||||
value: this.props.options[activeItemIdx].value,
|
|
||||||
});
|
|
||||||
e.preventDefault();
|
|
||||||
} else if (e.keyCode === 38) {
|
|
||||||
const activeItemIdx = Math.max(0, --this.state.activeItemIdx);
|
|
||||||
this.setState({
|
|
||||||
activeItemIdx,
|
|
||||||
value: this.props.options[activeItemIdx].value,
|
|
||||||
});
|
|
||||||
e.preventDefault();
|
|
||||||
} else if (e.keyCode === 27) {
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleBlur = () => {
|
|
||||||
setTimeout(() => this.close(), 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleItemClick = (val, idx) => {
|
|
||||||
this.handleSelect(val);
|
|
||||||
this.setState({
|
|
||||||
activeItemIdx: idx,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
renderOption = (option: { value: string; label: string }, idx: number) => {
|
|
||||||
return (
|
|
||||||
<DropDownItem
|
|
||||||
$active={idx === this.state.activeItemIdx}
|
|
||||||
key={option.value}
|
|
||||||
// tslint:disable-next-line
|
|
||||||
onMouseDown={() => {
|
|
||||||
this.handleItemClick(option.value, idx);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<small>
|
|
||||||
<strong>{option.label}</strong>
|
|
||||||
</small>
|
|
||||||
<br />
|
|
||||||
{option.value}
|
|
||||||
</DropDownItem>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { open, value } = this.state;
|
|
||||||
const { options, placeholder } = this.props;
|
|
||||||
return (
|
|
||||||
<ComboBoxWrap>
|
|
||||||
<Input
|
|
||||||
placeholder={placeholder}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
value={value}
|
|
||||||
onFocus={this.open}
|
|
||||||
onBlur={this.handleBlur}
|
|
||||||
onKeyDown={this.handleKeyPress}
|
|
||||||
aria-label="URL to an OpenAPI definition to try"
|
|
||||||
/>
|
|
||||||
<Button onClick={this.handleTryItClick}> TRY IT </Button>
|
|
||||||
{open && <DropDownList>{options.map(this.renderOption)}</DropDownList>}
|
|
||||||
</ComboBoxWrap>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
27363
demo/big-openapi.json
BIN
demo/code-samples-demo.gif
Normal file
|
After Width: | Height: | Size: 888 KiB |
|
|
@ -1,52 +0,0 @@
|
||||||
import * as yaml from 'js-yaml';
|
|
||||||
import * as React from 'react';
|
|
||||||
import { ChangeEvent, RefObject, useRef } from 'react';
|
|
||||||
import styled from '../../src/styled-components';
|
|
||||||
|
|
||||||
const Button = styled.button`
|
|
||||||
background-color: #fff;
|
|
||||||
color: #333;
|
|
||||||
padding: 2px 10px;
|
|
||||||
touch-action: manipulation;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
font-size: 16px;
|
|
||||||
height: 28px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
vertical-align: middle;
|
|
||||||
line-height: 1;
|
|
||||||
outline: none;
|
|
||||||
white-space: nowrap;
|
|
||||||
@media (max-width: 699px) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
function FileInput(props: { onUpload }) {
|
|
||||||
const hiddenFileInput: RefObject<HTMLInputElement> = useRef<HTMLInputElement>(null);
|
|
||||||
|
|
||||||
const handleClick = () => {
|
|
||||||
if (hiddenFileInput && hiddenFileInput.current) {
|
|
||||||
hiddenFileInput.current.click();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const uploadFile = (event: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const file = (event.target as HTMLInputElement).files![0];
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = () => {
|
|
||||||
props.onUpload(yaml.load(reader.result));
|
|
||||||
};
|
|
||||||
reader.readAsText(file);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
<Button onClick={handleClick}>Upload a file</Button>
|
|
||||||
<input type="file" style={{ display: 'none' }} onChange={uploadFile} ref={hiddenFileInput} />
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default FileInput;
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Redoc Interactive Demo</title>
|
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content="Redoc Interactive Demo. OpenAPI-generated API Reference Documentation"
|
|
||||||
/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
|
|
||||||
<meta property="og:title" content="Redoc Interactive Demo" />
|
|
||||||
<meta
|
|
||||||
property="og:description"
|
|
||||||
content="Redoc Interactive Demo. OpenAPI-generated API Reference Documentation"
|
|
||||||
/>
|
|
||||||
<meta
|
|
||||||
property="og:image"
|
|
||||||
content="https://user-images.githubusercontent.com/3975738/37729752-8a9ea38a-2d46-11e8-8438-42ed26bf1751.png"
|
|
||||||
/>
|
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
redoc {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="container"></div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
(function (i, s, o, g, r, a, m) {
|
|
||||||
i['GoogleAnalyticsObject'] = r;
|
|
||||||
(i[r] =
|
|
||||||
i[r] ||
|
|
||||||
function () {
|
|
||||||
(i[r].q = i[r].q || []).push(arguments);
|
|
||||||
}),
|
|
||||||
(i[r].l = 1 * new Date());
|
|
||||||
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
|
|
||||||
a.async = 1;
|
|
||||||
a.src = g;
|
|
||||||
m.parentNode.insertBefore(a, m);
|
|
||||||
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
|
|
||||||
|
|
||||||
if (window.location.host === 'rebilly.github.io') {
|
|
||||||
ga('create', 'UA-81703547-1', 'auto');
|
|
||||||
ga('send', 'pageview');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
213
demo/index.tsx
|
|
@ -1,213 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { createRoot } from 'react-dom/client';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import { RedocStandalone } from '../src';
|
|
||||||
import ComboBox from './ComboBox';
|
|
||||||
import FileInput from './components/FileInput';
|
|
||||||
|
|
||||||
const DEFAULT_SPEC = 'museum.yaml';
|
|
||||||
const NEW_VERSION_PETSTORE = 'openapi-3-1.yaml';
|
|
||||||
|
|
||||||
const demos = [
|
|
||||||
{ value: DEFAULT_SPEC, label: 'Museum API' },
|
|
||||||
{ value: NEW_VERSION_PETSTORE, label: 'Petstore OpenAPI 3.1' },
|
|
||||||
{ value: 'https://api.apis.guru/v2/specs/instagram.com/1.0.0/swagger.yaml', label: 'Instagram' },
|
|
||||||
{
|
|
||||||
value: 'https://api.apis.guru/v2/specs/googleapis.com/calendar/v3/openapi.yaml',
|
|
||||||
label: 'Google Calendar',
|
|
||||||
},
|
|
||||||
{ value: 'https://api.apis.guru/v2/specs/slack.com/1.7.0/openapi.yaml', label: 'Slack' },
|
|
||||||
{ value: 'https://api.apis.guru/v2/specs/zoom.us/2.0.0/openapi.yaml', label: 'Zoom.us' },
|
|
||||||
];
|
|
||||||
|
|
||||||
class DemoApp extends React.Component<
|
|
||||||
Record<string, unknown>,
|
|
||||||
{ spec: object | undefined; specUrl: string; dropdownOpen: boolean; cors: boolean }
|
|
||||||
> {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
let parts = window.location.search.match(/url=([^&]+)/);
|
|
||||||
let url = DEFAULT_SPEC;
|
|
||||||
if (parts && parts.length > 1) {
|
|
||||||
url = decodeURIComponent(parts[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
parts = window.location.search.match(/[?&]nocors(&|#|$)/);
|
|
||||||
let cors = true;
|
|
||||||
if (parts && parts.length > 1) {
|
|
||||||
cors = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
spec: undefined,
|
|
||||||
specUrl: url,
|
|
||||||
dropdownOpen: false,
|
|
||||||
cors,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
handleUploadFile = (spec: object) => {
|
|
||||||
this.setState({
|
|
||||||
spec,
|
|
||||||
specUrl: '',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = (url: string) => {
|
|
||||||
if (url === NEW_VERSION_PETSTORE) {
|
|
||||||
this.setState({ cors: false });
|
|
||||||
0;
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
specUrl: url,
|
|
||||||
});
|
|
||||||
window.history.pushState(
|
|
||||||
undefined,
|
|
||||||
'',
|
|
||||||
updateQueryStringParameter(location.search, 'url', url),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
toggleCors = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const cors = e.currentTarget.checked;
|
|
||||||
this.setState({
|
|
||||||
cors,
|
|
||||||
});
|
|
||||||
window.history.pushState(
|
|
||||||
undefined,
|
|
||||||
'',
|
|
||||||
updateQueryStringParameter(location.search, 'nocors', cors ? undefined : ''),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { specUrl, cors } = this.state;
|
|
||||||
let proxiedUrl = specUrl;
|
|
||||||
if (specUrl !== DEFAULT_SPEC) {
|
|
||||||
proxiedUrl = cors
|
|
||||||
? 'https://cors.redoc.ly/' + new URL(specUrl, window.location.href).href
|
|
||||||
: specUrl;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Heading>
|
|
||||||
<a href=".">
|
|
||||||
<Logo
|
|
||||||
src="https://github.com/Redocly/redoc/raw/main/docs/images/redoc.png"
|
|
||||||
alt="Redoc logo"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<ControlsContainer>
|
|
||||||
<FileInput onUpload={this.handleUploadFile} />
|
|
||||||
<ComboBox
|
|
||||||
placeholder={'URL to a spec to try'}
|
|
||||||
options={demos}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
value={specUrl === DEFAULT_SPEC ? '' : specUrl}
|
|
||||||
/>
|
|
||||||
<CorsCheckbox title="Use CORS proxy">
|
|
||||||
<input id="cors_checkbox" type="checkbox" onChange={this.toggleCors} checked={cors} />
|
|
||||||
<label htmlFor="cors_checkbox">CORS</label>
|
|
||||||
</CorsCheckbox>
|
|
||||||
</ControlsContainer>
|
|
||||||
<iframe
|
|
||||||
src="https://ghbtns.com/github-btn.html?user=Redocly&repo=redoc&type=star&count=true&size=large"
|
|
||||||
frameBorder="0"
|
|
||||||
scrolling="0"
|
|
||||||
width="160px"
|
|
||||||
height="30px"
|
|
||||||
/>
|
|
||||||
</Heading>
|
|
||||||
<RedocStandalone
|
|
||||||
spec={this.state.spec}
|
|
||||||
specUrl={proxiedUrl}
|
|
||||||
options={{ scrollYOffset: 'nav', sanitize: true }}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ====== Styled components ====== */
|
|
||||||
|
|
||||||
const ControlsContainer = styled.div`
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
flex: 1;
|
|
||||||
margin: 0 15px;
|
|
||||||
align-items: center;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const CorsCheckbox = styled.div`
|
|
||||||
margin-left: 10px;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
label {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 550px) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Heading = styled.nav`
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background: white;
|
|
||||||
border-bottom: 1px solid #cccccc;
|
|
||||||
z-index: 10;
|
|
||||||
padding: 5px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
font-family: Roboto, sans-serif;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Logo = styled.img`
|
|
||||||
height: 40px;
|
|
||||||
width: 124px;
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 15px;
|
|
||||||
|
|
||||||
@media screen and (max-width: 950px) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const container = document.getElementById('container');
|
|
||||||
const root = createRoot(container!);
|
|
||||||
root.render(<DemoApp />);
|
|
||||||
|
|
||||||
/* ====== Helpers ====== */
|
|
||||||
function updateQueryStringParameter(uri, key, value) {
|
|
||||||
const keyValue = value === '' ? key : key + '=' + value;
|
|
||||||
const re = new RegExp('([?|&])' + key + '=?.*?(&|#|$)', 'i');
|
|
||||||
if (uri.match(re)) {
|
|
||||||
if (value !== undefined) {
|
|
||||||
return uri.replace(re, '$1' + keyValue + '$2');
|
|
||||||
} else {
|
|
||||||
return uri.replace(re, (_, separator: string, rest: string) => {
|
|
||||||
if (rest.startsWith('&')) {
|
|
||||||
rest = rest.substring(1);
|
|
||||||
}
|
|
||||||
return separator === '&' ? rest : separator + rest;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (value === undefined) {
|
|
||||||
return uri;
|
|
||||||
}
|
|
||||||
let hash = '';
|
|
||||||
if (uri.indexOf('#') !== -1) {
|
|
||||||
hash = uri.replace(/.*#/, '#');
|
|
||||||
uri = uri.replace(/#.*/, '');
|
|
||||||
}
|
|
||||||
const separator = uri.indexOf('?') !== -1 ? '&' : '?';
|
|
||||||
return uri + separator + keyValue + hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
|
@ -1,22 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { createRoot } from 'react-dom/client';
|
|
||||||
import type { RedocRawOptions } from '../../src/services/RedocNormalizedOptions';
|
|
||||||
import { RedocStandalone } from '../../src';
|
|
||||||
|
|
||||||
const big = window.location.search.indexOf('big') > -1;
|
|
||||||
const swagger = window.location.search.indexOf('swagger') > -1;
|
|
||||||
|
|
||||||
const userUrl = window.location.search.match(/url=(.*)$/);
|
|
||||||
|
|
||||||
const specUrl =
|
|
||||||
(userUrl && userUrl[1]) || (swagger ? 'museum.yaml' : big ? 'big-openapi.json' : 'museum.yaml');
|
|
||||||
|
|
||||||
const options: RedocRawOptions = {
|
|
||||||
nativeScrollbars: false,
|
|
||||||
maxDisplayedEnumValues: 3,
|
|
||||||
schemaDefinitionsTagName: 'schemas',
|
|
||||||
};
|
|
||||||
|
|
||||||
const container = document.getElementById('example');
|
|
||||||
const root = createRoot(container!);
|
|
||||||
root.render(<RedocStandalone specUrl={specUrl} options={options} />);
|
|
||||||
|
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 306 KiB |
|
|
@ -1,65 +0,0 @@
|
||||||
import { renderToString } from 'react-dom/server';
|
|
||||||
import * as React from 'react';
|
|
||||||
import { ServerStyleSheet } from 'styled-components';
|
|
||||||
import { Redoc, createStore } from '../../';
|
|
||||||
import { readFileSync } from 'fs';
|
|
||||||
import { resolve } from 'path';
|
|
||||||
|
|
||||||
const yaml = require('js-yaml');
|
|
||||||
const http = require('http');
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const PORT = 9999;
|
|
||||||
|
|
||||||
const server = http.createServer(async (request, response) => {
|
|
||||||
console.time('request ' + request.url);
|
|
||||||
if (request.url === '/redoc.standalone.js') {
|
|
||||||
fs.createReadStream('bundles/redoc.standalone.js', 'utf8').pipe(response);
|
|
||||||
} else if (request.url === '/') {
|
|
||||||
const spec = yaml.load(readFileSync(resolve(__dirname, '../openapi.yaml'), 'utf-8'));
|
|
||||||
const store = await createStore(spec, 'path/to/spec.yaml');
|
|
||||||
|
|
||||||
const sheet = new ServerStyleSheet();
|
|
||||||
|
|
||||||
const html = renderToString(sheet.collectStyles(React.createElement(Redoc, { store })));
|
|
||||||
const css = sheet.getStyleTags();
|
|
||||||
|
|
||||||
const res = `<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf8" />
|
|
||||||
<title>ReDoc</title>
|
|
||||||
<!-- needed for adaptive design -->
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script src="redoc.standalone.js"></script>
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
|
||||||
${css}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const state = ${JSON.stringify(await store.toJS())};
|
|
||||||
Redoc.hydrate(state, document.getElementById('redoc'));
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<div id="redoc">${html}</div>
|
|
||||||
</body>
|
|
||||||
</html>`;
|
|
||||||
response.writeHead(200, { 'Content-Length': res.length });
|
|
||||||
response.write(res);
|
|
||||||
response.end();
|
|
||||||
} else {
|
|
||||||
response.writeHead(404);
|
|
||||||
response.write('Not found');
|
|
||||||
response.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
console.timeEnd('request ' + request.url);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(PORT, () => console.log(`Server started: http://127.0.0.1:${PORT}`));
|
|
||||||
|
|
@ -1,867 +0,0 @@
|
||||||
swagger: '2.0'
|
|
||||||
schemes:
|
|
||||||
- http
|
|
||||||
- https
|
|
||||||
host: petstore.swagger.io
|
|
||||||
basePath: /v2
|
|
||||||
info:
|
|
||||||
description: |
|
|
||||||
This is a sample server Petstore server.
|
|
||||||
You can find out more about Swagger at
|
|
||||||
[http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).
|
|
||||||
For this sample, you can use the api key `special-key` to test the authorization filters.
|
|
||||||
# Introduction
|
|
||||||
This API is documented in **OpenAPI format** and is based on
|
|
||||||
[Petstore sample](http://petstore.swagger.io/) provided by [swagger.io](http://swagger.io) team.
|
|
||||||
It was **extended** to illustrate features of [generator-openapi-repo](https://github.com/Rebilly/generator-openapi-repo)
|
|
||||||
tool and [ReDoc](https://github.com/Redocly/redoc) documentation. In addition to standard
|
|
||||||
OpenAPI syntax we use a few [vendor extensions](https://github.com/Redocly/redoc/blob/main/docs/redoc-vendor-extensions.md).
|
|
||||||
# OpenAPI Specification
|
|
||||||
This API is documented in **OpenAPI format** and is based on
|
|
||||||
[Petstore sample](http://petstore.swagger.io/) provided by [swagger.io](http://swagger.io) team.
|
|
||||||
It was **extended** to illustrate features of [generator-openapi-repo](https://github.com/Rebilly/generator-openapi-repo)
|
|
||||||
tool and [ReDoc](https://github.com/Redocly/redoc) documentation. In addition to standard
|
|
||||||
OpenAPI syntax we use a few [vendor extensions](https://github.com/Redocly/redoc/blob/main/docs/redoc-vendor-extensions.md).
|
|
||||||
# Cross-Origin Resource Sharing
|
|
||||||
This API features Cross-Origin Resource Sharing (CORS) implemented in compliance with [W3C spec](https://www.w3.org/TR/cors/).
|
|
||||||
And that allows cross-domain communication from the browser.
|
|
||||||
All responses have a wildcard same-origin which makes them completely public and accessible to everyone, including any code on any site.
|
|
||||||
# Authentication
|
|
||||||
Petstore offers two forms of authentication:
|
|
||||||
- API Key
|
|
||||||
- OAuth2
|
|
||||||
|
|
||||||
OAuth2 - an open protocol to allow secure authorization in a simple
|
|
||||||
and standard method from web, mobile and desktop applications.
|
|
||||||
<!-- ReDoc-Inject: <security-definitions> -->
|
|
||||||
version: 1.0.0
|
|
||||||
title: Swagger Petstore
|
|
||||||
termsOfService: 'http://swagger.io/terms/'
|
|
||||||
contact:
|
|
||||||
email: apiteam@swagger.io
|
|
||||||
url: https://github.com/Redocly/redoc
|
|
||||||
x-logo:
|
|
||||||
url: 'https://redocly.github.io/redoc/petstore-logo.png'
|
|
||||||
altText: Petstore logo
|
|
||||||
license:
|
|
||||||
name: Apache 2.0
|
|
||||||
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
|
|
||||||
externalDocs:
|
|
||||||
description: Find out how to create Github repo for your OpenAPI spec.
|
|
||||||
url: 'https://github.com/Rebilly/generator-openapi-repo'
|
|
||||||
tags:
|
|
||||||
- name: pet
|
|
||||||
description: Everything about your Pets
|
|
||||||
- name: store
|
|
||||||
description: Access to Petstore orders
|
|
||||||
- name: user
|
|
||||||
description: Operations about user
|
|
||||||
x-tagGroups:
|
|
||||||
- name: General
|
|
||||||
tags:
|
|
||||||
- pet
|
|
||||||
- store
|
|
||||||
- name: User Management
|
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
securityDefinitions:
|
|
||||||
petstore_auth:
|
|
||||||
description: |
|
|
||||||
Get access to data while protecting your account credentials.
|
|
||||||
OAuth2 is also a safer and more secure way to give you access.
|
|
||||||
type: oauth2
|
|
||||||
authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog'
|
|
||||||
flow: implicit
|
|
||||||
scopes:
|
|
||||||
'write:pets': modify pets in your account
|
|
||||||
'read:pets': read your pets
|
|
||||||
api_key:
|
|
||||||
description: |
|
|
||||||
For this sample, you can use the api key `special-key` to test the authorization filters.
|
|
||||||
type: apiKey
|
|
||||||
name: api_key
|
|
||||||
in: header
|
|
||||||
x-servers:
|
|
||||||
- url: //petstore.swagger.io/v2
|
|
||||||
description: Default server
|
|
||||||
- url: //petstore.swagger.io/sandbox
|
|
||||||
description: Sandbox server
|
|
||||||
paths:
|
|
||||||
/pet:
|
|
||||||
post:
|
|
||||||
tags:
|
|
||||||
- pet
|
|
||||||
summary: Add a new pet to the store
|
|
||||||
description: Add new pet to the store inventory.
|
|
||||||
operationId: addPet
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
- application/xml
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: Pet object that needs to be added to the store
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/Pet'
|
|
||||||
responses:
|
|
||||||
'405':
|
|
||||||
description: Invalid input
|
|
||||||
security:
|
|
||||||
- petstore_auth:
|
|
||||||
- 'write:pets'
|
|
||||||
- 'read:pets'
|
|
||||||
x-code-samples:
|
|
||||||
- lang: 'C#'
|
|
||||||
source: |
|
|
||||||
PetStore.v1.Pet pet = new PetStore.v1.Pet();
|
|
||||||
pet.setApiKey("your api key");
|
|
||||||
pet.petType = PetStore.v1.Pet.TYPE_DOG;
|
|
||||||
pet.name = "Rex";
|
|
||||||
// set other fields
|
|
||||||
PetStoreResponse response = pet.create();
|
|
||||||
if (response.statusCode == HttpStatusCode.Created)
|
|
||||||
{
|
|
||||||
// Successfully created
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Something wrong -- check response for errors
|
|
||||||
Console.WriteLine(response.getRawResponse());
|
|
||||||
}
|
|
||||||
- lang: PHP
|
|
||||||
source: "$form = new \\PetStore\\Entities\\Pet();\n$form->setPetType(\"Dog\");\n$form->setName(\"Rex\");\n// set other fields\ntry {\n $pet = $client->pets()->create($form);\n} catch (UnprocessableEntityException $e) {\n var_dump($e->getErrors());\n}\n"
|
|
||||||
put:
|
|
||||||
tags:
|
|
||||||
- pet
|
|
||||||
summary: Update an existing pet
|
|
||||||
description: ''
|
|
||||||
operationId: updatePet
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
- application/xml
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: Pet object that needs to be added to the store
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/Pet'
|
|
||||||
responses:
|
|
||||||
'400':
|
|
||||||
description: Invalid ID supplied
|
|
||||||
'404':
|
|
||||||
description: Pet not found
|
|
||||||
'405':
|
|
||||||
description: Validation exception
|
|
||||||
security:
|
|
||||||
- petstore_auth:
|
|
||||||
- 'write:pets'
|
|
||||||
- 'read:pets'
|
|
||||||
x-code-samples:
|
|
||||||
- lang: PHP
|
|
||||||
source: "$form = new \\PetStore\\Entities\\Pet();\n$form->setPetId(1);\n$form->setPetType(\"Dog\");\n$form->setName(\"Rex\");\n// set other fields\ntry {\n $pet = $client->pets()->update($form);\n} catch (UnprocessableEntityException $e) {\n var_dump($e->getErrors());\n}\n"
|
|
||||||
'/pet/{petId}':
|
|
||||||
get:
|
|
||||||
tags:
|
|
||||||
- pet
|
|
||||||
summary: Find pet by ID
|
|
||||||
description: Returns a single pet
|
|
||||||
operationId: getPetById
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: petId
|
|
||||||
in: path
|
|
||||||
description: ID of pet to return
|
|
||||||
required: true
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: successful operation
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/Pet'
|
|
||||||
'400':
|
|
||||||
description: Invalid ID supplied
|
|
||||||
'404':
|
|
||||||
description: Pet not found
|
|
||||||
security:
|
|
||||||
- api_key: []
|
|
||||||
post:
|
|
||||||
tags:
|
|
||||||
- pet
|
|
||||||
summary: Updates a pet in the store with form data
|
|
||||||
description: ''
|
|
||||||
operationId: updatePetWithForm
|
|
||||||
consumes:
|
|
||||||
- application/x-www-form-urlencoded
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: petId
|
|
||||||
in: path
|
|
||||||
description: ID of pet that needs to be updated
|
|
||||||
required: true
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
- name: name
|
|
||||||
in: formData
|
|
||||||
description: Updated name of the pet
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
- name: status
|
|
||||||
in: formData
|
|
||||||
description: Updated status of the pet
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'405':
|
|
||||||
description: Invalid input
|
|
||||||
security:
|
|
||||||
- petstore_auth:
|
|
||||||
- 'write:pets'
|
|
||||||
- 'read:pets'
|
|
||||||
delete:
|
|
||||||
tags:
|
|
||||||
- pet
|
|
||||||
summary: Deletes a pet
|
|
||||||
description: ''
|
|
||||||
operationId: deletePet
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: api_key
|
|
||||||
in: header
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
x-example: Bearer <TOKEN>
|
|
||||||
- name: petId
|
|
||||||
in: path
|
|
||||||
description: Pet id to delete
|
|
||||||
required: true
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
responses:
|
|
||||||
'400':
|
|
||||||
description: Invalid pet value
|
|
||||||
security:
|
|
||||||
- petstore_auth:
|
|
||||||
- 'write:pets'
|
|
||||||
- 'read:pets'
|
|
||||||
'/pet/{petId}/uploadImage':
|
|
||||||
post:
|
|
||||||
tags:
|
|
||||||
- pet
|
|
||||||
summary: uploads an image
|
|
||||||
description: ''
|
|
||||||
operationId: uploadFile
|
|
||||||
consumes:
|
|
||||||
- multipart/form-data
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: petId
|
|
||||||
in: path
|
|
||||||
description: ID of pet to update
|
|
||||||
required: true
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
- name: additionalMetadata
|
|
||||||
in: formData
|
|
||||||
description: Additional data to pass to server
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
- name: file
|
|
||||||
in: formData
|
|
||||||
description: file to upload
|
|
||||||
required: false
|
|
||||||
type: file
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: successful operation
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/ApiResponse'
|
|
||||||
security:
|
|
||||||
- petstore_auth:
|
|
||||||
- 'write:pets'
|
|
||||||
- 'read:pets'
|
|
||||||
/pet/findByStatus:
|
|
||||||
get:
|
|
||||||
tags:
|
|
||||||
- pet
|
|
||||||
summary: Finds Pets by status
|
|
||||||
description: Multiple status values can be provided with comma separated strings
|
|
||||||
operationId: findPetsByStatus
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: status
|
|
||||||
in: query
|
|
||||||
description: Status values that need to be considered for filter
|
|
||||||
required: true
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- available
|
|
||||||
- pending
|
|
||||||
- sold
|
|
||||||
default: available
|
|
||||||
collectionFormat: csv
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: successful operation
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/definitions/Pet'
|
|
||||||
'400':
|
|
||||||
description: Invalid status value
|
|
||||||
security:
|
|
||||||
- petstore_auth:
|
|
||||||
- 'write:pets'
|
|
||||||
- 'read:pets'
|
|
||||||
/pet/findByTags:
|
|
||||||
get:
|
|
||||||
tags:
|
|
||||||
- pet
|
|
||||||
summary: Finds Pets by tags
|
|
||||||
description: 'Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.'
|
|
||||||
operationId: findPetsByTags
|
|
||||||
deprecated: true
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: tags
|
|
||||||
in: query
|
|
||||||
description: Tags to filter by
|
|
||||||
required: true
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
collectionFormat: csv
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: successful operation
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/definitions/Pet'
|
|
||||||
'400':
|
|
||||||
description: Invalid tag value
|
|
||||||
security:
|
|
||||||
- petstore_auth:
|
|
||||||
- 'write:pets'
|
|
||||||
- 'read:pets'
|
|
||||||
/store/inventory:
|
|
||||||
get:
|
|
||||||
tags:
|
|
||||||
- store
|
|
||||||
summary: Returns pet inventories by status
|
|
||||||
description: Returns a map of status codes to quantities
|
|
||||||
operationId: getInventory
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
parameters: []
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: successful operation
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
additionalProperties:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
security:
|
|
||||||
- api_key: []
|
|
||||||
/store/order:
|
|
||||||
post:
|
|
||||||
tags:
|
|
||||||
- store
|
|
||||||
summary: Place an order for a pet
|
|
||||||
description: ''
|
|
||||||
operationId: placeOrder
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: order placed for purchasing the pet
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/Order'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: successful operation
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/Order'
|
|
||||||
'400':
|
|
||||||
description: Invalid Order
|
|
||||||
'/store/order/{orderId}':
|
|
||||||
get:
|
|
||||||
tags:
|
|
||||||
- store
|
|
||||||
summary: Find purchase order by ID
|
|
||||||
description: 'For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions'
|
|
||||||
operationId: getOrderById
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: orderId
|
|
||||||
in: path
|
|
||||||
description: ID of pet that needs to be fetched
|
|
||||||
required: true
|
|
||||||
type: integer
|
|
||||||
maximum: 5
|
|
||||||
minimum: 1
|
|
||||||
format: int64
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: successful operation
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/Order'
|
|
||||||
'400':
|
|
||||||
description: Invalid ID supplied
|
|
||||||
'404':
|
|
||||||
description: Order not found
|
|
||||||
delete:
|
|
||||||
tags:
|
|
||||||
- store
|
|
||||||
summary: Delete purchase order by ID
|
|
||||||
description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
|
||||||
operationId: deleteOrder
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: orderId
|
|
||||||
in: path
|
|
||||||
description: ID of the order that needs to be deleted
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
minimum: 1
|
|
||||||
responses:
|
|
||||||
'400':
|
|
||||||
description: Invalid ID supplied
|
|
||||||
'404':
|
|
||||||
description: Order not found
|
|
||||||
/user:
|
|
||||||
post:
|
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
summary: Create user
|
|
||||||
description: This can only be done by the logged in user.
|
|
||||||
operationId: createUser
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: Created user object
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/User'
|
|
||||||
responses:
|
|
||||||
default:
|
|
||||||
description: successful operation
|
|
||||||
'/user/{username}':
|
|
||||||
get:
|
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
summary: Get user by user name
|
|
||||||
description: ''
|
|
||||||
operationId: getUserByName
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: username
|
|
||||||
in: path
|
|
||||||
description: 'The name that needs to be fetched. Use user1 for testing. '
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: successful operation
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/User'
|
|
||||||
'400':
|
|
||||||
description: Invalid username supplied
|
|
||||||
'404':
|
|
||||||
description: User not found
|
|
||||||
put:
|
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
summary: Updated user
|
|
||||||
description: This can only be done by the logged in user.
|
|
||||||
operationId: updateUser
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: username
|
|
||||||
in: path
|
|
||||||
description: name that need to be deleted
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: Updated user object
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/User'
|
|
||||||
responses:
|
|
||||||
'400':
|
|
||||||
description: Invalid user supplied
|
|
||||||
'404':
|
|
||||||
description: User not found
|
|
||||||
delete:
|
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
summary: Delete user
|
|
||||||
description: This can only be done by the logged in user.
|
|
||||||
operationId: deleteUser
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: username
|
|
||||||
in: path
|
|
||||||
description: The name that needs to be deleted
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'400':
|
|
||||||
description: Invalid username supplied
|
|
||||||
'404':
|
|
||||||
description: User not found
|
|
||||||
/user/createWithArray:
|
|
||||||
post:
|
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
summary: Creates list of users with given input array
|
|
||||||
description: ''
|
|
||||||
operationId: createUsersWithArrayInput
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: List of user object
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/definitions/User'
|
|
||||||
responses:
|
|
||||||
default:
|
|
||||||
description: successful operation
|
|
||||||
/user/createWithList:
|
|
||||||
post:
|
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
summary: Creates list of users with given input array
|
|
||||||
description: ''
|
|
||||||
operationId: createUsersWithListInput
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: List of user object
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/definitions/User'
|
|
||||||
responses:
|
|
||||||
default:
|
|
||||||
description: successful operation
|
|
||||||
/user/login:
|
|
||||||
get:
|
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
summary: Logs user into the system
|
|
||||||
description: ''
|
|
||||||
operationId: loginUser
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: username
|
|
||||||
in: query
|
|
||||||
description: The user name for login
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
- name: password
|
|
||||||
in: query
|
|
||||||
description: The password for login in clear text
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: successful operation
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
examples:
|
|
||||||
application/json: OK
|
|
||||||
application/xml: <message> OK </message>
|
|
||||||
text/plain: OK
|
|
||||||
headers:
|
|
||||||
X-Rate-Limit:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
description: calls per hour allowed by the user
|
|
||||||
X-Expires-After:
|
|
||||||
type: string
|
|
||||||
format: date-time
|
|
||||||
description: date in UTC when token expires
|
|
||||||
'400':
|
|
||||||
description: Invalid username/password supplied
|
|
||||||
/user/logout:
|
|
||||||
get:
|
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
summary: Logs out current logged in user session
|
|
||||||
description: ''
|
|
||||||
operationId: logoutUser
|
|
||||||
produces:
|
|
||||||
- application/xml
|
|
||||||
- application/json
|
|
||||||
parameters: []
|
|
||||||
responses:
|
|
||||||
default:
|
|
||||||
description: successful operation
|
|
||||||
definitions:
|
|
||||||
ApiResponse:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
Cat:
|
|
||||||
description: A representation of a cat
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/definitions/Pet'
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
huntingSkill:
|
|
||||||
type: string
|
|
||||||
description: The measured skill for hunting
|
|
||||||
default: lazy
|
|
||||||
enum:
|
|
||||||
- clueless
|
|
||||||
- lazy
|
|
||||||
- adventurous
|
|
||||||
- aggressive
|
|
||||||
required:
|
|
||||||
- huntingSkill
|
|
||||||
Category:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
description: Category ID
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/definitions/Id'
|
|
||||||
name:
|
|
||||||
description: Category name
|
|
||||||
type: string
|
|
||||||
minLength: 1
|
|
||||||
sub:
|
|
||||||
description: Test Sub Category
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
prop1:
|
|
||||||
type: string
|
|
||||||
description: Dumb Property
|
|
||||||
xml:
|
|
||||||
name: Category
|
|
||||||
Dog:
|
|
||||||
description: A representation of a dog
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/definitions/Pet'
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
packSize:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
description: The size of the pack the dog is from
|
|
||||||
default: 1
|
|
||||||
minimum: 1
|
|
||||||
required:
|
|
||||||
- packSize
|
|
||||||
HoneyBee:
|
|
||||||
description: A representation of a honey bee
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/definitions/Pet'
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
honeyPerDay:
|
|
||||||
type: number
|
|
||||||
description: Average amount of honey produced per day in ounces
|
|
||||||
example: 3.14
|
|
||||||
required:
|
|
||||||
- honeyPerDay
|
|
||||||
Id:
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
Order:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
description: Order ID
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/definitions/Id'
|
|
||||||
petId:
|
|
||||||
description: Pet ID
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/definitions/Id'
|
|
||||||
quantity:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
minimum: 1
|
|
||||||
default: 1
|
|
||||||
shipDate:
|
|
||||||
description: Estimated ship date
|
|
||||||
type: string
|
|
||||||
format: date-time
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
description: Order Status
|
|
||||||
enum:
|
|
||||||
- placed
|
|
||||||
- approved
|
|
||||||
- delivered
|
|
||||||
complete:
|
|
||||||
description: Indicates whenever order was completed or not
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
xml:
|
|
||||||
name: Order
|
|
||||||
Pet:
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
- photoUrls
|
|
||||||
discriminator: petType
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
description: Pet ID
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/definitions/Id'
|
|
||||||
category:
|
|
||||||
description: Categories this pet belongs to
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/definitions/Category'
|
|
||||||
name:
|
|
||||||
description: The name given to a pet
|
|
||||||
type: string
|
|
||||||
example: Guru
|
|
||||||
photoUrls:
|
|
||||||
description: The list of URL to a cute photos featuring pet
|
|
||||||
type: array
|
|
||||||
default: []
|
|
||||||
xml:
|
|
||||||
name: photoUrl
|
|
||||||
wrapped: true
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
format: url
|
|
||||||
tags:
|
|
||||||
description: Tags attached to the pet
|
|
||||||
type: array
|
|
||||||
xml:
|
|
||||||
name: tag
|
|
||||||
wrapped: true
|
|
||||||
items:
|
|
||||||
$ref: '#/definitions/Tag'
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
description: Pet status in the store
|
|
||||||
enum:
|
|
||||||
- available
|
|
||||||
- pending
|
|
||||||
- sold
|
|
||||||
petType:
|
|
||||||
description: Type of a pet
|
|
||||||
type: string
|
|
||||||
xml:
|
|
||||||
name: Pet
|
|
||||||
Tag:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
description: Tag ID
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/definitions/Id'
|
|
||||||
name:
|
|
||||||
description: Tag name
|
|
||||||
type: string
|
|
||||||
minLength: 1
|
|
||||||
xml:
|
|
||||||
name: Tag
|
|
||||||
User:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
description: User ID
|
|
||||||
$ref: '#/definitions/Id'
|
|
||||||
username:
|
|
||||||
description: User supplied username
|
|
||||||
type: string
|
|
||||||
minLength: 4
|
|
||||||
example: John78
|
|
||||||
firstName:
|
|
||||||
description: User first name
|
|
||||||
type: string
|
|
||||||
minLength: 1
|
|
||||||
example: John
|
|
||||||
lastName:
|
|
||||||
description: User last name
|
|
||||||
type: string
|
|
||||||
minLength: 1
|
|
||||||
example: Smith
|
|
||||||
email:
|
|
||||||
description: User email address
|
|
||||||
type: string
|
|
||||||
format: email
|
|
||||||
example: john.smith@example.com
|
|
||||||
password:
|
|
||||||
type: string
|
|
||||||
description: 'User password, MUST contain a mix of upper and lower case letters, as well as digits'
|
|
||||||
format: password
|
|
||||||
minLength: 8
|
|
||||||
pattern: '(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])'
|
|
||||||
example: drowssaP123
|
|
||||||
phone:
|
|
||||||
description: User phone number in international format
|
|
||||||
type: string
|
|
||||||
pattern: "^\\+(?:[0-9]-?){6,14}[0-9]$"
|
|
||||||
example: +1-202-555-0192
|
|
||||||
x-nullable: true
|
|
||||||
userStatus:
|
|
||||||
description: User status
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
xml:
|
|
||||||
name: User
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
import * as CopyWebpackPlugin from 'copy-webpack-plugin';
|
|
||||||
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
|
||||||
import * as HtmlWebpackPlugin from 'html-webpack-plugin';
|
|
||||||
import { resolve } from 'path';
|
|
||||||
import * as webpack from 'webpack';
|
|
||||||
import { webpackIgnore } from '../config/webpack-utils';
|
|
||||||
|
|
||||||
const VERSION = JSON.stringify(require('../package.json').version);
|
|
||||||
const REVISION = JSON.stringify(
|
|
||||||
require('child_process').execSync('git rev-parse --short HEAD').toString().trim(),
|
|
||||||
);
|
|
||||||
|
|
||||||
function root(filename) {
|
|
||||||
return resolve(__dirname + '/' + filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default (env: { playground?: boolean; bench?: boolean } = {}) => ({
|
|
||||||
entry: [
|
|
||||||
root('../src/polyfills.ts'),
|
|
||||||
root(
|
|
||||||
env.playground
|
|
||||||
? 'playground/hmr-playground.tsx'
|
|
||||||
: env.bench
|
|
||||||
? '../benchmark/index.tsx'
|
|
||||||
: 'index.tsx',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
target: 'web',
|
|
||||||
output: {
|
|
||||||
filename: 'redoc-demo.bundle.js',
|
|
||||||
path: root('dist'),
|
|
||||||
globalObject: 'this',
|
|
||||||
},
|
|
||||||
|
|
||||||
devServer: {
|
|
||||||
static: __dirname,
|
|
||||||
port: 9090,
|
|
||||||
hot: true,
|
|
||||||
historyApiFallback: true,
|
|
||||||
open: true,
|
|
||||||
},
|
|
||||||
stats: {
|
|
||||||
children: true,
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.ts', '.tsx', '.js', '.json'],
|
|
||||||
fallback: {
|
|
||||||
path: require.resolve('path-browserify'),
|
|
||||||
buffer: require.resolve('buffer'),
|
|
||||||
http: false,
|
|
||||||
fs: false,
|
|
||||||
os: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
performance: false,
|
|
||||||
|
|
||||||
externals: {
|
|
||||||
esprima: 'esprima',
|
|
||||||
'node-fetch': 'null',
|
|
||||||
'node-fetch-h2': 'null',
|
|
||||||
yaml: 'null',
|
|
||||||
'safe-json-stringify': 'null',
|
|
||||||
},
|
|
||||||
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{ test: [/\.eot$/, /\.gif$/, /\.woff$/, /\.svg$/, /\.ttf$/], use: 'null-loader' },
|
|
||||||
{
|
|
||||||
test: /\.(tsx?|[cm]?js)$/,
|
|
||||||
loader: 'esbuild-loader',
|
|
||||||
options: {
|
|
||||||
target: 'es2015',
|
|
||||||
tsconfigRaw: require('../tsconfig.json'),
|
|
||||||
},
|
|
||||||
exclude: [/node_modules/],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: [
|
|
||||||
'style-loader',
|
|
||||||
'css-loader',
|
|
||||||
{
|
|
||||||
loader: 'esbuild-loader',
|
|
||||||
options: {
|
|
||||||
minify: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
__REDOC_VERSION__: VERSION,
|
|
||||||
__REDOC_REVISION__: REVISION,
|
|
||||||
'process.env': '{}',
|
|
||||||
'process.platform': '"browser"',
|
|
||||||
'process.stdout': 'null',
|
|
||||||
}),
|
|
||||||
// new webpack.NamedModulesPlugin(),
|
|
||||||
// new webpack.optimize.ModuleConcatenationPlugin(),
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
template: env.playground
|
|
||||||
? 'demo/playground/index.html'
|
|
||||||
: env.bench
|
|
||||||
? 'benchmark/index.html'
|
|
||||||
: 'demo/index.html',
|
|
||||||
}),
|
|
||||||
new webpack.ProvidePlugin({
|
|
||||||
Buffer: ['buffer', 'Buffer'],
|
|
||||||
}),
|
|
||||||
new ForkTsCheckerWebpackPlugin({ logger: { infrastructure: 'silent', issues: 'console' } }),
|
|
||||||
webpackIgnore(/js-yaml\/dumper\.js$/),
|
|
||||||
webpackIgnore(/json-schema-ref-parser\/lib\/dereference\.js/),
|
|
||||||
webpackIgnore(/^\.\/SearchWorker\.worker$/),
|
|
||||||
new CopyWebpackPlugin({
|
|
||||||
patterns: ['demo/museum.yaml'],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
311
docs/config.md
|
|
@ -1,311 +0,0 @@
|
||||||
# Configure Redoc
|
|
||||||
|
|
||||||
Getting your documentation just right is important, and Redoc comes with many configuration options to help you succeed in that mission.
|
|
||||||
|
|
||||||
Each deployment type has documentation on how to configure options for that type of Redoc project. This page lists all the options you can use with Redoc.
|
|
||||||
|
|
||||||
**Versions: 2.x**
|
|
||||||
|
|
||||||
{% admonition type="success" name="Client-side configuration" %}
|
|
||||||
|
|
||||||
Using Redoc as a standalone (HTML or React) tool, these options must be presented in [kebab case](https://en.wikipedia.org/wiki/Letter_case#Kebab_case).
|
|
||||||
For example, `scrollYOffset` becomes `scroll-y-offset`, and `expandResponses` becomes `expand-responses`.
|
|
||||||
|
|
||||||
{% /admonition %}
|
|
||||||
|
|
||||||
## Functional settings
|
|
||||||
|
|
||||||
|
|
||||||
### disableSearch
|
|
||||||
|
|
||||||
Disables search indexing and hides the search box from the API documentation page.
|
|
||||||
|
|
||||||
### minCharacterLengthToInitSearch
|
|
||||||
|
|
||||||
Sets the minimum amount of characters that need to be typed into the search dialog to initiate the search.
|
|
||||||
|
|
||||||
_Default: 3_
|
|
||||||
|
|
||||||
### hideDownloadButtons
|
|
||||||
|
|
||||||
Hides the 'Download' button for saving the API definition source file. **This setting does not make the API definition private**; it just hides the button.
|
|
||||||
|
|
||||||
### hideLoading
|
|
||||||
|
|
||||||
Hides the loading animation. Does not apply to CLI or Workflows-rendered docs.
|
|
||||||
|
|
||||||
### hideSchemaTitles
|
|
||||||
|
|
||||||
Hides the schema title next to to the type.
|
|
||||||
|
|
||||||
### jsonSamplesExpandLevel
|
|
||||||
|
|
||||||
Sets the default expand level for JSON payload samples (response and request body). The default value is 2, and the maximum supported value is '+Infinity'. It can also be configured as a string with the special value `all` that expands all levels.
|
|
||||||
|
|
||||||
_Default: 2_
|
|
||||||
|
|
||||||
### maxDisplayedEnumValues
|
|
||||||
|
|
||||||
Displays only the specified number of enum values. The remaining values are hidden in an expandable area. If not set, all values are displayed.
|
|
||||||
|
|
||||||
### onlyRequiredInSamples
|
|
||||||
|
|
||||||
Shows only required fields in request samples.
|
|
||||||
|
|
||||||
### sortRequiredPropsFirst
|
|
||||||
|
|
||||||
Shows required properties in schemas first, ordered in the same order as in the required array.
|
|
||||||
|
|
||||||
### schemasExpansionLevel
|
|
||||||
|
|
||||||
Specifies whether to automatically expand schemas in Reference docs. Set it to `all` to expand all schemas regardless of their level, or set it to a number to expand schemas up to the specified level. For example, `schemasExpansionLevel: 3` expands schemas up to three levels deep. The default value is `0`, meaning no schemas are expanded automatically.
|
|
||||||
|
|
||||||
### scrollYOffset
|
|
||||||
|
|
||||||
Specifies a vertical scroll-offset.
|
|
||||||
This setting is useful when there are fixed positioned elements at the top of the page, such as navbars, headers, etc.
|
|
||||||
|
|
||||||
Note that you can specify the `scrollYOffset` value in any of the following ways:
|
|
||||||
- as a number - a fixed number of pixels to be used as the offset.
|
|
||||||
- as a CSS selector - the selector of the element to be used for specifying the offset. The distance from the top of the page to the element's bottom is used as the offset.
|
|
||||||
- a function (advanced) - a getter function. Must return a number representing the offset (in pixels).
|
|
||||||
|
|
||||||
### showExtensions
|
|
||||||
|
|
||||||
Shows specification extensions ('x-' fields). Extensions used by Redoc are ignored. The value can be boolean or an array of strings with names of extensions to display. When used as boolean and set to `true`, all specification extensions are shown.
|
|
||||||
|
|
||||||
### sanitize
|
|
||||||
|
|
||||||
If set to `true`, the API definition is considered untrusted and all HTML/Markdown is sanitized to prevent XSS.
|
|
||||||
|
|
||||||
### downloadUrls
|
|
||||||
|
|
||||||
Set the URLs used to download the OpenAPI description or other documentation related files from the API documentation page.
|
|
||||||
|
|
||||||
### schemaDefinitionsTagName
|
|
||||||
|
|
||||||
If a value is set, all of the schemas are rendered with the designated tag name. The schemas then render and display in the sidebar navigation (with that associated tag name).
|
|
||||||
|
|
||||||
### generatedSamplesMaxDepth
|
|
||||||
|
|
||||||
The generatedSamplesMaxDepth option controls how many schema levels automatically generated for payload samples. The default is 8 which works well for most APIs, but you can adjust it if necessary for your use case.
|
|
||||||
|
|
||||||
### hidePropertiesPrefix
|
|
||||||
|
|
||||||
In complex data structures or object schemas where properties are nested within parent objects the hidePropertiesPrefix option enables the hiding of parent names for nested properties within the documentation.
|
|
||||||
|
|
||||||
_Default: true_
|
|
||||||
|
|
||||||
## Deprecated Functional settings
|
|
||||||
|
|
||||||
### hideDownloadButton
|
|
||||||
|
|
||||||
Hides the 'Download' button for saving the API definition source file. **This setting does not make the API definition private**; it just hides the button.
|
|
||||||
|
|
||||||
### downloadFileName
|
|
||||||
|
|
||||||
Sets the filename for the downloaded API definition source file.
|
|
||||||
|
|
||||||
### downloadDefinitionUrl
|
|
||||||
|
|
||||||
Sets the URL for the downloaded API definition source file.
|
|
||||||
|
|
||||||
### requiredPropsFirst
|
|
||||||
|
|
||||||
Shows required properties in schemas first, ordered in the same order as in the required array.
|
|
||||||
|
|
||||||
### jsonSampleExpandLevel
|
|
||||||
|
|
||||||
Sets the default expand level for JSON payload samples (response and request body). The default value is 2, and the maximum supported value is '+Infinity'. It can also be configured as a string with the special value `all` that expands all levels.
|
|
||||||
|
|
||||||
_Default: 2_
|
|
||||||
|
|
||||||
### schemaExpansionLevel
|
|
||||||
|
|
||||||
Specifies whether to automatically expand schemas in Reference docs. Set it to `all` to expand all schemas regardless of their level, or set it to a number to expand schemas up to the specified level. For example, `schemaExpansionLevel: 3` expands schemas up to three levels deep. The default value is `0`, meaning no schemas are expanded automatically.
|
|
||||||
|
|
||||||
|
|
||||||
### expandDefaultServerVariables
|
|
||||||
|
|
||||||
Enables or disables expanding default server variables.
|
|
||||||
|
|
||||||
### expandResponses
|
|
||||||
|
|
||||||
Controls which responses to expand by default. Specify one or more responses by providing their response codes as a comma-separated list without spaces, for example `expandResponses='200,201'`. Special value 'all' expands all responses by default. Be careful: this option can slow down documentation rendering time.
|
|
||||||
|
|
||||||
### expandSingleSchemaField
|
|
||||||
|
|
||||||
Automatically expands the single field in a schema.
|
|
||||||
|
|
||||||
### hideHostname
|
|
||||||
|
|
||||||
If set to `true`, the protocol and hostname are not shown in the operation definition.
|
|
||||||
|
|
||||||
### hideRequestPayloadSample
|
|
||||||
|
|
||||||
Hides request payload examples.
|
|
||||||
|
|
||||||
### hideOneOfDescription
|
|
||||||
|
|
||||||
If set to `true`, the description for `oneOf`/`anyOf` object is not shown in the schema.
|
|
||||||
|
|
||||||
### hideSchemaPattern
|
|
||||||
|
|
||||||
If set to `true`, the pattern is not shown in the schema.
|
|
||||||
|
|
||||||
### hideSecuritySection
|
|
||||||
|
|
||||||
Hides the Security panel section.
|
|
||||||
|
|
||||||
### hideSingleRequestSampleTab
|
|
||||||
|
|
||||||
Hides the request sample tab for requests with only one sample.
|
|
||||||
|
|
||||||
### menuToggle
|
|
||||||
|
|
||||||
If set to `true`, selecting an expanded item in the sidebar twice collapses it.
|
|
||||||
|
|
||||||
_Default: true_
|
|
||||||
|
|
||||||
### nativeScrollbars
|
|
||||||
|
|
||||||
If set to `true`, the sidebar uses the native scrollbar instead of perfect-scroll. This setting is a scrolling performance optimization for big API definitions.
|
|
||||||
|
|
||||||
### pathInMiddlePanel
|
|
||||||
|
|
||||||
Shows the path link and HTTP verb in the middle panel instead of the right panel.
|
|
||||||
|
|
||||||
### payloadSampleIdx
|
|
||||||
|
|
||||||
If set, the payload sample is inserted at the specified index. If there are `N` payload samples and the value configured here is bigger than `N`, the payload sample is inserted last. Indexes start from 0.
|
|
||||||
|
|
||||||
### showObjectSchemaExamples
|
|
||||||
|
|
||||||
Shows object schema example in the properties; default `false`.
|
|
||||||
|
|
||||||
### showWebhookVerb
|
|
||||||
|
|
||||||
When set to `true`, shows the HTTP request method for webhooks in operations and in the sidebar.
|
|
||||||
|
|
||||||
### simpleOneOfTypeLabel
|
|
||||||
|
|
||||||
Shows only unique `oneOf` types in the label without titles.
|
|
||||||
|
|
||||||
### sortEnumValuesAlphabetically
|
|
||||||
|
|
||||||
When set to `true`, sorts all enum values in all schemas alphabetically.
|
|
||||||
|
|
||||||
### sortOperationsAlphabetically
|
|
||||||
|
|
||||||
When set to `true`, sorts operations in the navigation sidebar and in the middle panel alphabetically.
|
|
||||||
|
|
||||||
### sortPropsAlphabetically
|
|
||||||
|
|
||||||
When set to `true`, sorts properties in all schemas alphabetically.
|
|
||||||
|
|
||||||
### sortTagsAlphabetically
|
|
||||||
|
|
||||||
When set to true, sorts tags in the navigation sidebar and in the middle panel alphabetically. Note that only tags are sorted alphabetically in the middle panel, not the operations associated with each tag. To sort operations alphabetically as well, you must set the `sortOperationsAlphabetically` setting to `true`.
|
|
||||||
|
|
||||||
_Default: false_
|
|
||||||
|
|
||||||
### untrustedSpec
|
|
||||||
|
|
||||||
If set to `true`, the API definition is considered untrusted and all HTML/Markdown is sanitized to prevent XSS.
|
|
||||||
|
|
||||||
## Theme settings
|
|
||||||
Change styles for the API documentation page. **Supported in Redoc CE 2.x**.
|
|
||||||
* `spacing`
|
|
||||||
* `unit`: 5 # main spacing unit used in autocomputed theme values later
|
|
||||||
* `sectionHorizontal`: 40 # Horizontal section padding. COMPUTED: spacing.unit * 8
|
|
||||||
* `sectionVertical`: 40 # Horizontal section padding. COMPUTED: spacing.unit * 8
|
|
||||||
* `breakpoints` # breakpoints for switching three/two and mobile view layouts
|
|
||||||
* `small`: '50rem'
|
|
||||||
* `medium`: '85rem'
|
|
||||||
* `large`: '105rem'
|
|
||||||
* `colors`
|
|
||||||
* `tonalOffset`: 0.3 # default tonal offset used in computations
|
|
||||||
* `typography`
|
|
||||||
* `fontSize`: '14px'
|
|
||||||
* `lineHeight`: '1.5em'
|
|
||||||
* `fontWeightRegular`: '400'
|
|
||||||
* `fontWeightBold`: '600'
|
|
||||||
* `fontWeightLight`: '300'
|
|
||||||
* `fontFamily`: 'Roboto, sans-serif'
|
|
||||||
* `smoothing`: 'antialiased'
|
|
||||||
* `optimizeSpeed`: true
|
|
||||||
* `headings`
|
|
||||||
* `fontFamily`: 'Montserrat, sans-serif'
|
|
||||||
* `fontWeight`: '400'
|
|
||||||
* `lineHeight`: '1.6em'
|
|
||||||
* `code` # inline code styling
|
|
||||||
* `fontSize`: '13px'
|
|
||||||
* `fontFamily`: 'Courier, monospace'
|
|
||||||
* `lineHeight`: # COMPUTED: typography.lineHeight
|
|
||||||
* `fontWeight`: # COMPUTED: typography.fontWeightRegular
|
|
||||||
* `color`: '#e53935'
|
|
||||||
* `backgroundColor`: 'rgba(38, 50, 56, 0.05)'
|
|
||||||
* `wrap`: false # whether to break word for inline blocks (otherwise they can overflow)
|
|
||||||
* `links`
|
|
||||||
* `color`: # COMPUTED: colors.primary.main
|
|
||||||
* `visited`: # COMPUTED: typography.links.color
|
|
||||||
* `hover`: # COMPUTED: lighten(0.2 typography.links.color)
|
|
||||||
* `textDecoration`: 'auto'
|
|
||||||
* `hoverTextDecoration`: 'auto'
|
|
||||||
* `sidebar`
|
|
||||||
* `width`: '260px'
|
|
||||||
* `backgroundColor`: '#fafafa'
|
|
||||||
* `textColor`: '#333333'
|
|
||||||
* `activeTextColor`: # COMPUTED: theme.sidebar.textColor (if set by user) or theme.colors.primary.main
|
|
||||||
* `groupItems` # Group headings
|
|
||||||
* `activeBackgroundColor`: # COMPUTED: theme.sidebar.backgroundColor
|
|
||||||
* `activeTextColor`: # COMPUTED: theme.sidebar.activeTextColor
|
|
||||||
* `textTransform`: 'uppercase'
|
|
||||||
* `level1Items` # Level 1 items like tags or section 1st level items
|
|
||||||
* `activeBackgroundColor`: # COMPUTED: theme.sidebar.backgroundColor
|
|
||||||
* `activeTextColor`: # COMPUTED: theme.sidebar.activeTextColor
|
|
||||||
* `textTransform`: 'none'
|
|
||||||
* `arrow` # sidebar arrow
|
|
||||||
* `size`: '1.5em'
|
|
||||||
* `color`: # COMPUTED: theme.sidebar.textColor
|
|
||||||
* `logo`
|
|
||||||
* `maxHeight`: # COMPUTED: sidebar.width
|
|
||||||
* `maxWidth`: # COMPUTED: sidebar.width
|
|
||||||
* `gutter`: '2px' # logo image padding
|
|
||||||
* `rightPanel`
|
|
||||||
* `backgroundColor`: '#263238'
|
|
||||||
* `width`: '40%'
|
|
||||||
* `textColor`: '#ffffff'
|
|
||||||
* `servers`
|
|
||||||
* `overlay`
|
|
||||||
* `backgroundColor`: '#fafafa'
|
|
||||||
* `textColor`: '#263238'
|
|
||||||
* `url`
|
|
||||||
* `backgroundColor`: '#fff'
|
|
||||||
* `fab`
|
|
||||||
* `backgroundColor`: '#263238'
|
|
||||||
* `color`: '#ffffff'
|
|
||||||
|
|
||||||
## Additional customization
|
|
||||||
|
|
||||||
### Security Definition location
|
|
||||||
|
|
||||||
You can inject the Security Definitions widget into any place in your definition `description`.
|
|
||||||
For more information, refer to [Security definitions injection](./security-definitions-injection.md).
|
|
||||||
|
|
||||||
### OpenAPI specification extensions
|
|
||||||
|
|
||||||
Redoc uses the following [specification extensions](https://redocly.com/docs-legacy/api-reference-docs/spec-extensions/):
|
|
||||||
* [`x-logo`](./redoc-vendor-extensions.md#x-logo) - is used to specify API logo
|
|
||||||
* [`x-traitTag`](./redoc-vendor-extensions.md#x-traittag) - useful for handling out common things like Pagination, Rate-Limits, etc
|
|
||||||
* [`x-codeSamples`](./redoc-vendor-extensions.md#x-codesamples) - specify operation code samples
|
|
||||||
* [`x-examples`](./redoc-vendor-extensions.md#x-examples) - specify JSON example for requests
|
|
||||||
* [`x-nullable`](./redoc-vendor-extensions.md#x-nullable) - mark schema param as a nullable
|
|
||||||
* [`x-displayName`](./redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories
|
|
||||||
* [`x-tagGroups`](./redoc-vendor-extensions.md#x-taggroups) - group tags by categories in the side menu
|
|
||||||
* [`x-servers`](./redoc-vendor-extensions.md#x-servers) - ability to specify different servers for API (backported from OpenAPI 3.0)
|
|
||||||
* [`x-additionalPropertiesName`](./redoc-vendor-extensions.md#x-additionalpropertiesname) - ability to supply a descriptive name for the additional property keys
|
|
||||||
* [`x-summary`](./redoc-vendor-extensions.md#x-summary) - For Response object, use as the response button text, with description rendered under the button
|
|
||||||
* [`x-explicitMappingOnly`](./redoc-vendor-extensions.md#x-explicitmappingonly) - In Schemas, display a more descriptive property name in objects with additionalProperties when viewing the property list with an object
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
seo:
|
|
||||||
title: Use the Redoc CLI
|
|
||||||
---
|
|
||||||
|
|
||||||
# How to use the Redocly CLI
|
|
||||||
|
|
||||||
With Redocly CLI, you can bundle your OpenAPI definition and API documentation
|
|
||||||
(made with Redoc) into an HTML file and render it locally.
|
|
||||||
|
|
||||||
## Step 1 - Install Redocly CLI
|
|
||||||
|
|
||||||
First, you need to install the `@redocly/cli` package.
|
|
||||||
|
|
||||||
You can install it [globally](../../cli/installation#install-globally) using npm.
|
|
||||||
|
|
||||||
Or you can install it during [runtime](../../cli/installation#use-npx-at-runtime) using npx or Docker.
|
|
||||||
|
|
||||||
## Step 2 - Build the HTML file
|
|
||||||
|
|
||||||
The Redocly CLI `build-docs` command builds Redoc into an HTML file.
|
|
||||||
|
|
||||||
To build an HTML file using Redocly CLI, enter the following command,
|
|
||||||
replacing `apis/openapi.yaml` with your API definition file's name and path:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
redocly build-docs apis/openapi.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
See the [build-docs](../../cli/commands/build-docs) documentation for more information
|
|
||||||
on the different options and ways you can use the command.
|
|
||||||
|
|
||||||
Also, check out [Redocly CLI commands](../../cli/commands), for more
|
|
||||||
information on the different things you can do with Redocly CLI including
|
|
||||||
linting, splitting, and bundling your API definition file.
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
seo:
|
|
||||||
title: Use the Redoc Docker image
|
|
||||||
---
|
|
||||||
|
|
||||||
# How to use the Redoc Docker image
|
|
||||||
|
|
||||||
Redoc is available as a pre-built Docker image in [Docker Hub](https://hub.docker.com/r/redocly/redoc/).
|
|
||||||
|
|
||||||
If you have [Docker](https://docs.docker.com/get-docker/) installed, pull the image with the following command:
|
|
||||||
|
|
||||||
```docker
|
|
||||||
docker pull redocly/redoc
|
|
||||||
```
|
|
||||||
|
|
||||||
Then run the image with the following command:
|
|
||||||
|
|
||||||
```docker
|
|
||||||
docker run -p 8080:80 redocly/redoc
|
|
||||||
```
|
|
||||||
|
|
||||||
The preview starts on port 8080, based on the port used in the command,
|
|
||||||
and can be accessed at `http://localhost:8080`.
|
|
||||||
To exit the preview, use `control+C`.
|
|
||||||
|
|
||||||
By default Redoc starts with a demo Swagger Petstore OpenAPI definition located at
|
|
||||||
http://petstore.swagger.io/v2/swagger.json. You can update this URL using
|
|
||||||
the environment variable `SPEC_URL`.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run -p 8080:80 -e SPEC_URL=https://api.example.com/openapi.json redocly/redoc
|
|
||||||
```
|
|
||||||
|
|
||||||
## Create a Dockerfile
|
|
||||||
|
|
||||||
You can also create a Dockerfile with some predefined environment variables. Check out
|
|
||||||
a sample [Dockerfile](https://github.com/Redocly/redoc/blob/main/config/docker/Dockerfile)
|
|
||||||
in our code repo.
|
|
||||||
|
|
@ -1,140 +0,0 @@
|
||||||
---
|
|
||||||
seo:
|
|
||||||
title: Use the Redoc HTML element
|
|
||||||
---
|
|
||||||
|
|
||||||
# Use Redoc in HTML
|
|
||||||
|
|
||||||
To render API documentation in an HTML page, start with the template below and
|
|
||||||
replace the `spec-url` value with the local file path or URL of your API
|
|
||||||
description.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Redoc</title>
|
|
||||||
<!-- needed for adaptive design -->
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Redoc doesn't change outer page styles
|
|
||||||
-->
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<redoc spec-url='http://petstore.swagger.io/v2/swagger.json'></redoc>
|
|
||||||
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"> </script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
{% admonition type="success" name="URL or local file" %}
|
|
||||||
Set `spec-url` to a relative path if the file is local, e.g. `spec-url=my-api.yaml`. Use a full URL like the example above if it's hosted elsewhere.
|
|
||||||
{% /admonition %}
|
|
||||||
|
|
||||||
Open the HTML file in your browser to see the HTML documentation rendering. You may want to read the next section and add some configuration to make your documentation your own.
|
|
||||||
|
|
||||||
## Configure Redoc
|
|
||||||
|
|
||||||
Redoc is highly configurable, find a [full list of configuration options](../config.md) on the dedicated page.
|
|
||||||
|
|
||||||
To configure Redoc in HTML, add the property names to the HTML tag. Here's an example that makes all the required properties display first in the list:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<redoc spec-url='http://petstore.swagger.io/v2/swagger.json' required-props-first=true></redoc>
|
|
||||||
```
|
|
||||||
|
|
||||||
Any of the individual properties can be added to the tag, as many as you need to get your API docs set up as you like them.
|
|
||||||
|
|
||||||
### Theme configuration
|
|
||||||
|
|
||||||
The `theme` configuration setting is more complex since it represents many nested options, you can supply these as a JSON string to the `theme` attribute. For example, to change the sidebar color you would use a tag like this:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<redoc spec-url='http://petstore.swagger.io/v2/swagger.json'
|
|
||||||
required-props-first=true
|
|
||||||
theme='{
|
|
||||||
"sidebar": {
|
|
||||||
"backgroundColor": "lightblue"
|
|
||||||
}
|
|
||||||
}'
|
|
||||||
></redoc>
|
|
||||||
```
|
|
||||||
|
|
||||||
Check out the [list of options for theme configuration](../config.md#theme-settings) and build up the configuration that suits your API needs.
|
|
||||||
|
|
||||||
## Advanced options
|
|
||||||
|
|
||||||
### The Redoc object
|
|
||||||
|
|
||||||
As an alternative to the HTML tag, you can also initialise Redoc in a web page using the Redoc object and invoking it from JavaScript. This is useful for situations where you want to create dynamic content in a page, and also provides a simple way to attach the Redoc element to an existing container.
|
|
||||||
|
|
||||||
The Redoc object offers an `init` function:
|
|
||||||
|
|
||||||
```js
|
|
||||||
Redoc.init(specOrSpecUrl, options, element, callback)
|
|
||||||
```
|
|
||||||
- `specOrSpecUrl`: Either a JSON object with the OpenAPI definition or a file name/URL to the
|
|
||||||
definition in JSON or YAML format.
|
|
||||||
- `options`: See the [configuration reference](../config.md).
|
|
||||||
- `element`: DOM element Redoc is inserted into.
|
|
||||||
- `callback`(optional): Callback to be called after Redoc has been fully rendered.
|
|
||||||
It is also called on errors with `error` as the first argument.
|
|
||||||
|
|
||||||
Call `Redoc.init()` from the JavaScript on a web page to add the element to the named container. Below is an example of an HTML page with a `<div>` tag, and the JavaScript to add the Redoc object to it.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head />
|
|
||||||
<body>
|
|
||||||
<H1>Redoc in action</H1>
|
|
||||||
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"> </script>
|
|
||||||
<div id="redoc-container"></div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
Redoc.init('http://petstore.swagger.io/v2/swagger.json', {
|
|
||||||
"expandResponses": "200,400"
|
|
||||||
}, document.getElementById('redoc-container'))
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
This example also sets the configuration for `expandResponses` so all 200 and 400 status responses are shown unfolded and with their details visible when the page loads.
|
|
||||||
|
|
||||||
### Self-host dependencies
|
|
||||||
|
|
||||||
You can reference the Redoc script using either a link to the files hosted on a CDN
|
|
||||||
or install to your `node-modules` folder. Using the CDN is the simplest option, but
|
|
||||||
if you need to host in a closed environment or have requirements around external
|
|
||||||
dependencies, it may be useful to self-host.
|
|
||||||
|
|
||||||
The main example shows using the CDN:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"> </script>
|
|
||||||
```
|
|
||||||
|
|
||||||
If you would instead prefer to host the depdencies yourself, first install `redoc` using `npm`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install redoc
|
|
||||||
```
|
|
||||||
|
|
||||||
_(Yarn users can install the `redoc` package with `yarn`)_.
|
|
||||||
|
|
||||||
You can then reference the Redoc script with a node modules link:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script src="node_modules/redoc/bundles/redoc.standalone.js"> </script>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
---
|
|
||||||
seo:
|
|
||||||
title: Redoc deployment guide
|
|
||||||
---
|
|
||||||
|
|
||||||
# Redoc deployment guide
|
|
||||||
|
|
||||||
Redoc offers multiple options for rendering your OpenAPI definition.
|
|
||||||
You should select the option that best fits your needs.
|
|
||||||
|
|
||||||
The following options are supported:
|
|
||||||
|
|
||||||
- **[Live demo](https://redocly.github.io/redoc/):**
|
|
||||||
The live demo offers a fast way to see how your OpenAPI renders with 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**.
|
|
||||||
- **[HTML element](./html.md):**
|
|
||||||
Using the HTML element works well for typical website deployments.
|
|
||||||
- **[React component](./react.md):**
|
|
||||||
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.
|
|
||||||
- **[Redocly CLI](./cli.md):**
|
|
||||||
Using the Redocly CLI is an option for users who prefer to use a command-line interface.
|
|
||||||
|
|
||||||
## Before you start
|
|
||||||
|
|
||||||
### OpenAPI definition
|
|
||||||
|
|
||||||
You need an OpenAPI definition. For testing purposes, you can use one of the following sample OpenAPI definitions:
|
|
||||||
|
|
||||||
- OpenAPI 3.0
|
|
||||||
- [Museum Example API](https://github.com/Redocly/museum-openapi-example/blob/main/openapi.yaml)
|
|
||||||
- [Petstore Sample OpenAPI Definition](https://petstore3.swagger.io/api/v3/openapi.json)
|
|
||||||
- OpenAPI 2.0
|
|
||||||
- [Thingful OpenAPI Definition](https://raw.githubusercontent.com/thingful/openapi-spec/master/spec/swagger.yaml)
|
|
||||||
- [Fitbit Plus OpenAPI Definition](https://raw.githubusercontent.com/TwineHealth/TwineDeveloperDocs/master/spec/swagger.yaml)
|
|
||||||
|
|
||||||
{% admonition type="info" name="OpenAPI specification" %}
|
|
||||||
For more information on the OpenAPI specification, refer to the [Learning OpenAPI 3](https://redocly.com/docs/resources/learning-openapi/)
|
|
||||||
section in the documentation.
|
|
||||||
{% /admonition %}
|
|
||||||
|
|
||||||
### How to run Redoc locally
|
|
||||||
|
|
||||||
If you want to view your Redoc output locally, you can simulate an HTTP server.
|
|
||||||
|
|
||||||
#### Python
|
|
||||||
|
|
||||||
If you have [Python 3](https://www.python.org/downloads/) installed, `cd` into your
|
|
||||||
project directory and run the following command:
|
|
||||||
|
|
||||||
```python
|
|
||||||
python3 -m http.server
|
|
||||||
```
|
|
||||||
|
|
||||||
If you have [Python 2](https://www.python.org/downloads/) installed, `cd` into your
|
|
||||||
project directory and run the following command:
|
|
||||||
|
|
||||||
```python
|
|
||||||
python -m SimpleHTTPServer 8000
|
|
||||||
```
|
|
||||||
|
|
||||||
The output after entering the command provides the local URL where the preview can be accessed.
|
|
||||||
To exit the preview, use `control-C`.
|
|
||||||
|
|
||||||
#### Node.js
|
|
||||||
|
|
||||||
If you have [Node.js](https://nodejs.org/en/download/) installed, install `http-server`
|
|
||||||
using the following npm command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install -g http-server
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, `cd` into your project directory and run the following command:
|
|
||||||
|
|
||||||
```node
|
|
||||||
http-server
|
|
||||||
```
|
|
||||||
|
|
||||||
The output after entering the command provides the local URL where the preview can be accessed.
|
|
||||||
To exit the preview, use `control-C`.
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
---
|
|
||||||
seo:
|
|
||||||
title: Use the Redoc React component
|
|
||||||
redirects:
|
|
||||||
'/docs/redoc/quickstart/react/':
|
|
||||||
to: '/docs/redoc/deployment/react/'
|
|
||||||
---
|
|
||||||
|
|
||||||
# How to use the Redoc React component
|
|
||||||
|
|
||||||
## Before you start
|
|
||||||
|
|
||||||
Install the following dependencies required by Redoc if you do not already have them installed:
|
|
||||||
|
|
||||||
- `react`
|
|
||||||
- `react-dom`
|
|
||||||
- `mobx`
|
|
||||||
- `styled-components`
|
|
||||||
- `core-js`
|
|
||||||
|
|
||||||
If you have npm installed, you can install these dependencies using the following command:
|
|
||||||
|
|
||||||
```js
|
|
||||||
npm i react react-dom mobx styled-components core-js
|
|
||||||
```
|
|
||||||
|
|
||||||
## Step 1 - Import the `RedocStandalone` component
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { RedocStandalone } from 'redoc';
|
|
||||||
```
|
|
||||||
|
|
||||||
## Step 2 - Use the component
|
|
||||||
|
|
||||||
You can either link to your OpenAPI definition with a URL, using the following format:
|
|
||||||
|
|
||||||
```react
|
|
||||||
<RedocStandalone specUrl="url/to/your/spec"/>
|
|
||||||
```
|
|
||||||
|
|
||||||
Or you can pass your OpenAPI definition as an object, using the following format:
|
|
||||||
|
|
||||||
```js
|
|
||||||
<RedocStandalone spec={/* spec as an object */}/>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Optional - Pass options
|
|
||||||
|
|
||||||
Options can be passed into the RedocStandalone component to alter how it renders.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
<RedocStandalone
|
|
||||||
specUrl="http://petstore.swagger.io/v2/swagger.json"
|
|
||||||
options={{
|
|
||||||
nativeScrollbars: true,
|
|
||||||
theme: { colors: { primary: { main: '#dd5522' } } },
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information on configuration options, refer to the
|
|
||||||
[Configuration options for Reference docs](https://redocly.com/docs/api-reference-docs/configuration/functionality/)
|
|
||||||
section of the documentation. Options available for Redoc are noted,
|
|
||||||
"Supported in Redoc CE".
|
|
||||||
|
|
||||||
## Optional - Specify `onLoaded` callback
|
|
||||||
|
|
||||||
You can also specify the `onLoaded` callback, which is called each time Redoc
|
|
||||||
is fully rendered or when an error occurs (with an error as the first argument).
|
|
||||||
|
|
||||||
```js
|
|
||||||
<RedocStandalone
|
|
||||||
specUrl="http://petstore.swagger.io/v2/swagger.json"
|
|
||||||
onLoaded={(error) => {
|
|
||||||
if (!error) {
|
|
||||||
console.log('Yay!');
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
Before Width: | Height: | Size: 310 KiB |
|
Before Width: | Height: | Size: 263 KiB |
|
Before Width: | Height: | Size: 469 KiB |
|
Before Width: | Height: | Size: 510 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 7.9 KiB |
|
|
@ -1,97 +0,0 @@
|
||||||
---
|
|
||||||
seo:
|
|
||||||
title: Redoc
|
|
||||||
---
|
|
||||||
|
|
||||||
# Redoc: Open source API documentation tool
|
|
||||||
|
|
||||||
Redoc is a clean and easy way to produce web-ready documentation from an OpenAPI description (Swagger is also still supported). With one command, create your documentation, and customize it to meet the needs of your users.
|
|
||||||
|
|
||||||
Redoc is based around a three panel layout, with clear sections for navigation, detailed documentation, and request/response examples.
|
|
||||||
|
|
||||||
## Headline features
|
|
||||||
|
|
||||||
* Modern layout with extensive customization options.
|
|
||||||
* Support for OpenAPI 3.1, 3.0 and older 2.0 and Swagger formats.
|
|
||||||
* Embed or build standalone HTML documentation.
|
|
||||||
* CLI tool for easy automation and local development.
|
|
||||||
|
|
||||||
## Demo
|
|
||||||
|
|
||||||
[Try the live demo](https://redocly.github.io/redoc/) and upload your own API specification there to try.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Redoc is provided as a CLI tool (also distributed as a Docker image), HTML tag, and React component.
|
|
||||||
|
|
||||||
### Generate documentation from the CLI
|
|
||||||
|
|
||||||
If you have Node installed, quickly generate documentation using `npx`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npx @redocly/cli build-docs openapi.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
The tool outputs by default to a file named `redoc-static.html` that you can open in your browser.
|
|
||||||
|
|
||||||
> [Redocly CLI](https://github.com/Redocly/redocly-cli/) does more than docs, check it out and add linting, bundling and more to your API workflow.
|
|
||||||
|
|
||||||
### Add an HTML element to the page
|
|
||||||
|
|
||||||
Create an HTML page, or edit an existing one, and add the following:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<redoc spec-url="http://petstore.swagger.io/v2/swagger.json"></redoc>
|
|
||||||
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"> </script>
|
|
||||||
```
|
|
||||||
|
|
||||||
Open the HTML file in your browser, and your API documentation is shown on the page.
|
|
||||||
|
|
||||||
Add your own `spec-url` to the `<redoc>` tag; this attribute can also be a local file. The JavaScript library can also be installed locally using `npm` and served from your own server, see the [HTML deployment documentation](https://redocly.com/docs/redoc/deployment/html/) for more details.
|
|
||||||
|
|
||||||
### More usage options
|
|
||||||
|
|
||||||
Check out the [deployment documentation](./deployment/intro.md) for more options, and detailed documentation for each.
|
|
||||||
|
|
||||||
## Configure Redoc
|
|
||||||
|
|
||||||
Redoc is highly configurable. Each deployment option accepts configuration in a way that's appropriate to that platform, but the options are the same for each. For example:
|
|
||||||
|
|
||||||
* Using [Redocly CLI](../cli), configuration goes in the `redocly.yaml` file, or can be supplied as command line parameters, such as `--theme.openapi.disableSearch`.
|
|
||||||
* Using HTML or React, configure by setting `option` in the tag.
|
|
||||||
|
|
||||||
Here's a sample `redocly.yaml` configuration file, showing a few common settings and tweaking some of the visual theme settings:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
theme:
|
|
||||||
openapi:
|
|
||||||
disableSearch: true
|
|
||||||
expandResponses: 200,202
|
|
||||||
jsonSamplesExpandLevel: 1
|
|
||||||
|
|
||||||
theme:
|
|
||||||
sidebar:
|
|
||||||
backgroundColor: '#eae0cc'
|
|
||||||
textColor: '#3d005b'
|
|
||||||
colors:
|
|
||||||
primary:
|
|
||||||
main: '#660099'
|
|
||||||
typography:
|
|
||||||
fontSize: 14pt
|
|
||||||
headings:
|
|
||||||
fontWeight: bold
|
|
||||||
```
|
|
||||||
|
|
||||||
Redocly CLI detects a file named `redocly.yaml` in the same directory as you run the command and uses it. See the documentation with a command like this:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
redocly build-docs openapi.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
There are many, many more options available. Visit the [configuration reference](./config.md) for a complete list.
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
* If you are new to OpenAPI, try the [OpenAPI starter project](../cli/openapi-starter) for a great introduction.
|
|
||||||
* Ready to build documentation from an existing OpenAPI file? Go to the [Redoc quickstart](./quickstart.md) and get started.
|
|
||||||
* Learn more about the project by visiting [Redoc on GitHub](https://github.com/Redocly/redoc).
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
---
|
|
||||||
seo:
|
|
||||||
title: Redoc quickstart guide
|
|
||||||
---
|
|
||||||
|
|
||||||
# Redoc quickstart guide
|
|
||||||
|
|
||||||
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
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Redoc</title>
|
|
||||||
<!-- needed for adaptive design -->
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Redoc doesn't change outer page styles
|
|
||||||
-->
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<!--
|
|
||||||
Redoc element with link to your OpenAPI definition
|
|
||||||
-->
|
|
||||||
<redoc spec-url="http://petstore.swagger.io/v2/swagger.json"></redoc>
|
|
||||||
<!--
|
|
||||||
Link to Redoc JavaScript on CDN for rendering standalone element
|
|
||||||
-->
|
|
||||||
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
{% admonition type="info" name="Redoc requires an HTTP server to run locally" %}
|
|
||||||
Loading local OpenAPI definitions is impossible without running a web server because of issues with
|
|
||||||
[same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy) and
|
|
||||||
other security reasons. Refer to [Running Redoc locally](./deployment/intro.md#how-to-run-redoc-locally) for more information.
|
|
||||||
{% /admonition %}
|
|
||||||
|
|
||||||
For a more detailed explanation with step-by-step instructions and additional options for using Redoc, refer to the [Redoc deployment guide](./deployment/intro.md).
|
|
||||||
|
|
@ -1,364 +0,0 @@
|
||||||
# Redoc vendor extensions
|
|
||||||
|
|
||||||
You can use the following [vendor extensions](https://redocly.com/docs/openapi-visual-reference/specification-extensions/) with Redoc.
|
|
||||||
|
|
||||||
- [Redoc vendor extensions](#redoc-vendor-extensions)
|
|
||||||
- [Swagger Object](#swagger-object)
|
|
||||||
- [x-servers](#x-servers)
|
|
||||||
- [x-tagGroups](#x-taggroups)
|
|
||||||
- [How to use with Redoc](#how-to-use-with-redoc)
|
|
||||||
- [Tag Group Object](#tag-group-object)
|
|
||||||
- [Fixed fields](#fixed-fields)
|
|
||||||
- [x-tagGroups example](#x-taggroups-example)
|
|
||||||
- [Info Object](#info-object)
|
|
||||||
- [x-logo](#x-logo)
|
|
||||||
- [How to use with Redoc](#how-to-use-with-redoc-1)
|
|
||||||
- [Logo Object](#logo-object)
|
|
||||||
- [Fixed fields](#fixed-fields-1)
|
|
||||||
- [x-logo example](#x-logo-example)
|
|
||||||
- [Tag Object](#tag-object)
|
|
||||||
- [x-traitTag](#x-traittag)
|
|
||||||
- [How to use with Redoc](#how-to-use-with-redoc-2)
|
|
||||||
- [x-traitTag example](#x-traittag-example)
|
|
||||||
- [x-displayName](#x-displayname)
|
|
||||||
- [Operation Object vendor extensions](#operation-object-vendor-extensions)
|
|
||||||
- [x-codeSamples](#x-codesamples)
|
|
||||||
- [How to use with Redoc](#how-to-use-with-redoc-3)
|
|
||||||
- [Code Sample Object](#code-sample-object)
|
|
||||||
- [Fixed fields](#fixed-fields-2)
|
|
||||||
- [Code Sample Object example](#code-sample-object-example)
|
|
||||||
- [x-badges](#x-badges)
|
|
||||||
- [Parameter Object](#parameter-object)
|
|
||||||
- [x-examples](#x-examples)
|
|
||||||
- [How to use with Redoc](#how-to-use-with-redoc-4)
|
|
||||||
- [Response Object vendor extensions](#response-object-vendor-extensions)
|
|
||||||
- [x-summary](#x-summary)
|
|
||||||
- [How to use with Redoc](#how-to-use-with-redoc-5)
|
|
||||||
- [Schema Object](#schema-object)
|
|
||||||
- [x-nullable](#x-nullable)
|
|
||||||
- [How to use with Redoc](#how-to-use-with-redoc-6)
|
|
||||||
- [x-additionalPropertiesName](#x-additionalpropertiesname)
|
|
||||||
- [How to use with Redoc](#how-to-use-with-redoc-7)
|
|
||||||
- [x-additionalPropertiesName example](#x-additionalpropertiesname-example)
|
|
||||||
- [x-explicitMappingOnly](#x-explicitmappingonly)
|
|
||||||
- [How to use with Redoc](#how-to-use-with-redoc-8)
|
|
||||||
- [x-explicitMappingOnly example](#x-explicitmappingonly-example)
|
|
||||||
- [x-enumDescriptions](#x-enumdescriptions)
|
|
||||||
- [How to use with Redoc](#how-to-use-with-redoc-9)
|
|
||||||
- [x-enumDescriptions example](#x-enumdescriptions-example)
|
|
||||||
|
|
||||||
## Swagger Object
|
|
||||||
Extends the OpenAPI root [OpenAPI Object](https://redocly.com/docs/openapi-visual-reference/openapi)
|
|
||||||
|
|
||||||
### x-servers
|
|
||||||
Backported from OpenAPI 3.0 [`servers`](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#server-object). Currently doesn't support templates.
|
|
||||||
|
|
||||||
### x-tagGroups
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :-----------: | :---------- |
|
|
||||||
| x-tagGroups | [ [Tag Group Object](#tag-group-object) ] | A list of tag groups |
|
|
||||||
|
|
||||||
#### How to use with Redoc
|
|
||||||
`x-tagGroups` is used to group tags in the side menu.
|
|
||||||
Before you use `x-tagGroups`, make sure you **add all tags to a group**, since a tag that is not in a group, **is not displayed** at all!
|
|
||||||
|
|
||||||
<a name="tagGroupObject"></a>
|
|
||||||
|
|
||||||
#### Tag Group Object
|
|
||||||
Information about tags group
|
|
||||||
##### Fixed fields
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :---------- | :--------: | :---------- |
|
|
||||||
| name | string | The group name |
|
|
||||||
| tags | [ string ] | List of tags to include in this group |
|
|
||||||
|
|
||||||
#### x-tagGroups example
|
|
||||||
json
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"x-tagGroups": [
|
|
||||||
{
|
|
||||||
"name": "User Management",
|
|
||||||
"tags": ["Users", "API keys", "Admin"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Statistics",
|
|
||||||
"tags": ["Main Stats", "Secondary Stats"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
yaml
|
|
||||||
```yaml
|
|
||||||
x-tagGroups:
|
|
||||||
- name: User Management
|
|
||||||
tags:
|
|
||||||
- Users
|
|
||||||
- API keys
|
|
||||||
- Admin
|
|
||||||
- name: Statistics
|
|
||||||
tags:
|
|
||||||
- Main Stats
|
|
||||||
- Secondary Stats
|
|
||||||
```
|
|
||||||
|
|
||||||
## Info Object
|
|
||||||
Extends the OpenAPI [Info Object](https://redocly.com/docs/openapi-visual-reference/info/)
|
|
||||||
|
|
||||||
### x-logo
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :-----------: | :---------- |
|
|
||||||
| x-logo | [Logo Object](#logo-object) | The information about API logo |
|
|
||||||
|
|
||||||
#### How to use with Redoc
|
|
||||||
`x-logo` is used to specify API logo. The corresponding image is displayed just above the side-menu.
|
|
||||||
|
|
||||||
<a name="logoObject"></a>
|
|
||||||
|
|
||||||
#### Logo Object
|
|
||||||
The information about API logo
|
|
||||||
|
|
||||||
#### Fixed fields
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :-------------- | :------: | :---------- |
|
|
||||||
| url | string | The URL pointing to the spec logo. MUST be in the format of a URL. It SHOULD be an absolute URL so your API definition is usable from any location |
|
|
||||||
| backgroundColor | string | background color to be used. MUST be RGB color in [hexadecimal format] (https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) |
|
|
||||||
| altText | string | Text to use for alt tag on the logo. Defaults to 'logo' if nothing is provided. |
|
|
||||||
| href | string | The URL pointing to the contact page. Default to 'info.contact.url' field of the OAS. |
|
|
||||||
|
|
||||||
|
|
||||||
#### x-logo example
|
|
||||||
json
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"info": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"title": "Swagger Petstore",
|
|
||||||
"x-logo": {
|
|
||||||
"url": "https://redocly.github.io/redoc/petstore-logo.png",
|
|
||||||
"backgroundColor": "#FFFFFF",
|
|
||||||
"altText": "Petstore logo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
yaml
|
|
||||||
```yaml
|
|
||||||
info:
|
|
||||||
version: "1.0.0"
|
|
||||||
title: "Swagger Petstore"
|
|
||||||
x-logo:
|
|
||||||
url: "https://redocly.github.io/redoc/petstore-logo.png"
|
|
||||||
backgroundColor: "#FFFFFF"
|
|
||||||
altText: "Petstore logo"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tag Object
|
|
||||||
Extends the OpenAPI [Tag Object](https://redocly.com/docs/openapi-visual-reference/tags/)
|
|
||||||
|
|
||||||
### x-traitTag
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :------: | :---------- |
|
|
||||||
| x-traitTag | boolean | In Swagger two operations can have multiple tags. This property distinguishes between tags that are used to group operations (default) from tags that are used to mark operation with certain trait (`true` value) |
|
|
||||||
|
|
||||||
#### How to use with Redoc
|
|
||||||
Tags that have `x-traitTag` set to `true` are listed in the side-menu but don't have any subitems (operations). It also renders the `description` tag.
|
|
||||||
This is useful for handling out common things like Pagination, Rate-Limits, etc.
|
|
||||||
|
|
||||||
#### x-traitTag example
|
|
||||||
json
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "Pagination",
|
|
||||||
"description": "Pagination description (can use markdown syntax)",
|
|
||||||
"x-traitTag": true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
yaml
|
|
||||||
```yaml
|
|
||||||
name: Pagination
|
|
||||||
description: Pagination description (can use markdown syntax)
|
|
||||||
x-traitTag: true
|
|
||||||
```
|
|
||||||
|
|
||||||
### x-displayName
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :------: | :---------- |
|
|
||||||
| x-displayName | string | Defines the text that is used for this tag in the menu and in section headings |
|
|
||||||
|
|
||||||
## Operation Object vendor extensions
|
|
||||||
Extends the OpenAPI [Operation Object](https://redocly.com/docs/openapi-visual-reference/operation/)
|
|
||||||
|
|
||||||
### x-codeSamples
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :------: | :---------- |
|
|
||||||
| x-codeSamples | [ [Code Sample Object](#code-sample-object) ] | A list of code samples associated with operation |
|
|
||||||
|
|
||||||
#### How to use with Redoc
|
|
||||||
`x-codeSamples` are rendered on the right panel in Redoc.
|
|
||||||
|
|
||||||
<a name="codeSampleObject"></a>
|
|
||||||
|
|
||||||
### Code Sample Object
|
|
||||||
Operation code sample
|
|
||||||
|
|
||||||
#### Fixed fields
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :---------- | :------: | :----------- |
|
|
||||||
| lang | string | Code sample language. Value should be one of the following [list](https://github.com/github/linguist/blob/master/lib/linguist/popular.yml) |
|
|
||||||
| label | string? | Code sample label, for example `Node` or `Python2.7`, _optional_, `lang` is used by default |
|
|
||||||
| source | string | Code sample source code |
|
|
||||||
|
|
||||||
|
|
||||||
#### Code Sample Object example
|
|
||||||
json
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"lang": "JavaScript",
|
|
||||||
"source": "console.log('Hello World');"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
yaml
|
|
||||||
```yaml
|
|
||||||
lang: JavaScript
|
|
||||||
source: console.log('Hello World');
|
|
||||||
```
|
|
||||||
|
|
||||||
### x-badges
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :------: | :---------- |
|
|
||||||
| x-badges | [[Badge Object](https://redocly.com/docs/realm/author/reference/openapi-extensions/x-badges#badge-object)] | A list of badges associated with the operation |
|
|
||||||
|
|
||||||
## Parameter Object
|
|
||||||
Extends the OpenAPI [Parameter Object](https://redocly.com/docs/openapi-visual-reference/parameter/)
|
|
||||||
|
|
||||||
### x-examples
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :------: | :---------- |
|
|
||||||
| x-examples | [Example Object](https://redocly.com/docs/openapi-visual-reference/example/) | Object that contains examples for the request. Applies when `in` is `body` and mime-type is `application/json` |
|
|
||||||
|
|
||||||
#### How to use with Redoc
|
|
||||||
`x-examples` are rendered in the JSON tab on the right panel in Redoc.
|
|
||||||
|
|
||||||
## Response Object vendor extensions
|
|
||||||
Extends the OpenAPI [Response Object](https://redocly.com/docs/openapi-visual-reference/response/).
|
|
||||||
|
|
||||||
### x-summary
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :------: | :---------- |
|
|
||||||
| x-summary | string | a short summary of the response |
|
|
||||||
|
|
||||||
#### How to use with Redoc
|
|
||||||
If specified, you can use `x-summary` as the response button text, with description rendered under the button.
|
|
||||||
|
|
||||||
## Schema Object
|
|
||||||
Extends the OpenAPI [Schema Object](https://redocly.com/docs/openapi-visual-reference/schemas/)
|
|
||||||
|
|
||||||
### x-nullable
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :------: | :---------- |
|
|
||||||
| x-nullable | boolean | marks schema as a nullable |
|
|
||||||
|
|
||||||
#### How to use with Redoc
|
|
||||||
Schemas marked as `x-nullable` are marked in Redoc with the label Nullable.
|
|
||||||
|
|
||||||
### x-additionalPropertiesName
|
|
||||||
**Attention**: This is a Redoc-specific vendor extension, and is not supported by other tools.
|
|
||||||
|
|
||||||
Extends the `additionalProperties` property of the schema object.
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :------: | :---------- |
|
|
||||||
| x-additionalPropertiesName | string | descriptive name of additional properties keys |
|
|
||||||
|
|
||||||
#### How to use with Redoc
|
|
||||||
Redoc uses this extension to display a more descriptive property name in objects with `additionalProperties` when viewing the property list with an `object`.
|
|
||||||
|
|
||||||
#### x-additionalPropertiesName example
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
Player:
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
additionalProperties:
|
|
||||||
x-additionalPropertiesName: attribute-name
|
|
||||||
type: string
|
|
||||||
```
|
|
||||||
|
|
||||||
### x-explicitMappingOnly
|
|
||||||
**Attention**: This is Redoc-specific vendor extension, and is not supported by other tools.
|
|
||||||
|
|
||||||
Extends the `discriminator` property of the schema object.
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :------: | :---------- |
|
|
||||||
| x-explicitMappingOnly | boolean | limit the discriminator selectpicker to the explicit mappings only |
|
|
||||||
|
|
||||||
#### How to use with Redoc
|
|
||||||
Redoc uses this extension to filter the `discriminator` mappings shown in the selectpicker.
|
|
||||||
When set to `true`, the selectpicker lists only the explicitly defined mappings. When `false`, the default behavior is kept, in other words, explicit and implicit mappings are shown.
|
|
||||||
|
|
||||||
#### x-explicitMappingOnly example
|
|
||||||
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
Pet:
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
- photoUrls
|
|
||||||
discriminator:
|
|
||||||
propertyName: petType
|
|
||||||
x-explicitMappingOnly: true
|
|
||||||
mapping:
|
|
||||||
cat: "#/components/schemas/Cat"
|
|
||||||
bee: "#/components/schemas/HoneyBee"
|
|
||||||
```
|
|
||||||
|
|
||||||
Shows in the selectpicker only the items `cat` and `bee`, even though the `Dog` class inherits from the `Pet` class.
|
|
||||||
|
|
||||||
### x-enumDescriptions
|
|
||||||
|
|
||||||
| Field Name | Type | Description |
|
|
||||||
| :------------- | :------: | :---------- |
|
|
||||||
| x-enumDescriptions | [[Enum Description Object](https://redocly.com/docs/realm/author/reference/openapi-extensions/x-enum-descriptions#enum-description-object)] | A list of the enum values and descriptions to include in the documentation. |
|
|
||||||
|
|
||||||
#### How to use with Redoc
|
|
||||||
The enum (short for "enumeration") fields in OpenAPI allow you to restrict the value of a field to a list of allowed values. These values need to be short and machine-readable, but that can make them harder for humans to parse and work with.
|
|
||||||
|
|
||||||
Add x-enumDescriptions to your OpenAPI description to show a helpful table of enum options and an explanation of what each one means. This field supports Markdown.
|
|
||||||
|
|
||||||
#### x-enumDescriptions example
|
|
||||||
The following example shows a schema with two short-named options, and the x-enumDescriptions entry to list all enum entries and give additional context for each:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
TicketType:
|
|
||||||
description: Type of ticket being purchased. Use `general` for regular museum entry and `event` for tickets to special events.
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- event
|
|
||||||
- general
|
|
||||||
x-enumDescriptions:
|
|
||||||
event: Event Tickets _(timed entry)_
|
|
||||||
general: General Admission
|
|
||||||
example: event
|
|
||||||
```
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
# Injection security definitions
|
|
||||||
|
|
||||||
You can inject the Security Definitions widget anywhere in your specification `description`:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
...
|
|
||||||
## Authorization
|
|
||||||
|
|
||||||
Some description
|
|
||||||
|
|
||||||
<!-- Redoc-Inject: <security-definitions> -->
|
|
||||||
...
|
|
||||||
```
|
|
||||||
The inject instruction is wrapped in an HTML comment,
|
|
||||||
so it is **visible only in Redoc** and not visible, for instance, in the SwaggerUI.
|
|
||||||
|
|
||||||
## Default behavior
|
|
||||||
|
|
||||||
If the injection tag is not found in the description, it is appended to the end
|
|
||||||
of description under the `Authentication` header.
|
|
||||||
|
|
||||||
If the `Authentication` header is already present in the description,
|
|
||||||
Security Definitions are not inserted or rendered.
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<script src="../bundles/redoc.standalone.js">{}</script>
|
|
||||||
<div id="redoc" />
|
|
||||||
</body>
|
|
||||||
</html>;
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<script src="../bundles/redoc.standalone.js">{}</script>
|
|
||||||
<div id="redoc" />
|
|
||||||
</body>
|
|
||||||
</html>;
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
||||||
describe('Menu', () => {
|
|
||||||
describe('3.0 spec', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.visit('e2e/standalone.html');
|
|
||||||
});
|
|
||||||
it('should have valid items count', () => {
|
|
||||||
cy.get('.menu-content').find('li').should('have.length', 35);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should sync active menu items while scroll', () => {
|
|
||||||
cy.contains('h2', 'Introduction')
|
|
||||||
.scrollIntoView()
|
|
||||||
.get('[role=menuitem] > label.active')
|
|
||||||
.should('have.text', 'Introduction');
|
|
||||||
|
|
||||||
cy.contains('h2', 'Add a new pet to the store')
|
|
||||||
.scrollIntoView()
|
|
||||||
.wait(100)
|
|
||||||
.get('[role=menuitem] > label.active')
|
|
||||||
.children()
|
|
||||||
.last()
|
|
||||||
.should('have.text', 'Add a new pet to the store')
|
|
||||||
.should('be.visible');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should sync active menu items while scroll back and scroll again', () => {
|
|
||||||
cy.contains('h2', 'Add a new pet to the store')
|
|
||||||
.scrollIntoView()
|
|
||||||
.wait(100)
|
|
||||||
.get('[role=menuitem] > label.active')
|
|
||||||
.children()
|
|
||||||
.last()
|
|
||||||
.should('have.text', 'Add a new pet to the store')
|
|
||||||
.should('be.visible');
|
|
||||||
|
|
||||||
cy.contains('h1', 'Swagger Petstore').scrollIntoView().wait(100);
|
|
||||||
|
|
||||||
cy.contains('h2', 'Introduction')
|
|
||||||
.scrollIntoView()
|
|
||||||
.wait(100)
|
|
||||||
.get('[role=menuitem] > label.active')
|
|
||||||
.should('have.text', 'Introduction');
|
|
||||||
|
|
||||||
cy.url().should('include', '#section/Introduction');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update URL hash when clicking on menu items', () => {
|
|
||||||
cy.contains('[role=menuitem] > label.-depth1', 'pet').click({ force: true });
|
|
||||||
cy.get('li[data-item-id="schema/Cat"]')
|
|
||||||
.should('have.text', 'schemaCat')
|
|
||||||
.click({ force: true });
|
|
||||||
cy.location('hash').should('equal', '#schema/Cat');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should contains badge schema from x-badges', () => {
|
|
||||||
cy.contains('h2', 'Add a new pet to the store').scrollIntoView();
|
|
||||||
|
|
||||||
cy.contains('h2 > span', 'Beta')
|
|
||||||
.scrollIntoView()
|
|
||||||
.wait(100)
|
|
||||||
.get('[role=menuitem] > label.active')
|
|
||||||
.children('span[type="badge"]')
|
|
||||||
.should('have.text', 'Beta');
|
|
||||||
|
|
||||||
cy.contains('h2 > span', 'Alpha')
|
|
||||||
.scrollIntoView()
|
|
||||||
.wait(100)
|
|
||||||
.get('[role=menuitem] > label.active')
|
|
||||||
.children('span[type="badge"]')
|
|
||||||
.should('have.text', 'Alpha');
|
|
||||||
|
|
||||||
cy.contains('h2 > span', 'Gamma')
|
|
||||||
.scrollIntoView()
|
|
||||||
.wait(100)
|
|
||||||
.get('[role=menuitem] > label.active')
|
|
||||||
.children('span[type="badge"]')
|
|
||||||
.should('have.text', 'Gamma');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should contains Cat schema in Pet using x-tags', () => {
|
|
||||||
cy.contains('[role=menuitem] > label.-depth1', 'pet').click({ force: true });
|
|
||||||
cy.location('hash').should('equal', '#tag/pet');
|
|
||||||
|
|
||||||
cy.contains('[role=menuitem]', 'Find pet by ID').click({ force: true });
|
|
||||||
cy.location('hash').should('equal', '#tag/pet/operation/getPetById');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should deactivate tag when other is activated', () => {
|
|
||||||
const petItem = () => cy.contains('[role=menuitem] > label.-depth1', 'pet');
|
|
||||||
|
|
||||||
petItem().click({ force: true }).should('have.class', 'active');
|
|
||||||
cy.contains('[role=menuitem] > label.-depth1', 'store').click({ force: true });
|
|
||||||
petItem().should('not.have.class', 'active');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be able to open a response object to see more details', () => {
|
|
||||||
cy.contains('h2', 'Find pet by ID')
|
|
||||||
.scrollIntoView()
|
|
||||||
.wait(100)
|
|
||||||
.parent()
|
|
||||||
.find('div h3')
|
|
||||||
.should('have.text', 'Responses')
|
|
||||||
.parent()
|
|
||||||
.find('div:first button')
|
|
||||||
.click()
|
|
||||||
.should('have.attr', 'aria-expanded', 'true')
|
|
||||||
.parent()
|
|
||||||
.find('div h5')
|
|
||||||
.then($h5 => $h5[0].firstChild!.nodeValue!.trim())
|
|
||||||
.should('eq', 'Response Schema:');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be able to open the operation details when the operation IDs have quotes', () => {
|
|
||||||
cy.visit('e2e/standalone-3-1.html');
|
|
||||||
cy.get('label span[title="pet"]').click({ multiple: true, force: true });
|
|
||||||
cy.get('li').contains('OperationId with quotes').click({ multiple: true, force: true });
|
|
||||||
cy.get('h2').contains('OperationId with quotes').should('be.visible');
|
|
||||||
cy.url().should('include', 'deletePetBy%22Id');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should encode URL when the operation IDs have backslashes', () => {
|
|
||||||
cy.visit('e2e/standalone-3-1.html');
|
|
||||||
cy.get('label span[title="pet"]').click({ multiple: true, force: true });
|
|
||||||
cy.get('li').contains('OperationId with backslash').click({ multiple: true, force: true });
|
|
||||||
cy.get('h2').contains('OperationId with backslash').should('be.visible');
|
|
||||||
cy.url().should('include', 'delete%5CPetById');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
// tslint:disable:no-implicit-dependencies
|
|
||||||
import * as yaml from 'js-yaml';
|
|
||||||
|
|
||||||
async function loadSpec(url: string): Promise<any> {
|
|
||||||
const spec = await (await fetch(url)).text();
|
|
||||||
return yaml.load(spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
function initReDoc(win, spec, options = {}) {
|
|
||||||
(win as any).Redoc.init(spec, options, win.document.getElementById('redoc'));
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('Servers', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.visit('e2e/');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have valid server', () => {
|
|
||||||
cy.window().then(async win => {
|
|
||||||
const spec = await loadSpec('/demo/openapi.yaml');
|
|
||||||
initReDoc(win, spec, {});
|
|
||||||
|
|
||||||
// TODO add cy-data attributes
|
|
||||||
cy.get('[data-section-id="tag/pet/operation/addPet"]').should(
|
|
||||||
'contain',
|
|
||||||
'http://petstore.swagger.io/v2/pet',
|
|
||||||
);
|
|
||||||
|
|
||||||
cy.get('[data-section-id="tag/pet/operation/addPet"]').should(
|
|
||||||
'contain',
|
|
||||||
'http://petstore.swagger.io/sandbox/pet',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have valid server for when servers not provided', () => {
|
|
||||||
cy.window().then(async win => {
|
|
||||||
const spec = await loadSpec('/demo/openapi.yaml');
|
|
||||||
delete spec.servers;
|
|
||||||
initReDoc(win, spec, {});
|
|
||||||
|
|
||||||
// TODO add cy-data attributes
|
|
||||||
cy.get('[data-section-id="tag/pet/operation/addPet"]').should(
|
|
||||||
'contain',
|
|
||||||
'http://localhost:' + win.location.port + '/pet',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have valid server for when servers not provided at .html pages', () => {
|
|
||||||
cy.visit('e2e/e2e.html');
|
|
||||||
cy.window().then(async win => {
|
|
||||||
const spec = await loadSpec('/demo/openapi.yaml');
|
|
||||||
delete spec.servers;
|
|
||||||
initReDoc(win, spec, {});
|
|
||||||
|
|
||||||
// TODO add cy-data attributes
|
|
||||||
cy.get('[data-section-id="tag/pet/operation/addPet"]').should(
|
|
||||||
'contain',
|
|
||||||
'http://localhost:' + win.location.port + '/pet',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
describe('Search', () => {
|
|
||||||
const getSearchInput = () => cy.get('[role="search"] input');
|
|
||||||
const getSearchResults = () => cy.get('[data-role="search:results"]');
|
|
||||||
const getResult = i => cy.get('[role=search] label').eq(i);
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.visit('e2e/standalone.html');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should correctly show and hide search results box', () => {
|
|
||||||
getSearchResults().should('not.exist');
|
|
||||||
|
|
||||||
// should not open for less than 3 symbols
|
|
||||||
getSearchInput().type('in', { force: true });
|
|
||||||
getSearchResults().should('not.exist');
|
|
||||||
|
|
||||||
getSearchInput().type('t', { force: true });
|
|
||||||
cy.get('[role=search] [role=menuitem]')
|
|
||||||
.should('have.length', 3)
|
|
||||||
.first()
|
|
||||||
.should('contain', 'Introduction');
|
|
||||||
|
|
||||||
getSearchInput().type('{esc}', { force: true });
|
|
||||||
getSearchResults().should('not.exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support arrow navigation', () => {
|
|
||||||
getSearchInput().type('int', { force: true });
|
|
||||||
|
|
||||||
cy.wait(500);
|
|
||||||
|
|
||||||
getSearchInput().type('{downarrow}', { force: true });
|
|
||||||
getResult(0).should('have.class', 'active');
|
|
||||||
|
|
||||||
getSearchInput().type('{downarrow}', { force: true });
|
|
||||||
getResult(1).should('have.class', 'active');
|
|
||||||
getResult(0).should('not.have.class', 'active');
|
|
||||||
|
|
||||||
getSearchInput().type('{uparrow}', { force: true });
|
|
||||||
getResult(1).should('not.have.class', 'active');
|
|
||||||
getResult(0).should('have.class', 'active');
|
|
||||||
|
|
||||||
getSearchInput().type('{uparrow}', { force: true });
|
|
||||||
getResult(0).should('have.class', 'active');
|
|
||||||
|
|
||||||
getSearchInput().type('{enter}', { force: true });
|
|
||||||
|
|
||||||
cy.contains('[role=menu] label', 'Introduction').should('have.class', 'active');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should mark search results', () => {
|
|
||||||
cy.get('[data-markjs]').should('not.exist');
|
|
||||||
getSearchInput().type('int', { force: true });
|
|
||||||
cy.get('[data-markjs]').should('exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show proper message when no search results are found', () => {
|
|
||||||
getSearchResults().should('not.exist');
|
|
||||||
getSearchInput().type('xzss', { force: true });
|
|
||||||
getSearchResults().should('exist').should('contain', 'No results found');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow search by path or keywords in path', () => {
|
|
||||||
getSearchInput().clear().type('uploadImage', { force: true });
|
|
||||||
cy.get('[role=search] [role=menuitem]')
|
|
||||||
.should('have.length', 1)
|
|
||||||
.first()
|
|
||||||
.should('contain', 'uploads an image');
|
|
||||||
|
|
||||||
getSearchInput()
|
|
||||||
.clear()
|
|
||||||
.type('/pet/{petId}/uploadImage', { force: true, parseSpecialCharSequences: false });
|
|
||||||
cy.get('[role=search] [role=menuitem]')
|
|
||||||
.should('have.length', 1)
|
|
||||||
.first()
|
|
||||||
.should('contain', 'uploads an image');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
describe('Standalone bundle test', () => {
|
|
||||||
function baseCheck(name: string, url: string) {
|
|
||||||
describe(name, () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.visit(url);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Render and check no errors', () => {
|
|
||||||
cy.get('.api-info').should('exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Render and click all the menu items', () => {
|
|
||||||
cy.get('.menu-content li').click({ multiple: true, force: true });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
baseCheck('OAS3 mode', 'e2e/standalone.html');
|
|
||||||
baseCheck('OAS3.1 mode', 'e2e/standalone-3-1.html');
|
|
||||||
baseCheck('OAS2 compatibility mode', 'e2e/standalone-compatibility.html');
|
|
||||||
});
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
describe('Supporting both operation/* and parent/*/operation* urls', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.visit('e2e/standalone.html');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should supporting operation/* url', () => {
|
|
||||||
cy.url().then(loc => {
|
|
||||||
cy.visit(loc + '#operation/updatePet');
|
|
||||||
cy.get('li[data-item-id="tag/pet/operation/updatePet"]').should('be.visible');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should supporting parent/*/operation url', () => {
|
|
||||||
cy.url().then(loc => {
|
|
||||||
cy.visit(loc + '#tag/pet/operation/addPet');
|
|
||||||
cy.get('li[data-item-id="tag/pet/operation/addPet"]').should('be.visible');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
const wp = require('@cypress/webpack-preprocessor');
|
|
||||||
|
|
||||||
const webpackOptions = {
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.ts', '.js'],
|
|
||||||
},
|
|
||||||
performance: false,
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.ts$/,
|
|
||||||
exclude: [/node_modules/],
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: 'esbuild-loader',
|
|
||||||
options: {
|
|
||||||
tsconfigRaw: require('../tsconfig.json'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
webpackOptions,
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = wp(options);
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
const cypressTypeScriptPreprocessor = require('./cy-ts-preprocessor');
|
|
||||||
|
|
||||||
module.exports = on => {
|
|
||||||
on('file:preprocessor', cypressTypeScriptPreprocessor);
|
|
||||||
};
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
<html>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<redoc spec-url="../demo/openapi-3-1.yaml" native-scrollbars></redoc>
|
|
||||||
<script src="../bundles/redoc.standalone.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||