라이브 콜아웃 선택 정렬 보정

This commit is contained in:
2026-06-04 15:29:45 +09:00
parent f048eaac2b
commit 67fbba3814
11 changed files with 100 additions and 117 deletions

View File

@@ -858,9 +858,23 @@ const focusEditableAtLine = (lineIndex, attempt = 0, cursorPosition = 'auto', ca
const matches = rendererRootRef.value
? [...rendererRootRef.value.querySelectorAll(`[data-source-line="${lineIndex}"]`)]
: []
const rangedMatches = rendererRootRef.value
? [...rendererRootRef.value.querySelectorAll('[data-source-line][data-source-line-end]')]
.filter((node) => {
const start = Number(node.getAttribute('data-source-line'))
const end = Number(node.getAttribute('data-source-line-end'))
return node.getAttribute('contenteditable') === 'true'
&& Number.isInteger(start)
&& Number.isInteger(end)
&& start <= lineIndex
&& lineIndex <= end
})
: []
const element = matches.find((node) => node.getAttribute('contenteditable') === 'true')
|| matches[0]
|| rangedMatches[0]
|| null
if (!element) {
@@ -875,8 +889,10 @@ const focusEditableAtLine = (lineIndex, attempt = 0, cursorPosition = 'auto', ca
const line = getMarkdownLine(lineIndex)
const isBlankMarker = /^>\s*$/.test(line) || /^[-*+]\s*$/.test(line) || /^\d+\.\s*$/.test(line.trim())
const elementSourceLine = Number(element.getAttribute('data-source-line'))
const isRangedLine = Number.isInteger(elementSourceLine) && elementSourceLine !== lineIndex
if (isBlankMarker || !line.trim()) {
if (!isRangedLine && (isBlankMarker || !line.trim())) {
if (element.getAttribute('contenteditable') === 'true') {
element.textContent = ''
element.innerHTML = ''
@@ -896,6 +912,23 @@ const focusEditableAtLine = (lineIndex, attempt = 0, cursorPosition = 'auto', ca
return
}
if (isRangedLine && Number.isInteger(elementSourceLine)) {
const text = readEditableTextFromElement(/** @type {HTMLElement} */ (element))
const textLines = text.length ? text.split('\n') : ['']
const targetLineIndex = Math.max(0, Math.min(lineIndex - elementSourceLine, textLines.length - 1))
const lineOffset = textLines
.slice(0, targetLineIndex)
.reduce((sum, textLine) => sum + textLine.length + 1, 0)
const lineText = textLines[targetLineIndex] ?? ''
const nextOffset = cursorPosition === 'end'
? lineOffset + lineText.length
: lineOffset
setEditableCaretOffset(/** @type {HTMLElement} */ (element), nextOffset)
element.scrollIntoView({ block: scrollBlock, inline: 'nearest' })
return
}
if (cursorPosition === 'start' || (cursorPosition === 'auto' && (isBlankMarker || !line.trim()))) {
setEditableCaretOffset(/** @type {HTMLElement} */ (element), 0)
element.scrollIntoView({ block: scrollBlock, inline: 'nearest' })