11import { fr } from "@codegouvfr/react-dsfr" ;
22import { useEditor , UseEditorOptions } from "@tiptap/react" ;
3- import { ReactNode } from "react" ;
3+ import { ReactNode , useEffect } from "react" ;
44import { tss } from "tss-react" ;
55
66import { editorContext } from "../contexts/editor" ;
@@ -14,6 +14,28 @@ function Provider(props: IProviderProps) {
1414 const editor = useEditor ( rest ) ;
1515 const { classes } = useStyles ( ) ;
1616
17+ // Keep the TipTap editor content in sync when the `content` prop changes.
18+ // TipTap only uses `content` at initialization; updates require an explicit command.
19+ useEffect ( ( ) => {
20+ if ( ! editor ) return ;
21+ const next = props . content ;
22+ if ( typeof next !== "string" ) return ;
23+ const ct = props . contentType ;
24+ // Determine current content based on contentType (markdown/html)
25+ type MaybeMarkdownEditor = typeof editor & { getMarkdown ?: ( ) => string } ;
26+ const mdEditor = editor as MaybeMarkdownEditor ;
27+ const current = ct === "markdown" && typeof mdEditor . getMarkdown === "function" ? mdEditor . getMarkdown ( ) : editor . getHTML ( ) ;
28+ if ( current !== next ) {
29+ // Update without emitting an update event to avoid feedback loops.
30+ const commands = editor . commands as unknown as { setMarkdown ?: ( md : string , opts ?: { emitUpdate ?: boolean } ) => void } ;
31+ if ( ct === "markdown" && typeof commands . setMarkdown === "function" ) {
32+ commands . setMarkdown ( next , { emitUpdate : false } ) ;
33+ } else {
34+ editor . commands . setContent ( next , { emitUpdate : false } ) ;
35+ }
36+ }
37+ } , [ editor , props . content , props . contentType ] ) ;
38+
1739 return (
1840 < div className = { classes . root } >
1941 < editorContext . Provider value = { editor } > { children } </ editorContext . Provider >
0 commit comments