관리자 마크다운 미리보기 추가
This commit is contained in:
@@ -17,6 +17,8 @@ const props = defineProps({
|
||||
const emit = defineEmits(['submit'])
|
||||
|
||||
const slugTouched = ref(Boolean(props.initialPost.slug))
|
||||
const editorMode = ref('write')
|
||||
const contentTextarea = ref(null)
|
||||
|
||||
const form = reactive({
|
||||
title: props.initialPost.title || '',
|
||||
@@ -66,6 +68,77 @@ const parseTags = (value) => [...new Set(value
|
||||
.map((tag) => toSlug(tag))
|
||||
.filter(Boolean))]
|
||||
|
||||
/**
|
||||
* 본문 선택 영역에 마크다운 문법 삽입
|
||||
* @param {string} before - 선택 영역 앞에 넣을 문자열
|
||||
* @param {string} after - 선택 영역 뒤에 넣을 문자열
|
||||
* @param {string} fallback - 선택 영역이 없을 때 넣을 문자열
|
||||
* @returns {void}
|
||||
*/
|
||||
const insertMarkdown = (before, after = '', fallback = '') => {
|
||||
const textarea = contentTextarea.value
|
||||
|
||||
if (!textarea) {
|
||||
form.content += fallback || before
|
||||
return
|
||||
}
|
||||
|
||||
const start = textarea.selectionStart
|
||||
const end = textarea.selectionEnd
|
||||
const selectedText = form.content.slice(start, end)
|
||||
const insertText = selectedText
|
||||
? `${before}${selectedText}${after}`
|
||||
: (fallback || `${before}${after}`)
|
||||
|
||||
form.content = `${form.content.slice(0, start)}${insertText}${form.content.slice(end)}`
|
||||
|
||||
nextTick(() => {
|
||||
textarea.focus()
|
||||
const cursor = start + insertText.length
|
||||
textarea.setSelectionRange(cursor, cursor)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 제목 문법 삽입
|
||||
* @returns {void}
|
||||
*/
|
||||
const insertHeading = () => {
|
||||
insertMarkdown('## ', '', '## 제목')
|
||||
}
|
||||
|
||||
/**
|
||||
* 굵게 문법 삽입
|
||||
* @returns {void}
|
||||
*/
|
||||
const insertBold = () => {
|
||||
insertMarkdown('**', '**', '**강조**')
|
||||
}
|
||||
|
||||
/**
|
||||
* 목록 문법 삽입
|
||||
* @returns {void}
|
||||
*/
|
||||
const insertList = () => {
|
||||
insertMarkdown('- ', '', '- 목록')
|
||||
}
|
||||
|
||||
/**
|
||||
* 인용 문법 삽입
|
||||
* @returns {void}
|
||||
*/
|
||||
const insertQuote = () => {
|
||||
insertMarkdown('> ', '', '> 인용')
|
||||
}
|
||||
|
||||
/**
|
||||
* 코드 블록 문법 삽입
|
||||
* @returns {void}
|
||||
*/
|
||||
const insertCodeBlock = () => {
|
||||
insertMarkdown('```\n', '\n```', '```\n코드\n```')
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 입력값 제출
|
||||
* @returns {void}
|
||||
@@ -102,14 +175,57 @@ const submitPost = () => {
|
||||
>
|
||||
</label>
|
||||
|
||||
<label class="admin-post-form__field grid gap-2 text-sm">
|
||||
<span class="admin-post-form__label font-medium">본문</span>
|
||||
<textarea
|
||||
v-model="form.content"
|
||||
class="admin-post-form__textarea min-h-[28rem] rounded border border-line bg-white px-3 py-3 font-mono text-sm leading-6"
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<div class="admin-post-form__field grid gap-2 text-sm">
|
||||
<div class="admin-post-form__editor-header flex flex-wrap items-center justify-between gap-3">
|
||||
<span class="admin-post-form__label font-medium">본문</span>
|
||||
<div class="admin-post-form__mode flex rounded border border-line bg-white p-1 text-xs font-semibold">
|
||||
<button
|
||||
class="admin-post-form__mode-button rounded px-3 py-1"
|
||||
:class="editorMode === 'write' ? 'bg-[#15171a] text-white' : 'text-muted'"
|
||||
type="button"
|
||||
@click="editorMode = 'write'"
|
||||
>
|
||||
작성
|
||||
</button>
|
||||
<button
|
||||
class="admin-post-form__mode-button rounded px-3 py-1"
|
||||
:class="editorMode === 'preview' ? 'bg-[#15171a] text-white' : 'text-muted'"
|
||||
type="button"
|
||||
@click="editorMode = 'preview'"
|
||||
>
|
||||
미리보기
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="editorMode === 'write'" class="admin-post-form__editor grid gap-2">
|
||||
<div class="admin-post-form__toolbar flex flex-wrap gap-2">
|
||||
<button class="admin-post-form__tool rounded border border-line bg-white px-3 py-1.5 text-xs font-semibold" type="button" @click="insertHeading">
|
||||
제목
|
||||
</button>
|
||||
<button class="admin-post-form__tool rounded border border-line bg-white px-3 py-1.5 text-xs font-semibold" type="button" @click="insertBold">
|
||||
굵게
|
||||
</button>
|
||||
<button class="admin-post-form__tool rounded border border-line bg-white px-3 py-1.5 text-xs font-semibold" type="button" @click="insertList">
|
||||
목록
|
||||
</button>
|
||||
<button class="admin-post-form__tool rounded border border-line bg-white px-3 py-1.5 text-xs font-semibold" type="button" @click="insertQuote">
|
||||
인용
|
||||
</button>
|
||||
<button class="admin-post-form__tool rounded border border-line bg-white px-3 py-1.5 text-xs font-semibold" type="button" @click="insertCodeBlock">
|
||||
코드
|
||||
</button>
|
||||
</div>
|
||||
<textarea
|
||||
ref="contentTextarea"
|
||||
v-model="form.content"
|
||||
class="admin-post-form__textarea min-h-[28rem] rounded border border-line bg-white px-3 py-3 font-mono text-sm leading-6"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<AdminMarkdownPreview v-else :content="form.content" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<aside class="admin-post-form__settings grid content-start gap-4">
|
||||
|
||||
Reference in New Issue
Block a user