use crate::config::ParsingConfig;
use anyhow::Result;
use regex::Regex;
use super::engine::{ParseRule, ParsedElement, ParsedElementType};
pub struct PatternBasedSectionDetectionRule<'a> {
patterns: Vec<regex::Regex>,
config: &'a ParsingConfig,
}
impl<'a> PatternBasedSectionDetectionRule<'a> {
pub fn new(config: &'a ParsingConfig) -> Result<Self> {
let mut patterns = Vec::new();
for pattern_str in &config.section_and_hierarchy.pattern_detection.patterns {
patterns.push(Regex::new(pattern_str)?);
}
Ok(Self { patterns, config })
}
}
impl<'a> ParseRule for PatternBasedSectionDetectionRule<'a> {
fn apply(&self, elements: Vec<ParsedElement>) -> Result<Vec<ParsedElement>> {
if !self.config.section_and_hierarchy.pattern_detection.enabled {
println!(" ⏭️ Pattern detection disabled, skipping");
return Ok(elements);
}
println!("🔍 APPLYING PATTERN-BASED SECTION DETECTION...");
println!(
" 📝 Checking {} patterns against {} elements",
self.patterns.len(),
elements.len()
);
let mut promoted_count = 0;
let mut result_elements = Vec::new();
for mut element in elements {
if element.element_type == ParsedElementType::Paragraph
&& self.should_be_section(&element)
{
println!(
" 🔼 Pattern matched: '{}' -> Section",
element.text.chars().take(50).collect::<String>()
);
element.element_type = ParsedElementType::Section;
promoted_count += 1;
}
result_elements.push(element);
}
println!(" ✅ Promoted {promoted_count} elements to sections based on patterns");
Ok(result_elements)
}
fn name(&self) -> &str {
"PatternBasedSectionDetection"
}
}
impl<'a> PatternBasedSectionDetectionRule<'a> {
fn matches_pattern(&self, text: &str) -> bool {
self.patterns.iter().any(|pattern| pattern.is_match(text))
}
fn should_be_section(&self, element: &ParsedElement) -> bool {
if !self.matches_pattern(&element.text) {
return false;
}
if !self
.config
.section_and_hierarchy
.pattern_detection
.respect_font_constraints
{
return true;
}
if let Some(style) = &element.style_info {
if let Some(font_size) = style.font_size {
font_size >= self.config.section_and_hierarchy.min_header_size
|| (self.config.section_and_hierarchy.use_bold_indicator && style.is_bold)
} else {
self.config.section_and_hierarchy.use_bold_indicator && style.is_bold
}
} else {
false
}
}
}