use turbovault_core::{Heading, LineIndex};
#[deprecated(
since = "1.2.0",
note = "Use turbovault_parser::parse_headings() instead"
)]
pub fn parse_headings(content: &str) -> Vec<Heading> {
crate::parse_headings(content)
}
#[deprecated(
since = "1.2.0",
note = "Use turbovault_parser::parse_headings() instead"
)]
#[allow(deprecated)]
pub fn parse_headings_indexed(content: &str, _index: &LineIndex) -> Vec<Heading> {
crate::parse_headings(content)
}
#[cfg(test)]
#[allow(deprecated)]
mod tests {
use super::*;
#[test]
fn test_h1_heading() {
let content = "# Main Title";
let headings = parse_headings(content);
assert_eq!(headings.len(), 1);
assert_eq!(headings[0].level, 1);
assert_eq!(headings[0].text, "Main Title");
}
#[test]
fn test_h2_heading() {
let content = "## Section";
let headings = parse_headings(content);
assert_eq!(headings.len(), 1);
assert_eq!(headings[0].level, 2);
}
#[test]
fn test_heading_anchor_generation() {
let content = "# This is a Long Title!";
let headings = parse_headings(content);
assert_eq!(headings[0].anchor, Some("this-is-a-long-title".to_string()));
}
#[test]
fn test_multiple_headings() {
let content = "# H1\n## H2\n### H3\n## H2-2";
let headings = parse_headings(content);
assert_eq!(headings.len(), 4);
assert_eq!(headings[0].level, 1);
assert_eq!(headings[1].level, 2);
assert_eq!(headings[2].level, 3);
}
#[test]
fn test_all_heading_levels() {
for level in 1..=6 {
let hashes = "#".repeat(level);
let content = format!("{} Heading", hashes);
let headings = parse_headings(&content);
assert_eq!(headings.len(), 1);
assert_eq!(headings[0].level, level as u8);
}
}
#[test]
fn test_heading_position_tracking() {
let content = "Some text\n# Heading on line 2\nMore text";
let headings = parse_headings(content);
assert_eq!(headings.len(), 1);
assert_eq!(headings[0].position.line, 2);
assert_eq!(headings[0].position.column, 1);
assert_eq!(headings[0].position.offset, 10); }
#[test]
fn test_heading_crlf_position_tracking() {
let content = "Some text\r\n# Heading on line 2\r\nMore text";
let headings = parse_headings(content);
assert_eq!(headings.len(), 1);
assert_eq!(headings[0].position.line, 2);
assert_eq!(headings[0].position.column, 1);
assert_eq!(headings[0].position.offset, 11); }
#[test]
fn test_heading_position_first_line() {
let content = "# First heading";
let headings = parse_headings(content);
assert_eq!(headings[0].position.line, 1);
assert_eq!(headings[0].position.column, 1);
assert_eq!(headings[0].position.offset, 0);
}
#[test]
fn test_heading_in_fenced_code_block_not_matched() {
let content = "# Real\n\n```markdown\n# Not a heading\n```\n\n## Also real";
let headings = parse_headings(content);
assert_eq!(headings.len(), 2);
assert_eq!(headings[0].text, "Real");
assert_eq!(headings[1].text, "Also real");
}
#[test]
fn test_fast_path_no_headings() {
let content = "No headings here, just plain text without the hash symbol.";
let headings = parse_headings(content);
assert_eq!(headings.len(), 0);
}
#[test]
fn test_indexed_matches_regular() {
let content = "Text\n# H1\n## H2";
let index = LineIndex::new(content);
let regular = parse_headings(content);
let indexed = parse_headings_indexed(content, &index);
assert_eq!(regular.len(), indexed.len());
for (r, i) in regular.iter().zip(indexed.iter()) {
assert_eq!(r.text, i.text);
assert_eq!(r.position.line, i.position.line);
assert_eq!(r.position.offset, i.position.offset);
}
}
}