Normalise CRLF in replace_text before computing the diff

Found while testing crates/model/src/edit.rs:420-439 (replace_text), reached from crates/engine/src/cmd/slide.rs:556 (notes)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-10-29 09:10:51 +01:00
co-authored by Claude Haiku 5.5
parent f893f6af7d
commit 9e5afc2c90
+18
View File
@@ -418,6 +418,8 @@ fn pos_of_char(body: &TextBody, mut n: usize) -> Pos {
/// keeps its run and paragraph formatting and new text takes the formatting where it lands. Text
/// that shares nothing with the old text replaces it as plain text.
pub fn replace_text(body: &mut TextBody, text: &str) {
// Normalise line endings first so the common prefix/suffix cannot split a `\r\n` pair.
let text = &text.replace("\r\n", "\n").replace('\r', "\n");
let old: Vec<char> = body.text().chars().collect();
let new: Vec<char> = text.chars().collect();
if old == new {
@@ -723,6 +725,22 @@ mod tests {
b
}
#[test]
fn replace_text_crlf_matches_from_text() {
// The kept suffix must not start inside a `\r\n` pair.
let mut b = TextBody::from_text("x\ny");
replace_text(&mut b, "z\r\ny");
assert_eq!(b.text(), "z\ny");
// CRLF in the kept prefix, and the same text with CRLF changes nothing.
let before = notes();
let mut b = before.clone();
replace_text(&mut b, "Overview\r\nFirst point\r\nSecond point");
assert_eq!(b, before);
replace_text(&mut b, "Overview\r\nFirst point\r\nSecond\rpoint");
assert_eq!(b.text(), "Overview\nFirst point\nSecond\npoint");
assert_eq!(b.paragraphs[0].runs[0].props.bold, Some(true));
}
#[test]
fn replace_text_keeps_formatting() {
let before = notes();