搭建网页版ChatGPT(四)
搭建网页版 ChatGPT(四)
前言
我们继续上一篇的内容,前面我们完成了对话功能以及请求的处理,本小节主要介绍如何渲染 chatGPT 返回的代码,让代码高亮。
还记得前面我们讲过的 mdx 的实时编译吗, 现在我们就要用到了。如果没看过的可以翻翻我前面的几篇文章,讲的很细。
让代码高亮
这里就不重复前面的 mdx 的内容了,使用起来非常简单
const ChatBot = ({ content, date }: ChatBotProps) => {
const [{ Content }, setState] =
useState <
any >
{
Content: undefined,
};
useEffect(() => {
compileAndRun(content, 'md').then(({ content, error }) => {
setState((state: any) => ({
Content: content || state.Content,
}));
});
}, [content]);
return (
<>
<div className='w-full'>
{Content ? <Content components={MDXComponents} /> : null}
</div>
</>
);
};
export default ChatBot;
小彩蛋
下面讲下如何实现代码复制功能,以下是复制按钮组件代码:
export function MDXCopyButton({
onCope,
style = {
position: 'absolute',
top: '10px',
right: '10px',
width: '1.1em',
height: '1.1em',
},
className,
}: {
onCope: (fn: any) => void;
style?: React.CSSProperties;
className?: string;
}) {
const [copied, setCopied] = React.useState(false);
const handleCope = async () => {
onCope(function (code: any) {
if (code) {
setCopied(true);
copyToClipboard(code).then(() => {
setCopied(false);
});
}
});
};
return (
<button
type='button'
title='Copy code'
className={className}
style={style}
onClick={() => handleCope()}
>
<svg
fill='none'
stroke='currentColor'
viewBox='0 0 24 24'
xmlns='http://www.w3.org/2000/svg'
>
{copied ? (
<path
strokeLinecap='round'
strokeLinejoin='round'
strokeWidth={2}
d='M5 13l4 4L19 7'
/>
) : (
<path
strokeLinecap='round'
strokeLinejoin='round'
strokeWidth='1.6px'
d='M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z'
/>
)}
</svg>
</button>
);
}
const copyToClipboard = async (text: string) => {
if (!navigator.clipboard) {
return;
}
await navigator.clipboard.writeText(text);
};
使用组件
export default memo(function CodeBlockWrapper(children): any {
const ref = useRef<HTMLPreElement>(null);
return (
<pre
ref={ref}
className='align-start flex'
>
<MDXCopyButton
onCope={(fn: any) => {
if (ref.current) {
fn(ref.current.innerText);
}
}}
/>
<code>{children}</code>
</pre>
);
});
最后
如果喜欢我的文章,欢迎关注我,同时也欢迎关注我的个人网站,里面有多个我一直迭代的项目,
还有我的 b 站,我会定期在 b 站分享一些你意想不到的知识。