import sys with open(sys.argv[1], 'r') as f: content = f.read() # Replace the entire NotesPage function and add NoteEditorPane old = '''function NotesPage() { const queryClient = useQueryClient(); const [search, setSearch] = useState(""); const [selectedNoteId, setSelectedNoteId] = useState(null); const [showBacklinks, setShowBacklinks] = useState(false); const [showVersions, setShowVersions] = useState(false); const selectedNoteRef = useRef(null); useRealtime({ enabled: true }); const { data: notesData, isLoading } = useApiQuery>( ["notes", search], "/notes?limit=200" + (search ? "&search=" + encodeURIComponent(search) : "") ); const notes = notesData?.items || []; const createMutation = useMutation({ mutationFn: () => api.post("/notes", { title: "Untitled", content: "" }), onSuccess: (note) => { queryClient.invalidateQueries({ queryKey: ["notes"] }); selectedNoteRef.current = note; setSelectedNoteId(note.id); }, }); const updateMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: any }) => api.patch("/notes/" + id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["notes"] }); }, }); const deleteMutation = useMutation({ mutationFn: (id: string) => api.delete("/notes/" + id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["notes"] }); selectedNoteRef.current = null; setSelectedNoteId(null); }, }); const selectNote = async (note: Note) => { try { const detail = await api.get("/notes/" + note.id); selectedNoteRef.current = detail; } catch { selectedNoteRef.current = note; } setSelectedNoteId(note.id); setShowBacklinks(false); setShowVersions(false); }; const selectedNote = selectedNoteRef.current; return (
{/* Left pane - note list */}
setSearch(e.target.value)} className="pl-8" tabIndex={-1} />
{isLoading ? (
Loading...
) : notes.length === 0 ? (
No notes yet.
) : (
{notes.map((note) => ( ))}
)}
{/* Right pane - editor */}
{selectedNote ? ( <>
Delete Note Are you sure you want to delete "{selectedNote.title}"? Cancel deleteMutation.mutate(selectedNote.id)} className="bg-destructive text-destructive-foreground">Delete
{ if (selectedNoteRef.current) { updateMutation.mutate({ id: selectedNoteRef.current.id, data: { content: html } }); } }} />
{/* Backlinks section */} {showBacklinks && selectedNote.backlinks && selectedNote.backlinks.length > 0 && (

Linked from

{selectedNote.backlinks.map((bl) => (
{bl.noteTitle}
))}
)} {/* Version history */} {showVersions && (

Version History

Version history available via API.

)} ) : (

Select a note or create a new one

)}
); }''' new = '''// Memoized right pane - only re-renders when note changes, not on parent re-renders const NoteEditorPane = memo(function NoteEditorPane({ note, onDelete }: { note: Note; onDelete: (id: string) => void }) { const [showBacklinks, setShowBacklinks] = useState(false); const [showVersions, setShowVersions] = useState(false); const queryClient = useQueryClient(); const updateMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: any }) => api.patch("/notes/" + id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["notes"] }); }, }); return ( <>
Delete Note Are you sure you want to delete "{note.title}"? Cancel onDelete(note.id)} className="bg-destructive text-destructive-foreground">Delete
{ updateMutation.mutate({ id: note.id, data: { content: html } }); }} />
{/* Backlinks section */} {showBacklinks && note.backlinks && note.backlinks.length > 0 && (

Linked from

{note.backlinks.map((bl) => (
{bl.noteTitle}
))}
)} {/* Version history */} {showVersions && (

Version History

Version history available via API.

)} ); }); function NotesPage() { const queryClient = useQueryClient(); const [search, setSearch] = useState(""); const [selectedNoteId, setSelectedNoteId] = useState(null); const selectedNoteRef = useRef(null); useRealtime({ enabled: true }); const { data: notesData, isLoading } = useApiQuery>( ["notes", search], "/notes?limit=200" + (search ? "&search=" + encodeURIComponent(search) : "") ); const notes = notesData?.items || []; const createMutation = useMutation({ mutationFn: () => api.post("/notes", { title: "Untitled", content: "" }), onSuccess: (note) => { queryClient.invalidateQueries({ queryKey: ["notes"] }); selectedNoteRef.current = note; setSelectedNoteId(note.id); }, }); const deleteMutation = useMutation({ mutationFn: (id: string) => api.delete("/notes/" + id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["notes"] }); selectedNoteRef.current = null; setSelectedNoteId(null); }, }); const selectNote = async (note: Note) => { try { const detail = await api.get("/notes/" + note.id); selectedNoteRef.current = detail; } catch { selectedNoteRef.current = note; } setSelectedNoteId(note.id); }; const selectedNote = selectedNoteRef.current; return (
{/* Left pane - note list */}
setSearch(e.target.value)} className="pl-8" tabIndex={-1} />
{isLoading ? (
Loading...
) : notes.length === 0 ? (
No notes yet.
) : (
{notes.map((note) => ( ))}
)}
{/* Right pane - editor (memoized, won't re-render on parent state changes) */}
{selectedNote ? ( deleteMutation.mutate(id)} /> ) : (

Select a note or create a new one

)}
); }''' content = content.replace(old, new, 1) with open(sys.argv[1], 'w') as f: f.write(content) print('Done')