File size: 2,711 Bytes
3998131 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
"""
Template Loader Module
Handles loading and parsing of letter templates.
"""
import re
import logging
from pathlib import Path
from typing import List, Dict, Set
from .config import TEMPLATE_DIR
logger = logging.getLogger(__name__)
class TemplateLoader:
"""
Responsible for discovering, loading, and parsing letter templates.
"""
def __init__(self, template_dir: Path = TEMPLATE_DIR):
self.template_dir = template_dir
def list_templates(self) -> List[str]:
"""
List all available template files in the template directory.
Returns a list of filenames.
"""
if not self.template_dir.exists():
logger.warning(f"Template directory not found: {self.template_dir}")
return []
# List text files
templates = [f.name for f in self.template_dir.glob("*.txt")]
return sorted(templates)
def load_template(self, template_name: str) -> str:
"""
Load the content of a specific template.
"""
template_path = self.template_dir / template_name
if not template_path.exists():
raise FileNotFoundError(f"Template not found: {template_name}")
try:
return template_path.read_text(encoding='utf-8')
except Exception as e:
logger.error(f"Error loading template {template_name}: {e}")
raise
def extract_placeholders(self, template_text: str) -> Set[str]:
"""
Extract placeholders from the template text.
Supports formats:
- [Placeholder Name]
- {{Placeholder Name}}
- <Placeholder Name>
"""
placeholders = set()
# Regex for [Placeholder]
bracket_matches = re.findall(r'\[(.*?)\]', template_text)
placeholders.update(bracket_matches)
# Regex for {{Placeholder}}
curly_matches = re.findall(r'\{\{(.*?)\}\}', template_text)
placeholders.update(curly_matches)
# Regex for <Placeholder>
angle_matches = re.findall(r'<(.*?)>', template_text)
placeholders.update(angle_matches)
# Regex for {Placeholder} - careful to avoid double braces if possible,
# but for now we just want to catch {Key}
# We use a negative lookahead/lookbehind or just simple matching for {Key}
# where Key doesn't contain { or }
single_curly_matches = re.findall(r'(?<!\{)\{([^{}]+)\}(?!\})', template_text)
placeholders.update(single_curly_matches)
# Filter out empty strings or purely structural tags if any
return {p.strip() for p in placeholders if p.strip()}
|