#[must_use]
pub(crate) fn strip_code_spans(line: &str) -> String {
let bytes = line.as_bytes();
let mut out = String::new();
let mut i = 0;
while i < bytes.len() {
if bytes[i] != b'`' {
let start = i;
while i < bytes.len() && bytes[i] != b'`' {
i += 1;
}
out.push_str(&line[start..i]);
continue;
}
let run_start = i;
while i < bytes.len() && bytes[i] == b'`' {
i += 1;
}
let run = i - run_start;
let mut j = i;
let mut close = None;
while j < bytes.len() {
if bytes[j] == b'`' {
let s = j;
while j < bytes.len() && bytes[j] == b'`' {
j += 1;
}
if j - s == run {
close = Some(j);
break;
}
} else {
j += 1;
}
}
match close {
Some(end) => i = end,
None => out.push_str(&line[run_start..i]),
}
}
out
}
#[cfg(test)]
mod tests {
use super::strip_code_spans;
#[test]
fn removes_single_and_multi_backtick_spans() {
assert_eq!(strip_code_spans("a `code` b"), "a b");
assert_eq!(strip_code_spans("see ``@rto:0001`` here"), "see here");
assert_eq!(strip_code_spans("x ```fenced inline``` y"), "x y");
}
#[test]
fn keeps_unmatched_backticks_and_plain_text() {
assert_eq!(strip_code_spans("no code here"), "no code here");
assert_eq!(strip_code_spans("unmatched ` tick"), "unmatched ` tick");
assert_eq!(strip_code_spans("``open ` mid"), "``open ` mid");
}
#[test]
fn preserves_utf8_outside_spans() {
assert_eq!(strip_code_spans("café `x` — ok"), "café — ok");
}
}