Skip to content

Commit 76ba2ab

Browse files
author
Léo MIEULET
committed
Improve types, doc, allow spec on ApiSchema + various changes
1 parent a0674c9 commit 76ba2ab

25 files changed

Lines changed: 2184 additions & 240 deletions

File tree

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,8 @@
8080
"printWidth": 80,
8181
"tabWidth": 2
8282
},
83-
"packageManager": "yarn@4.0.1"
83+
"packageManager": "yarn@4.0.1",
84+
"volta": {
85+
"node": "18.12.0"
86+
}
8487
}

packages/docusaurus-plugin-redoc/src/index.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
PluginDirectUsageOptions,
2525
DEFAULT_OPTIONS,
2626
} from './options';
27-
import type { SpecProps, ApiDocProps } from './types/common';
27+
import type { SpecDataResult, ApiDocProps } from './types/common';
2828
import { loadSpecWithConfig } from './loadSpec';
2929
import { loadRedoclyConfig } from './loadRedoclyConfig';
3030

@@ -45,12 +45,13 @@ export default function redocPlugin(
4545
const { debug, spec, url: downloadUrl, config, themeId } = options;
4646

4747
let url = downloadUrl;
48-
const isSpecFile = fs.existsSync(spec);
48+
const isExternalUrl = !!url;
49+
4950
const fileName = path.join(
5051
'redocusaurus',
5152
`${options.id || 'api-spec'}.yaml`,
5253
);
53-
let filesToWatch: string[] = isSpecFile ? [path.resolve(spec)] : [];
54+
let filesToWatch: string[] = !isExternalUrl ? [path.resolve(spec)] : [];
5455

5556
if (debug) {
5657
console.error('[REDOCUSAURUS_PLUGIN] Opts Input:', opts);
@@ -67,7 +68,7 @@ export default function redocPlugin(
6768

6869
let bundledSpec: Document, problems: NormalizedProblem[];
6970

70-
if (!isSpecFile) {
71+
if (isExternalUrl) {
7172
// If spec is a remote url then add it as download url also as a default
7273
url = url || spec;
7374
if (debug) {
@@ -123,10 +124,9 @@ export default function redocPlugin(
123124
throw new Error(`[Redocusaurus] Spec could not be parsed: ${spec}`);
124125
}
125126

126-
const data: SpecProps = {
127-
url,
127+
const data: SpecDataResult = {
128+
downloadSpecUrl: url,
128129
themeId,
129-
isSpecFile,
130130
// eslint-disable-next-line @typescript-eslint/no-explicit-any
131131
spec: content.converted as any,
132132
};
@@ -165,7 +165,7 @@ export default function redocPlugin(
165165
}
166166
},
167167
async postBuild({ content }) {
168-
if (!isSpecFile || downloadUrl) {
168+
if (isExternalUrl || downloadUrl) {
169169
return;
170170
}
171171
// Create a static file from bundled spec

packages/docusaurus-theme-redoc/src/theme/ApiDocMdx/ApiDocMdx.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import React, { useMemo } from 'react';
22
import Redoc from '@theme/Redoc';
33
import useSpecData from '@theme/useSpecData';
4-
import type { MdxProps as Props } from '../../types/common';
4+
import type { MdxProps } from '../../types/common';
55
import '../ApiSchema/styles.css';
66

7-
const ApiDocMdx: React.FC<Props> = ({ id }: Props): JSX.Element => {
7+
const ApiDocMdx: React.FC<MdxProps> = ({ id }: MdxProps): JSX.Element => {
88
const specProps = useSpecData(id);
99
const optionsOverrides = useMemo(() => {
1010
return {

packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,27 @@ import clsx from 'clsx';
33
import { ThemeProvider } from 'styled-components';
44
import '../../global';
55
import { SchemaDefinition } from 'redoc';
6-
import { useSpec } from '../../utils/useSpec';
7-
import { useSpecData } from '../useSpecData';
8-
import type { ApiSchemaProps as Props } from '../../types/common';
6+
import useSpec from '@theme/useSpec';
97
import '../Redoc/styles.css';
108
import './styles.css';
119

12-
const ApiSchema: React.FC<Props> = ({
13-
id,
14-
example,
10+
const ApiSchema: React.FC<ApiSchemaProps> = ({
11+
showExample,
1512
pointer,
13+
id,
14+
themeId,
15+
spec,
16+
optionsOverrides,
1617
...rest
17-
}: Props): JSX.Element => {
18-
const specProps = useSpecData(id);
19-
const { store } = useSpec(specProps);
18+
}: ApiSchemaProps): JSX.Element => {
19+
const { store } = useSpec(
20+
{
21+
id,
22+
themeId,
23+
spec,
24+
},
25+
optionsOverrides,
26+
);
2027

2128
useEffect(() => {
2229
/**
@@ -31,13 +38,14 @@ const ApiSchema: React.FC<Props> = ({
3138
className={clsx([
3239
'redocusaurus',
3340
'redocusaurus-schema',
34-
example ? null : 'hide-example',
41+
showExample ? null : 'hide-example',
3542
])}
3643
>
3744
<SchemaDefinition
3845
parser={store.spec.parser}
3946
options={store.options}
4047
schemaRef={pointer}
48+
showExample={showExample}
4149
{...rest}
4250
/>
4351
</div>
@@ -46,7 +54,7 @@ const ApiSchema: React.FC<Props> = ({
4654
};
4755

4856
ApiSchema.defaultProps = {
49-
example: false,
57+
showExample: false,
5058
};
5159

5260
export default ApiSchema;
Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import React from 'react';
22
import clsx from 'clsx';
33
import '../../global';
4-
import { RedocStandalone, RedocRawOptions } from 'redoc';
5-
import type { SpecProps } from '../../types/common';
6-
import { useSpecOptions } from '../../utils/useSpecOptions';
4+
import { RedocStandalone } from 'redoc';
5+
import useSpecOptions from '@theme/useSpecOptions';
76
import './styles.css';
87
import ServerRedoc from './ServerRedoc';
98

@@ -13,25 +12,19 @@ import ServerRedoc from './ServerRedoc';
1312
* (c) 2024 Rohit Gohri
1413
* Released under the MIT License
1514
*/
16-
function Redoc(
17-
props: Partial<SpecProps> & {
18-
className?: string;
19-
optionsOverrides?: RedocRawOptions;
20-
},
21-
): JSX.Element {
22-
const { className, optionsOverrides, spec, url, themeId, isSpecFile } = props;
15+
function Redoc(props: RedocProps): JSX.Element {
16+
const { className, optionsOverrides, url, themeId } = props;
2317
const { options } = useSpecOptions(themeId, optionsOverrides);
24-
const isDevMode = process.env.NODE_ENV === 'development';
2518

26-
if ((isDevMode && isSpecFile === false) || !spec) {
19+
if (url) {
2720
return (
2821
<div className={clsx(['redocusaurus', className])}>
2922
<RedocStandalone specUrl={url} options={options} />
3023
</div>
3124
);
3225
}
3326

34-
return <ServerRedoc {...props} spec={spec} />;
27+
return <ServerRedoc {...props} />;
3528
}
3629

3730
export default Redoc;

packages/docusaurus-theme-redoc/src/theme/Redoc/ServerRedoc.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import React from 'react';
22
import clsx from 'clsx';
33
import '../../global';
4-
import { Redoc as RedocComponent, RedocRawOptions } from 'redoc';
5-
import type { SpecProps } from '../../types/common';
6-
import { useSpec } from '../../utils/useSpec';
4+
import { Redoc as RedocComponent } from 'redoc';
5+
import useSpec from '@theme/useSpec';
76
import { ServerStyles } from './Styles';
87
import './styles.css';
98

@@ -13,22 +12,23 @@ import './styles.css';
1312
* (c) 2024 Rohit Gohri
1413
* Released under the MIT License
1514
*/
16-
function ServerRedoc(
17-
props: SpecProps & {
18-
className?: string;
19-
optionsOverrides?: RedocRawOptions;
20-
},
21-
): JSX.Element {
22-
const { className, optionsOverrides, ...specProps } = props;
23-
const { store, darkThemeOptions, lightThemeOptions, hasLogo } = useSpec(
24-
specProps,
15+
function ServerRedoc(props: RedocProps): JSX.Element {
16+
const { className, optionsOverrides, id, themeId, downloadSpecUrl } = props;
17+
const { store, spec, darkThemeOptions, lightThemeOptions, hasLogo } = useSpec(
18+
{
19+
spec: props.spec,
20+
themeId,
21+
downloadSpecUrl,
22+
id,
23+
},
2524
optionsOverrides,
2625
);
2726

2827
return (
2928
<>
3029
<ServerStyles
31-
specProps={specProps}
30+
spec={spec}
31+
url={downloadSpecUrl}
3232
lightThemeOptions={lightThemeOptions}
3333
darkThemeOptions={darkThemeOptions}
3434
/>

packages/docusaurus-theme-redoc/src/theme/Redoc/ServerStyles.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import '../../global';
33
import useBaseUrl from '@docusaurus/useBaseUrl';
44
import { AppStore, Redoc, RedocRawOptions } from 'redoc';
5+
import type { OpenAPISpec } from 'redoc/typings/types';
56
// eslint-disable-next-line import/no-extraneous-dependencies
67
import { renderToString } from 'react-dom/server';
78
import { ServerStyleSheet } from 'styled-components';
@@ -31,24 +32,28 @@ const renderCss = function (store: AppStore): string {
3132
const LIGHT_MODE_PREFIX = "html:not([data-theme='dark'])";
3233
const DARK_MODE_PREFIX = "html([data-theme='dark'])";
3334

35+
export type ServerStylesProps = {
36+
spec: OpenAPISpec;
37+
url?: string;
38+
lightThemeOptions: RedocRawOptions;
39+
darkThemeOptions: RedocRawOptions;
40+
};
41+
3442
export function ServerStyles({
35-
specProps,
43+
spec,
44+
url,
3645
lightThemeOptions,
3746
darkThemeOptions,
38-
}: {
39-
specProps: SpecProps;
40-
lightThemeOptions: RedocRawOptions;
41-
darkThemeOptions: RedocRawOptions;
42-
}) {
43-
const fullUrl = useBaseUrl(specProps.url, { absolute: true });
47+
}: ServerStylesProps) {
48+
const fullUrl = useBaseUrl(url, { absolute: true });
4449

4550
const lightCss = prefixCssSelectors(
46-
renderCss(new AppStore(specProps.spec, fullUrl, lightThemeOptions)),
51+
renderCss(new AppStore(spec, fullUrl, lightThemeOptions)),
4752
LIGHT_MODE_PREFIX,
4853
);
4954

5055
const darkCss = prefixCssSelectors(
51-
renderCss(new AppStore(specProps.spec, fullUrl, darkThemeOptions)),
56+
renderCss(new AppStore(spec, fullUrl, darkThemeOptions)),
5257
DARK_MODE_PREFIX,
5358
);
5459

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
import React from 'react';
22
import '../../global';
3-
import type { RedocRawOptions } from 'redoc';
3+
import type { ServerStylesProps } from './ServerStyles';
44

55
/**
66
* Don't hydrate/replace server styles
77
* @see https://github.com/facebook/react/issues/10923#issuecomment-338715787
88
*/
9-
export function ServerStyles(_props: {
10-
specProps: SpecProps;
11-
lightThemeOptions: RedocRawOptions;
12-
darkThemeOptions: RedocRawOptions;
13-
}) {
9+
export function ServerStyles(_props: ServerStylesProps) {
1410
return <div className="redocusaurus-styles"></div>;
1511
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { useSpec } from './useSpec';
2+
3+
export default useSpec;

packages/docusaurus-theme-redoc/src/utils/useSpec.ts renamed to packages/docusaurus-theme-redoc/src/theme/useSpec/useSpec.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import { useMemo, useEffect } from 'react';
22
import useBaseUrl from '@docusaurus/useBaseUrl';
33
import useIsBrowser from '@docusaurus/useIsBrowser';
44
import { useColorMode } from '@docusaurus/theme-common';
5-
import '../global';
5+
import useSpecData from '@theme/useSpecData';
6+
import useSpecOptions from '@theme/useSpecOptions';
7+
import '../../global';
68
import { AppStore, RedocRawOptions } from 'redoc';
7-
import type { SpecProps } from '../types/common';
8-
import { useSpecOptions } from './useSpecOptions';
99

1010
// the current store singleton in the app's instance
1111
let currentStore: AppStore | null = null;
@@ -17,27 +17,37 @@ let currentStore: AppStore | null = null;
1717
* Released under the MIT License
1818
*/
1919
export function useSpec(
20-
{ spec, url, themeId }: SpecProps,
20+
specInfo: SpecProps,
2121
optionsOverrides?: RedocRawOptions,
22-
) {
22+
): SpecResult {
23+
const { spec, downloadSpecUrl, themeId } = useSpecData(
24+
specInfo.id,
25+
specInfo.spec,
26+
specInfo.themeId,
27+
);
2328
const specOptions = useSpecOptions(themeId, optionsOverrides);
24-
const fullUrl = useBaseUrl(url, { absolute: true });
29+
// build download URL by using downloadSpecUrl, fallback to useSpecData result
30+
const fullDownloadSpecUrl = useBaseUrl(
31+
specInfo.downloadSpecUrl || downloadSpecUrl,
32+
{ absolute: true },
33+
);
2534
const isBrowser = useIsBrowser();
2635
const isDarkTheme = useColorMode().colorMode === 'dark';
2736

2837
const result = useMemo(() => {
2938
if (currentStore !== null && isBrowser) {
3039
currentStore.dispose();
3140
}
32-
currentStore = new AppStore(spec, fullUrl, specOptions.options);
41+
currentStore = new AppStore(spec, fullDownloadSpecUrl, specOptions.options);
3342

3443
return {
3544
...specOptions,
3645
// @ts-expect-error extra prop
3746
hasLogo: !!spec.info?.['x-logo'],
3847
store: currentStore,
48+
spec,
3949
};
40-
}, [isBrowser, spec, fullUrl, specOptions]);
50+
}, [isBrowser, spec, fullDownloadSpecUrl, specOptions]);
4151

4252
useEffect(() => {
4353
// to ensure that menu is properly loaded when theme gets changed

0 commit comments

Comments
 (0)