pub fn slugify(s: &str) -> String {
let mut out = String::new();
let mut prev_dash = false;
for ch in s.chars() {
if ch.is_ascii_alphanumeric() {
out.push(ch.to_ascii_lowercase());
prev_dash = false;
} else if ch.is_ascii() && !prev_dash {
out.push('-');
prev_dash = true;
}
}
out.trim_matches('-').to_string()
}
pub fn split_h2_sections(content: &str) -> Vec<(String, String)> {
let mut sections: Vec<(String, String)> = Vec::new();
let mut cur: Option<(String, Vec<&str>)> = None;
for line in content.lines() {
if let Some(rest) = line.strip_prefix("## ") {
if let Some((h, body)) = cur.take() {
sections.push((h, body.join("\n").trim().to_string()));
}
cur = Some((rest.trim().to_string(), Vec::new()));
} else if let Some((_, body)) = cur.as_mut() {
body.push(line);
}
}
if let Some((h, body)) = cur {
sections.push((h, body.join("\n").trim().to_string()));
}
sections
}