|
@@ -1,11 +1,7 @@
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { watchDebounced } from "@vueuse/core"
|
|
import { watchDebounced } from "@vueuse/core"
|
|
|
-import {
|
|
|
|
|
- EditorState,
|
|
|
|
|
- Selection,
|
|
|
|
|
- TextSelection,
|
|
|
|
|
- type Transaction,
|
|
|
|
|
-} from "prosemirror-state"
|
|
|
|
|
|
|
+import { EditorState, Selection, type Transaction } from "prosemirror-state"
|
|
|
|
|
+import { schema } from "../lib/schema"
|
|
|
import { EditorView } from "prosemirror-view"
|
|
import { EditorView } from "prosemirror-view"
|
|
|
import { onMounted, onUnmounted, useTemplateRef, watch } from "vue"
|
|
import { onMounted, onUnmounted, useTemplateRef, watch } from "vue"
|
|
|
import { createBlockKeyboardHandler } from "../composables/useBlockKeyboardHandlers"
|
|
import { createBlockKeyboardHandler } from "../composables/useBlockKeyboardHandlers"
|
|
@@ -15,7 +11,6 @@ import {
|
|
|
} from "../composables/useMarkdownDecorations"
|
|
} from "../composables/useMarkdownDecorations"
|
|
|
import { createPatternPlugin } from "../composables/usePatternPlugin"
|
|
import { createPatternPlugin } from "../composables/usePatternPlugin"
|
|
|
import type {
|
|
import type {
|
|
|
- CloseReason,
|
|
|
|
|
PatternClosePayload,
|
|
PatternClosePayload,
|
|
|
PatternOpenPayload,
|
|
PatternOpenPayload,
|
|
|
PatternUpdatePayload,
|
|
PatternUpdatePayload,
|
|
@@ -125,14 +120,11 @@ function focusAt(cursorPosition?: "start" | "end" | number) {
|
|
|
if (!view) return
|
|
if (!view) return
|
|
|
const doc = view.state.doc
|
|
const doc = view.state.doc
|
|
|
|
|
|
|
|
- // Helper: safely create a selection at the given position.
|
|
|
|
|
- // Uses Selection.near() to avoid crashes when position falls on
|
|
|
|
|
- // node boundaries (e.g., between paragraphs). TextSelection.create()
|
|
|
|
|
- // throws fatal errors on non-textblock positions.
|
|
|
|
|
|
|
+ const v = view
|
|
|
const setSafeSelection = (pos: number) => {
|
|
const setSafeSelection = (pos: number) => {
|
|
|
const resolved = doc.resolve(pos)
|
|
const resolved = doc.resolve(pos)
|
|
|
const safeSelection = Selection.near(resolved)
|
|
const safeSelection = Selection.near(resolved)
|
|
|
- view.dispatch(view.state.tr.setSelection(safeSelection))
|
|
|
|
|
|
|
+ v.dispatch(v.state.tr.setSelection(safeSelection))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (cursorPosition === "start") {
|
|
if (cursorPosition === "start") {
|
|
@@ -337,10 +329,10 @@ onUnmounted(() => {
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
watch(
|
|
watch(
|
|
|
- () => [props.focused, props.cursorPosition],
|
|
|
|
|
|
|
+ () => [props.focused, props.cursorPosition] as const,
|
|
|
([focused, cursorPosition]) => {
|
|
([focused, cursorPosition]) => {
|
|
|
if (!view) return
|
|
if (!view) return
|
|
|
- setDecorationsFocus(!!focused)
|
|
|
|
|
|
|
+ setDecorationsFocus(focused)
|
|
|
view.dispatch(view.state.tr)
|
|
view.dispatch(view.state.tr)
|
|
|
if (focused) focusAt(cursorPosition)
|
|
if (focused) focusAt(cursorPosition)
|
|
|
},
|
|
},
|
|
@@ -358,7 +350,7 @@ watch(
|
|
|
watchDebounced(
|
|
watchDebounced(
|
|
|
() => content.value,
|
|
() => content.value,
|
|
|
(newContent) => {
|
|
(newContent) => {
|
|
|
- if (!view) return
|
|
|
|
|
|
|
+ if (!view || newContent === undefined) return
|
|
|
const currentContent = docToContent(view.state.doc)
|
|
const currentContent = docToContent(view.state.doc)
|
|
|
if (currentContent === newContent) return
|
|
if (currentContent === newContent) return
|
|
|
|
|
|