2026-05-31 15:42:52 +09:00
|
|
|
<script setup>
|
|
|
|
|
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
|
|
|
|
|
import Editor from '@toast-ui/editor'
|
|
|
|
|
import '@toast-ui/editor/dist/toastui-editor.css'
|
|
|
|
|
import codeSyntaxHighlight from '@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight-all'
|
|
|
|
|
import 'prismjs/themes/prism-tomorrow.css'
|
|
|
|
|
import '@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight.css'
|
|
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
modelValue: { type: String, default: '' },
|
|
|
|
|
height: { type: String, default: '400px' },
|
|
|
|
|
placeholder: { type: String, default: '' },
|
|
|
|
|
initialEditType: { type: String, default: 'wysiwyg' }, // 'markdown' | 'wysiwyg'
|
|
|
|
|
})
|
|
|
|
|
const emit = defineEmits(['update:modelValue'])
|
|
|
|
|
|
|
|
|
|
const el = ref(null)
|
|
|
|
|
let editor = null
|
2026-05-31 19:52:23 +09:00
|
|
|
// 에디터가 마지막으로 emit 한 값. 부모가 되돌려준 echo 를 구분해 한글 조합(IME)이 깨지지 않게 한다.
|
|
|
|
|
let lastEmitted = props.modelValue || ''
|
2026-05-31 15:42:52 +09:00
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
editor = new Editor({
|
|
|
|
|
el: el.value,
|
|
|
|
|
height: props.height,
|
|
|
|
|
initialEditType: props.initialEditType,
|
|
|
|
|
hideModeSwitch: true, // 마크다운/위지윅 전환 탭 숨김 (WYSIWYG 전용)
|
|
|
|
|
plugins: [codeSyntaxHighlight], // 코드 구문 강조
|
|
|
|
|
initialValue: props.modelValue || '',
|
|
|
|
|
placeholder: props.placeholder,
|
|
|
|
|
usageStatistics: false,
|
|
|
|
|
autofocus: false,
|
|
|
|
|
events: {
|
2026-05-31 19:52:23 +09:00
|
|
|
change: () => {
|
|
|
|
|
lastEmitted = editor.getMarkdown()
|
|
|
|
|
emit('update:modelValue', lastEmitted)
|
|
|
|
|
},
|
2026-05-31 15:42:52 +09:00
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
2026-05-31 19:52:23 +09:00
|
|
|
// 외부 값 변경(수정 로드, 제출 후 초기화 등)만 에디터에 반영.
|
|
|
|
|
// 에디터 자신이 방금 emit 한 값(echo)이면 무시 → 입력 중 setMarkdown 으로 IME(한글) 조합이 끊기지 않게 한다.
|
2026-05-31 15:42:52 +09:00
|
|
|
watch(
|
|
|
|
|
() => props.modelValue,
|
|
|
|
|
(val) => {
|
2026-05-31 19:52:23 +09:00
|
|
|
const v = val || ''
|
|
|
|
|
if (v === lastEmitted) return
|
|
|
|
|
if (editor && v !== editor.getMarkdown()) {
|
|
|
|
|
lastEmitted = v
|
|
|
|
|
editor.setMarkdown(v)
|
2026-05-31 15:42:52 +09:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
editor?.destroy()
|
|
|
|
|
editor = null
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div ref="el"></div>
|
|
|
|
|
</template>
|