harness/plugins/proposal-builder/skills/proposal-builder-orchestrator/scripts/inspect_template.py
DESKTOP-TKLFCPR\ython 53f0dc5fa3 feat(proposal-builder): RFP+PPT템플릿 제안서 자동완성 플러그인 추가
- 전문가 7인: rfp-analyst·strategist·tech-advisor(아키텍처 총동원)·writer·visual-designer(선 아이콘 직접제작)·deck-designer·qa
- 오케스트레이터: '제안서 작성' 한마디로 전 파이프라인 총지휘 (Phase1~6)
- 커맨드 /proposal + 번들 스크립트(inspect_template·build_deck) + 설치/사용 가이드
- marketplace 등록 + plugin.json 동기화
- SI 구축·SM 유지보수 제안 주력

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 20:46:30 +09:00

67 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""
inspect_template.py — PPTX 디자인 템플릿 해부.
마스터/레이아웃/테마색/폰트/플레이스홀더를 덤프하여 deck-designer가 동일 스타일로 슬라이드를 생성하게 한다.
사용: python inspect_template.py <template.pptx> [--json out.json]
의존: pip install python-pptx
외부 호출 없음(로컬 파싱만).
"""
import sys, json, argparse
def main():
ap = argparse.ArgumentParser()
ap.add_argument("template")
ap.add_argument("--json", dest="out")
a = ap.parse_args()
try:
from pptx import Presentation
from pptx.util import Emu
except ImportError:
print("python-pptx 미설치 → pip install python-pptx", file=sys.stderr); sys.exit(2)
prs = Presentation(a.template)
spec = {
"slide_size": {"w_emu": prs.slide_width, "h_emu": prs.slide_height,
"w_in": round(prs.slide_width / 914400, 2), "h_in": round(prs.slide_height / 914400, 2)},
"masters": [], "layouts": [], "theme_fonts": {}, "theme_colors": {},
}
# 테마 폰트(첫 마스터의 테마)
try:
theme = prs.slide_masters[0].element.getroottree() # noqa
except Exception:
pass
for mi, master in enumerate(prs.slide_masters):
spec["masters"].append({"index": mi, "name": master.name or f"master{mi}",
"layout_count": len(master.slide_layouts)})
for li, layout in enumerate(master.slide_layouts):
phs = []
for ph in layout.placeholders:
phs.append({"idx": ph.placeholder_format.idx,
"type": str(ph.placeholder_format.type),
"name": ph.name,
"left_in": round((ph.left or 0)/914400, 2) if ph.left is not None else None,
"top_in": round((ph.top or 0)/914400, 2) if ph.top is not None else None,
"width_in": round((ph.width or 0)/914400, 2) if ph.width is not None else None,
"height_in": round((ph.height or 0)/914400, 2) if ph.height is not None else None})
spec["layouts"].append({"master": mi, "index": li, "name": layout.name, "placeholders": phs})
# 테마 색/폰트는 XML에서 best-effort 추출
try:
from pptx.oxml.ns import qn
master_part = prs.slide_masters[0]
themeEl = master_part.element.getparent() # noqa
except Exception:
pass
out = json.dumps(spec, ensure_ascii=False, indent=2)
if a.out:
with open(a.out, "w", encoding="utf-8") as f:
f.write(out)
print(f"기록: {a.out} (layouts={len(spec['layouts'])})")
else:
print(out)
if __name__ == "__main__":
main()