# Document Helper Functions # Contains helper functions like filter_empty_sections(), extract_business_name_from_content(), etc. import re import os import sys from typing import List, Dict, Any # Add the parent directory to sys.path to import from models.py sys.path.append(os.path.dirname(os.path.dirname(__file__))) from models import ExportSection def extract_business_name_from_content(sections: List[ExportSection]) -> str: """Extract business name from markdown content""" for section in sections: if section.content: lines = section.content.split('\n') for i, line in enumerate(lines): line = line.strip() # Look for "Business Name:" pattern if '**Business Name:**' in line or 'Business Name:' in line: # Extract the business name from the line if '**Business Name:**' in line: business_name = line.split('**Business Name:**')[1].strip() else: business_name = line.split('Business Name:')[1].strip() # Keep markdown formatting - don't strip ** symbols # business_name = re.sub(r'[*_`~]', '', business_name) business_name = business_name.strip() if business_name: return business_name # If not found on same line, check next line if i + 1 < len(lines): next_line = lines[i + 1].strip() business_name = next_line # Keep ** symbols business_name = business_name.strip() if business_name: return business_name return None def extract_subheadings(content: str) -> List[str]: """Extract subheadings from markdown content""" subheadings = [] lines = content.split('\n') for line in lines: line = line.strip() # Look for various markdown header patterns if (line.startswith('##') and not line.startswith('###')) or \ line.startswith('**') and line.endswith('**') and len(line) > 4: # Remove markdown formatting and clean up if line.startswith('##'): subheading = re.sub(r'^##+\s*', '', line) else: # Handle bold text that might be headings - keep ** symbols subheading = line # Keep ** symbols instead of stripping them # subheading = re.sub(r'[*_`~]', '', subheading) # Commented out to preserve ** symbols if subheading.strip() and len(subheading.strip()) > 3: # Avoid very short headings subheadings.append(subheading.strip()) return subheadings def filter_empty_sections(sections: List[ExportSection]) -> List[ExportSection]: """Filter out sections with no content to prevent empty pages""" filtered_sections = [] for section in sections: if section.content and section.content.strip(): # Clean the content to check if it's actually meaningful cleaned_content = section.content # No clean_text_for_pdf import, so use raw content if cleaned_content and len(cleaned_content.strip()) > 10: # At least 10 characters filtered_sections.append(section) # logging.info(f"Section '{section.title}' passed filtering with {len(cleaned_content)} characters") else: # logging.info(f"Section '{section.title}' filtered out - content too short: {len(cleaned_content) if cleaned_content else 0} chars") pass else: # logging.info(f"Section '{section.title}' filtered out - no content") pass # logging.info(f"Filtered sections: {len(filtered_sections)} out of {len(sections)} total") return filtered_sections def remove_duplicate_headings(content: str) -> str: """Remove duplicate headings from content""" if not content: return content lines = content.split('\n') cleaned_lines = [] seen_headings = set() for line in lines: line = line.strip() if not line: cleaned_lines.append('') continue # Check if this is any type of heading is_heading = False heading_text = "" # Markdown headings (# ## ### etc.) if line.startswith('#'): heading_text = re.sub(r'^#+\s*', '', line).strip() is_heading = True # Bold headings (**text**) elif line.startswith('**') and line.endswith('**') and len(line) > 4: heading_text = line[2:-2].strip() # Remove ** symbols is_heading = True # Check for numbered headings (e.g., "8.1 Management Team") elif re.match(r'^\d+\.?\d*\s+', line): heading_text = re.sub(r'^\d+\.?\d*\s+', '', line).strip() is_heading = True if is_heading and heading_text: # Normalize the heading text for comparison normalized_text = heading_text.lower().strip() # Also check for variations with "and" vs "&" variations = [ normalized_text, normalized_text.replace(' & ', ' and '), normalized_text.replace(' and ', ' & '), normalized_text.replace('&', 'and'), normalized_text.replace('and', '&') ] # Check if any variation has been seen before is_duplicate = any(var in seen_headings for var in variations) if not is_duplicate: # Add all variations to seen set for var in variations: seen_headings.add(var) cleaned_lines.append(line) # Skip duplicate headings else: cleaned_lines.append(line) return '\n'.join(cleaned_lines)