6ad82167bb
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
98 lines
3.0 KiB
Python
98 lines
3.0 KiB
Python
"""Regenera el appicon.ico de todas las apps C++ que declaren bloque icon: en su app.md."""
|
|
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
import yaml
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
|
|
|
from infra.generate_app_icon import generate_app_icon
|
|
|
|
|
|
def _find_registry_root() -> Path:
|
|
env_root = os.environ.get("FN_REGISTRY_ROOT")
|
|
if env_root:
|
|
return Path(env_root).resolve()
|
|
current = Path(__file__).resolve()
|
|
for parent in current.parents:
|
|
if (parent / "registry.db").exists():
|
|
return parent
|
|
raise FileNotFoundError("registry.db no encontrado; define FN_REGISTRY_ROOT")
|
|
|
|
|
|
def _read_frontmatter(md_path: Path) -> Optional[dict]:
|
|
text = md_path.read_text(encoding="utf-8")
|
|
if not text.startswith("---"):
|
|
return None
|
|
end = text.find("\n---", 3)
|
|
if end < 0:
|
|
return None
|
|
try:
|
|
return yaml.safe_load(text[3:end])
|
|
except yaml.YAMLError:
|
|
return None
|
|
|
|
|
|
def _iter_cpp_app_mds(root: Path):
|
|
for pattern in ("apps/*/app.md", "projects/*/apps/*/app.md"):
|
|
for md in sorted(root.glob(pattern)):
|
|
fm = _read_frontmatter(md)
|
|
if not fm or fm.get("lang") != "cpp":
|
|
continue
|
|
yield md, fm
|
|
|
|
|
|
def regenerate_app_icons(only: Optional[list[str]] = None) -> dict:
|
|
"""Recorre apps C++ con bloque icon: en su frontmatter y regenera appicon.ico.
|
|
|
|
Args:
|
|
only: Lista opcional de nombres de app a filtrar (campo `name`). Si None,
|
|
procesa todas las apps C++ con `icon:` declarado.
|
|
|
|
Returns:
|
|
dict con keys: ok (list[str]), skipped (list[dict]), failed (list[dict]).
|
|
"""
|
|
root = _find_registry_root()
|
|
ok, skipped, failed = [], [], []
|
|
|
|
for md, fm in _iter_cpp_app_mds(root):
|
|
name = fm.get("name", md.parent.name)
|
|
if only and name not in only:
|
|
continue
|
|
icon = fm.get("icon")
|
|
if not icon or not isinstance(icon, dict):
|
|
skipped.append({"name": name, "reason": "no icon: block"})
|
|
continue
|
|
phosphor = icon.get("phosphor")
|
|
accent = icon.get("accent")
|
|
if not phosphor or not accent:
|
|
skipped.append({"name": name, "reason": "icon: missing phosphor/accent"})
|
|
continue
|
|
out_ico = md.parent / "appicon.ico"
|
|
try:
|
|
generate_app_icon(
|
|
phosphor_icon_name=phosphor,
|
|
accent_hex=accent,
|
|
out_ico_path=str(out_ico),
|
|
)
|
|
ok.append(name)
|
|
except Exception as e:
|
|
failed.append({"name": name, "error": str(e)})
|
|
|
|
return {"ok": ok, "skipped": skipped, "failed": failed}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
only = sys.argv[1:] or None
|
|
result = regenerate_app_icons(only=only)
|
|
for name in result["ok"]:
|
|
print(f"OK {name}")
|
|
for s in result["skipped"]:
|
|
print(f"SKIP {s['name']}: {s['reason']}")
|
|
for f in result["failed"]:
|
|
print(f"FAIL {f['name']}: {f['error']}")
|
|
sys.exit(1 if result["failed"] else 0)
|