···200200impl EditorDocument {
201201 /// Check if a character position is within the block-syntax zone of its line.
202202 fn is_in_block_syntax_zone(&self, pos: usize) -> bool {
203203- if pos == 0 {
203203+ if pos <= BLOCK_SYNTAX_ZONE {
204204 return true;
205205 }
206206207207- let content_str = self.content.to_string();
208208- let mut last_newline_pos: Option<usize> = None;
209209-210210- for (i, c) in content_str.chars().take(pos).enumerate() {
211211- if c == '\n' {
212212- last_newline_pos = Some(i);
207207+ // Search backwards from pos-1, only need to check BLOCK_SYNTAX_ZONE + 1 chars.
208208+ let search_start = pos.saturating_sub(BLOCK_SYNTAX_ZONE + 1);
209209+ for i in (search_start..pos).rev() {
210210+ if self.content.char_at(i).ok() == Some('\n') {
211211+ // Found newline at i, distance from line start is pos - i - 1.
212212+ return (pos - i - 1) <= BLOCK_SYNTAX_ZONE;
213213 }
214214 }
215215-216216- let chars_from_line_start = match last_newline_pos {
217217- Some(nl_pos) => pos - nl_pos - 1,
218218- None => pos,
219219- };
220220-221221- chars_from_line_start <= BLOCK_SYNTAX_ZONE
215215+ // No newline found in search range, and pos > BLOCK_SYNTAX_ZONE, so not in zone.
216216+ false
222217 }
223218224219 /// Create a new editor document with the given content.
···695690696691 /// Remove text range from content and record edit info for incremental rendering.
697692 pub fn remove_tracked(&mut self, start: usize, len: usize) -> LoroResult<()> {
698698- let content_str = self.content.to_string();
699699- let contains_newline = content_str.chars().skip(start).take(len).any(|c| c == '\n');
693693+ let contains_newline = self
694694+ .content
695695+ .slice(start, start + len)
696696+ .map(|s| s.contains('\n'))
697697+ .unwrap_or(false);
700698 let in_block_syntax_zone = self.is_in_block_syntax_zone(start);
701699702700 let result = self.content.delete(start, len);
···714712715713 /// Replace text in content (delete then insert) and record combined edit info.
716714 pub fn replace_tracked(&mut self, start: usize, len: usize, text: &str) -> LoroResult<()> {
717717- let content_str = self.content.to_string();
718718- let delete_has_newline = content_str.chars().skip(start).take(len).any(|c| c == '\n');
715715+ let delete_has_newline = self
716716+ .content
717717+ .slice(start, start + len)
718718+ .map(|s| s.contains('\n'))
719719+ .unwrap_or(false);
719720 let in_block_syntax_zone = self.is_in_block_syntax_zone(start);
720721721722 let len_before = self.content.len_unicode();