117 lines
3.2 KiB
Vue
117 lines
3.2 KiB
Vue
<script setup>
|
|
const props = defineProps({
|
|
content: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
slashMenuActive: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
slashSuppressedLines: {
|
|
type: Array,
|
|
default: () => []
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits([
|
|
'keydown',
|
|
'gallery-reorder',
|
|
'merge-images-to-gallery',
|
|
'insert-image-to-gallery',
|
|
'extract-gallery-image',
|
|
'remove-gallery-image',
|
|
'block-content-change',
|
|
'content-replace',
|
|
'append-paragraph',
|
|
'insert-after-line',
|
|
'delete-line',
|
|
'merge-with-previous-line',
|
|
'line-focus',
|
|
'line-blur',
|
|
'slash-update',
|
|
'slash-end',
|
|
'slash-apply'
|
|
])
|
|
|
|
const previewRef = ref(null)
|
|
const rendererRef = ref(null)
|
|
|
|
/**
|
|
* 미리보기 표면 DOM을 반환한다.
|
|
* @returns {HTMLElement|null} 미리보기 DOM
|
|
*/
|
|
const getPreviewElement = () => previewRef.value
|
|
|
|
/**
|
|
* 지정한 라이브 편집 줄에 포커스를 이동한다.
|
|
* @param {...unknown} args - ContentMarkdownRenderer 포커스 인자
|
|
* @returns {void}
|
|
*/
|
|
const focusEditableAtLine = (...args) => {
|
|
rendererRef.value?.focusEditableAtLine?.(...args)
|
|
}
|
|
|
|
/**
|
|
* 라이브 문서 전체를 선택한다.
|
|
* @returns {void}
|
|
*/
|
|
const selectAllLiveDocument = () => {
|
|
rendererRef.value?.selectAllLiveDocument?.()
|
|
}
|
|
|
|
/**
|
|
* 원본 줄 번호에 해당하는 라이브 편집 DOM을 반환한다.
|
|
* @param {number|string|null} sourceLine - 원본 줄 번호
|
|
* @returns {Element|null} 줄 DOM
|
|
*/
|
|
const getSourceLineElement = (sourceLine) => {
|
|
if (sourceLine === null || sourceLine === undefined) {
|
|
return null
|
|
}
|
|
|
|
return previewRef.value?.querySelector?.(`[data-source-line="${sourceLine}"]`) ?? null
|
|
}
|
|
|
|
defineExpose({
|
|
getPreviewElement,
|
|
focusEditableAtLine,
|
|
selectAllLiveDocument,
|
|
getSourceLineElement
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
ref="previewRef"
|
|
class="admin-markdown-editor__preview min-h-[620px] px-0 py-5 text-[#15171a] outline-none"
|
|
style="--site-text: #15171a; --site-muted: #6b7280; --site-panel: #f6f7f8; --site-line: #e3e6e8; --site-accent: #2eb6ea;"
|
|
tabindex="0"
|
|
@keydown.capture="emit('keydown', $event)"
|
|
>
|
|
<ContentMarkdownRenderer
|
|
ref="rendererRef"
|
|
:content="props.content"
|
|
interactive
|
|
:slash-menu-active="props.slashMenuActive"
|
|
:slash-suppressed-lines="props.slashSuppressedLines"
|
|
@gallery-reorder="emit('gallery-reorder', $event)"
|
|
@merge-images-to-gallery="emit('merge-images-to-gallery', $event)"
|
|
@insert-image-to-gallery="emit('insert-image-to-gallery', $event)"
|
|
@extract-gallery-image="emit('extract-gallery-image', $event)"
|
|
@remove-gallery-image="emit('remove-gallery-image', $event)"
|
|
@block-content-change="emit('block-content-change', $event)"
|
|
@content-replace="emit('content-replace', $event)"
|
|
@append-paragraph="emit('append-paragraph', $event)"
|
|
@insert-after-line="emit('insert-after-line', $event)"
|
|
@delete-line="emit('delete-line', $event)"
|
|
@merge-with-previous-line="emit('merge-with-previous-line', $event)"
|
|
@line-focus="emit('line-focus', $event)"
|
|
@line-blur="emit('line-blur', $event)"
|
|
@slash-update="emit('slash-update', $event)"
|
|
@slash-end="emit('slash-end', $event)"
|
|
@slash-apply="emit('slash-apply', $event)"
|
|
/>
|
|
</div>
|
|
</template>
|