
    `i                     X   d Z ddlZddlZddlZddlmZ ddlmZ dedefdZ	dedefd	Z
d
edefdZdedefdZdedefdZdedefdZdedefdZdee   dee   dee   defdZdedee   fdZdedee   fdZdededee   fdZdedefdZdefdZedk(  r e e             y)zCExtract brand color candidates from scraped CSS and HTML snapshots.    N)Counter)Path	hex_valuereturnc                     | j                  d      }t        |      dv rdj                  d |D              }d|j                          S )N#)       c              3   &   K   | ]	  }|d z    yw)   N ).0chs     ;/home/jay/workspace/tools/insane-design/brand_candidates.py	<genexpr>z!_normalize_hex.<locals>.<genexpr>   s     /2Q/s   )lstriplenjoinupper)r   values     r   _normalize_hexr      sE    S!E
5zV///u{{}o    namec                     d }| j                         }t        d      D ]+  \  }}|j                  |      }|dk(  r|||f}|||k  s*|}- |dS |d   S )N)brandprimaryaccentactionctar   r   )lower	enumeratefind)r   bestloweredorderkeywordindex	candidates          r   
_pick_roler+      su    (,DjjlG#$ST wW%B;E7+	<9t+D 2*47*r   textc                     t               }t        j                  d|       D ]'  }|t        |j	                  d            xx   dz  cc<   ) |S )N#[0-9a-fA-F]{3,8}r      )r   refinditerr   group)r,   countsmatchs      r   _count_hexesr5      sF    iF148 4~ekk!n-.!3.4Mr   c                 $   t        |       dd  }t        |dd d      dz  }t        |dd d      dz  }t        |dd d      dz  }t        |||      }t        |||      }||k(  ry||z   dz  }dt	        d|z  dz
        z
  }|dk(  ry||z
  |z  d	z  S )
Nr/   r   r         r
      g        d   )r   intmaxminabs)	r   r   redgreenbluehighlow	lightnessdivisors	            r   _hex_saturationrF   &   s    9%ab)E
eAaj"

#Ca
B#%EuQqz2$DsE4 D
c5$
Cs{q I#a)ma'((G!|CZ7"c))r   htmlc                     t               }t        j                  d| t        j                        D ]+  }|j	                  t        |j                  d                   - |S )Nz<svg\b[\s\S]*?</svg>r   )r   r0   r1   
IGNORECASEupdater5   r2   )rG   r3   r4   s      r   _extract_svg_countsrK   6   sH    iF4dBMMJ 4l5;;q>234Mr   c                    t               }g }t        j                  d| t        j                        D ]"  }|j	                  |j                  d             $ t        d |D              sJt        j                  d| t        j                        D ]"  }|j	                  |j                  d             $ |D ]  }|j                  t        |              |S )Nz<(?P<tag>section|div|aside)\b(?=[^>]*(?:class|id|data-[\w-]+)=(['\"])[^'\"]*(?:customer|logo-wall|trusted|featured)[^'\"]*\2)[^>]*>[\s\S]*?</(?P=tag)>r   c              3   $   K   | ]  }d |v  
 yw)zlogo-carouselNr   )r   blocks     r   r   z,_extract_logo_wall_counts.<locals>.<genexpr>F   s     <E%'<s   z^<ul\b(?=[^>]*(?:class|id|data-[\w-]+)=(['\"])[^'\"]*logo-carousel[^'\"]*\1)[^>]*>[\s\S]*?</ul>)	r   r0   r1   rI   appendr2   anyrJ   r5   )rG   r3   blocksr4   rN   s        r   _extract_logo_wall_countsrR   =   s    iFF 	b
 &
 	ekk!n%& <V<<[[mMM
 	*E
 MM%++a.)	*  +l5)*+Mr   slugc                     | g g g di ddS )Nr   total_candidatesby_rolerS   semantic_varsselector_rolefrequency_candidatessummaryr   rS   s    r   _empty_resultr^   R   s      "()b9 r   rY   rZ   r[   c                 .   t               }| D ]  }||d   xx   dz  cc<    |r|dxx   t        |      z  cc<   |D ]  }||d   xx   dz  cc<    t        |       t        |      z   t        |      z   t        t        |j	                                     dS )Nroler/   selectorkindrU   )r   r   dictsorteditems)rY   rZ   r[   rW   items        r   _build_summaryrg   \   s     yG #V"#
s=11$ #V"#  .]1CCcJ^F__w}}/0 r   cssc                 J   g }t               }t        j                  d|       D ]}  }t        |j	                  d            }|s d|j	                  d       }t        |j	                  d            }|||f}||v rX|j                  |       |j                  |||d        |S )z_Return [{name, value_hex, role}] for CSS vars named --*-brand-* / --*-primary-* / --*-accent-*.z$--([\w-]+)\s*:\s*#([0-9a-fA-F]{3,8})r/   z--r   )r   	value_hexr`   )setr0   r1   r+   r2   r   addrO   )rh   resultsseenr4   r`   r   rj   keys           r   extract_semantic_brand_varsrp   l   s    G&)eDDcJ 
M%++a.)EKKN#$"5;;q>2	Y%$;9dKL
M Nr   c           
         g }t               }t        j                  d|       D ]:  }dj                  |j	                  d      j                               }|r%t        j                  d|t        j                        sZ|j	                  d      }t        j                  dd| d| d      j                         d	d
 }t        j                  d|      D ]  }|j	                  d      }t        j                  d|j	                  d            D ]N  }	t        |	j	                  d            }
|||
|f}||v r(|j                  |       |j                  |||
|d       P  = |S )zzReturn [{selector, property, hex, rule_snippet}] for hex values inside CSS rules matching primary CTA button/nav patterns.z([^{}]+)\{([^{}]*)\} r/   z&button|btn|cta|primary|action|nav|linkr   z\s+z {}N   z0([\w-]+)\s*:\s*([^;{}]*#[0-9a-fA-F]{3,8}[^;{}]*)r.   r   )ra   propertyhexrule_snippet)rk   r0   r1   r   r2   splitsearchrI   substripr   rl   rO   )rh   rm   rn   
rule_matchra   bodyrw   
decl_matchproperty_name	hex_matchr   ro   s               r   extract_selector_role_hexr   ~   sU   G+.5Dkk"93? 
88J,,Q/5578ryy)RT\^`^k^kl"vvfchZs4&+CDJJLTcR++&Y[_` 	J&,,Q/M[[)=z?O?OPQ?RS 	*9??1+=>		<H$;$,$1((4		, Nr   c                    t        |  d|       }|sg S t        |      }t        |      }g }t        |j	                         d       dd D ]|  \  }}d}|j                  |d      }	|	r|	dz  |k\  rd	}nA|j                  |d      }
||
z
  }|
r|
t        d
|dz        k\  rd}nt        |      dk  rd}nd}|j                  |||d       ~ |S )zdReturn [{hex, count, kind}] where kind is one of: frequency|svg_pattern|logo_wall|neutral|chromatic.
c                     | d    | d   fS )Nr/   r   r   )rf   s    r   <lambda>z.extract_frequency_candidates.<locals>.<lambda>   s    DQRG8UYZ[U\J] r   )ro   N   	frequencyr   r   	logo_wallr/   svg_pattern
   neutral	chromatic)rv   countrb   )	r5   rK   rR   rd   re   getr<   rF   rO   )rh   rG   total_counts
svg_countslogo_wall_counts
candidatesr   r   rb   logo_wall_count	svg_countexternal_counts               r   extract_frequency_candidatesr      s    3%r$ 01L	$T*J06J"<#5#5#7=]^_b`bc L	5*..y!<2e;D"y!4I"Y.NY#a!1C*DD$ +b0 ")eTJKL r   c           	      t   t        j                         dz  | z  }t        |j                  d            }|dz  dz  }|j                  j                  dd       |s9t        |       }|j                  t        j                  |dd	      d
z   d       |S d
j                  d |D              }|dz  }|j                         r|j                  dd      nd}t        |      }t        |      }	t        ||      }
| ||	|
t!        ||	|
      d}|j                  t        j                  |dd	      d
z   d       |S )zTop-level: reads insane-design/{slug}/css/*.css + insane-design/{slug}/index.html, writes insane-design/{slug}/phase1/brand_candidates.json.zinsane-designz	css/*.cssphase1zbrand_candidates.jsonT)parentsexist_okr   F)indentensure_asciir   utf-8)encodingc              3   B   K   | ]  }|j                  d d        yw)r   replacer   errorsN)	read_text)r   paths     r   r   zextract_all.<locals>.<genexpr>   s     ]4DNNGINF]s   z
index.htmlr   r   r   rX   )r   cwdrd   globparentmkdirr^   
write_textjsondumpsr   existsr   rp   r   r   rg   )rS   service_dir	css_filesoutput_pathresultrh   	html_pathrG   rY   rZ   r[   s              r   extract_allr      s>   ((*.5K{''45I(+BBKTD9t$tzz&ORVVahi
))]S\]
]Cl*IFOFVFVFX9	B^`D/4M-c2M7TB&& 4!-@TUF 4::fQUKdR]deMr   c                      t        t        j                        dkD  rt        j                  d   nd} t        |        t	        d|  d       y)Nr/   stripezwrote insane-design/z/phase1/brand_candidates.jsonr   )r   sysargvr   printr]   s    r   mainr      s>    chh-!+388A;D	 &C
DEr   __main__)__doc__r   r0   r   collectionsr   pathlibr   strr   r+   r5   floatrF   rK   rR   rc   r^   listrg   rp   r   r   r   r;   r   __name__
SystemExitr   r   r   <module>r      sV   I  	 
  c c 
+S 
+S 
+s w *s *u * c g C G *  :.24jPTUYPZ	 S T$Z $3 4: :c  d 8c d <c  z
TV
 r   