Bug: Multiple ProseMirror editors on same svelte component do not save properly

Simple reproduction in a foundry world with at least one actor defined:
<svelte:options accessors={true} />

<script>
import { ApplicationShell } from "#runtime/svelte/component/core";
import { TJSDocument } from "#runtime/svelte/store/fvtt/document";
import { TJSProseMirror } from "#standard/component";

export let elementRoot;

let actor = new TJSDocument(game.actors.contents[0]);
let base_options = {
document: $actor,
fieldName: "name",
collaborate: true,
button: false,
editable: true,
initialSelection: "start",
};
</script>

<ApplicationShell bind:elementRoot>
<main>
<h1>Basic application</h1>
<span>{$actor.name}</span>
<TJSProseMirror options={base_options} />
<TJSProseMirror options={base_options} />
</main>
</ApplicationShell>

<style lang="scss">
main {
text-align: center;
display: flex;
flex-direction: column;
}
</style>
<svelte:options accessors={true} />

<script>
import { ApplicationShell } from "#runtime/svelte/component/core";
import { TJSDocument } from "#runtime/svelte/store/fvtt/document";
import { TJSProseMirror } from "#standard/component";

export let elementRoot;

let actor = new TJSDocument(game.actors.contents[0]);
let base_options = {
document: $actor,
fieldName: "name",
collaborate: true,
button: false,
editable: true,
initialSelection: "start",
};
</script>

<ApplicationShell bind:elementRoot>
<main>
<h1>Basic application</h1>
<span>{$actor.name}</span>
<TJSProseMirror options={base_options} />
<TJSProseMirror options={base_options} />
</main>
</ApplicationShell>

<style lang="scss">
main {
text-align: center;
display: flex;
flex-direction: column;
}
</style>
The top editor save button will do nothing. In general, it seems like only the last editor's save button actually works. When the components are unmounted, save works normally. This issue persists even if the editors are targeting different fieldNames.
14 Replies
TyphonJS (Michael)
I'll have to take a look as TJSProseMirror does utilize the underlying Foundry support for controlling the editor / menu is the Foundry core support. I do load a custom plugin related to saving / changing key commands, but will need to investigate. Hopefully tomorrow I can take a look and include this in the next release.
WHITESPINE
WHITESPINEOP16mo ago
The Paragraph/Font panels also appear to have no effect, in the same minimal configuration pasted above.
TyphonJS (Michael)
I gather this potentially will be on the more challenging side of things due to the fact that TJSProseMirror is embedding the Foundry implementation of PM thus there is less direct control involved. IE the menu bar is not directly controlled or created by the component, so aspects involved in making sure there are not conflicts between multiple component usages may not be straightforward to solve. I don't want to hold up the next release to finish this up, so I'll likely push this to October though I'll try and do some initial engineering analysis before then. If you happen to have spare time to keep poking at things to get a better idea of what may be occurring that can help as well.
WHITESPINE
WHITESPINEOP16mo ago
Can't promise much there honestly I tried to trace it through but I have almost no idea where the actual element is being passed in I can try again though Paragraph/Font appears to be a firefox only issue
TyphonJS (Michael)
Is that also the case for normal Foundry & Firefox?
WHITESPINE
WHITESPINEOP16mo ago
I'll check when I get home assuming 5e system uses it The event listeners are getting setup properly they just aren't actually firing Same foundry install 5E prosemirror editors work. Additionally, even within the TJS world / dev server, utilizing the Journal prosemirrors work. I haven't really observed anything different in how they initialize listeners There's a specific prosemirror.js function that actually sets up the paragraph/font dropdowns:
/**
* Attach event listeners.
* @param {HTMLMenuElement} html The root menu element.
*/
activateListeners(html) {
if ( !this.#onAction ) return;
html.querySelectorAll(`.pm-dropdown.${this.#cssClass} li`).forEach(item => {
item.addEventListener("click", event => {
this.#onAction(event);
});
});
}
/**
* Attach event listeners.
* @param {HTMLMenuElement} html The root menu element.
*/
activateListeners(html) {
if ( !this.#onAction ) return;
html.querySelectorAll(`.pm-dropdown.${this.#cssClass} li`).forEach(item => {
item.addEventListener("click", event => {
this.#onAction(event);
});
});
}
For the listeners are being created in the TJS ProseMirror, but for whatever reason the events are never being fired My best guess was that something in the wrapping component was capturing or intercepting clicks but it doesn't really seem like that is the case Another wrinkle: Setting button to true and individually summoning each ProseMirror appears to resolve the save-aliasing issue.
TyphonJS (Michael)
Core could have changed how they implemented the PM support. Perhaps I just have to find a way to set a unique cssClass per component as that seems like the only problem. Though presumably html is just the menu element, but if it's somehow say the whole page or an element higher in the DOM then a unique CSS class would be needed. I'll take a look as that could be easy to fix. I'm done with all the other work for the next release.
TyphonJS (Michael)
So, from some cursory analysis there are various things that work and don't work when two editors are initialized. I'm just working w/ the basic example directly binding the content from the essential-svelte-esm demo and not a more complex setup. As things go this is going to take quite a bit of intense work diving into PM and furthermore working out all the details of the Foundry PM implementation. I of course did a fair amount of that a while back for the initial component implementation. This is not going to be something I can easily work on while traveling and is better suited to sustained full time effort, so I'll have to push things to the next release and not hold up the current release. I can potentially poke around at things for the coming month, but it might be early October before I can set aside dedicated blocks of time again as working with PM is not easy per se as you have to understand the internals of PM and what Foundry core is doing with it as well. IE no quick fix.
No description
TyphonJS (Michael)
If there is any consolation is that the TJSTinyMCE component works just fine seemingly w/ multiple editors, but that is to be expected from a fully blown / mature RTE which the Foundry core PM implementation is far from being mature. The only thing you'd be missing from the TJSTinyMCE implementation is potentially collaboration. I designed both editor components to take essentially the same configuration setup. In the meantime you can pretty easily work with the TJSTinyMCE component and more or less swap it to the PM one when the work is complete on hardening the PM component support.
WHITESPINE
WHITESPINEOP16mo ago
Thanks, I'll just use mce then for the time being
TyphonJS (Michael)
So, I'm debugging things presently. The Foundry ProseMirror implementation is just junk and buggy. The keymaps / control implementation internally to prosemirror.js does not respect independent editors and this affects the stock Foundry apps as well. IE the last opened editor is always the target of special key entry for instance. In the attached video I am opening two stock Foundry item instances for editing. A -> B. Then going back to A and hitting Ctrl-S this will save B instead of A. Hit Ctrl-S again from A and it tries to save B again. This indicates there is poor management inside of prosemirror.js for handling multiple open editors at the same time. It likely extends beyond just keymaps and includes other symptoms that you see. I'm going to try and work around this by always closing / saving any open editor when a new TJSProseMirror editor component is opened for editing. This won't help any of the Foundry core editors that might be open too. For system developers this will help for the most part until the core team fixes this major PM issue. The real solution is for a patch to the Foundry core implementation. It's just another PM implementation bug / lack of testing on the core teams part. I have zero belief that the PM based editor will ever be any good; at least any time soon.
TyphonJS (Michael)
https://github.com/foundryvtt/foundryvtt/issues/10139 On the latest v11.313 build w/ multiple editors opened clicking on the Save toolbar button seems to work correctly. I think your initial report indicated that they don't, but I believe you also were talking about Ctrl-s / key handling. The next TRL release will have a lot of general hardening improvements including the editors.
WHITESPINE
WHITESPINEOP15mo ago
Tbh I didn't know ctrl+s worked - I was simply referring to the buttons. That's an improvement, at least
TyphonJS (Michael)
Yeah, it can be a mess as each Foundry release / point releases things may change under the hood and w/ the PM work constantly being ongoing it's not something that is easy to track. I just loaded up v10.291 and it seems like the toolbar buttons save correctly when multiple editors are open. Nonetheless the solution for best current support w/ the next TRL release is to only allow one TJSProseMirror editor open at a time. When the next TRL release is out it would be great to get some hammering away on the editor components to find anything additionally that can be fixed. I put in a lot of testing and hardening especially around PopOut support, but for the PM angle it certainly can be temperamental given how it is being developed.
Want results from more Discord servers?
Add your server