"""Phase R'-6: AI 생성 HTML 정화 + 토큰 위반 검증. AI가 생성한 HTML에서: 1. 위험 태그 제거 ( 제거 html = re.sub(r"", "", html, flags=re.DOTALL | re.IGNORECASE) # 제거 html = re.sub(r"]*>.*?", "", html, flags=re.DOTALL | re.IGNORECASE) # on* 이벤트 핸들러 제거 html = re.sub(r'\s+on\w+="[^"]*"', "", html, flags=re.IGNORECASE) html = re.sub(r"\s+on\w+='[^']*'", "", html, flags=re.IGNORECASE) return html def _check_token_violations(html: str, area_name: str) -> None: """CSS에서 디자인 토큰을 사용하지 않고 하드코딩한 값을 경고한다. 정보용 경고만. 생성을 차단하지는 않음 (AI가 블록 CSS 패턴을 참고하므로 하드코딩이 일부 있을 수 있음). """ # ", html, re.DOTALL | re.IGNORECASE) if not style_blocks: return all_css = "\n".join(style_blocks) # 허용된 하드코딩 색상 (블록 CSS 패턴에서 자주 쓰이는 것) allowed_colors = { "#1e293b", "#0f172a", "#2563eb", "#93c5fd", "#60a5fa", "#ffffff", "#f8fafc", "#e2e8f0", "#475569", "#64748b", "#94a3b8", "#cbd5e1", "#1e40af", "#bae6fd", "#f0f9ff", "#006aff", "#00aaff", "#dc2626", "#fbbf24", "#0c4a6e", "#334155", "#0088cc", "#86efac", "#fde047", "#16a34a", "#fecaca", "#fef2f2", } # 하드코딩 색상 검출 (#으로 시작하는 hex) found_colors = set(re.findall(r"#[0-9a-fA-F]{3,8}", all_css)) unknown_colors = found_colors - allowed_colors if unknown_colors: logger.info( f"[R' 검증] {area_name}: 디자인 토큰 외 색상 {len(unknown_colors)}개 " f"(참고: {list(unknown_colors)[:5]})" )