···200impl EditorDocument {
201 /// Check if a character position is within the block-syntax zone of its line.
202 fn is_in_block_syntax_zone(&self, pos: usize) -> bool {
203- if pos == 0 {
204 return true;
205 }
206207- let content_str = self.content.to_string();
208- let mut last_newline_pos: Option<usize> = None;
209-210- for (i, c) in content_str.chars().take(pos).enumerate() {
211- if c == '\n' {
212- last_newline_pos = Some(i);
213 }
214 }
215-216- let chars_from_line_start = match last_newline_pos {
217- Some(nl_pos) => pos - nl_pos - 1,
218- None => pos,
219- };
220-221- chars_from_line_start <= BLOCK_SYNTAX_ZONE
222 }
223224 /// Create a new editor document with the given content.
···695696 /// Remove text range from content and record edit info for incremental rendering.
697 pub fn remove_tracked(&mut self, start: usize, len: usize) -> LoroResult<()> {
698- let content_str = self.content.to_string();
699- let contains_newline = content_str.chars().skip(start).take(len).any(|c| c == '\n');
000700 let in_block_syntax_zone = self.is_in_block_syntax_zone(start);
701702 let result = self.content.delete(start, len);
···714715 /// Replace text in content (delete then insert) and record combined edit info.
716 pub fn replace_tracked(&mut self, start: usize, len: usize, text: &str) -> LoroResult<()> {
717- let content_str = self.content.to_string();
718- let delete_has_newline = content_str.chars().skip(start).take(len).any(|c| c == '\n');
000719 let in_block_syntax_zone = self.is_in_block_syntax_zone(start);
720721 let len_before = self.content.len_unicode();
···200impl EditorDocument {
201 /// Check if a character position is within the block-syntax zone of its line.
202 fn is_in_block_syntax_zone(&self, pos: usize) -> bool {
203+ if pos <= BLOCK_SYNTAX_ZONE {
204 return true;
205 }
206207+ // Search backwards from pos-1, only need to check BLOCK_SYNTAX_ZONE + 1 chars.
208+ let search_start = pos.saturating_sub(BLOCK_SYNTAX_ZONE + 1);
209+ for i in (search_start..pos).rev() {
210+ if self.content.char_at(i).ok() == Some('\n') {
211+ // Found newline at i, distance from line start is pos - i - 1.
212+ return (pos - i - 1) <= BLOCK_SYNTAX_ZONE;
213 }
214 }
215+ // No newline found in search range, and pos > BLOCK_SYNTAX_ZONE, so not in zone.
216+ false
00000217 }
218219 /// Create a new editor document with the given content.
···690691 /// Remove text range from content and record edit info for incremental rendering.
692 pub fn remove_tracked(&mut self, start: usize, len: usize) -> LoroResult<()> {
693+ let contains_newline = self
694+ .content
695+ .slice(start, start + len)
696+ .map(|s| s.contains('\n'))
697+ .unwrap_or(false);
698 let in_block_syntax_zone = self.is_in_block_syntax_zone(start);
699700 let result = self.content.delete(start, len);
···712713 /// Replace text in content (delete then insert) and record combined edit info.
714 pub fn replace_tracked(&mut self, start: usize, len: usize, text: &str) -> LoroResult<()> {
715+ let delete_has_newline = self
716+ .content
717+ .slice(start, start + len)
718+ .map(|s| s.contains('\n'))
719+ .unwrap_or(false);
720 let in_block_syntax_zone = self.is_in_block_syntax_zone(start);
721722 let len_before = self.content.len_unicode();