Files

121 lines
3.4 KiB
Python

"""Find SVG and notes files in a project directory."""
from __future__ import annotations
import re
from pathlib import Path
from slide_roster import discover_slide_svgs
class NotesFileReadError(RuntimeError):
"""Report a matched notes file that cannot be decoded or read."""
def find_svg_files(
project_path: Path,
source: str = 'output',
*,
allow_fallback: bool = True,
) -> tuple[list[Path], str]:
"""Find SVG files in the project.
Args:
project_path: Project directory path.
source: SVG source directory alias or name.
- 'output': svg_output (hand-authored source; native default)
- 'final': svg_final (post-processed preview; diagnostic input)
- or any subdirectory name
allow_fallback: Try svg_output and then the project root when the
requested directory is missing.
Returns:
(list_of_svg_files, actual_directory_name) tuple.
"""
dir_map = {
'output': 'svg_output',
'final': 'svg_final',
}
dir_name = dir_map.get(source, source)
svg_dir = project_path / dir_name
if not svg_dir.exists():
if not allow_fallback:
return [], dir_name
print(f" Warning: {dir_name} directory does not exist, trying svg_output")
dir_name = 'svg_output'
svg_dir = project_path / dir_name
if not svg_dir.exists():
if project_path.is_dir():
svg_dir = project_path
dir_name = project_path.name
else:
return [], ''
return discover_slide_svgs(svg_dir), dir_name
def find_notes_files(
project_path: Path,
svg_files: list[Path] | None = None,
) -> dict[str, str]:
"""Find notes files and map them to SVG files.
Supports two matching modes (mixed matching supported):
1. Match by filename (priority): notes/01_cover.md -> 01_cover.svg
2. Match by index (backward compatible): notes/slide01.md -> 1st SVG
Args:
project_path: Project directory path.
svg_files: SVG file list (for filename matching).
Returns:
Dict mapping SVG filename stem to notes content.
"""
notes_dir = project_path / 'notes'
notes: dict[str, str] = {}
if not notes_dir.exists():
return notes
svg_stems_mapping: dict[str, int] = {}
svg_index_mapping: dict[int, str] = {}
if svg_files:
for i, svg_path in enumerate(svg_files, 1):
svg_stems_mapping[svg_path.stem] = i
svg_index_mapping[i] = svg_path.stem
for notes_file in notes_dir.glob('*.md'):
stem = notes_file.stem
# Try index-based matching (backward compat with slide01.md format).
match = re.search(r'slide[_]?(\d+)', stem)
mapped_stem = (
svg_index_mapping.get(int(match.group(1)))
if match
else None
)
filename_match = stem in svg_stems_mapping
if mapped_stem is None and not filename_match:
continue
try:
content = notes_file.read_text(encoding='utf-8').strip()
except (OSError, UnicodeError) as exc:
raise NotesFileReadError(
f"Cannot read matched notes file {notes_file}: {exc}"
) from exc
if not content:
continue
if mapped_stem:
notes[mapped_stem] = content
# Filename-based matching overrides index-based matching.
if filename_match:
notes[stem] = content
return notes