Files
foldsite/src/rendering/template_discovery.py
Tanishq Dubey ad81d7f3db
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 52s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 1m1s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 5m50s
docs refactor
2025-10-09 18:21:23 -04:00

221 lines
8.2 KiB
Python

"""
Smart Template Discovery System - Grug-approved simplification
Replaces the complex nested template discovery with simple, debuggable logic
"""
from pathlib import Path
from typing import Optional, List
class TemplateDiscovery:
"""
Simple template discovery that maintains all current functionality
Following grug principles: clear priority order, easy to debug
"""
def __init__(self, template_root: Path):
self.template_root = Path(template_root)
self._last_search_candidates = []
def find_template(self, content_path: Path, file_type: str, categories: List[str], extension: str) -> Optional[Path]:
"""
Find the best template for the given content
Uses simple priority list instead of complex nested loops
"""
# Build candidate template names in priority order
candidates = self._build_candidate_list(content_path, file_type, categories, extension)
self._last_search_candidates = candidates.copy() # Store for debugging
# Search from current directory up to template root (preserve hierarchy)
search_path = self.template_root / content_path.parent
while search_path >= self.template_root:
for candidate in candidates:
template_path = search_path / candidate
if template_path.exists():
return template_path
search_path = search_path.parent
return None
def get_last_search_candidates(self) -> List[str]:
"""Get the candidates from the last template search - for debugging"""
return self._last_search_candidates.copy()
def _build_candidate_list(self, content_path: Path, file_type: str, categories: List[str], extension: str) -> List[str]:
"""
Build list of template candidates in priority order
This replaces the complex nested loop logic with simple, clear ordering
"""
candidates = []
# 1. Specific file template (highest priority)
candidates.append(f"{content_path.stem}.html")
# 2. Type + extension templates
if extension:
candidates.append(f"__{file_type}.{extension}.html")
# 3. Type + category templates (preserve current category system)
for category in reversed(categories): # Most specific categories first
candidates.append(f"__{file_type}.{category}.html")
# 4. Generic type template
candidates.append(f"__{file_type}.html")
# 5. Default template (for ultimate fallback)
candidates.append("default.html")
return candidates
def find_style_candidates(self, content_path: Path, file_type: str, categories: List[str], extension: str) -> List[str]:
"""
Find CSS style candidates - similar logic to templates but for styles
Returns list of potential style paths in priority order
"""
candidates = []
# 1. Specific style for the content path
candidates.append(f"/{content_path}.css")
# 2. Type + extension styles in current and parent directories
search_path = content_path.parent
while True:
if extension:
candidates.append(f"/{search_path}/__{file_type}.{extension}.css")
# 3. Type + category styles
for category in reversed(categories):
candidates.append(f"/{search_path}/__{file_type}.{category}.css")
if search_path == Path('.'):
break
search_path = search_path.parent
# 4. Base style (always included)
candidates.append("/base.css")
return candidates
def debug_template_discovery(self, content_path: Path, file_type: str, categories: List[str], extension: str) -> dict:
"""
Debug information for template discovery - helps with troubleshooting
Grug-approved: when things break, need easy way to see what's happening
"""
candidates = self._build_candidate_list(content_path, file_type, categories, extension)
debug_info = {
'content_path': str(content_path),
'file_type': file_type,
'categories': categories,
'extension': extension,
'candidates': candidates,
'search_paths': [],
'found_templates': [],
'chosen_template': None
}
# Check each search path
search_path = self.template_root / content_path.parent
while search_path >= self.template_root:
debug_info['search_paths'].append(str(search_path))
for candidate in candidates:
template_path = search_path / candidate
if template_path.exists():
debug_info['found_templates'].append(str(template_path))
if debug_info['chosen_template'] is None:
debug_info['chosen_template'] = str(template_path)
search_path = search_path.parent
return debug_info
class LegacyTemplateDiscovery:
"""
Wrapper around the original complex template discovery for comparison
Helps ensure we don't break anything during migration
"""
def __init__(self, template_root: Path):
self.template_root = Path(template_root)
def find_template_legacy(self, content_path: Path, file_type: str, categories: List[str], extension: str) -> Optional[Path]:
"""
Original complex template discovery logic (from renderer.py)
Kept for comparison and gradual migration
"""
templates = []
# Check for folder template
if file_type == "folder":
folder_template = self.template_root / content_path / "__folder.html"
if folder_template.exists():
templates.append(folder_template)
else:
# Check for specific file template
specific_template = self.template_root / f"{content_path}.html"
if specific_template.exists():
templates.append(specific_template)
# If no specific template found, search with complex nested logic
if len(templates) == 0:
search_path = self.template_root / content_path.parent
while search_path >= self.template_root:
# Check type + extension
type_ext_template = search_path / f"__{file_type}.{extension}.html"
if type_ext_template.exists():
templates.append(type_ext_template)
break
# Check type + categories
for category in reversed(categories):
type_cat_template = search_path / f"__{file_type}.{category}.html"
if type_cat_template.exists():
templates.append(type_cat_template)
break
search_path = search_path.parent
return templates[0] if templates else None
def migrate_template_discovery(old_discovery: LegacyTemplateDiscovery, new_discovery: TemplateDiscovery) -> dict:
"""
Migration helper to compare old vs new template discovery
Helps ensure we don't break anything
"""
test_cases = [
# Common test cases
(Path("index.md"), "file", ["document"], "md"),
(Path("posts/my-post.md"), "file", ["document"], "md"),
(Path("images/gallery"), "folder", ["image"], None),
(Path("about.md"), "file", ["document"], "md"),
]
results = {
'total_tests': len(test_cases),
'matching': 0,
'differences': [],
'test_details': []
}
for content_path, file_type, categories, extension in test_cases:
old_result = old_discovery.find_template_legacy(content_path, file_type, categories, extension)
new_result = new_discovery.find_template(content_path, file_type, categories, extension)
test_detail = {
'content_path': str(content_path),
'old_result': str(old_result) if old_result else None,
'new_result': str(new_result) if new_result else None,
'matches': old_result == new_result
}
results['test_details'].append(test_detail)
if old_result == new_result:
results['matching'] += 1
else:
results['differences'].append(test_detail)
return results