v0.3.6: 修复文档大纲导航Bug + 新增自动保存功能

Bug修复:
  - 文档大纲点击标题未定位到编辑器内容 (P0)
  - 根因: raw markdown字符偏移 ≠ ProseMirror文档位置
  - 改为通过 view.state.doc.descendants() 遍历节点树,
    按 heading类型名 + level + textContent 三重匹配定位

新增功能:
  - 自动保存 (2秒防抖), 仅对文件标签页生效
  - 状态栏显示 自动/保存中... 指示器

版本同步: package.json / AboutDialog / README 均更新至 v0.3.6
This commit is contained in:
thzxx
2026-06-04 14:23:27 +08:00
parent a84ccb7353
commit c34a843d5c
9 changed files with 163 additions and 14 deletions
+25 -5
View File
@@ -9,6 +9,7 @@ import { useSidebarResize } from '../../hooks/useSidebarResize'
import { useFolderOperations } from '../../hooks/useFolderOperations'
import { useAutoExpandDir } from '../../hooks/useAutoExpandDir'
import { OutlinePanel, parseHeadings } from '../OutlinePanel'
import type { Heading } from '../OutlinePanel'
import { getEditorView, useEditorStore } from '../../stores/editorStore'
import { TextSelection } from '@milkdown/prose/state'
@@ -38,14 +39,33 @@ export const Sidebar = React.memo(function Sidebar() {
return parseHeadings(activeTab.content)
}, [activeTab?.content])
// Navigate to heading position in editor
const handleHeadingNavigate = useCallback((pos: number) => {
// Navigate to heading in ProseMirror document tree
const handleHeadingNavigate = useCallback((heading: Heading, index: number) => {
const view = getEditorView()
if (!view) return
try {
const tr = view.state.tr.setSelection(
TextSelection.create(view.state.doc, pos, pos)
)
let foundPos: number | null = null
let currentIndex = 0
view.state.doc.descendants((node, pos) => {
if (foundPos !== null) return false
if (node.type.name === 'heading' && node.attrs.level === heading.level) {
if (node.textContent.trim() === heading.text) {
if (currentIndex === index) {
foundPos = pos
return false
}
currentIndex++
}
}
return true
})
if (foundPos === null) return
const tr = view.state.tr
.setSelection(TextSelection.create(view.state.doc, foundPos, foundPos))
.scrollIntoView()
view.dispatch(tr)
view.focus()
} catch {