에디터 공통 포커스 실행 분리
This commit is contained in:
@@ -49,6 +49,7 @@ import { useAdminMarkdownSlashMenu } from '../../composables/useAdminMarkdownSla
|
||||
import { useAdminMarkdownSlashMenuPosition } from '../../composables/useAdminMarkdownSlashMenuPosition.js'
|
||||
import { useAdminMarkdownSlashCommandActions } from '../../composables/useAdminMarkdownSlashCommandActions.js'
|
||||
import { useAdminMarkdownHistory } from '../../composables/useAdminMarkdownHistory.js'
|
||||
import { useAdminMarkdownEditorFocusActions } from '../../composables/useAdminMarkdownEditorFocusActions.js'
|
||||
import { useAdminMarkdownMediaPicker } from '../../composables/useAdminMarkdownMediaPicker.js'
|
||||
import { useAdminMarkdownFocusBridge } from '../../composables/useAdminMarkdownFocusBridge.js'
|
||||
import { useAdminMarkdownPreviewFocus } from '../../composables/useAdminMarkdownPreviewFocus.js'
|
||||
@@ -440,44 +441,6 @@ const {
|
||||
syncWriteSlashState: () => syncWriteSlashState()
|
||||
})
|
||||
|
||||
/**
|
||||
* 현재 선택 위치에 맞춰 에디터 포커스를 복원한다.
|
||||
* @param {{ start: number, end: number }|null} selection - 복원할 선택 영역
|
||||
* @returns {void}
|
||||
*/
|
||||
const restoreEditorFocusAfterHistory = (selection = null) => {
|
||||
const focusLine = selection
|
||||
? getLineIndexAtOffset(selection.start)
|
||||
: activeLogicalLineIndex.value
|
||||
|
||||
if (activeMode.value === 'write') {
|
||||
if (selection) {
|
||||
setTextareaSelection(selection.start, selection.end, { preserveScroll: true })
|
||||
return
|
||||
}
|
||||
|
||||
focusTextareaAtLine(focusLine)
|
||||
return
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
const offset = selection
|
||||
? Math.max(0, selection.start - getLineStartOffset(focusLine))
|
||||
: 0
|
||||
|
||||
focusPreviewEditableAtLine(focusLine, 0, 'auto', offset, 'center')
|
||||
})
|
||||
}
|
||||
|
||||
const {
|
||||
recordEditorHistory,
|
||||
restoreEditorHistory
|
||||
} = useAdminMarkdownHistory({
|
||||
value: markdownValue,
|
||||
lastSelectionState,
|
||||
restoreFocusAfterHistory: restoreEditorFocusAfterHistory
|
||||
})
|
||||
|
||||
/**
|
||||
* 라이브 모드에 실제로 존재하는 편집 줄로 포커스 대상을 보정한다.
|
||||
* @param {number} line - 원본 줄 번호
|
||||
@@ -596,42 +559,6 @@ const {
|
||||
focusPreviewEditableAtLine
|
||||
})
|
||||
|
||||
/**
|
||||
* 본문 작성 시작 시 포커스할 첫 줄 인덱스를 반환한다.
|
||||
* @returns {number} 줄 번호(0-based)
|
||||
*/
|
||||
const getInitialContentFocusLineIndex = () => {
|
||||
const lines = (markdownValue.value ?? '').split('\n')
|
||||
|
||||
if (!lines.length) {
|
||||
return 0
|
||||
}
|
||||
|
||||
const firstLine = lines[0]?.trim() ?? ''
|
||||
|
||||
if (/^#{1,6}\s+/.test(firstLine)) {
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 본문 작성 시작 줄이 없으면 빈 줄을 추가한다.
|
||||
* @param {number} lineIndex - 포커스할 줄
|
||||
* @returns {number} 보정된 줄 번호
|
||||
*/
|
||||
const ensureContentFocusLineExists = (lineIndex) => {
|
||||
const lines = (markdownValue.value ?? '').split('\n')
|
||||
|
||||
if (lineIndex < lines.length) {
|
||||
return lineIndex
|
||||
}
|
||||
|
||||
markdownValue.value = lines.length ? `${markdownValue.value}\n` : ''
|
||||
return lines.length
|
||||
}
|
||||
|
||||
/**
|
||||
* 작성 모드와 미리보기 모드를 전환한다.
|
||||
* @returns {void}
|
||||
@@ -818,40 +745,6 @@ onMounted(() => {
|
||||
syncBlockPanelState()
|
||||
})
|
||||
|
||||
/**
|
||||
* 본문 에디터에 포커스한다. 현재 모드(write/preview)를 유지한다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const focusFirstBlock = () => {
|
||||
const focusLine = ensureContentFocusLineExists(getInitialContentFocusLineIndex())
|
||||
|
||||
if (activeMode.value === 'preview') {
|
||||
scrollPreviewToTop()
|
||||
|
||||
nextTick(() => {
|
||||
nextTick(() => {
|
||||
focusPreviewEditableAtLine(focusLine, 0, 'start')
|
||||
})
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
const textarea = getWriteTextareaElement()
|
||||
const lineStart = getLineStartOffset(focusLine)
|
||||
|
||||
if (textarea) {
|
||||
textarea.focus()
|
||||
textarea.setSelectionRange(lineStart, lineStart)
|
||||
textarea.scrollTop = 0
|
||||
}
|
||||
|
||||
activeLogicalLineIndex.value = focusLine
|
||||
refreshCaretLogicalLine()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* textarea 선택 영역 정보를 반환한다.
|
||||
* @returns {{ start: number, end: number, value: string }} 선택 정보
|
||||
@@ -924,6 +817,32 @@ const setTextareaSelection = (start, end = start, options = {}) => {
|
||||
})
|
||||
}
|
||||
|
||||
const {
|
||||
focusFirstBlock,
|
||||
restoreEditorFocusAfterHistory
|
||||
} = useAdminMarkdownEditorFocusActions({
|
||||
activeMode,
|
||||
value: markdownValue,
|
||||
activeLogicalLineIndex,
|
||||
getWriteTextareaElement,
|
||||
getLineIndexAtOffset,
|
||||
getLineStartOffset,
|
||||
setTextareaSelection,
|
||||
focusTextareaAtLine,
|
||||
refreshCaretLogicalLine,
|
||||
scrollPreviewToTop,
|
||||
focusPreviewEditableAtLine
|
||||
})
|
||||
|
||||
const {
|
||||
recordEditorHistory,
|
||||
restoreEditorHistory
|
||||
} = useAdminMarkdownHistory({
|
||||
value: markdownValue,
|
||||
lastSelectionState,
|
||||
restoreFocusAfterHistory: restoreEditorFocusAfterHistory
|
||||
})
|
||||
|
||||
/**
|
||||
* 선택 영역을 지정 문자열로 교체한다.
|
||||
* @param {string} replacement - 대체 문자열
|
||||
|
||||
Reference in New Issue
Block a user