Merge branch 'dev'
Deploy / deploy (push) Successful in 38s
CI / build (push) Failing after 15m16s

This commit is contained in:
ByungCheol
2026-06-07 20:16:14 +09:00
+40 -12
View File
@@ -17,6 +17,7 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const el = ref(null) const el = ref(null)
const imgInput = ref(null)
let editor = null let editor = null
// 에디터가 마지막으로 emit 한 값. 부모가 되돌려준 echo 를 구분해 입력 중 setMarkdown 으로 끊기지 않게. // 에디터가 마지막으로 emit 한 값. 부모가 되돌려준 echo 를 구분해 입력 중 setMarkdown 으로 끊기지 않게.
let lastEmitted = props.modelValue || '' let lastEmitted = props.modelValue || ''
@@ -28,6 +29,34 @@ async function uploadCompressed(fileOrBlob) {
return url return url
} }
// 커스텀 이미지 버튼 클릭 → 파일 선택 → 업로드 → 에디터에 삽입
// (Toast UI 기본 이미지 팝업이 작은 댓글창에서 잘려 OK 를 못 누르는 문제 회피)
async function onImagePick(e) {
const file = e.target.files?.[0]
e.target.value = ''
if (!file || !editor) return
try {
const url = await uploadCompressed(file)
const alt = file.name.replace(/\.[^.]+$/, '')
editor.exec('addImage', { imageUrl: url, altText: alt })
} catch {
/* 업로드 실패 시 미삽입 */
}
}
function makeImageButton() {
const btn = document.createElement('button')
btn.type = 'button'
btn.className = 'toastui-editor-toolbar-icons image'
btn.style.margin = '0'
btn.setAttribute('aria-label', '이미지')
btn.addEventListener('click', (ev) => {
ev.preventDefault()
imgInput.value?.click()
})
return btn
}
onMounted(() => { onMounted(() => {
editor = new Editor({ editor = new Editor({
el: el.value, el: el.value,
@@ -39,24 +68,20 @@ onMounted(() => {
placeholder: props.placeholder, placeholder: props.placeholder,
usageStatistics: false, usageStatistics: false,
autofocus: false, autofocus: false,
// 기본 이미지 버튼(팝업)을 커스텀(바로 업로드)으로 교체
toolbarItems: [
['heading', 'bold', 'italic', 'strike'],
['hr', 'quote'],
['ul', 'ol', 'task', 'indent', 'outdent'],
['table', { name: 'image', tooltip: '이미지', el: makeImageButton() }, 'link'],
['code', 'codeblock'],
],
events: { events: {
change: () => { change: () => {
lastEmitted = editor.getMarkdown() lastEmitted = editor.getMarkdown()
emit('update:modelValue', lastEmitted) emit('update:modelValue', lastEmitted)
}, },
}, },
hooks: {
// 이미지 추가 시 base64 대신 서버 업로드 → URL 삽입
addImageBlobHook: async (blob, callback) => {
try {
const url = await uploadCompressed(blob)
callback(url, '')
} catch {
/* 업로드 실패 시 미삽입 */
}
return false
},
},
}) })
}) })
@@ -80,5 +105,8 @@ onBeforeUnmount(() => {
</script> </script>
<template> <template>
<div>
<div ref="el"></div> <div ref="el"></div>
<input ref="imgInput" type="file" accept="image/*" hidden @change="onImagePick" />
</div>
</template> </template>