v1.2.9: 라이브 에디터·홈 피드·메인 커버 개선
라이브 모드 코드/콜아웃/토글 편집, 슬래시 명령, 홈 Latest List·Compact·Cards 보기, 사이트 설정 메인 화면 커버(720px) 및 HomeHero 반영. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
154
components/content/ContentMarkdownToggleEditor.vue
Normal file
154
components/content/ContentMarkdownToggleEditor.vue
Normal file
@@ -0,0 +1,154 @@
|
||||
<script setup>
|
||||
import { buildToggleBlockLines } from '../../lib/markdown-toggle.js'
|
||||
import ProseToggle from './ProseToggle.vue'
|
||||
import ContentMarkdownEditableInline from './ContentMarkdownEditableInline.vue'
|
||||
|
||||
const props = defineProps({
|
||||
/** 토글 제목 */
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/** 토글 본문 */
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/** 선언 줄 source-line(0-based) */
|
||||
titleSourceLine: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
/** 본문 첫 줄 source-line(0-based) */
|
||||
bodySourceLine: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['commit', 'insert-below'])
|
||||
|
||||
const titleEditorRef = ref(null)
|
||||
const bodyEditorRef = ref(null)
|
||||
const titleDraft = ref(props.title)
|
||||
|
||||
watch(() => props.title, (value) => {
|
||||
titleDraft.value = value
|
||||
})
|
||||
|
||||
/**
|
||||
* 토글 마크다운을 반영한다.
|
||||
* @param {{ title?: string, body?: string }} options - 옵션
|
||||
* @returns {void}
|
||||
*/
|
||||
const commitToggle = (options = {}) => {
|
||||
emit('commit', buildToggleBlockLines({
|
||||
title: options.title ?? titleDraft.value,
|
||||
body: options.body ?? props.modelValue
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* 제목 편집 반영
|
||||
* @param {string} value - 제목
|
||||
* @returns {void}
|
||||
*/
|
||||
const onTitleCommit = (value) => {
|
||||
titleDraft.value = String(value ?? '').trim()
|
||||
commitToggle({ title: titleDraft.value })
|
||||
}
|
||||
|
||||
/**
|
||||
* 제목 필드 이탈 전 로컬 초안 동기화(한글 조합·↓ 이동 시 본문 오염 방지)
|
||||
* @returns {void}
|
||||
*/
|
||||
const syncTitleDraft = () => {
|
||||
titleDraft.value = String(titleEditorRef.value?.readEditorValue?.() ?? titleDraft.value).trim()
|
||||
}
|
||||
|
||||
/**
|
||||
* 제목 Enter — 본문으로 포커스 이동
|
||||
* @returns {void}
|
||||
*/
|
||||
const onTitleEnterAdvance = () => {
|
||||
const nextTitle = String(titleEditorRef.value?.readEditorValue?.() ?? titleDraft.value).trim()
|
||||
titleDraft.value = nextTitle
|
||||
commitToggle({ title: titleDraft.value })
|
||||
|
||||
nextTick(() => {
|
||||
bodyEditorRef.value?.focusEditor('start')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 본문 편집 반영
|
||||
* @param {string} body - 본문
|
||||
* @returns {void}
|
||||
*/
|
||||
const onBodyCommit = (body) => {
|
||||
commitToggle({ body })
|
||||
}
|
||||
|
||||
/**
|
||||
* 토글 아래로 이탈
|
||||
* @param {Object} payload - insert-below 페이로드
|
||||
* @returns {void}
|
||||
*/
|
||||
const onExitBelow = (payload) => {
|
||||
emit('insert-below', payload)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProseToggle
|
||||
class="content-markdown-toggle-editor"
|
||||
data-editable-scope
|
||||
:title="titleDraft"
|
||||
default-open
|
||||
animated
|
||||
>
|
||||
<template #title>
|
||||
<ContentMarkdownEditableInline
|
||||
ref="titleEditorRef"
|
||||
tag="div"
|
||||
block-class="content-markdown-toggle-editor__title min-h-[1.75rem] outline-none"
|
||||
enter-mode="focus-next"
|
||||
navigation-scope="parent"
|
||||
:source-line="titleSourceLine"
|
||||
:model-value="titleDraft"
|
||||
@mousedown.stop
|
||||
@click.stop
|
||||
@commit="onTitleCommit"
|
||||
@enter-advance="onTitleEnterAdvance"
|
||||
@leave-block="syncTitleDraft"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<ContentMarkdownEditableInline
|
||||
ref="bodyEditorRef"
|
||||
tag="div"
|
||||
block-class="content-markdown-toggle-editor__body min-h-[3rem] outline-none"
|
||||
enter-mode="multiline"
|
||||
navigation-scope="parent"
|
||||
plain-text
|
||||
:source-line="bodySourceLine"
|
||||
:model-value="modelValue"
|
||||
@commit="onBodyCommit"
|
||||
@insert-below="onExitBelow"
|
||||
/>
|
||||
</ProseToggle>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.content-markdown-toggle-editor__title:empty::before {
|
||||
content: '토글 제목';
|
||||
color: var(--site-muted);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.content-markdown-toggle-editor__body:empty::before {
|
||||
content: '펼쳤을 때 보일 내용을 입력하세요';
|
||||
color: var(--site-muted);
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user