chore: 初始化 BlockFlow Workbench 仓库
建立前端与 Tauri 桌面端的首个版本提交,包含核心编辑器、项目文件读写、测试与构建配置。 补充 Git 忽略规则和换行规范,排除依赖、构建产物、本地运行日志与临时验证文件,方便在其他电脑继续开发。
This commit is contained in:
61
src/editor/extensions/SelectedBlockExtension.ts
Normal file
61
src/editor/extensions/SelectedBlockExtension.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { Extension } from "@tiptap/core"
|
||||
import { Plugin, PluginKey } from "@tiptap/pm/state"
|
||||
import { Decoration, DecorationSet } from "@tiptap/pm/view"
|
||||
import type { Node as ProseMirrorNode } from "@tiptap/pm/model"
|
||||
|
||||
export const selectedBlockPluginKey = new PluginKey<DecorationSet>("blockFlowSelectedBlock")
|
||||
|
||||
export const SelectedBlockExtension = Extension.create({
|
||||
name: "blockFlowSelectedBlock",
|
||||
|
||||
addStorage() {
|
||||
return {
|
||||
selectedBlockId: null as string | null
|
||||
}
|
||||
},
|
||||
|
||||
addProseMirrorPlugins() {
|
||||
return [
|
||||
new Plugin({
|
||||
key: selectedBlockPluginKey,
|
||||
state: {
|
||||
init: (_, state) => buildSelectedBlockDecorations(state.doc, this.storage.selectedBlockId as string | null),
|
||||
apply: (transaction, previous, _oldState, newState) => {
|
||||
const selectedBlockId = transaction.getMeta(selectedBlockPluginKey) as string | null | undefined
|
||||
if (selectedBlockId === undefined && !transaction.docChanged) {
|
||||
return previous
|
||||
}
|
||||
|
||||
return buildSelectedBlockDecorations(
|
||||
newState.doc,
|
||||
selectedBlockId === undefined ? (this.storage.selectedBlockId as string | null) : selectedBlockId
|
||||
)
|
||||
}
|
||||
},
|
||||
props: {
|
||||
decorations(state) {
|
||||
return selectedBlockPluginKey.getState(state)
|
||||
}
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
function buildSelectedBlockDecorations(doc: ProseMirrorNode, selectedBlockId: string | null): DecorationSet {
|
||||
if (selectedBlockId === null) {
|
||||
return DecorationSet.empty
|
||||
}
|
||||
|
||||
const decorations: Decoration[] = []
|
||||
doc.descendants((node, position) => {
|
||||
if (node.attrs.id === selectedBlockId) {
|
||||
decorations.push(Decoration.node(position, position + node.nodeSize, { class: "bf-selected-block" }))
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return DecorationSet.create(doc, decorations)
|
||||
}
|
||||
Reference in New Issue
Block a user