From 0676d47b1ca09128a9f5c752e2a55e885b810a4f Mon Sep 17 00:00:00 2001 From: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Date: Tue, 22 Sep 2026 20:39:47 -0400 Subject: [PATCH] fix(gallery): gate committed gallery drift in CI and prune stale pages Found in a review of the Pages site: - docs/gallery/ is committed but regenerated at deploy, so a stale commit shipped fine and drifted silently. Validate now regenerates it and fails on any diff. - build_gallery.py never removed the page folder of a renamed or removed entry, so the old page stayed published. It now deletes folders that hold only a generated index.html and match no entry. - signpost-preview.webp and wall-torch-preview.webp in docs/gallery/assets were referenced by nothing and still published. - The tag filter offered both "render" and "rendering", and both "transform" and "transforms". Merged into the majority spelling. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> --- .github/workflows/validate.yml | 14 ++++++++++++++ docs/gallery/assets/signpost-preview.webp | Bin 7016 -> 0 bytes docs/gallery/assets/wall-torch-preview.webp | Bin 20888 -> 0 bytes docs/gallery/index.html | 10 ++++------ examples/gallery.json | 8 ++++---- scripts/build_gallery.py | 10 ++++++++++ 6 files changed, 32 insertions(+), 10 deletions(-) delete mode 100644 docs/gallery/assets/signpost-preview.webp delete mode 100644 docs/gallery/assets/wall-torch-preview.webp diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index e6ced3af..61c6a249 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -142,6 +142,20 @@ jobs: - name: Check falsifiers declare the budget they target run: python3 tests/check_falsifier_targets.py + - name: Check committed gallery matches its generator + # docs/gallery/ is committed, but pages.yml regenerates it at deploy, so a + # stale commit ships fine and drifts silently. Regenerate and require no diff. + run: | + python3 scripts/build_gallery.py + drift=$(git status --porcelain -- docs/gallery) + if [ -n "$drift" ]; then + echo "::error::docs/gallery/ is stale. Run 'python scripts/build_gallery.py' and commit the result." + echo "$drift" + git --no-pager diff --stat -- docs/gallery + exit 1 + fi + echo "docs/gallery/ matches scripts/build_gallery.py output." + - name: Validate template Python syntax run: | echo "Checking template Python syntax..." diff --git a/docs/gallery/assets/signpost-preview.webp b/docs/gallery/assets/signpost-preview.webp deleted file mode 100644 index 3724acb3e26d6ce9638c976482c457e35351afb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7016 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 GzyJUyjh*BG diff --git a/docs/gallery/assets/wall-torch-preview.webp b/docs/gallery/assets/wall-torch-preview.webp deleted file mode 100644 index 8b4c01f87d8de729691935881d2d7ab0d573294e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20888 zcmV($K;yqsNk&GHQ2+o}MM6+kP&gojQ2+q2<^i1nDzF5j0zOeFkw&AUvMnMqXwpCm z32AO~tz3^1!!zbPGyek9|6l(zHg}mnrRsC_AC|n9KV7rituN-T(MV6MN~KTtn>1EW zlE3Hw-MDxCZue%*evf`NolXDT{hsoz^Oev7yyt%-Y4=|iqk5(GZLdGb`&Idy>L1Jl zp|_ZC*?(7mMV^2kr#`S=u^xe5bf5J-rvG%ZtiAEJzN&0x{9l3{llxu$k2!0jc>~Tf z>N*cIAm4xP|M~bT2kG1gwWpLWEmsXNdY8ITxV2n13(dnXcJ7!xOWi13TCN&k>YzbW zn{C&SWoh*|s?uN*={Z#c$eMj*d*bP3hZr(eSLI2*_Ex+y5 zvn;-M?sI)Ve}9SbTla(p(vaTWSSpjQ*{RrBOMu{`u*@R#Q+v?b={Bgo)r1*s{icdG z#wxJJeuc#bR>3<>qy|yrR0x#~ykam4T?+mjw5*ibH1!~yy?tGDj>V(n{~~5Ovld9& zl&SWK;x+HVrNJ}zLVXK~#D^gT*4hPnjtw7+R`Dh4qmh@oFz&Dq8-I(36Xd7L#=hnB z{9^pr@W;;hMk7NdH-d7I?_jg%F8ANQlfZ20KI{_Ty$wI{P_xqRJT3+^YLjjkwd!#B z*!^jc>5`5Ct+i5)q%`phd7Ny$IuI2js0kg!xrU^@|6fq;wayN~LSDNp;dQmZ0>)^sQvP0v`SsqoOU4MCwrf_jqOnN5Zb$ zX}1sSZ^s=|9)~NJd|b8`FtbkSQiW|#nWYmAloiy-F>^xg5Dfs~dOqxP*);tiJBa4d z6z@)S@9zw_p6g3lEWys0Xw?gjTZHOY@46n#Vn%g{quHhN zfM8DSOHqy&fh9!qnJ`2>Pb|!=giC$q*ggmTYvBmO?o>eFqesZUnwcH+X!8TGF9JRm z@BR$nsn(v|*0H*8@hpll6MH}*B&#=Pt`%+$3_)q19Vw#^@UOAu&zZ$E`6 z0ZB@BwoktM6JGu2x~t^`XYy_Qn&FH&pL$%0Bt4PxF~GV?eU6xK>g)2>cp{VcPR-sD zy;^NFEQwj3P83={=NG|`&YwDb>96+I1vC+E()#FydDs=985A6qBcu(zKNxnAB=fe9 z99UFR*b~zQWd=OHqA(?-TuUY@ZnLZ>Dnq$WGiaHlj4XiGMc`uH_a`E)XRdDRGmd@~5pHKdM{B^pmcc)TB=2ggI)J z%5AZ_9b+FZ&vDjibxfpa%?Y6IO@DR$)CsaV&(K9xWx27}G5i8_e%-~@K3PNgfYRD=+igQKLrXAd<7 zBoLnSukOFPbp&a3LUMgIZ> zD0MR*W7?^Wd+^FzO&Ymw5Ane-2E0#p#)3*wh8}pV|5}iP{%9NiF)QF>jdX%hIOYoH zg&r6F!IS~ZPa#Oo!;;z~ul3^n*Y{uDLwx{?`|gzTwNi3Y8MOwN(XGa=WnP^k?|A>q zSS=|V^qUrZukk|0wzX#F(ELSF7xKCLvK4Rhe&=NO1Fyf^UCXzdO$VhzEcUe4P36I* zjxdz;#q#Z?4N-RM$Mc&}P-YS8@E{_2gJt6)9;UPHYkAN@y~Ri#s*gpGFhpyoQ=wz1 z-;+dXH?E@2g^urBlJ&$RADFcM;BF#P8h61gVQ(T{1e)w-Wa5g$A+!K-}699wEB-Mv~JM4ykWwn0d zWoJN7Vzjwr+ln-2K(=e=Db8~+CT6y|%k<0hS$UWI;d+J~^vYj!c@Z!ms}Pt0Ncd@# z;8nW>f*_xoEe8S8TzOO2?aXR=VhUVo@ovfMR{W^!lJbUl?DA@Mio|;j-r@u1EMf{-tx|Km^*6%ZE zDP*TR@veO9SoG>en>Y!AmI^h~{sQP^q^B?ong!#H?iXkE#9&BF27i|@YPnw)T8(H4 zS9cpH^KtGz@r`kPnEGLa+m$DqTMjQ0*wZrQbo8J<1MP1$^mT2W&^E#I54KjO@=$lR zpCr>AQIop`*rC&kf+jD3O1O9Gc`|`gdrwS7D<`W9H6QthdHAR8ieL(g<#;0LHu-xK?LiL^B9LN)lK#m8+YOPizt0n zc}xqkd(DWSK=~;mfyV!pxh*H|&0YqJ?*`?qzKa~}8-FEd1_&9ES2T34Mtb`jFZ=|9 z4U-#5>y;AAed%n zpSiUir?3z^HHQKnRpL}>;rit<^AnP-xLd<;VaANMy|m8ZOU$ zj9yiV5~wvPm?&@oEHQTGH>R=<**N0LNERSz3UQQbRJE)W+#b94{(~Qs?1aG(oho$N z&|y?>xcjH}xc)kxN|3`DF!j;vp&&PQ>KBV`bW97XkU$(PSFcj{dCFp`-;##wO!)W( z3TDK7m*f9;m#7cQ){wI56&;knnPKbsCoUt9(cSEmDU`}(GLhS=j>MgjL zLcxlv6d_<1ZfC8;a2I+5)VCcjX~F07N1}1=GG;+=dn+j@|FzofcDr4uUXRTbJ%FYB z!8H)0NplI+(doSu8E9-4v+vbdt_3Rlix{^u@cP%-V2R67nQ@DE7wWtfeMSkpBP!5r z-!UUjFAoZH5Z^GOCwG6Wm9N1^i&WoVn?^-NGm4WY-qPQ2V-eavd`irj&l7yt12F@R zrsO&L8QJUsa@kU0^cK!r9zlolKJ%x{;UJYQ&ECQ(pF1&!bHRc9v(h@isrvaJ?zCO{ zy6Q+~A0p7}*~;1TB!0CdmP|vePSlh^1SZQsmTd?OcsUp{iag;d+Xq zN})a{y6ZQLC>hZ%+cx+prZFSJM7#R@x_^mS7yHQ>jD91j&qGJ-mRC*Xa1EFx{f8)0 z?)5hR|0q#q{;_GHH5&m(W7-re#*wk(Bpz%80092zMIWTwb?}d?W0*dVWtzRmQrxw! z0y;RTW?!qpV$r|vF7MP;k4;K8qm4^m{I*FyIC^bar%7KGu}0%D%=mT;;%dkml z+c@*g8)$e_D@8`exP#MYeG2C?k91oz`fJ72#J$oa3{jy8-SwbCod9ZnZ)nzderC1i@T`Ry>~V<|B$ zB+$nPYBf1;H<2X-7DQPaw_NQXbO3Hz#wdm5{2G^I-Jy4JLy8fe7&I!;BZ`p@-KBnU zzCVt=P4A;8-_jAOE)wC=xr>d()derRN|}q5BZu2_Ma(Dhh?-C|Ak+Pim#g&i!dq(A z^e4E}AWhB^{}DEq$}rF@Ku+P8k%BIM5Y;CH%b^bsrIp99y!>Rb!`cK^0<*&hZP^8C84 zUT`$&^9kBEYkjHlPK_S&c9t{bISG|}4-TpnX#mVZ0k~wo zf6((xt&Ch&-1G3IX2%dFq{6+n-LH zjbzj?7GKz z2)xJo`iVNPJ?;RjFD<2na~Y5usaG`sdS5b#$oRDwxjsXfk{M7} zJ5)aaHHM|7=YyxBHV}HE{VYCEaG*HY~P0~rQKb=PafH-rw&Z=7{O1+d6Y%!!Q6VYaa$(p^IKH$11eu`ll>cz zl!^;QEA!}!flPS1t_F|^ine#iFNDQtn66D^_Vr5zBT-B@pi$b7y}MZx!%jNgM~s*< zr{+gP<#vD`fr^4nmbAh;nu#-BZQ>TPn*6-ETfP>8`0^Ebp@P6p9)=~pOa>hqnCzkh zYy%`*S=`1wZa<6^T9#U@u=Dy*1n>bS(UY#?Cctk1DLaAbhhQjIvzpMV9mLi}GV+ah zl~7dlXdZ|!Y9&?8vI~+~84y9{sdUlj6KUX3icn2sz|<=H4)4j~0E*jjIU6r+tUmaD zaW6>A*t#S@F?8VA%>+AT_P#(FR>|PQqm+%<*rO}E6pEIn6(`ArD@-tLv+L3$-%xDB z*c2!m*Zu5%LM7E9?N@B_=j3h#Wa0*mXrdvDTT)ua-Ig6l>&o0O(%fA*lH$Bv#xy-6 z@RM?QS{@+~OcCYNxH4do3eo^5D^P@-qZ$Q@;}`8~R(h~RQUPUP9x%J)H+?vK^KuE= zSoyyD78j#&L~)U@1ptPEK0Y8%?SInzUV|gBT$#6}V>ANy%hm9UqM^@{ed_eZcY3gf zGIE=Hfi_Y_I+w8DH>c4{Tb_y2O%vzjusa-6r77uNGMRmIq`KjEXPo+Po9h2U<(Il6 z0u1lfESR$vc#v{epgX6!1H}XcG&qXsH|TJFadPs4?{Ilve_(zc&_6-4b80Pn>%2k*718# z!wccrMv7tGuEaHFPh(h2l@nrF2)dBofXoF)-bH3l#dYakCW!o~Y^QQIQDgVPhi&hv zU5Nz{3>W_vVYDDz-UyhPCe+=6;H!F??S^a$Y0CV09G^nfS((2A!3g!_24p9kq7 zVT2mw$ zQ)p`j+(slPr%+pTd4A8cTT$jzvbU@W0`3qkVP}bd+@uW|S!3=Pk~1f-C&NW(L?lVF zwW;dL?k{%rY_W@pYXz9n())AU5=)_ce%695pVVB_hsx|Wj_K2wSW9vGpiI6mb9*t@ zi*#LB!wV)|1-t*wtB8(;pZNz6@u!D6d*7%=-X+NHjT^pk@8<*eHqJGD{k~bMqh`D+ zdzm6TP7plqSR`BehT$LVtZdlvIBJi?X|hQ(OzXZeNI%<_Y2Js6-y_^eWVrfL`h5Y$ z@rs4|LYR-q=Q!$L&?79ftSw^Q@@kqtDbOl^k8K3wi7FLV(n(1`bCFZ~o|-nK-*?_- znOQ1vh#t&d?Yn?B;Xmm85(UIhzzmRH1jQ7{z?D`F)CoSRwfdEMQJ`2Ds%T1qqK+fp zX%?=rmRlgX-*-RR1gEMHP?-}ZQa#0+r~mFIaVg&1tsrbZ&^3;X+%5>)WF)c$VPH1v z9Lup8np1g2ygW>{m7tO?;{eIMKJ^Z{_nbtRueXz1_-Bq9@E4$h*Is|vh<>Fm>F+)h zeb%z+oRC4ov^$-^0%CxOdez&LNxdwh)PejH%>**;yVd1lSkqsyj_cpiED6^<{HG)5 zx_Q%qIuQ{}h#7w#4|8C3DZea|+ExES5L}p*Ftq{M|EbmkGmOvdu>d_v5UVxm*OA96 z3q%D`=tv>9@MIW2oM3OYClO=d7{uOU(Dof$0_AB91$Z+PBx#3emFK{yW;t&HGr(Z1 z`@Zz5wVPV9|8n&ucYV{ z%?=Bwl-VG@=m(rYD@;e8u_QAztf?qiw9#?Z&)f$XZBtTNDd*(%f^_L5KV`&!`xO7c zN*{YBCvYn$3A}nFkK`tgYi*tsI|%rvfc-fXh{|giNK!7P`BJMdmgqPnY`_zPhw^oN z8yha?Vbv_)b&t&y^pwGY6)lp`X3%otB>H@O_~~qE+VchBkxi!4F)!_oIYQJPhC#DL zTQ|IgWw`i`ooXq1`tQq<5%0X-UvO)v&v~L6O67HEjDNE$K?eSN8U)*#6StznM^Oa7 zE9H{aWgR<*ae$QnK&$B$-Kc%uZ}M^j({-fNA{5Pl_=_y!#`cy=2t&pDERP}Cv@)=ir${}@NW#_MUrHgUjG+LmWe%fne0+|Q=(sG2HmN@J zuKHI?k8M!Hki-f@haw_0vl)zXRr>E#IBv}M1GsIRG9$6XmRa3dAgxcb;0f5@uT;3c zOc*u$DUg{TJ>}VGo&?|Gn?LkJ3f92eCjtgnFW-iOrR*XZx`$wttb|<6n>2sL0dYWH*^Vr)) zA@<}PwT*LW=R#pPmT3ae7D?j(5#o+Ez%@)g6WF$nkN`BFL!1kFkDl`d5)vj;r`0_z zWnaF7e5~QcdG$7==U2P0Hq#+D#Y??oN%mUi6x$!!`i0Jgt!A|c1;6EG+(fgEak8+$f_(7U;dW65 z?f*aj^^%&@9+BDwaaFAR$x#+Sxq3a$X2J4M9;qR4{=LV3hPv zk@$yfO5||~2!-j99PXk*n47DjNoK-NeXJT;Eg-K&*U+sU%|~Y}1FdM36i5Et2Yrk# zj3=rXxX>^X8ixPN5Y7BnSX>lMQydp_yd>o6{^$@RtUBQ0U>^+7`5q+D5cA(YYDJca z4F3h)#R!!r2sqhK75V|le;tqui%F`WDpD%gzEC4`3`V8ZM2f-C`CB<>fWka7@jD+t zlR!EfSo9TwTAT{IT3y`-Uhy4x#?SPZ7(1hQ%!T*EN}DRbHfu^vlU|+}nxyXfLM_ZW zPkF3zUb0j&8iz6OsU|X8!B+MPb9u)Kr4Mt&i7e6za;nOo#9#(TN4s5p=6wk3!H?1A z6QdD;>P|}UdFrTolp6k#TbM@0#t#>q=)9>6NrLt@Ykt^1FDN33S|2wH0$IM%%M_qU@iM@geAK{`ctG_sEiD9%keJ z$(}V$%>KQ3OYu*2`Qo!qi=u^b9Fx^Fe^k$eJ!3qHm_8D+2Ti59Hv?Jb@@@-Ok%~Qj zKDr6==wbU;Mcp|cOP2OZaz*U2v58-N&p5XY;MIxj|BZ z3bAdck)B;}*pC=d(b35J^&hp)RQ&2Ljsn{p-e6!(r}u%F14;Bk^m;#yK$wskybO=B zpDb$V-N*{lV7W(Qw<}GyqppkJGz)$K61Hg{$Hr^t%obLsOBX$pAa!2u zre7O5&AIHDr_>6FFl(5{M4~H)(bk@3fUC}(b6|dy8DW!%)2eLYWHfq|>e&rwFAKt+)B&U&vvATfA(T@$tECMygX23 zL^aO&zyRcVH+;x%7@o=vEgTU}U()cSim`4VXp?UrgJ7xXlDqYS1Se{60-CtaJl?14KLczQs{D`R zVrR`3`;T%#NCWs02i703{9vqSt3{_inbb!j1uiuAOw6WNWo?iu+Nmx8qxSy>^ix?{QO5z--Jdf>XgKmEUyK!Lol#|Gm- z^Z3fCjGSJ5g-F}Sx?k(L5$VB;RPmwFM!-f{$iwybi#BZOZ=W#lulj$=6U{5m#NO8R z?lJwU^SLxedib+tD{F>&TxtqFA~LZh1;AiTe1TtB>0uIjT|_`plZzPIg`4oQ2ghos z7o#Adku=C2Mtf$;vP&wvS94riIjR%9Ps*?;(Gp=`CyFe)5r5>Sl&4_>K^-5Zy z$xlga1+4%86tn;ZEvs8g1px-9mI2gpIp;Nsu4n`vZki+ z$pjPOsZLK4MEAMfdK=W5fl`S<&zqgwo6FX|tfUx2hC+?}k>1&Ko#FVGKmY&$3nl;` z;~^lj2$RBFXvsqbRFPRCz&EyQh~^L1h{W$DWrW|a98bpr%#93P2~PE+qEpckzBpPT zD54A;_v=)^y{E1#tDr4$>9bVC(6bYggT(x{000000000T*wjpsni`Ex zUf-U{<(DU0Aaq|q07nsG$pY}7r(&YJK%vFlldtYJbqAp=6;1osduMvCfz7;1(8mAr zIC1#kv0mOtpQ*37``adFxp5_O3EV6uh$l}vR@pW&n7|J1HqX^b6WugR6HB!xu$S>V zJZd~=A5}P-63td^G%7fsx>ePUhtKMN?ib+aI-C6>VBWv`_MPrr>zTIB4wSrbLZ3+9 zWKm9$8=)FakACs2{NJ$0EG8>K2GqB1Ob>rRWcO>POV|G;jA#l&FS9K4f&E!cCzbbnecd0e+WkKYAy_7MX6l*ynG%F4Uh4 zLo*K?8|byA=CFESzf#n%WW|f?p8Svf%jP|^^7QVFeY_KG zG*`8+srUTToH)yJjvNMSXVpK1tXEuwE~WFE+H>+&sh8%rWGgQTNRB*zM`rf62wb{St9lb2UJMNX@WP zVAwdlaBT{I3M!;|(%|IlOt@f&Z-?*q{i1g6@_Qp(u;(l*yqz5To^A}5hBtRW3qT=X z;009hWh6^%57lN#-b<6UQgBxOR}&fD4)y#O`SEPjVQK8qL#2%(lN>4v!h5j zW`6`B*Mnw-sn`yToVxjSYngK*l-VpNJ&$Yv ziY)m!-Yw`sM3u=iZgDE6RBA1Hgk}H>v_(Cvgdb)S3y9K(YiA{oTz4XwUH{MTI ztUHmi6VL-u3=`he8jR-@j^Z0Y_Ug?d{-~{D z${}b%{*Ae~7+n}vyyE((R;alF;+-ecg64+bhz-S!bU2W19F2$kSAFb`{}~N_dUTK( z+$EIN;pDOA5ta!@f6N(#?g-|E)#gKP1A{lGzd;(oMhZ|MVdQ zM)cid+C?htw=WJNDF3{IXU47o#r~HFvC1dDVjHIHI^E+6u#X7dqsw)7O7pOiSvdHv zT`=8o*aB$u3-;ZUvQ+roF7__C|L5GESLIrk^hZvm^4J}qAyg&$Fv~c}nqhKBQ}CqU z=4w)?qb$D0?f3N)KNXI7JW7k&iCGGbHA3e>{lSG4#wJhPJH|a%QV+%}p%%d`dp~}z z`{v8$i0AD?#mIwuYh8(;2TWo!21y`*I=i9Rg*xOheJG__&-wlW6cM*3^*#wVmw zC={dPrEOI6h7BjQY^0T*Vb15~>;F8m0{%!vYsOw;o^yAds9Ph=hGpX<+C6A1k31ne z^dkh@w2gK71-#Uum}aa=O!@8<;#1H&1z+~Kbw0LAvdB!DtwvE8)ocz+mgDo~#Z@MC zHfqG1k`C2&tR*2j6~2JL>K(?x*rH4jUnt+AP*Aa{q)aqs^c>Bxh>61~r|c|*%D0%< zh+O6iPUc*Mz-@Acj2tREYdf}-AA-4}%V?Kxtgi-f1sVl^G<>EfI7G9rQ6Q4$>uEB+ zyZ>3p60e&$feq}bhy3jXB;0%!9<5MHX+2p0@<;6mq7>BiG<|?W2 zbU~um;++gJ2|ka$&x3u&cZAhoTxn9{zJ`?xY4%fNbuQK#dZaH1NdB)GtTZ$Puh)aj z?m)UqY7ZvNAcVOR%N6Zmw+DznB{E7v$kFGEP>dw&dSj>r==Qe2Th#D8Ios0`+TSEc z^2@y8UkX>1w4L@8IqhF#yzpaGJO#8tM*yCyZ*?R?&uMIQFCSf>CUvx;!*axCJ_zdf zy%f>lhQ!A>>5yZj)hH;|*_*x!!{PypN}0ZrmH}ercSn)yowL(4W1h3EEe3!?6tGQh)%F_K>u1ik4Mi@w1^%n z^(ruieBvo>jr${&fJ8xD!MqZ^&Cg?a_q8pHka}*#goHH!_}8n7^T(4|8KfR5nGPdi zJ8kn$81hR}`}}Art{5RvPd>{y%7T1!No^J(B9V7!`gC*K=1@-OVE)OG{e#GgUe{Ik z>lxjBN}L+_v!G(R1j+a#ANGrZBjR*@Xqd4ZpLC<*K8q{RnAZ`5t7b9CxZaE63vyYXV5Bm~-3QxaNBT*W5Y zk{Yy~M3&AL=M1U%%l@|)#i{9HKdb-!*mNZ4Z4~0k#2C7h*+T9Amx{~J5n~fKWdV){ zVyl;!cWY2moE-Zd?Y5!!2VjT@A~5BIf1fQu2-r7mv?& z^1Ac~05g2v#PIs?M;;;23 zIeCJrDR6xTNmSEh#7_~iK6~M>)NVIj&7G?t?M@ce5oe8yeN!eB)XH2kKCaeCd@KAq zFv1Yr$Cdswmpf8Z;Ff>MG;tL+e z6M~6WF?d+@%6X&O>qbZdA7eJz66t5CX|5xmP@8FOPCrvPb94t9M+tFfWX$pFH5&))HCWi15@otqoZ*s^CX{#G-N=GhugT*!_m63i> zPRQH->8DEo$ZAICoe@JuFb zH|*s*VM0})g$caPVK_n^Q>&Iop+}>n_QrO^-2J|H^tf{Kf?YVE4xr`UKg?mqLh6g$ z@~mu=gJz5v@@nnH&l3+x#buOLVn8?brTA&ozi+-F4s43|4#$2=lt+Zvnt~`KMQ@Q` ztcNFhj#m!nu}41%6U;)7F&06bWn5X+)Y8)Yj3IUrrDD85O@B`oOrxrQV~SRBHGO^N zEa@XlGz+aic2k0JSV2zh+_tEUm1Bri>hkQ3*9cRQ3}HT7l1^SC zT1t3Ivgm+oyElr;+(FHct60P5f7Djw}M8M7d1qoEP564wnucG>fhu<^YLF ziX5Tddm?T5@NLDnP6zkH3z+R@a|+j8HrW`$@q`sBC9iBSNf|Trkcj1hW(VS%DXwVl zagxYWCuD}I5ZM!{Ezu7E%H`3_a3ub=>g4@CbVMlcx9uZIIbZwI$kJ1Nb-@hTg&kGuWeB zSt7mtXFD&Hu0jg17-`N0>nxL`Y+6osks4T@=foc!0=(p5hYc8-2bZHy>14^YzE2d5 zO^=e5e}!!?3Ox6IF}n4e!Y|taAcre0XDbU2{O_t`m~Aad5D4TbpBfE;Rxl?}-!hW^ zg(WIowYT6+?v-)i?5TU@Bnl$GG&P}~;^Ga&U<%3A<$0SsIwn>BH?Ya$mvBZS6_W8S zaZy1$TX=>xjM7EenpbR!XvKjy@t0J*)98yr_1n2Yh-ggpbw%9OM8AvkOOKMpP8q=c zz603x7a3fzOy4t!gS3U$bfw2J#O?A~jCwjbCQ+(dJ9QgI{9(>c;?sJS_)G2JWpuH0 z7_5pm68R&na6W-C5yK2iVO-dYC-jlgesJ=81|Mg3e1~}xSCqoH$};_S_Cgzg2WzX) zedsj@H=H+RyPE-ReiQLtKkFU@#OA;6ha9f5pp~W5DC6LPqwCFAT*G#Uh-@5ecO%Qg z;Z=A%`z!tG8098g7E{HjLT3OuPKV^BBh}%4ii+Vo8e$Ekm+(($lRss5iSU*tK1?ng zT?hHbM2N?yvOw0ZBs+6$-Q$wFE5C;k8uOW%`kgG#lN7lxxZUx5!Im~OTp0Zg$?y)s zsk&--_@$%k^=)|9N9q{*2m)H_2jYA2oVn=>PtEs+FOqN_`3|~~z=w#V1Y(V4T_M+I zksE;E^TBHbVr=lYp>mp15p7-~Z0(F~$OEVPVxQOXc~-r@m2Jn0khE&bD&H3{pDNHa zZ(WLxF!P6H44yZ{%`B-IN|B~DoY5S+jHC*u0qrN30w0w(-E0hX2NmR@(k%$kf zZ&8xhv>#s7%kX)N8%HY}pfg`xEtC(QWIjyE!2D)v_~8z^r)Fyc(RWScEy8`3T1H$f zvHBc~LWOtp^*c3fD*u9ZZ3ed`pW%A$OrU%b-C|%9avqZ+&VJ*FBiMbQyQvACImZM? zP)dklhPGS14zHvqmozr^%~{2*Ubqj__Q@gNPWm4RS-%*i@>+^s7bpMlP=UvNpnzZTNcF1mN8rzL=28hEW^=s3bUZNLwCPYUkevLhToyo}Rf<hJQe$oU1}vVvP}f>C

`KsK20|$Ah@|Cvpl3tRnH>ds<_a%I+c{M&3E`3p8zhv^nC-4*&y;6mQv+ zKIM%^WgP6OzJ^xh;zz}h*-EOt>C&^DMV?^a_}t%d42dPJg+=1Gd7^xBMyCg-;z;ig z$7vQK2ZJBzuo$Lp;wT08*>}9Pp;NS&t*{7+UW3Ed0whCch zZ2(?-f5#J!j~#Rs5jq?aBM)fk$hyXd-k}78UkE^NsxvGie46B*9rl>#d{C?t0_l6uT-+ z)cVecBS{k`3~Rb8hy4umMvDww4xRjwicH=#iNQUxy%SfX5~mlud_C`5*vbJyn3b%- z<-BdI?v;FL=l_CUz0Ez;s3ZY-IAoDfM#w0QwGOjk4`k>0gVZ+PiLMPk0j|`cWEsk7 zwIBCc8AI=;Rak);1mhqK9ri57RW*mfz3SF6{7yoHkTcGP=vA|=c|o5`VCzJaF&h`X z#5FYT7JoLc#XI*GBK7Kcu(Y>ee=t>j5u;b~>V-wKYR!tOO9bp!Dvu6$An9q>!$urhE&w+x z{Oae$lPhpx3GBlVpdL=C??!@v{-kbDwE772a7*@%-}mAMA-ia%vNJ7$l&_wTg|h_! zKF`8cCX?NPqO8Pl6KI@T8%iASjkJ46mWzHJQgVcL@wT`Rr8MADMSdc?*JJ0 zdxp$oTBh8?GH2XCZHprpIwp-avh|TaCboA}&({4T%;dP@>0Fb97!Rmi0nbq@Ob1zk zFL%;=+T7ZV&*Azmu~0ak9d1@F0YrsYlMUIHaGM0g6Ed|9-ilG(P;31v!FbVLB9 z6yFp~1#3}G;Mmu+UPp~9{Atp1L>07gzxwba*hPP6 z1nc*WU$WLlKmDlNEL@8SPHA&P#oDnhZ;DN9Kb+&hgd>D%{M83}MCLt<&q()W{q4IR zIQJ}ZZ#j2fRi~*P*+fxm94vxffG}t zWE*9S$(Z$kqP?{o<8{eF1a9`fCJ-W#C!)gmL{Acu61e*&bPE;4Gb|^_I4aNP;SD@F z#yKm#hd6muF?(Hah8U`_7&YF$rxLnLpzOiLSSyC2GA-&&=VQh*nLbVTm^tLS2ha{> zYD5tykz{%eFE#YmnSw5)0_WXz>`FIdobZbrwBI9zc65yK zLtQkYH^J?g;hnhj-+2vJulYgoaPfkZ2-klGXE%|iFjI^-DGwm%v`O;Y1My3XL6n|O z$pnvvJTRev2fL6#J`{Coy^U`0=qR> zc2BmXX~Ai%GGo#;;nrd{nZDuug0n@s$cW1Ee?9<5pCR6_WDCwBo3~wDHYAMo>MLux z$M3^FZAw4f=d>gHx6OfWUPGlOg;szL7Z^U++WCiFuUriYAyAx;GQZY6p!X)=Y7}6H^phN#!)K(cF+C;0w@8&x_5NW`Dk528l{-W{KQp z6dt}r5u2$3Bwg3Ao1Us>{%xSBPlkki(wPgPE78bZgyT{!Q9YRMLv%U?XSt!DG~`k> z&X=gG{m=y|%qg8x4+w{bDwZ=m1>(S)F0I~h1yCTu?;|?myLc=}*P|bT$MO66#>pS8 zC(TN=;iK+^rXdKdpMk`2NAcX@K$S!DzHxRBcw1b`2)8~~jJ*<_ULV1TNLYymj%}hb zp+?Hf;Y$fBvBReKA=>_1MLF5z7r#;?#008vIZ_D98R;?{DHkG-cOnko?6d=1SJMQn^;7Nat09BL&(E@0eDBN)H@2!bBmuta&nr7_!O# z0{mL#+R_4ayp|mVj=lWk5|!U8N|3g#*r+O}(zW*W-c$kG!oPlznmg#I+7qn{0lv6< z84_ad&CU`F>duVbM1-vB1?W`>`MPk5bc&BSj7Q=6pqz!{iS_C~K~MwMQ9=e_XA@2i zWR(2zk<88wR+MD#-u#9{iF-7&DsgOTUbF}(8${kqpHz03hTf)RO2&*l-ntF7$jfhI z-D6;XF)Z~54(A9|dLK0L(D*TO(nIprY~>|0N{pO#cA|h+I^A3QTI_&$Lg{7{OK?+k zEDWRO2|lD@b=m5P=1wfXC)QYse6`HHYqzxotiXFN!sjp0jfBG$)=1YqDNu&2vow*!Zo=fmt1yJ783Wd6uKi z!B}#3_~CGL(`iQQn>cRrbH-yPv*`Cvo{J~4DLrU)IEV1ZuDSKLLSezBz{@c}qHjA~ zu&4`E-P&W@5fg=!3!}rYTg8#01k+h$>;s!9VAms6#bbf#9=mgCl*r%hbI%_V2+zh7 zA7tw$6`*2akHvr*y@^e z1ACt;fs}~;%Y>-(naXBCRgi)C5~gYe)N474DmD1AJRA5K`jLU? zUtztW`&$!^w>C^kbp=CXV*^Q4B?5?6Kd>(rHC;Rl>WW4m1Z*xzDdVR%NZ>XUzV)9)h)!&J+=4H}hZfyOjRXb%UA3Y_b6=5t!t;ftU|9jj3TcI#N!AU7n^^~J*QvCn6yJJa3|$@?Z-$#)<8kvRu- zjXb)OMTnd@cJ1LTY`MP5ZzXk57K9utrR)c1>5iGT%AsoXD!Q$S^%>X2?4=kqpRwlT z*sOR5a}-4^GRZFtp@a2pzz@E-^k3K=c~SN!JIQ^;FC6+jlMHLtq5B|X3{TE)LJ&k z!&;kz_`wp68eh~p7QV9pOdPwssMUPfU@~2JuCS?d8a~=UMPaNmv3$6+(whB(KgWOU zWg8B+?aAtJ<;E=Vs7&|+N0s(Y)Mm9~Tp{UF;*DQy2`|Lb{^$*u7Sx9AzCTlQqFF(y z-)o!Yh$}U0uI%@c(%zK)r&-1_b6pHcD;m zqtRR|#zAQrb@T*$KTAplFwOuZRynOe>rMp`sj(H3jnL~sIG!q(i|@Z+F_IA8;t@Ea z`P@a#Vb3$-Y);EeLdHxpISQx>1Zq=S>RVr&36NRP-zycAgw$miGJ=gh22753DH=Yz zqDKz_W>f$LdDe}vDBd0c6DF)LX@UL6n0nVJv_M8U4MWu4N*hewwpLCHr7K;fg{H;@ zf>7c>41PPtCKuA0PDvwzMXM}Jb1=0$;(ZR@(F z?Ztfl15p34x5*cj{Sen>?rcTvrDw&x|I4Uh9NL?rNgYV-El2P}?7gJc$2@>V6r+pg z($mb(z5sE+qk+6R=P>uVO#qnLq*5PTi%udw)Z6M}TT`i%I8aOk73fT7cWm2?s4K#X z%w%Itty`X!D{b}6s+u1N9<=NR-YVr1C3R+Xen!)e+cGu~#Vk2D2Q@$^DUsr-fDSf? zsuRfOO@Mg~kvcSz%;{=AXX3+$cT;dmv~j&5GaI+g&g+{4`4wUq&n8WRL2yYKgsf%$ zp8aiF#PfIBZim2jA^&6O;;-yz3I^fGxmwbLh>0a96KoN%C9jhq{jmdKeUUbf$H(#< zMeHm&4HOJ{FR!FmzmhAP^bK2{De+zoUtby=t|O4 z`YWR)2|-;4bt02$!Epyq9S%|$whrUq9k{g7nH{iv3EE@3NP1km!oHf za1W@CuG7J}d&uu71>61#xvf!0^wq6vq(D~LMjWhNRO|bS9nhXGUittyHRgMY8}?_P`;i1z+8j3{^vE20uxO-x*F(8!m!^y}fq{3& zdS8Ll!kzhr&XKIB8HNCfI_^>&Iw8;?NH&#oX>HnDI5oJ1-zRzJTmJel(fF{ut3^o= zFsKc)hW#~0r=&NLtB^r}x7WZc#;x{;7$JD@txfG@68)Ek}CU4 z)xXU7ZlE*9%woQOwEcfKF$tPE+y6;iR^7&Q$xr{pJYdjtbVXzmr1!rE5@t9YXZn(l zOu+XE8?63Ls? z+dU0;>|2qZf0+;J&m{+|OI(cr^_AzQ0{>sucp~Ea)ctfCmpW0fi`O<&p*GOjLpxk6 ziGDkErU-tm36ivS%&Amdb9d=GK4jQGYVhKh~084J|&sm%0e2&4;31?32{wG2cF}C)iQ+rHg;|U9gnA9MuS%)qy%% zApwa^Ey&-^WA`4x_NW|hMm#K}UvtWwUo=tg442&qpbXUjXIp7@g8&sQ<@lsLj|8*V z+UUQomr(C|Z-yJ`zl4H$%XxE++gFt?VS-+x)H*6Gj$$r*;DmVMRfyMpj3afjjC}dy z=@t{53;>5cjwg`tOk~l2TanNTG9b3@)*P{_hb2Cmq_#Vp5HPp+nS zYi72cOagY7YT^)RdE}j!OCo1wugMsI3l#!O|buB z|7JKv(P6HmH8(rl{rJ_b6t$aE!5@kXnc_Iy@W#!I1S8!Dfu)fCCyrd~c#+Rks@{xy zvwUS)*q*CpRCsp!ZqpPg9?h49V&rc&WO3_Qa3IYn>sJ0b`;DNIf(>=89PAz##mbAk zml6K^E?Rzv7%50MG$ekdOFTT=%?xr2FJg1r;irkR8P=90mXD|p+B7?Y2~#X|l(rQQ z53gsFg=5QR@5h4@LYM&xOG0=N*H7tm@BE+eq+`mqrGfB)Y@hj9)MWB@VRE%c^P*#F z@25aaB)K6_VBNM6CCz!^z+rgXw+$dvxj>Fk)QOzhtKkt87^)Bp7+IUljl5Q@${cV7 z30Kd^1Sof|xLRLg=sYpSs9~M5=m#xRq7f2Ks1>&vcVl8RWo9oeJ4K*ogSZ^dmys}b zn&b5fxd#I`5JiV(o+vOO`HV=W6V|`Z52}zfD=@M%C5%Lr_H>2nY4Avjm^>L2M0TIs z1hPQOsaq63H2X(Zn$4s@j=I1qdaKT%L1P!XpExamples and Showcase - - @@ -712,7 +710,7 @@

custom-normals-shade

View example custom-normals-shade -
+ -
+ -
+ -
+
diff --git a/examples/gallery.json b/examples/gallery.json index 6c5de1ff..2fb69827 100644 --- a/examples/gallery.json +++ b/examples/gallery.json @@ -432,7 +432,7 @@ "tags": [ "world", "sky", - "render" + "rendering" ] }, { @@ -469,7 +469,7 @@ "hero": "docs/gallery/assets/prop-origin-transform-hero.webp", "preview": "examples/prop-origin-transform/preview.webp", "tags": [ - "transform", + "transforms", "parenting", "game-pipeline" ] @@ -551,7 +551,7 @@ "tags": [ "uv", "game-pipeline", - "render" + "rendering" ] }, { @@ -579,7 +579,7 @@ "mesh", "attributes", "game-pipeline", - "render" + "rendering" ] }, { diff --git a/scripts/build_gallery.py b/scripts/build_gallery.py index 657a0738..9a6f5e2d 100644 --- a/scripts/build_gallery.py +++ b/scripts/build_gallery.py @@ -1059,6 +1059,16 @@ def main() -> int: encoding="utf-8", ) + # A renamed or removed entry would otherwise leave its old page published + # forever. Only folders this generator wrote qualify: a lone index.html + # and nothing else, so assets/, contact-sheets/ and asset-sheets/ are safe. + names = {ex["name"] for ex in examples} + for d in sorted(p for p in OUT_DIR.iterdir() if p.is_dir() and p.name not in names): + if [c.name for c in d.iterdir()] == ["index.html"]: + (d / "index.html").unlink() + d.rmdir() + print(f"Removed stale page {d.relative_to(REPO)}") + n_showcase = sum(1 for ex in examples if "showcase" in (ex.get("tags") or [])) print( f"Wrote {OUT_DIR / 'index.html'} + {len(examples)} detail pages "