|
1 | 1 | import styles from './text.module.css' |
2 | 2 | import ReactMarkdown from 'react-markdown' |
3 | 3 | import gfm from 'remark-gfm' |
4 | | -import { LightAsync as SyntaxHighlighter } from 'react-syntax-highlighter' |
5 | | -import atomDark from 'react-syntax-highlighter/dist/cjs/styles/prism/atom-dark' |
| 4 | +import dynamic from 'next/dynamic' |
6 | 5 | import React, { useState, memo, useRef, useCallback, useMemo, useEffect } from 'react' |
7 | 6 | import MediaOrLink from './media-or-link' |
8 | 7 | import { IMGPROXY_URL_REGEXP, decodeProxyUrl } from '@/lib/url' |
@@ -229,17 +228,41 @@ function Table ({ node, ...props }) { |
229 | 228 | } |
230 | 229 |
|
231 | 230 | function Code ({ node, inline, className, children, style, ...props }) { |
232 | | - return inline |
233 | | - ? ( |
| 231 | + const [ReactSyntaxHighlighter, setReactSyntaxHighlighter] = useState(null) |
| 232 | + const [syntaxTheme, setSyntaxTheme] = useState(null) |
| 233 | + |
| 234 | + const loadHighlighter = useCallback(() => |
| 235 | + Promise.all([ |
| 236 | + dynamic(() => import('react-syntax-highlighter').then(mod => mod.LightAsync), { ssr: false }), |
| 237 | + import('react-syntax-highlighter/dist/cjs/styles/hljs/atom-one-dark').then(mod => mod.default) |
| 238 | + ]), [] |
| 239 | + ) |
| 240 | + |
| 241 | + useEffect(() => { |
| 242 | + if (!inline) { |
| 243 | + // loading the syntax highlighter and theme only when needed |
| 244 | + loadHighlighter().then(([highlighter, theme]) => { |
| 245 | + setReactSyntaxHighlighter(() => highlighter) |
| 246 | + setSyntaxTheme(() => theme) |
| 247 | + }) |
| 248 | + } |
| 249 | + }, [inline]) |
| 250 | + |
| 251 | + if (inline || !ReactSyntaxHighlighter || !syntaxTheme) { |
| 252 | + return ( |
234 | 253 | <code className={className} {...props}> |
235 | 254 | {children} |
236 | 255 | </code> |
237 | | - ) |
238 | | - : ( |
239 | | - <SyntaxHighlighter style={atomDark} language='text' PreTag='div' {...props}> |
240 | | - {children} |
241 | | - </SyntaxHighlighter> |
242 | | - ) |
| 256 | + ) |
| 257 | + } |
| 258 | + |
| 259 | + const language = className?.match(/language-(\w+)/)?.[1] || 'text' |
| 260 | + |
| 261 | + return ( |
| 262 | + <ReactSyntaxHighlighter style={syntaxTheme} language={language} PreTag='div' customStyle={{ borderRadius: '0.3rem' }} {...props}> |
| 263 | + {children} |
| 264 | + </ReactSyntaxHighlighter> |
| 265 | + ) |
243 | 266 | } |
244 | 267 |
|
245 | 268 | function P ({ children, node, onlyImages, somethingBefore, somethingAfter, ...props }) { |
|
0 commit comments