prism-react-renderer是基于prism对于React的封装,解决了prism在更新code的同时破坏了dom结构,从而影响到diff算法的问题。
prism-react-renderer可以使code更新的时候,不会让整个组件的dom更新。
prism-react-renderer本身支持的语言是有限的,如果想要支持更多语言,需要从prism中导入。
在普通的React应用中导入示例如下:
github:github.com/FormidableL…
demo:github.com/FormidableL…
在nextjs中导入的示例如下:
使用next/dynamic进行动态导入。
import dynamic from 'next/dynamic';
import { useDarkMode } from '@/hooks/useDarkMode';
import { Highlight, themes, Prism } from 'prism-react-renderer';
import { useEffect, useMemo } from 'react';
import CopyButton from '../ui/CopyButton';
interface CodeEditorProps {
content: string;
language: string;
}
const CodeEditor: React.FC<CodeEditorProps> = ({ content, language }) => {
const { darkMode } = useDarkMode();
const codeTheme = useMemo(() => {
return darkMode ? themes.nightOwl : themes.nightOwlLight;
}, [darkMode]);
useEffect(() => {
// Example of importing a custom language directly from Prism
(typeof global !== 'undefined' ? global : window).Prism = Prism;
// @ts-ignore
language && dynamic(import(`prismjs/components/prism-${language}`), { ssr: false });
}, [language]);
return (
<div className="relative h-full">
<Highlight theme={codeTheme} code={String(content).replace(/\n$/, '')} language={language}>
{({ className, style, tokens, getLineProps, getTokenProps }) => (
<pre className={`${className} p-4 overflow-auto h-full`} style={style}>
{tokens.map((line, i) => (
<div key={i} {...getLineProps({ line })}>
{line.map((token, key) => (
<span key={key} {...getTokenProps({ token })} />
))}
</div>
))}
</pre>
)}
</Highlight>
<CopyButton size="xxs" textToCopy={content} className="absolute right-3 top-2" />
</div>
);
};
export default CodeEditor;