슬래시 메뉴 스크롤 계산 분리
This commit is contained in:
@@ -57,6 +57,7 @@ import {
|
||||
DEFAULT_SLASH_MENU_HEIGHT,
|
||||
DEFAULT_SLASH_MENU_WIDTH
|
||||
} from '../../lib/markdown-slash-menu-position.js'
|
||||
import { calculateSlashMenuScrollTop } from '../../lib/markdown-slash-menu-scroll.js'
|
||||
import { buildCalloutOpenerLine, CALLOUT_BACKGROUND_OPTIONS, QUOTE_BACKGROUND_OPTIONS } from '../../lib/markdown-callout.js'
|
||||
import { buildCodeFenceOpener } from '../../lib/markdown-code-block.js'
|
||||
import { buildToggleOpenerLine } from '../../lib/markdown-toggle.js'
|
||||
@@ -2497,16 +2498,12 @@ const scrollLiveSlashHighlightedIntoView = () => {
|
||||
return
|
||||
}
|
||||
|
||||
const itemTop = highlightedItem.offsetTop
|
||||
const itemBottom = itemTop + highlightedItem.offsetHeight
|
||||
const viewTop = menu.scrollTop
|
||||
const viewBottom = viewTop + menu.clientHeight
|
||||
|
||||
if (itemTop < viewTop) {
|
||||
menu.scrollTop = itemTop
|
||||
} else if (itemBottom > viewBottom) {
|
||||
menu.scrollTop = itemBottom - menu.clientHeight
|
||||
}
|
||||
menu.scrollTop = calculateSlashMenuScrollTop({
|
||||
itemTop: highlightedItem.offsetTop,
|
||||
itemHeight: highlightedItem.offsetHeight,
|
||||
viewTop: menu.scrollTop,
|
||||
viewHeight: menu.clientHeight
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
| lib/markdown-toc.js | 공개 게시글 TOC용 H1~H3 제목 추출과 앵커 ID 생성 |
|
||||
| lib/markdown-slash-commands.js | 관리자 Markdown-first 에디터 슬래시 명령 목록과 삽입 줄 정의, 미디어 명령 action 판별, 미디어 명령 지연 commit 무시·슬래시 원문 줄 교체 삽입 helper |
|
||||
| lib/markdown-slash-menu-position.js | 관리자 Markdown-first 에디터 슬래시 메뉴 뷰포트 위치 보정 helper |
|
||||
| lib/markdown-slash-menu-scroll.js | 관리자 Markdown-first 에디터 슬래시 메뉴 선택 항목 표시용 scrollTop 계산 helper |
|
||||
| lib/markdown-inline.js | 공개·관리자 공통 인라인 마크다운 파서, 링크·굵게·기울임·인라인 코드·첨자·인라인 색상 토큰(`::color[텍스트]`) 변환, 링크·굵게·기울임·색상 내부 중첩 인라인 문법과 `<br>` 줄바꿈 처리, 라이브 멀티라인 본문의 기본 불릿/번호 목록 HTML 변환과 contenteditable 목록 마커 기준 커서 offset 계산·직렬화 |
|
||||
| lib/post-tag-limit.js | 게시물별 태그 최대 개수 기본값·허용 범위·정규화 |
|
||||
| lib/analytics-shared.js | 통계 추적 경로 필터·체류/스크롤 상수(클라이언트·서버 공용) |
|
||||
@@ -123,6 +124,7 @@
|
||||
| tests/markdown-editor-history.test.js | 관리자 Markdown 에디터 undo/redo 히스토리 항목과 선택 범위 보정 단위 회귀 테스트 |
|
||||
| tests/markdown-editor-media.test.js | 관리자 Markdown 에디터 미디어 선택 helper의 종류·선택 가능 여부·미리보기·선택 상태·블록 생성 단위 회귀 테스트 |
|
||||
| tests/markdown-slash-commands.test.js | 관리자 슬래시 명령 파싱·미디어 action·포커스 대상·원문 줄 교체 삽입 단위 회귀 테스트 |
|
||||
| tests/markdown-slash-menu-scroll.test.js | 관리자 슬래시 메뉴 선택 항목 scrollTop 보정 단위 테스트 |
|
||||
| tests/markdown-block-parser.test.js | 공개 Markdown 본문 블록 파싱 단위 회귀 테스트 |
|
||||
| tests/markdown-fenced-meta.test.js | Markdown fenced 블록 시작·종료 줄 탐색, 본문 수집, 메타 파싱 단위 회귀 테스트 |
|
||||
| tests/markdown-quote.test.js | Markdown 인용 옵션 파싱과 편집 줄 변환 단위 회귀 테스트 |
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# 업데이트 이력
|
||||
|
||||
## v1.11.85
|
||||
|
||||
- 관리자 Markdown 에디터의 슬래시 메뉴 선택 항목 스크롤 계산을 `markdown-slash-menu-scroll` helper로 분리.
|
||||
- 슬래시 메뉴 선택 항목의 위·아래 스크롤 보정 단위 테스트 추가.
|
||||
|
||||
## v1.11.84
|
||||
|
||||
- 관리자 Markdown 에디터의 슬래시 메뉴 재배치 이벤트 리스너를 안정적인 참조로 정리.
|
||||
|
||||
32
lib/markdown-slash-menu-scroll.js
Normal file
32
lib/markdown-slash-menu-scroll.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 슬래시 메뉴 선택 항목이 보이도록 필요한 scrollTop을 계산한다.
|
||||
* @param {Object} options - 계산 옵션
|
||||
* @param {number} options.itemTop - 항목의 메뉴 내부 위쪽 위치
|
||||
* @param {number} options.itemHeight - 항목 높이
|
||||
* @param {number} options.viewTop - 현재 메뉴 scrollTop
|
||||
* @param {number} options.viewHeight - 메뉴 표시 높이
|
||||
* @returns {number} 적용할 scrollTop
|
||||
*/
|
||||
export const calculateSlashMenuScrollTop = ({
|
||||
itemTop,
|
||||
itemHeight,
|
||||
viewTop,
|
||||
viewHeight
|
||||
}) => {
|
||||
const safeItemTop = Number.isFinite(itemTop) ? itemTop : 0
|
||||
const safeItemHeight = Number.isFinite(itemHeight) ? Math.max(0, itemHeight) : 0
|
||||
const safeViewTop = Number.isFinite(viewTop) ? Math.max(0, viewTop) : 0
|
||||
const safeViewHeight = Number.isFinite(viewHeight) ? Math.max(0, viewHeight) : 0
|
||||
const itemBottom = safeItemTop + safeItemHeight
|
||||
const viewBottom = safeViewTop + safeViewHeight
|
||||
|
||||
if (safeItemTop < safeViewTop) {
|
||||
return Math.max(0, safeItemTop)
|
||||
}
|
||||
|
||||
if (itemBottom > viewBottom) {
|
||||
return Math.max(0, itemBottom - safeViewHeight)
|
||||
}
|
||||
|
||||
return safeViewTop
|
||||
}
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "sori.studio",
|
||||
"version": "1.11.84",
|
||||
"version": "1.11.85",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "sori.studio",
|
||||
"version": "1.11.84",
|
||||
"version": "1.11.85",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sori.studio",
|
||||
"version": "1.11.84",
|
||||
"version": "1.11.85",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"imports": {
|
||||
|
||||
40
tests/markdown-slash-menu-scroll.test.js
Normal file
40
tests/markdown-slash-menu-scroll.test.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
|
||||
import { calculateSlashMenuScrollTop } from '../lib/markdown-slash-menu-scroll.js'
|
||||
|
||||
test('슬래시 메뉴 항목이 보이는 범위 안이면 현재 scrollTop을 유지한다', () => {
|
||||
assert.equal(calculateSlashMenuScrollTop({
|
||||
itemTop: 48,
|
||||
itemHeight: 32,
|
||||
viewTop: 40,
|
||||
viewHeight: 120
|
||||
}), 40)
|
||||
})
|
||||
|
||||
test('슬래시 메뉴 항목이 위로 벗어나면 항목 위쪽으로 스크롤한다', () => {
|
||||
assert.equal(calculateSlashMenuScrollTop({
|
||||
itemTop: 20,
|
||||
itemHeight: 32,
|
||||
viewTop: 60,
|
||||
viewHeight: 120
|
||||
}), 20)
|
||||
})
|
||||
|
||||
test('슬래시 메뉴 항목이 아래로 벗어나면 항목 아래쪽이 보이도록 스크롤한다', () => {
|
||||
assert.equal(calculateSlashMenuScrollTop({
|
||||
itemTop: 180,
|
||||
itemHeight: 32,
|
||||
viewTop: 60,
|
||||
viewHeight: 120
|
||||
}), 92)
|
||||
})
|
||||
|
||||
test('슬래시 메뉴 스크롤 계산은 잘못된 숫자를 안전한 기본값으로 보정한다', () => {
|
||||
assert.equal(calculateSlashMenuScrollTop({
|
||||
itemTop: Number.NaN,
|
||||
itemHeight: -10,
|
||||
viewTop: -20,
|
||||
viewHeight: Number.POSITIVE_INFINITY
|
||||
}), 0)
|
||||
})
|
||||
Reference in New Issue
Block a user