From b38fc9f154fb32eb0db7c5ae65d2a110c30caffa Mon Sep 17 00:00:00 2001 From: zenn Date: Thu, 4 Jun 2026 10:28:43 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9D=B8=EC=9A=A9=20=EB=B8=94=EB=A1=9D=20?= =?UTF-8?q?=EC=83=89=EC=83=81=EA=B3=BC=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=ED=8C=A8=EB=84=90=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/admin/AdminEditorBlockPanel.vue | 28 ++- components/admin/AdminMarkdownEditor.vue | 49 ++++- .../content/ContentMarkdownCalloutEditor.vue | 201 ++---------------- .../content/ContentMarkdownRenderer.vue | 63 +++++- components/content/ProseBlockquote.vue | 33 ++- docs/changelog.md | 6 + docs/deploy.md | 8 +- docs/history.md | 4 + docs/map.md | 6 +- docs/spec.md | 2 + docs/update.md | 8 + lib/markdown-block-context.js | 6 +- lib/markdown-callout.js | 23 ++ package-lock.json | 4 +- package.json | 2 +- 15 files changed, 222 insertions(+), 221 deletions(-) diff --git a/components/admin/AdminEditorBlockPanel.vue b/components/admin/AdminEditorBlockPanel.vue index b944381..5c8b569 100644 --- a/components/admin/AdminEditorBlockPanel.vue +++ b/components/admin/AdminEditorBlockPanel.vue @@ -1,6 +1,12 @@ diff --git a/components/content/ContentMarkdownRenderer.vue b/components/content/ContentMarkdownRenderer.vue index 9fc9a8a..764f929 100644 --- a/components/content/ContentMarkdownRenderer.vue +++ b/components/content/ContentMarkdownRenderer.vue @@ -20,7 +20,7 @@ import { } from '../../lib/markdown-live-edit.js' import { buildCodeBlockLines, parseCodeFenceLine } from '../../lib/markdown-code-block.js' import { buildToggleBlockLines, parseToggleOpenerLine } from '../../lib/markdown-toggle.js' -import { CALLOUT_BACKGROUND_OPTIONS, parseCalloutOptions } from '../../lib/markdown-callout.js' +import { CALLOUT_BACKGROUND_OPTIONS, QUOTE_BACKGROUND_OPTIONS, parseCalloutOptions } from '../../lib/markdown-callout.js' import { createHeadingIdFactory } from '../../lib/markdown-toc.js' import ContentMarkdownCodeBlockEditor from './ContentMarkdownCodeBlockEditor.vue' import ProseCodeBlock from './ProseCodeBlock.vue' @@ -61,6 +61,8 @@ const emit = defineEmits([ 'delete-line', 'merge-with-previous-line', 'edit-image', + 'line-focus', + 'line-blur', 'slash-update', 'slash-end', 'slash-apply' @@ -141,7 +143,7 @@ const createBlock = (type = 'paragraph', text = '', level = null, id = '', optio calloutEmojiEnabled: options.calloutEmojiEnabled ?? true, calloutEmoji: options.calloutEmoji || '💡', calloutBackground: options.calloutBackground || 'blue', - quoteBackground: options.quoteBackground || 'pink', + quoteBackground: options.quoteBackground || 'gray', codeLanguage: options.codeLanguage || '', codeShowLineNumbers: options.codeShowLineNumbers !== false }) @@ -192,7 +194,7 @@ const parseQuoteOptions = (value) => { const [key, rawOptionValue] = token.split('=') const optionValue = String(rawOptionValue || '').trim() - if (key?.toLowerCase() === 'bg' && CALLOUT_BACKGROUND_OPTIONS.includes(optionValue)) { + if (key?.toLowerCase() === 'bg' && QUOTE_BACKGROUND_OPTIONS.includes(optionValue)) { quoteBackground = optionValue } }) @@ -1181,6 +1183,51 @@ const commitInlineBlockLines = (block, replacementLines) => { }) } +/** + * 라이브 편집 포커스/클릭 위치의 원본 줄을 상위에 알린다. + * @param {Event} event - 포커스 또는 포인터 이벤트 + * @returns {void} + */ +const emitLiveLineFocus = (event) => { + if (!props.interactive) { + return + } + + const target = event.target + + if (!(target instanceof Element)) { + return + } + + const sourceElement = target.closest('[data-source-line]') + const sourceLine = Number(sourceElement?.getAttribute('data-source-line')) + + if (!Number.isInteger(sourceLine) || sourceLine < 0) { + return + } + + emit('line-focus', sourceLine) +} + +/** + * 라이브 편집 영역을 벗어난 포커스를 상위에 알린다. + * @param {FocusEvent} event - 포커스 이탈 이벤트 + * @returns {void} + */ +const emitLiveLineBlur = (event) => { + if (!props.interactive || !rendererRootRef.value) { + return + } + + const nextTarget = event.relatedTarget + + if (nextTarget instanceof Node && rendererRootRef.value.contains(nextTarget)) { + return + } + + emit('line-blur') +} + /** * 문단 인라인 편집 반영 * @param {Object} block - 블록 @@ -2297,7 +2344,13 @@ onBeforeUnmount(() => {