docs refactor
All checks were successful
All checks were successful
This commit is contained in:
221
src/rendering/template_discovery.py
Normal file
221
src/rendering/template_discovery.py
Normal file
@ -0,0 +1,221 @@
|
||||
"""
|
||||
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
|
Reference in New Issue
Block a user