//! Locate inline code spans and fenced code blocks so substitution can skip //! them, preserving literal `{{ … }}` template syntax shown as examples. /// Return byte ranges of inline code spans and fenced code blocks. /// /// Public so that callers who need to reason about the same regions the /// substituter skips (a corpus lint, for instance) can share this definition /// instead of re-deriving it and drifting. pub fn code_span_ranges(input: &str) -> Vec<(usize, usize)> { let mut ranges = Vec::new(); let bytes = input.as_bytes(); let len = bytes.len(); let mut i = 0; while i < len { if bytes[i] == b'`' { let start = i; let mut tick_count = 0; while i < len && bytes[i] == b'`' { tick_count += 1; i += 1; } let mut found = false; while i < len { if bytes[i] == b'`' { let mut close_count = 0; while i < len && bytes[i] == b'`' { close_count += 1; i += 1; } if close_count == tick_count { ranges.push((start, i)); found = true; break; } } else { i += 1; } } if !found { ranges.push((start, len)); } } else { i += 1; } } ranges } #[cfg(test)] mod tests { use super::*; #[test] fn ranges_inline_code() { let input = "hello `code` world"; let ranges = code_span_ranges(input); assert_eq!(ranges.len(), 1); let (start, end) = ranges[0]; assert_eq!(&input[start..end], "`code`"); } #[test] fn ranges_fenced_code() { let input = "text\n```\ncode\n```\nmore"; let ranges = code_span_ranges(input); assert_eq!(ranges.len(), 1); let (start, end) = ranges[0]; assert!(input[start..end].starts_with("```")); assert!(input[start..end].ends_with("```")); } #[test] fn ranges_unclosed_backtick() { let input = "hello `unclosed"; let ranges = code_span_ranges(input); assert_eq!(ranges.len(), 1); assert_eq!(ranges[0], (6, input.len())); } #[test] fn no_code_spans() { assert!(code_span_ranges("no code here").is_empty()); } #[test] fn double_backticks_require_double_close() { // ``a`b`` — single ` inside must NOT close the double-tick span. let input = "``a`b``"; let ranges = code_span_ranges(input); assert_eq!(ranges.len(), 1, "the inner single ` must not close"); assert_eq!(&input[ranges[0].0..ranges[0].1], "``a`b``"); } #[test] fn mismatched_tick_counts_dont_close_span() { // Open with 1 tick, close attempt with 3 ticks: close_count=3 != tick_count=1. // Span never closes → runs to EOF. Pins `close_count == tick_count`. let input = "`code```"; let ranges = code_span_ranges(input); assert_eq!(ranges.len(), 1); assert_eq!(ranges[0], (0, input.len())); } #[test] fn multiple_disjoint_spans_get_separate_ranges() { let input = "a `one` b `two` c"; let ranges = code_span_ranges(input); assert_eq!(ranges.len(), 2); assert_eq!(&input[ranges[0].0..ranges[0].1], "`one`"); assert_eq!(&input[ranges[1].0..ranges[1].1], "`two`"); } #[test] fn unclosed_span_range_ends_at_input_len() { // Pins the `if !found { ranges.push((start, len)); }` branch. let input = "abc `unclosed"; let ranges = code_span_ranges(input); assert_eq!(ranges.len(), 1); assert_eq!(ranges[0], (4, input.len())); } }