Skip to content

Commit

Permalink
Merge pull request #339 from serut/feature/various-improvements
Browse files Browse the repository at this point in the history
Improve types, doc, allow spec on ApiSchema, fix showExample
  • Loading branch information
rohit-gohri authored Mar 24, 2024
2 parents adb9da8 + 438de62 commit 162cdc6
Show file tree
Hide file tree
Showing 25 changed files with 2,146 additions and 236 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,8 @@
"printWidth": 80,
"tabWidth": 2
},
"packageManager": "[email protected]"
"packageManager": "[email protected]",
"volta": {
"node": "18.12.0"
}
}
18 changes: 11 additions & 7 deletions packages/docusaurus-plugin-redoc/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
PluginDirectUsageOptions,
DEFAULT_OPTIONS,
} from './options';
import type { SpecProps, ApiDocProps } from './types/common';
import type { SpecDataResult, ApiDocProps } from './types/common';
import { loadSpecWithConfig } from './loadSpec';
import { loadRedoclyConfig } from './loadRedoclyConfig';

Expand All @@ -33,6 +33,10 @@ const version = require('../package.json').version;

export { PluginOptions, PluginDirectUsageOptions, loadRedoclyConfig };

function getIsExternalUrl(url = '') {
return ['http://', 'https://'].some((protocol) => url.startsWith(protocol));
}

export default function redocPlugin(
context: LoadContext,
opts: PluginOptions,
Expand All @@ -45,12 +49,13 @@ export default function redocPlugin(
const { debug, spec, url: downloadUrl, config, themeId } = options;

let url = downloadUrl;
const isSpecFile = fs.existsSync(spec);
const isExternalUrl = getIsExternalUrl(url);

const fileName = path.join(
'redocusaurus',
`${options.id || 'api-spec'}.yaml`,
);
let filesToWatch: string[] = isSpecFile ? [path.resolve(spec)] : [];
let filesToWatch: string[] = !isExternalUrl ? [path.resolve(spec)] : [];

if (debug) {
console.error('[REDOCUSAURUS_PLUGIN] Opts Input:', opts);
Expand All @@ -67,7 +72,7 @@ export default function redocPlugin(

let bundledSpec: Document, problems: NormalizedProblem[];

if (!isSpecFile) {
if (isExternalUrl) {
// If spec is a remote url then add it as download url also as a default
url = url || spec;
if (debug) {
Expand Down Expand Up @@ -123,10 +128,9 @@ export default function redocPlugin(
throw new Error(`[Redocusaurus] Spec could not be parsed: ${spec}`);
}

const data: SpecProps = {
const data: SpecDataResult = {
url,
themeId,
isSpecFile,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
spec: content.converted as any,
};
Expand Down Expand Up @@ -165,7 +169,7 @@ export default function redocPlugin(
}
},
async postBuild({ content }) {
if (!isSpecFile || downloadUrl) {
if (isExternalUrl || downloadUrl) {
return;
}
// Create a static file from bundled spec
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { useMemo } from 'react';
import Redoc from '@theme/Redoc';
import useSpecData from '@theme/useSpecData';
import { MdxProps as Props } from '../../types/common';
import { MdxProps } from '../../types/common';
import '../ApiSchema/styles.css';

const ApiDocMdx: React.FC<Props> = ({ id }: Props): JSX.Element => {
const ApiDocMdx: React.FC<MdxProps> = ({ id }: MdxProps): JSX.Element => {
const specProps = useSpecData(id);
const optionsOverrides = useMemo(() => {
return {
Expand Down
28 changes: 17 additions & 11 deletions packages/docusaurus-theme-redoc/src/theme/ApiSchema/ApiSchema.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@ import clsx from 'clsx';
import { ThemeProvider } from 'styled-components';
import '../../global';
import { SchemaDefinition } from 'redoc';
import { useSpec } from '../../utils/useSpec';
import { useSpecData } from '../useSpecData';
import { ApiSchemaProps as Props } from '../../types/common';
import useSpec from '@theme/useSpec';
import '../Redoc/styles.css';
import './styles.css';

const ApiSchema: React.FC<Props> = ({
id,
example,
const ApiSchema: React.FC<ApiSchemaProps> = ({
showExample,
pointer,
id,
spec,
optionsOverrides,
...rest
}: Props): JSX.Element => {
const specProps = useSpecData(id);
const { store } = useSpec(specProps);
}: ApiSchemaProps): JSX.Element => {
const { store } = useSpec(
{
id,
spec,
},
optionsOverrides,
);

useEffect(() => {
/**
Expand All @@ -31,13 +36,14 @@ const ApiSchema: React.FC<Props> = ({
className={clsx([
'redocusaurus',
'redocusaurus-schema',
example ? null : 'hide-example',
showExample ? null : 'hide-example',
])}
>
<SchemaDefinition
parser={store.spec.parser}
options={store.options}
schemaRef={pointer}
showExample={showExample}
{...rest}
/>
</div>
Expand All @@ -46,7 +52,7 @@ const ApiSchema: React.FC<Props> = ({
};

ApiSchema.defaultProps = {
example: false,
showExample: false,
};

export default ApiSchema;
23 changes: 10 additions & 13 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/Redoc.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,34 @@
import React from 'react';
import clsx from 'clsx';
import '../../global';
import { RedocStandalone, RedocRawOptions } from 'redoc';
import { SpecProps } from '../../types/common';
import { useSpecOptions } from '../../utils/useSpecOptions';
import { RedocStandalone } from 'redoc';
import useSpecOptions from '@theme/useSpecOptions';
import './styles.css';
import ServerRedoc from './ServerRedoc';

function getIsExternalUrl(url = '') {
return ['http://', 'https://'].some((protocol) => url.startsWith(protocol));
}

/*!
* Redocusaurus
* https://redocusaurus.vercel.app/
* (c) 2024 Rohit Gohri
* Released under the MIT License
*/
function Redoc(
props: Partial<SpecProps> & {
className?: string;
optionsOverrides?: RedocRawOptions;
},
): JSX.Element {
const { className, optionsOverrides, spec, url, themeId, isSpecFile } = props;
function Redoc(props: RedocProps): JSX.Element {
const { className, optionsOverrides, url, themeId } = props;
const { options } = useSpecOptions(themeId, optionsOverrides);
const isDevMode = process.env.NODE_ENV === 'development';

if ((isDevMode && isSpecFile === false) || !spec) {
if (getIsExternalUrl(url)) {
return (
<div className={clsx(['redocusaurus', className])}>
<RedocStandalone specUrl={url} options={options} />
</div>
);
}

return <ServerRedoc {...props} spec={spec} />;
return <ServerRedoc {...props} />;
}

export default Redoc;
25 changes: 12 additions & 13 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/ServerRedoc.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from 'react';
import clsx from 'clsx';
import '../../global';
import { Redoc as RedocComponent, RedocRawOptions } from 'redoc';
import { SpecProps } from '../../types/common';
import { useSpec } from '../../utils/useSpec';
import { Redoc as RedocComponent } from 'redoc';
import useSpec from '@theme/useSpec';
import { ServerStyles } from './Styles';
import './styles.css';

Expand All @@ -13,22 +12,22 @@ import './styles.css';
* (c) 2024 Rohit Gohri
* Released under the MIT License
*/
function ServerRedoc(
props: SpecProps & {
className?: string;
optionsOverrides?: RedocRawOptions;
},
): JSX.Element {
const { className, optionsOverrides, ...specProps } = props;
const { store, darkThemeOptions, lightThemeOptions, hasLogo } = useSpec(
specProps,
function ServerRedoc(props: RedocProps): JSX.Element {
const { className, optionsOverrides, url, id, themeId } = props;
const { store, spec, darkThemeOptions, lightThemeOptions, hasLogo } = useSpec(
{
spec: props.spec,
themeId,
id,
},
optionsOverrides,
);

return (
<>
<ServerStyles
specProps={specProps}
spec={spec}
url={url}
lightThemeOptions={lightThemeOptions}
darkThemeOptions={darkThemeOptions}
/>
Expand Down
23 changes: 14 additions & 9 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/ServerStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import '../../global';
import useBaseUrl from '@docusaurus/useBaseUrl';
import { AppStore, Redoc, RedocRawOptions } from 'redoc';
import type { OpenAPISpec } from 'redoc/typings/types';
// eslint-disable-next-line import/no-extraneous-dependencies
import { renderToString } from 'react-dom/server';
import { ServerStyleSheet } from 'styled-components';
Expand Down Expand Up @@ -53,22 +54,26 @@ const prefixCssSelectors = function (rules: string, className: string) {
const LIGHT_MODE_PREFIX = "html:not([data-theme='dark'])";
const DARK_MODE_PREFIX = "html([data-theme='dark'])";

export type ServerStylesProps = {
spec: OpenAPISpec;
url?: string;
lightThemeOptions: RedocRawOptions;
darkThemeOptions: RedocRawOptions;
};

export function ServerStyles({
specProps,
spec,
url,
lightThemeOptions,
darkThemeOptions,
}: {
specProps: SpecProps;
lightThemeOptions: RedocRawOptions;
darkThemeOptions: RedocRawOptions;
}) {
const fullUrl = useBaseUrl(specProps.url, { absolute: true });
}: ServerStylesProps) {
const fullUrl = useBaseUrl(url, { absolute: true });
const css = {
light: '',
dark: '',
};
const lightSheet = new ServerStyleSheet();
const lightStore = new AppStore(specProps.spec, fullUrl, lightThemeOptions);
const lightStore = new AppStore(spec, fullUrl, lightThemeOptions);
renderToString(
lightSheet.collectStyles(React.createElement(Redoc, { store: lightStore })),
);
Expand All @@ -78,7 +83,7 @@ export function ServerStyles({
css.light = prefixCssSelectors(lightCss, LIGHT_MODE_PREFIX);

const darkSheet = new ServerStyleSheet();
const darkStore = new AppStore(specProps.spec, fullUrl, darkThemeOptions);
const darkStore = new AppStore(spec, fullUrl, darkThemeOptions);
renderToString(
darkSheet.collectStyles(React.createElement(Redoc, { store: darkStore })),
);
Expand Down
8 changes: 2 additions & 6 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/Styles.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import React from 'react';
import '../../global';
import type { RedocRawOptions } from 'redoc';
import type { ServerStylesProps } from './ServerStyles';

/**
* Don't hydrate/replace server styles
* @see https://github.com/facebook/react/issues/10923#issuecomment-338715787
*/
export function ServerStyles(_props: {
specProps: SpecProps;
lightThemeOptions: RedocRawOptions;
darkThemeOptions: RedocRawOptions;
}) {
export function ServerStyles(_props: ServerStylesProps) {
return <div className="redocusaurus-styles"></div>;
}
3 changes: 3 additions & 0 deletions packages/docusaurus-theme-redoc/src/theme/useSpec/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { useSpec } from './useSpec';

export default useSpec;
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { useMemo, useEffect } from 'react';
import useBaseUrl from '@docusaurus/useBaseUrl';
import useIsBrowser from '@docusaurus/useIsBrowser';
import { useColorMode } from '@docusaurus/theme-common';
import '../global';
import useSpecData from '@theme/useSpecData';
import useSpecOptions from '@theme/useSpecOptions';
import '../../global';
import { AppStore, RedocRawOptions } from 'redoc';
import { SpecProps } from '../types/common';
import { useSpecOptions } from './useSpecOptions';

// the current store singleton in the app's instance
let currentStore: AppStore | null = null;
Expand All @@ -17,9 +17,14 @@ let currentStore: AppStore | null = null;
* Released under the MIT License
*/
export function useSpec(
{ spec, url, themeId }: SpecProps,
specInfo: SpecProps,
optionsOverrides?: RedocRawOptions,
) {
): SpecResult {
const { spec, url, themeId } = useSpecData(
specInfo.id,
specInfo.spec,
specInfo.themeId,
);
const specOptions = useSpecOptions(themeId, optionsOverrides);
const fullUrl = useBaseUrl(url, { absolute: true });
const isBrowser = useIsBrowser();
Expand All @@ -36,6 +41,7 @@ export function useSpec(
// @ts-expect-error extra prop
hasLogo: !!spec.info?.['x-logo'],
store: currentStore,
spec,
};
}, [isBrowser, spec, fullUrl, specOptions]);

Expand Down
18 changes: 0 additions & 18 deletions packages/docusaurus-theme-redoc/src/theme/useSpecData.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { useSpecData } from './useSpecData';

export default useSpecData;
Loading

0 comments on commit 162cdc6

Please sign in to comment.