I’m working on migrating my plugin, Mermaid Studio, to the new split architecture and it uses a TextEditorWithPreview with an interactive JCEF preview panel to display an interactive Mermaid diagram editor beside the text editor. By and large, the overall editor architecture mirrors the Markdown plugin, but it seems that the composite editor is being rendered on the backend and streamed instead of rendering on the client.
Everything I’ve seen so far indicates that the logic behind where composite editors get rendered lives inside the closed remote client/server jars.
Is there any way currently for third-party plugins to supply composite editors that are rendered on the client?
The first advice we can give is that all new code needs FileEditorProvider implemented in frontend module, so UI lives in client. Markdown plugin is rather bad example because it has a lot of intrinsic support code in JetBrains Client side (as implemented long time ago)
If I register the MermaidSplitEditorProvider frontend only, MermaidEditorWithPreview doesn’t get created for any remote files, only for files created on the client (e.g., scratch files, perhaps LightVirtualFile).
If I register in shared or backend, it loads on the backend and streams to the client for remote files. If it’s in shared, I actually get the client-loaded experience for scratch files and backend streamed experience for remote/project files in the same running IDE instance.
If markdown is a bad example, is there a better example plugin containing a custom/composite editor that ships on the frontend and actually loads correctly?
As it stands, I’m stuck shoving my editor and related EP registrations into a shared module despite having already wired them up for RPC since any file opened by the backend loads the editor on the backend and streams it to the client and any file opened by the client (in-memory files like scratch files) loads it from the frontend, so I end up having to fully support both back and frontend driven flows. Otherwise running in split mode will either be missing complete support (whether it’s a missing preview pane or something like formatters not executing on files opened from the non-wired side of the plugin).
The weird split I was seeing between scratch files and project files was due to a misplaced mermaid-specific scratch file creation action. Having resolved that by registering the action on both sides, the editor is now consistently backend rendered.
As far as I can tell, there’s no way for a third party plugin to render a custom editor, especially a composite on the front end. As @yuriy.artamonov mentioned, Markdown is a special case that, as far as I can tell, likely has support built into the client that enables it to render its composite editor on the frontend.
That leaves me with an initial split that looks like the following:
Editor streamed from backend
Editor actions require a custom toolbar since backend editor actions don’t get loaded on the frontend
Editor-related EPs join the editor on the backend (formatters, enter handlers, etc.)
I had some swing popups the overlaid on top of diagram preview JCEF panel (context menu, shape picker for flowcharts) that I ended up rewriting as part of the preview web app (with LAF driven styles) for split mode to minimize risk of composition issues with the streamed editor. The HTML components are identically styled to their swing counterparts.
Tool window panes live on the frontend and use custom RPC to push updates from the backend to the tool window and push changes to the backend. This gives them better UI responsiveness and fidelity than Lux-based pixel streaming. Custom rendered swing components make model-based streaming (BeControl) a non-option. It also happens that the plugin’s element style pane is usable in both standalone mermaid diagrams and also inside markdown code fences. Since the markdown editor lives on the frontend, the style pane makes use of the plugin’s original direct-psi read/write approach. This same direct-psi read/write approach is also used globally in monolith mode (the RPC path exists solely for standalone diagrams in split mode).
A great deal more than I’d initially expected ended up in shared modules that load on front and backend processes. There’s plenty that I didn’t cover here (mostly backend pieces and areas like settings placement/sync).
The key enabler for this refactor was implementing a fairly comprehensive e2e test suite that runs in both monolith and split mode to surface both capability discrepancies between the two modes and regressions that arose as a result of either the initial split mode refactor or subsequent EP relocations/rewrites.
This is likely the shape that’ll land in my plugin’s first split-mode release, but I wouldn’t be surprised if the shape looks different a year from now.