1
1
import * as React from "react" ;
2
2
import * as runtime from "react/jsx-runtime" ;
3
+ import * as R from "remeda" ;
3
4
4
5
import { evaluate , EvaluateOptions } from "@mdx-js/mdx" ;
5
- import { CircularProgress , Typography } from "@mui/material" ;
6
+ import { Button , CircularProgress , Typography } from "@mui/material" ;
6
7
import { ErrorBoundary , Suspense } from "@suspensive/react" ;
7
8
import { useSuspenseQuery } from "@tanstack/react-query" ;
8
9
import components , { MuiMdxComponentsOptions } from 'mui-mdx-components' ;
9
- import * as R from "remeda" ;
10
10
11
11
import { useCommonContext } from '../hooks/useCommonContext' ;
12
12
@@ -26,11 +26,45 @@ const MDXComponents: MuiMdxComponentsOptions = {
26
26
}
27
27
}
28
28
29
- const useMDX = ( text : string ) => {
30
- const { baseUrl } = useCommonContext ( ) ;
31
- const options : EvaluateOptions = { ...runtime , baseUrl }
29
+ const SimplifiedMDXErrorFallback : React . FC < { reset : ( ) => void } > = ( { reset } ) => {
30
+ return < >
31
+ < Typography variant = "body2" color = "error" >
32
+ 페이지를 그리던 중 문제가 발생했습니다, 잠시 후 다시 시도해주세요.< br />
33
+ 만약 문제가 계속 발생한다면, 파이콘 한국 준비 위원회에게 알려주세요!< br />
34
+ < br />
35
+ Problem occurred while drawing the page, please try again later.< br />
36
+ If the problem persists, please let the PyCon Korea organizing committee know!
37
+ </ Typography >
38
+ < br />
39
+ < Button variant = "outlined" onClick = { reset } > 다시 시도 | Retry</ Button >
40
+ </ > ;
41
+ }
42
+
43
+ const DetailedMDXErrorFallback : React . FC < { error : Error , reset : ( ) => void } > = ( { error, reset } ) => {
44
+ const errorObject = Object . getOwnPropertyNames ( error ) . reduce ( ( acc , key ) => ( { ...acc , [ key ] : ( error as unknown as { [ key : string ] : unknown } ) [ key ] } ) , { } ) ;
45
+ return < >
46
+ < Typography variant = "body2" color = "error" > MDX 변환 오류: { error . message } </ Typography >
47
+ < details open >
48
+ < summary > 오류 상세</ summary >
49
+ < pre style = { {
50
+ whiteSpace : "pre-wrap" ,
51
+ backgroundColor : "#f5f5f5" ,
52
+ padding : "1em" ,
53
+ borderRadius : "4px" ,
54
+ userSelect : "text" ,
55
+ } } >
56
+ < code > { JSON . stringify ( errorObject , null , 2 ) } </ code >
57
+ </ pre >
58
+ </ details >
59
+ < br />
60
+ < Button variant = "outlined" onClick = { reset } > 다시 시도</ Button >
61
+ </ > ;
62
+ } ;
63
+
64
+ const InnerMDXRenderer : React . FC < { text : string , baseUrl : string } > = ( { text, baseUrl } ) => {
65
+ const options : EvaluateOptions = { ...runtime , baseUrl } ;
32
66
33
- return useSuspenseQuery ( {
67
+ const { data } = useSuspenseQuery ( {
34
68
queryKey : [ "mdx" , text ] ,
35
69
queryFn : async ( ) => {
36
70
const { default : RenderResult } = await evaluate ( text , options ) ;
@@ -39,30 +73,21 @@ const useMDX = (text: string) => {
39
73
</ div >
40
74
} ,
41
75
} ) ;
42
- }
43
76
44
- const MDXErrorFallback : React . FC < { error : Error } > = ( { error } ) => {
45
- console . error ( error ) ;
46
- return (
47
- < Typography variant = "body2" color = "error" >
48
- MDX 변환 오류: { error . message }
49
- </ Typography >
50
- ) ;
51
- } ;
52
-
53
- const InnerMDXRenderer : React . FC < { text : string } > = ( { text } ) => {
54
- const { data } = useMDX ( text ) ;
55
77
return < > { data } </ > ;
56
78
}
57
79
58
80
export const MDXRenderer : React . FC < { text : string } > = ( { text } ) => {
59
81
// 원래 MDX는 각 줄의 마지막에 공백 2개가 있어야 줄바꿈이 되고, 또 연속 줄바꿈은 무시되지만,
60
82
// 편의성을 위해 렌더러 단에서 공백 2개를 추가하고 연속 줄바꿈을 <br />로 변환합니다.
61
- let processedText = text . split ( "\n" ) . map ( ( line ) => R . isEmpty ( line . trim ( ) ) ? "" : `${ line . trim ( ) } ` ) . join ( "\n" ) . replaceAll ( "\n\n" , "\n<br />\n" ) ;
83
+ const { baseUrl, debug } = useCommonContext ( ) ;
84
+
85
+ const ErrorHandler = debug ? DetailedMDXErrorFallback : SimplifiedMDXErrorFallback ;
86
+ const processedText = text . split ( "\n" ) . map ( ( line ) => R . isEmpty ( line . trim ( ) ) ? "" : `${ line . trim ( ) } ` ) . join ( "\n" ) . replaceAll ( "\n\n" , "\n<br />\n" ) ;
62
87
63
- return < ErrorBoundary fallback = { MDXErrorFallback } >
88
+ return < ErrorBoundary fallback = { ErrorHandler } >
64
89
< Suspense fallback = { < CircularProgress /> } >
65
- < InnerMDXRenderer text = { processedText } />
90
+ < InnerMDXRenderer text = { processedText } baseUrl = { baseUrl } />
66
91
</ Suspense >
67
92
</ ErrorBoundary >
68
93
} ;
0 commit comments