공개 본문 인용 편집 분리
This commit is contained in:
@@ -16,10 +16,8 @@ import {
|
||||
} from '../../lib/markdown-live-edit.js'
|
||||
import { CALLOUT_BACKGROUND_OPTIONS } from '../../lib/markdown-callout.js'
|
||||
import {
|
||||
formatQuoteLine,
|
||||
getQuoteContentStartLine,
|
||||
getQuoteLineEntries,
|
||||
normalizeQuoteEditableValue
|
||||
getQuoteLineEntries
|
||||
} from '../../lib/markdown-quote.js'
|
||||
import { getGalleryRows } from '../../lib/content-gallery-images.js'
|
||||
import { useContentMarkdownLightbox } from '../../composables/useContentMarkdownLightbox.js'
|
||||
@@ -29,6 +27,7 @@ import { useContentMarkdownLiveSelection } from '../../composables/useContentMar
|
||||
import { useContentMarkdownFencedBlocks } from '../../composables/useContentMarkdownFencedBlocks.js'
|
||||
import { useContentMarkdownParagraphs } from '../../composables/useContentMarkdownParagraphs.js'
|
||||
import { useContentMarkdownLists } from '../../composables/useContentMarkdownLists.js'
|
||||
import { useContentMarkdownQuotes } from '../../composables/useContentMarkdownQuotes.js'
|
||||
import ContentMarkdownCodeBlockEditor from './ContentMarkdownCodeBlockEditor.vue'
|
||||
import ProseCodeBlock from './ProseCodeBlock.vue'
|
||||
import ProseHtml from './ProseHtml.vue'
|
||||
@@ -199,6 +198,19 @@ const {
|
||||
insertBelowBlock: (block, options) => onInsertBelowBlock(block, options)
|
||||
})
|
||||
|
||||
const {
|
||||
onQuoteBlockCommit,
|
||||
onQuoteBlockInsertBelow,
|
||||
onQuoteBlockConvertToParagraph
|
||||
} = useContentMarkdownQuotes({
|
||||
content: computed(() => props.content),
|
||||
pendingFocusLine,
|
||||
pendingFocusPosition,
|
||||
pendingFocusOffset,
|
||||
commitInlineBlockLines: (block, replacementLines) => commitInlineBlockLines(block, replacementLines),
|
||||
insertBelowBlock: (block, options) => onInsertBelowBlock(block, options)
|
||||
})
|
||||
|
||||
/**
|
||||
* 빈 줄 공백 블록 높이를 반환한다.
|
||||
* @param {Object} block - 렌더링 블록
|
||||
@@ -400,16 +412,6 @@ const normalizeInsertBelowPayload = (payload) => {
|
||||
*/
|
||||
const getMarkdownLine = (lineIndex) => String(props.content || '').split('\n')[lineIndex] ?? ''
|
||||
|
||||
/**
|
||||
* 블록에 해당하는 원본 마크다운 줄 목록을 반환한다.
|
||||
* @param {Object} block - 블록
|
||||
* @returns {string[]} 줄 목록
|
||||
*/
|
||||
const getBlockSourceLines = (block) => String(props.content || '').split('\n').slice(
|
||||
block.meta.startLine,
|
||||
(block.meta.endLine ?? block.meta.startLine) + 1
|
||||
)
|
||||
|
||||
/**
|
||||
* 인라인 편집 결과를 마크다운 줄로 반영한다.
|
||||
* @param {Object} block - 블록
|
||||
@@ -680,142 +682,6 @@ const onHeadingInsertBelow = (block, payload) => {
|
||||
commitInlineBlockLines(block, [buildHeadingLine(block.level, value), ''])
|
||||
}
|
||||
|
||||
/**
|
||||
* 인용 줄 인라인 편집 반영
|
||||
* @param {Object} block - 인용 블록
|
||||
* @param {number} lineIndex - 줄 인덱스
|
||||
* @param {string|{ value: string, raw?: boolean }} payload - 편집 내용
|
||||
* @returns {void}
|
||||
*/
|
||||
const onQuoteLineInlineCommit = (block, lineIndex, payload) => {
|
||||
const { value, raw } = normalizeCommitPayload(payload)
|
||||
const sourceLines = String(props.content || '').split('\n').slice(
|
||||
block.meta.startLine,
|
||||
(block.meta.endLine ?? block.meta.startLine) + 1
|
||||
)
|
||||
const nextLines = [...sourceLines]
|
||||
|
||||
nextLines[lineIndex] = formatQuoteLine(value, raw)
|
||||
commitInlineBlockLines(block, nextLines)
|
||||
}
|
||||
|
||||
/**
|
||||
* 인용 줄 아래에 새 인용 줄을 삽입한다.
|
||||
* @param {Object} block - 인용 블록
|
||||
* @param {number} lineIndex - 줄 인덱스
|
||||
* @returns {void}
|
||||
*/
|
||||
const onQuoteLineInsertBelow = (block, lineIndex, payload) => {
|
||||
const { value, raw, before, after, caretAtStart } = normalizeInsertBelowPayload(payload)
|
||||
const nextLines = getBlockSourceLines(block)
|
||||
|
||||
if (caretAtStart && after.length) {
|
||||
nextLines[lineIndex] = formatQuoteLine(after, raw)
|
||||
nextLines.splice(lineIndex, 0, '> ')
|
||||
pendingFocusLine.value = block.meta.startLine + lineIndex
|
||||
pendingFocusPosition.value = 'start'
|
||||
commitInlineBlockLines(block, nextLines)
|
||||
return
|
||||
}
|
||||
|
||||
if (before.length && after.length) {
|
||||
nextLines[lineIndex] = formatQuoteLine(before, raw)
|
||||
nextLines.splice(lineIndex + 1, 0, formatQuoteLine(after, raw))
|
||||
pendingFocusLine.value = block.meta.startLine + lineIndex + 1
|
||||
pendingFocusPosition.value = 'start'
|
||||
commitInlineBlockLines(block, nextLines)
|
||||
return
|
||||
}
|
||||
|
||||
if (lineIndex < nextLines.length) {
|
||||
nextLines[lineIndex] = formatQuoteLine(value, raw)
|
||||
}
|
||||
|
||||
nextLines.splice(lineIndex + 1, 0, '> ')
|
||||
pendingFocusLine.value = block.meta.startLine + lineIndex + 1
|
||||
pendingFocusPosition.value = 'start'
|
||||
commitInlineBlockLines(block, nextLines)
|
||||
}
|
||||
|
||||
/**
|
||||
* 인용 블록 원본에서 옵션 선언 줄을 반환한다.
|
||||
* @param {Object} block - 인용 블록
|
||||
* @returns {string[]} 옵션 선언 줄
|
||||
*/
|
||||
const getQuoteOptionLines = (block) => {
|
||||
const contentStartLine = getQuoteContentStartLine(block)
|
||||
|
||||
if (contentStartLine <= block.meta.startLine) {
|
||||
return []
|
||||
}
|
||||
|
||||
return getBlockSourceLines(block).slice(0, contentStartLine - block.meta.startLine)
|
||||
}
|
||||
|
||||
/**
|
||||
* 인용 본문 문자열을 마크다운 줄로 변환한다.
|
||||
* @param {Object} block - 인용 블록
|
||||
* @param {string|{ value?: string }} payload - 편집 페이로드
|
||||
* @returns {string[]} 인용 마크다운 줄
|
||||
*/
|
||||
const buildQuoteBlockLines = (block, payload) => {
|
||||
const value = typeof payload === 'string'
|
||||
? payload
|
||||
: String(payload?.value ?? '')
|
||||
const bodyLines = String(value ?? '').replace(/\r/g, '').split('\n')
|
||||
const normalizedBodyLines = bodyLines.length ? bodyLines : ['']
|
||||
|
||||
return [
|
||||
...getQuoteOptionLines(block),
|
||||
...normalizedBodyLines.map((line) => formatQuoteLine(line, false))
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* 인용 블록 편집 반영
|
||||
* @param {Object} block - 인용 블록
|
||||
* @param {string|{ value?: string }} payload - 편집 페이로드
|
||||
* @returns {void}
|
||||
*/
|
||||
const onQuoteBlockCommit = (block, payload) => {
|
||||
const normalizedPayload = typeof payload === 'object' && payload !== null
|
||||
? { ...payload, value: normalizeQuoteEditableValue(payload.value) }
|
||||
: normalizeQuoteEditableValue(payload)
|
||||
|
||||
commitInlineBlockLines(block, buildQuoteBlockLines(block, normalizedPayload))
|
||||
}
|
||||
|
||||
/**
|
||||
* 인용 블록 마지막 줄에서 아래로 이탈한다.
|
||||
* @param {Object} block - 인용 블록
|
||||
* @param {string|Object} payload - insert-below 페이로드
|
||||
* @returns {void}
|
||||
*/
|
||||
const onQuoteBlockInsertBelow = (block, payload) => {
|
||||
const { value } = normalizeInsertBelowPayload(payload)
|
||||
|
||||
onQuoteBlockCommit(block, value)
|
||||
pendingFocusPosition.value = 'start'
|
||||
pendingFocusOffset.value = 0
|
||||
onInsertBelowBlock(block, { lines: [''] })
|
||||
}
|
||||
|
||||
/**
|
||||
* 인용 블록을 일반 문단 줄로 되돌린다.
|
||||
* @param {Object} block - 인용 블록
|
||||
* @param {string|Object} payload - 편집 페이로드
|
||||
* @returns {void}
|
||||
*/
|
||||
const onQuoteBlockConvertToParagraph = (block, payload) => {
|
||||
const { value } = normalizeCommitPayload(payload)
|
||||
const lines = normalizeQuoteEditableValue(value).split('\n')
|
||||
const replacementLines = lines.length ? lines : ['']
|
||||
|
||||
pendingFocusLine.value = block.meta.startLine
|
||||
pendingFocusPosition.value = 'start'
|
||||
commitInlineBlockLines(block, replacementLines)
|
||||
}
|
||||
|
||||
/**
|
||||
* 라이브 모드에서 현재 줄을 삭제한다.
|
||||
* @param {number} lineIndex - 줄 번호
|
||||
|
||||
Reference in New Issue
Block a user