diff --git a/web/src/components/CodeBlock.tsx b/web/src/components/CodeBlock.tsx deleted file mode 100644 index 11181949..00000000 --- a/web/src/components/CodeBlock.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import type { Themes } from 'react-shiki/web' -import { useMemo, useState } from 'react' -import { useShikiHighlighter } from 'react-shiki/web' -import { getTelegramWebApp } from '@/hooks/useTelegram' - -const SHIKI_THEMES: Themes = { - light: 'github-light', - dark: 'github-dark', -} - -function normalizeLanguage(language?: string): string { - const raw = language?.trim() - if (!raw) return 'text' - const cleaned = raw.startsWith('language-') ? raw.slice('language-'.length) : raw - const canonical = cleaned.toLowerCase() - if (canonical === 'text' || canonical === 'plaintext' || canonical === 'txt') return 'text' - return cleaned -} - -function safeCopyToClipboard(text: string): Promise { - if (navigator.clipboard?.writeText) { - return navigator.clipboard.writeText(text) - } - return Promise.reject(new Error('Clipboard API not available')) -} - -function CopyIcon(props: { className?: string }) { - return ( - - - - - ) -} - -function CheckIcon(props: { className?: string }) { - return ( - - - - ) -} - -export function CodeBlock(props: { - code: string - language?: string - showCopyButton?: boolean -}) { - const showCopyButton = props.showCopyButton ?? true - const normalizedLanguage = useMemo(() => normalizeLanguage(props.language), [props.language]) - - const [copied, setCopied] = useState(false) - - const highlighted = useShikiHighlighter(props.code, normalizedLanguage, SHIKI_THEMES, { - delay: 75, - outputFormat: 'react', - structure: 'inline', - }) - - const handleCopy = async () => { - try { - await safeCopyToClipboard(props.code) - getTelegramWebApp()?.HapticFeedback?.notificationOccurred('success') - setCopied(true) - setTimeout(() => setCopied(false), 1500) - } catch { - getTelegramWebApp()?.HapticFeedback?.notificationOccurred('error') - } - } - - return ( -
- {showCopyButton ? ( - - ) : null} - -
-                {typeof highlighted === 'string' ? (
-                    
-                ) : (
-                    
-                        {highlighted ?? props.code}
-                    
-                )}
-            
-
- ) -}