미리보기 집중 모드와 빈 줄 공백 보존

This commit is contained in:
2026-05-14 17:01:04 +09:00
parent 5da93b9aa4
commit 849e86802f
9 changed files with 60 additions and 13 deletions

View File

@@ -1002,7 +1002,7 @@ const handleKeydown = (event) => {
<template>
<div ref="editorRootRef" class="admin-markdown-editor grid gap-3">
<div class="admin-markdown-editor__toolbar flex flex-wrap items-center gap-1.5 rounded border border-[#e3e6e8] bg-white p-2">
<div v-if="activeMode === 'write'" class="admin-markdown-editor__toolbar flex flex-wrap items-center gap-1.5 rounded border border-[#e3e6e8] bg-white p-2">
<button class="admin-markdown-editor__tool rounded px-2.5 py-1.5 text-sm font-semibold text-[#394047] hover:bg-[#eff1f2]" type="button" @click="applyHeading(1)">
H1
</button>
@@ -1077,7 +1077,7 @@ const handleKeydown = (event) => {
<div class="admin-markdown-editor__editor-surface min-h-[620px]">
<div
ref="gutterRef"
class="admin-markdown-editor__gutter absolute bottom-0 left-0 top-0 w-10 select-none overflow-y-auto overflow-x-hidden py-5 font-mono text-[13px] leading-7 text-[#a0a8b0]"
class="admin-markdown-editor__gutter absolute bottom-0 left-0 top-0 w-10 select-none overflow-y-hidden overflow-x-hidden py-5 font-mono text-[13px] leading-7 text-[#a0a8b0]"
aria-hidden="true"
>
<div
@@ -1208,7 +1208,7 @@ const handleKeydown = (event) => {
<div
v-else
ref="previewRef"
class="admin-markdown-editor__preview min-h-[620px] rounded border border-[#e3e6e8] bg-white px-6 py-5 text-[#15171a]"
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"
>
@@ -1275,3 +1275,13 @@ const handleKeydown = (event) => {
</div>
</div>
</template>
<style scoped>
.admin-markdown-editor__gutter {
scrollbar-width: none;
}
.admin-markdown-editor__gutter::-webkit-scrollbar {
display: none;
}
</style>

View File

@@ -138,6 +138,13 @@ const hasMarkdownHardBreak = (line) => / {2,}$/.test(line)
*/
const cleanParagraphLine = (line) => line.replace(/ {2,}$/, '').trim()
/**
* 빈 줄 공백 블록 높이를 반환한다.
* @param {Object} block - 렌더링 블록
* @returns {string} Tailwind 높이 클래스
*/
const getSpacerHeightClass = (block) => block.meta?.legacy ? 'h-6' : 'h-8'
/**
* 닫힘 표식까지의 행 목록을 반환
* @param {Array<string>} lines - 전체 마크다운 행
@@ -263,7 +270,14 @@ const parseMarkdownBlocks = (markdown) => {
const line = lines[index]
const trimmedLine = line.trim()
if (trimmedLine === BLANK_PARAGRAPH_MARKER || !trimmedLine) {
if (trimmedLine === BLANK_PARAGRAPH_MARKER) {
blocks.push(createBlock('spacer', '', null, `block-${blocks.length}`, { meta: { legacy: true } }))
index += 1
continue
}
if (!trimmedLine) {
blocks.push(createBlock('spacer', '', null, `block-${blocks.length}`))
index += 1
continue
}
@@ -546,7 +560,8 @@ const showNextImage = () => {
<template>
<div class="content-markdown-renderer">
<template v-for="block in blocks" :key="block.id">
<ProseHeading v-if="block.type === 'heading'" :level="block.level">
<div v-if="block.type === 'spacer'" class="content-markdown-renderer__spacer" :class="getSpacerHeightClass(block)" aria-hidden="true" />
<ProseHeading v-else-if="block.type === 'heading'" :level="block.level">
<template v-for="(segment, segmentIndex) in parseInlineSegments(block.text)" :key="`${block.id}-heading-${segmentIndex}`">
<strong v-if="segment.type === 'strong'">{{ segment.text }}</strong>
<em v-else-if="segment.type === 'em'">{{ segment.text }}</em>