feat: P3a 代码语法高亮 (highlight.js + CodeBlock组件)
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
'use client'
|
||||
|
||||
import { useRef, useState } from 'react'
|
||||
import hljs from 'highlight.js/lib/core'
|
||||
import javascript from 'highlight.js/lib/languages/javascript'
|
||||
import python from 'highlight.js/lib/languages/python'
|
||||
import typescript from 'highlight.js/lib/languages/typescript'
|
||||
import xml from 'highlight.js/lib/languages/xml'
|
||||
import css from 'highlight.js/lib/languages/css'
|
||||
import bash from 'highlight.js/lib/languages/bash'
|
||||
import json from 'highlight.js/lib/languages/json'
|
||||
|
||||
hljs.registerLanguage('javascript', javascript)
|
||||
hljs.registerLanguage('js', javascript)
|
||||
hljs.registerLanguage('python', python)
|
||||
hljs.registerLanguage('py', python)
|
||||
hljs.registerLanguage('typescript', typescript)
|
||||
hljs.registerLanguage('ts', typescript)
|
||||
hljs.registerLanguage('xml', xml)
|
||||
hljs.registerLanguage('html', xml)
|
||||
hljs.registerLanguage('css', css)
|
||||
hljs.registerLanguage('bash', bash)
|
||||
hljs.registerLanguage('sh', bash)
|
||||
hljs.registerLanguage('json', json)
|
||||
|
||||
interface CodeBlockProps {
|
||||
code: string
|
||||
language?: string
|
||||
}
|
||||
|
||||
export function CodeBlock({ code, language }: CodeBlockProps) {
|
||||
const [copied, setCopied] = useState(false)
|
||||
const codeRef = useRef<HTMLElement>(null)
|
||||
|
||||
let highlighted = ''
|
||||
try {
|
||||
if (language && hljs.getLanguage(language)) {
|
||||
highlighted = hljs.highlight(code, { language }).value
|
||||
} else {
|
||||
highlighted = hljs.highlightAuto(code).value
|
||||
}
|
||||
} catch {
|
||||
highlighted = code
|
||||
}
|
||||
|
||||
async function copyCode() {
|
||||
try {
|
||||
await navigator.clipboard.writeText(code)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
} catch {}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative group my-2 rounded-xl overflow-hidden border border-border">
|
||||
<div className="flex items-center justify-between px-4 py-1.5 bg-muted/80 border-b border-border">
|
||||
<span className="text-xs text-muted-foreground">{language || 'code'}</span>
|
||||
<button onClick={copyCode}
|
||||
className="text-xs px-2 py-0.5 rounded text-muted-foreground hover:text-foreground hover:bg-accent transition-colors">
|
||||
{copied ? '已复制' : '复制'}
|
||||
</button>
|
||||
</div>
|
||||
<pre className="overflow-x-auto p-4 text-sm leading-relaxed bg-[#1e1e1e]">
|
||||
<code ref={codeRef} className={`language-${language || ''}`} dangerouslySetInnerHTML={{ __html: highlighted }} />
|
||||
</pre>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user