diff --git a/apps/desktop/src/components/main/body/sessions/note-input/enhanced/editor.tsx b/apps/desktop/src/components/main/body/sessions/note-input/enhanced/editor.tsx index 85a32bb85..abb782a32 100644 --- a/apps/desktop/src/components/main/body/sessions/note-input/enhanced/editor.tsx +++ b/apps/desktop/src/components/main/body/sessions/note-input/enhanced/editor.tsx @@ -2,7 +2,7 @@ import { forwardRef, useEffect, useMemo, useState } from "react"; import { type JSONContent, TiptapEditor } from "@hypr/tiptap/editor"; import NoteEditor from "@hypr/tiptap/editor"; -import { EMPTY_TIPTAP_DOC } from "@hypr/tiptap/shared"; +import { EMPTY_TIPTAP_DOC, isValidTiptapContent } from "@hypr/tiptap/shared"; import * as main from "../../../../../../store/tinybase/main"; @@ -19,7 +19,12 @@ export const EnhancedEditor = forwardRef< const value = store.getCell("enhanced_notes", enhancedNoteId, "content"); if (value && typeof value === "string" && value.trim()) { try { - setInitialContent(JSON.parse(value)); + const parsed = JSON.parse(value); + if (isValidTiptapContent(parsed)) { + setInitialContent(parsed); + } else { + setInitialContent(EMPTY_TIPTAP_DOC); + } } catch { setInitialContent(EMPTY_TIPTAP_DOC); } diff --git a/apps/desktop/src/components/main/body/sessions/note-input/raw.tsx b/apps/desktop/src/components/main/body/sessions/note-input/raw.tsx index 7e020bd06..4099a98db 100644 --- a/apps/desktop/src/components/main/body/sessions/note-input/raw.tsx +++ b/apps/desktop/src/components/main/body/sessions/note-input/raw.tsx @@ -6,6 +6,7 @@ import NoteEditor, { } from "@hypr/tiptap/editor"; import { EMPTY_TIPTAP_DOC, + isValidTiptapContent, type PlaceholderFunction, } from "@hypr/tiptap/shared"; @@ -25,7 +26,12 @@ export const RawEditor = forwardRef< const value = store.getCell("sessions", sessionId, "raw_md"); if (value && typeof value === "string" && value.trim()) { try { - setInitialContent(JSON.parse(value)); + const parsed = JSON.parse(value); + if (isValidTiptapContent(parsed)) { + setInitialContent(parsed); + } else { + setInitialContent(EMPTY_TIPTAP_DOC); + } } catch { setInitialContent(EMPTY_TIPTAP_DOC); } diff --git a/packages/tiptap/src/editor/index.tsx b/packages/tiptap/src/editor/index.tsx index 9320e8c9f..2efd0e7cb 100644 --- a/packages/tiptap/src/editor/index.tsx +++ b/packages/tiptap/src/editor/index.tsx @@ -100,7 +100,9 @@ const Editor = forwardRef<{ editor: TiptapEditor | null }, EditorProps>( { extensions, editable, - content: initialContent || shared.EMPTY_TIPTAP_DOC, + content: shared.isValidTiptapContent(initialContent) + ? initialContent + : shared.EMPTY_TIPTAP_DOC, onCreate: ({ editor }) => { editor.view.dom.setAttribute("spellcheck", "false"); editor.view.dom.setAttribute("autocomplete", "off"); @@ -129,7 +131,7 @@ const Editor = forwardRef<{ editor: TiptapEditor | null }, EditorProps>( previousContentRef.current = initialContent; if (setContentFromOutside) { const { from, to } = editor.state.selection; - if (initialContent) { + if (shared.isValidTiptapContent(initialContent)) { editor.commands.markNewContent(); } @@ -137,7 +139,7 @@ const Editor = forwardRef<{ editor: TiptapEditor | null }, EditorProps>( editor.commands.setTextSelection({ from, to }); } } else if (!editor.isFocused) { - if (initialContent) { + if (shared.isValidTiptapContent(initialContent)) { editor.commands.setContent(initialContent, { parseOptions: { preserveWhitespace: "full" }, }); diff --git a/packages/tiptap/src/shared/utils.ts b/packages/tiptap/src/shared/utils.ts index bcbd9b8dd..c677e65f8 100644 --- a/packages/tiptap/src/shared/utils.ts +++ b/packages/tiptap/src/shared/utils.ts @@ -7,6 +7,15 @@ import { getExtensions } from "./extensions"; export const EMPTY_TIPTAP_DOC: JSONContent = { type: "doc", content: [] }; +export function isValidTiptapContent(content: unknown): content is JSONContent { + if (!content || typeof content !== "object") { + return false; + } + + const obj = content as Record; + return obj.type === "doc" && Array.isArray(obj.content); +} + const turndown = new TurndownService({ headingStyle: "atx" }); turndown.addRule("p", {