Cursor positions on inline block boundaries

The idea is for Wordgard to properly support plots (nodes with content) that are inline. ProseMirror mostly punted on these—you can define them, but because the library just interprets native editing behavior, and native editing behavior is weird about inline element boundaries, it was hard to make it work in a useful way. Wordgard controls more of the editing and cursor management, and should be able to make this work better.

Plots introduce new document positions on their boundaries (before/after the open/close tokens) in ways that marks don’t. My original thinking was that you don’t always want the cursor to stop there—when you style such a plot in a way that doesn’t produce an obvious extra, visually distinct cursor position inside it, it’ll just look like your cursor is failing to move when you press arrow left/right. That feels janky and makes it unclear, to the user, whether the cursor is inside or outside the node. So at the moment the code has a cursorInsideBounds option on plots that controls whether positions directly inside the node are normalized to be outside of it or not. (Note that it doesn’t work very well yet in 0.4.0. I’m working on it, which prompted this post.)

But I’m finding in practice that the mode where an inline plot doesn’t have extra cursor positions inside its bounds doesn’t work very well. It’s annoying to not be able to type at its boundaries, and if you empty such a node, you end up with a silly invisible node that you cannot type into anymore.

One possible direction would be to forbid such empty nodes, much like empty block-content nodes are disallowed. Inline plots with cursor positions inside their bounds are allowed (you can put the cursor into them and start typing), but regular inline plots cannot be empty. Could enforce this at the change-application level and automatically enforce it like the block-content constraint.

But as I was looking into that I started wondering whether this type of plots is useful enough to support. For most inline plots I can think of (mentions, placeholder tags, links-as-nodes) it wouldn’t be much of an issue to style them in such a way that you can tell the difference between inside and outside cursor positions, and the extra control provided by the ability to place the cursor on both sides of their bounds is great to have.

So I wonder—can anybody think of a use case where that type of inline plot, which looks like a mark and has no extra cursor positions, is useful?

The most compelling one I’ve been able to come up with is when you want to treat something like links as actual coherent document units, rather than markup (and thus model them as nodes rather than marks) but still style them as usual (with just an underline and color). That presentation doesn’t allow for visually distinguishing inside/outside cursor positions. But it can be made to rather easily.

I’m using such a plot for verse numbers that must have a trailing space anyway for native spellcheck to not mark each as a mispelling. It also gives nice plaintext copying.

Upon further reflection, I do want an extra cursor position at the beginning, but not a 2nd one at the end. Currently to change the first digit of a verse number it’s easiest to modify after the first digit and then go back to delete the first digit (which is similar to editing a link in ‘standard’ editors, which I’ve always disliked).

So I see a few choices to accomplish that:

  1. Remove trailing spaces and implement a custom spellcheck (I’m leaning towards this because the native spellcheck is slow and buggy when editing anyways) and either:
    1. Continue using inline plots:
      1. Verify cursorInsideBounds works with good UX (totally missed this option – thanks for telling me!)
      2. Add trailing " " using Leaf.Spec.toText
    2. Use marks:
      1. Figure out how to disallow nesting since verse numbers cannot themselves have verse numbers
      2. Figure out how to add trailing " " for both display and copying (what’s the best way? I can’t easily think of it)
  2. You add a cursorInsideBounds: 'start' | 'end' | 'both' | null so I keep the trailing spaces and choose start

I’ll try out choice 1.1 today and report back.

1.1 is the ideal solution, but today it doesn’t work on Android Chrome.

I’m going to add an extra space to the start and end until the bug is fixed.

I’ve gone with the option of dropping inline plots without extra cursor positions for the time being (subject to reevaluation in the future). I’m certain I don’t want to make this configurable per-side.

Release 0.5.0 should work much better with inline plots than 0.4.0 did. There’s a new example showing how to use them.

1 Like

The new example is nice, and the use of CSS makes moving in and out of the plot natural.
Can the plots be made draggable, so that in the example you’d be able to drag a whole key around?

I played with it both in Firefox (140.12.0esr) and in Chromium(150.0.7871.100).

Only in Firefox I observed a strange behavior: when you enter the “Ctrl” key plot from the right, so that the cursor is just after the low case “L” of “Ctrl”, the first char you type goes inside the plot, then the next char “jumps” out of the plot.
So, say you press “A” and then “B”, you’ll get “CtrlA” as the plot content, and “B” next to it, but outside the plot.

This does not happen if you get to that position from within the plot (from the left).

It does not happen in Chromium either, I observed it only in Firefox.

Browser’s don’t allow nodes with editable text in them to be draggable normally via the native drag-drop, so that would have to be implemented separately. And I guess it would have to involve adding some kind of drag handle, because clicking and dragging in the text already has a meaning (selection).

This patch should help with typing at the end of a plot in Firefox: