├── .codesandbox
└── ci.json
├── .eslintrc.js
├── .github
└── workflows
│ ├── pr-title-check.yaml
│ ├── release.yaml
│ └── validate.yaml
├── .gitignore
├── .husky
└── pre-commit
├── .prettierrc.json
├── .vscode
└── settings.json
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── cypress.json
├── cypress
├── .eslintrc.js
├── fixtures
│ └── example.json
├── integration
│ └── test.spec.ts
├── plugins
│ └── index.ts
├── support
│ └── index.ts
└── tsconfig.json
├── demo
├── babel.config.js
├── docs
│ ├── intro.md
│ ├── tutorial-basics
│ │ ├── _category_.json
│ │ ├── congratulations.md
│ │ ├── create-a-blog-post.md
│ │ ├── create-a-document.md
│ │ ├── create-a-page.md
│ │ ├── deploy-your-site.md
│ │ └── markdown-features.mdx
│ └── tutorial-extras
│ │ ├── _category_.json
│ │ ├── manage-docs-versions.md
│ │ └── translate-your-site.md
├── docusaurus.config.js
├── examples
│ ├── custom-overview.md
│ ├── food
│ │ ├── _category_.json
│ │ ├── burgers
│ │ │ ├── _category_.json
│ │ │ └── openapi.yaml
│ │ └── yogurtstore
│ │ │ ├── _category_.json
│ │ │ └── openapi.yaml
│ ├── openapi-array-query-params.yaml
│ ├── openapi-cos.json
│ ├── openapi-issue-21.json
│ ├── openapi-issue-220.yaml
│ ├── petstore.yaml
│ └── petstore
│ │ ├── _category_.yaml
│ │ ├── _spec_.yaml
│ │ └── my-intro.md
├── package.json
├── sandbox.config.json
├── sidebars.js
├── src
│ ├── components
│ │ ├── HomepageFeatures.js
│ │ └── HomepageFeatures.module.css
│ ├── css
│ │ └── custom.css
│ └── pages
│ │ ├── index.js
│ │ ├── index.module.css
│ │ └── markdown-page.md
└── static
│ ├── .nojekyll
│ └── img
│ ├── docusaurus.png
│ ├── favicon.ico
│ ├── logo.svg
│ ├── tutorial
│ ├── docsVersionDropdown.png
│ └── localeDropdown.png
│ ├── undraw_docusaurus_mountain.svg
│ ├── undraw_docusaurus_react.svg
│ └── undraw_docusaurus_tree.svg
├── jest.config.js
├── lerna.json
├── package.json
├── packages
├── create-docusaurus-openapi
│ ├── README.md
│ ├── bin
│ │ └── index.js
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── tsconfig.json
├── docusaurus-plugin-openapi
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── docs
│ │ │ ├── docs.ts
│ │ │ ├── frontMatter.ts
│ │ │ ├── numberPrefix.ts
│ │ │ └── slug.ts
│ │ ├── index.ts
│ │ ├── markdown
│ │ │ ├── createDeprecationNotice.ts
│ │ │ ├── createDescription.ts
│ │ │ ├── createFullWidthTable.ts
│ │ │ ├── createParamsTable.ts
│ │ │ ├── createRequestBodyTable.ts
│ │ │ ├── createSchemaTable.ts
│ │ │ ├── createStatusCodesTable.ts
│ │ │ ├── createVersionBadge.ts
│ │ │ ├── index.ts
│ │ │ ├── schema.test.ts
│ │ │ ├── schema.ts
│ │ │ └── utils.ts
│ │ ├── openapi-to-postmanv2.d.ts
│ │ ├── openapi
│ │ │ ├── __fixtures__
│ │ │ │ └── examples
│ │ │ │ │ ├── openapi.yaml
│ │ │ │ │ └── yogurtstore
│ │ │ │ │ ├── _category_.json
│ │ │ │ │ ├── froyo.yaml
│ │ │ │ │ └── nested
│ │ │ │ │ └── nested.yaml
│ │ │ ├── createExample.ts
│ │ │ ├── index.ts
│ │ │ ├── openapi.test.ts
│ │ │ ├── openapi.ts
│ │ │ └── types.ts
│ │ ├── options.ts
│ │ ├── plugin-openapi.d.ts
│ │ ├── sidebars
│ │ │ ├── index.ts
│ │ │ └── sidebars.test.ts
│ │ ├── types.ts
│ │ ├── util.test.ts
│ │ └── util.ts
│ └── tsconfig.json
├── docusaurus-plugin-proxy
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ ├── options.ts
│ │ ├── plugin-proxy.d.ts
│ │ └── types.ts
│ └── tsconfig.json
├── docusaurus-preset-openapi
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ ├── preset-classic.d.ts
│ │ ├── preset-openapi.d.ts
│ │ └── theme-translations.d.ts
│ └── tsconfig.json
├── docusaurus-template-openapi
│ ├── README.md
│ ├── package.json
│ ├── template.json
│ └── template
│ │ ├── README.md
│ │ ├── babel.config.js
│ │ ├── blog
│ │ ├── 2019-05-28-first-blog-post.md
│ │ ├── 2019-05-29-long-blog-post.md
│ │ ├── 2021-08-01-mdx-blog-post.mdx
│ │ ├── 2021-08-26-welcome
│ │ │ ├── docusaurus-plushie-banner.jpeg
│ │ │ └── index.md
│ │ └── authors.yml
│ │ ├── docs
│ │ ├── intro.md
│ │ ├── tutorial-basics
│ │ │ ├── _category_.json
│ │ │ ├── congratulations.md
│ │ │ ├── create-a-blog-post.md
│ │ │ ├── create-a-document.md
│ │ │ ├── create-a-page.md
│ │ │ ├── deploy-your-site.md
│ │ │ └── markdown-features.mdx
│ │ └── tutorial-extras
│ │ │ ├── _category_.json
│ │ │ ├── manage-docs-versions.md
│ │ │ └── translate-your-site.md
│ │ ├── docusaurus.config.js
│ │ ├── gitignore
│ │ ├── openapi.json
│ │ ├── sidebars.js
│ │ ├── src
│ │ ├── components
│ │ │ ├── HomepageFeatures.js
│ │ │ └── HomepageFeatures.module.css
│ │ ├── css
│ │ │ └── custom.css
│ │ └── pages
│ │ │ ├── index.js
│ │ │ ├── index.module.css
│ │ │ └── markdown-page.md
│ │ └── static
│ │ ├── .nojekyll
│ │ └── img
│ │ ├── docusaurus.png
│ │ ├── favicon.ico
│ │ ├── logo.svg
│ │ ├── tutorial
│ │ ├── docsVersionDropdown.png
│ │ └── localeDropdown.png
│ │ ├── undraw_docusaurus_mountain.svg
│ │ ├── undraw_docusaurus_react.svg
│ │ └── undraw_docusaurus_tree.svg
└── docusaurus-theme-openapi
│ ├── babel.config.js
│ ├── package.json
│ ├── src
│ ├── index.ts
│ ├── theme-classic.d.ts
│ ├── theme-openapi.d.ts
│ ├── theme-translations.d.ts
│ ├── theme
│ │ ├── ApiDemoPanel
│ │ │ ├── Accept
│ │ │ │ ├── index.tsx
│ │ │ │ └── slice.ts
│ │ │ ├── Authorization
│ │ │ │ ├── auth-types.ts
│ │ │ │ ├── index.tsx
│ │ │ │ └── slice.ts
│ │ │ ├── Body
│ │ │ │ ├── index.tsx
│ │ │ │ └── slice.ts
│ │ │ ├── ContentType
│ │ │ │ ├── index.tsx
│ │ │ │ └── slice.ts
│ │ │ ├── Curl
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.module.css
│ │ │ ├── Execute
│ │ │ │ ├── index.tsx
│ │ │ │ └── makeRequest.ts
│ │ │ ├── FloatingButton
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.module.css
│ │ │ ├── FormFileUpload
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.module.css
│ │ │ ├── FormItem
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.module.css
│ │ │ ├── FormMultiSelect
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.module.css
│ │ │ ├── FormSelect
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.module.css
│ │ │ ├── FormTextInput
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.module.css
│ │ │ ├── MethodEndpoint
│ │ │ │ └── index.tsx
│ │ │ ├── ParamOptions
│ │ │ │ ├── index.tsx
│ │ │ │ ├── slice.ts
│ │ │ │ └── styles.module.css
│ │ │ ├── Response
│ │ │ │ ├── index.tsx
│ │ │ │ └── slice.ts
│ │ │ ├── Server
│ │ │ │ ├── index.tsx
│ │ │ │ ├── slice.ts
│ │ │ │ └── styles.module.css
│ │ │ ├── VSCode
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.module.css
│ │ │ ├── buildPostmanRequest.test.ts
│ │ │ ├── buildPostmanRequest.ts
│ │ │ ├── hooks.ts
│ │ │ ├── index.tsx
│ │ │ ├── persistanceMiddleware.ts
│ │ │ ├── storage-utils.ts
│ │ │ ├── store.ts
│ │ │ ├── styles.module.css
│ │ │ ├── text.test.ts
│ │ │ └── text.ts
│ │ ├── ApiItem
│ │ │ ├── index.tsx
│ │ │ └── styles.module.css
│ │ ├── ApiPage
│ │ │ ├── index.tsx
│ │ │ └── styles.module.css
│ │ └── MarkdownItem
│ │ │ └── index.tsx
│ └── types.ts
│ └── tsconfig.json
├── scripts
├── README.md
├── changelog.ts
├── check-pr-title.ts
├── publish.ts
├── utils
│ ├── dry-run.ts
│ ├── get-output.ts
│ └── print-utils.ts
└── version.ts
├── tsconfig.base.json
├── tsconfig.json
└── yarn.lock
/.codesandbox/ci.json:
--------------------------------------------------------------------------------
1 | {
2 | "buildCommand": "build-packages",
3 | "packages": ["packages/*"],
4 | "sandboxes": ["/demo"],
5 | "node": "14"
6 | }
7 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | const tsExtensions = [".ts", ".tsx", ".d.ts"];
9 | const allExtensions = [...tsExtensions, ".js", ".jsx"];
10 |
11 | module.exports = {
12 | ignorePatterns: ["demo/**", "packages/docusaurus-template-*/**"],
13 | root: true,
14 | extends: [
15 | "react-app",
16 | "plugin:jest/recommended",
17 | "plugin:jest/style",
18 | "plugin:testing-library/react",
19 | "plugin:jest-dom/recommended",
20 | ],
21 | plugins: ["import", "header"],
22 | rules: {
23 | "header/header": [
24 | "warn",
25 | "block",
26 | [
27 | " ============================================================================",
28 | " * Copyright (c) Cloud Annotations",
29 | " *",
30 | " * This source code is licensed under the MIT license found in the",
31 | " * LICENSE file in the root directory of this source tree.",
32 | " * ========================================================================== ",
33 | ],
34 | 2,
35 | ],
36 | "import/newline-after-import": ["warn", { count: 1 }],
37 | "import/no-extraneous-dependencies": [
38 | "warn",
39 | {
40 | devDependencies: false,
41 | optionalDependencies: false,
42 | peerDependencies: true,
43 | bundledDependencies: true,
44 | },
45 | ],
46 | "import/order": [
47 | "warn",
48 | {
49 | alphabetize: {
50 | order: "asc",
51 | caseInsensitive: true,
52 | },
53 | "newlines-between": "always",
54 | groups: [
55 | "builtin",
56 | "external",
57 | "internal",
58 | ["parent", "sibling", "index"],
59 | "object",
60 | ],
61 | pathGroups: [
62 | {
63 | pattern: "react?(-dom)",
64 | group: "external",
65 | position: "before",
66 | },
67 | ],
68 | pathGroupsExcludedImportTypes: ["builtin"],
69 | },
70 | ],
71 | },
72 | overrides: [
73 | {
74 | files: ["**/scripts/**", "cypress/**"],
75 | rules: {
76 | "import/no-extraneous-dependencies": [
77 | "warn",
78 | {
79 | devDependencies: true,
80 | optionalDependencies: false,
81 | peerDependencies: true,
82 | bundledDependencies: true,
83 | },
84 | ],
85 | },
86 | },
87 | ],
88 | settings: {
89 | "import/extensions": allExtensions,
90 | "import/external-module-folders": ["node_modules", "node_modules/@types"],
91 | "import/parsers": {
92 | "@typescript-eslint/parser": tsExtensions,
93 | },
94 | "import/resolver": {
95 | node: {
96 | extensions: allExtensions,
97 | },
98 | },
99 | },
100 | };
101 |
--------------------------------------------------------------------------------
/.github/workflows/pr-title-check.yaml:
--------------------------------------------------------------------------------
1 | name: PR Title Check
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - main
7 | types:
8 | - opened
9 | - synchronize
10 | - reopened
11 | - edited
12 |
13 | jobs:
14 | check:
15 | name: Check
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@v2
19 | with:
20 | fetch-depth: 0
21 | - name: Check
22 | run: npx ts-node --transpile-only scripts/check-pr-title.ts "$PR_TITLE"
23 | env:
24 | PR_TITLE: ${{ github.event.pull_request.title }}
25 |
--------------------------------------------------------------------------------
/.github/workflows/release.yaml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | env:
9 | FORCE_COLOR: true
10 |
11 | jobs:
12 | release:
13 | name: Release
14 | runs-on: ubuntu-latest
15 | if: ${{ github.repository == 'cloud-annotations/docusaurus-openapi' && github.ref == 'refs/heads/main' && github.event_name == 'push' }}
16 | steps:
17 | - uses: actions/checkout@v2
18 | with:
19 | fetch-depth: 0
20 | - run: |
21 | git config user.name "github-actions[bot]"
22 | git config user.email "github-actions[bot]@users.noreply.github.com"
23 | - uses: actions/setup-node@v2
24 | with:
25 | node-version: "*"
26 | registry-url: "https://registry.npmjs.org"
27 | - name: Release
28 | run: npx ts-node --transpile-only scripts/publish.ts
29 | env:
30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31 | NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
32 |
--------------------------------------------------------------------------------
/.github/workflows/validate.yaml:
--------------------------------------------------------------------------------
1 | name: Validate
2 |
3 | on: [push, pull_request]
4 |
5 | env:
6 | FORCE_COLOR: true
7 |
8 | jobs:
9 | prepare-yarn-cache:
10 | name: Prepare Cache
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v2
14 | - uses: actions/setup-node@v2
15 | with:
16 | node-version: "*"
17 | - uses: actions/cache@v2
18 | with:
19 | path: |
20 | node_modules
21 | */*/node_modules
22 | /home/runner/.cache/Cypress
23 | key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
24 | - name: Install
25 | run: yarn install --frozen-lockfile
26 |
27 | lint:
28 | name: Lint
29 | needs: prepare-yarn-cache
30 | runs-on: ubuntu-latest
31 | steps:
32 | - uses: actions/checkout@v2
33 | - uses: actions/setup-node@v2
34 | with:
35 | node-version: "*"
36 | - uses: actions/cache@v2
37 | with:
38 | path: |
39 | node_modules
40 | */*/node_modules
41 | key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
42 | - name: Install
43 | run: yarn install
44 | - name: Check format
45 | run: yarn format
46 | - name: Lint
47 | run: yarn lint --max-warnings 0
48 |
49 | test:
50 | name: Test
51 | needs: prepare-yarn-cache
52 | runs-on: ubuntu-latest
53 | steps:
54 | - uses: actions/checkout@v2
55 | - uses: actions/setup-node@v2
56 | with:
57 | node-version: "*"
58 | - uses: actions/cache@v2
59 | with:
60 | path: |
61 | node_modules
62 | */*/node_modules
63 | key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
64 | - name: Install
65 | run: yarn install
66 | - name: Test
67 | run: yarn test
68 |
69 | cypress:
70 | name: Cypress
71 | needs: prepare-yarn-cache
72 | runs-on: ubuntu-latest
73 | steps:
74 | - uses: actions/checkout@v2
75 | - uses: actions/setup-node@v2
76 | with:
77 | node-version: "*"
78 | - uses: actions/cache@v2
79 | with:
80 | path: |
81 | node_modules
82 | */*/node_modules
83 | /home/runner/.cache/Cypress
84 | key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
85 | - name: Install
86 | run: yarn install
87 | - name: Build
88 | run: yarn build
89 | - name: Cypress
90 | run: yarn test:cypress
91 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Cypress
2 | cypress/videos
3 | cypress/screenshots
4 |
5 | # Dist
6 | build
7 | dist
8 | lib
9 | lib-next
10 |
11 | # Dependencies
12 | /node_modules
13 |
14 | /build
15 |
16 | # Generated files
17 | .docusaurus
18 | .cache-loader
19 |
20 | # Misc
21 | .DS_Store
22 | .env.local
23 | .env.development.local
24 | .env.test.local
25 | .env.production.local
26 |
27 | npm-debug.log*
28 | yarn-debug.log*
29 | yarn-error.log*
30 |
31 | # Logs
32 | logs
33 | *.log
34 | npm-debug.log*
35 | yarn-debug.log*
36 | yarn-error.log*
37 | lerna-debug.log*
38 |
39 | # Diagnostic reports (https://nodejs.org/api/report.html)
40 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
41 |
42 | # Runtime data
43 | pids
44 | *.pid
45 | *.seed
46 | *.pid.lock
47 |
48 | # Directory for instrumented libs generated by jscoverage/JSCover
49 | lib-cov
50 |
51 | # Coverage directory used by tools like istanbul
52 | coverage
53 | *.lcov
54 |
55 | # nyc test coverage
56 | .nyc_output
57 |
58 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
59 | .grunt
60 |
61 | # Bower dependency directory (https://bower.io/)
62 | bower_components
63 |
64 | # node-waf configuration
65 | .lock-wscript
66 |
67 | # Compiled binary addons (https://nodejs.org/api/addons.html)
68 | build/Release
69 |
70 | # Dependency directories
71 | node_modules/
72 | jspm_packages/
73 |
74 | # TypeScript v1 declaration files
75 | typings/
76 |
77 | # TypeScript cache
78 | *.tsbuildinfo
79 |
80 | # Optional npm cache directory
81 | .npm
82 |
83 | # Optional eslint cache
84 | .eslintcache
85 |
86 | # Microbundle cache
87 | .rpt2_cache/
88 | .rts2_cache_cjs/
89 | .rts2_cache_es/
90 | .rts2_cache_umd/
91 |
92 | # Optional REPL history
93 | .node_repl_history
94 |
95 | # Output of 'npm pack'
96 | *.tgz
97 |
98 | # Yarn Integrity file
99 | .yarn-integrity
100 |
101 | # dotenv environment variables file
102 | .env
103 | .env.test
104 |
105 | # parcel-bundler cache (https://parceljs.org/)
106 | .cache
107 |
108 | # Next.js build output
109 | .next
110 |
111 | # Nuxt.js build / generate output
112 | .nuxt
113 | dist
114 |
115 | # Gatsby files
116 | .cache/
117 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
118 | # https://nextjs.org/blog/next-9-1#public-directory-support
119 | # public
120 |
121 | # vuepress build output
122 | .vuepress/dist
123 |
124 | # Serverless directories
125 | .serverless/
126 |
127 | # FuseBox cache
128 | .fusebox/
129 |
130 | # DynamoDB Local files
131 | .dynamodb/
132 |
133 | # TernJS port file
134 | .tern-port
135 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npx lint-staged
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "workbench.editor.labelFormat": "short",
3 | "[javascript]": {
4 | "editor.defaultFormatter": "esbenp.prettier-vscode",
5 | "editor.formatOnSave": true,
6 | "editor.codeActionsOnSave": {
7 | "source.fixAll.eslint": true
8 | }
9 | },
10 | "[typescript]": {
11 | "editor.defaultFormatter": "esbenp.prettier-vscode",
12 | "editor.formatOnSave": true,
13 | "editor.codeActionsOnSave": {
14 | "source.fixAll.eslint": true
15 | }
16 | },
17 | "[typescriptreact]": {
18 | "editor.defaultFormatter": "esbenp.prettier-vscode",
19 | "editor.formatOnSave": true,
20 | "editor.codeActionsOnSave": {
21 | "source.fixAll.eslint": true
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Cloud Annotations
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "baseUrl": "http://localhost:3000",
3 | "video": false
4 | }
5 |
--------------------------------------------------------------------------------
/cypress/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | module.exports = {
9 | plugins: ["cypress"],
10 | env: {
11 | "cypress/globals": true,
12 | },
13 | rules: {
14 | "testing-library/await-async-query": "off", // Cypress chains don't use promises
15 | "testing-library/prefer-screen-queries": "off", // screen queries don't make sense in the context of Cypress Testing Library
16 |
17 | // No Jest here
18 | "jest/expect-expect": "off",
19 | "jest/valid-expect": "off",
20 | "jest/valid-expect-in-promise": "off",
21 | "jest/no-conditional-expect": "off",
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/cypress/integration/test.spec.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | describe("test", () => {
9 | describe("Petstore", () => {
10 | it("loads Petstore page", () => {
11 | cy.visit("/petstore");
12 | navTo(
13 | [/^pet$/i, /add a new pet to the store/i],
14 | /add a new pet to the store/i
15 | );
16 | });
17 |
18 | it("renders authentication header fields", () => {
19 | cy.visit("/petstore/find-pet-by-id");
20 | cy.findByRole("button", { name: /authorize/i })
21 | .should("exist")
22 | .click();
23 | cy.get('input[placeholder="api_key"]').should("exist");
24 | });
25 | });
26 |
27 | it("loads Cloud Object Storage page", () => {
28 | cy.visit("/cos");
29 | navTo([], /generating an iam token/i);
30 | });
31 |
32 | it("loads a page with authentication", () => {
33 | cy.visit("/cos/list-buckets");
34 | cy.findByRole("button", { name: /authorize/i }).should("exist");
35 |
36 | cy.visit("/cos/create-a-bucket");
37 | cy.findByRole("button", { name: /authorize/i }).should("exist");
38 | });
39 | });
40 |
41 | /**
42 | * Navigate to page using the sidebar
43 | */
44 | function navTo(links: RegExp[], heading: RegExp) {
45 | cy.on("uncaught:exception", () => {
46 | // there is an uncaught error trying to load monaco in ci
47 | return false;
48 | });
49 |
50 | links.forEach((linkRegex) => {
51 | cy.get("nav.menu").then(($menu) => {
52 | const navElement = $menu
53 | .find("a")
54 | .toArray()
55 | .find((el) => linkRegex.test(el.innerText));
56 | if (navElement) {
57 | cy.wrap(navElement).click({ force: true });
58 | } else {
59 | cy.log(`No link or button found matching regex: ${linkRegex}`);
60 | }
61 | });
62 | });
63 |
64 | cy.findByRole("heading", { name: heading, level: 1 }).should("exist");
65 | }
66 |
--------------------------------------------------------------------------------
/cypress/plugins/index.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | const plugins: Cypress.PluginConfig = (on, config) => {
9 | // `on` is used to hook into various events Cypress emits
10 | // `config` is the resolved Cypress config
11 | };
12 |
13 | export default plugins;
14 |
--------------------------------------------------------------------------------
/cypress/support/index.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import "@testing-library/cypress/add-commands";
9 |
--------------------------------------------------------------------------------
/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.base.json",
3 | "compilerOptions": {
4 | "isolatedModules": false,
5 | "types": ["cypress", "@testing-library/cypress"]
6 | },
7 | "include": ["**/*.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/demo/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve("@docusaurus/core/lib/babel/preset")],
3 | };
4 |
--------------------------------------------------------------------------------
/demo/docs/intro.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | ---
4 |
5 | # Tutorial Intro
6 |
7 | Let's discover **Docusaurus in less than 5 minutes**.
8 |
9 | ## Getting Started
10 |
11 | Get started by **creating a new site**.
12 |
13 | ## Generate a new site
14 |
15 | Generate a new Docusaurus site using the **OpenAPI template**:
16 |
17 | ```shell
18 | npx create-docusaurus-openapi my-website
19 | ```
20 |
21 | ## Start your site
22 |
23 | Run the development server:
24 |
25 | ```shell
26 | cd my-website
27 |
28 | npx docusaurus start
29 | ```
30 |
31 | Your site starts at `http://localhost:3000`.
32 |
33 | Open `openapi.json` and make some edits: the site **reloads automatically** and displays your changes.
34 |
--------------------------------------------------------------------------------
/demo/docs/tutorial-basics/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Tutorial - Basics",
3 | "position": 2
4 | }
5 |
--------------------------------------------------------------------------------
/demo/docs/tutorial-basics/congratulations.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 6
3 | ---
4 |
5 | # Congratulations!
6 |
7 | You have just learned the **basics of Docusaurus** and made some changes to the **initial template**.
8 |
9 | Docusaurus has **much more to offer**!
10 |
11 | Have **5 more minutes**? Take a look at **[versioning](../tutorial-extras/manage-docs-versions.md)** and **[i18n](../tutorial-extras/translate-your-site.md)**.
12 |
13 | Anything **unclear** or **buggy** in this tutorial? [Please report it!](https://github.com/facebook/docusaurus/discussions/4610)
14 |
15 | ## What's next?
16 |
17 | - Read the [official documentation](https://docusaurus.io/).
18 | - Add a custom [Design and Layout](https://docusaurus.io/docs/styling-layout)
19 | - Add a [search bar](https://docusaurus.io/docs/search)
20 | - Find inspirations in the [Docusaurus showcase](https://docusaurus.io/showcase)
21 | - Get involved in the [Docusaurus Community](https://docusaurus.io/community/support)
22 |
--------------------------------------------------------------------------------
/demo/docs/tutorial-basics/create-a-blog-post.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | ---
4 |
5 | # Create a Blog Post
6 |
7 | Docusaurus creates a **page for each blog post**, but also a **blog index page**, a **tag system**, an **RSS** feed...
8 |
9 | ## Create your first Post
10 |
11 | Create a file at `blog/2021-02-28-greetings.md`:
12 |
13 | ```md title="blog/2021-02-28-greetings.md"
14 | ---
15 | slug: greetings
16 | title: Greetings!
17 | authors:
18 | - name: Joel Marcey
19 | title: Co-creator of Docusaurus 1
20 | url: https://github.com/JoelMarcey
21 | image_url: https://github.com/JoelMarcey.png
22 | - name: Sébastien Lorber
23 | title: Docusaurus maintainer
24 | url: https://sebastienlorber.com
25 | image_url: https://github.com/slorber.png
26 | tags: [greetings]
27 | ---
28 |
29 | Congratulations, you have made your first post!
30 |
31 | Feel free to play around and edit this post as much you like.
32 | ```
33 |
34 | A new blog post is now available at `http://localhost:3000/blog/greetings`.
35 |
--------------------------------------------------------------------------------
/demo/docs/tutorial-basics/create-a-document.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # Create a Document
6 |
7 | Documents are **groups of pages** connected through:
8 |
9 | - a **sidebar**
10 | - **previous/next navigation**
11 | - **versioning**
12 |
13 | ## Create your first Doc
14 |
15 | Create a markdown file at `docs/hello.md`:
16 |
17 | ```md title="docs/hello.md"
18 | # Hello
19 |
20 | This is my **first Docusaurus document**!
21 | ```
22 |
23 | A new document is now available at `http://localhost:3000/docs/hello`.
24 |
25 | ## Configure the Sidebar
26 |
27 | Docusaurus automatically **creates a sidebar** from the `docs` folder.
28 |
29 | Add metadatas to customize the sidebar label and position:
30 |
31 | ```md title="docs/hello.md" {1-4}
32 | ---
33 | sidebar_label: "Hi!"
34 | sidebar_position: 3
35 | ---
36 |
37 | # Hello
38 |
39 | This is my **first Docusaurus document**!
40 | ```
41 |
42 | It is also possible to create your sidebar explicitly in `sidebars.js`:
43 |
44 | ```diff title="sidebars.js"
45 | module.exports = {
46 | tutorialSidebar: [
47 | {
48 | type: 'category',
49 | label: 'Tutorial',
50 | - items: [...],
51 | + items: ['hello'],
52 | },
53 | ],
54 | };
55 | ```
56 |
--------------------------------------------------------------------------------
/demo/docs/tutorial-basics/create-a-page.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | ---
4 |
5 | # Create a Page
6 |
7 | Add **Markdown or React** files to `src/pages` to create a **standalone page**:
8 |
9 | - `src/pages/index.js` -> `localhost:3000/`
10 | - `src/pages/foo.md` -> `localhost:3000/foo`
11 | - `src/pages/foo/bar.js` -> `localhost:3000/foo/bar`
12 |
13 | ## Create your first React Page
14 |
15 | Create a file at `src/pages/my-react-page.js`:
16 |
17 | ```jsx title="src/pages/my-react-page.js"
18 | import React from "react";
19 | import Layout from "@theme/Layout";
20 |
21 | export default function MyReactPage() {
22 | return (
23 |
24 | My React page
25 | This is a React page
26 |
27 | );
28 | }
29 | ```
30 |
31 | A new page is now available at `http://localhost:3000/my-react-page`.
32 |
33 | ## Create your first Markdown Page
34 |
35 | Create a file at `src/pages/my-markdown-page.md`:
36 |
37 | ```mdx title="src/pages/my-markdown-page.md"
38 | # My Markdown page
39 |
40 | This is a Markdown page
41 | ```
42 |
43 | A new page is now available at `http://localhost:3000/my-markdown-page`.
44 |
--------------------------------------------------------------------------------
/demo/docs/tutorial-basics/deploy-your-site.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | ---
4 |
5 | # Deploy your site
6 |
7 | Docusaurus is a **static-site-generator** (also called **[Jamstack](https://jamstack.org/)**).
8 |
9 | It builds your site as simple **static HTML, JavaScript and CSS files**.
10 |
11 | ## Build your site
12 |
13 | Build your site **for production**:
14 |
15 | ```bash
16 | npm run build
17 | ```
18 |
19 | The static files are generated in the `build` folder.
20 |
21 | ## Deploy your site
22 |
23 | Test your production build locally:
24 |
25 | ```bash
26 | npm run serve
27 | ```
28 |
29 | The `build` folder is now served at `http://localhost:3000/`.
30 |
31 | You can now deploy the `build` folder **almost anywhere** easily, **for free** or very small cost (read the **[Deployment Guide](https://docusaurus.io/docs/deployment)**).
32 |
--------------------------------------------------------------------------------
/demo/docs/tutorial-basics/markdown-features.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | ---
4 |
5 | # Markdown Features
6 |
7 | Docusaurus supports **[Markdown](https://daringfireball.net/projects/markdown/syntax)** and a few **additional features**.
8 |
9 | ## Front Matter
10 |
11 | Markdown documents have metadata at the top called [Front Matter](https://jekyllrb.com/docs/front-matter/):
12 |
13 | ```text title="my-doc.md"
14 | // highlight-start
15 | ---
16 | id: my-doc-id
17 | title: My document title
18 | description: My document description
19 | slug: /my-custom-url
20 | ---
21 | // highlight-end
22 |
23 | ## Markdown heading
24 |
25 | Markdown text with [links](./hello.md)
26 | ```
27 |
28 | ## Links
29 |
30 | Regular Markdown links are supported, using url paths or relative file paths.
31 |
32 | ```md
33 | Let's see how to [Create a page](/create-a-page).
34 | ```
35 |
36 | ```md
37 | Let's see how to [Create a page](./create-a-page.md).
38 | ```
39 |
40 | **Result:** Let's see how to [Create a page](./create-a-page.md).
41 |
42 | ## Images
43 |
44 | Regular Markdown images are supported.
45 |
46 | Add an image at `static/img/docusaurus.png` and display it in Markdown:
47 |
48 | ```md
49 | 
50 | ```
51 |
52 | 
53 |
54 | ## Code Blocks
55 |
56 | Markdown code blocks are supported with Syntax highlighting.
57 |
58 | ```jsx title="src/components/HelloDocusaurus.js"
59 | function HelloDocusaurus() {
60 | return (
61 |
Hello, Docusaurus!
62 | )
63 | }
64 | ```
65 |
66 | ```jsx title="src/components/HelloDocusaurus.js"
67 | function HelloDocusaurus() {
68 | return Hello, Docusaurus!
;
69 | }
70 | ```
71 |
72 | ## Admonitions
73 |
74 | Docusaurus has a special syntax to create admonitions and callouts:
75 |
76 | :::tip My tip
77 |
78 | Use this awesome feature option
79 |
80 | :::
81 |
82 | :::danger Take care
83 |
84 | This action is dangerous
85 |
86 | :::
87 |
88 | :::tip My tip
89 |
90 | Use this awesome feature option
91 |
92 | :::
93 |
94 | :::danger Take care
95 |
96 | This action is dangerous
97 |
98 | :::
99 |
100 | ## MDX and React Components
101 |
102 | [MDX](https://mdxjs.com/) can make your documentation more **interactive** and allows using any **React components inside Markdown**:
103 |
104 | ```jsx
105 | export const Highlight = ({children, color}) => (
106 | {
115 | alert(`You clicked the color ${color} with label ${children}`)
116 | }}>
117 | {children}
118 |
119 | );
120 |
121 | This is Docusaurus green !
122 |
123 | This is Facebook blue !
124 | ```
125 |
126 | export const Highlight = ({ children, color }) => (
127 | {
136 | alert(`You clicked the color ${color} with label ${children}`);
137 | }}
138 | >
139 | {children}
140 |
141 | );
142 |
143 | This is Docusaurus green !
144 |
145 | This is Facebook blue !
146 |
--------------------------------------------------------------------------------
/demo/docs/tutorial-extras/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Tutorial - Extras",
3 | "position": 3
4 | }
5 |
--------------------------------------------------------------------------------
/demo/docs/tutorial-extras/manage-docs-versions.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | ---
4 |
5 | # Manage Docs Versions
6 |
7 | Docusaurus can manage multiple versions of your docs.
8 |
9 | ## Create a docs version
10 |
11 | Release a version 1.0 of your project:
12 |
13 | ```bash
14 | npm run docusaurus docs:version 1.0
15 | ```
16 |
17 | The `docs` folder is copied into `versioned_docs/version-1.0` and `versions.json` is created.
18 |
19 | Your docs now have 2 versions:
20 |
21 | - `1.0` at `http://localhost:3000/docs/` for the version 1.0 docs
22 | - `current` at `http://localhost:3000/docs/next/` for the **upcoming, unreleased docs**
23 |
24 | ## Add a Version Dropdown
25 |
26 | To navigate seamlessly across versions, add a version dropdown.
27 |
28 | Modify the `docusaurus.config.js` file:
29 |
30 | ```js title="docusaurus.config.js"
31 | module.exports = {
32 | themeConfig: {
33 | navbar: {
34 | items: [
35 | // highlight-start
36 | {
37 | type: "docsVersionDropdown",
38 | },
39 | // highlight-end
40 | ],
41 | },
42 | },
43 | };
44 | ```
45 |
46 | The docs version dropdown appears in your navbar:
47 |
48 | 
49 |
50 | ## Update an existing version
51 |
52 | It is possible to edit versioned docs in their respective folder:
53 |
54 | - `versioned_docs/version-1.0/hello.md` updates `http://localhost:3000/docs/hello`
55 | - `docs/hello.md` updates `http://localhost:3000/docs/next/hello`
56 |
--------------------------------------------------------------------------------
/demo/docs/tutorial-extras/translate-your-site.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # Translate your site
6 |
7 | Let's translate `docs/intro.md` to French.
8 |
9 | ## Configure i18n
10 |
11 | Modify `docusaurus.config.js` to add support for the `fr` locale:
12 |
13 | ```js title="docusaurus.config.js"
14 | module.exports = {
15 | i18n: {
16 | defaultLocale: "en",
17 | locales: ["en", "fr"],
18 | },
19 | };
20 | ```
21 |
22 | ## Translate a doc
23 |
24 | Copy the `docs/intro.md` file to the `i18n/fr` folder:
25 |
26 | ```bash
27 | mkdir -p i18n/fr/docusaurus-plugin-content-docs/current/
28 |
29 | cp docs/intro.md i18n/fr/docusaurus-plugin-content-docs/current/intro.md
30 | ```
31 |
32 | Translate `i18n/fr/docusaurus-plugin-content-docs/current/intro.md` in French.
33 |
34 | ## Start your localized site
35 |
36 | Start your site on the French locale:
37 |
38 | ```bash
39 | npm run start -- --locale fr
40 | ```
41 |
42 | Your localized site is accessible at `http://localhost:3000/fr/` and the `Getting Started` page is translated.
43 |
44 | :::caution
45 |
46 | In development, you can only use one locale at a same time.
47 |
48 | :::
49 |
50 | ## Add a Locale Dropdown
51 |
52 | To navigate seamlessly across languages, add a locale dropdown.
53 |
54 | Modify the `docusaurus.config.js` file:
55 |
56 | ```js title="docusaurus.config.js"
57 | module.exports = {
58 | themeConfig: {
59 | navbar: {
60 | items: [
61 | // highlight-start
62 | {
63 | type: "localeDropdown",
64 | },
65 | // highlight-end
66 | ],
67 | },
68 | },
69 | };
70 | ```
71 |
72 | The locale dropdown now appears in your navbar:
73 |
74 | 
75 |
76 | ## Build your localized site
77 |
78 | Build your site for a specific locale:
79 |
80 | ```bash
81 | npm run build -- --locale fr
82 | ```
83 |
84 | Or build your site to include all the locales at once:
85 |
86 | ```bash
87 | npm run build
88 | ```
89 |
--------------------------------------------------------------------------------
/demo/examples/custom-overview.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 0
3 | slug: /
4 | ---
5 |
6 | # Custom Overview
7 |
8 | This is a custom file written in mdx.
9 |
--------------------------------------------------------------------------------
/demo/examples/food/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Foods",
3 | "collapsed": true
4 | }
5 |
--------------------------------------------------------------------------------
/demo/examples/food/burgers/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Burger Store",
3 | "collapsed": true
4 | }
5 |
--------------------------------------------------------------------------------
/demo/examples/food/burgers/openapi.yaml:
--------------------------------------------------------------------------------
1 | openapi: 3.0.3
2 | info:
3 | title: Burger Example
4 | version: 1.0.0
5 | description: Sample description.
6 | paths:
7 | /flavors:
8 | get:
9 | summary: List All Burgers
10 | description: Burgers
11 | parameters:
12 | - in: query
13 | name: Calories<
14 | schema:
15 | type: string
16 | description: Calories less than the given amount.
17 | responses:
18 | 200:
19 | description: OK
20 |
--------------------------------------------------------------------------------
/demo/examples/food/yogurtstore/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Yogurt Store",
3 | "collapsed": true
4 | }
5 |
--------------------------------------------------------------------------------
/demo/examples/food/yogurtstore/openapi.yaml:
--------------------------------------------------------------------------------
1 | openapi: 3.0.3
2 | info:
3 | title: Frozen Yogurt Example
4 | version: 1.0.0
5 | description: Sample description.
6 | paths:
7 | /flavors:
8 | get:
9 | summary: List All Flavors
10 | description: Froyo's the best!
11 | responses:
12 | 200:
13 | description: OK
14 |
--------------------------------------------------------------------------------
/demo/examples/openapi-array-query-params.yaml:
--------------------------------------------------------------------------------
1 | openapi: 3.0.3
2 | info:
3 | version: 1.0.0
4 | title: ""
5 | servers:
6 | - url: https://example.com
7 | paths:
8 | /Things:
9 | get:
10 | summary: View Things
11 | parameters:
12 | - name: "arrayParam"
13 | in: "query"
14 | required: false
15 | description: "You can pass 0, 1 or 2 occurrences of this in the query string"
16 | style: "form"
17 | explode: true
18 | schema:
19 | type: "array"
20 | maxItems: 2
21 | items:
22 | type: "string"
23 | responses:
24 | "200":
25 | description: OK
26 | /Stuff:
27 | get:
28 | summary: View Stuff
29 | parameters:
30 | - name: "arrayParam"
31 | in: "query"
32 | required: false
33 | description: "You can pass 0, 1 or 2 occurrences of this in the query string"
34 | style: "pipeDelimited"
35 | explode: false
36 | schema:
37 | type: "array"
38 | maxItems: 2
39 | items:
40 | type: "string"
41 | responses:
42 | "200":
43 | description: OK
44 |
--------------------------------------------------------------------------------
/demo/examples/openapi-issue-21.json:
--------------------------------------------------------------------------------
1 | {
2 | "openapi": "",
3 | "info": {
4 | "title": "",
5 | "version": ""
6 | },
7 | "paths": {
8 | "/health": {
9 | "get": {
10 | "responses": {
11 | "200": {
12 | "description": "OK"
13 | }
14 | }
15 | }
16 | },
17 | "/api/account/links/{partnerId}": {
18 | "post": {
19 | "description": "This method receives an authorization token. That token will be used to get the user's tokens."
20 | }
21 | },
22 | "/account/pairs/{pairId}/linking-caps": {
23 | "get": {}
24 | },
25 | "/api/aoi/subscriptions": {
26 | "post": {
27 | "description": "This method will create a new AOI subscription"
28 | }
29 | },
30 | "/api/aoi/subscriptions/pair/{pairId}": {
31 | "get": {
32 | "description": "This method will return the AOI subscription based on the user session and the linked account"
33 | },
34 | "delete": {
35 | "description": "This method will delete the current aoi subscription for a given pair"
36 | }
37 | },
38 | "/api/exchange/orders/{transactionId}": {
39 | "get": {}
40 | },
41 | "/api/feedback/contact-us": {
42 | "post": {}
43 | },
44 | "/maintenance/partners/{partnerId}/accounts/{accountId}/history": {
45 | "delete": {}
46 | },
47 | "/partners/accounts/{accountId}/links/{partnerId}/exists": {
48 | "get": {
49 | "description": "Proxy to PAUL's check if link exists"
50 | }
51 | }
52 | },
53 | "components": {}
54 | }
55 |
--------------------------------------------------------------------------------
/demo/examples/openapi-issue-220.yaml:
--------------------------------------------------------------------------------
1 | openapi: 3.0.3
2 | info:
3 | version: 1.0.0
4 | title: ""
5 | servers:
6 | - url: https://example.com
7 | security:
8 | - basic_auth: []
9 | paths:
10 | /Calls:
11 | post:
12 | tags:
13 | - Calls
14 | operationId: create_a_call
15 | summary: Create a Call
16 | requestBody:
17 | required: true
18 | content:
19 | application/x-www-form-urlencoded:
20 | schema:
21 | type: object
22 | properties:
23 | StatusCallback:
24 | type: string
25 | example: https://your-api-endpoint.com/path
26 | StatusCallbackEvent:
27 | type: array
28 | items:
29 | type: string
30 | enum:
31 | - initiated
32 | - ringing
33 | - answered
34 | - completed
35 | example:
36 | - completed
37 | encoding:
38 | StatusCallbackEvent:
39 | style: form
40 | explode: true
41 | responses:
42 | "200":
43 | description: OK
44 |
--------------------------------------------------------------------------------
/demo/examples/petstore/_category_.yaml:
--------------------------------------------------------------------------------
1 | label: My Custom Petstore
2 |
--------------------------------------------------------------------------------
/demo/examples/petstore/my-intro.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 0
3 | ---
4 |
5 | # My intro
6 |
7 | This is a custom intro file for Petstore
8 |
--------------------------------------------------------------------------------
/demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "version": "0.7.6",
4 | "private": true,
5 | "scripts": {
6 | "docusaurus": "docusaurus",
7 | "start": "docusaurus start",
8 | "build": "docusaurus build",
9 | "swizzle": "docusaurus swizzle",
10 | "deploy": "docusaurus deploy",
11 | "clear": "docusaurus clear",
12 | "serve": "docusaurus serve",
13 | "write-translations": "docusaurus write-translations",
14 | "write-heading-ids": "docusaurus write-heading-ids"
15 | },
16 | "dependencies": {
17 | "@docusaurus/core": "^3.6.0",
18 | "@docusaurus/faster": "^3.6.0",
19 | "@svgr/webpack": "^5.5.0",
20 | "clsx": "^1.2.1",
21 | "docusaurus-preset-openapi": "^0.7.6",
22 | "file-loader": "^6.2.0",
23 | "prism-react-renderer": "^2.1.0",
24 | "react": "^18.0.0",
25 | "react-dom": "^18.0.0",
26 | "url-loader": "^4.1.1"
27 | },
28 | "browserslist": {
29 | "production": [
30 | ">0.5%",
31 | "not dead",
32 | "not op_mini all"
33 | ],
34 | "development": [
35 | "last 1 chrome version",
36 | "last 1 firefox version",
37 | "last 1 safari version"
38 | ]
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/demo/sandbox.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "infiniteLoopProtection": true,
3 | "hardReloadOnChange": true,
4 | "view": "browser",
5 | "template": "docusaurus",
6 | "container": {
7 | "startScript": "watch",
8 | "node": "14"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/demo/sidebars.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Creating a sidebar enables you to:
3 | - create an ordered group of docs
4 | - render a sidebar for each doc of that group
5 | - provide next/previous navigation
6 |
7 | The sidebars can be generated from the filesystem, or explicitly defined here.
8 |
9 | Create as many sidebars as you want.
10 | */
11 |
12 | // @ts-check
13 |
14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
15 | const sidebars = {
16 | // By default, Docusaurus generates a sidebar from the docs folder structure
17 | tutorialSidebar: [{ type: "autogenerated", dirName: "." }],
18 |
19 | // But you can create a sidebar manually
20 | /*
21 | tutorialSidebar: [
22 | {
23 | type: 'category',
24 | label: 'Tutorial',
25 | items: ['hello'],
26 | },
27 | ],
28 | */
29 | };
30 |
31 | export default sidebars;
32 |
--------------------------------------------------------------------------------
/demo/src/components/HomepageFeatures.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import clsx from "clsx";
3 | import styles from "./HomepageFeatures.module.css";
4 |
5 | const FeatureList = [
6 | {
7 | title: "Easy to Use",
8 | Svg: require("../../static/img/undraw_docusaurus_mountain.svg").default,
9 | description: (
10 | <>
11 | Docusaurus was designed from the ground up to be easily installed and
12 | used to get your website up and running quickly.
13 | >
14 | ),
15 | },
16 | {
17 | title: "Focus on What Matters",
18 | Svg: require("../../static/img/undraw_docusaurus_tree.svg").default,
19 | description: (
20 | <>
21 | Docusaurus lets you focus on your docs, and we'll do the chores. Go
22 | ahead and move your docs into the docs
directory.
23 | >
24 | ),
25 | },
26 | {
27 | title: "Powered by React",
28 | Svg: require("../../static/img/undraw_docusaurus_react.svg").default,
29 | description: (
30 | <>
31 | Extend or customize your website layout by reusing React. Docusaurus can
32 | be extended while reusing the same header and footer.
33 | >
34 | ),
35 | },
36 | ];
37 |
38 | function Feature({ Svg, title, description }) {
39 | return (
40 |
41 |
42 |
43 |
44 |
45 |
{title}
46 |
{description}
47 |
48 |
49 | );
50 | }
51 |
52 | export default function HomepageFeatures() {
53 | return (
54 |
55 |
56 |
57 | {FeatureList.map((props, idx) => (
58 |
59 | ))}
60 |
61 |
62 |
63 | );
64 | }
65 |
--------------------------------------------------------------------------------
/demo/src/components/HomepageFeatures.module.css:
--------------------------------------------------------------------------------
1 | .features {
2 | display: flex;
3 | align-items: center;
4 | padding: 2rem 0;
5 | width: 100%;
6 | }
7 |
8 | .featureSvg {
9 | height: 200px;
10 | width: 200px;
11 | }
12 |
--------------------------------------------------------------------------------
/demo/src/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import clsx from "clsx";
3 | import Layout from "@theme/Layout";
4 | import Link from "@docusaurus/Link";
5 | import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
6 | import styles from "./index.module.css";
7 | import HomepageFeatures from "../components/HomepageFeatures";
8 |
9 | function HomepageHeader() {
10 | const { siteConfig } = useDocusaurusContext();
11 | return (
12 |
26 | );
27 | }
28 |
29 | export default function Home() {
30 | const { siteConfig } = useDocusaurusContext();
31 | return (
32 |
36 |
37 |
38 |
39 |
40 |
41 | );
42 | }
43 |
--------------------------------------------------------------------------------
/demo/src/pages/index.module.css:
--------------------------------------------------------------------------------
1 | /**
2 | * CSS files with the .module.css suffix will be treated as CSS modules
3 | * and scoped locally.
4 | */
5 |
6 | .heroBanner {
7 | padding: 4rem 0;
8 | text-align: center;
9 | position: relative;
10 | overflow: hidden;
11 | }
12 |
13 | @media screen and (max-width: 966px) {
14 | .heroBanner {
15 | padding: 2rem;
16 | }
17 | }
18 |
19 | .buttons {
20 | display: flex;
21 | align-items: center;
22 | justify-content: center;
23 | }
24 |
--------------------------------------------------------------------------------
/demo/src/pages/markdown-page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Markdown page example
3 | ---
4 |
5 | # Markdown page example
6 |
7 | You don't need React to write simple standalone pages.
8 |
--------------------------------------------------------------------------------
/demo/static/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/demo/static/.nojekyll
--------------------------------------------------------------------------------
/demo/static/img/docusaurus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/demo/static/img/docusaurus.png
--------------------------------------------------------------------------------
/demo/static/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/demo/static/img/favicon.ico
--------------------------------------------------------------------------------
/demo/static/img/tutorial/docsVersionDropdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/demo/static/img/tutorial/docsVersionDropdown.png
--------------------------------------------------------------------------------
/demo/static/img/tutorial/localeDropdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/demo/static/img/tutorial/localeDropdown.png
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | module.exports = {
9 | preset: "ts-jest",
10 | testEnvironment: "node",
11 | roots: [
12 | "/packages/docusaurus-plugin-openapi/src",
13 | "/packages/docusaurus-preset-openapi/src",
14 | "/packages/docusaurus-theme-openapi/src",
15 | ],
16 | };
17 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.7.6",
3 | "npmClient": "yarn",
4 | "useWorkspaces": true
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "root",
4 | "workspaces": {
5 | "packages": [
6 | "packages/*",
7 | "demo"
8 | ]
9 | },
10 | "scripts": {
11 | "prepare": "husky install",
12 | "watch": "lerna run watch --parallel",
13 | "watch:demo": "nodemon --watch \"./packages/*/lib/**/*.*\" --exec \"yarn start --no-open\"",
14 | "build": "yarn build-packages && yarn build-demo",
15 | "build-packages": "lerna run build --no-private --stream",
16 | "build-demo": "yarn workspace demo build",
17 | "serve": "yarn workspace demo serve",
18 | "start": "yarn workspace demo start",
19 | "cy:run": "cypress run",
20 | "cy:open": "cypress open",
21 | "format": "prettier . --check --ignore-unknown --ignore-path .gitignore",
22 | "lint": "eslint . --ignore-path .gitignore --ext .ts,.tsx,.js",
23 | "test": "jest",
24 | "test:cypress:dev": "start-server-and-test watch:demo http://localhost:3000 cy:open",
25 | "test:cypress": "start-server-and-test serve http://localhost:3000 cy:run",
26 | "release:changelog": "scripts/changelog.ts",
27 | "release:version": "scripts/version.ts",
28 | "release:publish": "scripts/publish.ts",
29 | "clean": "rm -rf node_modules build demo/.docusaurus demo/build demo/node_modules && find packages -name node_modules -type d -maxdepth 2 -exec rm -rf {} + && find packages -name dist -type d -maxdepth 2 -exec rm -rf {} + && find packages -name lib -type d -maxdepth 2 -exec rm -rf {} + && find packages -name lib-next -type d -maxdepth 2 -exec rm -rf {} +"
30 | },
31 | "devDependencies": {
32 | "@babel/cli": "^7.16.0",
33 | "@babel/core": "^7.16.0",
34 | "@babel/eslint-parser": "^7.16.3",
35 | "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0",
36 | "@babel/plugin-proposal-optional-chaining": "^7.16.0",
37 | "@babel/plugin-transform-modules-commonjs": "^7.16.0",
38 | "@babel/preset-typescript": "^7.16.0",
39 | "@testing-library/cypress": "^8.0.1",
40 | "@types/jest": "^27.0.2",
41 | "@types/node": "^18.0.0",
42 | "@typescript-eslint/eslint-plugin": "^6.0.0",
43 | "@typescript-eslint/parser": "^6.0.0",
44 | "babel-eslint": "^10.0.0",
45 | "cross-env": "^7.0.3",
46 | "cypress": "^8.7.0",
47 | "eslint": "^7.5.0",
48 | "eslint-config-react-app": "^6.0.0",
49 | "eslint-plugin-cypress": "^2.12.1",
50 | "eslint-plugin-flowtype": "^5.2.0",
51 | "eslint-plugin-header": "^3.1.1",
52 | "eslint-plugin-import": "^2.22.0",
53 | "eslint-plugin-jest": "^25.0.6",
54 | "eslint-plugin-jest-dom": "^3.9.2",
55 | "eslint-plugin-jsx-a11y": "^6.3.1",
56 | "eslint-plugin-react": "^7.20.3",
57 | "eslint-plugin-react-hooks": "^4.0.8",
58 | "eslint-plugin-testing-library": "^4.12.4",
59 | "husky": "^7.0.2",
60 | "jest": "^27.3.1",
61 | "lerna": "^4.0.0",
62 | "lint-staged": "^11.2.3",
63 | "nodemon": "^2.0.15",
64 | "prettier": "^2.4.1",
65 | "semver": "^7.3.5",
66 | "start-server-and-test": "^1.14.0",
67 | "ts-jest": "^27.0.6",
68 | "ts-node": "^10.9.1",
69 | "typescript": "^5.2.2"
70 | },
71 | "lint-staged": {
72 | "**/*": "prettier --write --ignore-unknown"
73 | },
74 | "engines": {
75 | "node": ">=14"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/packages/create-docusaurus-openapi/README.md:
--------------------------------------------------------------------------------
1 | # `create-docusaurus-openapi`
2 |
--------------------------------------------------------------------------------
/packages/create-docusaurus-openapi/bin/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | /* ============================================================================
3 | * Copyright (c) Cloud Annotations
4 | *
5 | * This source code is licensed under the MIT license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | * ========================================================================== */
8 |
9 | // @ts-check
10 |
11 | const path = require("path");
12 |
13 | const logger = require("@docusaurus/logger").default;
14 | const program = require("commander");
15 | const semver = require("semver");
16 |
17 | const { default: init } = require("../lib");
18 | const requiredVersion = require("../package.json").engines.node;
19 |
20 | if (!semver.satisfies(process.version, requiredVersion)) {
21 | logger.error("Minimum Node.js version not met :(");
22 | logger.info`You are using Node.js number=${process.version}, Requirement: Node.js number=${requiredVersion}.`;
23 | process.exit(1);
24 | }
25 |
26 | function wrapCommand(fn) {
27 | return (...args) =>
28 | fn(...args).catch((err) => {
29 | logger.error(err.stack);
30 | process.exitCode = 1;
31 | });
32 | }
33 |
34 | program
35 | .version(require("../package.json").version)
36 | .usage(" [options]");
37 |
38 | program
39 | .command("init [siteName] [template] [rootDir]", { isDefault: true })
40 | .option("--use-npm")
41 | .option("--skip-install")
42 | .option("--typescript")
43 | .description("Initialize website.")
44 | .action(
45 | (
46 | siteName,
47 | template,
48 | rootDir = ".",
49 | { useNpm, skipInstall, typescript } = {}
50 | ) => {
51 | wrapCommand(init)(path.resolve(rootDir), siteName, template, {
52 | useNpm,
53 | skipInstall,
54 | typescript,
55 | });
56 | }
57 | );
58 |
59 | program.arguments("").action((cmd) => {
60 | program.outputHelp();
61 | logger.error`Unknown command code=${cmd}.`;
62 | });
63 |
64 | program.parse(process.argv);
65 |
66 | if (!process.argv.slice(1).length) {
67 | program.outputHelp();
68 | }
69 |
--------------------------------------------------------------------------------
/packages/create-docusaurus-openapi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "create-docusaurus-openapi",
3 | "version": "0.7.6",
4 | "description": "Create Docusaurus apps easily.",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/cloud-annotations/docusaurus-openapi.git",
8 | "directory": "packages/create-docusaurus-openapi"
9 | },
10 | "bugs": {
11 | "url": "https://github.com/cloud-annotations/docusaurus-openapi/issues"
12 | },
13 | "scripts": {
14 | "create-docusaurus-openapi": "create-docusaurus-openapi",
15 | "build": "tsc",
16 | "watch": "tsc --watch"
17 | },
18 | "bin": {
19 | "create-docusaurus-openapi": "bin/index.js"
20 | },
21 | "publishConfig": {
22 | "access": "public"
23 | },
24 | "license": "MIT",
25 | "dependencies": {
26 | "@docusaurus/logger": "^3.6.0",
27 | "commander": "^5.1.0",
28 | "fs-extra": "^11.0.0",
29 | "lodash": "^4.17.20",
30 | "prompts": "^2.4.1",
31 | "semver": "^7.3.4",
32 | "shelljs": "^0.8.4",
33 | "supports-color": "^8.1.1",
34 | "tslib": "^2.3.1"
35 | },
36 | "engines": {
37 | "node": ">=18"
38 | },
39 | "devDependencies": {
40 | "@types/fs-extra": "^11.0.0",
41 | "@types/prompts": "^2.0.9",
42 | "@types/shelljs": "^0.8.6",
43 | "@types/supports-color": "^8.1.1"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/packages/create-docusaurus-openapi/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "lib"
5 | },
6 | "include": ["src"]
7 | }
8 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/README.md:
--------------------------------------------------------------------------------
1 | Docusaurus OpenAPI
2 |
3 |
4 |
5 | OpenAPI plugin for generating API reference docs in Docusaurus v2.
6 |
7 |
8 |
9 |
10 |
11 | 
12 |
13 |
14 |
15 | ## Multiple OpenAPI Definitions
16 |
17 | To have more than one OpenAPI pages, add additional OpenAPI plugin instances:
18 |
19 | ```js
20 | /* docusaurus.config.js */
21 |
22 | {
23 | presets: [
24 | [
25 | 'docusaurus-preset-openapi',
26 | {
27 | api: {
28 | // id: 'cars', // omitted => default instance
29 | path: 'cars/openapi.json',
30 | routeBasePath: 'cars',
31 | // ... other options
32 | },
33 | },
34 | ],
35 | ],
36 | plugins: [
37 | [
38 | 'docusaurus-plugin-openapi',
39 | {
40 | id: 'trains',
41 | path: 'trains/openapi.json',
42 | routeBasePath: 'trains',
43 | // ... other options
44 | },
45 | ],
46 | [
47 | 'docusaurus-plugin-openapi',
48 | {
49 | id: 'bikes',
50 | path: 'bikes/openapi.json',
51 | routeBasePath: 'bikes',
52 | // ... other options
53 | },
54 | ],
55 | ],
56 | }
57 | ```
58 |
59 | This will create routes for `/cars`, `/trains` and `/bikes`.
60 |
61 | > **Note:** One instance of the plugin is included in the preset. All additional plugin instances will require an `id`.
62 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docusaurus-plugin-openapi",
3 | "description": "OpenAPI plugin for Docusaurus.",
4 | "version": "0.7.6",
5 | "license": "MIT",
6 | "publishConfig": {
7 | "access": "public"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/cloud-annotations/docusaurus-openapi.git",
12 | "directory": "packages/docusaurus-plugin-openapi"
13 | },
14 | "bugs": {
15 | "url": "https://github.com/cloud-annotations/docusaurus-openapi/issues"
16 | },
17 | "main": "lib/index.js",
18 | "types": "src/plugin-openapi.d.ts",
19 | "scripts": {
20 | "build": "tsc",
21 | "watch": "tsc --watch"
22 | },
23 | "devDependencies": {
24 | "@docusaurus/module-type-aliases": "^3.6.0",
25 | "@docusaurus/types": "^3.6.0",
26 | "@types/js-yaml": "^4.0.5",
27 | "@types/json-schema": "^7.0.9",
28 | "@types/lodash": "^4.14.176",
29 | "@types/postman-collection": "^3.5.3",
30 | "utility-types": "^3.10.0"
31 | },
32 | "dependencies": {
33 | "@docusaurus/mdx-loader": "^3.6.0",
34 | "@docusaurus/plugin-content-docs": "^3.6.0",
35 | "@docusaurus/utils": "^3.6.0",
36 | "@docusaurus/utils-common": "^3.6.0",
37 | "@docusaurus/utils-validation": "^3.6.0",
38 | "chalk": "^4.1.2",
39 | "clsx": "^1.2.1",
40 | "js-yaml": "^4.1.0",
41 | "json-refs": "^3.0.15",
42 | "json-schema-resolve-allof": "^1.5.0",
43 | "lodash": "^4.17.20",
44 | "openapi-to-postmanv2": "^4.20.1",
45 | "postman-collection": "^4.1.0",
46 | "webpack": "^5.95.0"
47 | },
48 | "peerDependencies": {
49 | "react": "^18.0.0",
50 | "react-dom": "^18.0.0"
51 | },
52 | "engines": {
53 | "node": ">=18"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/docs/frontMatter.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | /**
9 | * Copyright (c) Facebook, Inc. and its affiliates.
10 | *
11 | * This source code is licensed under the MIT license found in the
12 | * LICENSE file in the root directory of this source tree.
13 | */
14 |
15 | /**
16 | * Taken and adapted from:
17 | * https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-plugin-content-docs/src/frontMatter.ts
18 | */
19 |
20 | import type { DocFrontMatter } from "@docusaurus/plugin-content-docs";
21 | import {
22 | JoiFrontMatter as Joi, // Custom instance for front matter
23 | URISchema,
24 | FrontMatterTagsSchema,
25 | FrontMatterTOCHeadingLevels,
26 | validateFrontMatter,
27 | } from "@docusaurus/utils-validation";
28 |
29 | // NOTE: we don't add any default value on purpose here
30 | // We don't want default values to magically appear in doc metadata and props
31 | // While the user did not provide those values explicitly
32 | // We use default values in code instead
33 | const DocFrontMatterSchema = Joi.object({
34 | id: Joi.string(),
35 | // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
36 | title: Joi.string().allow(""),
37 | hide_title: Joi.boolean(),
38 | hide_table_of_contents: Joi.boolean(),
39 | keywords: Joi.array().items(Joi.string().required()),
40 | image: URISchema,
41 | // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
42 | description: Joi.string().allow(""),
43 | slug: Joi.string(),
44 | sidebar_label: Joi.string(),
45 | sidebar_position: Joi.number(),
46 | sidebar_class_name: Joi.string(),
47 | sidebar_custom_props: Joi.object().unknown(),
48 | displayed_sidebar: Joi.string().allow(null),
49 | tags: FrontMatterTagsSchema,
50 | pagination_label: Joi.string(),
51 | custom_edit_url: URISchema.allow("", null),
52 | parse_number_prefixes: Joi.boolean(),
53 | pagination_next: Joi.string().allow(null),
54 | pagination_prev: Joi.string().allow(null),
55 | draft: Joi.boolean(),
56 | ...FrontMatterTOCHeadingLevels,
57 | }).unknown();
58 |
59 | export function validateDocFrontMatter(frontMatter: {
60 | [key: string]: unknown;
61 | }): DocFrontMatter {
62 | return validateFrontMatter(frontMatter, DocFrontMatterSchema);
63 | }
64 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/docs/numberPrefix.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | /**
9 | * Copyright (c) Facebook, Inc. and its affiliates.
10 | *
11 | * This source code is licensed under the MIT license found in the
12 | * LICENSE file in the root directory of this source tree.
13 | */
14 |
15 | /**
16 | * Taken and adapted from:
17 | * https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-plugin-content-docs/src/numberPrefix.ts
18 | */
19 |
20 | import type { NumberPrefixParser } from "@docusaurus/plugin-content-docs";
21 |
22 | // Best-effort to avoid parsing some patterns as number prefix
23 | // ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640
24 | // ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653
25 | // Both of them would look like 7.0-foo or 2021-11-foo
26 | // note: we could try to parse float numbers in filenames, but that is probably
27 | // not worth it, as a version such as "8.0" can be interpreted as either a
28 | // version or a float. User can configure her own NumberPrefixParser if she
29 | // wants 8.0 to be interpreted as a float
30 | const ignoredPrefixPattern = /^\d+[-_.]\d+/;
31 |
32 | const numberPrefixPattern =
33 | /^(?\d+)\s*[-_.]+\s*(?[^-_.\s].*)$/;
34 |
35 | // 0-myDoc => {filename: myDoc, numberPrefix: 0}
36 | // 003 - myDoc => {filename: myDoc, numberPrefix: 3}
37 | export const DefaultNumberPrefixParser: NumberPrefixParser = (
38 | filename: string
39 | ) => {
40 | if (ignoredPrefixPattern.test(filename)) {
41 | return { filename, numberPrefix: undefined };
42 | }
43 | const match = numberPrefixPattern.exec(filename);
44 | if (!match) {
45 | return { filename, numberPrefix: undefined };
46 | }
47 | return {
48 | filename: match.groups!.suffix!,
49 | numberPrefix: parseInt(match.groups!.numberPrefix!, 10),
50 | };
51 | };
52 |
53 | // 0-myDoc => myDoc
54 | export function stripNumberPrefix(
55 | str: string,
56 | parser: NumberPrefixParser
57 | ): string {
58 | return parser(str).filename;
59 | }
60 |
61 | // 0-myFolder/0-mySubfolder/0-myDoc => myFolder/mySubfolder/myDoc
62 | export function stripPathNumberPrefixes(
63 | path: string,
64 | parser: NumberPrefixParser
65 | ): string {
66 | return path
67 | .split("/")
68 | .map((segment) => stripNumberPrefix(segment, parser))
69 | .join("/");
70 | }
71 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/docs/slug.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | /**
9 | * Copyright (c) Facebook, Inc. and its affiliates.
10 | *
11 | * This source code is licensed under the MIT license found in the
12 | * LICENSE file in the root directory of this source tree.
13 | */
14 |
15 | /**
16 | * Taken and adapted from:
17 | * https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-plugin-content-docs/src/slug.ts
18 | */
19 |
20 | import type {
21 | NumberPrefixParser,
22 | DocMetadataBase,
23 | } from "@docusaurus/plugin-content-docs";
24 | import { isValidPathname, resolvePathname } from "@docusaurus/utils";
25 | import { addLeadingSlash, addTrailingSlash } from "@docusaurus/utils-common";
26 |
27 | import { isCategoryIndex, toCategoryIndexMatcherParam } from "./docs";
28 | import {
29 | DefaultNumberPrefixParser,
30 | stripPathNumberPrefixes,
31 | } from "./numberPrefix";
32 |
33 | export default function getSlug({
34 | baseID,
35 | frontMatterSlug,
36 | source,
37 | sourceDirName,
38 | stripDirNumberPrefixes = true,
39 | numberPrefixParser = DefaultNumberPrefixParser,
40 | }: {
41 | baseID: string;
42 | frontMatterSlug?: string;
43 | source: DocMetadataBase["source"];
44 | sourceDirName: DocMetadataBase["sourceDirName"];
45 | stripDirNumberPrefixes?: boolean;
46 | numberPrefixParser?: NumberPrefixParser;
47 | }): string {
48 | function getDirNameSlug(): string {
49 | const dirNameStripped = stripDirNumberPrefixes
50 | ? stripPathNumberPrefixes(sourceDirName, numberPrefixParser)
51 | : sourceDirName;
52 | const resolveDirname =
53 | sourceDirName === "."
54 | ? "/"
55 | : addLeadingSlash(addTrailingSlash(dirNameStripped));
56 | return resolveDirname;
57 | }
58 |
59 | function computeSlug(): string {
60 | if (frontMatterSlug?.startsWith("/")) {
61 | return frontMatterSlug;
62 | }
63 | const dirNameSlug = getDirNameSlug();
64 | if (
65 | !frontMatterSlug &&
66 | isCategoryIndex(toCategoryIndexMatcherParam({ source, sourceDirName }))
67 | ) {
68 | return dirNameSlug;
69 | }
70 | const baseSlug = frontMatterSlug ?? baseID;
71 | return resolvePathname(baseSlug, getDirNameSlug());
72 | }
73 |
74 | function ensureValidSlug(slug: string): string {
75 | if (!isValidPathname(slug)) {
76 | throw new Error(
77 | `We couldn't compute a valid slug for document with ID "${baseID}" in "${sourceDirName}" directory.
78 | The slug we computed looks invalid: ${slug}.
79 | Maybe your slug front matter is incorrect or there are special characters in the file path?
80 | By using front matter to set a custom slug, you should be able to fix this error:
81 |
82 | ---
83 | slug: /my/customDocPath
84 | ---
85 | `
86 | );
87 | }
88 | return slug;
89 | }
90 |
91 | return ensureValidSlug(computeSlug());
92 | }
93 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/markdown/createDeprecationNotice.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { guard, Props, render } from "./utils";
9 |
10 | function createAdmonition({ children }: Props) {
11 | return `:::caution[deprecated]\n\n${render(children)}\n\n:::`;
12 | }
13 |
14 | interface DeprecationNoticeProps {
15 | deprecated?: boolean;
16 | description?: string;
17 | }
18 |
19 | export function createDeprecationNotice({
20 | deprecated,
21 | description,
22 | }: DeprecationNoticeProps) {
23 | return guard(deprecated, () =>
24 | createAdmonition({
25 | children:
26 | description ??
27 | "This endpoint has been deprecated and may be removed in future versions of the API.",
28 | })
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/markdown/createDescription.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | export function createDescription(description: string | undefined) {
9 | if (!description) {
10 | return "";
11 | }
12 | return `\n\n${description}\n\n`;
13 | }
14 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/markdown/createFullWidthTable.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { create, Props } from "./utils";
9 |
10 | export function createFullWidthTable({ children, style, ...rest }: Props) {
11 | return create("table", {
12 | style: { display: "table", width: "100%", ...style },
13 | ...rest,
14 | children,
15 | });
16 | }
17 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/markdown/createRequestBodyTable.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { createSchemaTable } from "./createSchemaTable";
9 |
10 | interface Props {
11 | title: string;
12 | body: any;
13 | }
14 |
15 | export function createRequestBodyTable({ title, body }: Props) {
16 | return createSchemaTable({ title, body, type: "request" });
17 | }
18 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/markdown/createStatusCodesTable.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { createDescription } from "./createDescription";
9 | import { createFullWidthTable } from "./createFullWidthTable";
10 | import { createSchemaTable } from "./createSchemaTable";
11 | import { create } from "./utils";
12 | import { ApiItem } from "../types";
13 |
14 | interface Props {
15 | responses: ApiItem["responses"];
16 | }
17 |
18 | export function createStatusCodesTable({ responses }: Props) {
19 | if (responses === undefined) {
20 | return undefined;
21 | }
22 |
23 | const codes = Object.keys(responses);
24 | if (codes.length === 0) {
25 | return undefined;
26 | }
27 |
28 | return createFullWidthTable({
29 | children: [
30 | create("thead", {
31 | children: create("tr", {
32 | children: create("th", {
33 | style: { textAlign: "left" },
34 | children: `Responses`,
35 | }),
36 | }),
37 | }),
38 | create("tbody", {
39 | children: codes.map((code) =>
40 | create("tr", {
41 | children: create("td", {
42 | children: [
43 | create("div", {
44 | style: { display: "flex" },
45 | children: [
46 | create("div", {
47 | style: { marginRight: "var(--ifm-table-cell-padding)" },
48 | children: create("code", {
49 | children: code,
50 | }),
51 | }),
52 | create("div", {
53 | children: createDescription(responses[code].description),
54 | }),
55 | ],
56 | }),
57 | create("div", {
58 | children: createSchemaTable({
59 | style: {
60 | marginTop: "var(--ifm-table-cell-padding)",
61 | marginBottom: "0px",
62 | },
63 | title: "Schema",
64 | body: {
65 | content: responses[code].content,
66 | },
67 | type: "response",
68 | }),
69 | }),
70 | ],
71 | }),
72 | })
73 | ),
74 | }),
75 | ],
76 | });
77 | }
78 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/markdown/createVersionBadge.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { escape } from "lodash";
9 |
10 | import { create, guard } from "./utils";
11 |
12 | export function createVersionBadge(version: string | undefined) {
13 | return guard(version, (version) => [
14 | create("span", {
15 | className: "theme-doc-version-badge badge badge--secondary",
16 | children: `Version: ${escape(version)}`,
17 | }),
18 | `\n`,
19 | ]);
20 | }
21 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/markdown/index.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { escape } from "lodash";
9 |
10 | import { createDeprecationNotice } from "./createDeprecationNotice";
11 | import { createDescription } from "./createDescription";
12 | import { createParamsTable } from "./createParamsTable";
13 | import { createRequestBodyTable } from "./createRequestBodyTable";
14 | import { createStatusCodesTable } from "./createStatusCodesTable";
15 | import { createVersionBadge } from "./createVersionBadge";
16 | import { render } from "./utils";
17 | import { ApiPageMetadata, InfoPageMetadata } from "../types";
18 |
19 | export function createApiPageMD({
20 | title,
21 | api: {
22 | deprecated,
23 | "x-deprecated-description": deprecatedDescription,
24 | description,
25 | parameters,
26 | requestBody,
27 | responses,
28 | },
29 | }: ApiPageMetadata) {
30 | return render([
31 | `# ${escape(title)}\n\n`,
32 | createDeprecationNotice({ deprecated, description: deprecatedDescription }),
33 | createDescription(description),
34 | createParamsTable({ parameters, type: "path" }),
35 | createParamsTable({ parameters, type: "query" }),
36 | createParamsTable({ parameters, type: "header" }),
37 | createParamsTable({ parameters, type: "cookie" }),
38 | createRequestBodyTable({ title: "Request Body", body: requestBody }),
39 | createStatusCodesTable({ responses }),
40 | ]);
41 | }
42 |
43 | export function createInfoPageMD({
44 | info: { title, version, description },
45 | }: InfoPageMetadata) {
46 | return render([
47 | createVersionBadge(version),
48 | `# ${escape(title)}\n\n`,
49 | createDescription(description),
50 | ]);
51 | }
52 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/markdown/schema.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { SchemaObject } from "../openapi/types";
9 |
10 | function prettyName(schema: SchemaObject, circular?: boolean) {
11 | if (schema.$ref) {
12 | return schema.$ref.replace("#/components/schemas/", "") + circular
13 | ? " (circular)"
14 | : "";
15 | }
16 |
17 | if (schema.format) {
18 | return schema.format;
19 | }
20 |
21 | if (schema.allOf) {
22 | return "object";
23 | }
24 |
25 | if (schema.type === "object") {
26 | return schema.xml?.name ?? schema.type;
27 | }
28 |
29 | return schema.title ?? schema.type;
30 | }
31 |
32 | export function getSchemaName(
33 | schema: SchemaObject,
34 | circular?: boolean
35 | ): string {
36 | if (schema.items) {
37 | return prettyName(schema.items, circular) + "[]";
38 | }
39 |
40 | return prettyName(schema, circular) ?? "";
41 | }
42 |
43 | export function getQualifierMessage(schema?: SchemaObject): string | undefined {
44 | // TODO:
45 | // - maxItems
46 | // - minItems
47 | // - uniqueItems
48 | // - maxProperties
49 | // - minProperties
50 | // - multipleOf
51 | if (!schema) {
52 | return undefined;
53 | }
54 |
55 | if (schema.items) {
56 | return getQualifierMessage(schema.items);
57 | }
58 |
59 | let message = "**Possible values:** ";
60 |
61 | let qualifierGroups = [];
62 |
63 | if (schema.minLength || schema.maxLength) {
64 | let lengthQualifier = "";
65 | if (schema.minLength) {
66 | lengthQualifier += `${schema.minLength} ≤ `;
67 | }
68 | lengthQualifier += "length";
69 | if (schema.maxLength) {
70 | lengthQualifier += ` ≤ ${schema.maxLength}`;
71 | }
72 | qualifierGroups.push(lengthQualifier);
73 | }
74 |
75 | if (
76 | schema.minimum ||
77 | schema.maximum ||
78 | typeof schema.exclusiveMinimum === "number" ||
79 | typeof schema.exclusiveMaximum === "number"
80 | ) {
81 | let minmaxQualifier = "";
82 | if (typeof schema.exclusiveMinimum === "number") {
83 | minmaxQualifier += `${schema.exclusiveMinimum} < `;
84 | } else if (schema.minimum && !schema.exclusiveMinimum) {
85 | minmaxQualifier += `${schema.minimum} ≤ `;
86 | } else if (schema.minimum && schema.exclusiveMinimum === true) {
87 | minmaxQualifier += `${schema.minimum} < `;
88 | }
89 | minmaxQualifier += "value";
90 | if (typeof schema.exclusiveMaximum === "number") {
91 | minmaxQualifier += ` < ${schema.exclusiveMaximum}`;
92 | } else if (schema.maximum && !schema.exclusiveMaximum) {
93 | minmaxQualifier += ` ≤ ${schema.maximum}`;
94 | } else if (schema.maximum && schema.exclusiveMaximum === true) {
95 | minmaxQualifier += ` < ${schema.maximum}`;
96 | }
97 | qualifierGroups.push(minmaxQualifier);
98 | }
99 |
100 | if (schema.pattern) {
101 | qualifierGroups.push(
102 | `Value must match regular expression \`${schema.pattern}\``
103 | );
104 | }
105 |
106 | if (schema.enum) {
107 | qualifierGroups.push(`[${schema.enum.map((e) => `\`${e}\``).join(", ")}]`);
108 | }
109 |
110 | if (qualifierGroups.length === 0) {
111 | return undefined;
112 | }
113 |
114 | return message + qualifierGroups.join(", ");
115 | }
116 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/markdown/utils.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | export type Children = string | undefined | (string | undefined)[];
9 |
10 | export type Props = Record & { children?: Children };
11 |
12 | export function create(tag: string, props: Props): string {
13 | const { children, ...rest } = props;
14 |
15 | let propString = "";
16 | for (const [key, value] of Object.entries(rest)) {
17 | propString += ` ${key}={${JSON.stringify(value)}}`;
18 | }
19 |
20 | return `<${tag}${propString}>${render(children)}${tag}>`;
21 | }
22 |
23 | export function guard(
24 | value: T | undefined,
25 | cb: (value: T) => Children
26 | ): string {
27 | if (value) {
28 | const children = cb(value);
29 | return render(children);
30 | }
31 | return "";
32 | }
33 |
34 | export function render(children: Children): string {
35 | const res = Array.isArray(children)
36 | ? children.filter((c) => c !== undefined).join("\n")
37 | : children ?? "";
38 |
39 | const isMultiline = res.split("\n").length > 1;
40 |
41 | // It is not possible to wrap “blocks” if text and tags are on the same line,
42 | // but the corresponding tags are on different lines. This can accidentally
43 | // happen if the rendered item has multiple lines. To be safe, we pad with
44 | // newlines.
45 | //
46 | // See: https://mdxjs.com/migrating/v2/#jsx
47 | if (isMultiline) {
48 | return "\n" + res + "\n";
49 | }
50 |
51 | return res;
52 | }
53 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/openapi-to-postmanv2.d.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | declare module "openapi-to-postmanv2" {
9 | export default any;
10 | }
11 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/openapi/__fixtures__/examples/openapi.yaml:
--------------------------------------------------------------------------------
1 | openapi: 3.0.3
2 | info:
3 | title: YAML Example
4 | version: 1.0.0
5 | description: Sample description.
6 | paths:
7 | /hello:
8 | get:
9 | summary: Hello World
10 | description: Example OpenApi definition with YAML.
11 | responses:
12 | 200:
13 | description: OK
14 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/openapi/__fixtures__/examples/yogurtstore/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Foods",
3 | "collapsed": true
4 | }
5 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/openapi/__fixtures__/examples/yogurtstore/froyo.yaml:
--------------------------------------------------------------------------------
1 | openapi: 3.0.3
2 | info:
3 | title: Frozen Yogurt Example
4 | version: 1.0.0
5 | description: Sample description.
6 | paths:
7 | /flavors:
8 | get:
9 | summary: List All Flavors
10 | description: Froyo's the best!
11 | responses:
12 | 200:
13 | description: OK
14 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/openapi/__fixtures__/examples/yogurtstore/nested/nested.yaml:
--------------------------------------------------------------------------------
1 | openapi: 3.0.3
2 | info:
3 | title: Nested Folder Example
4 | version: 1.0.0
5 | description: Sample description.
6 | paths:
7 | /flavors:
8 | get:
9 | summary: List All
10 | description: All
11 | responses:
12 | 200:
13 | description: OK
14 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/openapi/createExample.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { SchemaObject } from "./types";
9 |
10 | interface OASTypeToTypeMap {
11 | string: string;
12 | number: number;
13 | integer: number;
14 | boolean: boolean;
15 | object: any;
16 | array: any[];
17 | }
18 |
19 | type Primitives = {
20 | [OASType in keyof OASTypeToTypeMap]: {
21 | [format: string]: (schema: SchemaObject) => OASTypeToTypeMap[OASType];
22 | };
23 | };
24 |
25 | const primitives: Primitives = {
26 | string: {
27 | default: () => "string",
28 | email: () => "user@example.com",
29 | date: () => new Date().toISOString().substring(0, 10),
30 | uuid: () => "3fa85f64-5717-4562-b3fc-2c963f66afa6",
31 | hostname: () => "example.com",
32 | ipv4: () => "198.51.100.42",
33 | ipv6: () => "2001:0db8:5b96:0000:0000:426f:8e17:642a",
34 | },
35 | number: {
36 | default: () => 0,
37 | float: () => 0.0,
38 | },
39 | integer: {
40 | default: () => 0,
41 | },
42 | boolean: {
43 | default: (schema) =>
44 | typeof schema.default === "boolean" ? schema.default : true,
45 | },
46 | object: {},
47 | array: {},
48 | };
49 |
50 | export const sampleFromSchema = (schema: SchemaObject = {}): any => {
51 | let { type, example, allOf, properties, items } = schema;
52 |
53 | if (example !== undefined) {
54 | return example;
55 | }
56 |
57 | if (allOf) {
58 | // TODO: We are just assuming it will always be an object for now
59 | let obj: SchemaObject = {
60 | type: "object",
61 | properties: {},
62 | required: [], // NOTE: We shouldn't need to worry about required
63 | };
64 | for (let item of allOf) {
65 | if (item.properties) {
66 | obj.properties = {
67 | ...obj.properties,
68 | ...item.properties,
69 | };
70 | }
71 | }
72 | return sampleFromSchema(obj);
73 | }
74 |
75 | if (!type) {
76 | if (properties) {
77 | type = "object";
78 | } else if (items) {
79 | type = "array";
80 | } else {
81 | return;
82 | }
83 | }
84 |
85 | if (type === "object") {
86 | let obj: any = {};
87 | for (let [name, prop] of Object.entries(properties ?? {})) {
88 | if (prop.deprecated) {
89 | continue;
90 | }
91 | obj[name] = sampleFromSchema(prop);
92 | }
93 | return obj;
94 | }
95 |
96 | if (type === "array") {
97 | if (Array.isArray(items?.anyOf)) {
98 | return items?.anyOf.map((item) => sampleFromSchema(item));
99 | }
100 |
101 | if (Array.isArray(items?.oneOf)) {
102 | return items?.oneOf.map((item) => sampleFromSchema(item));
103 | }
104 |
105 | return [sampleFromSchema(items)];
106 | }
107 |
108 | if (schema.enum) {
109 | if (schema.default) {
110 | return schema.default;
111 | }
112 | return normalizeArray(schema.enum)[0];
113 | }
114 |
115 | return primitive(schema);
116 | };
117 |
118 | function primitive(schema: SchemaObject = {}) {
119 | let { type, format } = schema;
120 |
121 | if (type === undefined) {
122 | return;
123 | }
124 |
125 | let fn = primitives[type].default;
126 |
127 | if (format !== undefined) {
128 | fn = primitives[type][format] || fn;
129 | }
130 |
131 | if (fn) {
132 | return fn(schema);
133 | }
134 |
135 | return "Unknown Type: " + schema.type;
136 | }
137 |
138 | function normalizeArray(arr: any) {
139 | if (Array.isArray(arr)) {
140 | return arr;
141 | }
142 | return [arr];
143 | }
144 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/openapi/index.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | export { readOpenapiFiles, processOpenapiFiles } from "./openapi";
9 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/openapi/openapi.test.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import path from "path";
9 |
10 | import { readOpenapiFiles } from ".";
11 |
12 | // npx jest packages/docusaurus-plugin-openapi/src/openapi/openapi.test.ts --watch
13 |
14 | describe("openapi", () => {
15 | describe("readOpenapiFiles", () => {
16 | it("readOpenapiFiles", async () => {
17 | const results = await readOpenapiFiles(
18 | path.join(__dirname, "__fixtures__/examples"),
19 | {}
20 | );
21 | const categoryMeta = results.find((x) =>
22 | x.source.endsWith("_category_.json")
23 | );
24 | expect(categoryMeta).toBeFalsy();
25 | // console.log(results);
26 | const yaml = results.find((x) => x.source.endsWith("openapi.yaml"));
27 | expect(yaml).toBeTruthy();
28 | expect(yaml?.sourceDirName).toBe(".");
29 | const froyo = results.find((x) => x.source.endsWith("froyo.yaml"));
30 | expect(froyo).toBeTruthy();
31 | expect(froyo?.sourceDirName).toBe("yogurtstore");
32 | const nested = results.find((x) => x.source.endsWith("nested.yaml"));
33 | expect(nested).toBeTruthy();
34 | expect(nested?.sourceDirName).toBe("yogurtstore/nested");
35 | });
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/types.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import type { MDXOptions } from "@docusaurus/mdx-loader";
9 | import type { TagsPluginOptions } from "@docusaurus/utils";
10 | import type { Request } from "postman-collection";
11 |
12 | import {
13 | InfoObject,
14 | OperationObject,
15 | SecuritySchemeObject,
16 | } from "./openapi/types";
17 |
18 | export type {
19 | PropSidebarItemCategory,
20 | SidebarItemLink,
21 | PropSidebar,
22 | PropSidebarItem,
23 | } from "@docusaurus/plugin-content-docs-types";
24 | export interface PluginOptions extends MDXOptions, TagsPluginOptions {
25 | id: string;
26 | path: string;
27 | routeBasePath: string;
28 | apiLayoutComponent: string;
29 | apiItemComponent: string;
30 | admonitions:
31 | | boolean
32 | // AdmonitionOptions is not exported from @docusaurus/mdx-loader
33 | | {
34 | tag: string;
35 | keywords: string[];
36 | };
37 | sidebarCollapsible: boolean;
38 | sidebarCollapsed: boolean;
39 | }
40 |
41 | export interface LoadedContent {
42 | loadedApi: ApiMetadata[];
43 | }
44 |
45 | export type ApiMetadata = ApiPageMetadata | InfoPageMetadata | MdxPageMetadata;
46 |
47 | export interface ApiMetadataBase {
48 | sidebar?: string;
49 | previous?: ApiNavLink;
50 | next?: ApiNavLink;
51 | //
52 | id: string; // TODO legacy versioned id => try to remove
53 | title: string;
54 | description: string;
55 | source: string; // @site aliased source => "@site/docs/folder/subFolder/subSubFolder/myDoc.md"
56 | sourceDirName: string; // relative to the versioned docs folder (can be ".") => "folder/subFolder/subSubFolder"
57 | slug: string;
58 | permalink: string;
59 | sidebarPosition?: number;
60 | frontMatter: Record;
61 | }
62 |
63 | export interface ApiPageMetadata extends ApiMetadataBase {
64 | type: "api";
65 | api: ApiItem;
66 | }
67 |
68 | export interface ApiItem extends OperationObject {
69 | method: string; // get, post, put, etc...
70 | path: string; // The endpoint path => "/api/getPets"
71 | jsonRequestBodyExample: string;
72 | securitySchemes?: {
73 | [key: string]: SecuritySchemeObject;
74 | };
75 | postman?: Request;
76 | info: InfoObject;
77 | }
78 |
79 | export interface InfoPageMetadata extends ApiMetadataBase {
80 | type: "info";
81 | info: ApiInfo;
82 | }
83 |
84 | export interface MdxPageMetadata extends ApiMetadataBase {
85 | type: "mdx";
86 | }
87 |
88 | export type ApiInfo = InfoObject;
89 |
90 | export interface ApiNavLink {
91 | title: string;
92 | permalink: string;
93 | }
94 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/util.test.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { isURL } from "./util";
9 |
10 | describe("util", () => {
11 | describe("isURL", () => {
12 | it("full external link", () => {
13 | const url = "http://www.google.com";
14 | expect(isURL(url)).toBe(true);
15 | });
16 |
17 | it("Windows path", () => {
18 | // this is a windows path checking
19 | // related to issue #190
20 | // https://github.com/cloud-annotations/docusaurus-openapi/issues/190
21 | const url = "C:\\docusaurus-openapi\\openapi.json";
22 | expect(isURL(url)).toBe(false);
23 | });
24 |
25 | it("Linux/Unix path", () => {
26 | const url = "/mnt/c/Users/docusaurus-openapi/openapi.json";
27 | expect(isURL(url)).toBe(false);
28 | });
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/src/util.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | export const isURL = (url: string) => {
9 | return /^(?:[a-z]+:)?\/\//i.test(url);
10 | };
11 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-openapi/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "lib"
5 | },
6 | "include": ["src"]
7 | }
8 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-proxy/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docusaurus-plugin-proxy",
3 | "description": "A dev server proxy for Docusaurus.",
4 | "version": "0.7.6",
5 | "license": "MIT",
6 | "publishConfig": {
7 | "access": "public"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/cloud-annotations/docusaurus-openapi.git",
12 | "directory": "packages/docusaurus-plugin-proxy"
13 | },
14 | "bugs": {
15 | "url": "https://github.com/cloud-annotations/docusaurus-openapi/issues"
16 | },
17 | "main": "lib/index.js",
18 | "types": "src/plugin-proxy.d.ts",
19 | "scripts": {
20 | "build": "tsc",
21 | "watch": "tsc --watch"
22 | },
23 | "devDependencies": {
24 | "@docusaurus/types": "^3.6.0",
25 | "@types/webpack-dev-server": "^4.7.2"
26 | },
27 | "engines": {
28 | "node": ">=14"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-proxy/src/index.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import type { LoadContext, Plugin } from "@docusaurus/types";
9 |
10 | import type { PluginOptions } from "./types";
11 |
12 | export default function pluginOpenAPI(
13 | _context: LoadContext,
14 | options: PluginOptions
15 | ): Plugin {
16 | return {
17 | name: "docusaurus-plugin-proxy",
18 |
19 | // docusaurus type is outdated
20 | configureWebpack(): any {
21 | return {
22 | devServer: {
23 | proxy: options,
24 | },
25 | };
26 | },
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-proxy/src/options.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import type { PluginOptions } from "./types";
9 |
10 | export const DEFAULT_OPTIONS: Omit = {
11 | proxy: undefined,
12 | };
13 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-proxy/src/plugin-proxy.d.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | declare module "docusaurus-plugin-proxy" {
9 | export type Options = Partial;
10 | }
11 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-proxy/src/types.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import type { Configuration } from "webpack-dev-server";
9 |
10 | export interface PluginOptions {
11 | proxy: Configuration["proxy"];
12 | }
13 |
--------------------------------------------------------------------------------
/packages/docusaurus-plugin-proxy/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "lib"
5 | },
6 | "include": ["src"]
7 | }
8 |
--------------------------------------------------------------------------------
/packages/docusaurus-preset-openapi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docusaurus-preset-openapi",
3 | "description": "OpenAPI preset for Docusaurus.",
4 | "version": "0.7.6",
5 | "license": "MIT",
6 | "keywords": [
7 | "openapi",
8 | "swagger",
9 | "docusaurus",
10 | "documentation",
11 | "react"
12 | ],
13 | "publishConfig": {
14 | "access": "public"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/cloud-annotations/docusaurus-openapi.git",
19 | "directory": "packages/docusaurus-preset-openapi"
20 | },
21 | "bugs": {
22 | "url": "https://github.com/cloud-annotations/docusaurus-openapi/issues"
23 | },
24 | "main": "lib/index.js",
25 | "types": "src/preset-openapi.d.ts",
26 | "scripts": {
27 | "build": "tsc",
28 | "watch": "tsc --watch"
29 | },
30 | "devDependencies": {
31 | "@docusaurus/types": "^3.6.0"
32 | },
33 | "dependencies": {
34 | "@docusaurus/preset-classic": "^3.6.0",
35 | "docusaurus-plugin-openapi": "^0.7.6",
36 | "docusaurus-plugin-proxy": "^0.7.6",
37 | "docusaurus-theme-openapi": "^0.7.6"
38 | },
39 | "peerDependencies": {
40 | "react": "^18.0.0",
41 | "react-dom": "^18.0.0"
42 | },
43 | "engines": {
44 | "node": ">=18"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/packages/docusaurus-preset-openapi/src/index.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import presetClassic from "@docusaurus/preset-classic";
9 | import type { Preset, LoadContext, PluginOptions } from "@docusaurus/types";
10 | import type { Options } from "docusaurus-preset-openapi";
11 |
12 | function makePluginConfig(
13 | source: string,
14 | options?: PluginOptions
15 | ): string | [string, PluginOptions] {
16 | if (options) {
17 | return [require.resolve(source), options];
18 | }
19 | return require.resolve(source);
20 | }
21 |
22 | export default function preset(
23 | context: LoadContext,
24 | options: Options = {}
25 | ): Preset {
26 | const { proxy, api, ...rest } = options;
27 |
28 | const { themes = [], plugins = [] } = presetClassic(context, rest);
29 |
30 | themes.push(makePluginConfig("docusaurus-theme-openapi"));
31 |
32 | if (api !== false) {
33 | plugins.push(makePluginConfig("docusaurus-plugin-openapi", api));
34 | }
35 |
36 | if (proxy !== false) {
37 | plugins.push(makePluginConfig("docusaurus-plugin-proxy", proxy));
38 | }
39 |
40 | return { themes, plugins };
41 | }
42 |
--------------------------------------------------------------------------------
/packages/docusaurus-preset-openapi/src/preset-classic.d.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | ///
9 |
10 | import type { Preset, LoadContext } from "@docusaurus/types";
11 |
12 | declare module "@docusaurus/preset-classic" {
13 | export default function preset(
14 | context: LoadContext,
15 | options: Options
16 | ): Preset;
17 | }
18 |
--------------------------------------------------------------------------------
/packages/docusaurus-preset-openapi/src/preset-openapi.d.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import type {
9 | Options as ClassicOptions,
10 | ThemeConfig as ClassicThemeConfig,
11 | } from "@docusaurus/preset-classic";
12 |
13 | export type Options = {
14 | api?: false | import("docusaurus-plugin-openapi").Options;
15 | proxy?: false | import("docusaurus-plugin-proxy").Options;
16 | } & ClassicOptions;
17 |
18 | export type ThemeConfig = import("docusaurus-theme-openapi").ThemeConfig &
19 | ClassicThemeConfig;
20 |
--------------------------------------------------------------------------------
/packages/docusaurus-preset-openapi/src/theme-translations.d.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | // TODO: Remove this when https://github.com/facebook/docusaurus/issues/6087 is resolved.
9 | declare module "@docusaurus/theme-translations";
10 |
--------------------------------------------------------------------------------
/packages/docusaurus-preset-openapi/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "lib"
5 | },
6 | "include": ["src"]
7 | }
8 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/README.md:
--------------------------------------------------------------------------------
1 | # docusaurus-template-openapi
2 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docusaurus-template-openapi",
3 | "version": "0.7.6",
4 | "keywords": [
5 | "react",
6 | "create-docusaurus",
7 | "template",
8 | "openapi"
9 | ],
10 | "description": "OpenAPI template for Docusaurus.",
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/cloud-annotations/docusaurus-openapi.git",
14 | "directory": "packages/docusaurus-template-openapi"
15 | },
16 | "bugs": {
17 | "url": "https://github.com/cloud-annotations/docusaurus-openapi/issues"
18 | },
19 | "license": "MIT",
20 | "engines": {
21 | "node": ">=14"
22 | },
23 | "files": [
24 | "template",
25 | "template.json"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template.json:
--------------------------------------------------------------------------------
1 | {
2 | "package": {
3 | "name": "demo",
4 | "version": "0.7.6",
5 | "private": true,
6 | "scripts": {
7 | "docusaurus": "docusaurus",
8 | "start": "docusaurus start",
9 | "build": "docusaurus build",
10 | "swizzle": "docusaurus swizzle",
11 | "deploy": "docusaurus deploy",
12 | "clear": "docusaurus clear",
13 | "serve": "docusaurus serve",
14 | "write-translations": "docusaurus write-translations",
15 | "write-heading-ids": "docusaurus write-heading-ids"
16 | },
17 | "dependencies": {
18 | "@docusaurus/core": "^3.6.0",
19 | "docusaurus-preset-openapi": "0.7.6",
20 | "@mdx-js/react": "^3.0.0",
21 | "clsx": "^1.2.1",
22 | "prism-react-renderer": "^2.1.0",
23 | "react": "^18.0.0",
24 | "react-dom": "^18.0.0",
25 | "url": "^0.11.0"
26 | },
27 | "browserslist": {
28 | "production": [">0.5%", "not dead", "not op_mini all"],
29 | "development": [
30 | "last 1 chrome version",
31 | "last 1 firefox version",
32 | "last 1 safari version"
33 | ]
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/README.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
4 |
5 | ### Installation
6 |
7 | ```
8 | $ yarn
9 | ```
10 |
11 | ### Local Development
12 |
13 | ```
14 | $ yarn start
15 | ```
16 |
17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
18 |
19 | ### Build
20 |
21 | ```
22 | $ yarn build
23 | ```
24 |
25 | This command generates static content into the `build` directory and can be served using any static contents hosting service.
26 |
27 | ### Deployment
28 |
29 | Using SSH:
30 |
31 | ```
32 | $ USE_SSH=true yarn deploy
33 | ```
34 |
35 | Not using SSH:
36 |
37 | ```
38 | $ GIT_USER= yarn deploy
39 | ```
40 |
41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
42 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve("@docusaurus/core/lib/babel/preset")],
3 | };
4 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/blog/2019-05-28-first-blog-post.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: first-blog-post
3 | title: First Blog Post
4 | authors:
5 | name: Gao Wei
6 | title: Docusaurus Core Team
7 | url: https://github.com/wgao19
8 | image_url: https://github.com/wgao19.png
9 | tags: [hola, docusaurus]
10 | ---
11 |
12 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
13 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/blog/2019-05-29-long-blog-post.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: long-blog-post
3 | title: Long Blog Post
4 | authors: endi
5 | tags: [hello, docusaurus]
6 | ---
7 |
8 | This is the summary of a very long blog post,
9 |
10 | Use a `` comment to limit blog post size in the list view.
11 |
12 |
13 |
14 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
15 |
16 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
17 |
18 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
19 |
20 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
21 |
22 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
23 |
24 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
25 |
26 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
27 |
28 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
29 |
30 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
31 |
32 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
33 |
34 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
35 |
36 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
37 |
38 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
39 |
40 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
41 |
42 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
43 |
44 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
45 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/blog/2021-08-01-mdx-blog-post.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | slug: mdx-blog-post
3 | title: MDX Blog Post
4 | authors: [slorber]
5 | tags: [docusaurus]
6 | ---
7 |
8 | Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
9 |
10 | :::tip
11 |
12 | Use the power of React to create interactive blog posts.
13 |
14 | ```js
15 |
16 | ```
17 |
18 |
19 |
20 | :::
21 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/packages/docusaurus-template-openapi/template/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/blog/2021-08-26-welcome/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: welcome
3 | title: Welcome
4 | authors: [slorber, yangshun]
5 | tags: [facebook, hello, docusaurus]
6 | ---
7 |
8 | [Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
9 |
10 | Simply add Markdown files (or folders) to the `blog` directory.
11 |
12 | Regular blog authors can be added to `authors.yml`.
13 |
14 | The blog post date can be extracted from filenames, such as:
15 |
16 | - `2019-05-30-welcome.md`
17 | - `2019-05-30-welcome/index.md`
18 |
19 | A blog post folder can be convenient to co-locate blog post images:
20 |
21 | 
22 |
23 | The blog supports tags as well!
24 |
25 | **And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
26 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/blog/authors.yml:
--------------------------------------------------------------------------------
1 | endi:
2 | name: Endilie Yacop Sucipto
3 | title: Maintainer of Docusaurus
4 | url: https://github.com/endiliey
5 | image_url: https://github.com/endiliey.png
6 |
7 | yangshun:
8 | name: Yangshun Tay
9 | title: Front End Engineer @ Facebook
10 | url: https://github.com/yangshun
11 | image_url: https://github.com/yangshun.png
12 |
13 | slorber:
14 | name: Sébastien Lorber
15 | title: Docusaurus maintainer
16 | url: https://sebastienlorber.com
17 | image_url: https://github.com/slorber.png
18 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/intro.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | ---
4 |
5 | # Tutorial Intro
6 |
7 | Let's discover **Docusaurus in less than 5 minutes**.
8 |
9 | ## Getting Started
10 |
11 | Get started by **creating a new site**.
12 |
13 | Or **try Docusaurus immediately** with **[docusaurus.new](https://docusaurus.new)**.
14 |
15 | ## Generate a new site
16 |
17 | Generate a new Docusaurus site using the **classic template**:
18 |
19 | ```shell
20 | npm init docusaurus@latest my-website classic
21 | ```
22 |
23 | ## Start your site
24 |
25 | Run the development server:
26 |
27 | ```shell
28 | cd my-website
29 |
30 | npx docusaurus start
31 | ```
32 |
33 | Your site starts at `http://localhost:3000`.
34 |
35 | Open `docs/intro.md` and edit some lines: the site **reloads automatically** and displays your changes.
36 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/tutorial-basics/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Tutorial - Basics",
3 | "position": 2
4 | }
5 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/tutorial-basics/congratulations.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 6
3 | ---
4 |
5 | # Congratulations!
6 |
7 | You have just learned the **basics of Docusaurus** and made some changes to the **initial template**.
8 |
9 | Docusaurus has **much more to offer**!
10 |
11 | Have **5 more minutes**? Take a look at **[versioning](../tutorial-extras/manage-docs-versions.md)** and **[i18n](../tutorial-extras/translate-your-site.md)**.
12 |
13 | Anything **unclear** or **buggy** in this tutorial? [Please report it!](https://github.com/facebook/docusaurus/discussions/4610)
14 |
15 | ## What's next?
16 |
17 | - Read the [official documentation](https://docusaurus.io/).
18 | - Add a custom [Design and Layout](https://docusaurus.io/docs/styling-layout)
19 | - Add a [search bar](https://docusaurus.io/docs/search)
20 | - Find inspirations in the [Docusaurus showcase](https://docusaurus.io/showcase)
21 | - Get involved in the [Docusaurus Community](https://docusaurus.io/community/support)
22 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/tutorial-basics/create-a-blog-post.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | ---
4 |
5 | # Create a Blog Post
6 |
7 | Docusaurus creates a **page for each blog post**, but also a **blog index page**, a **tag system**, an **RSS** feed...
8 |
9 | ## Create your first Post
10 |
11 | Create a file at `blog/2021-02-28-greetings.md`:
12 |
13 | ```md title="blog/2021-02-28-greetings.md"
14 | ---
15 | slug: greetings
16 | title: Greetings!
17 | authors:
18 | - name: Joel Marcey
19 | title: Co-creator of Docusaurus 1
20 | url: https://github.com/JoelMarcey
21 | image_url: https://github.com/JoelMarcey.png
22 | - name: Sébastien Lorber
23 | title: Docusaurus maintainer
24 | url: https://sebastienlorber.com
25 | image_url: https://github.com/slorber.png
26 | tags: [greetings]
27 | ---
28 |
29 | Congratulations, you have made your first post!
30 |
31 | Feel free to play around and edit this post as much you like.
32 | ```
33 |
34 | A new blog post is now available at `http://localhost:3000/blog/greetings`.
35 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/tutorial-basics/create-a-document.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # Create a Document
6 |
7 | Documents are **groups of pages** connected through:
8 |
9 | - a **sidebar**
10 | - **previous/next navigation**
11 | - **versioning**
12 |
13 | ## Create your first Doc
14 |
15 | Create a markdown file at `docs/hello.md`:
16 |
17 | ```md title="docs/hello.md"
18 | # Hello
19 |
20 | This is my **first Docusaurus document**!
21 | ```
22 |
23 | A new document is now available at `http://localhost:3000/docs/hello`.
24 |
25 | ## Configure the Sidebar
26 |
27 | Docusaurus automatically **creates a sidebar** from the `docs` folder.
28 |
29 | Add metadata to customize the sidebar label and position:
30 |
31 | ```md title="docs/hello.md" {1-4}
32 | ---
33 | sidebar_label: "Hi!"
34 | sidebar_position: 3
35 | ---
36 |
37 | # Hello
38 |
39 | This is my **first Docusaurus document**!
40 | ```
41 |
42 | It is also possible to create your sidebar explicitly in `sidebars.js`:
43 |
44 | ```diff title="sidebars.js"
45 | module.exports = {
46 | tutorialSidebar: [
47 | {
48 | type: 'category',
49 | label: 'Tutorial',
50 | - items: [...],
51 | + items: ['hello'],
52 | },
53 | ],
54 | };
55 | ```
56 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/tutorial-basics/create-a-page.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | ---
4 |
5 | # Create a Page
6 |
7 | Add **Markdown or React** files to `src/pages` to create a **standalone page**:
8 |
9 | - `src/pages/index.js` -> `localhost:3000/`
10 | - `src/pages/foo.md` -> `localhost:3000/foo`
11 | - `src/pages/foo/bar.js` -> `localhost:3000/foo/bar`
12 |
13 | ## Create your first React Page
14 |
15 | Create a file at `src/pages/my-react-page.js`:
16 |
17 | ```jsx title="src/pages/my-react-page.js"
18 | import React from "react";
19 | import Layout from "@theme/Layout";
20 |
21 | export default function MyReactPage() {
22 | return (
23 |
24 | My React page
25 | This is a React page
26 |
27 | );
28 | }
29 | ```
30 |
31 | A new page is now available at `http://localhost:3000/my-react-page`.
32 |
33 | ## Create your first Markdown Page
34 |
35 | Create a file at `src/pages/my-markdown-page.md`:
36 |
37 | ```mdx title="src/pages/my-markdown-page.md"
38 | # My Markdown page
39 |
40 | This is a Markdown page
41 | ```
42 |
43 | A new page is now available at `http://localhost:3000/my-markdown-page`.
44 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/tutorial-basics/deploy-your-site.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | ---
4 |
5 | # Deploy your site
6 |
7 | Docusaurus is a **static-site-generator** (also called **[Jamstack](https://jamstack.org/)**).
8 |
9 | It builds your site as simple **static HTML, JavaScript and CSS files**.
10 |
11 | ## Build your site
12 |
13 | Build your site **for production**:
14 |
15 | ```bash
16 | npm run build
17 | ```
18 |
19 | The static files are generated in the `build` folder.
20 |
21 | ## Deploy your site
22 |
23 | Test your production build locally:
24 |
25 | ```bash
26 | npm run serve
27 | ```
28 |
29 | The `build` folder is now served at `http://localhost:3000/`.
30 |
31 | You can now deploy the `build` folder **almost anywhere** easily, **for free** or very small cost (read the **[Deployment Guide](https://docusaurus.io/docs/deployment)**).
32 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/tutorial-basics/markdown-features.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | ---
4 |
5 | # Markdown Features
6 |
7 | Docusaurus supports **[Markdown](https://daringfireball.net/projects/markdown/syntax)** and a few **additional features**.
8 |
9 | ## Front Matter
10 |
11 | Markdown documents have metadata at the top called [Front Matter](https://jekyllrb.com/docs/front-matter/):
12 |
13 | ```text title="my-doc.md"
14 | // highlight-start
15 | ---
16 | id: my-doc-id
17 | title: My document title
18 | description: My document description
19 | slug: /my-custom-url
20 | ---
21 | // highlight-end
22 |
23 | ## Markdown heading
24 |
25 | Markdown text with [links](./hello.md)
26 | ```
27 |
28 | ## Links
29 |
30 | Regular Markdown links are supported, using url paths or relative file paths.
31 |
32 | ```md
33 | Let's see how to [Create a page](/create-a-page).
34 | ```
35 |
36 | ```md
37 | Let's see how to [Create a page](./create-a-page.md).
38 | ```
39 |
40 | **Result:** Let's see how to [Create a page](./create-a-page.md).
41 |
42 | ## Images
43 |
44 | Regular Markdown images are supported.
45 |
46 | Add an image at `static/img/docusaurus.png` and display it in Markdown:
47 |
48 | ```md
49 | 
50 | ```
51 |
52 | 
53 |
54 | ## Code Blocks
55 |
56 | Markdown code blocks are supported with Syntax highlighting.
57 |
58 | ```jsx title="src/components/HelloDocusaurus.js"
59 | function HelloDocusaurus() {
60 | return (
61 | Hello, Docusaurus!
62 | )
63 | }
64 | ```
65 |
66 | ```jsx title="src/components/HelloDocusaurus.js"
67 | function HelloDocusaurus() {
68 | return Hello, Docusaurus!
;
69 | }
70 | ```
71 |
72 | ## Admonitions
73 |
74 | Docusaurus has a special syntax to create admonitions and callouts:
75 |
76 | :::tip My tip
77 |
78 | Use this awesome feature option
79 |
80 | :::
81 |
82 | :::danger Take care
83 |
84 | This action is dangerous
85 |
86 | :::
87 |
88 | :::tip My tip
89 |
90 | Use this awesome feature option
91 |
92 | :::
93 |
94 | :::danger Take care
95 |
96 | This action is dangerous
97 |
98 | :::
99 |
100 | ## MDX and React Components
101 |
102 | [MDX](https://mdxjs.com/) can make your documentation more **interactive** and allows using any **React components inside Markdown**:
103 |
104 | ```jsx
105 | export const Highlight = ({children, color}) => (
106 | {
115 | alert(`You clicked the color ${color} with label ${children}`)
116 | }}>
117 | {children}
118 |
119 | );
120 |
121 | This is Docusaurus green !
122 |
123 | This is Facebook blue !
124 | ```
125 |
126 | export const Highlight = ({ children, color }) => (
127 | {
136 | alert(`You clicked the color ${color} with label ${children}`);
137 | }}
138 | >
139 | {children}
140 |
141 | );
142 |
143 | This is Docusaurus green !
144 |
145 | This is Facebook blue !
146 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/tutorial-extras/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Tutorial - Extras",
3 | "position": 3
4 | }
5 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/tutorial-extras/manage-docs-versions.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | ---
4 |
5 | # Manage Docs Versions
6 |
7 | Docusaurus can manage multiple versions of your docs.
8 |
9 | ## Create a docs version
10 |
11 | Release a version 1.0 of your project:
12 |
13 | ```bash
14 | npm run docusaurus docs:version 1.0
15 | ```
16 |
17 | The `docs` folder is copied into `versioned_docs/version-1.0` and `versions.json` is created.
18 |
19 | Your docs now have 2 versions:
20 |
21 | - `1.0` at `http://localhost:3000/docs/` for the version 1.0 docs
22 | - `current` at `http://localhost:3000/docs/next/` for the **upcoming, unreleased docs**
23 |
24 | ## Add a Version Dropdown
25 |
26 | To navigate seamlessly across versions, add a version dropdown.
27 |
28 | Modify the `docusaurus.config.js` file:
29 |
30 | ```js title="docusaurus.config.js"
31 | module.exports = {
32 | themeConfig: {
33 | navbar: {
34 | items: [
35 | // highlight-start
36 | {
37 | type: "docsVersionDropdown",
38 | },
39 | // highlight-end
40 | ],
41 | },
42 | },
43 | };
44 | ```
45 |
46 | The docs version dropdown appears in your navbar:
47 |
48 | 
49 |
50 | ## Update an existing version
51 |
52 | It is possible to edit versioned docs in their respective folder:
53 |
54 | - `versioned_docs/version-1.0/hello.md` updates `http://localhost:3000/docs/hello`
55 | - `docs/hello.md` updates `http://localhost:3000/docs/next/hello`
56 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/docs/tutorial-extras/translate-your-site.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # Translate your site
6 |
7 | Let's translate `docs/intro.md` to French.
8 |
9 | ## Configure i18n
10 |
11 | Modify `docusaurus.config.js` to add support for the `fr` locale:
12 |
13 | ```js title="docusaurus.config.js"
14 | module.exports = {
15 | i18n: {
16 | defaultLocale: "en",
17 | locales: ["en", "fr"],
18 | },
19 | };
20 | ```
21 |
22 | ## Translate a doc
23 |
24 | Copy the `docs/intro.md` file to the `i18n/fr` folder:
25 |
26 | ```bash
27 | mkdir -p i18n/fr/docusaurus-plugin-content-docs/current/
28 |
29 | cp docs/intro.md i18n/fr/docusaurus-plugin-content-docs/current/intro.md
30 | ```
31 |
32 | Translate `i18n/fr/docusaurus-plugin-content-docs/current/intro.md` in French.
33 |
34 | ## Start your localized site
35 |
36 | Start your site on the French locale:
37 |
38 | ```bash
39 | npm run start -- --locale fr
40 | ```
41 |
42 | Your localized site is accessible at `http://localhost:3000/fr/` and the `Getting Started` page is translated.
43 |
44 | :::caution
45 |
46 | In development, you can only use one locale at a same time.
47 |
48 | :::
49 |
50 | ## Add a Locale Dropdown
51 |
52 | To navigate seamlessly across languages, add a locale dropdown.
53 |
54 | Modify the `docusaurus.config.js` file:
55 |
56 | ```js title="docusaurus.config.js"
57 | module.exports = {
58 | themeConfig: {
59 | navbar: {
60 | items: [
61 | // highlight-start
62 | {
63 | type: "localeDropdown",
64 | },
65 | // highlight-end
66 | ],
67 | },
68 | },
69 | };
70 | ```
71 |
72 | The locale dropdown now appears in your navbar:
73 |
74 | 
75 |
76 | ## Build your localized site
77 |
78 | Build your site for a specific locale:
79 |
80 | ```bash
81 | npm run build -- --locale fr
82 | ```
83 |
84 | Or build your site to include all the locales at once:
85 |
86 | ```bash
87 | npm run build
88 | ```
89 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | # Production
5 | /build
6 |
7 | # Generated files
8 | .docusaurus
9 | .cache-loader
10 |
11 | # Misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/sidebars.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Creating a sidebar enables you to:
3 | - create an ordered group of docs
4 | - render a sidebar for each doc of that group
5 | - provide next/previous navigation
6 |
7 | The sidebars can be generated from the filesystem, or explicitly defined here.
8 |
9 | Create as many sidebars as you want.
10 | */
11 |
12 | // @ts-check
13 |
14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
15 | const sidebars = {
16 | // By default, Docusaurus generates a sidebar from the docs folder structure
17 | tutorialSidebar: [{ type: "autogenerated", dirName: "." }],
18 |
19 | // But you can create a sidebar manually
20 | /*
21 | tutorialSidebar: [
22 | {
23 | type: 'category',
24 | label: 'Tutorial',
25 | items: ['hello'],
26 | },
27 | ],
28 | */
29 | };
30 |
31 | module.exports = sidebars;
32 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/src/components/HomepageFeatures.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import clsx from "clsx";
3 | import styles from "./HomepageFeatures.module.css";
4 |
5 | const FeatureList = [
6 | {
7 | title: "Easy to Use",
8 | Svg: require("../../static/img/undraw_docusaurus_mountain.svg").default,
9 | description: (
10 | <>
11 | Docusaurus was designed from the ground up to be easily installed and
12 | used to get your website up and running quickly.
13 | >
14 | ),
15 | },
16 | {
17 | title: "Focus on What Matters",
18 | Svg: require("../../static/img/undraw_docusaurus_tree.svg").default,
19 | description: (
20 | <>
21 | Docusaurus lets you focus on your docs, and we'll do the chores. Go
22 | ahead and move your docs into the docs
directory.
23 | >
24 | ),
25 | },
26 | {
27 | title: "Powered by React",
28 | Svg: require("../../static/img/undraw_docusaurus_react.svg").default,
29 | description: (
30 | <>
31 | Extend or customize your website layout by reusing React. Docusaurus can
32 | be extended while reusing the same header and footer.
33 | >
34 | ),
35 | },
36 | ];
37 |
38 | function Feature({ Svg, title, description }) {
39 | return (
40 |
41 |
42 |
43 |
44 |
45 |
{title}
46 |
{description}
47 |
48 |
49 | );
50 | }
51 |
52 | export default function HomepageFeatures() {
53 | return (
54 |
55 |
56 |
57 | {FeatureList.map((props, idx) => (
58 |
59 | ))}
60 |
61 |
62 |
63 | );
64 | }
65 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/src/components/HomepageFeatures.module.css:
--------------------------------------------------------------------------------
1 | .features {
2 | display: flex;
3 | align-items: center;
4 | padding: 2rem 0;
5 | width: 100%;
6 | }
7 |
8 | .featureSvg {
9 | height: 200px;
10 | width: 200px;
11 | }
12 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/src/css/custom.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Any CSS included here will be global. The classic template
3 | * bundles Infima by default. Infima is a CSS framework designed to
4 | * work well for content-centric websites.
5 | */
6 |
7 | /* You can override the default Infima variables here. */
8 | :root {
9 | --ifm-color-primary: #25c2a0;
10 | --ifm-color-primary-dark: rgb(33, 175, 144);
11 | --ifm-color-primary-darker: rgb(31, 165, 136);
12 | --ifm-color-primary-darkest: rgb(26, 136, 112);
13 | --ifm-color-primary-light: rgb(70, 203, 174);
14 | --ifm-color-primary-lighter: rgb(102, 212, 189);
15 | --ifm-color-primary-lightest: rgb(146, 224, 208);
16 | --ifm-code-font-size: 95%;
17 | }
18 |
19 | .docusaurus-highlight-code-line {
20 | background-color: rgba(0, 0, 0, 0.1);
21 | display: block;
22 | margin: 0 calc(-1 * var(--ifm-pre-padding));
23 | padding: 0 var(--ifm-pre-padding);
24 | }
25 |
26 | html[data-theme="dark"] .docusaurus-highlight-code-line {
27 | background-color: rgba(0, 0, 0, 0.3);
28 | }
29 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/src/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import clsx from "clsx";
3 | import Layout from "@theme/Layout";
4 | import Link from "@docusaurus/Link";
5 | import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
6 | import styles from "./index.module.css";
7 | import HomepageFeatures from "../components/HomepageFeatures";
8 |
9 | function HomepageHeader() {
10 | const { siteConfig } = useDocusaurusContext();
11 | return (
12 |
26 | );
27 | }
28 |
29 | export default function Home() {
30 | const { siteConfig } = useDocusaurusContext();
31 | return (
32 |
36 |
37 |
38 |
39 |
40 |
41 | );
42 | }
43 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/src/pages/index.module.css:
--------------------------------------------------------------------------------
1 | /**
2 | * CSS files with the .module.css suffix will be treated as CSS modules
3 | * and scoped locally.
4 | */
5 |
6 | .heroBanner {
7 | padding: 4rem 0;
8 | text-align: center;
9 | position: relative;
10 | overflow: hidden;
11 | }
12 |
13 | @media screen and (max-width: 966px) {
14 | .heroBanner {
15 | padding: 2rem;
16 | }
17 | }
18 |
19 | .buttons {
20 | display: flex;
21 | align-items: center;
22 | justify-content: center;
23 | }
24 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/src/pages/markdown-page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Markdown page example
3 | ---
4 |
5 | # Markdown page example
6 |
7 | You don't need React to write simple standalone pages.
8 |
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/static/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/packages/docusaurus-template-openapi/template/static/.nojekyll
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/static/img/docusaurus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/packages/docusaurus-template-openapi/template/static/img/docusaurus.png
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/static/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/packages/docusaurus-template-openapi/template/static/img/favicon.ico
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/static/img/tutorial/docsVersionDropdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/packages/docusaurus-template-openapi/template/static/img/tutorial/docsVersionDropdown.png
--------------------------------------------------------------------------------
/packages/docusaurus-template-openapi/template/static/img/tutorial/localeDropdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloud-annotations/docusaurus-openapi/4483c46bbd7e7f0bf451a6434b8916eb935e6c0d/packages/docusaurus-template-openapi/template/static/img/tutorial/localeDropdown.png
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/babel.config.js:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | module.exports = {
9 | env: {
10 | // USED FOR NODE/RUNTIME
11 | // maybe we should differenciate both cases because
12 | // we mostly need to transpile some features so that node does not crash...
13 | lib: {
14 | presets: [
15 | ["@babel/preset-typescript", { isTSX: true, allExtensions: true }],
16 | ],
17 | // Useful to transpile for older node versions
18 | plugins: [
19 | "@babel/plugin-transform-modules-commonjs",
20 | "@babel/plugin-proposal-nullish-coalescing-operator",
21 | "@babel/plugin-proposal-optional-chaining",
22 | ],
23 | },
24 |
25 | // USED FOR JS SWIZZLE
26 | // /lib-next folder is used as source to swizzle JS source code
27 | // This JS code is created from TS source code
28 | // This source code should look clean/human readable to be usable
29 | "lib-next": {
30 | presets: [
31 | ["@babel/preset-typescript", { isTSX: true, allExtensions: true }],
32 | ],
33 | },
34 | },
35 | };
36 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docusaurus-theme-openapi",
3 | "description": "OpenAPI theme for Docusaurus.",
4 | "version": "0.7.6",
5 | "license": "MIT",
6 | "publishConfig": {
7 | "access": "public"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/cloud-annotations/docusaurus-openapi.git",
12 | "directory": "packages/docusaurus-theme-openapi"
13 | },
14 | "bugs": {
15 | "url": "https://github.com/cloud-annotations/docusaurus-openapi/issues"
16 | },
17 | "types": "src/theme-openapi.d.ts",
18 | "main": "lib/index.js",
19 | "scripts": {
20 | "build": "tsc --noEmit && yarn babel:lib && yarn babel:lib-next && yarn format:lib-next",
21 | "watch": "concurrently --names \"lib,lib-next,tsc\" --kill-others \"yarn babel:lib --watch\" \"yarn babel:lib-next --watch\" \"yarn tsc --watch\"",
22 | "babel:lib": "cross-env BABEL_ENV=lib babel src -d lib --extensions \".tsx,.ts\" --ignore \"**/*.d.ts\" --copy-files",
23 | "babel:lib-next": "cross-env BABEL_ENV=lib-next babel src -d lib-next --extensions \".tsx,.ts\" --ignore \"**/*.d.ts\" --copy-files",
24 | "format:lib-next": "prettier --config ../../.prettierrc.json --write \"lib-next/**/*.{js,ts,jsx,tsc}\""
25 | },
26 | "devDependencies": {
27 | "@docusaurus/module-type-aliases": "^3.6.0",
28 | "@docusaurus/types": "^3.6.0",
29 | "@types/concurrently": "^6.3.0",
30 | "@types/crypto-js": "^4.1.0",
31 | "@types/lodash": "^4.14.176",
32 | "@types/mdx-js__react": "^1.5.4",
33 | "@types/postman-collection": "^3.5.3",
34 | "@types/rtlcss": "^3.1.1",
35 | "concurrently": "^5.2.0"
36 | },
37 | "dependencies": {
38 | "@docusaurus/theme-common": "^3.6.0",
39 | "@mdx-js/react": "^3.0.0",
40 | "@monaco-editor/react": "^4.3.1",
41 | "@reduxjs/toolkit": "^1.7.1",
42 | "buffer": "^6.0.3",
43 | "clsx": "^1.2.1",
44 | "crypto-js": "^4.1.1",
45 | "docusaurus-plugin-openapi": "^0.7.6",
46 | "immer": "^9.0.7",
47 | "lodash": "^4.17.20",
48 | "marked": "^11.0.0",
49 | "monaco-editor": "^0.31.1",
50 | "postman-code-generators": "^1.0.0",
51 | "postman-collection": "^4.1.0",
52 | "prism-react-renderer": "^2.1.0",
53 | "process": "^0.11.10",
54 | "react-magic-dropzone": "^1.0.1",
55 | "react-redux": "^7.2.0",
56 | "redux-devtools-extension": "^2.13.8",
57 | "refractor": "^4.8.1",
58 | "striptags": "^3.2.0",
59 | "webpack": "^5.95.0"
60 | },
61 | "peerDependencies": {
62 | "react": "^18.0.0",
63 | "react-dom": "^18.0.0"
64 | },
65 | "engines": {
66 | "node": ">=18"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/index.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import path from "path";
9 |
10 | import type { ConfigureWebpackUtils, Plugin } from "@docusaurus/types";
11 | import type { Configuration as WebpackConfiguration } from "webpack";
12 |
13 | export default function docusaurusThemeOpenAPI(): Plugin {
14 | return {
15 | name: "docusaurus-theme-openapi",
16 |
17 | getThemePath() {
18 | return path.join(__dirname, "..", "lib-next", "theme");
19 | },
20 |
21 | getTypeScriptThemePath() {
22 | return path.resolve(__dirname, "..", "src", "theme");
23 | },
24 |
25 | configureWebpack(
26 | _config: WebpackConfiguration,
27 | _isServer: boolean,
28 | { currentBundler }: ConfigureWebpackUtils
29 | ) {
30 | const bundler = currentBundler.instance ?? require("webpack");
31 | return {
32 | plugins: [
33 | new bundler.ProvidePlugin({
34 | Buffer: [require.resolve("buffer/"), "Buffer"],
35 | process: require.resolve("process/browser"),
36 | }),
37 | ],
38 | resolve: {
39 | fallback: {
40 | buffer: require.resolve("buffer/"),
41 | process: require.resolve("process/browser"),
42 | },
43 | },
44 | };
45 | },
46 | };
47 | }
48 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme-classic.d.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | ///
9 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme-openapi.d.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | ///
9 |
10 | declare module "docusaurus-theme-openapi" {
11 | export type ThemeConfig = Partial;
12 | }
13 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme-translations.d.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | // TODO: Remove this when https://github.com/facebook/docusaurus/issues/6087 is resolved.
9 | declare module "@docusaurus/theme-translations";
10 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/Accept/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import FormItem from "./../FormItem";
11 | import FormSelect from "./../FormSelect";
12 | import { setAccept } from "./slice";
13 | import { useTypedDispatch, useTypedSelector } from "../hooks";
14 |
15 | function Accept() {
16 | const value = useTypedSelector((state) => state.accept.value);
17 | const options = useTypedSelector((state) => state.accept.options);
18 | const dispatch = useTypedDispatch();
19 |
20 | if (options.length <= 1) {
21 | return null;
22 | }
23 |
24 | return (
25 |
26 | dispatch(setAccept(e.target.value))}
30 | />
31 |
32 | );
33 | }
34 |
35 | export default Accept;
36 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/Accept/slice.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { createSlice, PayloadAction } from "@reduxjs/toolkit";
9 |
10 | export interface State {
11 | value: string;
12 | options: string[];
13 | }
14 |
15 | const initialState: State = {} as any;
16 |
17 | export const slice = createSlice({
18 | name: "accept",
19 | initialState,
20 | reducers: {
21 | setAccept: (state, action: PayloadAction) => {
22 | state.value = action.payload;
23 | },
24 | },
25 | });
26 |
27 | export const { setAccept } = slice.actions;
28 |
29 | export default slice.reducer;
30 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/Authorization/auth-types.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | export function getAuthDataKeys(security: { [key: string]: any }) {
9 | // Bearer Auth
10 | if (security.type === "http" && security.scheme === "bearer") {
11 | return ["token"];
12 | }
13 |
14 | // Basic Auth
15 | if (security.type === "http" && security.scheme === "basic") {
16 | return ["username", "password"];
17 | }
18 |
19 | // none
20 | return [];
21 | }
22 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/ContentType/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import FormItem from "./../FormItem";
11 | import FormSelect from "./../FormSelect";
12 | import { setContentType } from "./slice";
13 | import { useTypedDispatch, useTypedSelector } from "../hooks";
14 |
15 | function ContentType() {
16 | const value = useTypedSelector((state) => state.contentType.value);
17 | const options = useTypedSelector((state) => state.contentType.options);
18 | const dispatch = useTypedDispatch();
19 |
20 | if (options.length <= 1) {
21 | return null;
22 | }
23 |
24 | return (
25 |
26 | dispatch(setContentType(e.target.value))}
30 | />
31 |
32 | );
33 | }
34 |
35 | export default ContentType;
36 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/ContentType/slice.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { createSlice, PayloadAction } from "@reduxjs/toolkit";
9 |
10 | export interface State {
11 | value: string;
12 | options: string[];
13 | }
14 |
15 | const initialState: State = {} as any;
16 |
17 | export const slice = createSlice({
18 | name: "contentType",
19 | initialState,
20 | reducers: {
21 | setContentType: (state, action: PayloadAction) => {
22 | state.value = action.payload;
23 | },
24 | },
25 | });
26 |
27 | export const { setContentType } = slice.actions;
28 |
29 | export default slice.reducer;
30 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/Curl/styles.module.css:
--------------------------------------------------------------------------------
1 | .buttonGroup {
2 | background: var(--openapi-card-background-color);
3 | color: var(--ifm-pre-color);
4 | font-family: var(--ifm-font-family-monospace);
5 | /* font-size: var(--ifm-code-font-size); */
6 | /* line-height: var(--ifm-pre-line-height); */
7 | /* margin-bottom: calc(var(--ifm-spacing-vertical) / 4); */
8 | margin-bottom: 1px;
9 | margin-top: 0;
10 | border-radius: var(--openapi-card-border-radius)
11 | var(--openapi-card-border-radius) 2px 2px;
12 | display: flex;
13 | justify-content: center;
14 | flex-wrap: wrap;
15 | }
16 |
17 | .buttonGroup button {
18 | -webkit-appearance: none;
19 | -moz-appearance: none;
20 | appearance: none;
21 |
22 | cursor: pointer;
23 | /* font-size: calc(0.875rem * var(--ifm-button-size-multiplier)); */
24 | /* line-height: 1.5; */
25 | /* font-weight: var(--ifm-button-font-weight); */
26 |
27 | /* font-size: var(--ifm-code-font-size); */
28 | font-size: 13.3333px;
29 | line-height: var(--ifm-pre-line-height);
30 | font-weight: var(--ifm-font-weight-semibold);
31 |
32 | padding: calc(
33 | var(--ifm-button-padding-vertical) * var(--ifm-button-size-multiplier)
34 | )
35 | calc(
36 | var(--ifm-button-padding-horizontal) * var(--ifm-button-size-multiplier)
37 | );
38 |
39 | text-align: center;
40 |
41 | transition: color var(--ifm-button-transition-duration)
42 | cubic-bezier(0.08, 0.52, 0.52, 1),
43 | background var(--ifm-button-transition-duration)
44 | cubic-bezier(0.08, 0.52, 0.52, 1),
45 | border-color var(--ifm-button-transition-duration)
46 | cubic-bezier(0.08, 0.52, 0.52, 1);
47 | -webkit-user-select: none;
48 | user-select: none;
49 | white-space: nowrap;
50 |
51 | background: transparent;
52 |
53 | color: var(--ifm-menu-color);
54 | border: 0px solid transparent;
55 | /* border-radius: var(--ifm-pre-border-radius); */
56 |
57 | --margin: 0.25rem;
58 |
59 | border-radius: calc(var(--margin));
60 | /* border-radius: 0.25rem; */
61 |
62 | display: block;
63 |
64 | /* margin: 2px; */
65 | margin: var(--margin);
66 | margin-right: 0;
67 | }
68 |
69 | .buttonGroup button:last-child {
70 | margin-right: 0.25rem;
71 | }
72 |
73 | .buttonGroup button:hover {
74 | background: var(--ifm-menu-color-background-active);
75 | }
76 |
77 | .buttonGroup button:focus {
78 | outline: 0;
79 | }
80 |
81 | .buttonGroup button.selected {
82 | background: var(--ifm-menu-color-background-active);
83 | color: var(--ifm-menu-color-active);
84 | }
85 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/Execute/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import sdk from "postman-collection";
11 |
12 | import buildPostmanRequest from "./../buildPostmanRequest";
13 | import makeRequest from "./makeRequest";
14 | import { useTypedDispatch, useTypedSelector } from "../hooks";
15 | import { Param } from "../ParamOptions/slice";
16 | import { setResponse } from "../Response/slice";
17 |
18 | function validateRequest(params: {
19 | path: Param[];
20 | query: Param[];
21 | header: Param[];
22 | cookie: Param[];
23 | }) {
24 | for (let paramList of Object.values(params)) {
25 | for (let param of paramList) {
26 | if (param.required && !param.value) {
27 | return false;
28 | }
29 | }
30 | }
31 | return true;
32 | }
33 |
34 | interface Props {
35 | postman: sdk.Request;
36 | proxy?: string;
37 | }
38 |
39 | function Execute({ postman, proxy }: Props) {
40 | const pathParams = useTypedSelector((state) => state.params.path);
41 | const queryParams = useTypedSelector((state) => state.params.query);
42 | const cookieParams = useTypedSelector((state) => state.params.cookie);
43 | const headerParams = useTypedSelector((state) => state.params.header);
44 | const contentType = useTypedSelector((state) => state.contentType.value);
45 | const body = useTypedSelector((state) => state.body);
46 | const accept = useTypedSelector((state) => state.accept.value);
47 | const server = useTypedSelector((state) => state.server.value);
48 | const params = useTypedSelector((state) => state.params);
49 | const auth = useTypedSelector((state) => state.auth);
50 |
51 | const isValidRequest = validateRequest(params);
52 |
53 | const dispatch = useTypedDispatch();
54 |
55 | const postmanRequest = buildPostmanRequest(postman, {
56 | queryParams,
57 | pathParams,
58 | cookieParams,
59 | contentType,
60 | accept,
61 | headerParams,
62 | body,
63 | server,
64 | auth,
65 | });
66 |
67 | return (
68 |
85 | );
86 | }
87 |
88 | export default Execute;
89 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FloatingButton/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import styles from "./styles.module.css";
11 |
12 | interface Props {
13 | label?: string;
14 | onClick?: React.MouseEventHandler;
15 | children?: React.ReactNode;
16 | }
17 |
18 | function FloatingButton({ label, onClick, children }: Props) {
19 | return (
20 |
21 | {label && (
22 |
25 | )}
26 | {children}
27 |
28 | );
29 | }
30 |
31 | export default FloatingButton;
32 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FloatingButton/styles.module.css:
--------------------------------------------------------------------------------
1 | .floatingButton {
2 | position: relative;
3 | }
4 |
5 | .floatingButton button {
6 | position: relative;
7 | background: rgba(25, 26, 27, 0.9);
8 | border: none;
9 | border-radius: var(--ifm-global-radius);
10 | color: var(--ifm-color-white);
11 | cursor: pointer;
12 | outline: none;
13 | padding: 0.4rem 0.5rem;
14 | opacity: 0;
15 | visibility: hidden;
16 | transition: opacity 0.2s ease-in-out, visibility 0.2s ease-in-out,
17 | bottom 0.2s ease-in-out;
18 | position: absolute;
19 | top: calc(var(--ifm-pre-padding) / 2);
20 | right: calc(var(--ifm-pre-padding) / 2);
21 | }
22 |
23 | .floatingButton:hover button {
24 | visibility: visible;
25 | opacity: 1;
26 | }
27 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FormFileUpload/styles.module.css:
--------------------------------------------------------------------------------
1 | .dropzone {
2 | display: inline-flex;
3 | align-items: center;
4 | justify-content: center;
5 | cursor: pointer;
6 | border: 2px dashed var(--openapi-monaco-border-color);
7 | /* border: 2px dashed var(--ifm-color-primary); */
8 | background-color: var(--openapi-input-background);
9 |
10 | width: 100%;
11 | /* min-height: 120px; */
12 | /* padding: 16px 11px; */
13 | border-radius: 4px;
14 | padding: var(--ifm-pre-padding);
15 | font-size: var(--ifm-code-font-size);
16 | }
17 |
18 | .dropzoneHover {
19 | display: inline-flex;
20 | align-items: center;
21 | justify-content: center;
22 | cursor: pointer;
23 | border: 2px dashed var(--openapi-monaco-border-color);
24 | background-color: var(--openapi-input-background);
25 | width: 100%;
26 | border-radius: 4px;
27 | padding: var(--ifm-pre-padding);
28 | font-size: var(--ifm-code-font-size);
29 | border: 2px dashed var(--ifm-color-primary);
30 |
31 | background: linear-gradient(
32 | var(--openapi-dropzone-hover-shim),
33 | var(--openapi-dropzone-hover-shim)
34 | ),
35 | linear-gradient(var(--ifm-color-primary), var(--ifm-color-primary));
36 | }
37 |
38 | .dropzone:hover {
39 | border: 2px dashed var(--ifm-color-primary);
40 | background: linear-gradient(
41 | var(--openapi-dropzone-hover-shim),
42 | var(--openapi-dropzone-hover-shim)
43 | ),
44 | linear-gradient(var(--ifm-color-primary), var(--ifm-color-primary));
45 | }
46 |
47 | .dropzoneContent {
48 | display: flex;
49 | align-items: center;
50 | justify-content: center;
51 | flex-wrap: wrap;
52 | margin: var(--ifm-pre-padding) 0;
53 | color: var(--openapi-dropzone-color);
54 | }
55 |
56 | .dropzone:hover .dropzoneContent {
57 | color: var(--ifm-pre-color);
58 | }
59 |
60 | .dropzoneHover .dropzoneContent {
61 | display: flex;
62 | align-items: center;
63 | justify-content: center;
64 | flex-wrap: wrap;
65 | margin: var(--ifm-pre-padding) 0;
66 | color: var(--ifm-pre-color);
67 | }
68 |
69 | .filename {
70 | margin: 0 calc(var(--ifm-pre-padding) * 1.5);
71 | white-space: nowrap;
72 | overflow: hidden;
73 | text-overflow: ellipsis;
74 | flex: 1;
75 | }
76 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FormItem/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import styles from "./styles.module.css";
11 |
12 | interface Props {
13 | label: string;
14 | type?: string;
15 | children?: React.ReactNode;
16 | }
17 |
18 | function FormItem({ label, type, children }: Props) {
19 | return (
20 |
21 |
{label}
22 | {type &&
— {type}}
23 |
{children}
24 |
25 | );
26 | }
27 |
28 | export default FormItem;
29 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FormItem/styles.module.css:
--------------------------------------------------------------------------------
1 | .formItem {
2 | margin-top: var(--ifm-pre-padding);
3 | }
4 |
5 | .formItem:first-child {
6 | margin-top: 0;
7 | }
8 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FormMultiSelect/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import styles from "./styles.module.css";
11 |
12 | interface Props {
13 | value?: string;
14 | options: string[];
15 | onChange?: React.ChangeEventHandler;
16 | }
17 |
18 | function FormMultiSelect({ value, options, onChange }: Props) {
19 | if (options.length === 0) {
20 | return null;
21 | }
22 |
23 | let height;
24 | if (options.length < 6) {
25 | const selectPadding = 12 * 2;
26 | const rawHeight = options.length * 29;
27 | const innerMargins = 4 * options.length - 1;
28 | const outerMargins = 4 * 2;
29 | const mysteryScroll = 1;
30 | height =
31 | rawHeight + innerMargins + outerMargins + selectPadding + mysteryScroll;
32 | }
33 |
34 | return (
35 |
51 | );
52 | }
53 |
54 | export default FormMultiSelect;
55 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FormMultiSelect/styles.module.css:
--------------------------------------------------------------------------------
1 | .inputBase {
2 | margin-top: calc(var(--ifm-pre-padding) / 2);
3 | /* height: 40px; */
4 | background-color: var(--openapi-input-background);
5 | border: none;
6 | outline: none;
7 | width: 100%;
8 | font-size: var(--ifm-code-font-size);
9 | color: var(--ifm-pre-color);
10 | padding: 12px var(--ifm-pre-padding);
11 |
12 | border-radius: 4px;
13 | border: 2px solid transparent;
14 | }
15 |
16 | html[data-theme="light"] .selectInput {
17 | border-color: var(--ifm-color-primary-lightest);
18 | border-style: solid;
19 | border-width: 1px;
20 | }
21 |
22 | .selectInput {
23 | composes: inputBase;
24 | -moz-appearance: none;
25 | -webkit-appearance: none;
26 | appearance: none;
27 | }
28 |
29 | .selectInput option {
30 | border-radius: 0.25rem;
31 | color: var(--ifm-menu-color);
32 | margin: 0.25rem 0;
33 | padding: var(--ifm-menu-link-padding-vertical)
34 | var(--ifm-menu-link-padding-horizontal);
35 | }
36 |
37 | .selectInput:focus option:checked {
38 | /* background: #0f62fe linear-gradient(0deg, #0f62fe 0%, #0f62fe 100%); */
39 | }
40 |
41 | .selectInput:focus {
42 | /* box-shadow: inset 0px 0px 0px 2px white; */
43 | border: 2px solid var(--openapi-input-border);
44 | }
45 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FormSelect/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import styles from "./styles.module.css";
11 |
12 | interface Props {
13 | value?: string;
14 | options?: string[];
15 | onChange?: React.ChangeEventHandler;
16 | }
17 |
18 | function FormSelect({ value, options, onChange }: Props) {
19 | if (!Array.isArray(options) || options.length === 0) {
20 | return null;
21 | }
22 |
23 | return (
24 |
33 | );
34 | }
35 |
36 | export default FormSelect;
37 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FormSelect/styles.module.css:
--------------------------------------------------------------------------------
1 | .inputBase {
2 | margin-top: calc(var(--ifm-pre-padding) / 2);
3 | /* height: 40px; */
4 | background-color: var(--openapi-input-background);
5 | border: none;
6 | outline: none;
7 | width: 100%;
8 | font-size: var(--ifm-code-font-size);
9 | color: var(--ifm-pre-color);
10 | padding: 12px 48px 12px var(--ifm-pre-padding);
11 |
12 | border-radius: 4px;
13 | }
14 |
15 | html[data-theme="dark"] .selectInput {
16 | margin-top: calc(var(--ifm-pre-padding) / 2);
17 | /* height: 40px; */
18 | background-color: var(--openapi-input-background);
19 | border: none;
20 | outline: none;
21 | width: 100%;
22 | font-size: var(--ifm-code-font-size);
23 | color: var(--ifm-pre-color);
24 | /* padding: 12px var(--ifm-pre-padding); */
25 |
26 | border-radius: 4px;
27 | -moz-appearance: none;
28 | -webkit-appearance: none;
29 | appearance: none;
30 |
31 | background-image: url('data:image/svg+xml;charset=US-ASCII,');
32 | background-repeat: no-repeat;
33 | background-position: right var(--ifm-pre-padding) top 50%;
34 | background-size: auto auto;
35 | }
36 |
37 | html[data-theme="light"] .selectInput {
38 | border-color: var(--ifm-color-primary-lightest);
39 | border-style: solid;
40 | border-width: 1px;
41 | }
42 |
43 | .selectInput {
44 | composes: inputBase;
45 | -moz-appearance: none;
46 | -webkit-appearance: none;
47 | appearance: none;
48 |
49 | background-image: url('data:image/svg+xml;charset=US-ASCII,');
50 | background-repeat: no-repeat;
51 | background-position: right var(--ifm-pre-padding) top 50%;
52 | background-size: auto auto;
53 | }
54 |
55 | .selectInput:focus {
56 | box-shadow: inset 0px 0px 0px 2px var(--openapi-input-border);
57 | }
58 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FormTextInput/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import styles from "./styles.module.css";
11 | import { stripText } from "../text";
12 |
13 | interface Props {
14 | value?: string;
15 | placeholder?: string;
16 | password?: boolean;
17 | onChange?: React.ChangeEventHandler;
18 | }
19 |
20 | function FormTextInput({ value, placeholder, password, onChange }: Props) {
21 | return (
22 |
30 | );
31 | }
32 |
33 | export default FormTextInput;
34 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/FormTextInput/styles.module.css:
--------------------------------------------------------------------------------
1 | .inputBase {
2 | margin-top: calc(var(--ifm-pre-padding) / 2);
3 | /* height: 40px; */
4 | background-color: var(--openapi-input-background);
5 | border: none;
6 | outline: none;
7 | width: 100%;
8 | font-size: var(--ifm-code-font-size);
9 | color: var(--ifm-pre-color);
10 | padding: 12px var(--ifm-pre-padding);
11 |
12 | border-radius: 4px;
13 | }
14 |
15 | html[data-theme="light"] .input {
16 | border-color: var(--ifm-color-primary-lightest);
17 | border-style: solid;
18 | border-width: 1px;
19 | }
20 |
21 | .input {
22 | composes: inputBase;
23 | }
24 |
25 | .input:focus {
26 | box-shadow: inset 0px 0px 0px 2px var(--openapi-input-border);
27 | }
28 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/MethodEndpoint/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | function colorForMethod(method: string) {
11 | switch (method.toLowerCase()) {
12 | case "get":
13 | return "var(--openapi-code-blue)";
14 | case "put":
15 | return "var(--openapi-code-orange)";
16 | case "post":
17 | return "var(--openapi-code-green)";
18 | case "delete":
19 | return "var(--openapi-code-red)";
20 | default:
21 | return undefined;
22 | }
23 | }
24 |
25 | interface Props {
26 | method: string;
27 | path: string;
28 | }
29 |
30 | function MethodEndpoint({ method, path }: Props) {
31 | return (
32 |
38 |
39 | {method.toUpperCase()}
40 | {" "}
41 | {path.replace(/{([a-z0-9-_]+)}/gi, ":$1")}
42 |
43 | );
44 | }
45 |
46 | export default MethodEndpoint;
47 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/ParamOptions/slice.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { createSlice, PayloadAction } from "@reduxjs/toolkit";
9 | import { ParameterObject } from "docusaurus-plugin-openapi/src/openapi/types";
10 |
11 | export type Param = ParameterObject & { value?: string[] | string };
12 |
13 | export interface State {
14 | path: Param[];
15 | query: Param[];
16 | header: Param[];
17 | cookie: Param[];
18 | }
19 |
20 | const initialState: State = {} as any;
21 |
22 | export const slice = createSlice({
23 | name: "params",
24 | initialState,
25 | reducers: {
26 | setParam: (state, action: PayloadAction) => {
27 | const newParam = action.payload;
28 | const paramGroup = state[action.payload.in];
29 | const index = paramGroup.findIndex((p) => p.name === newParam.name);
30 | paramGroup[index] = newParam;
31 | },
32 | },
33 | });
34 |
35 | export const { setParam } = slice.actions;
36 |
37 | export default slice.reducer;
38 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/Response/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import FloatingButton from "./../FloatingButton";
11 | import { clearResponse } from "./slice";
12 | import { useTypedDispatch, useTypedSelector } from "../hooks";
13 |
14 | // TODO: We probably shouldn't attempt to format XML...
15 | function formatXml(xml: string) {
16 | const tab = " ";
17 | let formatted = "";
18 | let indent = "";
19 |
20 | xml.split(/>\s*).forEach((node) => {
21 | if (node.match(/^\/\w/)) {
22 | // decrease indent by one 'tab'
23 | indent = indent.substring(tab.length);
24 | }
25 | formatted += indent + "<" + node + ">\r\n";
26 | if (node.match(/^\w[^>]*[^/]$/)) {
27 | // increase indent
28 | indent += tab;
29 | }
30 | });
31 | return formatted.substring(1, formatted.length - 3);
32 | }
33 |
34 | function Response() {
35 | const response = useTypedSelector((state) => state.response.value);
36 | const dispatch = useTypedDispatch();
37 |
38 | if (response === undefined) {
39 | return null;
40 | }
41 |
42 | let prettyResponse: string = response;
43 | try {
44 | prettyResponse = JSON.stringify(JSON.parse(response), null, 2);
45 | } catch {
46 | if (response.startsWith(" dispatch(clearResponse())} label="Clear">
53 |
60 | {prettyResponse || "No Response"}
61 |
62 |
63 | );
64 | }
65 |
66 | export default Response;
67 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/Response/slice.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { createSlice, PayloadAction } from "@reduxjs/toolkit";
9 |
10 | export interface State {
11 | value?: string;
12 | }
13 |
14 | const initialState: State = {} as any;
15 |
16 | export const slice = createSlice({
17 | name: "response",
18 | initialState,
19 | reducers: {
20 | setResponse: (state, action: PayloadAction) => {
21 | state.value = action.payload;
22 | },
23 | clearResponse: (state) => {
24 | state.value = undefined;
25 | },
26 | },
27 | });
28 |
29 | export const { setResponse, clearResponse } = slice.actions;
30 |
31 | export default slice.reducer;
32 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/Server/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React, { useState } from "react";
9 |
10 | import FormItem from "./../FormItem";
11 | import FormSelect from "./../FormSelect";
12 | import FormTextInput from "./../FormTextInput";
13 | import { setServer, setServerVariable } from "./slice";
14 | import styles from "./styles.module.css";
15 | import FloatingButton from "../FloatingButton";
16 | import { useTypedDispatch, useTypedSelector } from "../hooks";
17 |
18 | function Server() {
19 | const [isEditing, setIsEditing] = useState(false);
20 | const value = useTypedSelector((state) => state.server.value);
21 | const options = useTypedSelector((state) => state.server.options);
22 |
23 | const dispatch = useTypedDispatch();
24 |
25 | if (options.length <= 0) {
26 | return null;
27 | }
28 |
29 | if (options.length <= 1 && value?.variables === undefined) {
30 | return null;
31 | }
32 |
33 | if (!isEditing) {
34 | let url = "";
35 | if (value) {
36 | url = value.url.replace(/\/$/, "");
37 | if (value.variables) {
38 | Object.keys(value.variables).forEach((variable) => {
39 | url = url.replace(
40 | `{${variable}}`,
41 | value.variables?.[variable].storedValue ?? ""
42 | );
43 | });
44 | }
45 | }
46 | return (
47 | setIsEditing(true)} label="Edit">
48 |
54 | {url}
55 |
56 |
57 | );
58 | }
59 |
60 | return (
61 |
62 |
69 |
70 | s.url)}
72 | onChange={(e) => dispatch(setServer(e.target.value))}
73 | />
74 |
75 | {value?.variables &&
76 | Object.keys(value.variables).map((key) => {
77 | if (value.variables?.[key].enum !== undefined) {
78 | return (
79 |
80 | {
84 | dispatch(setServerVariable({ key, value: e.target.value }));
85 | }}
86 | />
87 |
88 | );
89 | }
90 | return (
91 |
92 | {
96 | dispatch(setServerVariable({ key, value: e.target.value }));
97 | }}
98 | />
99 |
100 | );
101 | })}
102 |
103 | );
104 | }
105 |
106 | export default Server;
107 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/Server/slice.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { createSlice, PayloadAction } from "@reduxjs/toolkit";
9 | // TODO: we might want to export this
10 | import {
11 | ServerObject,
12 | ServerVariable,
13 | } from "docusaurus-plugin-openapi/src/openapi/types";
14 |
15 | import { ThemeConfig } from "../../../types";
16 | import { createStorage } from "../storage-utils";
17 |
18 | interface Map {
19 | [key: string]: T;
20 | }
21 |
22 | export type ServerObjectWithStorage = ServerObject & {
23 | variables?: Map;
24 | };
25 |
26 | export function createServer({
27 | servers,
28 | options: opts,
29 | }: {
30 | servers: ServerObject[];
31 | options?: ThemeConfig["api"];
32 | }): State {
33 | const storage = createStorage(opts?.authPersistance);
34 |
35 | let options: ServerObjectWithStorage[] = servers.map((s) => {
36 | // A deep copy of the original ServerObject, augmented with `storedValue` props.
37 | const srv = JSON.parse(JSON.stringify(s)) as ServerObjectWithStorage;
38 |
39 | let persisted = undefined;
40 | try {
41 | persisted = JSON.parse(
42 | storage.getItem(`docusaurus.openapi.server/${s.url}`) ?? ""
43 | );
44 | } catch {}
45 |
46 | if (!persisted) {
47 | persisted = {};
48 | }
49 |
50 | if (!persisted.variables) {
51 | persisted.variables = {};
52 | }
53 |
54 | srv.variables = srv.variables ?? {};
55 |
56 | for (const v of Object.keys(srv.variables)) {
57 | if (v in persisted.variables) {
58 | if (
59 | persisted.variables[v].storedValue !== undefined &&
60 | persisted.variables[v].storedValue !== null &&
61 | persisted.variables[v].storedValue !== ""
62 | ) {
63 | srv.variables[v].storedValue = persisted.variables[v].storedValue;
64 | } else {
65 | srv.variables[v].storedValue = srv.variables[v].default;
66 | }
67 | }
68 | }
69 |
70 | return srv;
71 | });
72 |
73 | return { value: options[0], options: options };
74 | }
75 |
76 | export interface State {
77 | value?: ServerObjectWithStorage;
78 | options: ServerObjectWithStorage[];
79 | }
80 |
81 | const initialState: State = {} as any;
82 |
83 | export const slice = createSlice({
84 | name: "server",
85 | initialState,
86 | reducers: {
87 | setServer: (state, action: PayloadAction) => {
88 | state.value = state.options.find((s) => s.url === action.payload);
89 | },
90 | setServerVariable: (
91 | state,
92 | action: PayloadAction<{ key: string; value: string }>
93 | ) => {
94 | if (state.value?.variables) {
95 | state.value.variables[action.payload.key].storedValue =
96 | action.payload.value;
97 | }
98 | },
99 | },
100 | });
101 |
102 | export const { setServer, setServerVariable } = slice.actions;
103 |
104 | export default slice.reducer;
105 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/Server/styles.module.css:
--------------------------------------------------------------------------------
1 | .showMoreButton {
2 | -webkit-appearance: none;
3 | -moz-appearance: none;
4 | appearance: none;
5 |
6 | cursor: pointer;
7 | font-size: var(--ifm-code-font-size);
8 | /* font-weight: var(--ifm-button-font-weight); */
9 | /* line-height: 1.5; */
10 |
11 | padding: 0;
12 |
13 | user-select: none;
14 | white-space: nowrap;
15 |
16 | border: 0px solid transparent;
17 |
18 | display: block;
19 | /* width: 100%; */
20 |
21 | background-color: transparent;
22 |
23 | color: var(--ifm-color-primary);
24 | cursor: pointer;
25 | margin-top: var(--ifm-pre-padding);
26 | margin-bottom: 0;
27 | text-align: left;
28 | display: block;
29 | }
30 |
31 | .showMoreButton:focus {
32 | outline: 0;
33 | }
34 |
35 | .showMoreButton:hover {
36 | /* text-decoration: underline; */
37 | /* background-color: red; */
38 | color: var(--ifm-color-primary-hover);
39 | }
40 |
41 | .showMoreButton:first-child {
42 | margin-top: 0;
43 | }
44 |
45 | .optionsPanel:empty {
46 | display: none;
47 | }
48 |
49 | .optionsPanel {
50 | background: var(--openapi-card-background-color);
51 | border-radius: var(--openapi-card-border-radius);
52 | color: var(--ifm-pre-color);
53 | line-height: var(--ifm-pre-line-height);
54 | margin-bottom: var(--ifm-spacing-vertical);
55 | margin-top: 0;
56 | overflow: auto;
57 | padding: var(--ifm-pre-padding);
58 |
59 | /* hack for view calculation when monaco is hidden */
60 | position: relative;
61 | }
62 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/VSCode/styles.module.css:
--------------------------------------------------------------------------------
1 | .monacoBase {
2 | margin-top: calc(var(--ifm-pre-padding) / 2);
3 | border-radius: 4px;
4 | padding: var(--ifm-pre-padding);
5 | background-color: var(--openapi-monaco-background-color);
6 | }
7 |
8 | .monaco {
9 | composes: monacoBase;
10 |
11 | box-shadow: 0 0 0 1px var(--openapi-monaco-border-color);
12 | border: 2px solid transparent;
13 | }
14 |
15 | .monacoFocus {
16 | composes: monacoBase;
17 |
18 | border: 2px solid var(--openapi-input-border);
19 | }
20 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/buildPostmanRequest.test.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import sdk from "postman-collection";
9 |
10 | import { openApiQueryParams2PostmanQueryParams } from "./buildPostmanRequest";
11 |
12 | describe("openApiQueryParams2PostmanQueryParams", () => {
13 | it("should transform empty array to empty array", () => {
14 | const expected: sdk.QueryParam[] = [];
15 | const actual = openApiQueryParams2PostmanQueryParams([]);
16 | expect(actual).toStrictEqual(expected);
17 | });
18 |
19 | it("default to comma delimited", () => {
20 | const expected: sdk.QueryParam[] = [
21 | new sdk.QueryParam({ key: "arrayParam", value: "abc,def" }),
22 | ];
23 | const actual = openApiQueryParams2PostmanQueryParams([
24 | {
25 | name: "arrayParam",
26 | in: "query",
27 | value: ["abc", "def"],
28 | },
29 | ]);
30 | expect(actual).toStrictEqual(expected);
31 | });
32 |
33 | it("should expand params if explode=true", () => {
34 | const expected: sdk.QueryParam[] = [
35 | new sdk.QueryParam({ key: "arrayParam", value: "abc" }),
36 | new sdk.QueryParam({ key: "arrayParam", value: "def" }),
37 | ];
38 | const actual = openApiQueryParams2PostmanQueryParams([
39 | {
40 | name: "arrayParam",
41 | in: "query",
42 | style: "form",
43 | explode: true,
44 | value: ["abc", "def"],
45 | },
46 | ]);
47 | expect(actual).toStrictEqual(expected);
48 | });
49 |
50 | it("should respect style=pipeDelimited", () => {
51 | const expected: sdk.QueryParam[] = [
52 | new sdk.QueryParam({ key: "arrayParam", value: "abc|def" }),
53 | ];
54 | const actual = openApiQueryParams2PostmanQueryParams([
55 | {
56 | name: "arrayParam",
57 | in: "query",
58 | style: "pipeDelimited",
59 | value: ["abc", "def"],
60 | },
61 | ]);
62 | expect(actual).toStrictEqual(expected);
63 | });
64 |
65 | it("should respect style=spaceDelimited", () => {
66 | const expected: sdk.QueryParam[] = [
67 | new sdk.QueryParam({ key: "arrayParam", value: "abc%20def" }),
68 | ];
69 | const actual = openApiQueryParams2PostmanQueryParams([
70 | {
71 | name: "arrayParam",
72 | in: "query",
73 | style: "spaceDelimited",
74 | value: ["abc", "def"],
75 | },
76 | ]);
77 | expect(actual).toStrictEqual(expected);
78 | });
79 | });
80 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/hooks.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
9 |
10 | import type { RootState, AppDispatch } from "./store";
11 |
12 | export const useTypedDispatch = () => useDispatch();
13 | export const useTypedSelector: TypedUseSelectorHook = useSelector;
14 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/persistanceMiddleware.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { Middleware } from "@reduxjs/toolkit";
9 |
10 | import { setAuthData, setSelectedAuth } from "./Authorization/slice";
11 | import { setServer, setServerVariable } from "./Server/slice";
12 | import { createStorage, hashArray } from "./storage-utils";
13 | import { AppDispatch, RootState } from "./store";
14 | import { ThemeConfig } from "../../types";
15 |
16 | export function createPersistanceMiddleware(options: ThemeConfig["api"]) {
17 | const persistanceMiddleware: Middleware<{}, RootState, AppDispatch> =
18 | (storeAPI) => (next) => (action) => {
19 | const result = next(action);
20 |
21 | const state = storeAPI.getState();
22 |
23 | const storage = createStorage(options?.authPersistance);
24 |
25 | if (action.type === setAuthData.type) {
26 | for (const [key, value] of Object.entries(state.auth.data)) {
27 | if (Object.values(value).filter(Boolean).length > 0) {
28 | storage.setItem(key, JSON.stringify(value));
29 | } else {
30 | storage.removeItem(key);
31 | }
32 | }
33 | }
34 |
35 | if (action.type === setSelectedAuth.type) {
36 | if (state.auth.selected) {
37 | storage.setItem(
38 | hashArray(Object.keys(state.auth.options)),
39 | state.auth.selected
40 | );
41 | }
42 | }
43 |
44 | if (action.type === setServer.type) {
45 | if (state.server.value?.url) {
46 | // FIXME What to use as key?
47 | storage.setItem(
48 | `docusaurus.openapi.server/${state.server.value?.url}`,
49 | JSON.stringify(state.server.value)
50 | );
51 | }
52 | }
53 |
54 | if (action.type === setServerVariable.type) {
55 | if (state.server.value?.url) {
56 | storage.setItem(
57 | `docusaurus.openapi.server/${state.server.value?.url}`,
58 | JSON.stringify(state.server.value)
59 | );
60 | }
61 | }
62 |
63 | return result;
64 | };
65 | return persistanceMiddleware;
66 | }
67 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/storage-utils.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import crypto from "crypto-js";
9 |
10 | export function hashArray(arr: string[]) {
11 | function hash(message: string) {
12 | return crypto.SHA1(message).toString();
13 | }
14 | const hashed = arr.map((item) => hash(item));
15 | hashed.sort();
16 | const res = hashed.join();
17 | return hash(res);
18 | }
19 |
20 | type Persistance = false | "localStorage" | "sessionStorage" | undefined;
21 |
22 | export function createStorage(persistance: Persistance): Storage {
23 | if (persistance === false) {
24 | return {
25 | getItem: () => null,
26 | setItem: () => {},
27 | clear: () => {},
28 | key: () => null,
29 | removeItem: () => {},
30 | length: 0,
31 | };
32 | }
33 |
34 | if (persistance === "sessionStorage") {
35 | return sessionStorage;
36 | }
37 |
38 | return localStorage;
39 | }
40 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/store.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { configureStore, combineReducers } from "@reduxjs/toolkit";
9 |
10 | import accept from "./Accept/slice";
11 | import auth from "./Authorization/slice";
12 | import body from "./Body/slice";
13 | import contentType from "./ContentType/slice";
14 | import params from "./ParamOptions/slice";
15 | import response from "./Response/slice";
16 | import server from "./Server/slice";
17 |
18 | const rootReducer = combineReducers({
19 | accept,
20 | contentType,
21 | response,
22 | server,
23 | body,
24 | params,
25 | auth,
26 | });
27 |
28 | export type RootState = ReturnType;
29 |
30 | export const createStoreWithState = (
31 | preloadedState: RootState,
32 | middlewares: any[]
33 | ) =>
34 | configureStore({
35 | reducer: rootReducer,
36 | preloadedState,
37 | middleware: (getDefaultMiddleware) =>
38 | getDefaultMiddleware().concat(...middlewares),
39 | });
40 |
41 | export type AppDispatch = ReturnType["dispatch"];
42 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/styles.module.css:
--------------------------------------------------------------------------------
1 | .optionsPanel:empty {
2 | display: none;
3 | }
4 |
5 | .optionsPanel {
6 | background: var(--openapi-card-background-color);
7 | border-radius: var(--openapi-card-border-radius);
8 | color: var(--ifm-pre-color);
9 | line-height: var(--ifm-pre-line-height);
10 | margin-bottom: var(--ifm-spacing-vertical);
11 | margin-top: 0;
12 | overflow: auto;
13 | padding: var(--ifm-pre-padding);
14 |
15 | /* hack for view calculation when monaco is hidden */
16 | position: relative;
17 | }
18 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/text.test.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { stripText } from "./text";
9 |
10 | describe("stripText function", () => {
11 | it("should return empty string when passed undefined", () => {
12 | expect(stripText(undefined)).toBe("");
13 | });
14 |
15 | it("should strip markdown", () => {
16 | expect(
17 | stripText(
18 | "**This** description contains [markdown](https://www.markdownguide.org/)"
19 | )
20 | ).toBe("This description contains markdown");
21 | });
22 |
23 | it("should strip HTML", () => {
24 | expect(
25 | stripText(
26 | 'This description contains HTML'
27 | )
28 | ).toBe("This description contains HTML");
29 | });
30 |
31 | it("should replace newlines with space", () => {
32 | expect(stripText("one\ntwo\n\nthree")).toBe("one two three");
33 | });
34 |
35 | it("should insert whitespace between HTML elements", () => {
36 | expect(
37 | stripText("two
three
four")
38 | ).toBe("one two three four");
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiDemoPanel/text.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { marked } from "marked";
9 | import striptags from "striptags";
10 |
11 | export function stripText(text?: string): string {
12 | if (text === undefined) {
13 | return "";
14 | }
15 | const renderer = new marked.TextRenderer();
16 | marked.use({ silent: true, renderer });
17 | const parsedMarkdown = marked.parse(text, { async: false }) as string;
18 | return striptags(parsedMarkdown, [], " ").replace(/\s+/g, " ").trim();
19 | }
20 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiItem/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
11 | import { PageMetadata } from "@docusaurus/theme-common";
12 | import type { Props } from "@theme/ApiItem";
13 | import DocPaginator from "@theme/DocPaginator";
14 | import clsx from "clsx";
15 |
16 | import styles from "./styles.module.css";
17 |
18 | let ApiDemoPanel = (_: { item: any }) => ;
19 | if (ExecutionEnvironment.canUseDOM) {
20 | ApiDemoPanel = require("@theme/ApiDemoPanel").default;
21 | }
22 |
23 | function ApiItem(props: Props): JSX.Element {
24 | const { content: ApiContent } = props;
25 | const { metadata, frontMatter } = ApiContent;
26 | const { image, keywords } = frontMatter;
27 | const { description, title, api, previous, next } = metadata;
28 |
29 | return (
30 | <>
31 |
32 |
33 |
34 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
44 |
45 |
48 |
49 | >
50 | );
51 | }
52 |
53 | export default ApiItem;
54 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/ApiItem/styles.module.css:
--------------------------------------------------------------------------------
1 | .apiItemContainer article > *:first-child,
2 | .apiItemContainer header + * {
3 | margin-top: 0;
4 | }
5 |
6 | /* default markdown margins look really silly in a table */
7 | :global(.theme-api-markdown table *:last-child) {
8 | margin-bottom: 0;
9 | }
10 |
11 | @media (min-width: 997px) {
12 | .docItemCol {
13 | max-width: 75% !important;
14 | }
15 |
16 | /* Prevent hydration FOUC, as the mobile TOC needs to be server-rendered */
17 | .tocMobile {
18 | display: none;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/theme/MarkdownItem/index.tsx:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import React from "react";
9 |
10 | import { PageMetadata } from "@docusaurus/theme-common";
11 | import DocPaginator from "@theme/DocPaginator";
12 | import type { Props } from "@theme/MarkdownItem";
13 | import MDXContent from "@theme/MDXContent";
14 | import clsx from "clsx";
15 |
16 | import styles from "../ApiItem/styles.module.css";
17 |
18 | export default function MarkdownItem(props: Props) {
19 | const { content: MDXPageContent } = props;
20 | const {
21 | metadata: { title, description, frontMatter, previous, next },
22 | } = MDXPageContent;
23 | const { image, keywords } = frontMatter;
24 |
25 | return (
26 | <>
27 |
28 |
29 |
30 |
31 |
32 |
33 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | >
50 | );
51 | }
52 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/src/types.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | export interface ThemeConfig {
9 | api?: {
10 | proxy?: string;
11 | authPersistance?: false | "localStorage" | "sessionStorage";
12 | serverVariablesPersistance?: false | "localStorage" | "sessionStorage";
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/packages/docusaurus-theme-openapi/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "lib": ["DOM", "ES2019"],
5 | "module": "esnext",
6 | "noEmit": true,
7 | "jsx": "react"
8 | },
9 | "include": ["src"]
10 | }
11 |
--------------------------------------------------------------------------------
/scripts/README.md:
--------------------------------------------------------------------------------
1 | # Release
2 |
3 | ## Propose a release
4 |
5 | Update package versions, update the changelog and open a PR to propose a new release.
6 |
7 | ### 1. Update package versions
8 |
9 | ```
10 | yarn release:version
11 | version options:
12 | - major | minor | patch | premajor | preminor | prepatch | prerelease | graduate
13 | ```
14 |
15 | Creating a prerelease, example:
16 |
17 | ```
18 | yarn release:version preminor
19 | 1.2.3 -> 1.3.3-rc.0
20 | ```
21 |
22 | Graduating a prerelease, example:
23 |
24 | ```
25 | yarn release:version graduate
26 | 1.3.3-rc.5 -> 1.3.3
27 | ```
28 |
29 | ### 2. Update template version
30 |
31 | Update the template file, which will be used by `npx` and `yarn` to create a new template site.
32 |
33 | Go to `packages\docusaurus-template-openapi\template.json`, then update the version of the template and the relevant version of `docusaurus-preset-openapi` under the dependencies.
34 |
35 | ### 3. Update `CHANGELOG.md`
36 |
37 | A partial changelog can be generated by running:
38 |
39 | ```
40 | yarn release:changelog
41 | ```
42 |
43 | Fill out the required information in the generated template and prepend it to `CHANGELOG.md`
44 |
45 | ### 3. Open a PR
46 |
47 | Open a PR to be approved/merged. Once merged, the packages should be published.
48 |
49 | ## Publish
50 |
51 | To create a tag and publish all packages to npm, run:
52 |
53 | ```
54 | yarn release:publish
55 | ```
56 |
57 | Once published update the GitHub release tag to include changelog information.
58 |
--------------------------------------------------------------------------------
/scripts/changelog.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ts-node
2 | /* ============================================================================
3 | * Copyright (c) Cloud Annotations
4 | *
5 | * This source code is licensed under the MIT license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | * ========================================================================== */
8 |
9 | import { getOutput } from "./utils/get-output";
10 | import { printBanner, printSpacer } from "./utils/print-utils";
11 | import pkg from "../lerna.json";
12 |
13 | const ORG = "cloud-annotations";
14 | const REPO = "docusaurus-openapi";
15 | const BRANCH = "main";
16 |
17 | const COMMIT_FILTERS = [/\(release\) v.*/];
18 |
19 | // Makes the script crash on unhandled rejections instead of silently
20 | // ignoring them. In the future, promise rejections that are not handled will
21 | // terminate the Node.js process with a non-zero exit code.
22 | process.on("unhandledRejection", (err) => {
23 | throw err;
24 | });
25 |
26 | function findUpstreamMaster() {
27 | const remotes = getOutput("git remote -v").split(/\r?\n/);
28 |
29 | for (const remote of remotes) {
30 | const [name, url, method] = remote.split(/\s/);
31 |
32 | const r = new RegExp(`${ORG}\\/${REPO}(\\.git)?$`);
33 |
34 | if (r.test(url) && method === "(push)") {
35 | return `${name}/${BRANCH}`;
36 | }
37 | }
38 | return undefined;
39 | }
40 |
41 | function findLatestTag() {
42 | return getOutput(`git describe --tags --abbrev=0 --match "v*"`);
43 | }
44 |
45 | function getCommits(commitRange: string) {
46 | return getOutput(`git log --pretty="%s" ${commitRange}`).split(/\r?\n/);
47 | }
48 |
49 | function formatCommits(commits: string[]) {
50 | return commits
51 | .filter((c) => {
52 | for (const filter of COMMIT_FILTERS) {
53 | if (filter.test(c)) {
54 | return false;
55 | }
56 | }
57 | return true;
58 | })
59 | .map((c) => {
60 | const r = /\(#(\d+)\)$/;
61 | return `- ${c.replace(
62 | r,
63 | `([#$1](https://github.com/${ORG}/${REPO}/pull/$1))`
64 | )}`;
65 | });
66 | }
67 |
68 | function main() {
69 | const args = process.argv.slice(2);
70 | let commitRange;
71 | if (args.length > 0) {
72 | commitRange = args.join(" ");
73 | } else {
74 | const latestTag = findLatestTag();
75 | if (latestTag === undefined) {
76 | console.error("Error: Unable to find the latest tag.");
77 | process.exit(1);
78 | }
79 |
80 | const upstream = findUpstreamMaster();
81 | if (upstream === undefined) {
82 | console.error("Error: Unable to find the upstream.");
83 | process.exit(1);
84 | }
85 | commitRange = `${latestTag}...${upstream}`;
86 | }
87 |
88 | console.log(`Comparing ${commitRange}`);
89 |
90 | const commits = getCommits(commitRange);
91 | const formattedCommits = formatCommits(commits);
92 |
93 | if (formattedCommits.length === 0) {
94 | console.error("Error: There has been no changes since last release.");
95 | process.exit(1);
96 | }
97 |
98 | const date = new Date().toLocaleDateString("en-US", {
99 | month: "short",
100 | day: "numeric",
101 | year: "numeric",
102 | });
103 |
104 | const changelog = `
105 | ## ${pkg.version} (${date})
106 |
107 | High-level enhancements
108 |
109 | - TODO HIGHLIGHTS
110 |
111 | Other enhancements and bug fixes
112 |
113 | ${formattedCommits.join("\n")}
114 | `;
115 |
116 | printBanner("Prepend the following to CHANGELOG.md");
117 | console.log(changelog);
118 | printSpacer();
119 | }
120 |
121 | main();
122 |
--------------------------------------------------------------------------------
/scripts/check-pr-title.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ts-node
2 | /* ============================================================================
3 | * Copyright (c) Cloud Annotations
4 | *
5 | * This source code is licensed under the MIT license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | * ========================================================================== */
8 |
9 | import { getOutput } from "./utils/get-output";
10 | import { version } from "../lerna.json";
11 |
12 | // Makes the script crash on unhandled rejections instead of silently
13 | // ignoring them. In the future, promise rejections that are not handled will
14 | // terminate the Node.js process with a non-zero exit code.
15 | process.on("unhandledRejection", (err) => {
16 | throw err;
17 | });
18 |
19 | function versions() {
20 | return getOutput(`git tag --list 'v*'`).split("\n");
21 | }
22 |
23 | function main() {
24 | const actualTitle = process.argv[2];
25 | const expectedTitle = `Prepare release v${version}`;
26 |
27 | if (!versions().includes(`v${version}`)) {
28 | if (actualTitle !== expectedTitle) {
29 | console.log(`\x1b[31mPR title should be: "${expectedTitle}"\x1b[0m`);
30 | process.exit(1);
31 | }
32 | }
33 | }
34 |
35 | main();
36 |
--------------------------------------------------------------------------------
/scripts/publish.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ts-node
2 | /* ============================================================================
3 | * Copyright (c) Cloud Annotations
4 | *
5 | * This source code is licensed under the MIT license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | * ========================================================================== */
8 |
9 | import { execSync } from "child_process";
10 | import fs from "fs";
11 | import path from "path";
12 |
13 | import { createDryRun } from "./utils/dry-run";
14 | import { getOutput } from "./utils/get-output";
15 | import { printBanner } from "./utils/print-utils";
16 | import { version } from "../lerna.json";
17 |
18 | const ORG = "cloud-annotations";
19 | const REPO = "docusaurus-openapi";
20 | let REPO_ROOT = undefined;
21 |
22 | // Makes the script crash on unhandled rejections instead of silently
23 | // ignoring them. In the future, promise rejections that are not handled will
24 | // terminate the Node.js process with a non-zero exit code.
25 | process.on("unhandledRejection", (err) => {
26 | throw err;
27 | });
28 |
29 | const safeExec = createDryRun(execSync);
30 | const safeRmdir = createDryRun(fs.rmSync);
31 | const safeMkdir = createDryRun(fs.mkdirSync);
32 |
33 | function getGitUserName() {
34 | return getOutput("git config user.name");
35 | }
36 |
37 | function getGitUserEmail() {
38 | return getOutput("git config user.email");
39 | }
40 |
41 | function ensureCleanDir(path: string) {
42 | if (fs.existsSync(path)) {
43 | safeRmdir(path, { recursive: true });
44 | }
45 | safeMkdir(path, { recursive: true });
46 | }
47 |
48 | function checkoutCode() {
49 | printBanner("Retrieving source code");
50 |
51 | const BUILD_PATH = "build";
52 | ensureCleanDir(BUILD_PATH);
53 |
54 | safeExec(`git clone git@github.com:${ORG}/${REPO}.git ${REPO}`, {
55 | cwd: BUILD_PATH,
56 | });
57 |
58 | REPO_ROOT = path.join(BUILD_PATH, REPO);
59 | }
60 |
61 | function configureGit() {
62 | const gitUserName = getGitUserName();
63 | const gitUserEmail = getGitUserEmail();
64 | safeExec(`git config user.name ${gitUserName}`, {
65 | cwd: REPO_ROOT,
66 | });
67 | safeExec(`git config user.email ${gitUserEmail}`, {
68 | cwd: REPO_ROOT,
69 | });
70 | }
71 |
72 | function buildAndPublish() {
73 | safeExec(`yarn install --frozen-lockfile`, {
74 | cwd: REPO_ROOT,
75 | stdio: "ignore",
76 | });
77 |
78 | printBanner("Building Packages");
79 |
80 | safeExec(`yarn lerna run build --no-private`, {
81 | cwd: REPO_ROOT,
82 | });
83 |
84 | printBanner("Publishing Packages");
85 |
86 | // --no-verify-access enables lerna publish to work in ci with access token.
87 | safeExec(`lerna publish --yes from-package --no-verify-access`, {
88 | cwd: REPO_ROOT,
89 | });
90 | }
91 |
92 | function tag() {
93 | const tag = `v${version}`;
94 | const message = `Version ${version}`;
95 | safeExec(`git tag -a ${tag} -m "${message}"`, {
96 | cwd: REPO_ROOT,
97 | });
98 | safeExec(`git push origin ${tag}`, {
99 | cwd: REPO_ROOT,
100 | });
101 | }
102 |
103 | function versions() {
104 | return getOutput(`git tag --list 'v*'`).split("\n");
105 | }
106 |
107 | function main() {
108 | if (versions().includes(`v${version}`)) {
109 | console.log(`\x1b[33mSKIPPING: Version ${version} already exists.\x1b[0m`);
110 | return;
111 | }
112 | if (!process.env.CI) {
113 | checkoutCode();
114 | }
115 | configureGit();
116 | buildAndPublish();
117 | tag();
118 | }
119 |
120 | main();
121 |
--------------------------------------------------------------------------------
/scripts/utils/dry-run.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | const IS_DRY_RUN =
9 | process.argv.slice(2).findIndex((arg) => /--dry-{0,1}run/i.test(arg)) !== -1;
10 |
11 | export function createDryRun any>(cmd: T) {
12 | if (IS_DRY_RUN) {
13 | return (...args: Parameters) => {
14 | const arg0 = args[0];
15 | const arg1 = args[1];
16 |
17 | let commandString = `${cmd.name}(\`${arg0}\`)`;
18 |
19 | if (arg1 !== undefined) {
20 | commandString = `${cmd.name}(\`${arg0}\`, ${JSON.stringify(
21 | arg1,
22 | null,
23 | 2
24 | )})`;
25 | }
26 |
27 | console.log();
28 | for (const line of commandString.split("\n")) {
29 | console.log(`> ${line}`);
30 | }
31 | console.log();
32 | };
33 | }
34 |
35 | return cmd;
36 | }
37 |
--------------------------------------------------------------------------------
/scripts/utils/get-output.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | import { execSync } from "child_process";
9 |
10 | export function getOutput(command: string) {
11 | return execSync(command).toString("utf-8").trim();
12 | }
13 |
--------------------------------------------------------------------------------
/scripts/utils/print-utils.ts:
--------------------------------------------------------------------------------
1 | /* ============================================================================
2 | * Copyright (c) Cloud Annotations
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | * ========================================================================== */
7 |
8 | export function printBanner(title: string) {
9 | console.log();
10 | console.log("-".repeat(80));
11 | const titleWidth = title.length + 2;
12 | const left = Math.floor((80 - titleWidth) / 2);
13 | const right = Math.ceil((80 - titleWidth) / 2);
14 | console.log(`${"-".repeat(left)} ${title} ${"-".repeat(right)}`);
15 | console.log("-".repeat(80));
16 | }
17 |
18 | export function printSpacer() {
19 | console.log("-".repeat(80));
20 | console.log();
21 | }
22 |
23 | export function printValue(key: string, value: string) {
24 | console.log(`${key} \t\t-> ${value}`);
25 | }
26 |
--------------------------------------------------------------------------------
/scripts/version.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ts-node
2 | /* ============================================================================
3 | * Copyright (c) Cloud Annotations
4 | *
5 | * This source code is licensed under the MIT license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | * ========================================================================== */
8 |
9 | import { execSync } from "child_process";
10 |
11 | import semver from "semver";
12 |
13 | import pkg from "../lerna.json";
14 |
15 | // Makes the script crash on unhandled rejections instead of silently
16 | // ignoring them. In the future, promise rejections that are not handled will
17 | // terminate the Node.js process with a non-zero exit code.
18 | process.on("unhandledRejection", (err) => {
19 | throw err;
20 | });
21 |
22 | function generateVersion(
23 | bump:
24 | | "major"
25 | | "minor"
26 | | "patch"
27 | | "premajor"
28 | | "preminor"
29 | | "prepatch"
30 | | "prerelease"
31 | | "graduate"
32 | ) {
33 | if (bump === "graduate") {
34 | const v = semver.parse(pkg.version);
35 | if (v === null) {
36 | console.error("Error: Invalid package version.");
37 | process.exit(1);
38 | }
39 | return `${v.major}.${v.minor}.${v.patch}`;
40 | }
41 |
42 | const newVersion = semver.inc(pkg.version, bump, "rc");
43 | if (newVersion === null) {
44 | console.error("Error: Invalid package version.");
45 | process.exit(1);
46 | }
47 | return newVersion;
48 | }
49 |
50 | function main() {
51 | const [bump] = process.argv.slice(2);
52 |
53 | let nextVersion;
54 | switch (bump) {
55 | case "major":
56 | case "minor":
57 | case "patch":
58 | case "premajor":
59 | case "preminor":
60 | case "prepatch":
61 | case "prerelease":
62 | case "graduate":
63 | nextVersion = generateVersion(bump);
64 | break;
65 | default:
66 | const v = semver.valid(bump);
67 | if (v === null) {
68 | console.error("Error: Invalid version bump.");
69 | process.exit(1);
70 | }
71 | nextVersion = v;
72 | }
73 |
74 | execSync(
75 | `lerna version ${nextVersion} --no-git-tag-version --no-push --yes`,
76 | { stdio: "ignore" }
77 | );
78 | }
79 |
80 | main();
81 |
--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2019",
4 | "module": "commonjs",
5 | "lib": ["ESNext", "DOM"],
6 | "declaration": true,
7 | // "allowJs": true, // causing strange issue
8 | "skipLibCheck": true,
9 | "jsx": "react",
10 |
11 | /* Strict Type-Checking Options */
12 | "strict": true,
13 | "strictNullChecks": true,
14 | "strictFunctionTypes": true,
15 | "strictBindCallApply": true,
16 | "strictPropertyInitialization": true,
17 | "noImplicitThis": true,
18 | "alwaysStrict": true,
19 |
20 | /* Additional Checks */
21 | "noImplicitReturns": true,
22 | "noFallthroughCasesInSwitch": true,
23 | "forceConsistentCasingInFileNames": true,
24 |
25 | /* Module Resolution Options */
26 | "moduleResolution": "node",
27 | "allowSyntheticDefaultImports": true,
28 | "esModuleInterop": true,
29 |
30 | /* Advanced Options */
31 | "resolveJsonModule": true,
32 | "isolatedModules": true
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "resolveJsonModule": true,
4 | "esModuleInterop": true,
5 | "noEmit": true
6 | },
7 | "include": ["scripts"]
8 | }
9 |
--------------------------------------------------------------------------------