Resolve json code block freezing issue

This commit is contained in:
yangdx
2025-05-07 04:35:53 +08:00
parent 2485bfe53c
commit 1509e3985e

View File

@@ -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}