Repository navigation
feat(rust): carets and RangeSelection editing - #120
Merged
Merged
Conversation
Ports caret/LexicalCaret.ts and caret/LexicalCaretUtils.ts: sibling, child and text point carets in both directions, caret ranges with their text slices, $comparePointCaretNext, $normalizeCaret, $caretFromPoint, $caretRangeFromSelection, $setSelectionFromCaretRange and $removeTextFromCaretRange. Point.isBefore now orders points on different nodes through carets, as JS does. RangeSelection and NodeSelection gain getNodes and getTextContent ($getNodesFromCaretRangeCompat), with the cached nodes cleared where JS clears them. JS's six caret classes become one PointCaret with a kind and a direction, as in the Swift port. Slots, NodeState and DecoratorNode branches are no-ops until those are ported (rust/PARITY.md). Checked in rust/: fmt, clippy -D warnings, cargo test (including getNodes/getTextContent/isBackward for 10 range selections and a node selection against output recorded from the JS package), rustdoc, cargo +1.88 check. Conformance: scripts/caret 5/5 (was waiting on carets); every other replayed case unchanged; 0 failures. Amp-Thread-ID: https://ampcode.com/threads/T-16d45229-bfa8-417a-a091-d3e3888d830d
## Description The conformance runner's script interpreter (the one that replays `scripts/*` vectors) moves to `rust/conformance/src/scripts.rs` as a public `Session`: `Session::start(script)`, `session.editor()`, and `session.run(step, snapshot)`, which returns the step's result in the field order `ops.ts` writes. The suites call `scripts::check` as before. The desktop playgrounds drive their editor through it, so a session can be exported as a script and replayed in JS. ## Test plan ### Before ``` $ cargo run -q --locked --release -p lexical-conformance | **Total** | 172 | 40 | 0 | 132 | 0 | | ``` ### After ``` $ cargo run -q --locked --release -p lexical-conformance | **Total** | 172 | 40 | 0 | 132 | 0 | | ``` Amp-Thread-ID: https://ampcode.com/threads/T-16d45229-bfa8-417a-a091-d3e3888d830d
## Description Ports the editing methods of `LexicalSelection.ts`: `insertText`, `insertRawText`, `insertNodes` (both selection kinds), `insertParagraph`, `insertLineBreak`, `removeText`, `formatText`, `toggleFormat`, `setFormat`, `setStyle`, `deleteCharacter`, `deleteWord` and `deleteLine`, with `$insertNodes` and `$selectAll`, `ParagraphNode.insertNewAfter`, and `$splitTextPointCaretSlice`. The scripts interpreter runs the `selection`, `selectAll`, `selectNodes` and `insertNodes` actions, and the conformance runner now replays `fuzz/core`. Deletion follows JS headless: past the model, JS extends the selection with the DOM's `Selection.modify`, which a headless editor doesn't have, so the update throws `window object not found`, as the vectors record. ## Test plan ### Before ``` $ cargo run -q --locked --release -p lexical-conformance | `scripts/selection` | 19 | 2 | 0 | 17 | 0 | partial | | `fuzz/core` | – | – | – | – | – | not implemented | | **Total** | 172 | 40 | 0 | 132 | 0 | | ``` ### After ``` $ cargo run -q --locked --release -p lexical-conformance | `fuzz/core` | 40 | 40 | 0 | 0 | 0 | pass | | `scripts/selection` | 19 | 19 | 0 | 0 | 0 | pass | | **Total** | 212 | 99 | 0 | 113 | 0 | | ``` The remaining 113 cases wait on node packages (rich-text, list, link, code, hashtag, overflow). Unit tests check paths no vector covers against JS's output: insertText redirects, formatText with alignment, headless deletion (120 cases), and `tokenizeRawText`. fmt, clippy, tests, rustdoc and the 1.88 check pass. Amp-Thread-ID: https://ampcode.com/threads/T-16d45229-bfa8-417a-a091-d3e3888d830d
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #119 (
rust-update); review that one first. This finishes the editing part of M1 inrust/DESIGN.md: a Rust editor can now be typed into, not only updated through node methods.What changes
caret.rs,caret_utils.rs), ported fromLexicalCaret.tsandLexicalCaretUtils.ts: sibling, child and text point carets, caret ranges and text slices,$removeTextFromCaretRange,$normalizeCaret. OnePointCarettype with a kind and a direction stands in for JS's six classes, as in Swift.Point.isBeforenow goes through carets, andRangeSelection.getNodes/getTextContentare ported for both selection kinds.insertText,insertRawText,insertNodes(both selection kinds),insertParagraph,insertLineBreak,removeText,formatText,toggleFormat,setFormat,setStyle,deleteCharacter,deleteWord,deleteLine,$insertNodesand$selectAll.Selection.modify. A headless editor has no window, so the update throwswindow object not found, and the vectors record that. A text layout will provide that step through an editor hook, as the Swift port'sSelectionMovementdoes; that comes in the next PR, with the desktop playgrounds.Sessioninrust/conformance/src/scripts.rs, so the desktop playgrounds can drive their editor with it and export a session as a vector. The runner now also replaysfuzz/core.How it was checked
In
rust/:cargo fmt --check, clippy-D warnings,cargo test, rustdoc-D warnings,cargo +1.88 check.scripts/*(6 files)fuzz/coreThe 113 waiting cases need rich-text, list, link, code, hashtag or overflow.
Paths no vector covers are unit-tested against output recorded from the real JS: insertText redirects (token, segmented and tab nodes, element points), formatText with alignment, 120 headless deletion cases,
tokenizeRawText, andgetNodes/getTextContent. I also ran a temporary 1,500-session fuzz offormatTextagainst JS, which matched on every step, but it isn't checked in.