From 474d42129a305124391c7ef140e89d20e0701a16 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 13:43:57 +0530 Subject: [PATCH 01/32] fix config --- .vscode/settings.json | 83 +++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index bb9f2d5a..040d3c8d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,43 +1,42 @@ { - "eslint.validate": [ - "javascript", - "javascriptreact", - "typescript", - "typescriptreact", - "graphql" - ], - "eslint.options": { - "extentions": [".js", ".jsx", ".ts", ".tsx", ".graphql"] - }, - "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "[javascript]": { - "editor.formatOnSave": false, - "editor.codeActionsOnSave": { - "source.fixAll": true - } - }, - "[javascriptreact]": { - "editor.formatOnSave": false, - "editor.codeActionsOnSave": { - "source.fixAll": true - } - }, - "[typescript]": { - "editor.formatOnSave": false, - "editor.codeActionsOnSave": { - "source.fixAll": true - } - }, - "[typescriptreact]": { - "editor.formatOnSave": false, - "editor.codeActionsOnSave": { - "source.fixAll": true - } - }, - "editor.tabCompletion": "on", - "editor.tabSize": 2, - "editor.rulers": [80, 120], - "typescript.tsdk": "node_modules/typescript/lib" - } - \ No newline at end of file + "eslint.validate": [ + "javascript", + "javascriptreact", + "typescript", + "typescriptreact", + "graphql" + ], + "eslint.options": { + "extensions": [".js", ".jsx", ".ts", ".tsx", ".graphql"] + }, + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[javascript]": { + "editor.formatOnSave": false, + "editor.codeActionsOnSave": { + "source.fixAll": true + } + }, + "[javascriptreact]": { + "editor.formatOnSave": false, + "editor.codeActionsOnSave": { + "source.fixAll": true + } + }, + "[typescript]": { + "editor.formatOnSave": false, + "editor.codeActionsOnSave": { + "source.fixAll": true + } + }, + "[typescriptreact]": { + "editor.formatOnSave": false, + "editor.codeActionsOnSave": { + "source.fixAll": true + } + }, + "editor.tabCompletion": "on", + "editor.tabSize": 2, + "editor.rulers": [80, 120], + "typescript.tsdk": "node_modules/typescript/lib" +} From 62bafc2221ab62071959d7bb7e196aec1792d64e Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 13:44:06 +0530 Subject: [PATCH 02/32] add vercel support --- website/docusaurus.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 63920780..76d480bf 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -71,7 +71,7 @@ const config = { description: 'Integrate Redoc easily into your Docusaurus Site', }, }, - url: process.env.DEPLOY_PRIME_URL || 'http://localhost:5000', // Your website URL + url: process.env.VERCEL_URL || process.env.DEPLOY_PRIME_URL || 'http://localhost:5000', // Your website URL baseUrl: process.env.DEPLOY_BASE_URL || '/', // Base URL for your project */ favicon: 'img/favicon.ico', themeConfig: { From 4a61225624ce42b9dcdd05da4620789b91937c60 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 13:45:05 +0530 Subject: [PATCH 03/32] =?UTF-8?q?=F0=9F=92=A5=20parse=20specUrls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/docusaurus-plugin-redoc/package.json | 1 + packages/docusaurus-plugin-redoc/src/index.ts | 23 ++++++++++--------- .../docusaurus-plugin-redoc/src/options.ts | 12 ++-------- yarn.lock | 1 + 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/packages/docusaurus-plugin-redoc/package.json b/packages/docusaurus-plugin-redoc/package.json index ee6960dc..9e79ac5c 100644 --- a/packages/docusaurus-plugin-redoc/package.json +++ b/packages/docusaurus-plugin-redoc/package.json @@ -29,6 +29,7 @@ "@docusaurus/types": "^2.0.0-beta.17", "@docusaurus/utils": "^2.0.0-beta.17", "joi": "^17.5.0", + "redoc": "^2.0.0-rc.64", "yaml": "^1.10.2" }, "engines": { diff --git a/packages/docusaurus-plugin-redoc/src/index.ts b/packages/docusaurus-plugin-redoc/src/index.ts index 3a3e69f3..ac9b0074 100644 --- a/packages/docusaurus-plugin-redoc/src/index.ts +++ b/packages/docusaurus-plugin-redoc/src/index.ts @@ -7,6 +7,7 @@ import type { } from '@docusaurus/types'; import { normalizeUrl } from '@docusaurus/utils'; import YAML from 'yaml'; +import { loadAndBundleSpec } from 'redoc'; import { Spec, @@ -21,7 +22,7 @@ export { PluginOptions }; export default function redocPlugin( context: LoadContext, opts: PluginOptions, -): Plugin | null> { +): Plugin> { const { baseUrl } = context.siteConfig; const options: PluginOptionsWithDefault = { ...DEFAULT_OPTIONS, ...opts }; const { debug, spec, specUrl } = options; @@ -32,19 +33,20 @@ export default function redocPlugin( return { name: 'docusaurus-plugin-redoc', async loadContent() { - let content: Record | null = null; + let parsedSpec: Record | null = null; if (spec) { const file = fs.readFileSync(spec).toString(); if (spec.endsWith('.yaml') || spec.endsWith('.yml')) { - const parsedSpec = YAML.parse(file); - content = parsedSpec; - } else content = JSON.parse(file); + parsedSpec = YAML.parse(file); + } else parsedSpec = JSON.parse(file); } + const content = await loadAndBundleSpec(parsedSpec || specUrl!); if (debug) { console.error('[REDOCUSAURUS_PLUGIN] Content:', content); } - return content; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return content as any; }, getPathsToWatch() { if (!spec) { @@ -61,17 +63,15 @@ export default function redocPlugin( } const data: Spec = { specUrl, - type: content ? 'object' : 'url', - // eslint-disable-next-line @typescript-eslint/no-explicit-any - content: (content || specUrl) as any, + content, }; setGlobalData(data); const specData = await createData( - `redocApiSpec-${options.id || '1'}.json`, + `redocApiSpecV1-${options.id || '1'}.json`, JSON.stringify(data), ); const layoutData = await createData( - `redocApiLayout-${options.id || '1'}.json`, + `redocApiLayoutV1-${options.id || '1'}.json`, JSON.stringify(options.layout), ); @@ -79,6 +79,7 @@ export default function redocPlugin( const routePath = options.routePath.startsWith('/') ? options.routePath.slice(1) : options.routePath; + const routeOptions = { path: normalizeUrl([baseUrl, routePath]), component: options.apiDocComponent, diff --git a/packages/docusaurus-plugin-redoc/src/options.ts b/packages/docusaurus-plugin-redoc/src/options.ts index 41257503..5e985ad7 100644 --- a/packages/docusaurus-plugin-redoc/src/options.ts +++ b/packages/docusaurus-plugin-redoc/src/options.ts @@ -16,16 +16,8 @@ type LayoutProps = { export type Spec = { specUrl?: string; -} & ( - | { - type: 'url'; - content: string; - } - | { - type: 'object'; - content: Record; - } -); + content: Record; +}; export interface PluginOptions { id?: string; diff --git a/yarn.lock b/yarn.lock index d9f39f24..57377b74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5958,6 +5958,7 @@ __metadata: "@docusaurus/types": ^2.0.0-beta.17 "@docusaurus/utils": ^2.0.0-beta.17 joi: ^17.5.0 + redoc: ^2.0.0-rc.64 yaml: ^1.10.2 languageName: unknown linkType: soft From 73910c3b91935225405cee3964f1ee49bf92e0c1 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 13:59:43 +0530 Subject: [PATCH 04/32] =?UTF-8?q?=F0=9F=92=A5=20always=20render=20via=20st?= =?UTF-8?q?ore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/hooks/useSpec.ts | 35 ++++++++++++++ .../src/theme/ApiDoc/ApiDoc.tsx | 9 +--- .../src/theme/ApiSchema/ApiSchema.tsx | 48 ++++--------------- .../src/theme/Redoc/Redoc.tsx | 41 ++++------------ .../src/types/common.ts | 25 +++------- 5 files changed, 61 insertions(+), 97 deletions(-) create mode 100644 packages/docusaurus-theme-redoc/src/hooks/useSpec.ts diff --git a/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts b/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts new file mode 100644 index 00000000..1ca977a6 --- /dev/null +++ b/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts @@ -0,0 +1,35 @@ +import { useMemo } from 'react'; +import { usePluginData } from '@docusaurus/useGlobalData'; +import { useColorMode } from '@docusaurus/theme-common'; +import { AppStore } from 'redoc'; +import { GlobalData, SpecProps } from '../types/common'; + +/** + * Redocusaurus + * https://rohit-gohri.github.io/redocusaurus/ + * (c) 2022 Rohit Gohri + * Released under the MIT License + */ +export function useSpec(spec: SpecProps['spec'], specUrl?: string) { + const { isDarkTheme } = useColorMode(); + const themeOptions = usePluginData('docusaurus-theme-redoc'); + + const result = useMemo(() => { + const { lightTheme, darkTheme, redocOptions } = themeOptions; + const theme = isDarkTheme ? darkTheme : lightTheme; + + const options = { + ...redocOptions, + theme, + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const store = new AppStore(spec as any, specUrl, options); + + return { + store, + options, + }; + }, [spec, specUrl, themeOptions, isDarkTheme]); + + return result; +} diff --git a/packages/docusaurus-theme-redoc/src/theme/ApiDoc/ApiDoc.tsx b/packages/docusaurus-theme-redoc/src/theme/ApiDoc/ApiDoc.tsx index 1533cd05..501c06ca 100644 --- a/packages/docusaurus-theme-redoc/src/theme/ApiDoc/ApiDoc.tsx +++ b/packages/docusaurus-theme-redoc/src/theme/ApiDoc/ApiDoc.tsx @@ -3,20 +3,15 @@ import Layout from '@theme/Layout'; import Redoc from '@theme/Redoc'; import { ApiDocProps as Props } from '../../types/common'; -function ApiDoc({ layoutProps, spec: propSpec }: Props): JSX.Element { +function ApiDoc({ layoutProps, spec }: Props): JSX.Element { const { title = 'API Docs', description = 'Open API Reference Docs for the API', } = layoutProps || {}; - const spec: Record | undefined = - propSpec.type === 'object' ? propSpec.content : undefined; - const specUrl: string | undefined = - propSpec.type === 'url' ? propSpec.content : undefined; - return ( - + ); } diff --git a/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx b/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx index be26f3e1..2670287e 100644 --- a/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx +++ b/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx @@ -1,15 +1,12 @@ -import React, { useMemo } from 'react'; -import { - usePluginData, - useAllPluginInstancesData, -} from '@docusaurus/useGlobalData'; -import { useColorMode } from '@docusaurus/theme-common'; +import React from 'react'; +import { useAllPluginInstancesData } from '@docusaurus/useGlobalData'; import clsx from 'clsx'; import { ThemeProvider } from 'styled-components'; -import { SchemaDefinition, AppStore } from 'redoc'; -import { ApiSchemaProps as Props, GlobalData, Spec } from '../../types/common'; +import { SchemaDefinition } from 'redoc'; +import { ApiSchemaProps as Props, Spec } from '../../types/common'; import '../Redoc/styles.css'; import './styles.css'; +import { useSpec } from '../../hooks/useSpec'; const ApiSchema: React.FC = ({ id, @@ -17,41 +14,14 @@ const ApiSchema: React.FC = ({ pointer, ...rest }: Props): JSX.Element => { - const { isDarkTheme } = useColorMode(); const allData = useAllPluginInstancesData('docusaurus-plugin-redoc'); - const { lightTheme, darkTheme, redocOptions } = usePluginData( - 'docusaurus-theme-redoc', - ); - const theme = isDarkTheme ? darkTheme : lightTheme; - - const store = useMemo(() => { - const { specUrl, content, type } = - allData[id as string] || - Object.values(allData).filter( - ({ type: dataType }) => dataType === 'object', - )?.[0]; - - if (type !== 'object' || !content) { - console.warn( - { allData }, - '[Redocusaurus] ApiSchems needs a spec file to render', - ); - return null; - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return new AppStore(content as any, specUrl, { - ...redocOptions, - theme, - }); - }, [id, allData, redocOptions, theme]); + const { specUrl, content } = + allData[id as string] || Object.values(allData)[0]; - if (!store) { - // @ts-expect-error fix return type - return null; - } + const { store, options } = useSpec(content, specUrl); return ( - +
( - 'docusaurus-theme-redoc', - ); - const theme = isDarkTheme ? darkTheme : lightTheme; - const { spec, specUrl, ...rest } = props; - const store = useMemo(() => { - if (!spec) return null; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return new AppStore(spec as any, specUrl, { - ...redocOptions, - theme, - }); - }, [spec, specUrl, redocOptions, theme]); + const { spec, specUrl } = props; + const { store } = useSpec(spec, specUrl); return (
- {store ? ( - - ) : ( - - )} +
); } diff --git a/packages/docusaurus-theme-redoc/src/types/common.ts b/packages/docusaurus-theme-redoc/src/types/common.ts index ed6fff24..98db1e9f 100644 --- a/packages/docusaurus-theme-redoc/src/types/common.ts +++ b/packages/docusaurus-theme-redoc/src/types/common.ts @@ -1,17 +1,14 @@ import type { Props as LayoutProps } from '@theme/Layout'; -import type { - RedocRawOptions, - ObjectDescriptionProps, - RedocStandaloneProps, -} from 'redoc'; +import type { RedocRawOptions, ObjectDescriptionProps } from 'redoc'; import type { RecursivePartial } from './util'; -export interface RedocProps - extends Omit { - spec?: Record; +export interface SpecProps { + spec: Record; specUrl?: string; } +export type RedocProps = SpecProps; + export type ApiSchemaProps = Omit< ObjectDescriptionProps, 'parser' | 'options' | 'schemaRef' @@ -30,16 +27,8 @@ export type ApiSchemaProps = Omit< export type Spec = { specUrl?: string; -} & ( - | { - type: 'url'; - content: string; - } - | { - type: 'object'; - content: Record; - } -); + content: Record; +}; export type ApiDocProps = { layoutProps?: Omit; From 105c61bd0cb970a94f70f5cf85dfd82dce6cf4d5 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 14:06:30 +0530 Subject: [PATCH 05/32] use base url for specUrl --- packages/docusaurus-theme-redoc/src/hooks/useSpec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts b/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts index 1ca977a6..ec52c4e6 100644 --- a/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts +++ b/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts @@ -1,4 +1,5 @@ import { useMemo } from 'react'; +import useBaseUrl from '@docusaurus/useBaseUrl'; import { usePluginData } from '@docusaurus/useGlobalData'; import { useColorMode } from '@docusaurus/theme-common'; import { AppStore } from 'redoc'; @@ -11,6 +12,7 @@ import { GlobalData, SpecProps } from '../types/common'; * Released under the MIT License */ export function useSpec(spec: SpecProps['spec'], specUrl?: string) { + const url = useBaseUrl(specUrl); const { isDarkTheme } = useColorMode(); const themeOptions = usePluginData('docusaurus-theme-redoc'); @@ -23,13 +25,13 @@ export function useSpec(spec: SpecProps['spec'], specUrl?: string) { theme, }; // eslint-disable-next-line @typescript-eslint/no-explicit-any - const store = new AppStore(spec as any, specUrl, options); + const store = new AppStore(spec as any, url, options); return { store, options, }; - }, [spec, specUrl, themeOptions, isDarkTheme]); + }, [spec, url, themeOptions, isDarkTheme]); return result; } From 3f58d0ad0bd45c621825d9cde1e4b4d78389fa5a Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 14:08:44 +0530 Subject: [PATCH 06/32] update examples --- website/docs/guides/schema-imports.mdx | 24 ++++++++++++++---------- website/docusaurus.config.js | 21 +++++++++------------ 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/website/docs/guides/schema-imports.mdx b/website/docs/guides/schema-imports.mdx index 786af3a1..94f9913e 100644 --- a/website/docs/guides/schema-imports.mdx +++ b/website/docs/guides/schema-imports.mdx @@ -43,16 +43,20 @@ const config = { 'redocusaurus', { specs: [ + { + id: 'using-spec-yaml', + spec: 'openapi.yaml', + /** + * This becomes the Download URL in this case, while docs are generated from `spec` file + */ + specUrl: `/openapi-page.yaml`, + routePath: '/examples/using-spec-yaml/', + }, { id: 'using-spec-url', specUrl: 'https://redocly.github.io/redoc/openapi.yaml', routePath: '/examples/using-spec-url/', }, - { - id: 'using-relative-url', - specUrl: `${process.env.DEPLOY_BASE_URL || '/'}openapi-page.yaml`, - routePath: '/examples/using-relative-url/', - }, ], theme: { /** @@ -76,16 +80,16 @@ const config = { ```tsx import ApiSchema from '@theme/ApiSchema'; +; ; -; ``` ### Results -#### For ID `id="using-spec-url"` +#### For ID `id="using-spec-yaml"` - + -#### For ID `id="using-relative-url"` +#### For ID `id="using-spec-url"` - + diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 76d480bf..88854737 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -6,25 +6,22 @@ const redocusaurus = [ { debug: Boolean(process.env.DEBUG || process.env.CI), specs: [ - { - id: 'using-spec-url', - specUrl: 'https://redocly.github.io/redoc/openapi.yaml', - routePath: '/examples/using-spec-url/', - }, - { - id: 'using-relative-url', - specUrl: `${process.env.DEPLOY_BASE_URL || '/'}openapi-page.yaml`, - routePath: '/examples/using-relative-url/', - }, { id: 'using-spec-yaml', + // Local File spec: 'openapi.yaml', /** - * This becomes the Download URL in this case, while docs are generated from `spec` + * This becomes the Download URL in this case, while docs are generated from `spec` file */ - specUrl: `${process.env.DEPLOY_BASE_URL || '/'}openapi-page.yaml`, + specUrl: `/openapi-page.yaml`, routePath: '/examples/using-spec-yaml/', }, + { + id: 'using-spec-url', + // Remote File + specUrl: 'https://redocly.github.io/redoc/openapi.yaml', + routePath: '/examples/using-spec-url/', + }, ], theme: { /** From 9881df96cc385e920ce66272607fee82651a751c Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 14:24:51 +0530 Subject: [PATCH 07/32] export hooks --- .../src/theme/ApiSchema/ApiSchema.tsx | 13 ++++------- .../src/theme/useApiData.ts | 16 +++++++++++++ .../src/types/modules.d.ts | 23 +++++++++++-------- 3 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 packages/docusaurus-theme-redoc/src/theme/useApiData.ts diff --git a/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx b/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx index 2670287e..7d516e0c 100644 --- a/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx +++ b/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import { useAllPluginInstancesData } from '@docusaurus/useGlobalData'; import clsx from 'clsx'; import { ThemeProvider } from 'styled-components'; import { SchemaDefinition } from 'redoc'; -import { ApiSchemaProps as Props, Spec } from '../../types/common'; +import { useSpec } from '../../hooks/useSpec'; +import { useApiData } from '../useApiData'; +import { ApiSchemaProps as Props } from '../../types/common'; import '../Redoc/styles.css'; import './styles.css'; -import { useSpec } from '../../hooks/useSpec'; const ApiSchema: React.FC = ({ id, @@ -14,11 +14,8 @@ const ApiSchema: React.FC = ({ pointer, ...rest }: Props): JSX.Element => { - const allData = useAllPluginInstancesData('docusaurus-plugin-redoc'); - const { specUrl, content } = - allData[id as string] || Object.values(allData)[0]; - - const { store, options } = useSpec(content, specUrl); + const apiData = useApiData(id); + const { store, options } = useSpec(apiData); return ( diff --git a/packages/docusaurus-theme-redoc/src/theme/useApiData.ts b/packages/docusaurus-theme-redoc/src/theme/useApiData.ts new file mode 100644 index 00000000..144f6f2f --- /dev/null +++ b/packages/docusaurus-theme-redoc/src/theme/useApiData.ts @@ -0,0 +1,16 @@ +import { useAllPluginInstancesData } from '@docusaurus/useGlobalData'; +import { Spec } from '../types/common'; + +/** + * + * @param id ID of plugin data + * @returns Spec Data of ID or first one if ID is not provided + */ +export function useApiData(id?: string) { + const allData = useAllPluginInstancesData('docusaurus-plugin-redoc'); + const apiData = allData[id as string] || Object.values(allData)[0]; + + return apiData; +} + +export default useApiData; diff --git a/packages/docusaurus-theme-redoc/src/types/modules.d.ts b/packages/docusaurus-theme-redoc/src/types/modules.d.ts index 18e95617..e68e24a9 100644 --- a/packages/docusaurus-theme-redoc/src/types/modules.d.ts +++ b/packages/docusaurus-theme-redoc/src/types/modules.d.ts @@ -10,15 +10,10 @@ declare module '@theme/Redoc' { declare module '@theme/ApiDoc' { import { Props as LayoutProps } from '@theme/Layout'; - type Spec = - | { - type: 'url'; - content: string; - } - | { - type: 'object'; - content: Record; - }; + type Spec = { + content: Record; + specUrl?: string; + }; export type Props = { layoutProps?: Omit; @@ -28,3 +23,13 @@ declare module '@theme/ApiDoc' { const ApiDoc: (props: Props) => JSX.Element; export default ApiDoc; } + +declare module '@theme/useApiData' { + type Spec = { + content: Record; + specUrl?: string; + }; + + const useApiData: (id?: string) => Spec; + export default useApiData; +} From 7d3710e52a5a0ab6be21a8e430ecfb7ea8a8a28e Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 14:27:38 +0530 Subject: [PATCH 08/32] fix example build --- website/docusaurus.config.js | 6 ++++++ website/src/pages/examples/custom-layout/index.jsx | 7 +++---- website/src/pages/examples/custom-page/index.jsx | 11 ++++------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 88854737..d28e47ae 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -22,6 +22,12 @@ const redocusaurus = [ specUrl: 'https://redocly.github.io/redoc/openapi.yaml', routePath: '/examples/using-spec-url/', }, + { + id: 'using-custom-layout', + spec: 'openapi.yaml', + specUrl: `/openapi-page.yaml`, + // NOTE: no `routePath` passed, instead data used in custom React Component ('custom-layout/index.jsx') + }, ], theme: { /** diff --git a/website/src/pages/examples/custom-layout/index.jsx b/website/src/pages/examples/custom-layout/index.jsx index 6a047758..0b3993fe 100644 --- a/website/src/pages/examples/custom-layout/index.jsx +++ b/website/src/pages/examples/custom-layout/index.jsx @@ -1,14 +1,13 @@ import React from 'react'; import Layout from '@theme/Layout'; import Redoc from '@theme/Redoc'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -const STATIC_SPEC = '/openapi-component.yaml'; +import useApiData from '@theme/useApiData'; function CustomPage() { + const specData = useApiData('using-custom-layout'); return ( - + ); } diff --git a/website/src/pages/examples/custom-page/index.jsx b/website/src/pages/examples/custom-page/index.jsx index e60bb643..eaa4cb86 100644 --- a/website/src/pages/examples/custom-page/index.jsx +++ b/website/src/pages/examples/custom-page/index.jsx @@ -1,20 +1,17 @@ import React from 'react'; import ApiDoc from '@theme/ApiDoc'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -const STATIC_SPEC = '/openapi-page.yaml'; +import useApiData from '@theme/useApiData'; function CustomPage() { + const specData = useApiData('using-custom-layout'); + return ( ); } From cd9f19f8f042dd71d9bab16665112e082abf4333 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 14:31:51 +0530 Subject: [PATCH 09/32] fix schema imports --- .../docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx b/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx index 7d516e0c..a8a247a7 100644 --- a/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx +++ b/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx @@ -15,10 +15,10 @@ const ApiSchema: React.FC = ({ ...rest }: Props): JSX.Element => { const apiData = useApiData(id); - const { store, options } = useSpec(apiData); + const { store } = useSpec(apiData.content, apiData.specUrl); return ( - +
Date: Sat, 12 Mar 2022 14:32:23 +0530 Subject: [PATCH 10/32] fix dev scripts --- package.json | 2 +- packages/docusaurus-theme-redoc/package.json | 3 +- yarn.lock | 68 +++++++++++++++++++- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 75ccae40..c0a1078a 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "build": "yarn workspaces foreach --exclude 'redocusaurus-website' -tv run build", "build:website": "yarn workspace redocusaurus-website run build", "clean": "yarn workspaces foreach -Atv exec \"rm -rf dist* .tsbuild*.info\"", - "dev": "yarn workspaces foreach --exclude redocusaurus-website -pv run dev", + "dev": "yarn workspaces foreach --exclude redocusaurus-website -piv run dev", "dev:website": "yarn workspace redocusaurus-website run dev", "lint": "eslint . --ext .js,.jsx,.ts,.tsx", "lint:fix": "yarn lint --fix", diff --git a/packages/docusaurus-theme-redoc/package.json b/packages/docusaurus-theme-redoc/package.json index 0f862449..04ad2589 100644 --- a/packages/docusaurus-theme-redoc/package.json +++ b/packages/docusaurus-theme-redoc/package.json @@ -45,7 +45,8 @@ "@types/react-dom": "^17.0.13", "@types/react-router-dom": "^5.3.3", "@types/rtlcss": "^3.1.2", - "@types/styled-components": "^5.1.24" + "@types/styled-components": "^5.1.24", + "nodemon": "^2.0.15" }, "engines": { "node": ">=14" diff --git a/yarn.lock b/yarn.lock index 57377b74..1dd71e69 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4715,7 +4715,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.4.2, chokidar@npm:^3.5.3": +"chokidar@npm:^3.4.2, chokidar@npm:^3.5.2, chokidar@npm:^3.5.3": version: 3.5.3 resolution: "chokidar@npm:3.5.3" dependencies: @@ -5980,6 +5980,7 @@ __metadata: lodash: ^4.17.21 mobx: ^6.3.13 node-polyfill-webpack-plugin: ^1.1.4 + nodemon: ^2.0.15 redoc: ^2.0.0-rc.64 styled-components: ^5.3.3 to-arraybuffer: ^1.0.1 @@ -8031,6 +8032,13 @@ __metadata: languageName: node linkType: hard +"ignore-by-default@npm:^1.0.1": + version: 1.0.1 + resolution: "ignore-by-default@npm:1.0.1" + checksum: 441509147b3615e0365e407a3c18e189f78c07af08564176c680be1fabc94b6c789cad1342ad887175d4ecd5225de86f73d376cec8e06b42fd9b429505ffcf8a + languageName: node + linkType: hard + "ignore@npm:^4.0.6": version: 4.0.6 resolution: "ignore@npm:4.0.6" @@ -9971,6 +9979,26 @@ __metadata: languageName: node linkType: hard +"nodemon@npm:^2.0.15": + version: 2.0.15 + resolution: "nodemon@npm:2.0.15" + dependencies: + chokidar: ^3.5.2 + debug: ^3.2.7 + ignore-by-default: ^1.0.1 + minimatch: ^3.0.4 + pstree.remy: ^1.1.8 + semver: ^5.7.1 + supports-color: ^5.5.0 + touch: ^3.1.0 + undefsafe: ^2.0.5 + update-notifier: ^5.1.0 + bin: + nodemon: bin/nodemon.js + checksum: 0569b09b713fdcc76f06734d7cc106950e69e02069cbf44bda3fae8d266926bdfa003aeddd22f8fcdf46ea6ff51ca64f5528f8006536e79820a26e648ef346cf + languageName: node + linkType: hard + "noms@npm:0.0.0": version: 0.0.0 resolution: "noms@npm:0.0.0" @@ -9992,6 +10020,17 @@ __metadata: languageName: node linkType: hard +"nopt@npm:~1.0.10": + version: 1.0.10 + resolution: "nopt@npm:1.0.10" + dependencies: + abbrev: 1 + bin: + nopt: ./bin/nopt.js + checksum: f62575aceaa3be43f365bf37a596b89bbac2e796b001b6d2e2a85c2140a4e378ff919e2753ccba959c4fd344776fc88c29b393bc167fa939fb1513f126f4cd45 + languageName: node + linkType: hard + "normalize-package-data@npm:^2.5.0": version: 2.5.0 resolution: "normalize-package-data@npm:2.5.0" @@ -11353,6 +11392,13 @@ __metadata: languageName: node linkType: hard +"pstree.remy@npm:^1.1.8": + version: 1.1.8 + resolution: "pstree.remy@npm:1.1.8" + checksum: 5cb53698d6bb34dfb278c8a26957964aecfff3e161af5fbf7cee00bbe9d8547c7aced4bd9cb193bce15fb56e9e4220fc02a5bf9c14345ffb13a36b858701ec2d + languageName: node + linkType: hard + "public-encrypt@npm:^4.0.0": version: 4.0.3 resolution: "public-encrypt@npm:4.0.3" @@ -12496,7 +12542,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:2 || 3 || 4 || 5, semver@npm:^5.4.1": +"semver@npm:2 || 3 || 4 || 5, semver@npm:^5.4.1, semver@npm:^5.7.1": version: 5.7.1 resolution: "semver@npm:5.7.1" bin: @@ -13639,6 +13685,17 @@ __metadata: languageName: node linkType: hard +"touch@npm:^3.1.0": + version: 3.1.0 + resolution: "touch@npm:3.1.0" + dependencies: + nopt: ~1.0.10 + bin: + nodetouch: ./bin/nodetouch.js + checksum: e0be589cb5b0e6dbfce6e7e077d4a0d5f0aba558ef769c6d9c33f635e00d73d5be49da6f8631db302ee073919d82b5b7f56da2987feb28765c95a7673af68647 + languageName: node + linkType: hard + "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -13852,6 +13909,13 @@ __metadata: languageName: node linkType: hard +"undefsafe@npm:^2.0.5": + version: 2.0.5 + resolution: "undefsafe@npm:2.0.5" + checksum: f42ab3b5770fedd4ada175fc1b2eb775b78f609156f7c389106aafd231bfc210813ee49f54483d7191d7b76e483bc7f537b5d92d19ded27156baf57592eb02cc + languageName: node + linkType: hard + "unherit@npm:^1.0.4": version: 1.1.3 resolution: "unherit@npm:1.1.3" From e80c03a2f0e6d1bc02926d0720913eeb2a5dddaf Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 14:33:35 +0530 Subject: [PATCH 11/32] docs(changeset): Parse schema at build time for urls too, remove support for relative urls --- .changeset/many-trees-hug.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/many-trees-hug.md diff --git a/.changeset/many-trees-hug.md b/.changeset/many-trees-hug.md new file mode 100644 index 00000000..3ce3c7ac --- /dev/null +++ b/.changeset/many-trees-hug.md @@ -0,0 +1,6 @@ +--- +'docusaurus-plugin-redoc': major +'docusaurus-theme-redoc': major +--- + +Parse schema at build time for urls too, remove support for relative urls From f7df0556e377eca594f8b95187d67c196d75aab6 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 14:39:31 +0530 Subject: [PATCH 12/32] fix url for vercel --- website/docusaurus.config.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index d28e47ae..2f5a9257 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -1,3 +1,7 @@ +if (process.env.VERCEL_URL) { + process.env.DEPLOY_PRIME_URL = `https://${process.env.VERCEL_URL}`; +} + /** * @type {import('redocusaurus').PresetEntry} */ @@ -74,7 +78,7 @@ const config = { description: 'Integrate Redoc easily into your Docusaurus Site', }, }, - url: process.env.VERCEL_URL || process.env.DEPLOY_PRIME_URL || 'http://localhost:5000', // Your website URL + url: process.env.DEPLOY_PRIME_URL || 'http://localhost:5000', // Your website URL baseUrl: process.env.DEPLOY_BASE_URL || '/', // Base URL for your project */ favicon: 'img/favicon.ico', themeConfig: { From d24dfee2c9cd265c6103233532556f976e9208ba Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 18:01:13 +0530 Subject: [PATCH 13/32] add common symlinked types --- packages/docusaurus-plugin-redoc/src/types/common.d.ts | 1 + .../src/types/{common.ts => common.d.ts} | 9 ++++++++- packages/docusaurus-theme-redoc/src/types/util.d.ts | 7 ------- 3 files changed, 9 insertions(+), 8 deletions(-) create mode 120000 packages/docusaurus-plugin-redoc/src/types/common.d.ts rename packages/docusaurus-theme-redoc/src/types/{common.ts => common.d.ts} (83%) delete mode 100644 packages/docusaurus-theme-redoc/src/types/util.d.ts diff --git a/packages/docusaurus-plugin-redoc/src/types/common.d.ts b/packages/docusaurus-plugin-redoc/src/types/common.d.ts new file mode 120000 index 00000000..747ea362 --- /dev/null +++ b/packages/docusaurus-plugin-redoc/src/types/common.d.ts @@ -0,0 +1 @@ +../../../docusaurus-theme-redoc/src/types/common.d.ts \ No newline at end of file diff --git a/packages/docusaurus-theme-redoc/src/types/common.ts b/packages/docusaurus-theme-redoc/src/types/common.d.ts similarity index 83% rename from packages/docusaurus-theme-redoc/src/types/common.ts rename to packages/docusaurus-theme-redoc/src/types/common.d.ts index 98db1e9f..4f343430 100644 --- a/packages/docusaurus-theme-redoc/src/types/common.ts +++ b/packages/docusaurus-theme-redoc/src/types/common.d.ts @@ -1,6 +1,13 @@ import type { Props as LayoutProps } from '@theme/Layout'; import type { RedocRawOptions, ObjectDescriptionProps } from 'redoc'; -import type { RecursivePartial } from './util'; + +export type RecursivePartial = { + [P in keyof T]?: T[P] extends (infer U)[] + ? RecursivePartial[] // eslint-disable-next-line @typescript-eslint/ban-types + : T[P] extends object + ? RecursivePartial + : T[P]; +}; export interface SpecProps { spec: Record; diff --git a/packages/docusaurus-theme-redoc/src/types/util.d.ts b/packages/docusaurus-theme-redoc/src/types/util.d.ts deleted file mode 100644 index 1eb4363d..00000000 --- a/packages/docusaurus-theme-redoc/src/types/util.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type RecursivePartial = { - [P in keyof T]?: T[P] extends (infer U)[] - ? RecursivePartial[] // eslint-disable-next-line @typescript-eslint/ban-types - : T[P] extends object - ? RecursivePartial - : T[P]; -}; From 37df72d34a217d561bd3f5e2076e14ef772e6790 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 18:18:16 +0530 Subject: [PATCH 14/32] don't hide download button by default --- packages/docusaurus-theme-redoc/Readme.md | 2 +- packages/docusaurus-theme-redoc/src/redocData.ts | 1 - website/docs/guides/schema-imports.mdx | 2 +- website/docs/guides/server-side-rendering.md | 2 +- website/docusaurus.config.js | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/docusaurus-theme-redoc/Readme.md b/packages/docusaurus-theme-redoc/Readme.md index a918b715..a60e8a42 100644 --- a/packages/docusaurus-theme-redoc/Readme.md +++ b/packages/docusaurus-theme-redoc/Readme.md @@ -57,7 +57,7 @@ primaryColor: '#1890ff', * Options to pass to redoc * @see https://github.com/redocly/redoc#redoc-options-object */ -redocOptions: { hideDownloadButton: false, disableSearch: true }, +redocOptions: { disableSearch: true }, /** * Options to pass to override RedocThemeObject * @see https://github.com/Redocly/redoc#redoc-theme-object diff --git a/packages/docusaurus-theme-redoc/src/redocData.ts b/packages/docusaurus-theme-redoc/src/redocData.ts index 94841c27..d95eff36 100644 --- a/packages/docusaurus-theme-redoc/src/redocData.ts +++ b/packages/docusaurus-theme-redoc/src/redocData.ts @@ -4,7 +4,6 @@ import { GlobalData, RedocThemeOverrides } from './types/common'; const defaultOptions: Partial = { scrollYOffset: 'nav.navbar', - hideDownloadButton: true, expandSingleSchemaField: true, menuToggle: true, // @ts-expect-error not available in types diff --git a/website/docs/guides/schema-imports.mdx b/website/docs/guides/schema-imports.mdx index 94f9913e..fd5e1faf 100644 --- a/website/docs/guides/schema-imports.mdx +++ b/website/docs/guides/schema-imports.mdx @@ -67,7 +67,7 @@ const config = { * Options to pass to redoc * @see https://github.com/redocly/redoc#redoc-options-object */ - redocOptions: { hideDownloadButton: false, disableSearch: true }, + redocOptions: { disableSearch: true }, }, }, ], diff --git a/website/docs/guides/server-side-rendering.md b/website/docs/guides/server-side-rendering.md index 6fa69442..7365d38e 100644 --- a/website/docs/guides/server-side-rendering.md +++ b/website/docs/guides/server-side-rendering.md @@ -62,7 +62,7 @@ const config = { * Options to pass to redoc * @see https://github.com/redocly/redoc#redoc-options-object */ - redocOptions: { hideDownloadButton: false, disableSearch: true }, + redocOptions: { disableSearch: true }, }, }, ], diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index e887802d..4c5ded71 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -49,7 +49,7 @@ const redocusaurus = [ * Options to pass to redoc * @see https://github.com/redocly/redoc#redoc-options-object */ - redocOptions: { hideDownloadButton: false, disableSearch: true }, + redocOptions: { disableSearch: true }, /** * Options to pass to override RedocThemeObject * @see https://github.com/Redocly/redoc#redoc-theme-object From 33627d299789203b57d38ec7ed8e9c601d0c96b4 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 20:18:25 +0530 Subject: [PATCH 15/32] =?UTF-8?q?=F0=9F=92=A5=20simplify=20plugin=20option?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/docusaurus-plugin-redoc/Readme.md | 29 +++----- packages/docusaurus-plugin-redoc/src/index.ts | 69 +++++++++++-------- .../docusaurus-plugin-redoc/src/options.ts | 27 ++------ .../src/types/common.d.ts | 37 ++-------- packages/redocusaurus/src/index.ts | 1 - 5 files changed, 61 insertions(+), 102 deletions(-) diff --git a/packages/docusaurus-plugin-redoc/Readme.md b/packages/docusaurus-plugin-redoc/Readme.md index 40f12a15..2b738d0d 100644 --- a/packages/docusaurus-plugin-redoc/Readme.md +++ b/packages/docusaurus-plugin-redoc/Readme.md @@ -2,35 +2,28 @@ ![npm](https://img.shields.io/npm/v/docusaurus-plugin-redoc?style=flat-square) -This plugin parses your OpenAPI spec files and creates pages using the `ApiDoc` component from your theme. Use with `docusaurus-theme-redoc`. +This plugin parses your OpenAPI spec files and makes them available as plugin data. Can use to creates pages using the `@theme/ApiDoc` component from your theme, or render it through custom react pages. -Read More Here: +⚠️⚠️⚠️ NOTE: Not recommended for direct use. Use through main package instead: [`redocusaurus`](https://github.com/rohit-gohri/redocusaurus) ## Options -Either of `spec` or `specUrl` is required (both can also be provided). +### spec (required, string: file path or remote absolute url) -### spec +Either a file path to an OpenAPI YAML/JSON file, or a url to one hosted on some website (not the same docusaurus website). Will be **parsed** at build time and forwarded to Redoc component. -A path to a OpenAPI yaml or json file. Will be parsed and forwarded to Redoc component. This has higher priority over specUrl. +### url (optional, string: download url) -### specUrl +A url pointing to an OpenAPI spec. This will be used as download url and `spec` will be used for rendering. This is needed because by default the download url will point to a processed and parsed JSON file. -A url pointing to an OpenAPI spec. If both are present, then this will be used as download url and `spec` for rendering. +### route (optional, string: relative uri) -### layout +Route URL at which docs would be available, this will use the theme component `@theme/ApiDoc` from `docusaurus-theme-redoc` to render the page. You can also skip this option and render the docs as you wish using a custom page. -An object to pass as layout props. Useful to set title/description of the page. See all properties available [here](https://github.com/rohit-gohri/redocusaurus/blob/main/packages/docusaurus-plugin-redoc/src/options.ts#L3). +### layout (optional, object: layoutProps) -### routePath (default: `/api/`) - -Route URL at which docs would be available - -### apiDocComponent (default: `@theme/ApiDoc`) - -If you want to use a custom component to render the spec instead of the one with `docusaurus-theme-redoc` then overwrite this with a path to the component. -It will be forwarded a single prop, see [ApiDoc](https://github.com/rohit-gohri/redocusaurus/blob/main/packages/docusaurus-theme-redoc/src/theme/ApiDoc/ApiDoc.tsx) for example. +An object to pass as layout props. Useful to set title/description of the page. See all properties available [here](./src/options.ts#L3). ## Docs -See: +See for examples and programmatic usage. diff --git a/packages/docusaurus-plugin-redoc/src/index.ts b/packages/docusaurus-plugin-redoc/src/index.ts index ac9b0074..2538f0c0 100644 --- a/packages/docusaurus-plugin-redoc/src/index.ts +++ b/packages/docusaurus-plugin-redoc/src/index.ts @@ -10,12 +10,12 @@ import YAML from 'yaml'; import { loadAndBundleSpec } from 'redoc'; import { - Spec, PluginOptionSchema, PluginOptions, PluginOptionsWithDefault, DEFAULT_OPTIONS, } from './options'; +import { ParsedSpec, SpecProps, ApiDocProps } from './types/common'; export { PluginOptions }; @@ -25,7 +25,7 @@ export default function redocPlugin( ): Plugin> { const { baseUrl } = context.siteConfig; const options: PluginOptionsWithDefault = { ...DEFAULT_OPTIONS, ...opts }; - const { debug, spec, specUrl } = options; + const { debug, spec, url } = options; if (debug) { console.error('[REDOCUSAURUS_PLUGIN] Opts Input:', opts); console.error('[REDOCUSAURUS_PLUGIN] Options:', options); @@ -33,18 +33,25 @@ export default function redocPlugin( return { name: 'docusaurus-plugin-redoc', async loadContent() { - let parsedSpec: Record | null = null; - if (spec) { + let parsedSpec: ParsedSpec | null = null; + // If local file + if (fs.existsSync(spec)) { + if (debug) { + console.log('[REDOCUSAURUS_PLUGIN] reading file: ', spec); + } + const file = fs.readFileSync(spec).toString(); if (spec.endsWith('.yaml') || spec.endsWith('.yml')) { parsedSpec = YAML.parse(file); } else parsedSpec = JSON.parse(file); } - const content = await loadAndBundleSpec(parsedSpec || specUrl!); + if (debug) { - console.error('[REDOCUSAURUS_PLUGIN] Content:', content); + console.log('[REDOCUSAURUS_PLUGIN] bundling spec'); } + const content = await loadAndBundleSpec(parsedSpec || spec!); + // eslint-disable-next-line @typescript-eslint/no-explicit-any return content as any; }, @@ -57,37 +64,39 @@ export default function redocPlugin( }, async contentLoaded({ content, actions }) { const { createData, addRoute, setGlobalData } = actions; - if (!content && !specUrl) { - console.error('[Redocusaurus] No spec provided'); - return; + if (!content) { + throw new Error(`[Redocusaurus] Spec could not be parsed: ${spec}`); } - const data: Spec = { - specUrl, - content, + + const data: SpecProps = { + url, + spec: content, }; setGlobalData(data); - const specData = await createData( - `redocApiSpecV1-${options.id || '1'}.json`, - JSON.stringify(data), - ); - const layoutData = await createData( - `redocApiLayoutV1-${options.id || '1'}.json`, - JSON.stringify(options.layout), - ); - if (options.addRoute) { - const routePath = options.routePath.startsWith('/') - ? options.routePath.slice(1) - : options.routePath; + if (options.route) { + const specProps = await createData( + `redocApiSpecV1-${options.id || '1'}.json`, + JSON.stringify(data), + ); + const layoutProps = await createData( + `redocApiLayoutV1-${options.id || '1'}.json`, + JSON.stringify(options.layout), + ); + const routePath = options.route.startsWith('/') + ? options.route.slice(1) + : options.route; + + const modules: Record = { + specProps, + layoutProps, + }; const routeOptions = { - path: normalizeUrl([baseUrl, routePath]), - component: options.apiDocComponent, - modules: { - spec: specData, - layoutProps: layoutData, - }, + modules, + component: '@theme/ApiDoc', exact: true, + path: normalizeUrl([baseUrl, routePath]), }; if (debug) { diff --git a/packages/docusaurus-plugin-redoc/src/options.ts b/packages/docusaurus-plugin-redoc/src/options.ts index 5e985ad7..62864aa4 100644 --- a/packages/docusaurus-plugin-redoc/src/options.ts +++ b/packages/docusaurus-plugin-redoc/src/options.ts @@ -14,44 +14,29 @@ type LayoutProps = { }; }; -export type Spec = { - specUrl?: string; - content: Record; -}; - export interface PluginOptions { id?: string; - spec?: string; - specUrl?: string; + spec: string; + url?: string; + route?: string; layout?: LayoutProps; debug?: boolean; - addRoute?: boolean; - routePath?: string; - apiDocComponent?: string; } export interface PluginOptionsWithDefault extends PluginOptions { debug: boolean; - addRoute: boolean; - routePath: string; - apiDocComponent: string; } -export const DEFAULT_OPTIONS: PluginOptionsWithDefault = { +export const DEFAULT_OPTIONS: Omit = { layout: {}, debug: false, - addRoute: true, - routePath: '/api/', // URL Route. - apiDocComponent: '@theme/ApiDoc', }; export const PluginOptionSchema = Joi.object({ id: Joi.string(), spec: Joi.string(), - specUrl: Joi.string().uri({ allowRelative: true }), + url: Joi.string().uri({ allowRelative: true }).optional(), layout: Joi.any().default(DEFAULT_OPTIONS.layout), debug: Joi.boolean().default(DEFAULT_OPTIONS.debug), - addRoute: Joi.boolean().default(DEFAULT_OPTIONS.addRoute), - routePath: Joi.string().default(DEFAULT_OPTIONS.routePath), - apiDocComponent: Joi.string().default(DEFAULT_OPTIONS.apiDocComponent), + path: Joi.string().uri({ relativeOnly: true }).optional(), }); diff --git a/packages/docusaurus-theme-redoc/src/types/common.d.ts b/packages/docusaurus-theme-redoc/src/types/common.d.ts index 4f343430..5ab33cf7 100644 --- a/packages/docusaurus-theme-redoc/src/types/common.d.ts +++ b/packages/docusaurus-theme-redoc/src/types/common.d.ts @@ -1,17 +1,11 @@ import type { Props as LayoutProps } from '@theme/Layout'; -import type { RedocRawOptions, ObjectDescriptionProps } from 'redoc'; +import type { ObjectDescriptionProps } from 'redoc'; -export type RecursivePartial = { - [P in keyof T]?: T[P] extends (infer U)[] - ? RecursivePartial[] // eslint-disable-next-line @typescript-eslint/ban-types - : T[P] extends object - ? RecursivePartial - : T[P]; -}; +export type ParsedSpec = Record; export interface SpecProps { - spec: Record; - specUrl?: string; + spec: ParsedSpec; + url?: string; } export type RedocProps = SpecProps; @@ -32,28 +26,7 @@ export type ApiSchemaProps = Omit< example?: boolean; }; -export type Spec = { - specUrl?: string; - content: Record; -}; - export type ApiDocProps = { + specProps: SpecProps; layoutProps?: Omit; - spec: Spec; -}; - -export type RedocThemeOverrides = RecursivePartial< - NonNullable ->; - -export interface ThemeOptions { - primaryColor?: string; - redocTheme?: Partial; - redocOptions?: Partial>; -} - -export type GlobalData = { - redocOptions: NonNullable; - darkTheme: Partial; - lightTheme: Partial; }; diff --git a/packages/redocusaurus/src/index.ts b/packages/redocusaurus/src/index.ts index 0e7a1915..e9e212ef 100644 --- a/packages/redocusaurus/src/index.ts +++ b/packages/redocusaurus/src/index.ts @@ -41,7 +41,6 @@ export default function preset( { id: `plugin-redoc-${index}`, ...pluginOpts, - routePath: pluginOpts.routePath ?? `/api/${index}`, debug, }, ]), From 3211730bbc384a9dfac8ce4f1b11d8c24516c13e Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 20:38:05 +0530 Subject: [PATCH 16/32] =?UTF-8?q?=F0=9F=92=A5=20update=20theme=20options?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/docusaurus-theme-redoc/package.json | 3 +- packages/docusaurus-theme-redoc/src/index.ts | 8 +--- .../docusaurus-theme-redoc/src/redocData.ts | 33 +++++++++------- .../src/types/options.d.ts | 39 +++++++++++++++++++ yarn.lock | 1 + 5 files changed, 64 insertions(+), 20 deletions(-) create mode 100644 packages/docusaurus-theme-redoc/src/types/options.d.ts diff --git a/packages/docusaurus-theme-redoc/package.json b/packages/docusaurus-theme-redoc/package.json index 82f68dbb..2d49300e 100644 --- a/packages/docusaurus-theme-redoc/package.json +++ b/packages/docusaurus-theme-redoc/package.json @@ -47,7 +47,8 @@ "@types/react-router-dom": "^5.3.3", "@types/rtlcss": "^3.1.2", "@types/styled-components": "^5.1.24", - "nodemon": "^2.0.15" + "nodemon": "^2.0.15", + "typescript": "^4.6.2" }, "engines": { "node": ">=14" diff --git a/packages/docusaurus-theme-redoc/src/index.ts b/packages/docusaurus-theme-redoc/src/index.ts index 1e1b6251..4d723477 100644 --- a/packages/docusaurus-theme-redoc/src/index.ts +++ b/packages/docusaurus-theme-redoc/src/index.ts @@ -1,7 +1,7 @@ import path from 'path'; import type { LoadContext, Plugin } from '@docusaurus/types'; import NodePolyfillPlugin from 'node-polyfill-webpack-plugin'; -import { ThemeOptions, GlobalData } from './types/common'; +import { ThemeOptions, GlobalData } from './types/options'; import { getGlobalData } from './redocData'; // eslint-disable-next-line import/no-extraneous-dependencies, import/order @@ -34,11 +34,7 @@ export default function redocTheme( }, async contentLoaded({ actions }) { const { setGlobalData } = actions; - const globalData = getGlobalData( - options.primaryColor, - options.redocTheme, - options.redocOptions, - ); + const globalData = getGlobalData(options); setGlobalData(globalData); }, diff --git a/packages/docusaurus-theme-redoc/src/redocData.ts b/packages/docusaurus-theme-redoc/src/redocData.ts index d95eff36..1159aa60 100644 --- a/packages/docusaurus-theme-redoc/src/redocData.ts +++ b/packages/docusaurus-theme-redoc/src/redocData.ts @@ -1,6 +1,6 @@ import merge from 'lodash/merge'; import { RedocRawOptions } from 'redoc'; -import { GlobalData, RedocThemeOverrides } from './types/common'; +import { GlobalData, RedocThemeOverrides, ThemeOptions } from './types/options'; const defaultOptions: Partial = { scrollYOffset: 'nav.navbar', @@ -15,11 +15,10 @@ const getDefaultTheme = ( customTheme?: RedocThemeOverrides, ): RedocThemeOverrides => { return merge( - {}, { colors: { primary: { - main: primaryColor || '#25c2a0', + main: primaryColor || 'var(--ifm-color-primary)', }, }, }, @@ -44,6 +43,11 @@ const DOCUSAURUS = { * Theme override that is independant of Light/Black themes */ const COMMON_THEME: RedocThemeOverrides = { + colors: { + primary: { + main: 'var(--ifm-color-primary)', + }, + }, typography: { fontFamily: 'var(--ifm-font-family-base)', fontSize: 'var(--ifm-font-size-base)', @@ -133,21 +137,24 @@ export function getRedocThemes(customTheme: RedocThemeOverrides): { }; } -export function getGlobalData( - primaryColor?: string, - customTheme?: RedocThemeOverrides, - redocOptions?: Partial, -): GlobalData { - const { lightTheme, darkTheme } = getRedocThemes( - getDefaultTheme(primaryColor, customTheme), - ); +export function getGlobalData({ + primaryColor, + theme: customTheme, + options, +}: ThemeOptions): GlobalData { + const overrides = + primaryColor || customTheme + ? getDefaultTheme(primaryColor, customTheme) + : {}; + + const { lightTheme, darkTheme } = getRedocThemes(overrides); return { lightTheme, darkTheme, - redocOptions: { + options: { ...defaultOptions, - ...redocOptions, + ...options, }, }; } diff --git a/packages/docusaurus-theme-redoc/src/types/options.d.ts b/packages/docusaurus-theme-redoc/src/types/options.d.ts new file mode 100644 index 00000000..ea817be2 --- /dev/null +++ b/packages/docusaurus-theme-redoc/src/types/options.d.ts @@ -0,0 +1,39 @@ +import type { RedocRawOptions } from 'redoc'; + +export type RecursivePartial = { + [P in keyof T]?: T[P] extends (infer U)[] + ? RecursivePartial[] // eslint-disable-next-line @typescript-eslint/ban-types + : T[P] extends object + ? RecursivePartial + : T[P]; +}; + +export type RedocThemeOverrides = RecursivePartial< + NonNullable +>; + +export interface ThemeOptions { + /** + * Primary Color to pass to Redoc Theme, + * ideally this should be all the customization you need + */ + primaryColor?: string; + /** + * Options to pass to redoc + * @see https://github.com/redocly/redoc#redoc-options-object + */ + options?: Partial>; + /** + * Options to pass to override RedocThemeObject if you + * want to customize the theme yourself. + * **NOTE:** This will overwrite the dark/light mode fixes added in `redocusaurus` + * @see https://github.com/Redocly/redoc#redoc-theme-object + */ + theme?: Partial; +} + +export type GlobalData = { + options: NonNullable; + darkTheme: Partial; + lightTheme: Partial; +}; diff --git a/yarn.lock b/yarn.lock index c5bdd5db..fa68b3d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5985,6 +5985,7 @@ __metadata: redoc: ^2.0.0-rc.64 styled-components: ^5.3.3 to-arraybuffer: ^1.0.1 + typescript: ^4.6.2 languageName: unknown linkType: soft From 1d74856388cecfc127248cb71a70b6755c2d4706 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 20:45:44 +0530 Subject: [PATCH 17/32] fix plugin validation --- packages/docusaurus-plugin-redoc/src/options.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-plugin-redoc/src/options.ts b/packages/docusaurus-plugin-redoc/src/options.ts index 62864aa4..09f53b43 100644 --- a/packages/docusaurus-plugin-redoc/src/options.ts +++ b/packages/docusaurus-plugin-redoc/src/options.ts @@ -32,11 +32,11 @@ export const DEFAULT_OPTIONS: Omit = { debug: false, }; -export const PluginOptionSchema = Joi.object({ +export const PluginOptionSchema = Joi.object({ id: Joi.string(), spec: Joi.string(), url: Joi.string().uri({ allowRelative: true }).optional(), layout: Joi.any().default(DEFAULT_OPTIONS.layout), debug: Joi.boolean().default(DEFAULT_OPTIONS.debug), - path: Joi.string().uri({ relativeOnly: true }).optional(), + route: Joi.string().uri({ relativeOnly: true }).optional(), }); From 42134975ad2904bae34cecc44726cb481dec27c8 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 20:50:34 +0530 Subject: [PATCH 18/32] color needs to be a hex value --- packages/docusaurus-theme-redoc/src/redocData.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/docusaurus-theme-redoc/src/redocData.ts b/packages/docusaurus-theme-redoc/src/redocData.ts index 1159aa60..9f38aef0 100644 --- a/packages/docusaurus-theme-redoc/src/redocData.ts +++ b/packages/docusaurus-theme-redoc/src/redocData.ts @@ -18,7 +18,7 @@ const getDefaultTheme = ( { colors: { primary: { - main: primaryColor || 'var(--ifm-color-primary)', + main: primaryColor || '#25c2a0', }, }, }, @@ -43,11 +43,6 @@ const DOCUSAURUS = { * Theme override that is independant of Light/Black themes */ const COMMON_THEME: RedocThemeOverrides = { - colors: { - primary: { - main: 'var(--ifm-color-primary)', - }, - }, typography: { fontFamily: 'var(--ifm-font-family-base)', fontSize: 'var(--ifm-font-size-base)', @@ -142,10 +137,7 @@ export function getGlobalData({ theme: customTheme, options, }: ThemeOptions): GlobalData { - const overrides = - primaryColor || customTheme - ? getDefaultTheme(primaryColor, customTheme) - : {}; + const overrides = getDefaultTheme(primaryColor, customTheme); const { lightTheme, darkTheme } = getRedocThemes(overrides); From bb214d64e3826bc6d08a1372ff076408ecd0b77b Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 20:59:10 +0530 Subject: [PATCH 19/32] =?UTF-8?q?=F0=9F=92=A5=20update=20theme=20component?= =?UTF-8?q?s=20to=20match=20new=20plugin=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../docusaurus-theme-redoc/src/hooks/useSpec.ts | 13 +++++++------ .../src/theme/ApiDoc/ApiDoc.tsx | 17 ++++++++++------- .../src/theme/ApiSchema/ApiSchema.tsx | 2 +- .../src/theme/Redoc/Redoc.tsx | 7 +++---- .../src/theme/useApiData.ts | 8 +++++--- .../src/types/common.d.ts | 4 ++-- 6 files changed, 28 insertions(+), 23 deletions(-) diff --git a/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts b/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts index ec52c4e6..04b6463b 100644 --- a/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts +++ b/packages/docusaurus-theme-redoc/src/hooks/useSpec.ts @@ -3,7 +3,8 @@ import useBaseUrl from '@docusaurus/useBaseUrl'; import { usePluginData } from '@docusaurus/useGlobalData'; import { useColorMode } from '@docusaurus/theme-common'; import { AppStore } from 'redoc'; -import { GlobalData, SpecProps } from '../types/common'; +import { SpecProps } from '../types/common'; +import { GlobalData } from '../types/options'; /** * Redocusaurus @@ -11,13 +12,13 @@ import { GlobalData, SpecProps } from '../types/common'; * (c) 2022 Rohit Gohri * Released under the MIT License */ -export function useSpec(spec: SpecProps['spec'], specUrl?: string) { - const url = useBaseUrl(specUrl); +export function useSpec({ spec, url }: SpecProps) { + const fullUrl = useBaseUrl(url); const { isDarkTheme } = useColorMode(); const themeOptions = usePluginData('docusaurus-theme-redoc'); const result = useMemo(() => { - const { lightTheme, darkTheme, redocOptions } = themeOptions; + const { lightTheme, darkTheme, options: redocOptions } = themeOptions; const theme = isDarkTheme ? darkTheme : lightTheme; const options = { @@ -25,13 +26,13 @@ export function useSpec(spec: SpecProps['spec'], specUrl?: string) { theme, }; // eslint-disable-next-line @typescript-eslint/no-explicit-any - const store = new AppStore(spec as any, url, options); + const store = new AppStore(spec as any, fullUrl, options); return { store, options, }; - }, [spec, url, themeOptions, isDarkTheme]); + }, [spec, fullUrl, themeOptions, isDarkTheme]); return result; } diff --git a/packages/docusaurus-theme-redoc/src/theme/ApiDoc/ApiDoc.tsx b/packages/docusaurus-theme-redoc/src/theme/ApiDoc/ApiDoc.tsx index 501c06ca..88ee15e4 100644 --- a/packages/docusaurus-theme-redoc/src/theme/ApiDoc/ApiDoc.tsx +++ b/packages/docusaurus-theme-redoc/src/theme/ApiDoc/ApiDoc.tsx @@ -3,15 +3,18 @@ import Layout from '@theme/Layout'; import Redoc from '@theme/Redoc'; import { ApiDocProps as Props } from '../../types/common'; -function ApiDoc({ layoutProps, spec }: Props): JSX.Element { - const { - title = 'API Docs', - description = 'Open API Reference Docs for the API', - } = layoutProps || {}; +function ApiDoc({ layoutProps, specProps }: Props): JSX.Element { + const defaultTitle = specProps.spec?.info?.title || 'API Docs'; + const defaultDescription = + specProps.spec?.info?.description || 'Open API Reference Docs for the API'; return ( - - + + ); } diff --git a/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx b/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx index a8a247a7..41cd3b20 100644 --- a/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx +++ b/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx @@ -15,7 +15,7 @@ const ApiSchema: React.FC = ({ ...rest }: Props): JSX.Element => { const apiData = useApiData(id); - const { store } = useSpec(apiData.content, apiData.specUrl); + const { store } = useSpec(apiData); return ( diff --git a/packages/docusaurus-theme-redoc/src/theme/Redoc/Redoc.tsx b/packages/docusaurus-theme-redoc/src/theme/Redoc/Redoc.tsx index 2b4f4938..90542625 100644 --- a/packages/docusaurus-theme-redoc/src/theme/Redoc/Redoc.tsx +++ b/packages/docusaurus-theme-redoc/src/theme/Redoc/Redoc.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Redoc as RedocComponent } from 'redoc'; -import { RedocProps as Props } from '../../types/common'; +import { SpecProps } from '../../types/common'; import { useSpec } from '../../hooks/useSpec'; import './styles.css'; @@ -10,9 +10,8 @@ import './styles.css'; * (c) 2022 Rohit Gohri * Released under the MIT License */ -function Redoc(props: Props): JSX.Element { - const { spec, specUrl } = props; - const { store } = useSpec(spec, specUrl); +function Redoc(props: SpecProps): JSX.Element { + const { store } = useSpec(props); return (
diff --git a/packages/docusaurus-theme-redoc/src/theme/useApiData.ts b/packages/docusaurus-theme-redoc/src/theme/useApiData.ts index 144f6f2f..ca23a94a 100644 --- a/packages/docusaurus-theme-redoc/src/theme/useApiData.ts +++ b/packages/docusaurus-theme-redoc/src/theme/useApiData.ts @@ -1,13 +1,15 @@ import { useAllPluginInstancesData } from '@docusaurus/useGlobalData'; -import { Spec } from '../types/common'; +import { SpecProps } from '../types/common'; /** * * @param id ID of plugin data * @returns Spec Data of ID or first one if ID is not provided */ -export function useApiData(id?: string) { - const allData = useAllPluginInstancesData('docusaurus-plugin-redoc'); +export function useApiData(id?: string): SpecProps { + const allData = useAllPluginInstancesData( + 'docusaurus-plugin-redoc', + ); const apiData = allData[id as string] || Object.values(allData)[0]; return apiData; diff --git a/packages/docusaurus-theme-redoc/src/types/common.d.ts b/packages/docusaurus-theme-redoc/src/types/common.d.ts index 5ab33cf7..7b9c18ab 100644 --- a/packages/docusaurus-theme-redoc/src/types/common.d.ts +++ b/packages/docusaurus-theme-redoc/src/types/common.d.ts @@ -1,7 +1,7 @@ import type { Props as LayoutProps } from '@theme/Layout'; -import type { ObjectDescriptionProps } from 'redoc'; +import type { ObjectDescriptionProps, OpenAPISpec } from 'redoc'; -export type ParsedSpec = Record; +export type ParsedSpec = OpenAPISpec; export interface SpecProps { spec: ParsedSpec; From 3151f544766d67e5c44aca3eb906ea5b44756fd2 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 21:00:43 +0530 Subject: [PATCH 20/32] rename hook --- .../src/theme/ApiSchema/ApiSchema.tsx | 6 +++--- .../src/theme/{useApiData.ts => useSpecData.ts} | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) rename packages/docusaurus-theme-redoc/src/theme/{useApiData.ts => useSpecData.ts} (83%) diff --git a/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx b/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx index 41cd3b20..aff220b2 100644 --- a/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx +++ b/packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx @@ -3,7 +3,7 @@ import clsx from 'clsx'; import { ThemeProvider } from 'styled-components'; import { SchemaDefinition } from 'redoc'; import { useSpec } from '../../hooks/useSpec'; -import { useApiData } from '../useApiData'; +import { useSpecData } from '../useSpecData'; import { ApiSchemaProps as Props } from '../../types/common'; import '../Redoc/styles.css'; import './styles.css'; @@ -14,8 +14,8 @@ const ApiSchema: React.FC = ({ pointer, ...rest }: Props): JSX.Element => { - const apiData = useApiData(id); - const { store } = useSpec(apiData); + const specProps = useSpecData(id); + const { store } = useSpec(specProps); return ( diff --git a/packages/docusaurus-theme-redoc/src/theme/useApiData.ts b/packages/docusaurus-theme-redoc/src/theme/useSpecData.ts similarity index 83% rename from packages/docusaurus-theme-redoc/src/theme/useApiData.ts rename to packages/docusaurus-theme-redoc/src/theme/useSpecData.ts index ca23a94a..ae8d800e 100644 --- a/packages/docusaurus-theme-redoc/src/theme/useApiData.ts +++ b/packages/docusaurus-theme-redoc/src/theme/useSpecData.ts @@ -6,7 +6,7 @@ import { SpecProps } from '../types/common'; * @param id ID of plugin data * @returns Spec Data of ID or first one if ID is not provided */ -export function useApiData(id?: string): SpecProps { +export function useSpecData(id?: string): SpecProps { const allData = useAllPluginInstancesData( 'docusaurus-plugin-redoc', ); @@ -15,4 +15,4 @@ export function useApiData(id?: string): SpecProps { return apiData; } -export default useApiData; +export default useSpecData; From 162aefab4cbe5dcce5e65cfd7d47a323272c60c8 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 21:26:27 +0530 Subject: [PATCH 21/32] fix type error --- packages/docusaurus-plugin-redoc/src/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/docusaurus-plugin-redoc/src/index.ts b/packages/docusaurus-plugin-redoc/src/index.ts index 2538f0c0..a3df2af8 100644 --- a/packages/docusaurus-plugin-redoc/src/index.ts +++ b/packages/docusaurus-plugin-redoc/src/index.ts @@ -70,7 +70,8 @@ export default function redocPlugin( const data: SpecProps = { url, - spec: content, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + spec: content as any, }; setGlobalData(data); @@ -110,10 +111,9 @@ export default function redocPlugin( export function validateOptions({ options, -}: OptionValidationContext): Promise { - const { value, error } = PluginOptionSchema.validate(options); +}: OptionValidationContext): void { + const { error } = PluginOptionSchema.validate(options); if (error) { throw error; } - return value; } From e697ed6d119047627cfad423a2addc4f78f483a4 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 21:27:30 +0530 Subject: [PATCH 22/32] custom simpler merge fn --- packages/docusaurus-theme-redoc/src/merge.ts | 43 +++++++++++++++++++ .../docusaurus-theme-redoc/src/redocData.ts | 2 +- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 packages/docusaurus-theme-redoc/src/merge.ts diff --git a/packages/docusaurus-theme-redoc/src/merge.ts b/packages/docusaurus-theme-redoc/src/merge.ts new file mode 100644 index 00000000..5799ecc3 --- /dev/null +++ b/packages/docusaurus-theme-redoc/src/merge.ts @@ -0,0 +1,43 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import isObject from 'lodash/isObject'; + +/** + * Simple merge that only merges objects recursively, overwriting rest (arrays, getters, primitives) + */ +function mergeTwo(root: any, overrides: any) { + if (!overrides) return root; + + Object.keys(overrides).forEach((key) => { + const objVal: any = Object.getOwnPropertyDescriptor(root, key); + const srcVal: any = Object.getOwnPropertyDescriptor(overrides, key); + + if ( + objVal && + !objVal.get && + !srcVal.get && + isObject(srcVal.value) && + isObject(objVal.value) + ) { + mergeTwo(root[key], overrides[key]); + return; + } + + Object.defineProperty(root, key, srcVal); + }); + + return root; +} + +/** + * Merge 'n' objects + */ +export function merge(...args: [root: any, first: any, ...rest: any[]]) { + const [root, first, ...rest] = args; + + let merged = mergeTwo(root, first); + rest.forEach((override) => { + merged = mergeTwo(merged, override); + }); + + return merged; +} diff --git a/packages/docusaurus-theme-redoc/src/redocData.ts b/packages/docusaurus-theme-redoc/src/redocData.ts index 9f38aef0..ca938eab 100644 --- a/packages/docusaurus-theme-redoc/src/redocData.ts +++ b/packages/docusaurus-theme-redoc/src/redocData.ts @@ -1,5 +1,5 @@ -import merge from 'lodash/merge'; import { RedocRawOptions } from 'redoc'; +import { merge } from './merge'; import { GlobalData, RedocThemeOverrides, ThemeOptions } from './types/options'; const defaultOptions: Partial = { From e45d3a085693b5952f83c431b35c1258ddc5f3c4 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 21:27:39 +0530 Subject: [PATCH 23/32] update examples --- website/docusaurus.config.js | 46 +++++++++++-------- .../pages/examples/custom-layout/index.jsx | 11 +++-- .../src/pages/examples/custom-page/index.jsx | 10 ++-- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 4c5ded71..be66c225 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -1,14 +1,3 @@ -let version = "v0"; -try { - version = require('./version.json'); -} -catch(err){ -} - -if (process.env.VERCEL_URL) { - process.env.DEPLOY_PRIME_URL = `https://${process.env.VERCEL_URL}`; -} - /** * @type {import('redocusaurus').PresetEntry} */ @@ -22,22 +11,28 @@ const redocusaurus = [ // Local File spec: 'openapi.yaml', /** - * This becomes the Download URL in this case, while docs are generated from `spec` file + * Download URL while docs are generated from `spec` file */ - specUrl: `/openapi-page.yaml`, - routePath: '/examples/using-spec-yaml/', + url: `/openapi-page.yaml`, + route: '/examples/using-spec-yaml/', }, { id: 'using-spec-url', // Remote File - specUrl: 'https://redocly.github.io/redoc/openapi.yaml', - routePath: '/examples/using-spec-url/', + spec: 'https://redocly.github.io/redoc/openapi.yaml', + route: '/examples/using-spec-url/', + }, + { + id: 'using-custom-page', + spec: 'openapi.yaml', + url: `/openapi-page.yaml`, + // NOTE: no `route` passed, instead data used in custom React Component ('custom-page/index.jsx') }, { id: 'using-custom-layout', spec: 'openapi.yaml', - specUrl: `/openapi-page.yaml`, - // NOTE: no `routePath` passed, instead data used in custom React Component ('custom-layout/index.jsx') + url: `/openapi-page.yaml`, + // NOTE: no `route` passed, instead data used in custom React Component ('custom-layout/index.jsx') }, ], theme: { @@ -49,16 +44,27 @@ const redocusaurus = [ * Options to pass to redoc * @see https://github.com/redocly/redoc#redoc-options-object */ - redocOptions: { disableSearch: true }, + options: { disableSearch: true }, /** * Options to pass to override RedocThemeObject * @see https://github.com/Redocly/redoc#redoc-theme-object */ - redocTheme: {}, + theme: {}, }, }, ]; +let version = "v0"; +try { + version = require('./version.json'); +} +catch(err){ +} + +if (process.env.VERCEL_URL) { + process.env.DEPLOY_PRIME_URL = `https://${process.env.VERCEL_URL}`; +} + /** * @type {Partial} */ diff --git a/website/src/pages/examples/custom-layout/index.jsx b/website/src/pages/examples/custom-layout/index.jsx index 0b3993fe..8e019132 100644 --- a/website/src/pages/examples/custom-layout/index.jsx +++ b/website/src/pages/examples/custom-layout/index.jsx @@ -1,13 +1,16 @@ import React from 'react'; import Layout from '@theme/Layout'; import Redoc from '@theme/Redoc'; -import useApiData from '@theme/useApiData'; +import useSpecData from '@theme/useSpecData'; function CustomPage() { - const specData = useApiData('using-custom-layout'); + const specData = useSpecData('using-custom-layout'); return ( - - + + ); } diff --git a/website/src/pages/examples/custom-page/index.jsx b/website/src/pages/examples/custom-page/index.jsx index eaa4cb86..b6633b8c 100644 --- a/website/src/pages/examples/custom-page/index.jsx +++ b/website/src/pages/examples/custom-page/index.jsx @@ -1,17 +1,17 @@ import React from 'react'; import ApiDoc from '@theme/ApiDoc'; -import useApiData from '@theme/useApiData'; +import useSpecData from '@theme/useSpecData'; function CustomPage() { - const specData = useApiData('using-custom-layout'); + const specData = useSpecData('using-custom-page'); return ( ); } From 9e334bebad7825f4689b162d12314b1b32ab7d07 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 21:32:23 +0530 Subject: [PATCH 24/32] set url automatically --- packages/docusaurus-plugin-redoc/src/index.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-plugin-redoc/src/index.ts b/packages/docusaurus-plugin-redoc/src/index.ts index a3df2af8..9e91ad67 100644 --- a/packages/docusaurus-plugin-redoc/src/index.ts +++ b/packages/docusaurus-plugin-redoc/src/index.ts @@ -25,7 +25,8 @@ export default function redocPlugin( ): Plugin> { const { baseUrl } = context.siteConfig; const options: PluginOptionsWithDefault = { ...DEFAULT_OPTIONS, ...opts }; - const { debug, spec, url } = options; + const { debug, spec, url: downloadUrl } = options; + let url = downloadUrl; if (debug) { console.error('[REDOCUSAURUS_PLUGIN] Opts Input:', opts); console.error('[REDOCUSAURUS_PLUGIN] Options:', options); @@ -45,6 +46,9 @@ export default function redocPlugin( if (spec.endsWith('.yaml') || spec.endsWith('.yml')) { parsedSpec = YAML.parse(file); } else parsedSpec = JSON.parse(file); + } else { + // If spec is a remote url then add it as download url + url = spec; } if (debug) { From 310984dd9705045dc8ff089f95a9040b9d62944d Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 21:36:57 +0530 Subject: [PATCH 25/32] update types for modules --- .../src/types/common.d.ts | 3 +- .../src/types/modules.d.ts | 45 ++++++++++--------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/packages/docusaurus-theme-redoc/src/types/common.d.ts b/packages/docusaurus-theme-redoc/src/types/common.d.ts index 7b9c18ab..627c07a3 100644 --- a/packages/docusaurus-theme-redoc/src/types/common.d.ts +++ b/packages/docusaurus-theme-redoc/src/types/common.d.ts @@ -1,5 +1,6 @@ import type { Props as LayoutProps } from '@theme/Layout'; -import type { ObjectDescriptionProps, OpenAPISpec } from 'redoc'; +import type { ObjectDescriptionProps } from 'redoc'; +import type { OpenAPISpec } from 'redoc/typings/types'; export type ParsedSpec = OpenAPISpec; diff --git a/packages/docusaurus-theme-redoc/src/types/modules.d.ts b/packages/docusaurus-theme-redoc/src/types/modules.d.ts index e68e24a9..651d9f6d 100644 --- a/packages/docusaurus-theme-redoc/src/types/modules.d.ts +++ b/packages/docusaurus-theme-redoc/src/types/modules.d.ts @@ -1,35 +1,36 @@ +interface SpecProps { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + spec: import('redoc/typings/types').OpenAPISpec; + url?: string; +} + declare module '@theme/Redoc' { - export type Props = { - spec?: Record; - specUrl?: string; - }; - const Redoc: (props: Props) => JSX.Element; + const Redoc: (props: SpecProps) => JSX.Element; export default Redoc; } declare module '@theme/ApiDoc' { import { Props as LayoutProps } from '@theme/Layout'; - type Spec = { - content: Record; - specUrl?: string; - }; - - export type Props = { + interface ApiDocProps { + /** + * Get this by using `@theme/useSpecData` hook + */ + specProps: SpecProps; + /** + * Title/Description for layout is by default loaded from the API spec + */ layoutProps?: Omit; - spec: Spec; - }; + } - const ApiDoc: (props: Props) => JSX.Element; + const ApiDoc: (props: ApiDocProps) => JSX.Element; export default ApiDoc; } -declare module '@theme/useApiData' { - type Spec = { - content: Record; - specUrl?: string; - }; - - const useApiData: (id?: string) => Spec; - export default useApiData; +declare module '@theme/useSpecData' { + /** + * Load redocusaurus plugin data by ID + */ + const useSpecData: (id?: string) => SpecProps; + export default useSpecData; } From d3d2a8ce6252340c8da14e6ce3ab51f74d3a6cfb Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 21:43:17 +0530 Subject: [PATCH 26/32] use default only if id is not provided --- packages/docusaurus-theme-redoc/src/theme/useSpecData.ts | 2 +- packages/redocusaurus/src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-theme-redoc/src/theme/useSpecData.ts b/packages/docusaurus-theme-redoc/src/theme/useSpecData.ts index ae8d800e..1cb505ce 100644 --- a/packages/docusaurus-theme-redoc/src/theme/useSpecData.ts +++ b/packages/docusaurus-theme-redoc/src/theme/useSpecData.ts @@ -10,7 +10,7 @@ export function useSpecData(id?: string): SpecProps { const allData = useAllPluginInstancesData( 'docusaurus-plugin-redoc', ); - const apiData = allData[id as string] || Object.values(allData)[0]; + const apiData = id ? allData[id as string] : Object.values(allData)[0]; return apiData; } diff --git a/packages/redocusaurus/src/index.ts b/packages/redocusaurus/src/index.ts index e9e212ef..cbecb8e5 100644 --- a/packages/redocusaurus/src/index.ts +++ b/packages/redocusaurus/src/index.ts @@ -39,8 +39,8 @@ export default function preset( ...specsArray.map((pluginOpts, index) => [ require.resolve('docusaurus-plugin-redoc'), { - id: `plugin-redoc-${index}`, ...pluginOpts, + id: pluginOpts.id || `plugin-redoc-${index}`, debug, }, ]), From 8d65f947a33eded75a2e6bd25ebf7853d7f17fbe Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 22:36:03 +0530 Subject: [PATCH 27/32] fix build --- packages/docusaurus-plugin-redoc/src/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-plugin-redoc/src/index.ts b/packages/docusaurus-plugin-redoc/src/index.ts index 9e91ad67..d8955555 100644 --- a/packages/docusaurus-plugin-redoc/src/index.ts +++ b/packages/docusaurus-plugin-redoc/src/index.ts @@ -115,9 +115,10 @@ export default function redocPlugin( export function validateOptions({ options, -}: OptionValidationContext): void { - const { error } = PluginOptionSchema.validate(options); +}: OptionValidationContext): PluginOptions { + const { value, error } = PluginOptionSchema.validate(options); if (error) { throw error; } + return value!; } From ff71868720af130e04e4bd86f5d426d97fbc1b14 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 22:52:37 +0530 Subject: [PATCH 28/32] fix types for ServerStyle --- packages/docusaurus-theme-redoc/src/types/modules.d.ts | 8 ++++++++ website/src/theme/Root/index.tsx | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-theme-redoc/src/types/modules.d.ts b/packages/docusaurus-theme-redoc/src/types/modules.d.ts index 651d9f6d..116f9108 100644 --- a/packages/docusaurus-theme-redoc/src/types/modules.d.ts +++ b/packages/docusaurus-theme-redoc/src/types/modules.d.ts @@ -4,6 +4,14 @@ interface SpecProps { url?: string; } +declare module '@theme/ServerStyle' { + /** + * @see https://github.com/facebook/docusaurus/issues/3236#issuecomment-788953743 + */ + const ServerStyle: (props: { from: React.ReactNode }) => JSX.Element; + export default ServerStyle; +} + declare module '@theme/Redoc' { const Redoc: (props: SpecProps) => JSX.Element; export default Redoc; diff --git a/website/src/theme/Root/index.tsx b/website/src/theme/Root/index.tsx index f51e98b6..53a3e74a 100644 --- a/website/src/theme/Root/index.tsx +++ b/website/src/theme/Root/index.tsx @@ -1,5 +1,4 @@ import React from 'react'; - import ServerStyle from '@theme/ServerStyle'; function Root({ children }: { children: React.Component }): JSX.Element { From faa6eb1200663cfccdb55f92214fe4ee4b29e7bc Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 22:52:49 +0530 Subject: [PATCH 29/32] =?UTF-8?q?=F0=9F=94=A8=20do=20initial=20build=20for?= =?UTF-8?q?=20dev=20cmd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 213a2109..315d5861 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "build:packages": "yarn workspaces foreach --exclude redocusaurus-website --exclude redocusaurus-monorepo -tpv run build", "build:website": "yarn workspace redocusaurus exec 'echo \\\"$npm_package_version\\\" > $PROJECT_CWD/website/version.json' && yarn workspace redocusaurus-website run build", "clean": "yarn workspaces foreach -Atv exec \"rm -rf dist* .tsbuild*.info\"", - "dev": "concurrently 'yarn dev:packages' 'yarn dev:website'", + "dev": "yarn build:packages && yarn workspaces foreach --exclude redocusaurus-monorepo -piv run dev", "dev:packages": "yarn workspaces foreach --exclude redocusaurus-website --exclude redocusaurus-monorepo -piv run dev", "dev:website": "yarn workspace redocusaurus-website run dev", "lint": "eslint . --ext .js,.jsx,.ts,.tsx", From 117563e0b5177819a206c7609f25b68260050308 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 23:04:48 +0530 Subject: [PATCH 30/32] docs(changeset): Simplify plugin/theme options --- .changeset/sixty-cougars-ring.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/sixty-cougars-ring.md diff --git a/.changeset/sixty-cougars-ring.md b/.changeset/sixty-cougars-ring.md new file mode 100644 index 00000000..6f3b377b --- /dev/null +++ b/.changeset/sixty-cougars-ring.md @@ -0,0 +1,7 @@ +--- +'docusaurus-plugin-redoc': major +'docusaurus-theme-redoc': major +'redocusaurus': major +--- + +Simplify plugin/theme options From 8c26b35d822d17e279aa12410bffbe5a2ac330aa Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 23:05:29 +0530 Subject: [PATCH 31/32] docs(changeset): Add new `useSpecData` hook for programmatic use of plugin data --- .changeset/proud-lizards-itch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/proud-lizards-itch.md diff --git a/.changeset/proud-lizards-itch.md b/.changeset/proud-lizards-itch.md new file mode 100644 index 00000000..4b8269d4 --- /dev/null +++ b/.changeset/proud-lizards-itch.md @@ -0,0 +1,5 @@ +--- +'docusaurus-theme-redoc': minor +--- + +Add new `useSpecData` hook for programmatic use of plugin data From 25fada00ec31a22723190affb324c754f41e3ad0 Mon Sep 17 00:00:00 2001 From: Rohit Gohri Date: Sat, 12 Mar 2022 23:06:19 +0530 Subject: [PATCH 32/32] docs(changeset): Change default redoc options, download button not hidden by default --- .changeset/plenty-months-double.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/plenty-months-double.md diff --git a/.changeset/plenty-months-double.md b/.changeset/plenty-months-double.md new file mode 100644 index 00000000..7a689db5 --- /dev/null +++ b/.changeset/plenty-months-double.md @@ -0,0 +1,5 @@ +--- +'docusaurus-theme-redoc': major +--- + +Change default redoc options, download button not hidden by default