From 0238e0b22fd8aceae868014a8eecc788f7f20d90 Mon Sep 17 00:00:00 2001 From: ByungCheol Date: Sun, 7 Jun 2026 18:14:40 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20PC=20=EB=A7=88=ED=81=AC=EB=8B=A4?= =?UTF-8?q?=EC=9A=B4=20=EC=97=90=EB=94=94=ED=84=B0=EC=97=90=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80(=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=E2=86=92=20=EC=95=95=EC=B6=95=20=E2=86=92?= =?UTF-8?q?=20base64=20=EC=9E=84=EB=B2=A0=EB=93=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이미지 버튼: 파일 선택 → imageToBlob(1280px·JPEG0.85)로 압축 → ![alt](data:...) 삽입 - 웹 에디터처럼 본문에 임베드(별도 서버 저장 없음), 단 압축으로 용량 절감 Co-Authored-By: Claude Opus 4.8 --- src/components/editor/MarkdownEditor.vue | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) 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(() => { + +