
    iS                       U d Z ddlmZ ddlZddlZddlmZ  ee      j                         j                  Z
e
dz  Zdddd	d
Zded<   ddiZded<   d+dZd,dZd,dZd+dZd-dZd.dZd-dZd.dZd/dZd/dZdZdZd0dZd0dZd0dZd0d Zd1d!Zd2d"Z d3d#Z!d1d$Z"	 	 	 	 	 	 	 	 	 	 d4d%Z#d5d&Z$d5d'Z%d6d(Z&d7d)Z'e(d*k(  r e'        yy)8u  gen_*.py / rerender_*.py 하드코딩 마이그레이션 스크립트.

실행: python3 _migrate_hardcodes.py

수행 작업:
  A. 경로 하드코딩 → WORKSPACE_ROOT / "..." 참조
  B. font-size: Npx → config 상수 참조
  C. line-height: N → config 상수 참조
  D. FONT_DIR 정의 제거 (gen_config 에서 import)
  E. @font-face 하드코딩 경로 → FONT_DIR 참조
  F. gen_config import 추가
    )annotationsN)Path_backup)
_METRIC_PXCORE_METRIC_MIN_PX)_HEADLINE_PXHEADLINE_MIN_PX)_SUBHEAD_PXSUBHEAD_MIN_PX)_CTA_PX
CTA_MIN_PX)`   T   @   (   zdict[int, tuple[str, str]]FONT_SIZE_MAPz1.3)	_LH_RATIOHEAD_SUB_RATIOzdict[str, tuple[str, str]]LINE_HEIGHT_MAPc                X    | t         v rt         |    d   S | j                  dd      }d| S )u+   line-height 값에 대한 변수명 생성.r   .__LH_)r   replace)valsafes     V/home/jay/workspace/.worktrees/task-2116-dev1/tools/ai-image-gen/_migrate_hardcodes.py_lh_var_namer   &   s6    
os#A&&;;sC D$=    c                6    | t         v rt         |    d   S d|  dS )u,   font-size px 값에 대한 변수명 생성.r   _SIZE_PX)r   pxs    r   _fs_var_namer%   .   s(    	]R ##B4r?r   c                @    | t         v rt         |    d   S t        |       S )u-   font-size px 값에 대한 우변 값 생성.   )r   strr#   s    r   _fs_var_valuer)   5   s#    	]R ##r7Nr   c                .    | t         v rt         |    d   S | S )u,   line-height 값에 대한 우변 값 생성.r'   )r   )r   s    r   _lh_var_valuer+   <   s    
os#A&&Jr   c                d    t        d t        j                  d|       D              }t        |      S )u;   소스에서 font-size: Npx 패턴의 고유 px 값 수집.c              3  2   K   | ]  }t        |        y wNint.0ms     r   	<genexpr>z%collect_font_sizes.<locals>.<genexpr>E   s     K!s1vK   zfont-size:\s*(\d+)pxsetrefindallsortedsourcevalss     r   collect_font_sizesr>   C   s(    Krzz*A6JKKD$<r   c                    t        j                  d|       }g }t               }|D ];  }	 t        |      }|dk\  r||vs|j                  |       |j                  |       = |S # t        $ r Y Kw xY w)u   소스에서 line-height: N (단위 없는) 패턴의 고유 값 수집.

    px 단위가 붙은 것은 별도 처리이므로 여기서는 제외.
    z6line-height:\s*([0-9]+(?:\.[0-9]+)?)(?:\s*;|\s*}|\s*$)
   r8   r9   r7   float
ValueErroraddappend)r<   all_vals
ratio_valsseenvfvs         r   collect_line_heightsrK   I   s    
 zzSU[\HJ5D !	qB 8D=HHQKa !   		   A%%	A10A1c                d    t        d t        j                  d|       D              }t        |      S )u0   line-height: Npx 패턴의 고유 px 값 수집.c              3  2   K   | ]  }t        |        y wr.   r/   r1   s     r   r4   z*collect_line_heights_px.<locals>.<genexpr>c   s     M!s1vMr5   zline-height:\s*(\d+)pxr6   r;   s     r   collect_line_heights_pxrO   a   s(    Mrzz*CVLMMD$<r   c                    t        j                  d|       }g }t               }|D ];  }	 t        |      }|dk\  s||vs|j                  |       |j                  |       = |S # t        $ r Y Kw xY w)uH   line-height: N (단위없는, >= 10 정수) 패턴의 고유 값 수집.z3line-height:\s*([0-9]+(?:\.[0-9]+)?)(?:\s*[;}\n\r])r@   rA   )r<   rF   large_int_valsrH   rI   rJ   s         r   collect_line_heights_no_unitrR   g   s    zzPRXYHNUD %	qB 8HHQK!!!$%   		rL   c                @    t        t        j                  d|             S )uG   return f""", = f""" 패턴을 통해 f-string HTML 파일인지 판단.z(return|=)\s*f"""boolr8   searchr<   s    r   is_fstring_html_filerX   {   s    		.788r   c                @    t        t        j                  d|             S )u@   HTML_XXX = """...""" 패턴 (non-f-string) 이 있는지 판단.z\bHTML_\w+\s*=\s*"""rT   rW   s    r   has_plain_html_varsrZ      s    		16:;;r   z/home/jay/workspacez'/home/jay/.local/share/fonts/Pretendardc                    d}dd}t        j                  d||       \  }}||z  }|} dd}t        j                  d||       \  }}||z  }|} | |fS )u~   하드코딩된 /home/jay/workspace 경로를 WORKSPACE_ROOT 참조로 치환.
    반환: (수정된 소스, 치환 수)
    r   c                x    | j                  d      }|t        t              d  j                  d      }|rd| dS y)Nr'   /zWORKSPACE_ROOT / ""WORKSPACE_ROOTgrouplen_WSlstripr3   innerrels      r   repl_path_ctorz%migrate_paths.<locals>.repl_path_ctor   s?    
CHI%%c*'uA..#r   z%Path\("(/home/jay/workspace[^"]*?)"\)c                x    | j                  d      }|t        t              d  j                  d      }|rd| dS y)Nr'   r]   zstr(WORKSPACE_ROOT / "z")zstr(WORKSPACE_ROOT)r`   re   s      r   repl_str_wsz"migrate_paths.<locals>.repl_str_ws   s?    
CHI%%c*+C533(r   z"(/home/jay/workspace[^"]*?)"r3   zre.Matchreturnr(   r8   subn)r<   countrh   
new_sourcenrj   s         r   migrate_pathsrr      sw     E$ GG0MJ
 
QJEF) GG(MJ
 
QJEF5=r   c                f    ddg}d}|D ]#  }t        j                  |d|       \  }}||z  }|} % | |fS )ux   FONT_DIR = Path.home() / ... 정의를 제거 (gen_config에서 import).
    반환: (수정된 소스, 제거 수)
    zL\n?FONT_DIR\s*=\s*Path\.home\(\)\s*/\s*"\.local/share/fonts/Pretendard"\s*\nzT\n?FONT_DIR\s*=\s*Path\.home\(\)\s*/\s*"\.local/share/fonts"\s*/\s*"Pretendard"\s*\nr   
rm   )r<   patternsro   patrp   rq   s         r   migrate_font_dir_defrw      sX     	X_H E T62
A
 5=r   c                    d}t        j                  dd|       \  }}||z  }|} t        j                  dd|       \  }}||z  }|} t        j                  dd|       \  }}||z  }|} | |fS )u  @font-face 내 하드코딩된 파일 경로를 FONT_DIR 참조로 치환.

    f-string 내부: file:///home/jay/.local/share/fonts/Pretendard/Pretendard-X.otf
    → file://{FONT_DIR}/Pretendard-X.otf

    일반 string 내부: file:///home/jay/.local/share/fonts/Pretendard/Pretendard-X.otf
    → 일반 string이라면 f-string으로 변환이 필요하지만, 이 스크립트는
      상수 블록으로 치환하는 방식을 사용.
    r   z0file:///home/jay/\.local/share/fonts/Pretendard/file://{FONT_DIR}/z2Path\("/home/jay/\.local/share/fonts/Pretendard"\)FONT_DIRz*"/home/jay/\.local/share/fonts/Pretendard"zstr(FONT_DIR)rm   )r<   ro   rp   rq   s       r   migrate_inline_font_pathsr{      s     E GG;MJ
 
QJEF GG=MJ
 
QJEF GG5MJ
 
QJEF5=r   c                x    d}dd}t        j                  d|| t         j                        \  }}||z  }|} | |fS )u  HTML_XXX = """...""" 블록 내 @font-face 하드코딩 처리.

    일반 문자열 내부는 f-string이 아니므로 {FONT_DIR} 치환이 불가.
    대신, file:///home/jay/.local/share/fonts/Pretendard/ 를
    {_FONT_DIR_PLACEHOLDER_} 으로 바꾸고 나중에 _apply_font_config 에 넣는
    방식은 복잡도를 높이므로, 더 실용적인 방법을 사용:

    HTML_XXX = """...""" 를 HTML_XXX = f"""...""" 로 변환하고
    내부의 {{ }} 이스케이프를 적용한다.
    r   c                    | j                  d      }| j                  d      }d|vr| j                  d      S d|v r|}n"|j                  dd      j                  dd      }|j                  d	d
      }| d| dS )Nr'      z.file:///home/jay/.local/share/fonts/Pretendardr   z{{{}z}}z/file:///home/jay/.local/share/fonts/Pretendard/ry   z = f"""""")ra   r   )r3   varnamecontentnew_contents       r   convert_plain_html_to_fstringzNmigrate_font_face_block_in_plain_string.<locals>.convert_plain_html_to_fstring  s    ''!*''!*;7J771: 7?!K "//#t4<<S$GK!))= 
 '+c22r   z(HTML_\w+)\s*=\s*"""(.*?)""")flagsrk   )r8   rn   DOTALL)r<   ro   r   rp   rq   s        r   'migrate_font_face_block_in_plain_stringr      sL     E3( GG'%ii	MJ 
QJEF5=r   c                   g }| D ].  }t        |      }t        |      }|j                  | d|        0 |D ].  }t        |      }t	        |      }|j                  | d|        0 |rdj                  |      dz   S dS )uO   파일 상단에 추가할 폰트 사이즈 / line-height 상수 정의 블록.z = rt    )r%   r)   rE   r   r+   join)
font_sizes	lh_ratioslinesr$   varr   lhs          r   build_size_constantsr   (  s    E '2BuCu%&'  '2BuCu%&' ',499Ud"33r   c                    d}|D ]D  }t        |      }d| d}d| d}| j                  |      }|s.| j                  ||      } ||z  }F | |fS )uL   소스 내 font-size: Npx 를 {_VAR_PX}px 또는 변수명 참조로 치환.r   zfont-size: r$   zfont-size: {z}px)r%   ro   r   )r<   r   ro   r$   r   patternreplacementrq   s           r   replace_font_sizes_in_sourcer   6  sr    E 2t2&%cU$/LL!^^G[9FQJE 5=r   c                    d}|D ]C  }t        |      }d| }d| d}| j                  |      }|s-| j                  ||      } ||z  }E | |fS )uF   소스 내 line-height: N 를 {_LH_VAR} 또는 변수명으로 치환.r   zline-height: zline-height: {r   )r   ro   r   )r<   r   ro   r   r   r   r   rq   s           r   replace_line_heights_in_sourcer   D  sp    E 2!"&'uB/LL!^^G[9FQJE 5=r   c                    g }| D ]%  }t        |      }|j                  d| d| d       ' |D ]%  }t        |      }|j                  d| d| d       ' dj                  |      }d| d	S )
u1   _apply_font_config() 헬퍼 함수 소스 생성.z        "font-size: zpx": f"font-size: {z}px",z        "line-height: z": f"line-height: {z}",rt   u}   

def _apply_font_config(html: str) -> str:
    """폰트 사이즈 하드코딩을 config 값으로 치환."""
    subs = {
z_
    }
    for old, new in subs.items():
        html = html.replace(old, new)
    return html
)r%   rE   r   r   )r   r   
subs_linesr$   r   r   subs_strs          r   build_apply_font_config_funcr   X  s    J V204HVTUV  V222$6J3%tTUV yy$H
 

 
 
r   c                z   g }| r|j                  d       |r|j                  d       t               }|D ]&  }|t        v s|j                  t        |   d          ( |D ]&  }|t        v s|j                  t        |   d          ( |j                  t        |             |sydj                  |      }d| dS )u"   실제로 필요한 것만 import.r_   rz   r'   r   , zfrom gen_config import rt   )rE   r7   r   rD   r   extendr:   r   )	uses_workspaceuses_font_dirr   r   importsneeded_constsr$   r   imports_strs	            r   build_import_liner   s  s     G'(z"EM 4mB/234  6 ob1!456 NN6-()))G$K$[M44r   c                   | j                  d      }d}t        |      D ]:  \  }}|j                         }|j                  d      s|j                  d      s9|}< |dk(  rst        |      D ]d  \  }}|j                         }|s|j                  d      r+|j                  d      r=|j                  d      rOt	        d	 |d
| D              c S  yt	        d |d
|dz    D              S )u\   import 구문 삽입 위치 (마지막 import/from 라인 다음) 반환 (문자 인덱스).T)keependszimport zfrom #r   z'''c              3  2   K   | ]  }t        |        y wr.   rb   r2   ls     r   r4   z.find_import_insertion_point.<locals>.<genexpr>  s     5a3q65r5   Nr   c              3  2   K   | ]  }t        |        y wr.   r   r   s     r   r4   z.find_import_insertion_point.<locals>.<genexpr>  s     <!s1v<r5   r'   )
splitlines	enumeratestrip
startswithsum)r<   r   last_import_idxilinestrippeds         r   find_import_insertion_pointr     s    t,EOU#  4::<y)X-@-@-IO  " ' 	6GAtzz|H 3 3C 8ATATUZA[dldwdwx}d~55!9555	6 <u%:':;<<<r   c                    t        |       S )uM   상수 정의 삽입 위치 (import 블록 이후) 반환 (문자 인덱스).)r   rW   s    r   find_constants_insertion_pointr     s    &v..r   c                V   | j                  d      }|}g }d|v r| j                  dddS t        |      \  }}|r|j                  d| d       t	        |      \  }}|r|j                  d	| d       t        |      \  }}|r|j                  d
| d       t        |      \  }}|r|j                  d| d       t        |      }t        |      }	t        ||      \  }}
|
r|j                  d|
 d       t        ||	      \  }}|r|j                  d| d       d|v }d|v }t        ||||	      }|s|s| j                  dddS t        ||	      }|s|rOt        |      }d}|r||z  }|r||z  }|d| |z   ||d z   }|r|j                  d       |r|j                  d       ||k(  r| j                  dddS t        j                  d       t        | j                  z  }t!        j"                  | |       | j%                  |d       | j                  d|t'        |      dS )uA   파일을 읽고 마이그레이션을 적용하여 덮어쓴다.zutf-8)encodingzfrom gen_config importTzalready migrated)fileskippedreasonu   경로 치환 u   건u   FONT_DIR 정의 제거 u   plain HTML→fstring 변환 u   폰트 경로 치환 u   font-size 치환 u   line-height 치환 r_   rz   zno changes neededr   Nu   gen_config import 추가u   상수 정의 추가zno effective changes)exist_okF)r   r   changesbackup)	read_textnamerr   rE   rw   r   r{   r>   rK   r   r   r   r   r   
BACKUP_DIRmkdirshutilcopy2
write_textr(   )fpathr<   originalr   n_pathsn_fdirn_plainn_fpr   r   n_fsn_lhr   r   import_lineconst_block	ins_pointinsert_textbackup_paths                      r   process_filer     s|   __g_.FHG  6)

t?QRR $F+OFGy45 *&1NFF0<= >fEOFG5gYcBC -V4LFD.tfC89 $F+J$V,I 0
CLFD*4&451&)DLFD,TF#67 &/N&(M#NM:yYKw

t?RSS 'z9=K k/7	;&K;&K
#k1F9:4FFNN56NN12

t?UVV d#uzz)K
LL$ 
Vg. 

k"	 r   c                 `   t        t        t        j                  d            t        t        j                  d            z         } t        dz  t        dz  h}| D cg c]	  }||vs| } }t	        dt        |        d       d}d}| D ]  }t        |      }|j                  d      r,|j                  d	d
      }t	        d|d    d|        |dz  }Kdj                  |j                  dg             }t	        d|d    d|        |dz  } t	        d| d| dt                y c c}w )Nzgen_*.pyzrerender_*.pyz_migrate_hardcodes.pyzgen_config.pyu   대상 파일 u   개 처리 시작...
r   r   r   r   z	  [SKIP] r   u    — r'   r   r   z	  [OK]   u	   
완료: u   개 수정, u   개 스킵, 백업: )
r:   listAI_DIRglobprintrb   r   getr   r   )	targetsexcludef	processedr   r   resultr   changes_strs	            r   mainr     s8   V[[$%V[[-I(JJG ///1IJG!6QQg%5q6G6	N3w<.(>
?@IG 	e$::i ZZ"-FIfVn-U6(;<qLG))FJJy"$=>KIfVn-U;-@ANI	 
JykgY6J:,
WX% 7s   	D+'D+__main__)r   r(   rl   r(   )r$   r0   rl   r(   )r<   r(   rl   	list[int])r<   r(   rl   	list[str])r<   r(   rl   rU   )r<   r(   rl   tuple[str, int])r   r   r   r   rl   r(   )r<   r(   r   r   rl   r   )r<   r(   r   r   rl   r   )
r   rU   r   rU   r   r   r   r   rl   r(   )r<   r(   rl   r0   )r   r   rl   dict)rl   None))__doc__
__future__r   r8   r   pathlibr   __file__resolveparentr   r   r   __annotations__r   r   r%   r)   r+   r>   rK   rO   rR   rX   rZ   rc   _FONTS_HARDrr   rw   r{   r   r   r   r   r   r   r   r   r   r   __name__ r   r   <module>r      s8   # 	   
h			!	(	(i
 	-+)!	-)  
*/+ 
0(9
< 7(V((V+d4(6555 5 	5
 	5D=$/
UxY6 zF r   