1- import { useEditor , EditorContent } from "@tiptap/react" ;
2- import StarterKit from "@tiptap/starter-kit" ;
3- import { Markdown } from "@tiptap/markdown" ;
4- import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight" ;
5- import { createLowlight , common } from "lowlight" ;
6- import { useEffect } from "react" ;
1+ import { EditorContent , useEditor } from "@tiptap/react" ;
2+ import { useEffect , useRef } from "react" ;
73import type { Note } from "../hooks/useNotes" ;
8-
9- const lowlight = createLowlight ( common ) ;
4+ import { editorExtensions , normalizeEditorContent } from "../editor" ;
105
116type Props = {
127 activeNote : Note | null ;
138 updateNoteContent : ( json : object ) => void ;
149} ;
1510
1611export function Editor ( { activeNote, updateNoteContent } : Props ) {
12+ const updateNoteContentRef = useRef ( updateNoteContent ) ;
13+
14+ useEffect ( ( ) => {
15+ updateNoteContentRef . current = updateNoteContent ;
16+ } , [ updateNoteContent ] ) ;
17+
1718 const editor = useEditor ( {
18- extensions : [
19- StarterKit . configure ( { codeBlock : false } ) ,
20- CodeBlockLowlight . configure ( { lowlight } ) ,
21- Markdown ,
22- ] ,
23- content : activeNote ?. content ?? "" ,
24- contentType : "markdown" ,
19+ extensions : editorExtensions ,
20+ content : normalizeEditorContent ( activeNote ?. content ) ,
2521 onUpdate ( { editor } ) {
26- updateNoteContent ( editor . getJSON ( ) ) ;
22+ updateNoteContentRef . current ( editor . getJSON ( ) ) ;
2723 } ,
2824 onBlur ( { editor } ) {
2925 setTimeout ( ( ) => {
@@ -32,7 +28,6 @@ export function Editor({ activeNote, updateNoteContent }: Props) {
3228 } ,
3329 } ) ;
3430
35- // Auto-focus on mount and when the window regains focus
3631 useEffect ( ( ) => {
3732 const timer = setTimeout ( ( ) => editor ?. commands . focus ( ) , 100 ) ;
3833 return ( ) => clearTimeout ( timer ) ;
@@ -44,16 +39,17 @@ export function Editor({ activeNote, updateNoteContent }: Props) {
4439 return ( ) => window . removeEventListener ( "focus" , onFocus ) ;
4540 } , [ editor ] ) ;
4641
47- // When switching notes, update editor content
4842 useEffect ( ( ) => {
49- if ( ! editor || ! activeNote ) return ;
43+ if ( ! editor ) return ;
44+
5045 const currentJson = JSON . stringify ( editor . getJSON ( ) ) ;
51- const targetContent = activeNote . content ;
46+ const targetContent = normalizeEditorContent ( activeNote ? .content ) ;
5247 const targetJson = JSON . stringify ( targetContent ) ;
48+
5349 if ( currentJson !== targetJson ) {
54- editor . commands . setContent ( targetContent as string | object , { emitUpdate : false } ) ;
50+ editor . commands . setContent ( targetContent , { emitUpdate : false } ) ;
5551 }
56- } , [ editor , activeNote ?. id ] ) ; // eslint-disable-line react-hooks/exhaustive-deps
52+ } , [ editor , activeNote ] ) ;
5753
5854 return (
5955 < EditorContent
0 commit comments