'use client'; import { useEffect } from 'react'; import type { FC } from 'react'; import { Crepe as CrepeClass } from '@milkdown/crepe'; import { Milkdown, useEditor } from '@milkdown/react'; import { Editor, rootCtx, defaultValueCtx, editorViewOptionsCtx } from '@milkdown/core'; import { replaceAll } from '@milkdown/utils'; // (선택) UI 스타일 import '@milkdown/crepe/theme/common/style.css'; import '@milkdown/crepe/theme/frame.css'; type Props = { /** 부모에서 내려주는 마크다운 */ value: string; /** 필요 시 외부에서 Crepe 인스턴스 접근 */ editorRef?: React.RefObject; }; export const MilkdownViewer: FC = ({ value, editorRef }) => { const { get } = useEditor((root) => { // 1) Crepe 생성 (초기 값은 parent value) const crepe = new CrepeClass({ root, defaultValue: value, featureConfigs: { // 필요 시 다른 기능 설정은 유지 가능 }, }); if (editorRef) editorRef.current = crepe; // 2) 항상 읽기 전용 crepe.editor.config((ctx) => { // 최초 값 보장 ctx.set(defaultValueCtx, value); // 편집 불가 ctx.update(editorViewOptionsCtx, (prev) => ({ ...prev, editable: () => false, })); }); // ✅ 읽기 전용이라 업로드 플러그인은 제거 (원하면 .use(upload) 복구) return crepe.editor; }, []); // 팩토리 고정: 리마운트/루프 방지 // 3) 부모 value 변경 시 문서 전체 교체 useEffect(() => { const editor = get(); if (!editor) return; editor.action(replaceAll(value)); }, [get, value]); return (
) };