Lazy Code
Using Prism
/src/**/code/import-prismjs.ts
import * as Prism from 'prismjs';
import 'prismjs/themes/prism.min.css/';
// Import all supported languages
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-markdown';
export default Prism;
/src/**/code/LazyCode.tsx
import React, { useState } from 'react';
let PrismImport: any;
function usePrism() {
if (!PrismImport) {
throw new Promise(async (resolve) => {
PrismImport = await import('./import-prismjs');
resolve(null);
});
}
return PrismImport.default;
}
// Valid languages based on the imported list
type PrismLanguages = 'javascript' | 'markdown';
type CodeProps = { code: string; lang?: PrismLanguages; }
function SuspenseCode({ code, lang = 'plain' }: CodeProps) {
const Prism = usePrism();
const [html, setHtml] = useState('');
const [langClassName, setLangClassName] = useState('language-plain');
useEffect(() => {
const grammar = Prism?.languages[lang];
if (grammar) {
setLangClassName(`language-${lang}`);
setHtml(Prism?.highlight(code, grammar, lang));
} else {
setLangClassName('language-plain');
setHtml(Prism?.highlight(code, Prism?.languages.plain, 'plain'));
}
}, [content, lang]);
return (
<pre>
<code
role="code"
dangerouslySetInnerHTML={{ __html: html }}
spellCheck="false"
className={langClassName}
/>
</pre>
);
}
interface LazyCodeProps extends CodeProps {
fallback?: React.ReactNode;
}
export function LazyCode({ fallback, ...props }: LazyCodeProps) {
return (
<React.Suspense fallback={fallback}>
<SuspenseCode {...props} />
</React.Suspense>
);
}