-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
handling changes to prosemirror stored marks #2
Comments
Yeah I've been trying to think of a nice way to deal with this. What do you mean by "look at the current stored marks state"? You mean do something like immediately after inserting, check the stored marks and if there is no stored mark but automerge expands an existing mark then unmark the newly inserted character? |
Yes, there are two cases to handle: (1) Automerge has extended a mark with 'after' however the corresponding stored mark has been cleared in the editor Here's a video showing the desired behavior: In my current prototype here's how I'm handling both (this code would be right after the // collect the stored marks at the selection and the inserted marks
const storedMarks = tr.selection.$head.marks();
const insertedMarks = Automerge.marks(doc, kDocContentKey).filter(
(m) => m.value !== null && m.start <= from && m.end >= from
);
// remove any inserted marks that are not in set of stored marks at the selection
for (const mark of insertedMarks) {
if (!storedMarks.find(storedMark => storedMark.type.name === mark.name)) {
const expand = schema.marks[mark.name].spec.inclusive === false ? 'none' : 'after';
Automerge.unmark(
doc,
[kDocContentKey],
{ expand, start: from, end: from + insertedContent.length },
mark.name
)
}
}
// apply any stored marks that were not included in the inserted marks
for (const mark of storedMarks) {
if (!insertedMarks.find(insertedMark => insertedMark.name === mark.type.name)) {
const expand = mark.type.spec.inclusive === false ? 'none' : 'after';
Automerge.mark(
doc,
[kDocContentKey],
{ expand, start: from, end: from + insertedContent.length },
mark.type.name,
JSON.stringify(mark.attrs)
)
}
} Note that this code likely only handles single character typing insertions correctly (a paste at the cursor may need more sophisticated logic). There also might be a much more elegant way to do this that eludes me (or perhaps some additional construct in Automerge that makes this unnecessary). |
In creating a similar prototype, one additional case I ended up needing to handle was mapping the current Prosemirror stored marks state when intercepting Prosemirror transactions and applying them as Automerge doc changes.
For example, if the user's cursor is located at the end of a
bold
mark withexpand: after
and they insert a character, this will normally extend the bold mark in both Prosemirror and Automerge (so far so good). However, if the user toggles the "Bold" command off prior to inserting the character, this updates the Prosemirror "stored marks" state (removing bold from it). This implies that subsequent insertions should not expand the mark (because bold was toggled off).Similarly, if the user is in the middle of plain text and they execute the "Bold" command (with no selection) it updates the Prosemirror stored marks so that subsequent characters will be bold.
Perhaps this can be modeled in Automerge by marking/unmarking an "empty" selection at the cursor position? Or perhaps the splice logic just needs to look at the current stored marks state (that's what I did to start with).
Note that a Prosemirror transaction that updates the current stored marks will have
tr.storedMarksSet === true
(and will have the actual stored marks toggled intr.storedMarks
).The text was updated successfully, but these errors were encountered: