use std::borrow::Cow;
#[must_use]
pub fn strip_markdown_fences(input: &str) -> &str {
let trimmed = input.trim();
let Some(after_open) = trimmed.strip_prefix("```") else {
return input;
};
if !trimmed.ends_with("```") {
return input;
}
let after_lang = after_open.split_once('\n').map_or("", |(_, rest)| rest);
let Some(body) = after_lang.strip_suffix("```") else {
return input;
};
body.strip_suffix('\n').unwrap_or(body)
}
#[must_use]
pub fn strip_outer_braces(input: &str) -> &str {
let trimmed = input.trim();
if !(trimmed.starts_with('{') && trimmed.ends_with('}')) {
return input;
}
let mut depth: i32 = 0;
let mut close_pos = None;
for (i, ch) in trimmed.char_indices() {
match ch {
'{' => depth += 1,
'}' => {
depth -= 1;
if depth == 0 {
close_pos = Some(i);
break;
}
}
_ => {}
}
}
match close_pos {
Some(pos) if pos == trimmed.len() - 1 => {
&trimmed[1..trimmed.len() - 1]
}
_ => input,
}
}
#[must_use]
pub fn normalize_line_endings(input: &str) -> Cow<'_, str> {
if input.contains("\r\n") {
Cow::Owned(input.replace("\r\n", "\n"))
} else {
Cow::Borrowed(input)
}
}
#[must_use]
pub fn normalize_for_body_replace(input: &str) -> String {
let step1 = strip_markdown_fences(input);
let step2 = strip_outer_braces(step1);
normalize_line_endings(step2).into_owned()
}
#[must_use]
pub fn normalize_for_full_replace(input: &str) -> String {
let step1 = strip_markdown_fences(input);
normalize_line_endings(step1).into_owned()
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used)]
mod tests {
use super::*;
#[test]
fn test_strip_markdown_fences_with_lang() {
let input = "```rust\nfn hello() {}\n```";
assert_eq!(strip_markdown_fences(input), "fn hello() {}");
}
#[test]
fn test_strip_markdown_fences_no_lang() {
let input = "```\nfn hello() {}\n```";
assert_eq!(strip_markdown_fences(input), "fn hello() {}");
}
#[test]
fn test_strip_markdown_fences_passthrough_no_fences() {
let input = "fn hello() {}";
assert_eq!(strip_markdown_fences(input), "fn hello() {}");
}
#[test]
fn test_strip_markdown_fences_passthrough_partial() {
let input = "```rust\nfn hello() {}";
assert_eq!(strip_markdown_fences(input), input);
}
#[test]
fn test_strip_markdown_fences_opening_only_no_closing() {
let input = "```rust\nfn main() {}\n// no closing fence";
let result = strip_markdown_fences(input);
assert_eq!(result, input); }
#[test]
fn test_strip_markdown_fences_multiline() {
let input = "```typescript\nconst x = 1;\nconst y = 2;\n```";
assert_eq!(strip_markdown_fences(input), "const x = 1;\nconst y = 2;");
}
#[test]
fn test_strip_outer_braces_simple() {
let input = "{ return 42; }";
assert_eq!(strip_outer_braces(input), " return 42; ");
}
#[test]
fn test_strip_outer_braces_multiline() {
let input = "{\n x := 1\n return x\n}";
let result = strip_outer_braces(input);
assert_eq!(result, "\n x := 1\n return x\n");
}
#[test]
fn test_strip_outer_braces_nested_inner_preserved() {
let input = "{ if (x) { y } }";
let result = strip_outer_braces(input);
assert_eq!(result, " if (x) { y } ");
}
#[test]
fn test_strip_outer_braces_not_wrapped() {
let input = "return 42;";
assert_eq!(strip_outer_braces(input), "return 42;");
}
#[test]
fn test_strip_outer_braces_unmatched() {
let input = "{ x } something }";
assert_eq!(strip_outer_braces(input), "{ x } something }");
}
#[test]
fn test_normalize_crlf_to_lf() {
let input = "line1\r\nline2\r\nline3";
let result = normalize_line_endings(input);
assert_eq!(result.as_ref(), "line1\nline2\nline3");
}
#[test]
fn test_normalize_already_lf_is_borrowed() {
let input = "line1\nline2";
let result = normalize_line_endings(input);
assert!(matches!(result, Cow::Borrowed(_)));
}
#[test]
fn test_normalize_full_pipeline_fence_and_braces() {
let input = "```go\n{ return 42; }\n```";
let result = normalize_for_body_replace(input);
assert_eq!(result, " return 42; ");
}
#[test]
fn test_normalize_full_pipeline_plain_code() {
let input = "x := compute()\nreturn x";
let result = normalize_for_body_replace(input);
assert_eq!(result, "x := compute()\nreturn x");
}
#[test]
fn test_normalize_full_pipeline_crlf() {
let input = "x := 1\r\nreturn x";
let result = normalize_for_body_replace(input);
assert_eq!(result, "x := 1\nreturn x");
}
#[test]
fn test_strip_markdown_fences_inline_no_newline_returns_input() {
let input = "```code```";
assert_eq!(
strip_markdown_fences(input),
input,
"inline fence with no newline must be returned unchanged"
);
}
#[test]
fn test_strip_markdown_fences_only_opening_and_closing_no_body() {
let input = "```\n```";
let result = strip_markdown_fences(input);
assert_eq!(result, "", "empty-body fence must strip to empty string");
}
#[test]
fn test_normalize_for_full_replace_does_not_strip_braces() {
let input = "{ return 42; }";
let result = normalize_for_full_replace(input);
assert_eq!(
result, input,
"normalize_for_full_replace must preserve outer braces"
);
}
#[test]
fn test_normalize_for_full_replace_strips_fence_and_crlf() {
let input = "```go\r\nfunc Hello() {}\n```";
let result = normalize_for_full_replace(input);
assert_eq!(result, "func Hello() {}");
}
}