Преглед изворни кода

Merge pull request #7484 from weseek/fix/code-block-code-highlight

fix: CodeBlock string is be `[object Object]` if searched
Yuki Takei пре 3 година
родитељ
комит
0e2536247e
1 измењених фајлова са 57 додато и 8 уклоњено
  1. 57 8
      packages/app/src/components/ReactMarkdownComponents/CodeBlock.tsx

+ 57 - 8
packages/app/src/components/ReactMarkdownComponents/CodeBlock.tsx

@@ -1,3 +1,5 @@
+import { ReactNode } from 'react';
+
 import type { CodeComponent } from 'react-markdown/lib/ast-to-react';
 import type { CodeComponent } from 'react-markdown/lib/ast-to-react';
 import { PrismAsyncLight } from 'react-syntax-highlighter';
 import { PrismAsyncLight } from 'react-syntax-highlighter';
 import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
 import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
@@ -5,6 +7,60 @@ import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
 import styles from './CodeBlock.module.scss';
 import styles from './CodeBlock.module.scss';
 
 
 
 
+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 }) => {
 export const CodeBlock: CodeComponent = ({ inline, className, children }) => {
 
 
   if (inline) {
   if (inline) {
@@ -22,14 +78,7 @@ export const CodeBlock: CodeComponent = ({ inline, className, children }) => {
       {name != null && (
       {name != null && (
         <cite className={`code-highlighted-title ${styles['code-highlighted-title']}`}>{name}</cite>
         <cite className={`code-highlighted-title ${styles['code-highlighted-title']}`}>{name}</cite>
       )}
       )}
-      <PrismAsyncLight
-        className="code-highlighted"
-        PreTag="div"
-        style={oneDark}
-        language={lang}
-      >
-        {String(children).replace(/\n$/, '')}
-      </PrismAsyncLight>
+      <CodeBlockSubstance lang={lang}>{children}</CodeBlockSubstance>
     </>
     </>
   );
   );
 };
 };