From 4e16d0049103a3a232d9444690bdb54feb5490ce Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 15 Apr 2022 10:04:48 +0800 Subject: [PATCH] refactor --- .../src/theme-classic.d.ts | 4 +- .../src/theme/CodeBlock/index.tsx | 70 +++++++++---------- 2 files changed, 34 insertions(+), 40 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index 7d3bda55d6a7..f4cead69c404 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -148,10 +148,10 @@ declare module '@theme/BlogLayout' { } declare module '@theme/CodeBlock' { - import type {ReactElement} from 'react'; + import type {ReactNode} from 'react'; export interface Props { - readonly children: string | ReactElement; + readonly children: ReactNode; readonly className?: string; readonly metastring?: string; readonly title?: string; diff --git a/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx b/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx index 2d699299492e..f77860afdea0 100644 --- a/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx @@ -7,13 +7,12 @@ import React, { isValidElement, - useEffect, - useState, type ComponentProps, - type ReactElement, + type ReactNode, } from 'react'; import clsx from 'clsx'; import Highlight, {defaultProps, type Language} from 'prism-react-renderer'; +import useIsBrowser from '@docusaurus/useIsBrowser'; import { useThemeConfig, parseCodeBlockTitle, @@ -82,51 +81,47 @@ function CodeBlockLine({ ); } -function childrenToString(children: string | ReactElement): string | null { +/** + * Best attempt to make the children a plain string so it is copyable. If there + * are react elements, we will not be able to copy the content, and it will + * return `children` as-is; otherwise, it concatenates the string children + * together. + */ +function maybeStringifyChildren(children: ReactNode): ReactNode { if (React.Children.toArray(children).some((el) => isValidElement(el))) { - return null; + return children; } // The children is now guaranteed to be one/more plain strings return Array.isArray(children) ? children.join('') : (children as string); } -// The Prism theme on SSR is always the default theme but the site theme -// can be in a different mode. React hydration doesn't update DOM styles -// that come from SSR. Hence force a re-render after mounting to apply the -// current relevant styles. There will be a flash seen of the original -// styles seen using this current approach but that's probably ok. Fixing -// the flash will require changing the theming approach and is not worth it -// at this point. -function useCodeBlockKey(): string { - const [mounted, setMounted] = useState(false); - useEffect(() => { - setMounted(true); - }, []); - return String(mounted); -} - -export default function CodeBlock({children, ...props}: Props): JSX.Element { - const key = useCodeBlockKey(); - const childrenString = childrenToString(children); - return childrenString ? ( - - {childrenString} - - ) : ( - - {children} - +export default function CodeBlock({ + children: rawChildren, + ...props +}: Props): JSX.Element { + // The Prism theme on SSR is always the default theme but the site theme can + // be in a different mode. React hydration doesn't update DOM styles that come + // from SSR. Hence force a re-render after mounting to apply the current + // relevant styles. + const isBrowser = useIsBrowser(); + const children = maybeStringifyChildren(rawChildren); + const CodeBlockComp = + typeof children === 'string' ? CodeBlockString : CodeBlockJSX; + return ( + + {children as string} + ); } -function CodeBlockContainer({ - as: Wrapper, +function CodeBlockContainer({ + as: As, ...props -}: {as: As} & ComponentProps) { +}: {as: T} & ComponentProps) { return ( - // @ts-expect-error: TODO bad typing here -