feat: editor improvements and architectural grid prototype
Multiple feature additions and improvements across the application: - NextGen Editor: drag handles, smart paste, block actions - Structured views: Kanban and table layouts for notes - Architectural Grid: new brainstorming/agent interface prototype - Flashcards: SM-2 revision algorithm with AI generation - MCP server: robustness improvements - Graph/PDF chat: fix click propagation and copy behavior - Various UI/UX enhancements and bug fixes Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,25 @@
|
||||
import { Extension } from '@tiptap/core'
|
||||
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
||||
import type { Transaction } from '@tiptap/pm/state'
|
||||
import type { Node as PMNode } from '@tiptap/pm/model'
|
||||
|
||||
const BLOCK_TYPES = ['paragraph', 'heading', 'blockquote', 'bulletList', 'orderedList', 'taskList', 'codeBlock']
|
||||
|
||||
function assignMissingBlockIds(tr: Transaction, doc: PMNode) {
|
||||
let modified = false
|
||||
doc.descendants((node, pos) => {
|
||||
if (!BLOCK_TYPES.includes(node.type.name)) return
|
||||
if (node.attrs['data-id']) return
|
||||
|
||||
tr.setNodeMarkup(pos, undefined, {
|
||||
...node.attrs,
|
||||
'data-id': generateBlockId(),
|
||||
})
|
||||
modified = true
|
||||
})
|
||||
return modified
|
||||
}
|
||||
|
||||
function generateBlockId(): string {
|
||||
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
||||
return crypto.randomUUID()
|
||||
@@ -17,6 +34,18 @@ function generateBlockId(): string {
|
||||
export const UniqueIdExtension = Extension.create({
|
||||
name: 'uniqueId',
|
||||
|
||||
onCreate({ editor }) {
|
||||
const assign = () => {
|
||||
if (editor.isDestroyed) return
|
||||
const { tr, doc } = editor.state
|
||||
if (assignMissingBlockIds(tr, doc)) {
|
||||
editor.view.dispatch(tr)
|
||||
}
|
||||
}
|
||||
assign()
|
||||
requestAnimationFrame(assign)
|
||||
},
|
||||
|
||||
addProseMirrorPlugins() {
|
||||
return [
|
||||
new Plugin({
|
||||
@@ -26,20 +55,7 @@ export const UniqueIdExtension = Extension.create({
|
||||
if (!hasDocChanged) return null
|
||||
|
||||
const { tr, doc } = newState
|
||||
let modified = false
|
||||
|
||||
doc.descendants((node, pos) => {
|
||||
if (!BLOCK_TYPES.includes(node.type.name)) return
|
||||
if (node.attrs['data-id']) return
|
||||
|
||||
tr.setNodeMarkup(pos, undefined, {
|
||||
...node.attrs,
|
||||
'data-id': generateBlockId(),
|
||||
})
|
||||
modified = true
|
||||
})
|
||||
|
||||
return modified ? tr : null
|
||||
return assignMissingBlockIds(tr, doc) ? tr : null
|
||||
},
|
||||
}),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user