diff --git a/src/components/editor/MarkdownEditor.vue b/src/components/editor/MarkdownEditor.vue index cfeb593..e49f48a 100644 --- a/src/components/editor/MarkdownEditor.vue +++ b/src/components/editor/MarkdownEditor.vue @@ -6,6 +6,7 @@ import codeSyntaxHighlight from '@toast-ui/editor-plugin-code-syntax-highlight/d import 'prismjs/themes/prism-tomorrow.css' import '@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight.css' import MarkdownViewer from '@/components/editor/MarkdownViewer.vue' +import { imageToBlob } from '@/utils/receiptOcr' const props = defineProps({ modelValue: { type: String, default: '' }, @@ -103,6 +104,46 @@ function insertLink() { }) } +// 이미지: 파일 선택 → 리사이즈/압축(JPEG) → base64 임베드 (웹 에디터와 동일하게 본문에 포함, 별도 서버 저장 없음) +const imgInput = ref(null) +const imgBusy = ref(false) +function pickImage() { + imgInput.value?.click() +} +function blobToDataUrl(blob) { + return new Promise((resolve, reject) => { + const r = new FileReader() + r.onload = () => resolve(r.result) + r.onerror = reject + r.readAsDataURL(blob) + }) +} +async function onImagePick(e) { + const file = e.target.files?.[0] + e.target.value = '' + if (!file) return + imgBusy.value = true + try { + const blob = await imageToBlob(file, 1280) // 긴 변 1280px, JPEG 0.85 압축 + const dataUrl = await blobToDataUrl(blob) + const ta = taRef.value + const s = ta ? ta.selectionStart : text.value.length + const alt = file.name.replace(/\.[^.]+$/, '') + const md = `![${alt}](${dataUrl})` + text.value = text.value.slice(0, s) + md + text.value.slice(s) + nextTick(() => { + if (!ta) return + ta.focus() + const pos = s + md.length + ta.setSelectionRange(pos, pos) + }) + } catch { + /* 이미지 처리 실패 무시 */ + } finally { + imgBusy.value = false + } +} + /* ===================== 웹/APK: Toast UI 위지윅 ===================== */ const el = ref(null) let editor = null @@ -169,9 +210,11 @@ onBeforeUnmount(() => { + +