Merge branch 'dev'
This commit is contained in:
@@ -14,32 +14,22 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
|
// PC(Electron)는 위지윅(contenteditable)에서 한글 IME 첫 자음이 중복되는 Chromium 버그가 있어
|
||||||
|
// 마크다운(텍스트 기반) 모드로 입력받는다. 웹/모바일(APK)은 위지윅 유지.
|
||||||
|
const isElectron = typeof navigator !== 'undefined' && /electron/i.test(navigator.userAgent)
|
||||||
|
const editType = isElectron ? 'markdown' : props.initialEditType
|
||||||
|
|
||||||
const el = ref(null)
|
const el = ref(null)
|
||||||
let editor = null
|
let editor = null
|
||||||
// 에디터가 마지막으로 emit 한 값. 부모가 되돌려준 echo 를 구분해 한글 조합(IME)이 깨지지 않게 한다.
|
// 에디터가 마지막으로 emit 한 값. 부모가 되돌려준 echo 를 구분해 입력 중 setMarkdown 으로 끊기지 않게.
|
||||||
let lastEmitted = props.modelValue || ''
|
let lastEmitted = props.modelValue || ''
|
||||||
// IME(한글 등) 조합 중 여부. 조합 중에는 getMarkdown/emit 을 보류해 첫 자음이 중복되는 문제를 막는다.
|
|
||||||
let composing = false
|
|
||||||
|
|
||||||
function emitValue() {
|
|
||||||
if (!editor) return
|
|
||||||
lastEmitted = editor.getMarkdown()
|
|
||||||
emit('update:modelValue', lastEmitted)
|
|
||||||
}
|
|
||||||
function onCompStart() {
|
|
||||||
composing = true
|
|
||||||
}
|
|
||||||
function onCompEnd() {
|
|
||||||
composing = false
|
|
||||||
emitValue() // 조합 완료 시 한 번만 반영
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
editor = new Editor({
|
editor = new Editor({
|
||||||
el: el.value,
|
el: el.value,
|
||||||
height: props.height,
|
height: props.height,
|
||||||
initialEditType: props.initialEditType,
|
initialEditType: editType,
|
||||||
hideModeSwitch: true, // 마크다운/위지윅 전환 탭 숨김 (WYSIWYG 전용)
|
hideModeSwitch: true,
|
||||||
plugins: [codeSyntaxHighlight], // 코드 구문 강조
|
plugins: [codeSyntaxHighlight], // 코드 구문 강조
|
||||||
initialValue: props.modelValue || '',
|
initialValue: props.modelValue || '',
|
||||||
placeholder: props.placeholder,
|
placeholder: props.placeholder,
|
||||||
@@ -47,24 +37,19 @@ onMounted(() => {
|
|||||||
autofocus: false,
|
autofocus: false,
|
||||||
events: {
|
events: {
|
||||||
change: () => {
|
change: () => {
|
||||||
// 조합 중에는 보류 — 조합 중 getMarkdown 호출이 IME 를 끊어 자음 중복을 유발한다.
|
lastEmitted = editor.getMarkdown()
|
||||||
if (composing) return
|
emit('update:modelValue', lastEmitted)
|
||||||
emitValue()
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
// 조합 이벤트는 contenteditable 에서 버블링되어 래퍼(el)에서 잡힌다.
|
|
||||||
el.value.addEventListener('compositionstart', onCompStart)
|
|
||||||
el.value.addEventListener('compositionend', onCompEnd)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 외부 값 변경(수정 로드, 제출 후 초기화 등)만 에디터에 반영.
|
// 외부 값 변경(수정 로드, 제출 후 초기화 등)만 에디터에 반영. echo 는 무시.
|
||||||
// 에디터 자신이 방금 emit 한 값(echo)이거나 조합 중이면 무시 → 입력 중 setMarkdown 으로 IME 조합이 끊기지 않게 한다.
|
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
(val) => {
|
(val) => {
|
||||||
const v = val || ''
|
const v = val || ''
|
||||||
if (composing || v === lastEmitted) return
|
if (v === lastEmitted) return
|
||||||
if (editor && v !== editor.getMarkdown()) {
|
if (editor && v !== editor.getMarkdown()) {
|
||||||
lastEmitted = v
|
lastEmitted = v
|
||||||
editor.setMarkdown(v)
|
editor.setMarkdown(v)
|
||||||
@@ -73,10 +58,6 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
if (el.value) {
|
|
||||||
el.value.removeEventListener('compositionstart', onCompStart)
|
|
||||||
el.value.removeEventListener('compositionend', onCompEnd)
|
|
||||||
}
|
|
||||||
editor?.destroy()
|
editor?.destroy()
|
||||||
editor = null
|
editor = null
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user