"""새 catalog 로더. 기존 templates/catalog.yaml과 별도로, templates/catalog/blocks.yaml을 로드하는 모듈. 기존 코드는 건드리지 않음. """ from __future__ import annotations import logging from pathlib import Path from typing import Any logger = logging.getLogger(__name__) def load_blocks_catalog( path: str | Path = "templates/catalog/blocks.yaml", ) -> list[dict]: """blocks.yaml 로드. Returns: [{"id": "prerequisites-3col", "structure_type": "3col-parallel", "keywords": ["필수", "요건", ...], "slots": ["sub_title", "body", "bullets"], "recipe_compat": ["direct_fit", "parallel_cluster"], "not_for": ["long_table"], "template": "blocks/structures/prerequisites-3col.html", "when": "3개 병렬 비교"}, ...] """ import yaml path = Path(path) if not path.exists(): logger.warning(f"[catalog] blocks.yaml 없음: {path}") return [] try: data = yaml.safe_load(path.read_text(encoding="utf-8")) blocks = data if isinstance(data, list) else data.get("blocks", []) logger.info(f"[catalog] {len(blocks)}개 블록 로드: {path}") return blocks except Exception as e: logger.error(f"[catalog] 로드 실패: {e}") return [] def find_block_by_id( blocks: list[dict], block_id: str, ) -> dict | None: """ID로 블록 찾기.""" return next((b for b in blocks if b.get("id") == block_id), None) def filter_blocks_by_structure( blocks: list[dict], structure_type: str, ) -> list[dict]: """structure_type으로 필터링.""" return [b for b in blocks if b.get("structure_type") == structure_type] def filter_blocks_by_recipe( blocks: list[dict], recipe: str, ) -> list[dict]: """recipe 호환 블록 필터링.""" return [b for b in blocks if recipe in b.get("recipe_compat", [])]