Skip to content

Commit d7aa112

Browse files
committed
fix: mdxComponent를 @frontend/common의 global context로 넘기도록 수정
1 parent 7729920 commit d7aa112

File tree

6 files changed

+236
-99
lines changed

6 files changed

+236
-99
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// 후대의 개발자님께 : 컴포넌트 맨 첫글자가 대문자로 시작하지 않으면 JSX 컴포넌트가 아니라 일반 HTML 태그로 인식합니다. 제발 대문자로 시작해주세요.
2+
import * as mui from "@mui/material";
3+
import type { MDXComponents } from "mdx/types.js";
4+
5+
import * as Shop from "@frontend/shop";
6+
7+
const MUIMDXComponents: MDXComponents = {
8+
Mui__material__Accordion: mui.Accordion,
9+
Mui__material__AccordionActions: mui.AccordionActions,
10+
Mui__material__AccordionDetails: mui.AccordionDetails,
11+
Mui__material__AccordionSummary: mui.AccordionSummary,
12+
Mui__material__Alert: mui.Alert,
13+
Mui__material__AlertTitle: mui.AlertTitle,
14+
Mui__material__AppBar: mui.AppBar,
15+
Mui__material__Autocomplete: mui.Autocomplete,
16+
Mui__material__Avatar: mui.Avatar,
17+
Mui__material__AvatarGroup: mui.AvatarGroup,
18+
Mui__material__Backdrop: mui.Backdrop,
19+
Mui__material__Badge: mui.Badge,
20+
Mui__material__BottomNavigation: mui.BottomNavigation,
21+
Mui__material__BottomNavigationAction: mui.BottomNavigationAction,
22+
Mui__material__Box: mui.Box,
23+
Mui__material__Breadcrumbs: mui.Breadcrumbs,
24+
Mui__material__Button: mui.Button,
25+
Mui__material__ButtonBase: mui.ButtonBase,
26+
Mui__material__ButtonGroup: mui.ButtonGroup,
27+
Mui__material__Card: mui.Card,
28+
Mui__material__CardActionArea: mui.CardActionArea,
29+
Mui__material__CardActions: mui.CardActions,
30+
Mui__material__CardContent: mui.CardContent,
31+
Mui__material__CardHeader: mui.CardHeader,
32+
Mui__material__CardMedia: mui.CardMedia,
33+
Mui__material__Checkbox: mui.Checkbox,
34+
Mui__material__Chip: mui.Chip,
35+
Mui__material__CircularProgress: mui.CircularProgress,
36+
Mui__material__Collapse: mui.Collapse,
37+
Mui__material__Container: mui.Container,
38+
Mui__material__Dialog: mui.Dialog,
39+
Mui__material__DialogActions: mui.DialogActions,
40+
Mui__material__DialogContent: mui.DialogContent,
41+
Mui__material__DialogContentText: mui.DialogContentText,
42+
Mui__material__DialogTitle: mui.DialogTitle,
43+
Mui__material__Divider: mui.Divider,
44+
Mui__material__Drawer: mui.Drawer,
45+
Mui__material__Fab: mui.Fab,
46+
Mui__material__Fade: mui.Fade,
47+
Mui__material__FilledInput: mui.FilledInput,
48+
Mui__material__FormControl: mui.FormControl,
49+
Mui__material__FormControlLabel: mui.FormControlLabel,
50+
Mui__material__FormGroup: mui.FormGroup,
51+
Mui__material__FormHelperText: mui.FormHelperText,
52+
Mui__material__FormLabel: mui.FormLabel,
53+
Mui__material__Grid: mui.Grid,
54+
Mui__material__Grow: mui.Grow,
55+
Mui__material__Icon: mui.Icon,
56+
Mui__material__IconButton: mui.IconButton,
57+
Mui__material__ImageList: mui.ImageList,
58+
Mui__material__ImageListItem: mui.ImageListItem,
59+
Mui__material__ImageListItemBar: mui.ImageListItemBar,
60+
Mui__material__Input: mui.Input,
61+
Mui__material__InputAdornment: mui.InputAdornment,
62+
Mui__material__InputBase: mui.InputBase,
63+
Mui__material__InputLabel: mui.InputLabel,
64+
Mui__material__LinearProgress: mui.LinearProgress,
65+
Mui__material__Link: mui.Link,
66+
Mui__material__List: mui.List,
67+
Mui__material__ListItem: mui.ListItem,
68+
Mui__material__ListItemAvatar: mui.ListItemAvatar,
69+
Mui__material__ListItemButton: mui.ListItemButton,
70+
Mui__material__ListItemIcon: mui.ListItemIcon,
71+
Mui__material__ListItemSecondaryAction: mui.ListItemSecondaryAction,
72+
Mui__material__ListItemText: mui.ListItemText,
73+
Mui__material__ListSubheader: mui.ListSubheader,
74+
Mui__material__Menu: mui.Menu,
75+
Mui__material__MenuItem: mui.MenuItem,
76+
Mui__material__MenuList: mui.MenuList,
77+
Mui__material__MobileStepper: mui.MobileStepper,
78+
Mui__material__Modal: mui.Modal,
79+
Mui__material__NativeSelect: mui.NativeSelect,
80+
Mui__material__NoSsr: mui.NoSsr,
81+
Mui__material__OutlinedInput: mui.OutlinedInput,
82+
Mui__material__Pagination: mui.Pagination,
83+
Mui__material__PaginationItem: mui.PaginationItem,
84+
Mui__material__Paper: mui.Paper,
85+
Mui__material__Popover: mui.Popover,
86+
Mui__material__Popper: mui.Popper,
87+
Mui__material__Portal: mui.Portal,
88+
Mui__material__Radio: mui.Radio,
89+
Mui__material__RadioGroup: mui.RadioGroup,
90+
Mui__material__Rating: mui.Rating,
91+
Mui__material__Select: mui.Select,
92+
Mui__material__Skeleton: mui.Skeleton,
93+
Mui__material__Slide: mui.Slide,
94+
Mui__material__Slider: mui.Slider,
95+
Mui__material__Snackbar: mui.Snackbar,
96+
Mui__material__SnackbarContent: mui.SnackbarContent,
97+
Mui__material__SpeedDial: mui.SpeedDial,
98+
Mui__material__SpeedDialAction: mui.SpeedDialAction,
99+
Mui__material__SpeedDialIcon: mui.SpeedDialIcon,
100+
Mui__material__Stack: mui.Stack,
101+
Mui__material__Step: mui.Step,
102+
Mui__material__StepButton: mui.StepButton,
103+
Mui__material__StepConnector: mui.StepConnector,
104+
Mui__material__StepContent: mui.StepContent,
105+
Mui__material__StepIcon: mui.StepIcon,
106+
Mui__material__StepLabel: mui.StepLabel,
107+
Mui__material__Stepper: mui.Stepper,
108+
Mui__material__SvgIcon: mui.SvgIcon,
109+
Mui__material__SwipeableDrawer: mui.SwipeableDrawer,
110+
Mui__material__Switch: mui.Switch,
111+
Mui__material__Tab: mui.Tab,
112+
Mui__material__Table: mui.Table,
113+
Mui__material__TableBody: mui.TableBody,
114+
Mui__material__TableCell: mui.TableCell,
115+
Mui__material__TableContainer: mui.TableContainer,
116+
Mui__material__TableFooter: mui.TableFooter,
117+
Mui__material__TableHead: mui.TableHead,
118+
Mui__material__TablePagination: mui.TablePagination,
119+
Mui__material__TableRow: mui.TableRow,
120+
Mui__material__TableSortLabel: mui.TableSortLabel,
121+
Mui__material__Tabs: mui.Tabs,
122+
Mui__material__TabScrollButton: mui.TabScrollButton,
123+
Mui__material__TextField: mui.TextField,
124+
Mui__material__TextareaAutosize: mui.TextareaAutosize,
125+
Mui__material__ToggleButton: mui.ToggleButton,
126+
Mui__material__ToggleButtonGroup: mui.ToggleButtonGroup,
127+
Mui__material__Toolbar: mui.Toolbar,
128+
Mui__material__Tooltip: mui.Tooltip,
129+
Mui__material__Typography: mui.Typography,
130+
Mui__material__Zoom: mui.Zoom,
131+
};
132+
133+
const PythonKRShopMDXComponents: MDXComponents = {
134+
Shop__Common__PriceDisplay: Shop.Components.Common.PriceDisplay,
135+
Shop__Common__SignInGuard: Shop.Components.Common.SignInGuard,
136+
Shop__Common__ContextProvider: Shop.Components.Common.ShopContextProvider,
137+
Shop__Feature__CartStatus: Shop.Components.Features.CartStatus,
138+
Shop__Feature__ProductList: Shop.Components.Features.ProductList,
139+
Shop__Feature__OrderList: Shop.Components.Features.OrderList,
140+
Shop__Feature__UserInfo: Shop.Components.Features.UserInfo,
141+
};
142+
143+
export const PyConKRMDXComponents = {
144+
...MUIMDXComponents,
145+
...PythonKRShopMDXComponents,
146+
};
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
export const MDX_HELP_TEXT = `\
2+
MDX 간단 사용 설명서
3+
4+
긴 가로줄을 넣고 싶다면, \`---\`를 사용해주세요!
5+
6+
---
7+
8+
제목은 아래와 같이 표현해요.
9+
# H1
10+
## H2
11+
### H3
12+
#### H4
13+
##### H5
14+
###### H6
15+
16+
---
17+
18+
**굵은 글자는 이렇게**
19+
*이탤릭(기울어진 글자)는 요렇게*
20+
응용 표현으로 ***굵으면서 기울어진 글자는 요렇게***
21+
22+
[링크는 이렇게 사용하고요,](https://pycon.kr)
23+
변수명과 같은 짧은 코드는 \`이렇게\` 표현해요!
24+
\`\`\`
25+
# 긴 코드는 이렇게 표현할 수 있어요.
26+
import antigravity
27+
\`\`\`
28+
29+
---
30+
31+
HTML 태그 중 일부를 사용할 수 있어요!
32+
33+
예를 들면 <sub>sub</sub> 태그나
34+
위로 가는 <sup>sup</sup> 태그도 있고요,
35+
밑줄도 <ins>표현할 수 있죠!</ins>
36+
37+
---
38+
39+
> 인용구는 이렇게 표현해요.
40+
> 여러 줄을 표현할수도 있고요!
41+
42+
---
43+
44+
사진 첨부는 이렇게 해요!
45+
![OctoCat](https://myoctocat.com/assets/images/base-octocat.svg)
46+
47+
만약 크기 조절을 하고 싶다면 HTML 태그도 가능해요!
48+
<img width="150px" src="https://myoctocat.com/assets/images/base-octocat.svg" />
49+
50+
---
51+
52+
- 순번이 없는 목록은 이렇게 사용해요.
53+
- 만약 하위 항목을 표현하고 싶으시다면
54+
- 이렇게 앞에 공백 2개를 붙여주세요!
55+
56+
---
57+
58+
1. 순번이 있는 목록은 이렇게 사용해요.
59+
2. 실수로 다음의 숫자를 잘못 적어도
60+
1. 자동으로 제대로 3번으로 나와요!
61+
62+
---
63+
64+
{ /*
65+
화면 상에는 노출되지 않는 주석은 이렇게 사용해요.
66+
주의하실 점은, 서버에서 클라이언트로 페이지의 내용을 응답할때는 요 주석 데이터도 같이 보내지므로, 절때 민감한 내용을 주석에 담지는 말아주세요!
67+
*/ }
68+
`
Lines changed: 14 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,11 @@
11
import React from "react";
22

3-
import { Box, Button, Card, CardContent, TextField, Typography } from "@mui/material";
4-
import type { MDXComponents } from "mdx/types.js";
3+
import { Box, Button, Stack } from "@mui/material";
54

5+
import { MDX_HELP_TEXT } from "@apps/pyconkr/consts/mdx_help_text";
66
import * as Common from "@frontend/common";
7-
import * as Shop from "@frontend/shop";
87

98
const LOCAL_STEORAGE_KEY = "mdi_test_input";
10-
const MDX_TEST_STRING = `\
11-
MDX 간단 사용 설명서
12-
13-
긴 가로줄을 넣고 싶다면, \`---\`를 사용해주세요!
14-
15-
---
16-
17-
제목은 아래와 같이 표현해요.
18-
# H1
19-
## H2
20-
### H3
21-
#### H4
22-
##### H5
23-
###### H6
24-
25-
---
26-
27-
**굵은 글자는 이렇게**
28-
*이탤릭(기울어진 글자)는 요렇게*
29-
응용 표현으로 ***굵으면서 기울어진 글자는 요렇게***
30-
31-
[링크는 이렇게 사용하고요,](https://pycon.kr)
32-
변수명과 같은 짧은 코드는 \`이렇게\` 표현해요!
33-
\`\`\`
34-
# 긴 코드는 이렇게 표현할 수 있어요.
35-
import antigravity
36-
\`\`\`
37-
38-
---
39-
40-
HTML 태그 중 일부를 사용할 수 있어요!
41-
42-
예를 들면 <sub>sub</sub> 태그나
43-
위로 가는 <sup>sup</sup> 태그도 있고요,
44-
밑줄도 <ins>표현할 수 있죠!</ins>
45-
46-
---
47-
48-
> 인용구는 이렇게 표현해요.
49-
> 여러 줄을 표현할수도 있고요!
50-
51-
---
52-
53-
사진 첨부는 이렇게 해요!
54-
![OctoCat](https://myoctocat.com/assets/images/base-octocat.svg)
55-
56-
만약 크기 조절을 하고 싶다면 HTML 태그도 가능해요!
57-
<img width="150px" src="https://myoctocat.com/assets/images/base-octocat.svg" />
58-
59-
---
60-
61-
- 순번이 없는 목록은 이렇게 사용해요.
62-
- 만약 하위 항목을 표현하고 싶으시다면
63-
- 이렇게 앞에 공백 2개를 붙여주세요!
64-
65-
---
66-
67-
1. 순번이 있는 목록은 이렇게 사용해요.
68-
2. 실수로 다음의 숫자를 잘못 적어도
69-
1. 자동으로 제대로 3번으로 나와요!
70-
71-
---
72-
73-
{ /*
74-
화면 상에는 노출되지 않는 주석은 이렇게 사용해요.
75-
주의하실 점은, 서버에서 클라이언트로 페이지의 내용을 응답할때는 요 주석 데이터도 같이 보내지므로, 절때 민감한 내용을 주석에 담지는 말아주세요!
76-
*/ }
77-
`
78-
79-
const PyConMDXComponents: MDXComponents = {
80-
Shop__Common__PriceDisplay: Shop.Components.Common.PriceDisplay,
81-
Shop__Common__SignInGuard: Shop.Components.Common.SignInGuard,
82-
Shop__Common__ContextProvider: Shop.Components.Common.ShopContextProvider,
83-
Shop__Feature__CartStatus: Shop.Components.Features.CartStatus,
84-
Shop__Feature__ProductList: Shop.Components.Features.ProductList,
85-
Shop__Feature__OrderList: Shop.Components.Features.OrderList,
86-
Shop__Feature__UserInfo: Shop.Components.Features.UserInfo,
87-
}
889

8910
const getMdxInputFromLocalStorage: () => string = () => {
9011
const input = localStorage.getItem(LOCAL_STEORAGE_KEY);
@@ -106,19 +27,17 @@ export const MdiTestPage: React.FC = () => {
10627
const setMDXInput = (text: string) => setState({ text: setMdxInputToLocalStorage(text), resetKey: window.crypto.randomUUID() });
10728

10829
return (
109-
<Box sx={{ p: 3 }}>
110-
<Typography variant="h5" gutterBottom>MDX 에디터</Typography>
111-
<TextField inputRef={inputRef} defaultValue={state.text} multiline fullWidth minRows={4} sx={{ my: 2 }} />
112-
<Button variant="contained" onClick={() => inputRef.current && setMDXInput(inputRef.current.value)}>변환</Button>
113-
&nbsp;
114-
<Button variant="contained" onClick={() => setMDXInput(MDX_TEST_STRING)}>테스트용 Help Text 로딩</Button>
115-
<br />
116-
<br />
117-
<Card>
118-
<CardContent>
119-
<Common.Components.MDXRenderer {...state} components={PyConMDXComponents} />
120-
</CardContent>
121-
</Card>
122-
</Box>
30+
<Stack direction="row" spacing={2} sx={{ width: "100%", flexGrow: 1, p: 2 }}>
31+
<Stack direction="column" spacing={2} sx={{ width: "50%", maxWidth: "50%" }}>
32+
<textarea ref={inputRef} defaultValue={state.text} style={{ flexGrow: 1 }} />
33+
<Stack direction="column" spacing={2} sx={{ mb: 2 }}>
34+
<Button variant="contained" sx={{ flexGrow: 1 }} onClick={() => inputRef.current && setMDXInput(inputRef.current.value)}>변환</Button>
35+
<Button variant="contained" sx={{ flexGrow: 1 }} onClick={() => setMDXInput(MDX_HELP_TEXT)}>Help Text 로딩</Button>
36+
</Stack>
37+
</Stack>
38+
<Box sx={{ width: "50%", maxWidth: "50%", overflowY: "scroll" }}>
39+
<Common.Components.MDXRenderer {...state} />
40+
</Box>
41+
</Stack>
12342
);
12443
};

apps/pyconkr/src/main.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import * as Common from "@frontend/common";
1212
import * as Shop from "@frontend/shop";
1313

1414
import { App } from "./App.tsx";
15-
import { IS_DEBUG_ENV } from './consts/index.ts';
15+
import { IS_DEBUG_ENV } from './consts';
16+
import { PyConKRMDXComponents } from './consts/mdx_components.ts';
1617
import { globalStyles, muiTheme } from "./styles/globalStyles.ts";
1718

1819
const queryClient = new QueryClient({
@@ -40,6 +41,7 @@ const CommonOptions: Common.Contexts.ContextOptions = {
4041
baseUrl: '.',
4142
backendApiDomain: import.meta.env.VITE_PYCONKR_BACKEND_API_DOMAIN,
4243
backendApiTimeout: 10000,
44+
mdxComponents: PyConKRMDXComponents,
4345
};
4446

4547
const ShopOptions: Shop.Contexts.ContextOptions = {

packages/common/src/components/mdx.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ const lineFormatterForMDX = (line: string) => {
3838
return `${trimmedLine} \n`;
3939
}
4040

41-
export const MDXRenderer: React.FC<{ text: string; components?: MDXComponents, resetKey?: string }> = ({ text, components, resetKey }) => {
42-
const { baseUrl } = Hooks.Common.useCommonContext();
41+
export const MDXRenderer: React.FC<{ text: string; resetKey?: string }> = ({ text, resetKey }) => {
42+
const { baseUrl, mdxComponents } = Hooks.Common.useCommonContext();
4343
const [state, setState] = React.useState<{ component: React.ReactNode, resetKey: string }>({
4444
component: <CircularProgress />,
4545
resetKey: window.crypto.randomUUID(),
@@ -56,7 +56,7 @@ export const MDXRenderer: React.FC<{ text: string; components?: MDXComponents, r
5656
// 편의성을 위해 렌더러 단에서 공백 2개를 추가하고 연속 줄바꿈을 <br />로 변환합니다.
5757
const processedText = text.split("\n").map(lineFormatterForMDX).join("").replaceAll("\n\n", "\n<br />\n");
5858
const { default: RenderResult } = await evaluate(processedText, { ...runtime, ...provider, baseUrl });
59-
setRenderResult(<RenderResult components={muiComponents({ overrides: { ...CustomMDXComponents, ...components } })} />);
59+
setRenderResult(<RenderResult components={muiComponents({ overrides: { ...CustomMDXComponents, ...(mdxComponents || {}) } })} />);
6060
} catch (error) {
6161
setRenderResult(<ErrorFallback error={error as Error} reset={setRandomResetKey} />);
6262
}

packages/common/src/contexts/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { MDXComponents } from 'mdx/types';
12
import * as React from "react";
23

34
namespace GlobalContext {
@@ -6,6 +7,7 @@ namespace GlobalContext {
67
debug?: boolean;
78
backendApiDomain: string;
89
backendApiTimeout: number;
10+
mdxComponents?: MDXComponents;
911
}
1012

1113
export const context = React.createContext<ContextOptions>({

0 commit comments

Comments
 (0)