Compare commits

..

15 Commits
main ... v0.5.2

Author SHA1 Message Date
Roman Hotsiy
c4dd9025ac Release v0.5.2 2016-02-03 18:59:00 +02:00
Roman Hotsiy
c2c3e07005 Merge branch 'master' into releases 2016-02-03 18:57:47 +02:00
Roman Hotsiy
417eb1741f Release v0.5.1 2016-02-03 17:07:28 +02:00
Roman Hotsiy
132974acc0 Merge branch 'master' into releases 2016-02-03 17:05:18 +02:00
RedocBot
1a05a723b4 Release v0.5.0 2016-02-01 17:31:35 +00:00
RedocBot
d9f9126af7 Merge branch 'master' into releases 2016-02-01 17:30:54 +00:00
Roman Hotsiy
f8b677a75e Release v0.4.0 2016-01-24 23:27:39 +02:00
Roman Hotsiy
35651acd10 Merge branch 'master' into releases 2016-01-24 23:25:30 +02:00
RedocBot
e34f471dbf Release v0.3.0 2016-01-20 17:39:18 +00:00
RedocBot
ffd9cb5510 Merge branch 'master' into releases 2016-01-20 17:38:37 +00:00
Roman Hotsiy
d385589d3a Release v0.2.0 2016-01-20 17:09:02 +02:00
Roman Hotsiy
9d26d9b426 Merge branch 'master' into releases 2016-01-20 17:08:38 +02:00
Roman Hotsiy
e34fab394b Release v0.1.0 2016-01-18 17:56:48 +02:00
Roman Hotsiy
e1847867ed Merge branch 'master' into releases 2016-01-18 17:55:16 +02:00
travis@localhost
2c284f585c Release v0.0.1 2016-01-06 16:26:02 +00:00
436 changed files with 181980 additions and 101113 deletions

12
.codeclimate.yml Normal file
View File

@ -0,0 +1,12 @@
engines:
eslint:
enabled: true
scss-lint:
enabled: true
fixme:
enabled: true
ratings:
paths:
- "lib/**"
exclude_paths:
- "**.spec.js"

View File

@ -1,12 +0,0 @@
*
!src/
!config
!demo/favicon.png
!custom.d.ts
!typings/styled-patch.d.ts
!tsconfig.json
!webpack.config.ts
!package.json
!package-lock.json

View File

@ -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

5
.eslintignore Normal file
View File

@ -0,0 +1,5 @@
build/
gulpfile.js
*.conf.js
*.config.js
demo/

31
.eslintrc Normal file
View File

@ -0,0 +1,31 @@
{
"parser": "babel-eslint",
"extends": "eslint:recommended",
"env": {
"browser": true,
"jasmine": true
},
// currently eslint doesn't support extension-typed configs
"globals": {
"should": true,
"expect": true,
"sinon": true
},
"rules": {
"quotes": [2, "single"],
"no-console": 0,
"comma-spacing": 2,
"comma-style": [2, "last"],
"consistent-return": 2,
"strict": [2, "global"],
"eqeqeq": [2, "smart"],
"curly": [2, "multi-line"],
"semi-spacing": [2, {"before": false, "after": true}],
"semi": [2, "always"],
"no-extra-semi": 2,
"comma-dangle": [2, "never"],
"no-sequences": 2,
"comma-spacing": [2, {"before": false, "after": true}],
"comma-style": [2, "last"]
}
}

View File

@ -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
],
},
],
},
};

2
.github/CODEOWNERS vendored
View File

@ -1,2 +0,0 @@
* @Redocly/keyboard-warriors
/docs/ @Redocly/technical-writers

View File

@ -1,98 +0,0 @@
# Redoc Contributing Guide
Hi! We're really excited that you are interested in contributing to Redoc. Before submitting your contribution though, please make sure to take a moment and read through the following guidelines.
- [Redoc Contributing Guide](#redoc-contributing-guide)
- [Issue Reporting Guidelines](#issue-reporting-guidelines)
- [Pull Request Guidelines](#pull-request-guidelines)
- [Development Setup](#development-setup)
- [Commonly used NPM scripts](#commonly-used-npm-scripts)
- [Project Structure](#project-structure)
## Issue Reporting Guidelines
- Before filing a new issue, try to make sure your problem doesnt already exist.
- The best way to get your bug fixed is to provide a reduced test case.
## Pull Request Guidelines
Before submitting a pull request, please make sure the following is done:
1. Fork the repository and create your branch from main.
2. Run `npm install` in the repository root.
3. If youve 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.
5. Format your code with prettier (`npm run prettier`).
## Development Setup
You need [Node.js](http://nodejs.org) at `v12.0.0+`.
After cloning the repo, run:
```bash
$ npm install # or npm
```
### Commonly used NPM scripts
``` bash
# dev-server, watch and auto reload playground
$ npm start
# start playground app in production environment
$ npm run start:prod
# runt tslint
$ npm run lint
# try autofix tslint issues
$ npm run lint -- --fix
# run unit tests
$ npm run unit
# run e2e tests
$ npm run e2e
# Make sure you have created bundle before running e2e test
# E.g. run `npm run bundle` and wait for the finishing process.
# open cypress UI to debug e2e test
$ npm run cy:open
# run the unit tests (includes linting and license checks)
$ npm test
# prepare bundles
$ npm run bundle
# 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.
## Project Structure
- **`benchmark`**: contains basic perf benchmark. Not fully ready yet
- **`demo`**: contains project demo with demo specs and HMR playground used in development
- `demo/playground`: HMR Playground used in development
- **`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/).
- **`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/services`**: contains different services used by Redoc including MobX stores
- **`src/services/models`**: contains classes for OpenAPI entities (e.g. Response, Operations, etc)
- **`src/types`**: contains extra typescript typings including OpenAPI doc typings
- **`src/utils`**: utility functions
- **`src/styled-components.ts`**: - reexports styled-components with proper typescript annotations using theme
- **`src/theme.ts`**: - default theme (colors, fonts, etc) used by all the components

View File

@ -1,22 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: 'Type: Bug'
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Minimal reproducible OpenAPI snippet(if possible)**
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.

View File

@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: 'Type: Enhancement'
assignees: ''
---
**Describe the problem to be solved**
A clear and concise description of what problem to be solved
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -1,13 +0,0 @@
## What/Why/How?
## Reference
## Tests
## Screenshots (optional)
## Check yourself
- [ ] Code is linted
- [ ] Tested
- [ ] All new/updated code is covered with tests

View File

@ -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

View File

@ -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]*)"

View File

@ -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

View File

@ -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

View File

@ -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+[.?!]'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 }}

View File

@ -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 }}

View File

@ -1,12 +0,0 @@
name: Unit Tests
on: [push]
jobs:
build-and-unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm ci
- run: npm run bundle
- run: npm test

20
.gitignore vendored
View File

@ -9,7 +9,6 @@
# Linux trash folder which might appear on any partition or disk
.Trash-*
demo/dist/
### Node ###
# Logs
@ -21,19 +20,10 @@ npm-debug.log*
# 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
#jspm
jspm_packages
/dist
/demo/build
.tmp
/coverage
.ghpages-tmp
stats.json
yarn.lock
.idea
.vscode
.eslintcache

View File

@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm run pre-commit

View File

@ -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

View File

@ -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"

View File

@ -1,6 +1,12 @@
*
!bundles/*
!typings/**/*
!package.json
!README.md
!LICENSE
.DS_Store
**/.*
.tmp
node_modules
jspm_packages
tests
lib
demo
build
coverage

View File

@ -1 +0,0 @@
*.md

53
.travis.yml Normal file
View File

@ -0,0 +1,53 @@
language: node_js
node_js:
- '4.0'
branches:
except:
- releases
matrix:
include:
- env: JOB=e2e
fast_finish: true
allow_failures:
- env: JOB=e2e
env:
global:
- GH_REF: github.com/Rebilly/ReDoc.git
- GIT_AUTHOR_EMAIL: redoc-bot@users.noreply.github.com
- GIT_AUTHOR_NAME: RedocBot
- SAUCE_USERNAME: redoc
- secure: OgYIXlyF3tvHVrMjqIMR7UPhNvMzNZRkKE++LsQPUT4aoUmHoeukjgE9tKCZac3Z+PcAlgHQ6dPUqjqij2d/emYBIrCx4ABvTOnxQYHbk+8GriwPvQjV33MCfKvRQAf3XPNcga02aOO/EEGejrtY/i5sz86XPZFXap4scxbvnF0rzOwGU9/A40JLsvKjtfdRxJ3aC2QBnUHP9JkfBOzbs3jjwEWYN7HdUBqtYU+wiUwvHhpEPQ8BVNF5ETp5OxxkTdqJlMRf3azC4U/Rl8dhUXZP2l1ZBdpgahDvSkx1zXPwKRg1jos88jahqH/v8DLHtXNuYQy4S48nKWZfaRtQegG/XsYAftYPtYage7L9D0nFQW9YZI0vwUBEzh2YTf+QNpVwUSyZhVuS1oS+scTb8RU8BVVZd6hRpJiaI2YiPM6ZFN7a69deV0cASov3yI7GSfeq4MmB4hu72Le+GhemQMLRxNgtr32c18XW1XoHEnpV7s0eKXnZrevnM06tW/nX9TQXGloaMUeQzoZY0AuF00zmrHDaNgwT63ULjY0W591Ey1Ztfq4ixdCoi6IPAtl49vTnNMMMqatI7Si/haI6hGyTy+H0xK1GlUpBCe5CGusXDSKUqrlKS5Izreepfj1G+12391ixiapkwV3SbYdQEhcDt7HWupyI4Zfkvg8EwwE=
- secure: H2GClDJ7TEQaWgnk8d2fIVDpLwG3rTmN8TalUzrCqXGoG6ylCVmlwzKLgfPPWrVgSA7QTdfNV0ab7c2KyPoZBinHmeGMSuKNLVbhOXRc2VFxTBntBTuyJhfCgQEpUKvJesJUuv5RuBn//wC7VZcVVNc06TZDEe8+aDVYQuCRMXZJ4X3e6nSZ64QX2veyVcr+TjnRsZPkeBVcK9hngvuaxLb/hbJ85CvjiseZRt47PGIcrEpMn9n2GMw1m0fNnPoN+MBTSCnIklTmdjPG7t4GUSLmD6H0lNLdXuehYqmQAHgYrLec1aiFlV57QaDoDZrq2hSf4vDmCB/FVydGhD5JunI67pujoV2OnD1V80eUZhYNWOYsJ2Nfp4NxgXsPUcE6zWLYsLfktMPZADhOXInQRACt1cnx8zMYKLnch1RY/ZqjSg0nPtRjLzQ0lNsw5leixvBdBnMjxYHVyAWVwg8WiJMaLO9vog2Qnxg1NTacHO2CsOmm2rw6stpg7ndp/+nOleRlfUKggjt0Tn3FjwCIXeGup2P2EBa+WW2YMAaoMFofYviR5vRlKBgdKo9fsAruaO1r6nm2EdAjOlniyw92bEfU/qOey1nVp/oK2S82uT5In8KB7vl6rF3ak7WAsT9Q5vZUhsrG+eE4PVyIyWNBhs4A7pSwZGHDR/MYtp0E2ug=
- secure: QiSLFxMS0fNLQAuG081Oi22OkL8BqCDnZVGk0a69azNzl5vv3PCcYO2Sjbloe48gPVH3p5AonDTtDEtnUbMcCJjtrhggqs5gSilO+UVgDb+4LfrYDnJ8ffaeVGIugay9wl2aJVz3iNbnIovGP7Nw+M/OWtLc2xq6zE1rIJkdRJ4K55PYfO8EMDvzI7hjZxSZ+Kgglcdl/wdBSKXy/qG0atALQU9ilJnk/DcobCjaUjgH/v0HXTSO8K3TNso6Zo4HOO6xWXHDZnJ2sLNltW1jveBpfCr/ZlccgPASU03nIudJyKvX8V4fXQ+2Z2Rj3JtR0x95SSH3M7ixx3s4teiXNFe9HPMfN1NLh/zf8UmgWIN1uwyYecsjRVzz+ZsfnrNBjGyXdEJg5c6SZGIa/UMSxaQFdRzEA419qw2eJ9qcmfNPyIvijugEBupJsxK6MW+mrD8qaGKQDzEP1dD7PUlr1BBckFNI8SZKD0gEaqM/ibebxrMS2IcGE5Nk7qLdaOAdB1plXAhMl+PGNaPx4+cniUqIIpgDTX8hlmd/Qk8ThyN5Z4aQyWI2WfH1BSqwg8dQfB5B6WNUDbJh/4Z6AX7e7ACiMLKoRkBTWpQ1FIwEJh5j8X/mtMBjf4+HSf8kfnAWFCmPTpRcYz9i4ZUDfa/9QKMoumCjokfItU7Ue2UE5v4=
- secure: apiavCfCQngL9Een1m7MIXMf3bqO3rY4YY59TMBl/yFKi80CEsHPHhgVUkl6hC+aM5PeBt/vgjh37rHMX31j/pcSZ4Z8SO/4Bwr36iHfhSxSEuAQog8P07qWqH7wYYWGIVmF682stgl0fYF+GN92sx/6edFVzsWVECf2G7imtICKSTbhKGm3Dhn2JwGnhD7eyfgZ33omgiaswumdu0xABoXDfqSZR+16fC4Ap5rhv3fXO9ndvRNy1STn376nT+my6e86UrQL4aS/S+HNHgIe1BUs+5cOp6Jgw6t0ie7phY0EAiECsRxy9K4e3Dctv9m6+Wma4+vy65MS0zGyrqey6oyV4l827sCOjrD1qcqc9bX6FlMSouVoNfE4ZjINNAbgigTaiLSoDSPcf5I5smkkM2ezzFOMSZwZxNdaNL2LKb97vc8m/ZUkv0sKZyT7oqVL7aJweEivsSHj5l2KR8Z7XrVB1y2eI6GvyTSa/d+CL4dSRzjh8+IRN047YBrdTKD5IkdT0upfoBu14WPUfFmLKxX+iMCslXRWb6kwojhrWNYmZvL65KRAzJ6+eIPDG/W5QUOpYyYT77bLlBQjVo6NmVvl9v3HMECq9CHH0ivKFBGPiKMOx7cJkTax3FuyznOW2WCXB9kTb5Zk9toaiNlSp9L6ll/h2Eyxa6n6sWUgmmM=
addons:
sauce_connect: true
cache:
directories:
- node_modules
- jspm_packages
before_install:
- travis_retry npm install jspm
- jspm config registries.github.auth $JSPM_GITHUB_AUTH_TOKEN
before_deploy:
- npm run build-dist
deploy:
- skip_cleanup: true
provider: script
script: ./build/deploy_gh_pages.sh
on:
branch: master
condition: $JOB != e2e
- skip_cleanup: true
provider: script
script: npm run branch-release
on:
branch: master
condition: $JOB != e2e
- provider: npm
skip_cleanup: true
email: gotsijroman@gmail.com
api_key:
secure: PuhWLERrCEFmXmdFpw2OVFlqpOIVDmgwk5JUJOYaFdVCh/smp0+jZCQ4vrdFpuG96rnDVirD+A8xvW6NgsNNaRthLgOB/LRdFN69rU6Gvn3At6wlnC55t5dlhxPvCfnzJcHVBLXX4EmMkjnZqDg2uczXTzPodr3FnQJNuXmP8B33fzDVLyHccvXZ90abwXWVrgRIXPU28niqCR8DOC2OTzs7wqz+BLNkYDRRbyYXsg62HWuD33x5iof5IqBmhzBt3usCGmF3QGcgHrXHdZw3sZnit8+Bua++3KrXR0x6HGXXN1AoXVmCAkCa5OTQ5R3tCRxiJN3P2KLnvWeZR74sTFkovJB/6pGCvbJ/c7Wnuw6sD7SgOUBD359ULB6lAf5OnxBLoNebX4JxxVXF+zA4E3Bl44VxkzDpPWc15xqBPMB5vBREzMVmJ5mExn2s5cmLQjADbl9h0y6gZnhnNJ+iTmqtrVyM0ZkF2rPrzrTdGD+ULmRIlTMkdD1bh+/TJ3RdXT3P4/zNUJmiNnvgnnJVYYvsGaXWF+7uCVHT/8k2RsoSHqgkqh0gkDqGSwVix55y5mC7T2Vk9lMBhm6MvFJXaonOX0kxJS4EDQ3plPd6/ybG+TLhwggYnQ8o9msU5Nt6FpUShKiezjKurIhbQZdwlVivX3tahjW2QjNDO58xGgY=
on:
tags: true

View File

@ -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]

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-present, Rebilly, Inc.
Copyright (c) 2015, Rebilly, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

211
README.md
View File

@ -1,144 +1,113 @@
<div align="center">
<img alt="Redoc logo" src="https://raw.githubusercontent.com/Redocly/redoc/main//docs/images/redoc.png" width="400px" />
# ReDoc
[![Build Status](https://travis-ci.org/Rebilly/ReDoc.svg?branch=master)](https://travis-ci.org/Rebilly/ReDoc) [![Coverage Status](https://coveralls.io/repos/Rebilly/ReDoc/badge.svg?branch=master&service=github)](https://coveralls.io/github/Rebilly/ReDoc?branch=master) [![Code Climate](https://codeclimate.com/github/Rebilly/ReDoc/badges/gpa.svg)](https://codeclimate.com/github/Rebilly/ReDoc) [![David](https://david-dm.org/Rebilly/ReDoc/dev-status.svg)](https://david-dm.org/Rebilly/ReDoc#info=devDependencies)
# Generate beautiful API documentation from OpenAPI
[![npm](http://img.shields.io/npm/v/redoc.svg)](https://www.npmjs.com/package/swagger-parser) [![Bower](http://img.shields.io/bower/v/redoc.svg)](http://bower.io/) [![License](https://img.shields.io/npm/l/redoc.svg)](https://github.com/Rebilly/ReDoc/blob/master/LICENSE)
[![npm](http://img.shields.io/npm/v/redoc.svg)](https://www.npmjs.com/package/redoc) [![License](https://img.shields.io/npm/l/redoc.svg)](https://github.com/Redocly/redoc/blob/main/LICENSE)
[![Browser Compatibility](https://saucelabs.com/browser-matrix/redoc.svg)](https://saucelabs.com/u/redoc)
[![bundle size](http://img.badgesize.io/https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js?compression=gzip&max=300000)](https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js) [![npm](https://img.shields.io/npm/dm/redoc.svg)](https://www.npmjs.com/package/redoc) [![jsDelivr status](https://data.jsdelivr.com/v1/package/npm/redoc/badge)](https://www.jsdelivr.com/package/npm/redoc)
</div>
Swagger-generated API Reference Documentation
[Live demo](http://rebilly.github.io/ReDoc/)
## About Redoc
Redoc is an open source tool for generating documentation from OpenAPI (formerly Swagger) definitions.
By default Redoc offers a three-panel, responsive layout:
- The left panel contains a search bar and navigation menu.
- The central panel contains the documentation.
- The right panel contains request and response examples.
![Redoc demo](https://raw.githubusercontent.com/Redocly/redoc/main/demo/redoc-demo.png)
## Live demo
If you want to see how Redoc renders your OpenAPI definition,
you can try it out online at https://redocly.github.io/redoc/.
A version of the Swagger Petstore API is displayed by default.
To test it with your own OpenAPI definition,
enter the URL for your definition and select **TRY IT**.
## Redoc features
- Responsive three-panel design with menu/scrolling synchronization
- Support for OpenAPI 3.1, OpenAPI 3.0, and Swagger 2.0
- 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
- [Simple integration with `create-react-app`](https://redocly.com/docs/redoc/quickstart/react/)
- Code samples support (with vendor extension) <br>
![code samples in action](docs/images/code-samples-demo.gif)
## 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`:
```bash
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 within the body tags:
## Deployment
#### tl;dr
```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>
<!DOCTYPE html>
<html>
<head>
<title>ReDoc</title>
<!-- needed for adaptive design -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--
ReDoc uses font options from the parent element
So override default browser styles
-->
<style>
body {
margin: 0;
padding: 0;
font-family: Verdana, Geneva, sans-serif;
font-size: 14px;
color: #333;
}
</style>
</head>
<body>
<redoc spec-url='http://petstore.swagger.io/v2/swagger.json'>
</redoc>
<script src="bower_components/redoc/dist/redoc.min.js"> </script>
</body>
</html>
```
Open the HTML file in your browser, and your API documentation is shown on the page.
#### 1. Install redoc
Install using [bower](bower.io):
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.
bower install redoc
### More usage options
or using [npm](https://docs.npmjs.com/getting-started/what-is-npm):
Check out the [deployment documentation](./docs/deployment/intro.md) for more options, and detailed documentation for each.
npm install redoc --save
## Redoc vs. Redocly API Reference
Alternatively you can just download [`redoc.min.js`](https://raw.githubusercontent.com/Rebilly/ReDoc/releases/dist/redoc.min.js).
Redoc 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/)
with additional features including:
#### 2. Reference redoc script in HTML
Then reference [`redoc.min.js`](https://raw.githubusercontent.com/Rebilly/ReDoc/releases/dist/redoc.min.js) in your HTML page:
```html
<script src="bower_components/redoc/dist/redoc.min.js"> </script>
```
For npm:
```html
<script src="node_modules/redoc/dist/redoc.min.js"> </script>
```
* Try-it console
* Automated code samples
* Pagination
* Extra theme options
#### 3. Add `<redoc>` element to your page
```html
<redoc spec-url="<url to your spec>"></redoc>
```
### Documentation and resources
- [Reference docs](https://redocly.com/docs/api-reference-docs/getting-started/) - we take care of the hosting
- [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/)
- API linting, bundling, and much more with open source [Redocly CLI](https://redocly.com/docs/cli)
## Showcase
A sample of the organizations using Redocly tools in the wild:
- [Rebilly](https://api-reference.rebilly.com/)
- [Docker Engine](https://docs.docker.com/engine/api/v1.25/)
- [Zuora](https://www.zuora.com/developer/api-reference/)
- [Discourse](http://docs.discourse.org)
- [Commbox](https://www.commbox.io/api/)
- [APIs.guru](https://apis.guru/api-doc/)
- [BoxKnight](https://www.docs.boxknight.com/)
- [Quaderno API](https://developers.quaderno.io/api)
_Pull requests to add your own API page to the list are welcome_
#### 4. Enjoy :smile:
## Configuration
Redoc is highly configurable, see the [configuration documentation](docs/config.md) for details.
### OpenAPI specification extensions
Redoc uses the following [specification extensions](https://redocly.com/docs/api-reference-docs/spec-extensions/):
#### Swagger vendor extensions
ReDoc makes use of the following [vendor extensions](http://swagger.io/specification/#vendorExtensions):
* [`x-logo`](docs/redoc-vendor-extensions.md#x-logo) - is used to specify API logo
* [`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-badges`](docs/redoc-vendor-extensions.md#x-badges) - specify operation badges
* [`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-displayName`](docs/redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories
* [`x-tagGroups`](docs/redoc-vendor-extensions.md#x-tagGroups) - group tags by categories in the side menu
* [`x-servers`](docs/redoc-vendor-extensions.md#x-servers) - ability to specify different servers for API (backported from OpenAPI 3.0)
* [`x-additionalPropertiesName`](docs/redoc-vendor-extensions.md#x-additionalPropertiesName) - ability to supply a descriptive name for the additional property keys
* [`x-summary`](docs/redoc-vendor-extensions.md#x-summary) - for Response object, use as the response button text, with description rendered under the button
* [`x-explicitMappingOnly`](docs/redoc-vendor-extensions.md#x-explicitMappingOnly) - in Schemas, display a more descriptive property name in objects with additionalProperties when viewing the property list with an object
* [`x-traitTag`](docs/redoc-vendor-extensions.md#x-traitTag) - useful for handling out common things like Pagination, Rate-Limits, etc
* [`x-code-samples`](docs/redoc-vendor-extensions.md#x-code-samples) - specify operation code samples
## Releases
#### Options
* `spec-url` - relative or absolute url to your spec file
* `scroll-y-offset` - If set, specifies a vertical scroll-offset. This is often useful when there are fixed positioned elements at the top of the page, such as navbars, headers etc.
`scroll-y-offset` can be specified in various ways:
* **number**: A fixed number of pixels to be used as offset
* **selector**: selector of the element to be used for specifying the offset. The distance from the top of the page to the element's bottom will be used as offset.
* **function**: A getter function. Must return a number representing the offset (in pixels).
**The README for the `1.x` version is on the [v1.x](https://github.com/Redocly/redoc/tree/v1.x) branch.**
## Advanced usage
Instead of adding `spec-url` attribute to the `<redoc>` element you can initialize ReDoc via globally exposed `Redoc` object:
```js
Redoc.init(specUrl, options)
```
All the 2.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
- `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)**:
- particular release, for example `v1.2.0`: https://rebilly.github.io/ReDoc/releases/v1.2.0/redoc.min.js
- `v1.x.x` release: https://rebilly.github.io/ReDoc/releases/v1.x.x/redoc.min.js
- `latest` release: https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js - points to latest 1.x.x release since 2.x releases are not hosted on this CDN but on unpkg.
## Development
see [CONTRIBUTING.md](.github/CONTRIBUTING.md)
`options` is javascript object with camel-cased version of options names as the keys. For example:
```js
Redoc.init('http://petstore.swagger.io/v2/swagger.json', {
scrollYOffset: 50
})
```
-----------
## Running locally
1. Clone repository
`git clone https://github.com/Rebilly/ReDoc.git`
2. Go to the project folder
`cd ReDoc`
3. Install node modules and front-end dependencies
`npm install`
`npm run jspm-install`
4. _(optional)_ Replace `demo/swagger.json` with your own schema
5. Start the server
`npm start`
6. Open `http://localhost:9000`

View File

@ -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;
}

View File

@ -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>

View File

@ -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();

30
bower.json Normal file
View File

@ -0,0 +1,30 @@
{
"name": "redoc",
"description": "Swagger-generated API Reference Documentation",
"main": "dist/redoc.min.js",
"authors": [
"Roman Hotsiy"
],
"repository": {
"type": "git",
"url": "git://github.com/Rebilly/ReDoc"
},
"license": "MIT",
"keywords": [
"Swagger",
"JSON-Schema",
"API",
"documentation",
"Angular 2"
],
"homepage": "https://github.com/Rebilly/ReDoc",
"moduleType": ["globals", "amd"],
"ignore": [
"**/.*",
"node_modules",
"tests",
"lib",
"demo",
"build"
]
}

14
build/deploy_gh_pages.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
set -o pipefail
(
set -e
set -x
cd demo
git init
git config user.name "Travis-CI"
git config user.email "travis@travis"
cp -r ../dist ./dist
git add .
git commit -m "Deployed to Github Pages"
git push --force "https://${GH_TOKEN}@${GH_REF}" master:gh-pages 2>&1
) 2>&1 | sed "s/${GH_TOKEN}/xxPASSxx/"

11
build/paths.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = {
source: 'lib/**/*.js',
html: 'lib/**/*.html',
scss: 'lib/**/*.scss',
sourceEntryPoint: 'lib/index.js',
outputName: 'redoc',
output: 'dist/',
tmp: '.tmp/',
demo: 'demo/**/*',
tests: '{lib,tests}/**/*.spec.js'
};

6
build/run_tests.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
if [ "$JOB" = "e2e" ]; then
npm run e2e
else
npm run unit
fi

102
build/tasks/build.js Normal file
View File

@ -0,0 +1,102 @@
var gulp = require('gulp');
var runSequence = require('run-sequence');
var Builder = require('systemjs-builder');
var inlineNg2Template = require('gulp-inline-ng2-template');
var path = require('path');
var sourcemaps = require('gulp-sourcemaps');
var paths = require('../paths');
var fs= require('fs');
var concat = require('gulp-concat');
var gulp = require('gulp');
var sass = require('gulp-sass');
var replace = require('gulp-replace');
var rename = require('gulp-rename');
paths.redocBuilt = path.join(paths.output, paths.outputName);
gulp.task('build', function (callback) {
return runSequence(
'clean',
'bundleProd',
callback
);
});
gulp.task('buildDev', function (callback) {
return runSequence(
'clean',
'bundle',
callback
);
});
gulp.task('bundle', ['buildStatic', 'concatDeps']);
gulp.task('bundleProd', ['bundle', 'buildStaticMin', 'concatDepsMin']);
gulp.task('inlineTemplates', ['sass'], function() {
return gulp.src(paths.source, { base: './' })
.pipe(replace(/'(.*?\.css)'/g, '\'.tmp/$1\''))
.pipe(inlineNg2Template({ base: '/' }))
.pipe(gulp.dest(paths.tmp));
});
var JS_DEV_DEPS = [
'node_modules/zone.js/dist/zone-microtask.js',
'node_modules/reflect-metadata/Reflect.js',
'node_modules/babel-polyfill/dist/polyfill.js'
];
var JS_DEV_DEPS_MIN = [
'node_modules/zone.js/dist/zone-microtask.min.js',
'node_modules/reflect-metadata/Reflect.js',
'node_modules/babel-polyfill/dist/polyfill.min.js'
]
gulp.task('sass', function () {
return gulp.src(paths.scss, { base: './' })
.pipe(sass.sync({outputStyle: 'compressed'}).on('error', sass.logError))
.pipe(gulp.dest(paths.tmp));
});
// concatenate angular2 deps
gulp.task('concatDeps', ['buildStatic'], function() {
return concatDeps(JS_DEV_DEPS, paths.redocBuilt + '.js');
});
gulp.task('concatDepsMin', ['buildStatic'], function() {
return concatDeps(JS_DEV_DEPS_MIN, paths.redocBuilt + '.min.js');
});
gulp.task('buildStatic', ['inlineTemplates'], function(cb) {
bundle(paths.redocBuilt + '.js', false, cb);
});
gulp.task('buildStaticMin', ['inlineTemplates'], function(cb) {
bundle(paths.redocBuilt + '.min.js', true, cb);
});
function concatDeps(deps, file) {
return gulp.src(deps.concat([file]))
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(concat(file))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('.'))
}
function bundle(outputFile, minify, cb) {
fs.existsSync('dist') || fs.mkdirSync('dist');
var builder = new Builder('./', 'system.config.js');
builder
.buildStatic(path.join(paths.tmp, paths.sourceEntryPoint),
outputFile,
{ format:'umd', sourceMaps: true, lowResSourceMaps: true, minify: minify }
)
.then(function() {
cb();
})
.catch(function(err) {
cb(new Error(err));
});
}

9
build/tasks/clean.js Normal file
View File

@ -0,0 +1,9 @@
var gulp = require('gulp');
var paths = require('../paths');
var del = require('del');
var vinylPaths = require('vinyl-paths');
gulp.task('clean', function () {
return gulp.src([paths.output, paths.tmp])
.pipe(vinylPaths(del));
});

34
build/tasks/e2e.js Normal file
View File

@ -0,0 +1,34 @@
var gulp = require('gulp');
var gp = require('gulp-protractor');
var browserSync = require('browser-sync').create('bs-e2e');
gulp.task('test-server', function (done) {
browserSync.init({
open: false,
notify: false,
port: 3000,
ghostMode: false,
server: {
baseDir: './tests/e2e',
routes: {
'/dist': './dist',
'/swagger.yml': './demo/swagger.yml'
},
}
}, done);
});
gulp.task('e2e', ['bundleProd', 'test-server'], function(done) {
gulp.src(['tests/e2e/**/*.js'], { read:false })
.pipe(gp.protractor({
configFile: './protractor.conf.js'
})).on('error', function(e) {
browserSync.exit();
throw e;
done();
}).on('end', function() {
browserSync.exit();
done();
});
});

10
build/tasks/lint.js Normal file
View File

@ -0,0 +1,10 @@
var gulp = require('gulp');
var eslint = require('gulp-eslint');
var paths = require('../paths');
gulp.task('lint', function () {
return gulp.src([paths.source, paths.tests])
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});

17
build/tasks/serve.js Normal file
View File

@ -0,0 +1,17 @@
var gulp = require('gulp');
var browserSync = require('browser-sync').create('bs');
gulp.task('serve', ['watch'], function (done) {
browserSync.init({
open: false,
notify: false,
port: 9000,
server: {
baseDir: './demo',
routes: {
'/dist': './dist'
},
},
reloadDelay: 500
}, done);
});

13
build/tasks/test.js Normal file
View File

@ -0,0 +1,13 @@
var gulp = require('gulp');
var Server = require('karma').Server;
/**
* Run test once and exit
*/
gulp.task('test', ['inlineTemplates'], function (done) {
new Server({
configFile: __dirname + '/../../karma.conf.js',
singleRun: true
}, done).start();
});

14
build/tasks/watch.js Normal file
View File

@ -0,0 +1,14 @@
var gulp = require('gulp');
var paths = require('../paths');
var browserSync = require('browser-sync').get('bs');
function changed(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
}
gulp.task('watch', ['buildDev'], function () {
gulp.watch([ paths.source ], [ 'bundle', browserSync.reload ]).on('change', changed);
gulp.watch([ paths.html ], [ 'bundle', browserSync.reload]).on('change', changed);
gulp.watch([ paths.scss ], [ 'bundle', browserSync.reload]).on('change', changed);
gulp.watch([ paths.demo ], [ '', browserSync.reload ]).on('change', changed);
});

View File

@ -1,56 +0,0 @@
# To run:
# docker build -t redoc .
# docker run -it --rm -p 80:80 -e SPEC_URL='http://localhost:8000/swagger.yaml' redoc
# Ensure http://localhost:8000/swagger.yaml is served with cors. A good solution is:
# npm i -g http-server
# http-server -p 8000 --cors
FROM node:18-alpine
RUN apk update && apk add --no-cache git
# Install dependencies
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 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
FROM nginx:alpine
ENV PAGE_TITLE="ReDoc"
ENV PAGE_FAVICON="favicon.png"
ENV BASE_PATH=
ENV SPEC_URL="http://petstore.swagger.io/v2/swagger.json"
ENV PORT=80
ENV REDOC_OPTIONS=
# copy files to the nginx folder
COPY --from=0 build/bundles /usr/share/nginx/html
COPY config/docker/index.tpl.html /usr/share/nginx/html/index.html
COPY demo/favicon.png /usr/share/nginx/html/
COPY config/docker/nginx.conf /etc/nginx/
COPY config/docker/docker-run.sh /usr/local/bin
# Provide rights to the root group to write to nginx repositories (needed to run in OpenShift)
RUN chgrp -R 0 /etc/nginx && \
chgrp -R 0 /usr/share/nginx/html && \
chgrp -R 0 /var/cache/nginx && \
chgrp -R 0 /var/log/nginx && \
chgrp -R 0 /var/run && \
chmod -R g+rwX /etc/nginx && \
chmod -R g+rwX /usr/share/nginx/html && \
chmod -R g+rwX /var/cache/nginx && \
chmod -R g+rwX /var/log/nginx && \
chmod -R g+rwX /var/run
EXPOSE 80
CMD ["sh", "/usr/local/bin/docker-run.sh"]

View File

@ -1,55 +0,0 @@
# Official ReDoc Docker Image
## Usage
### Docker
Serve remote spec by URL:
docker run -it --rm -p 80:80 \
-e SPEC_URL='http://localhost:8000/swagger.yaml' redocly/redoc
Serve local file:
docker run -it --rm -p 80:80 \
-v $(pwd)/demo/swagger.yaml:/usr/share/nginx/html/swagger.yaml \
-e SPEC_URL=swagger.yaml redocly/redoc
Serve local file and watch for updates:
docker run -it --rm -p 80:80 \
-v $(pwd)/demo/:/usr/share/nginx/html/swagger/ \
-e SPEC_URL=swagger/swagger.yaml redocly/redoc
### OpenShift
To quote [OpenShift Container Platform-Specific Guidelines](https://docs.openshift.com/container-platform/3.11/creating_images/guidelines.html#openshift-specific-guidelines):
> Support Arbitrary User IDs
>
> By default, OpenShift Container Platform runs containers using an arbitrarily assigned user ID. This provides additional security against processes escaping the container due to a container engine vulnerability and thereby achieving escalated permissions on the host node.
>
> For an image to support running as an arbitrary user, directories and files that may be written to by processes in the image should be owned by the root group and be read/writable by that group. Files to be executed should also have group execute permissions.
To comply with those requirements the `Dockerfile` contains instructions to adapt the rights for the folders:
- `/etc/nginx` because the `docker-run.sh` script modifies it at startup time
- `/usr/share/nginx/html` because the `docker-run.sh` script modifies it at startup time
- `/var/cache/nginx` because the Nginx process writes to it
- `/var/log/nginx` because the Nginx process writes to it
- `/var/run` because the Nginx process writes to it
Another issue with OpenShift is that the default exposed port `80` cannot be used as it is restricted. So one needs to use another port like `8080` (using the `PORT` configuration as described below), and then to configure the `container spec` accordingly.
## Runtime configuration options
- `PAGE_TITLE` (default `"ReDoc"`) - page title
- `PAGE_FAVICON` (default `"favicon.png"`) - URL to page favicon
- `BASE_PATH` (optional) - prepend favicon & standalone bundle with this path
- `SPEC_URL` (default `"http://petstore.swagger.io/v2/swagger.json"`) - URL to spec
- `PORT` (default `80`) - nginx port
- `REDOC_OPTIONS` (optional) - [`<redoc>` tag attributes](https://github.com/Redocly/redoc#redoc-tag-attributes)
## Build
docker build -t redocly/redoc .

View File

@ -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;'

View File

@ -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 .

View File

@ -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>

View File

@ -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';
}
}
}
}

View File

@ -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
View File

@ -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>;

View File

@ -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,
},
});

View File

@ -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>
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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;

55502
demo/dist/redoc.full.js vendored Normal file

File diff suppressed because it is too large Load Diff

1
demo/dist/redoc.full.js.map vendored Normal file

File diff suppressed because one or more lines are too long

967
demo/dist/redoc.full.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
demo/dist/redoc.full.min.js.map vendored Normal file

File diff suppressed because one or more lines are too long

57092
demo/dist/redoc.js vendored Normal file

File diff suppressed because one or more lines are too long

1
demo/dist/redoc.js.map vendored Normal file

File diff suppressed because one or more lines are too long

967
demo/dist/redoc.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
demo/dist/redoc.min.js.map vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -1,63 +1,23 @@
<!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"
/>
<title>ReDoc</title>
<link rel="stylesheet" href="main.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="container"></div>
<nav>
<header> ReDoc </header>
<form id="schema-url-form">
<input id="schema-url-input" value='swagger.yml'>
<button type="submit"> Explore </button>
</form>
</nav>
<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');
<redoc scroll-y-offset="body > nav" spec-url='swagger.yml'></redoc>
if (window.location.host === 'rebilly.github.io') {
ga('create', 'UA-81703547-1', 'auto');
ga('send', 'pageview');
}
</script>
<!-- ReDoc built file with all dependencies included -->
<script src="dist/redoc.js"> </script>
<script src="main.js"> </script>
</body>
</html>

View File

@ -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&amp;repo=redoc&amp;type=star&amp;count=true&amp;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;
}
}

99
demo/main.css Normal file
View File

@ -0,0 +1,99 @@
body {
font-family: Verdana, Geneva, sans-serif;
font-size: 14px;
color: #333;
margin: 0;
line-height: 1.5;
padding-top: 50px;
}
nav input, nav button {
font-size: 16px;
height: 28px;
box-sizing: border-box;
vertical-align: middle;
line-height: 1;
outline: none;
}
nav header {
float: left;
margin-left: 20px;
font-size: 25px;
color: #00329F;
font-weight: bold;
}
nav input {
width: 50%;
box-sizing: border-box;
max-width: 500px;
color: #555;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
-webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
}
nav input:focus {
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
}
nav button {
background-color: #fff;
color: #333;
padding: 2px 10px;
touch-action: manipulation;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 1px solid #ccc;
border-radius: 4px;
}
nav button:hover {
background-color: #e6e6e6;
border-color: #adadad;
}
nav button:active {
background-color: #d4d4d4;
border-color: #8c8c8c;
}
nav {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
background-color: white;
border-bottom: 1px solid #ccc;
position: fixed;
top: 0;
z-index: 1;
box-sizing: border-box;
}
@media (min-width: 1000px) {
nav header {
position: absolute;
}
}
@media (max-width: 500px) {
nav input {
width: 70%;
}
nav header {
display: none;
}
}

11
demo/main.js Normal file
View File

@ -0,0 +1,11 @@
;(function() {
'use strict';
var schemaUrlForm = document.getElementById('schema-url-form');
var schemaUrlInput = document.getElementById('schema-url-input');
schemaUrlForm.addEventListener('submit', function(event) {
event.preventDefault();
Redoc.init(schemaUrlInput.value);
return false;
})
})();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,787 +0,0 @@
openapi: 3.1.0
info:
title: Redocly Museum API
description: An imaginary, but delightful Museum API for interacting with museum services and information. Built with love by Redocly.
version: 1.0.0
contact:
email: team@redocly.com
url: 'https://redocly.com/docs/cli/'
x-logo:
url: 'https://redocly.github.io/redoc/museum-logo.png'
altText: Museum logo
license:
name: MIT
url: 'https://opensource.org/license/mit/ '
servers:
- url: 'https://api.fake-museum-example.com/v1'
paths:
/museum-hours:
get:
summary: Get museum hours
description: Get upcoming museum operating hours
operationId: getMuseumHours
tags:
- Operations
x-badges:
- name: 'Beta'
position: before
color: purple
parameters:
- $ref: '#/components/parameters/StartDate'
- $ref: '#/components/parameters/PaginationPage'
- $ref: '#/components/parameters/PaginationLimit'
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/GetMuseumHoursResponse'
examples:
default:
summary: Museum opening hours
value:
- date: '2023-09-11'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-12'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-13'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-17'
timeOpen: '09:00'
timeClose: '18:00'
closed:
summary: The museum is closed
value: []
'400':
description: Bad request
'404':
description: Not found
/special-events:
post:
security: []
operationId: CreateSpecialEvent
summary: Create special event
tags:
- Events
x-badges:
- name: 'Alpha'
color: purple
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateSpecialEventRequest'
examples:
default_example:
$ref: '#/components/examples/CreateSpecialEventRequestExample'
responses:
'200':
description: success
content:
application/json:
schema:
$ref: '#/components/schemas/SpecialEventResponse'
examples:
default_example:
$ref: '#/components/examples/CreateSpecialEventResponseExample'
'400':
description: Bad request
'404':
description: Not found
get:
summary: List special events
description: Return a list of upcoming special events at the museum.
security: []
operationId: listSpecialEvents
x-badges:
- name: 'Gamma'
tags:
- Events
parameters:
- name: startDate
in: query
description: The starting date to retrieve future operating hours from. Defaults to today's date.
schema:
type: string
format: date
example: 2023-02-23
- name: endDate
in: query
description: The end of a date range to retrieve special events for. Defaults to 7 days after `startDate`.
schema:
type: string
format: date
example: 2023-04-18
- name: page
in: query
description: The page number to retrieve.
schema:
type: integer
default: 1
example: 2
- name: limit
in: query
description: The number of days per page.
schema:
type: integer
default: 10
maximum: 30
example: 15
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/ListSpecialEventsResponse'
examples:
default_example:
$ref: '#/components/examples/ListSpecialEventsResponseExample'
'400':
description: Bad request
'404':
description: Not found
/special-events/{eventId}:
get:
summary: Get special event
description: Get details about a special event.
operationId: getSpecialEvent
tags:
- Events
parameters:
- $ref: '#/components/parameters/EventId'
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/SpecialEventResponse'
examples:
default_example:
$ref: '#/components/examples/GetSpecialEventResponseExample'
'400':
description: Bad request
'404':
description: Not found
patch:
summary: Update special event
description: Update the details of a special event
operationId: updateSpecialEvent
tags:
- Events
parameters:
- $ref: '#/components/parameters/EventId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateSpecialEventRequest'
examples:
default_example:
$ref: '#/components/examples/UpdateSpecialEventRequestExample'
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/SpecialEventResponse'
examples:
default_example:
$ref: '#/components/examples/UpdateSpecialEventResponseExample'
'400':
description: Bad request
'404':
description: Not found
delete:
summary: Delete special event
description: Delete a special event from the collection. Allows museum to cancel planned events.
operationId: deleteSpecialEvent
tags:
- Events
parameters:
- $ref: '#/components/parameters/EventId'
responses:
'204':
description: Success - no content
'400':
description: Bad request
'401':
description: Unauthorized
'404':
description: Not found
/tickets:
post:
summary: Buy museum tickets
description: Purchase museum tickets for general entry or special events.
operationId: buyMuseumTickets
tags:
- Tickets
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BuyMuseumTicketsRequest'
examples:
general_entry:
$ref: '#/components/examples/BuyGeneralTicketsRequestExample'
event_entry:
$ref: '#/components/examples/BuyEventTicketsRequestExample'
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/BuyMuseumTicketsResponse'
examples:
general_entry:
$ref: '#/components/examples/BuyGeneralTicketsResponseExample'
event_entry:
$ref: '#/components/examples/BuyEventTicketsResponseExample'
'400':
description: Bad request
'404':
description: Not found
/tickets/{ticketId}/qr:
get:
summary: Get ticket QR code
description: Return an image of your ticket with scannable QR code. Used for event entry.
operationId: getTicketCode
tags:
- Tickets
parameters:
- $ref: '#/components/parameters/TicketId'
responses:
'200':
description: Scannable event ticket in image format
content:
image/png:
schema:
$ref: '#/components/schemas/GetTicketCodeResponse'
'400':
description: Bad request
'404':
description: Not found
components:
schemas:
SpecialEvent:
description: Request payload for creating new special events at the museum.
properties:
name:
description: Name of the special event
type: string
example: Fossil lecture
location:
description: Location where the special event is held
type: string
example: Lecture theatre
eventDescription:
description: Description of the special event
type: string
example: Our panel of experts will share their favorite fossils and explain why they are so great.
dates:
description: List of planned dates for the special event
type: array
items:
type: string
format: date
example: 2024-03-29
price:
description: Price of a ticket for the special event
type: number
format: float
example: 12.50
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: Special event ticket
general: General museum entry ticket
example: event
Date:
type: string
format: date
example: 2023-10-29
Email:
description: Email address for ticket purchaser.
type: string
format: email
example: museum-lover@example.com
Phone:
description: Phone number for the ticket purchaser (optional).
type: string
example: +1(234)-567-8910
BuyMuseumTicketsRequest:
description: Request payload used for purchasing museum tickets.
type: object
properties:
ticketType:
$ref: '#/components/schemas/TicketType'
eventId:
description: Unique identifier for a special event. Required if purchasing tickets for the museum's special events.
$ref: '#/components/schemas/EventId'
ticketDate:
description: Date that the ticket is valid for.
$ref: '#/components/schemas/Date'
email:
$ref: '#/components/schemas/Email'
phone:
$ref: '#/components/schemas/Phone'
required:
- ticketType
- ticketDate
- email
TicketMessage:
description: Confirmation message after a ticket purchase.
type: string
example: Museum general entry ticket purchased
TicketId:
description: Unique identifier for museum ticket. Generated when purchased.
type: string
format: uuid
example: a54a57ca-36f8-421b-a6b4-2e8f26858a4c
TicketConfirmation:
description: Unique confirmation code used to verify ticket purchase.
type: string
example: ticket-event-a98c8f-7eb12
BuyMuseumTicketsResponse:
description: Details for a museum ticket after a successful purchase.
type: object
properties:
message:
$ref: '#/components/schemas/TicketMessage'
eventName:
$ref: '#/components/schemas/EventName'
ticketId:
$ref: '#/components/schemas/TicketId'
ticketType:
$ref: '#/components/schemas/TicketType'
ticketDate:
description: Date the ticket is valid for.
$ref: '#/components/schemas/Date'
confirmationCode:
$ref: '#/components/schemas/TicketConfirmation'
required:
- message
- ticketId
- ticketType
- ticketDate
- confirmationCode
GetTicketCodeResponse:
description: An image of a ticket with a QR code used for museum or event entry.
type: string
format: binary
GetMuseumHoursResponse:
description: List of museum operating hours for consecutive days.
type: array
items:
$ref: '#/components/schemas/MuseumDailyHours'
MuseumDailyHours:
description: Daily operating hours for the museum.
type: object
properties:
date:
description: Date the operating hours apply to.
$ref: '#/components/schemas/Date'
example: 2024-12-31
timeOpen:
type: string
pattern: '^([01]\d|2[0-3]):?([0-5]\d)$'
description: Time the museum opens on a specific date. Uses 24 hour time format (`HH:mm`).
example: 09:00
timeClose:
description: Time the museum closes on a specific date. Uses 24 hour time format (`HH:mm`).
type: string
pattern: '^([01]\d|2[0-3]):?([0-5]\d)$'
example: 18:00
required:
- date
- timeOpen
- timeClose
EventId:
description: Identifier for a special event.
type: string
format: uuid
example: 3be6453c-03eb-4357-ae5a-984a0e574a54
EventName:
type: string
description: Name of the special event
example: Pirate Coding Workshop
EventLocation:
type: string
description: Location where the special event is held
example: Computer Room
EventDescription:
type: string
description: Description of the special event
example: Captain Blackbeard shares his love of the C...language. And possibly Arrrrr (R lang).
EventDates:
type: array
items:
$ref: '#/components/schemas/Date'
description: List of planned dates for the special event
EventPrice:
description: Price of a ticket for the special event
type: number
format: float
example: 25
CreateSpecialEventRequest:
description: Request payload for creating new special events at the museum.
properties:
name:
$ref: '#/components/schemas/EventName'
location:
$ref: '#/components/schemas/EventLocation'
eventDescription:
$ref: '#/components/schemas/EventDescription'
dates:
$ref: '#/components/schemas/EventDates'
price:
$ref: '#/components/schemas/EventPrice'
required:
- name
- location
- eventDescription
- dates
- price
UpdateSpecialEventRequest:
description: Request payload for updating an existing special event. Only included fields are updated in the event.
properties:
name:
$ref: '#/components/schemas/EventName'
location:
$ref: '#/components/schemas/EventLocation'
eventDescription:
$ref: '#/components/schemas/EventDescription'
dates:
$ref: '#/components/schemas/EventDates'
price:
$ref: '#/components/schemas/EventPrice'
ListSpecialEventsResponse:
description: A list of upcoming special events
type: array
items:
$ref: '#/components/schemas/SpecialEventResponse'
SpecialEventResponse:
description: Information about a special event.
properties:
eventId:
$ref: '#/components/schemas/EventId'
name:
$ref: '#/components/schemas/EventName'
location:
$ref: '#/components/schemas/EventLocation'
eventDescription:
$ref: '#/components/schemas/EventDescription'
dates:
$ref: '#/components/schemas/EventDates'
price:
$ref: '#/components/schemas/EventPrice'
required:
- eventId
- name
- location
- eventDescription
- dates
- price
securitySchemes:
MuseumPlaceholderAuth:
type: http
scheme: basic
examples:
BuyGeneralTicketsRequestExample:
summary: General entry ticket
value:
ticketType: general
ticketDate: 2023-09-07
email: todd@example.com
BuyEventTicketsRequestExample:
summary: Special event ticket
value:
ticketType: general
eventId: dad4bce8-f5cb-4078-a211-995864315e39
ticketDate: 2023-09-05
email: todd@example.com
BuyGeneralTicketsResponseExample:
summary: General entry ticket
value:
message: Museum general entry ticket purchased
ticketId: 382c0820-0530-4f4b-99af-13811ad0f17a
ticketType: general
ticketDate: 2023-09-07
confirmationCode: ticket-general-e5e5c6-dce78
BuyEventTicketsResponseExample:
summary: Special event ticket
value:
message: Museum special event ticket purchased
ticketId: b811f723-17b2-44f7-8952-24b03e43d8a9
eventName: Mermaid Treasure Identification and Analysis
ticketType: event
ticketDate: 2023-09-05
confirmationCode: ticket-event-9c55eg-8v82a
CreateSpecialEventRequestExample:
summary: Create special event
value:
name: Mermaid Treasure Identification and Analysis
location: Under the seaaa 🦀 🎶 🌊.
eventDescription: Join us as we review and classify a rare collection of 20 thingamabobs, gadgets, gizmos, whoosits, and whatsits, kindly donated by Ariel.
dates:
- 2023-09-05
- 2023-09-08
price: 0
CreateSpecialEventResponseExample:
summary: Special event created
value:
eventId: dad4bce8-f5cb-4078-a211-995864315e39
name: Mermaid Treasure Identification and Analysis
location: Under the seaaa 🦀 🎶 🌊.
eventDescription: Join us as we review and classify a rare collection of 20 thingamabobs, gadgets, gizmos, whoosits, and whatsits, kindly donated by Ariel.
dates:
- 2023-09-05
- 2023-09-08
price: 30
GetSpecialEventResponseExample:
summary: Get special event
value:
eventId: 6744a0da-4121-49cd-8479-f8cc20526495
name: Time Traveler Tea Party
location: Temporal Tearoom
eventDescription: Sip tea with important historical figures.
dates:
- 2023-11-18
- 2023-11-25
- 2023-12-02
price: 60
ListSpecialEventsResponseExample:
summary: List of special events
value:
- eventId: f3e0e76e-e4a8-466e-ab9c-ae36c15b8e97
name: Sasquatch Ballet
location: Seattle... probably
eventDescription: They're big, they're hairy, but they're also graceful. Come learn how the biggest feet can have the lightest touch.
dates:
- 2023-12-15
- 2023-12-22
price: 40
- eventId: 2f14374a-9c65-4ee5-94b7-fba66d893483
name: Solar Telescope Demonstration
location: Far from the sun.
eventDescription: Look at the sun without going blind!
dates:
- 2023-09-07
- 2023-09-14
price: 50
- eventId: 6aaa61ba-b2aa-4868-b803-603dbbf7bfdb
name: Cook like a Caveman
location: Fire Pit on East side
eventDescription: Learn to cook on an open flame.
dates:
- 2023-11-10
- 2023-11-17
- 2023-11-24
price: 5
- eventId: 602b75e1-5696-4ab8-8c7a-f9e13580f910
name: Underwater Basket Weaving
location: Rec Center Pool next door.
eventDescription: Learn to weave baskets underwater.
dates:
- 2023-09-12
- 2023-09-15
price: 15
- eventId: dad4bce8-f5cb-4078-a211-995864315e39
name: Mermaid Treasure Identification and Analysis
location: Room Sea-12
eventDescription: Join us as we review and classify a rare collection of 20 thingamabobs, gadgets, gizmos, whoosits, and whatsits — kindly donated by Ariel.
dates:
- 2023-09-05
- 2023-09-08
price: 30
- eventId: 6744a0da-4121-49cd-8479-f8cc20526495
name: Time Traveler Tea Party
location: Temporal Tearoom
eventDescription: Sip tea with important historical figures.
dates:
- 2023-11-18
- 2023-11-25
- 2023-12-02
price: 60
- eventId: 3be6453c-03eb-4357-ae5a-984a0e574a54
name: Pirate Coding Workshop
location: Computer Room
eventDescription: Captain Blackbeard shares his love of the C...language. And possibly Arrrrr (R lang).
dates:
- 2023-10-29
- 2023-10-30
- 2023-10-31
price: 45
- eventId: 9d90d29a-2af5-4206-97d9-9ea9ceadcb78
name: Llama Street Art Through the Ages
location: Auditorium
eventDescription: Llama street art?! Alpaca my bags -- let's go!
dates:
- 2023-10-29
- 2023-10-30
- 2023-10-31
price: 45
- eventId: a3c7b2c4-b5fb-4ef7-9322-00a919864957
name: The Great Parrot Debate
location: Outdoor Amphitheatre
eventDescription: See leading parrot minds discuss important geopolitical issues.
dates:
- 2023-11-03
- 2023-11-10
price: 35
- eventId: b92d46b7-4c5d-422b-87a5-287767e26f29
name: Eat a Bunch of Corn
location: Cafeteria
eventDescription: We accidentally bought too much corn. Please come eat it.
dates:
- 2023-11-10
- 2023-11-17
- 2023-11-24
price: 5
UpdateSpecialEventRequestExample:
summary: Update special event request
value:
location: On the beach.
price: 15
UpdateSpecialEventResponseExample:
summary: Update special event
value:
eventId: dad4bce8-f5cb-4078-a211-995864315e39
name: Mermaid Treasure Identification and Analysis
location: On the beach.
eventDescription: Join us as we review and classify a rare collection of 20 thingamabobs, gadgets, gizmos, whoosits, and whatsits, kindly donated by Ariel.
dates:
- 2023-09-05
- 2023-09-08
price: 15
GetMuseumHours:
summary: Museum opening hours
value:
- date: '2023-09-11'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-12'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-13'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-14'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-15'
timeOpen: '10:00'
timeClose: '16:00'
- date: '2023-09-18'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-19'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-20'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-21'
timeOpen: '09:00'
timeClose: '18:00'
- date: '2023-09-22'
timeOpen: '10:00'
timeClose: '16:00'
ClosedMuseumHours:
summary: The museum is closed
value: []
parameters:
PaginationPage:
name: page
in: query
description: The page number to retrieve.
schema:
type: integer
default: 1
example: 2
PaginationLimit:
name: limit
in: query
description: The number of days per page.
schema:
type: integer
default: 10
maximum: 30
example: 15
EventId:
name: eventId
in: path
description: An identifier for a special event.
required: true
schema:
type: string
format: uuid
example: dad4bce8-f5cb-4078-a211-995864315e39
StartDate:
name: startDate
in: query
description: The starting date to retrieve future operating hours from. Defaults to today's date.
schema:
type: string
format: date
example: 2023-02-23
EndDate:
name: endDate
in: query
description: The end of a date range to retrieve special events for. Defaults to 7 days after `startDate`.
schema:
type: string
format: date
example: 2023-04-18
TicketId:
name: ticketId
in: path
description: An identifier for a ticket to a museum event. Used to generate ticket image.
required: true
schema:
type: string
format: uuid
example: a54a57ca-36f8-421b-a6b4-2e8f26858a4c
tags:
- name: Operations
x-displayName: About the museum
description: Operational information about the museum.
- name: Events
x-displayName: Upcoming events
description: Special events hosted by the Museum.
- name: Tickets
x-displayName: Buy tickets
description: Museum tickets for general entrance or special events.
x-tagGroups:
- name: Plan your visit
tags:
- Operations
- Events
- name: Purchases
tags:
- Tickets
- name: Entities
tags:
- Schemas
security:
- MuseumPlaceholderAuth: []

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -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} />);

View File

@ -1,26 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<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>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 270 KiB

View File

@ -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}`));

View File

@ -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

877
demo/swagger.yml Normal file
View File

@ -0,0 +1,877 @@
---
swagger: "2.0"
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."
version: "1.0.0"
title: "Swagger Petstore"
termsOfService: "http://swagger.io/terms/"
contact:
email: "apiteam@swagger.io"
x-logo:
url: "https://rebilly.github.io/ReDoc/petstore-logo.png"
license:
name: "Apache 2.0"
url: "http://www.apache.org/licenses/LICENSE-2.0.html"
host: "petstore.swagger.io"
basePath: "/v2"
tags:
-
name: "Pagination"
x-traitTag: true
description: |-
Sometimes you just can't get enough. For this reason, we've provided a convenient way to access more data in
any request for sequential data. Simply call the url in the next_url parameter and we'll respond with the next
set of data.
```json
{
...
"pagination": {
"next_url": "https://api.instagram.com/v1/tags/puppy/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&max_id=13872296",
"next_max_id": "13872296"
}
}
```
On views where pagination is present, we also support the `count` parameter.
Simply set this to the number of items you'd like to receive. Note that the default values
should be fine for most applications - but if you decide to increase this number there is a maximum value
defined on each endpoint.
externalDocs:
description: "Find out more"
url: "http://swagger.io"
-
name: "JSONP"
x-traitTag: true
description: |-
If you're writing an AJAX application, and you'd like to wrap our response with a callback,
all you have to do is specify a callback parameter with any API call:
```
https://api.instagram.com/v1/tags/coffee/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&callback=callbackFunction
```
Would respond with:
```js
callbackFunction({
...
});
```
> Example of markdown blockquote
externalDocs:
description: "Find out more"
url: "http://swagger.io"
-
name: "pet"
description: "Everything about your Pets"
externalDocs:
description: "Find out more"
url: "http://swagger.io"
-
name: "store"
description: "Access to Petstore orders"
-
name: "user"
description: "Operations about user"
externalDocs:
description: "Find out more about our store"
url: "http://swagger.io"
schemes:
- "http"
paths:
/pet:
post:
tags:
- "pet"
summary: "Add a new pet to the store"
description: ""
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: PHP
source: |-
$form = new \PetStore\Entities\Pet();
$form->setPetType("Dog");
$form->setName("Rex");
// set other fields
try {
$pet = $client->pets()->create($form);
} catch (UnprocessableEntityException $e) {
var_dump($e->getErrors());
}
-
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());
}
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"
x-code-samples:
-
lang: PHP
source: |-
$form = new \PetStore\Entities\Pet();
$form->setPetId(1);
$form->setPetType("Dog");
$form->setName("Rex");
// set other fields
try {
$pet = $client->pets()->update($form);
} catch (UnprocessableEntityException $e) {
var_dump($e->getErrors());
}
security:
-
petstore_auth:
- "write:pets"
- "read:pets"
/pet/findByStatus:
get:
tags:
- "pet"
- "Pagination"
- "JSONP"
summary: "Finds Pets by status"
description: "Multiple status values can be provided with comma seperated 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"
- "Pagination"
- "JSONP"
summary: "Finds Pets by tags"
description: "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing."
operationId: "findPetsByTags"
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"
/pet/{petId}:
get:
tags:
- "pet"
- "JSONP"
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"
-
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"
/store/inventory:
get:
tags:
- "store"
- "JSONP"
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"
- "JSONP"
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/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"
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 toekn 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"
/user/{username}:
get:
tags:
- "user"
- "JSONP"
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"
securityDefinitions:
petstore_auth:
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:
type: "apiKey"
name: "api_key"
in: "header"
definitions:
Order:
type: "object"
properties:
id:
type: "integer"
format: "int64"
petId:
type: "integer"
format: "int64"
quantity:
type: "integer"
format: "int32"
shipDate:
type: "string"
format: "date-time"
status:
type: "string"
description: "Order Status"
enum:
- "placed"
- "approved"
- "delivered"
complete:
type: "boolean"
default: false
xml:
name: "Order"
User:
type: "object"
properties:
id:
type: "integer"
format: "int64"
username:
type: "string"
firstName:
type: "string"
lastName:
type: "string"
email:
type: "string"
password:
type: "string"
phone:
type: "string"
userStatus:
type: "integer"
format: "int32"
description: "User Status"
xml:
name: "User"
Category:
type: "object"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
xml:
name: "Category"
Tag:
type: "object"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
xml:
name: "Tag"
Pet:
type: "object"
required:
- "name"
- "photoUrls"
- "petType"
discriminator: "petType"
properties:
petType:
type: "string"
id:
type: "integer"
format: "int64"
category:
$ref: "#/definitions/Category"
name:
type: "string"
example: "doggie"
photoUrls:
type: "array"
xml:
name: "photoUrl"
wrapped: true
items:
type: "string"
tags:
type: "array"
xml:
name: "tag"
wrapped: true
items:
$ref: "#/definitions/Tag"
status:
type: "string"
description: "pet status in the store"
enum:
- "available"
- "pending"
- "sold"
xml:
name: "Pet"
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"
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: 0
minimum: 0
required:
- "packSize"
ApiResponse:
type: "object"
properties:
code:
type: "integer"
format: "int32"
type:
type: "string"
message:
type: "string"
externalDocs:
description: "Find out more about Swagger"
url: "http://swagger.io"

View File

@ -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'],
}),
],
});

57155
dist/redoc.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/redoc.js.map vendored Normal file

File diff suppressed because one or more lines are too long

998
dist/redoc.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/redoc.min.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -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

View File

@ -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.

View 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.

View File

@ -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>
```

View File

@ -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`.

View File

@ -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!');
}
}}
/>
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 469 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Some files were not shown because too many files have changed in this diff Show More