├── .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 | ![Docusaurus logo](/img/docusaurus.png) 50 | ``` 51 | 52 | ![Docusaurus logo](/img/docusaurus.png) 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 | ![Docs Version Dropdown](/img/tutorial/docsVersionDropdown.png) 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 | ![Locale Dropdown](/img/tutorial/localeDropdown.png) 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 |
13 |
14 |

{siteConfig.title}

15 |

{siteConfig.tagline}

16 |
17 | 21 | Get Started 22 | 23 |
24 |
25 |
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 | ![](https://user-images.githubusercontent.com/4212769/85324376-b9e3d900-b497-11ea-9765-c42a8ad1ff61.png) 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)}`; 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 | ![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg) 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 | ![Docusaurus logo](/img/docusaurus.png) 50 | ``` 51 | 52 | ![Docusaurus logo](/img/docusaurus.png) 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 | ![Docs Version Dropdown](/img/tutorial/docsVersionDropdown.png) 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 | ![Locale Dropdown](/img/tutorial/localeDropdown.png) 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 |
13 |
14 |

{siteConfig.title}

15 |

{siteConfig.tagline}

16 |
17 | 21 | Docusaurus Tutorial - 5min ⏱️ 22 | 23 |
24 |
25 |
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* { 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(/^]*[^/]$/)) { 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("
one

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 |
38 | 39 |
40 |
41 | 42 | 43 |
44 |
45 |
46 | {api && } 47 |
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 | --------------------------------------------------------------------------------