Skip to content

Commit

Permalink
Add ApiDocMdx component for nested apis (#180)
Browse files Browse the repository at this point in the history
  • Loading branch information
rohit-gohri committed May 15, 2022
1 parent 2d09476 commit eb69763
Show file tree
Hide file tree
Showing 16 changed files with 1,607 additions and 1,458 deletions.
5 changes: 5 additions & 0 deletions .changeset/thick-cheetahs-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'docusaurus-theme-redoc': minor
---

Add support for multiple apis in MDX
24 changes: 24 additions & 0 deletions packages/docusaurus-theme-redoc/src/theme/ApiDocMdx/ApiDocMdx.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, { useMemo } from 'react';
import Redoc from '../Redoc';
import { useSpecData } from '../useSpecData';
import { MdxProps as Props } from '../../types/common';
import '../ApiSchema/styles.css';

const ApiDocMdx: React.FC<Props> = ({ id }: Props): JSX.Element => {
const specProps = useSpecData(id);
const optionsOverrides = useMemo(() => {
return {
theme: {
// TODO: Investigate what the best breakpoints should be
breakpoints: {
medium: '130rem',
large: '130rem',
},
},
};
}, []);

return <Redoc {...specProps} optionsOverrides={optionsOverrides} />;
};

export default ApiDocMdx;
3 changes: 3 additions & 0 deletions packages/docusaurus-theme-redoc/src/theme/ApiDocMdx/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ApiDocMdx from './ApiDocMdx';

export default ApiDocMdx;
17 changes: 13 additions & 4 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/Redoc.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import clsx from 'clsx';
import '../../global';
import { Redoc as RedocComponent } from 'redoc';
import { Redoc as RedocComponent, RedocRawOptions } from 'redoc';
import { SpecProps } from '../../types/common';
import { useSpec } from '../../utils/useSpec';
import { ServerStyles } from './Styles';
Expand All @@ -13,8 +13,17 @@ import './styles.css';
* (c) 2022 Rohit Gohri
* Released under the MIT License
*/
function Redoc(props: SpecProps & { className?: string }): JSX.Element {
const { store, darkStore, lightStore, hasLogo } = useSpec(props);
function Redoc(
props: SpecProps & {
className?: string;
optionsOverrides?: RedocRawOptions;
},
): JSX.Element {
const { className, optionsOverrides, ...specProps } = props;
const { store, darkStore, lightStore, hasLogo } = useSpec(
specProps,
optionsOverrides,
);

return (
<>
Expand All @@ -23,7 +32,7 @@ function Redoc(props: SpecProps & { className?: string }): JSX.Element {
className={clsx([
'redocusaurus',
hasLogo && 'redocusaurus-has-logo',
props.className,
className,
])}
>
<RedocComponent store={store} />
Expand Down
27 changes: 17 additions & 10 deletions packages/docusaurus-theme-redoc/src/types/common.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,28 @@ export interface SpecProps {

export type RedocProps = SpecProps;

export type ApiSchemaProps = Omit<
ObjectDescriptionProps,
'parser' | 'options' | 'schemaRef'
> & {
export interface MdxProps {
/**
* If you have multiple apis, then add a `id` field in the specs array
* And pass the same here
*/
id?: string;
pointer: ObjectDescriptionProps['schemaRef'];
/**
* Show the example or not
*/
example?: boolean;
};
}

export type ApiSchemaProps = Omit<
ObjectDescriptionProps,
'parser' | 'options' | 'schemaRef'
> &
MdxProps & {
/**
* Show the example or not
*/
example?: boolean;
/**
* Ref to the schema
*/
pointer: ObjectDescriptionProps['schemaRef'];
};

export type ApiDocProps = {
specProps: SpecProps;
Expand Down
35 changes: 35 additions & 0 deletions packages/docusaurus-theme-redoc/src/types/modules.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,41 @@ declare module '@theme/ApiDoc' {
export default ApiDoc;
}

declare module '@theme/ApiDocMdx' {
interface MdxProps {
/**
* If you have multiple apis, then add a `id` field in the specs array
* And pass the same here
*/
id?: string;
}

const ApiDocMdx: (props: MdxProps) => JSX.Element;
export default ApiDocMdx;
}

declare module '@theme/ApiSchema' {
interface ApiSchemaProps {
/**
* If you have multiple apis, then add a `id` field in the specs array
* And pass the same here
*/
id?: string;
/**
* Show the example or not
*/
example?: boolean;

/**
* Ref to the schema
*/
pointer: string;
}

const ApiSchema: (props: ApiSchemaProps) => JSX.Element;
export default ApiSchema;
}

declare module '@theme/useSpecData' {
/**
* Load redocusaurus plugin data by ID
Expand Down
47 changes: 33 additions & 14 deletions packages/docusaurus-theme-redoc/src/utils/useSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import useBaseUrl from '@docusaurus/useBaseUrl';
import useIsBrowser from '@docusaurus/useIsBrowser';
import { usePluginData } from '@docusaurus/useGlobalData';
import { useColorMode } from '@docusaurus/theme-common';
import merge from 'lodash/merge';
import '../global';
import { AppStore, RedocRawOptions } from 'redoc';
import { SpecProps } from '../types/common';
Expand All @@ -14,7 +15,10 @@ import { GlobalData } from '../types/options';
* (c) 2022 Rohit Gohri
* Released under the MIT License
*/
export function useSpec({ spec, url }: SpecProps) {
export function useSpec(
{ spec, url }: SpecProps,
optionsOverrides?: RedocRawOptions,
) {
const fullUrl = useBaseUrl(url, { absolute: true });
const isBrowser = useIsBrowser();
const isDarkTheme = useColorMode().colorMode === 'dark';
Expand All @@ -31,24 +35,39 @@ export function useSpec({ spec, url }: SpecProps) {
: redocOptions.scrollYOffset,
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const lightStore = new AppStore(spec as any, fullUrl, {
...redocOptions,
...commonOptions,
theme: lightTheme,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const darkStore = new AppStore(spec as any, fullUrl, {
...redocOptions,
...commonOptions,
theme: darkTheme,
});
const lightStore = new AppStore(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
spec as any,
fullUrl,
merge(
{
...redocOptions,
...commonOptions,
theme: lightTheme,
},
optionsOverrides,
),
);

const darkStore = new AppStore(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
spec as any,
fullUrl,
merge(
{
...redocOptions,
...commonOptions,
theme: darkTheme,
},
optionsOverrides,
),
);

return {
lightStore,
darkStore,
};
}, [isBrowser, spec, fullUrl, themeOptions]);
}, [isBrowser, spec, fullUrl, themeOptions, optionsOverrides]);

const result = useMemo(() => {
return {
Expand Down
1 change: 1 addition & 0 deletions website/docs/guides/build-time-rendering.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Build Time Rendering
description: Parse the OpenAPI schema at build time and skip the loading screen
sidebar_position: 3
---

:::caution
Expand Down
1 change: 1 addition & 0 deletions website/docs/guides/migrating-to-v1.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: Migrating to V1
sidebar_position: 4
---

## Options Changed
Expand Down
25 changes: 25 additions & 0 deletions website/docs/guides/multiple-apis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: Showing Multiple APIs
sidebar_position: 2
---

## Nested View with MDX

To display multiple API docs with the Docusaurus sidebar for navigation you can use the MDX component `@theme/ApiDocMdx` along with the setting `hide_table_of_contents` for the file. For an example check the "Nested Docs Example" section in the sidebar.

```mdx
---
title: API 1 - Swagger Petstore
hide_table_of_contents: true
---

import ApiDocMdx from '@theme/ApiDocMdx';

<ApiDocMdx id="using-single-yaml" />
```

The output of the above is viewable here: [Nested API 1](/docs/nested/nested-1).

## Full Pages with links in Dropdown

For a simpler solution just add all the routes in a Navbar Dropdown (see [docs](https://docusaurus.io/docs/api/themes/configuration#navbar-dropdown)). This is how the "Examples" of this website is structured.
1 change: 1 addition & 0 deletions website/docs/guides/schema-imports.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: Schema Imports
sidebar_position: 1
---

import ApiSchema from '@theme/ApiSchema';
Expand Down
2 changes: 2 additions & 0 deletions website/docs/nested/_category_.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
label: 'Nested Docs Example'
position: 10
8 changes: 8 additions & 0 deletions website/docs/nested/nested-1.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: API 1 - Swagger Petstore
hide_table_of_contents: true
---

import ApiDocMdx from '@theme/ApiDocMdx';

<ApiDocMdx id="using-single-yaml" />
8 changes: 8 additions & 0 deletions website/docs/nested/nested-2.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: API 2 - Swagger Petstore
hide_table_of_contents: true
---

import ApiDocMdx from '@theme/ApiDocMdx';

<ApiDocMdx id="using-swagger-json" />
1 change: 1 addition & 0 deletions website/snapshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const urls = [
path: '/examples/using-single-yaml/',
},
{ name: 'URL Spec', path: '/examples/using-remote-url/' },
{ name: 'Nested Example', path: '/docs/nested/nested-1' },
{ name: 'Schema Imports', path: '/docs/guides/schema-imports' },
];

Expand Down
Loading

1 comment on commit eb69763

@vercel
Copy link

@vercel vercel bot commented on eb69763 May 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.