use std::sync::LazyLock;
use regex::Regex;
static ATX_RE: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^ {0,3}#[ \t]+\S[^\n]*(?:\r?\n|$)").unwrap());
static SETEXT_RE: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^[^\n]+\r?\n {0,3}=+[ \t]*(?:\r?\n|$)").unwrap());
pub fn strip_leading_h1(body: &str) -> &str {
let bytes = body.as_bytes();
let mut cursor = 0usize;
loop {
let mut i = cursor;
while i < bytes.len() && matches!(bytes[i], b' ' | b'\t' | b'\r') {
i += 1;
}
if i < bytes.len() && bytes[i] == b'\n' {
cursor = i + 1;
} else {
break;
}
}
let rest = &body[cursor..];
if rest.is_empty() {
return body;
}
if let Some(m) = ATX_RE.find(rest) {
return &rest[m.end()..];
}
if let Some(m) = SETEXT_RE.find(rest) {
return &rest[m.end()..];
}
body
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn strips_leading_atx_h1() {
let body = "# Hello\n\nbody text\n";
assert_eq!(strip_leading_h1(body), "\nbody text\n");
}
#[test]
fn strips_leading_atx_h1_after_blank_lines() {
let body = "\n\n# Hello\n\nbody text\n";
assert_eq!(strip_leading_h1(body), "\nbody text\n");
}
#[test]
fn strips_leading_atx_h1_without_trailing_newline() {
let body = "# Hello";
assert_eq!(strip_leading_h1(body), "");
}
#[test]
fn strips_leading_setext_h1() {
let body = "Hello\n=====\n\nbody text\n";
assert_eq!(strip_leading_h1(body), "\nbody text\n");
}
#[test]
fn preserves_body_without_leading_h1() {
let body = "Just a paragraph\n\n## Subheading\n";
assert_eq!(strip_leading_h1(body), body);
}
#[test]
fn preserves_mid_document_h1() {
let body = "intro paragraph\n\n# Later heading\n\nmore body\n";
assert_eq!(strip_leading_h1(body), body);
}
#[test]
fn preserves_h2_at_start() {
let body = "## Subheading first\n\nbody\n";
assert_eq!(strip_leading_h1(body), body);
}
#[test]
fn preserves_atx_without_space() {
let body = "#Hello\n\nbody\n";
assert_eq!(strip_leading_h1(body), body);
}
#[test]
fn preserves_deeply_indented_hash() {
let body = " # Hello\n\nbody\n";
assert_eq!(strip_leading_h1(body), body);
}
#[test]
fn handles_empty_body() {
assert_eq!(strip_leading_h1(""), "");
assert_eq!(strip_leading_h1("\n\n"), "\n\n");
}
}