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
How to make Peritext agnostic to the underlying plain text CRDT #31
Comments
A possible solution
We need to fix the above issue without relying on the behavior of the underlying plain text CRDT. Instead, we may resort to style patches. The patches have the types of interface Patch {
type: "extend" | "shrink"
from: OpId
to: OpId
targetSpan: OpId
} If we are agnostic to the text CRDT, when the user performs insert op among a bunch of tombstones, we will lose control of where the new character ends up. However, the above dilemma example may be fixed by some new styling patches. For example, if client A inserts x before 2, A can generate a If client A inserts x after 4, A can generate a DownsidesThe styles of concurrent inserts inside the new op range are affectedIn the below example, we generate a new remove link op. However, there might be a concurrent insert before character 4, which should have the link style. But the new delete link op will remove its style unintentionally. So to avoid too many unintentional behaviors, we must associate the patch with a target id. OverheadSuppose there are n inserts, m deletes, and k styling operations. In the worst case, there will be |
Hi @zxch3n, yes, this is a known issue, and your proposal seems like a reasonable way of resolving it. We decided to accept this issue in Peritext because it's a fairly unusual edge case, it does not affect convergence, and it can easily be corrected by the user if necessary (e.g. if the user types a character at the end of a bold+link span, and the new character is neither bold nor linked, the user can easily fix up the character by making it bold manually). Also, when I tested this case in various text editors, Google Docs and Apple Pages actually didn't grow a bold span when a bold and link span ended at the same position, even though they do grow a bold span if it doesn't coincide with an end of link. The fact that popular products do this suggests that users can live with a little bit of inconsistent behaviour. |
@ept Thanks for your reply. You're right, the inconsistency is not an important issue. But I think if the solution works, it can offer two nice properties to the algorithm
|
I've implemented this idea, but its integration turns out to be too complicated to be practical. |
Unfortunately, this issue makes Peritext as it stands unsuitable for use in diamond types. I'd also love a workable answer to this problem. |
In the current implementation, Peritext needs a special behavior to fix an issue related to tombstones, as mentioned in the article. It requires the plain text CRDT to insert text after the tombstone with a special property (a tombstone that has an “after” anchor on it) to make the span expansion behavior intuitive.
peritext/src/micromerge.ts
Lines 775 to 800 in 89c162d
And there still are cases that this approach cannot fix. Normally, if we have a rich text span like
<bold><link>a</link></bold>
and insert
x
after it, the intuitive outcome would be<bold><link>a</link>x</bold>
However, it’s not always the case if there are tombstones. Imagine this case
<link><bold>1</bold>234</link>5
then we delete
234
and insert anx
character after1
.The image below illustrates the dilemma: no matter where we insert x, we cannot meet the requirements of making
x
bold and non-link.The current Peritext implementation chooses the most intuitive position: after
4
, which makesx
non-bold and non-link. While in situations without tombstones, it would be bold and non-link. Thus the same view and operation to the user might produce different results in the current Peritext implementation.The text was updated successfully, but these errors were encountered: