Resolve json code block freezing issue
This commit is contained in:
@@ -116,6 +116,12 @@ const isInlineCode = (node?: Element): boolean => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Check if it is a large JSON
|
||||||
|
const isLargeJson = (language: string | undefined, content: string | undefined): boolean => {
|
||||||
|
if (!content || language !== 'json') return false;
|
||||||
|
return content.length > 5000; // JSON larger than 5KB is considered large JSON
|
||||||
|
};
|
||||||
|
|
||||||
// Memoize the CodeHighlight component
|
// Memoize the CodeHighlight component
|
||||||
const CodeHighlight = memo(({ className, children, node, renderAsDiagram = false, ...props }: CodeHighlightProps) => {
|
const CodeHighlight = memo(({ className, children, node, renderAsDiagram = false, ...props }: CodeHighlightProps) => {
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
@@ -126,6 +132,10 @@ const CodeHighlight = memo(({ className, children, node, renderAsDiagram = false
|
|||||||
const mermaidRef = useRef<HTMLDivElement>(null);
|
const mermaidRef = useRef<HTMLDivElement>(null);
|
||||||
const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null); // Use ReturnType for better typing
|
const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null); // Use ReturnType for better typing
|
||||||
|
|
||||||
|
// Get the content string, check if it is a large JSON
|
||||||
|
const contentStr = String(children || '').replace(/\n$/, '');
|
||||||
|
const isLargeJsonBlock = isLargeJson(language, contentStr);
|
||||||
|
|
||||||
// Handle Mermaid rendering with debounce
|
// Handle Mermaid rendering with debounce
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Effect should run when renderAsDiagram becomes true or hasRendered changes.
|
// Effect should run when renderAsDiagram becomes true or hasRendered changes.
|
||||||
@@ -247,11 +257,19 @@ const CodeHighlight = memo(({ className, children, node, renderAsDiagram = false
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Dependencies: renderAsDiagram ensures effect runs when diagram should be shown.
|
// Dependencies: renderAsDiagram ensures effect runs when diagram should be shown.
|
||||||
// children, language, theme trigger re-render if code/context changes.
|
|
||||||
// Dependencies include all values used inside the effect to satisfy exhaustive-deps.
|
// Dependencies include all values used inside the effect to satisfy exhaustive-deps.
|
||||||
// The !hasRendered check prevents re-execution of render logic after success.
|
// The !hasRendered check prevents re-execution of render logic after success.
|
||||||
}, [renderAsDiagram, hasRendered, language, children, theme]); // Add children and theme back
|
}, [renderAsDiagram, hasRendered, language, children, theme]); // Add children and theme back
|
||||||
|
|
||||||
|
// For large JSON, skip syntax highlighting completely and use a simple pre tag
|
||||||
|
if (isLargeJsonBlock) {
|
||||||
|
return (
|
||||||
|
<pre className="whitespace-pre-wrap break-words bg-muted p-4 rounded-md overflow-x-auto text-sm font-mono">
|
||||||
|
{contentStr}
|
||||||
|
</pre>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Render based on language type
|
// Render based on language type
|
||||||
// If it's a mermaid language block and rendering as diagram is not requested (e.g., incomplete stream), display as plain text
|
// If it's a mermaid language block and rendering as diagram is not requested (e.g., incomplete stream), display as plain text
|
||||||
if (language === 'mermaid' && !renderAsDiagram) {
|
if (language === 'mermaid' && !renderAsDiagram) {
|
||||||
@@ -262,7 +280,7 @@ const CodeHighlight = memo(({ className, children, node, renderAsDiagram = false
|
|||||||
language="text" // Use text as language to avoid syntax highlighting errors
|
language="text" // Use text as language to avoid syntax highlighting errors
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{String(children).replace(/\n$/, '')}
|
{contentStr}
|
||||||
</SyntaxHighlighter>
|
</SyntaxHighlighter>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -273,6 +291,7 @@ const CodeHighlight = memo(({ className, children, node, renderAsDiagram = false
|
|||||||
return <div className="mermaid-diagram-container my-4 overflow-x-auto" ref={mermaidRef}></div>;
|
return <div className="mermaid-diagram-container my-4 overflow-x-auto" ref={mermaidRef}></div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Handle non-Mermaid code blocks
|
// Handle non-Mermaid code blocks
|
||||||
return !inline ? (
|
return !inline ? (
|
||||||
<SyntaxHighlighter
|
<SyntaxHighlighter
|
||||||
@@ -281,12 +300,12 @@ const CodeHighlight = memo(({ className, children, node, renderAsDiagram = false
|
|||||||
language={language}
|
language={language}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{String(children).replace(/\n$/, '')}
|
{contentStr}
|
||||||
</SyntaxHighlighter>
|
</SyntaxHighlighter>
|
||||||
) : (
|
) : (
|
||||||
// Handle inline code
|
// Handle inline code
|
||||||
<code
|
<code
|
||||||
className={cn(className, 'mx-1 rounded-sm bg-muted px-1 py-0.5 font-mono text-sm')} // 添加 font-mono 确保使用等宽字体
|
className={cn(className, 'mx-1 rounded-sm bg-muted px-1 py-0.5 font-mono text-sm')} // Add font-mono to ensure monospaced font is used
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
Reference in New Issue
Block a user