Repository navigation
[lexical-website][lexical-y] Documentation Update: Say what the word edit cap of text made again counts, how repeated words are kept, and drop the 30 ms figure #9652
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -818,14 +818,18 @@ person's: | |
| joined to a changed word through an inline node, with no space between, is | ||
| written again with it, and an inline node made between two changes is new | ||
| where it is put. The words kept are the longest run of words the two | ||
| texts share in the same order (where a word repeats, which of its | ||
| occurrences is kept can differ from what the update meant), wherever | ||
| that takes at most 2,048 word edits among the words both texts have, so | ||
| that the comparison stays within about 30 ms for a 5,000-word line. | ||
| Beyond that (a line made again with most of its words moved), only its | ||
| common start and end are kept. A word that is not kept is written again: | ||
| one the update moved past kept words, and beyond 2,048 edits, every word | ||
| between the first and the last change. Prefer | ||
| texts share in the same order, wherever that takes at most 2,048 word | ||
| edits among the words both texts have (words only added, or only | ||
| removed, between a start and an end those words share take none), so | ||
|
Comment on lines
+822
to
+823
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional: |
||
| that the comparison stays linear in the line's length. Where a word | ||
| repeats next to a change, which of its occurrences is kept can differ | ||
| from what the update meant: `aa bb` made again as `aa aa bb` keeps the | ||
| first `aa`, so a collaborator's concurrent edit of the old `aa` lands on | ||
| the first of the two. Beyond 2,048 edits (a line made again with most of | ||
|
Comment on lines
+825
to
+828
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional: this holds with no caret in the made text, but made text is anchored at the caret. With the caret right after the first
Comment on lines
+826
to
+828
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional: this holds without a caret, but text of nodes made again is anchored at the caret. With the caret right after the first |
||
| its words moved), only its common start and end are kept. A word that is | ||
| not kept is written again: one the update moved past kept words, and | ||
| beyond 2,048 edits, every word between the first and the last change. | ||
| Prefer | ||
| these to `setTextContent`, which sets a node's text whole: such a change | ||
| (and a change the browser makes to the DOM text, as an IME composition | ||
| does) keeps the start and end its text shares with the node's old text, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -60,7 +60,7 @@ issues and docs that carry it. | |
| | D26 | **Undo favours people taking turns over concurrent races.** Where a fix makes undo correct for sequential edits at the cost of rare races between an undo and a simultaneous edit of the same text, the sequential case wins. | Taking turns is the common case; a race with a simultaneous edit of the same text is rare. Picked on 10-28, confirmed on 10-30. | `DECIDED` | 10-30 | [#9400] | | ||
| | D27 | **Moves are a delete and a re-insert** at launch; the binding rewrites the cheaper side. Real moves within a container ([#9449], records after Yjs's unmerged `ContentMove` design) are paused and land last, backward compatible: a new layout version that older clients open read only. Move records leave tombstones, as every Yjs binding does. Moves across containers stay copies. | Every Yjs binding turns moves into delete plus insert; Yjs dropped its own move for complexity. Reliability of the rest came first. | `DECIDED` | 10-25 | [#9449], [#9455], [y.md: Limits][limits] | | ||
| | D28 | **Text identity is fixed at the source.** While a binding is attached, core records text edits (`spliceText`, insert and remove, split and merge), and text entity plugins record a grow as a move and a remake as a retype. Text only `setTextContent` or the DOM changed is diffed. The binding adds no per-case heuristics. | No binding can recover intent an API dropped; special-case rules were fragile and regressed neighbouring cases. | `DECIDED` | 10-27 | [#9483], [y.md: Edits made by code][y-code] | | ||
| | D29 | **Remade text keeps its common start and end by character**, whatever the node boundaries (y-prosemirror's `updateYText` rule), **and between two changes every run of unchanged whole words** (the longest common run of words, by a linear-space shortest edit script over the words both texts have, up to 2,048 edits, about 30 ms for a 5,000-word line; past it, only the start and end; a word the update moved is written again; a word changed only in part is written whole, so a collaborator's undone delete of its unchanged part shows twice, [#9635]), and never brings back a collaborator's delete. It replaces the word matching of [#9565]. | It is the industry-standard behaviour, and word matching glued words together and merged numbers oddly. Keeping only the start and end wrote everything between two changed words again, so a collaborator's delete there came back, and showed twice after the collaborator's undo ([#9621]). | `DECIDED` | 10-30 | [#9565], [#9598], [#9621] | | ||
| | D29 | **Remade text keeps its common start and end by character**, whatever the node boundaries (y-prosemirror's `updateYText` rule), **and between two changes every run of unchanged whole words** (the longest common run of words, by a linear-space shortest edit script over the words both texts have, up to 2,048 edits, words only added or only removed between a shared start and end taking none, linear in the line's length; past it, only the start and end; where a word repeats next to a change, which occurrence is kept follows that edit script (`aa bb` made again as `aa aa bb` keeps the first `aa`); a word the update moved is written again; a word changed only in part is written whole, so a collaborator's undone delete of its unchanged part shows twice, [#9635]), and never brings back a collaborator's delete. It replaces the word matching of [#9565]. | It is the industry-standard behaviour, and word matching glued words together and merged numbers oddly. Keeping only the start and end wrote everything between two changed words again, so a collaborator's delete there came back, and showed twice after the collaborator's undo ([#9621]). | `DECIDED` | 10-30 | [#9565], [#9598], [#9621] | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional: for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional: for |
||
| | D30 | **Diffed rewrites snap to whole words**; keystrokes and IME composition keep the exact diff. Scripts without spaces treat each character as a boundary. **A diffed insertion or deletion without a caret that the diff would put inside a word goes to the first place in the run of equal text it could be in where both its ends are at word edges** (a word deleted with the separator before it); a caret's placement, and one already at word edges, stay. | Concurrent rewrites otherwise split words. Real word segmentation is a follow-up ([#9467]). Without a caret a diff takes the common start first and put deletions inside words, so a collaborator's concurrent delete of the same word took a letter of the next one ([#9636]); the first edge keeps a word typed after a deleted word apart from the next one, as typing goes (a space, then a word). | `DECIDED` | 10-30 | [#9400], [#9467], [#9636] | | ||
| | D31 | **A list item's nested list gets an item of its own.** `NodeStructureExtension`'s list rule prevents an item holding a nested list next to other content when it is written; the binding does not repair it afterwards. | That shape lost text in outdents, Backspaces and offline merges. Preventing it at write time follows D20. | `DECIDED` | 10-26 | [#9452], [y.md: Limits][limits] | | ||
| | D32 | **List merging ignores `start`.** | Existing Lexical behaviour, intended. | `DECIDED` | 10-23 | [#9452] | | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: this reads as exempting any line whose shared words were only added or only removed, but
exactWordsstrips the shared words' common start and end once and then counts every added or removed word against the cap (Inline.ts:916-929,:858). Only one run in one place is free:w0z w1z w2zmade again with 1,100 repeats ofw2zbeforew1zand 1,100 ofw0zafter it keeps none of the three shared words; 1,000 in each place keeps all three. Maybe "(one run of words added, or removed, in one place between the start and end those words share takes none)", here, in theEXACT_EDITScomment and in D29.