
    Si6+                        d Z ddlZddlZddlZddlmZ ddlmZmZm	Z	m
Z
mZmZmZ  e       Zh dZ ej                   dej"                        Z ej                   dej"                        Zi dd	d
d	dddddddddddddddddddddddddddd d!d Zd"ed#ee   fd$Zd%ed#edz  fd&Zd'ed#ee   fd(Zd)ed#efd*Zd+ed#efd,Zd- Ze d.k(  r e        yy)/u  디자인 브리프 폰트 규칙 검증 스크립트.

마케팅팀이 디자인팀에 전달하는 브리프의 폰트 사이즈가
DQ 규칙(단일 소스: memory/specs/dq-rules.json)을 준수하는지 자동 검증한다.

사용법:
    python3 tools/validate-design-brief.py <브리프파일.md>
    python3 tools/validate-design-brief.py <브리프파일.md> --json

★ 모든 규칙은 memory/specs/dq-rules.json에서 로드됨.
  규칙 변경 시 dq-rules.json만 수정하면 이 스크립트에 자동 반영.
    N)Path)DQ_RULESABSOLUTE_MIN_PXMIN_FONT_FAMILIESBANNED_FONTSget_font_ruleget_all_font_rulesrules_version>   	   본명조   나눔명조   마루부리   어그로체   나눔스퀘어   에스코어드림   나눔스퀘어 Neo   카카오 큰글씨   카카오 작은글씨GMarket SansNoto Sans KRBlack Han Sans
Pretendardu,   (\d+)\s*(?:~|[-–])\s*(\d+)\s*px|(\d+)\s*pxum  (구분선|border|라운드|radius|패딩|padding|margin|간격|spacing|gap|line-height|행간|라인\s*간격|터치\s*영역|그리드|grid|max-width|min-width|max-height|min-height|width|height|벗어나|사이즈\s*정확|해상도|dpi|안전\s*영역|blur|opacity|shadow|검수|PASS|FAIL|0건|기준|dq-rules|단일\s*소스|font_sizes|font_pairing|font_ratio)thind   hairline
extralight   zultra-lightlighti,  regulari  normalmediumi  semiboldiX  z	semi-bolddemiboldboldi  	extraboldi   z
extra-boldz
ultra-boldblacki  heavytextreturnc                    g }t         j                  |       D ]  }|j                  d      rd|j                  d      rS|j                  t	        |j                  d                   |j                  t	        |j                  d                   x|j                  d      s|j                  t	        |j                  d                    |S )u(   텍스트에서 모든 px 값을 추출.         )
PX_PATTERNfinditergroupappendint)r'   valuesmatchs      L/home/jay/workspace/.worktrees/task-2117-dev1/tools/validate-design-brief.pyextract_px_valuesr5   G   s    F$$T* /;;q>ekk!nMM#ekk!n-.MM#ekk!n-.[[^MM#ekk!n-./ M    linec                    | j                         }| j                  dd      }g ddfg ddfg ddfg d	d
fg ddfg}|D ]D  \  }}|D ]:  }|j                         |v s!|j                         |j                         v s6|c c S  F y)uE   라인에서 텍스트 역할(헤드라인/서브/CTA 등)을 감지.  )   핵심 수치u   핵심수치u   숫자/강조u   숫자 강조u   수치 강조r;   )   헤드라인headlineu   메인 카피u   메인카피z	main copyr<   )   서브헤드subheadu   서브 카피u   서브카피zsub copyu   본문r>   )ctau   버튼buttonCTA)   면책
disclaimeru   최소rC   N)lowerreplace)r7   rE   
normalizedrole_patternskeywordsrolekws          r4   detect_rolerL   S   s    JJLEc2&J 
^_no	SUcd	[]kl	$e,	+X6M ( $ 	BxxzU"bhhjJ4D4D4F&F	 r6   contentc                     t               }t        D ]  }|| v s|j                  |        t        D ]  }|| v s|j                  |        |S )u2   브리프에서 사용된 폰트 이름을 추출.)setKNOWN_FONTSaddr   )rM   foundfonts      r4   detect_fontsrT   f   sT    EE 7?IIdO  7?IIdO Lr6   filepathc                 N   t        |       }|j                         sdd|  dS |j                  d      }|j                  d      }g }g }g }g }t	        |d      D ]  \  }}	t        |	      }
|
st        j                  |	      r*|j                  |
       t        |	      }|
D ]E  }|t        k  s|j                  |dd	d
| d|	j                         dd  d| dt         dd       G |s|t        v st        |   }t        |
      }||d   k  s|j                  |dd| d|d    d| d| d|d    dd        t        |      }|t         z  }|t         z
  }t#               }|D ]x  }t	        |      D ]h  \  }}	||	v s|t%        d|dz
        |dz    }dj'                  |      }t)        j                  d|t(        j*                        rW|j-                  |        x z |r(|j                  ddddj'                  |       dd       t/        |      t0        k  r@|j                  d d!d"t/        |       d#t0         d$|rdj'                  |      nd% dd&d       t)        j2                  d'|      }|r|j                  d(t/        |       d)       d*|vrd+|vr|j                  d,d!d-d.       t5        d/ |D              }t5        d0 |D              }t/        |      }|dk(  xr |dk(  }|rd1nd2t7        |      |||t/        |      t9        t;        |            d3|||d4S )5u2   브리프 파일을 검증하고 결과를 반환.erroru   파일 없음: )statusmessagezutf-8)encoding
r*   FONT_SIZE_VIOLATIONCRITICALu"   40px 미만 절대 금지 위반: u   px (라인: NP   )u   px → u   px 이상으로 변경)r7   typeseverityrY   fixmin_pxERRORu    최소 u   px 위반: pxr      r9   u(   금지|banned|불가|사용하지|쓰지BANNED_FONTu   금지 폰트 사용: , uD   Pretendard, Noto Sans KR, Black Han Sans 등 허용 폰트로 교체)r`   ra   rY   rb   FONT_DIVERSITYWARNINGu   폰트 u   종 감지 — 최소 u   종 필수 (감지된 폰트: u   없음uS   메인(Black Han Sans/나눔명조) + 서브(Pretendard/Noto Sans KR) 조합 사용u   ###\s*슬라이드\s*\d+u   슬라이드 
   개 감지u   3초u	   가독성READABILITY_CHECKuO   3초 가독성 테스트 언급 없음 — 디자인팀 QC 기준 포함 권장)r`   ra   rY   c              3   J   K   | ]  }|j                  d       dk(  sd  yw)ra   r]   r*   Nget.0es     r4   	<genexpr>z!validate_brief.<locals>.<genexpr>   s      NqaeeJ.?:.MN   ##c              3   J   K   | ]  }|j                  d       dk(  sd  yw)ra   rd   r*   Nrn   rp   s     r4   rs   z!validate_brief.<locals>.<genexpr>   s      HA155+<+GaHrt   PASSFAIL)criticalerrorswarningstotal_px_values_foundfonts_detected)rX   filesummaryry   rz   info)r   exists	read_textsplit	enumerater5   NON_FONT_CONTEXTSsearchextendrL   r   r0   stripFONT_SIZE_RULESminrT   r   rO   maxjoinre
IGNORECASErQ   lenr   findallsumstrsortedlist)rU   pathrM   linesry   rz   r   all_px_valuesir7   	px_valuesrJ   re   rulemin_px_in_linefontsbanned_foundvalid_fontsactually_bannedrS   context_linescontext_textslide_sectionscritical_counterror_countwarning_countpasseds                              r4   validate_briefr   r   s   >D;;=!z.JKKnngn.GMM$EFHD MUA& "4%d+	 ##D)Y'4   	BO#1 *!CB4|TXT^T^T`adbdTeSffgh T(99OP 	 DO+"4(D ^NX.1 '"&xX/?{>JZZ\],-WT(^4DDZ[ 9"J !E<'L,&K eO  ' 	GAtt| %c!QUmAE :"xx6yy!Ll\^\i\ij#''-	 !/		/0J/KLY	
 	 ;++$! [!1 22HIZH[ \-GRTYY{-CX`,aabdh
 	 ZZ ;WENmC$7#8
CD WG!;'!h
 	 NFNNNHHHKMMq 5[A%5F #&D	&!%%(%7$T%[1
  r6   resultc           
         g }| d   }|dk(  rdnd}|j                  | d|        |j                  d| d           |j                  d       | d	   }|j                  d
|d    d       |j                  d|d   rdj                  |d         nd        |j                  d       | d   r|j                  d       | d   D ]\  }|j                  dd      }d|v r	d|d    dnd}|j                  d| d| d|d           d|v sF|j                  d|d           ^ |j                  d       | d   r_|j                  d       | d   D ]5  }|j                  d |d           d|v s|j                  d|d           7 |j                  d       |d!k(  r"|j                  d"       |j                  d#       d$j                  |      S )%u,   결과를 읽기 좋은 텍스트로 포맷.rX   rv   u   ✅u   ❌u    디자인 브리프 검증: u      파일: r}   r:   r~   u      폰트 사이즈 값 r{   rk   u      폰트 종류: r|   rh   u   감지 안됨ry   u   ── 오류 ──ra   rd   r7   z (line r_   z   []r9   rY   rb   u              → 수정: rz   u   ── 경고 ──z   [WARNING] rw   u7   ★ 위 오류를 수정한 후 다시 검증하세요.uT     참고: teams/design/CLAUDE.md Section 9 (타이포그래피 계층 구조 규칙)r[   )r0   r   ro   )	r   r   rX   iconsrr   sev	line_infows	            r4   format_resultr      s   EHFf$5%D	LLD66vh?@	LL;vf~./0	LLyA	LL+A.E,F+GzRS	LL%JZH[dii2B0C&Dap%qrs	LLh+,! 	CA%%
G,C28A+'!F)A.2ILL4uAi[!I,@Az6qxjAB	C 	Rj+,
# 	CALL=978z6qxjAB	C 	RNOkl99Ur6   c                     t        t        j                        dk  rt        d       t        d       t        d       t        d       t        d       t        d       t        d       t        d       t        d	       t        d
       t        d       t        d       t        j                  d       t        j                  d   } dt        j                  v }t        |       }|r"t        t        j                  |dd             nt        t        |             t        j                  |d   dk(  rd       y d       y )Nr+   uI   사용법: python3 validate-design-brief.py <브리프파일.md> [--json]r:   uF   디자인 브리프의 폰트 규칙 준수 여부를 검증합니다.u   디자인팀 확정 규칙:u'     핵심 수치:    96px+  (weight 900)u+     헤드라인:     84px+  (weight 800-900)u+     서브헤드:     64px+  (weight 600-700)z'  CTA:          40px+  (weight 700-800)u+     면책/최소:    40px   (weight 400-500)u     40px 미만:    절대 금지u$     폰트:         최소 2종 필수r*   z--jsonF)ensure_asciiindentrX   rv   r   )	r   sysargvprintexitr   jsondumpsr   )rU   output_jsonr   s      r4   mainr     s    
388}qYZb	VWb	+,78;<;<78;</045xx{Hchh&KH%FdjjeA>?mF#$HH&"f,Q4!4r6   __main__)!__doc__r   r   r   pathlibr   dq_rulesr   r   r   r   r   r	   r
   r   rP   compiler   r-   r   
WEIGHT_MAPr   r   r1   r5   rL   rO   rT   dictr   r   r   __name__ r6   r4   <module>r      s   
 
     %& RZZGW
 BJJD MM 

C
S
#
$c
 S
 s	
 c	

 c
 
 !#
 (23
 C
 
 #C
 *6s
 S
 3

	C 	DI 	c cDj &	# 	#c( 	wS wT wt%$ %3 %P5: zF r6   