import { useState, useEffect } from 'react'
import { Copy, Download } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Skeleton } from '@/components/ui/skeleton'
import { getRawUrl } from '@/lib/gitApi'
import type { GitBlob } from '@/lib/gitApi'
interface FileViewerProps {
blob: GitBlob
ref: string
loading?: boolean
}
// Syntax-highlighted file viewer with line numbers, copy, and download buttons.
// highlight.js is loaded lazily (dynamic import) so it doesn't bloat the initial bundle.
export function FileViewer({ blob, ref, loading }: FileViewerProps) {
const [highlighted, setHighlighted] = useState<{ html: string; lineCount: number } | null>(null)
useEffect(() => {
if (blob.isBinary || !blob.content) {
setHighlighted({ html: '', lineCount: 0 })
return
}
setHighlighted(null)
let cancelled = false
import('highlight.js').then(({ default: hljs }) => {
if (cancelled) return
const ext = blob.path.split('.').pop() ?? ''
const result = hljs.getLanguage(ext)
? hljs.highlight(blob.content, { language: ext })
: hljs.highlightAuto(blob.content)
setHighlighted({
html: result.value,
lineCount: blob.content.split('\n').length,
})
})
return () => { cancelled = true }
}, [blob])
if (loading || highlighted === null) return