11import 'katex/dist/katex.min.css'
2- import React , { cloneElement , isValidElement , useCallback , useMemo , useRef } from 'react'
2+ import React , { cloneElement , isValidElement , useCallback , useEffect , useMemo , useRef } from 'react'
33import ReactMarkdown from 'react-markdown'
44import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
55import { base16AteliersulphurpoolLight , vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism'
@@ -14,7 +14,10 @@ import Download from 'yet-another-react-lightbox/plugins/download'
1414import Zoom from 'yet-another-react-lightbox/plugins/zoom'
1515import remarkMermaid from '../remark/remarkMermaid'
1616import 'yet-another-react-lightbox/styles.css'
17+ import { drawBlurhashToCanvas } from '../utils/blurhash'
1718import { useColorMode } from '../utils/darkModeUtils'
19+ import { parseImageUrlMetadata } from '../utils/image-upload'
20+ import { useImageLoadState } from '../utils/use-image-load-state'
1821
1922interface SectionChildProps {
2023 node ?: { tagName ?: string }
@@ -47,6 +50,69 @@ const isMarkdownImageLinkAtEnd = (text: string) => {
4750 return false
4851}
4952
53+ function MarkdownImage ( {
54+ src,
55+ alt,
56+ show,
57+ rounded,
58+ scale,
59+ className,
60+ } : {
61+ src ?: string
62+ alt ?: string
63+ show : ( src ?: string ) => void
64+ rounded : boolean
65+ scale : string
66+ className ?: string
67+ } ) {
68+ const canvasRef = useRef < HTMLCanvasElement > ( null )
69+ const { src : cleanSrc , blurhash, width, height } = parseImageUrlMetadata ( src )
70+ const { failed, imageRef, loaded, onError, onLoad } = useImageLoadState ( cleanSrc )
71+ const roundedClass = rounded ? 'rounded-xl' : ''
72+ const aspectRatio = width && height ? `${ width } / ${ height } ` : undefined
73+
74+ useEffect ( ( ) => {
75+ if ( ! blurhash || ! canvasRef . current ) {
76+ return
77+ }
78+ try {
79+ drawBlurhashToCanvas ( canvasRef . current , blurhash )
80+ } catch ( error ) {
81+ console . error ( 'Failed to render blurhash' , error )
82+ }
83+ } , [ blurhash ] )
84+
85+ return (
86+ < span
87+ className = { `relative inline-block max-w-full overflow-hidden ${ roundedClass } ` }
88+ style = { { zoom : scale , aspectRatio } }
89+ >
90+ { blurhash && ! loaded ? (
91+ < canvas
92+ ref = { canvasRef }
93+ aria-hidden = 'true'
94+ className = { `absolute inset-0 h-full w-full scale-110 blur-sm ${ roundedClass } ` }
95+ />
96+ ) : null }
97+ < img
98+ ref = { imageRef }
99+ src = { cleanSrc }
100+ alt = { alt }
101+ width = { width }
102+ height = { height }
103+ onClick = { ( ) => {
104+ show ( cleanSrc )
105+ } }
106+ onLoad = { onLoad }
107+ onError = { onError }
108+ className = { `mx-auto max-w-full cursor-zoom-in transition-opacity ${ roundedClass } ${ className || '' } ${
109+ blurhash && ( ! loaded || failed ) ? 'opacity-0' : 'opacity-100'
110+ } `}
111+ />
112+ </ span >
113+ )
114+ }
115+
50116export function Markdown ( { content } : { content : string } ) {
51117 const colorMode = useColorMode ( )
52118 const [ index , setIndex ] = React . useState ( - 1 )
@@ -97,23 +163,15 @@ export function Markdown({ content }: { content: string }) {
97163 const offset = node ?. position ?. start . offset ?? 0
98164 const previousContent = content . slice ( 0 , offset )
99165 const newlinesBefore = countNewlinesBeforeNode ( previousContent , offset )
100- const imageAlt = typeof props . alt === 'string' ? props . alt : ''
101166 const Image = ( { rounded, scale } : { rounded : boolean ; scale : string } ) => (
102- < button
103- type = 'button'
104- className = 'bg-transparent border-0 p-0'
105- onClick = { ( ) => {
106- show ( src )
107- } }
108- >
109- < img
110- src = { src }
111- { ...props }
112- alt = { imageAlt }
113- className = { `mx-auto ${ rounded ? 'rounded-xl' : '' } ` }
114- style = { { zoom : scale } }
115- />
116- </ button >
167+ < MarkdownImage
168+ src = { src }
169+ alt = { typeof props . alt === 'string' ? props . alt : '' }
170+ show = { show }
171+ rounded = { rounded }
172+ scale = { scale }
173+ className = { props . className }
174+ />
117175 )
118176 if (
119177 newlinesBefore >= 1 ||
0 commit comments