mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-14 19:27:07 -04:00
Text: story.replaceRange keeps the caret on a character boundary
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
e47f65a595
commit
02f187cc5d
1 file changed
+23
-2
@@ -84,8 +84,8 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
st.replace(a..b, &text);
|
||||
let len = st.len();
|
||||
if let Some(t) = sel.text.as_mut().filter(|t| t.story == sid) {
|
||||
t.anchor = t.anchor.min(len);
|
||||
t.focus = t.focus.min(len);
|
||||
t.anchor = floor_char_boundary(&st.text, t.anchor);
|
||||
t.focus = floor_char_boundary(&st.text, t.focus);
|
||||
}
|
||||
Ok(json!({"length": len}))
|
||||
})
|
||||
@@ -973,6 +973,27 @@ mod open_type_tests {
|
||||
assert_eq!(s.doc().unwrap().selection.text.unwrap().focus, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replacing_a_range_stays_on_utf8_boundaries() {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({})).unwrap();
|
||||
let r = s.execute("frame.create", &json!({"rect": [0, 0, 200, 100], "content": "text", "text": "é漢🙂x"})).unwrap();
|
||||
let sid = r["story"].clone();
|
||||
// Offsets inside 漢 (2..5) and 🙂 (5..9) snap back to the character starts: 漢 is replaced.
|
||||
s.execute("story.replaceRange", &json!({"story": sid, "start": 3, "end": 6, "text": "字"})).unwrap();
|
||||
let story = designcraft_doc::StoryId(sid.as_u64().unwrap());
|
||||
assert_eq!(s.doc().unwrap().doc.story(story).unwrap().text, "é字🙂x");
|
||||
// A caret before 🙂 (byte 5) would land inside it once é (2 bytes) is gone.
|
||||
s.execute("text.select", &json!({"story": sid, "anchor": 5})).unwrap();
|
||||
s.execute("story.replaceRange", &json!({"story": sid, "start": 0, "end": 2, "text": ""})).unwrap();
|
||||
let st = s.doc().unwrap();
|
||||
let t = st.selection.text.unwrap();
|
||||
let text = &st.doc.story(t.story).unwrap().text;
|
||||
assert_eq!(text, "字🙂x");
|
||||
assert!(text.is_char_boundary(t.anchor) && text.is_char_boundary(t.focus), "caret {t:?} in {text:?}");
|
||||
s.execute("text.move", &json!({"dir": "right"})).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn open_type_toggles_reach_the_text() {
|
||||
let mut s = Session::new();
|
||||
|
||||
Reference in new issue
Block a user