'use client'; import { useState, useMemo } from 'react'; import { Copy, Check } from 'lucide-react'; import { Button } from '@/components/ui/button'; interface CodeBlockProps { code: string; type: 'bash' | 'sql' | 'text'; showLineNumbers?: boolean; } export function CodeBlock({ code, type, showLineNumbers = true }: CodeBlockProps) { console.log('[CodeBlock] Render - code length:', code?.length, 'code preview:', code?.substring(0, 50), 'type:', type); const [copied, setCopied] = useState(false); // Compute highlighted code synchronously const highlighted = useMemo(() => { if (!code) return ''; try { // eslint-disable-next-line @typescript-eslint/no-require-imports const Prism = require('prismjs'); if (type === 'sql') { // eslint-disable-next-line @typescript-eslint/no-require-imports require('prismjs/components/prism-sql'); } else if (type === 'bash') { // eslint-disable-next-line @typescript-eslint/no-require-imports require('prismjs/components/prism-bash'); } const language = type === 'text' ? 'text' : type; const grammar = Prism.languages[language] || Prism.languages.text; return Prism.highlight(code, grammar, language); } catch (e) { console.error('[CodeBlock] Prism error:', e); return code.replace(//g, '>'); } }, [code, type]); console.log('[CodeBlock] highlighted length:', highlighted?.length); const handleCopy = async () => { await navigator.clipboard.writeText(code); setCopied(true); setTimeout(() => setCopied(false), 2000); }; // Split code into lines for line numbers const lines = code ? code.split('\n') : []; const highlightedLines = highlighted ? highlighted.split('\n') : []; return (
{showLineNumbers ? (
{/* Line numbers column */}
{lines.map((_: string, i: number) => (
{i + 1}
))}
{/* Code column */}
{highlightedLines.map((line: string, i: number) => (
))}
) : (
)}