|
|
@@ -1,4 +1,4 @@
|
|
|
-import { useMemo } from 'react';
|
|
|
+import { ReactNode } from 'react';
|
|
|
|
|
|
import type { CodeComponent } from 'react-markdown/lib/ast-to-react';
|
|
|
import { PrismAsyncLight } from 'react-syntax-highlighter';
|
|
|
@@ -6,12 +6,62 @@ import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
|
|
|
|
|
import styles from './CodeBlock.module.scss';
|
|
|
|
|
|
-export const CodeBlock: CodeComponent = ({ inline, className, children }) => {
|
|
|
|
|
|
- const isHighlightedByElasticsearch = useMemo((): boolean => {
|
|
|
- const hasOnlyOneStringChild = children.length === 1 && typeof children[0] === 'string';
|
|
|
- return !hasOnlyOneStringChild;
|
|
|
- }, [children]);
|
|
|
+function extractChildrenToIgnoreReactNode(children: ReactNode): ReactNode {
|
|
|
+
|
|
|
+ if (children == null) {
|
|
|
+ return children;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Single element array
|
|
|
+ if (Array.isArray(children) && children.length === 1) {
|
|
|
+ return extractChildrenToIgnoreReactNode(children[0]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Multiple element array
|
|
|
+ if (Array.isArray(children) && children.length > 1) {
|
|
|
+ return children.map(node => extractChildrenToIgnoreReactNode(node)).join('');
|
|
|
+ }
|
|
|
+
|
|
|
+ // object
|
|
|
+ if (typeof children === 'object') {
|
|
|
+ const grandChildren = (children as any).children ?? (children as any).props.children;
|
|
|
+ return extractChildrenToIgnoreReactNode(grandChildren);
|
|
|
+ }
|
|
|
+
|
|
|
+ return String(children).replace(/\n$/, '');
|
|
|
+}
|
|
|
+
|
|
|
+function CodeBlockSubstance({ lang, children }: { lang: string, children: ReactNode }): JSX.Element {
|
|
|
+ // return alternative element
|
|
|
+ // in order to fix "CodeBlock string is be [object Object] if searched"
|
|
|
+ // see: https://github.com/weseek/growi/pull/7484
|
|
|
+ //
|
|
|
+ // Note: You can also remove this code if the user requests to see the code highlighted in Prism as-is.
|
|
|
+ const isSimpleString = Array.isArray(children) && children.length === 1 && typeof children[0] === 'string';
|
|
|
+ if (!isSimpleString) {
|
|
|
+ return (
|
|
|
+ <div className="code-highlighted" style={oneDark['pre[class*="language-"]']}>
|
|
|
+ <code className={`language-${lang}`} style={oneDark['code[class*="language-"]']}>
|
|
|
+ {children}
|
|
|
+ </code>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <PrismAsyncLight
|
|
|
+ className="code-highlighted"
|
|
|
+ PreTag="div"
|
|
|
+ style={oneDark}
|
|
|
+ language={lang}
|
|
|
+ >
|
|
|
+ {extractChildrenToIgnoreReactNode(children)}
|
|
|
+ </PrismAsyncLight>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+export const CodeBlock: CodeComponent = ({ inline, className, children }) => {
|
|
|
|
|
|
if (inline) {
|
|
|
return <code className={`code-inline ${className ?? ''}`}>{children}</code>;
|
|
|
@@ -28,22 +78,7 @@ export const CodeBlock: CodeComponent = ({ inline, className, children }) => {
|
|
|
{name != null && (
|
|
|
<cite className={`code-highlighted-title ${styles['code-highlighted-title']}`}>{name}</cite>
|
|
|
)}
|
|
|
- {isHighlightedByElasticsearch ? (
|
|
|
- <div className="code-highlighted" style={oneDark['pre[class*="language-"]']}>
|
|
|
- <code className={`language-${lang}`} style={oneDark['code[class*="language-"]']}>
|
|
|
- {children}
|
|
|
- </code>
|
|
|
- </div>
|
|
|
- ) : (
|
|
|
- <PrismAsyncLight
|
|
|
- className="code-highlighted"
|
|
|
- PreTag="div"
|
|
|
- style={oneDark}
|
|
|
- language={lang}
|
|
|
- >
|
|
|
- {String(children).replace(/\n$/, '')}
|
|
|
- </PrismAsyncLight>
|
|
|
- )}
|
|
|
+ <CodeBlockSubstance lang={lang}>{children}</CodeBlockSubstance>
|
|
|
</>
|
|
|
);
|
|
|
};
|