128 lines
3.3 KiB
Vue
128 lines
3.3 KiB
Vue
<script setup>
|
|
import { buildCalloutOpenerLine } from '../../lib/markdown-callout.js'
|
|
import ProseCallout from './ProseCallout.vue'
|
|
import ContentMarkdownEditableInline from './ContentMarkdownEditableInline.vue'
|
|
|
|
const props = defineProps({
|
|
/** 콜아웃 본문 */
|
|
modelValue: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
calloutEmojiEnabled: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
calloutEmoji: {
|
|
type: String,
|
|
default: '💡'
|
|
},
|
|
calloutTitle: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
calloutBackground: {
|
|
type: String,
|
|
default: 'blue'
|
|
},
|
|
/** 본문 첫 줄 source-line(0-based) */
|
|
bodySourceLine: {
|
|
type: Number,
|
|
required: true
|
|
},
|
|
/** 콜아웃 선언 줄 source-line(0-based) */
|
|
blockSourceLine: {
|
|
type: Number,
|
|
required: true
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits(['commit', 'delete-line', 'insert-above', 'insert-below', 'merge-with-previous', 'leave-block'])
|
|
|
|
const bodyLines = computed(() => {
|
|
const lines = String(props.modelValue ?? '').replace(/\r/g, '').split('\n')
|
|
return lines.length ? lines : ['']
|
|
})
|
|
|
|
/**
|
|
* 콜아웃 마크다운 줄을 반영한다.
|
|
* @param {string[]} contentLines - 본문 줄
|
|
* @returns {void}
|
|
*/
|
|
const commitCalloutLines = (contentLines) => {
|
|
emit('commit', [
|
|
buildCalloutOpenerLine({
|
|
calloutEmojiEnabled: props.calloutEmojiEnabled,
|
|
calloutEmoji: props.calloutEmoji,
|
|
calloutBackground: props.calloutBackground,
|
|
title: props.calloutTitle
|
|
}),
|
|
...contentLines,
|
|
':::'
|
|
])
|
|
}
|
|
|
|
/**
|
|
* 콜아웃 본문 문자열을 줄 목록으로 정규화한다.
|
|
* @param {string|{ value?: string }} payload - 편집 페이로드
|
|
* @returns {string[]} 본문 줄
|
|
*/
|
|
const normalizeBodyLines = (payload) => {
|
|
const value = typeof payload === 'string'
|
|
? payload
|
|
: String(payload?.value ?? '')
|
|
|
|
const lines = String(value ?? '').replace(/\r/g, '').split('\n')
|
|
return lines.length ? lines : ['']
|
|
}
|
|
|
|
/**
|
|
* 본문 편집 반영
|
|
* @param {string|{ value?: string }} payload - 편집 페이로드
|
|
* @returns {void}
|
|
*/
|
|
const onBodyCommit = (payload) => {
|
|
commitCalloutLines(normalizeBodyLines(payload))
|
|
}
|
|
|
|
/**
|
|
* 본문 입력 중 마크다운을 동기화한다.
|
|
* @param {string|{ value?: string }} payload - 편집 페이로드
|
|
* @returns {void}
|
|
*/
|
|
const onBodyInput = (payload) => {
|
|
commitCalloutLines(normalizeBodyLines(payload))
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
class="content-markdown-callout-editor relative"
|
|
:data-source-line="blockSourceLine"
|
|
>
|
|
<ProseCallout
|
|
:emoji-enabled="calloutEmojiEnabled"
|
|
:emoji="calloutEmoji"
|
|
:background="calloutBackground"
|
|
:title="calloutTitle"
|
|
>
|
|
<ContentMarkdownEditableInline
|
|
block-class="content-markdown-callout-editor__body min-w-0 text-[15px] leading-8 text-[var(--site-text)]"
|
|
enter-mode="multiline"
|
|
plain-text
|
|
arrow-exit-creates-line
|
|
:source-line="bodySourceLine"
|
|
:source-line-count="bodyLines.length"
|
|
:model-value="modelValue"
|
|
@input="onBodyInput"
|
|
@commit="onBodyCommit"
|
|
@delete-line="emit('delete-line', $event)"
|
|
@insert-above="emit('insert-above', $event)"
|
|
@insert-below="emit('insert-below', $event)"
|
|
@merge-with-previous="emit('merge-with-previous', bodySourceLine, $event)"
|
|
@leave-block="emit('leave-block', $event)"
|
|
/>
|
|
</ProseCallout>
|
|
</div>
|
|
</template>
|