{siteTitle}
+ + + + + + + +did you stand too close to the fire?
+ like a liar looking for forgiveness from a stone.
bhM&g-q#M_>qk$UDt0ITQYb(+?j+z%B?Eh!br-Pc1i0JSKTxx!tl>nk2>wk7 z4rQ*T${RE-8Q{VL74UrOI|yS$danHpFS& ly$u=;T}A=j>hd+Fbmnc zWtNn%7Nb3ol&U%4Frh Mb dz2fZ!pLqe#Yv9~7rdJn}_$)61R~824jL++Oo~=O>?v? WA{7c)lTwi#lM=Q=Bo+o)qV62v8gO;UsT&&FmG;Q-rsmsPsqXBdXc#huL>{U8k zf&4gd_C8u{BHQUPU_@Ib43+)Q(w-&rU_;+T?E$n!viAO?3U{9p!PSq0KjLEfiQxQA z&!pmT%B*PJaRPo-zpNqVnJ-7cb2G*=zlj*65e~^yAAQJme)+S;LJ5er*h}vy{WhZD zyiy2E`zN|AYu|5~Cncb@T>a~7n-QzwyD8nUMv9XxRVH=1 zn7>`d+q353Wxi*cLH4Fl;jZ&&Mn?y6?B=B9Pyhv CG~IyXpxg9#_`(QE7@zP4n!jFK68!K5va-9J!$}BbqWhyT#vme67>9OQR`Q zipDQmMd0bL{N|2y{FErys&DqU87N#fB6m!YP)8u(8_-cGTZ92~CC0iny fTp`z?>>K&fIHxm$>@4uY__znq3EGgrRa}+4L1j^}< zfh%i6xdLux;O6sjEL{ce3KJ- *lo&wIZ0=L&w5zw{ke^M6e_fZC| z?2r$wMxZMWGA)MflSIgmfohhz6A)Rui8R5$_r*kD#Sm#dM?=VRW&g9# ^yZ0POc(QHg |e_vIZl6IM6pR9HNhM&H!KL1R{h=FT1=hMfEA7)0Iu0{-3 zpQA3*nA@rXmwG$=Y8uOGWpFt$u(kxqmLNFSpcw ?TMrrDSE-$qfoD~^H44p3sL0{kNm!eRg-yFiHs zps9v2@tS{dkiG`yELI-E`>27VWX~74>$?c>)xtPY2;kBh5T_vaEik7=bgQEdMG&tW z*F{15*%XwV|3RB|NeRUFH2W+fI&UFR$T|dqrU=Fqnnzlf!2F^<_J{HZ-wsOK(CmoK zSQ>)(=Mf))-QOKCOK$_#vK6rc;{UMdhuejOSkuDz#VlWK{)F2=$*t5^0iYcjk?Vr2 zJb{*#Ll(nF5oK#qpb(kw)``~BqKq-c&^Rp!iZY7>WdI)~!(}oG$Vf1c4*NrElhEYZ zOHqsw5MK-~AG8k=2D}}G?!oq=aNR%QTlp0KtyPzVmQu77W8N*8;-}bABJF&KFd#6A z6JJUoH8KbvDj)#s1nO8SNM11hcckx~MzgHIm}}9NAiQeckYSHuEokixHA%>c{KVjn z*78&cr|-WRgC={{J_+j%Iz8>JPt#L(QoFxWyPO#D^}TBUKva5_XF*~s_13MZEoUAx z9G?#!17$PlxL44qXBqY)innk|?%kuz^eUIg8m*ptqBq&DR{lM2jhZgkw@EX%U?)js zyi(Pag;C=yM=!2-s=oDpvPNn~PoMREPJhH`l}E%qDTP;7i(v57#rAW>v1hoM7iMZA z2InWN>Tdfsu&u%a49n*4SFIxqii7?{h=vXO_35p$`wDZ&Y%iX-qT|^&?sAmf1ZQ)p zkIn23-(R=oF9=JEP`QoIPgKx`F=27o9?X7eJQ>FI=pB7AJoDkja$w41nis>3dgdRg z2@mwQK3@V9LxQuAZ>en+t2H9farT00QxkggIOh{tV(NGDdX3B$!YdLth5w=*LOr&2 zp+et=YTV01C>xO4;kc;xO(Wju>WRJu(yuw^2ZjcYe+mCLx5{cxtoqZrG^(W3!q~Zd zA$)bM#&W;!j};F3$cNO9%bLe2wln2J>f_W@+-2AjsT0WuX~D9sm;8B=H8TntE7(Kp z1OFcA9!wpntlyXMj%QMlVwNON@bR5C|16=j14N#zrE({&0(*_P?col^6vDpg>Id$j zLmwY5L|pxGue^Cuh_*e;W1KbiH#K}ZuX9UiZJfq_E6yiNPLET{<@)E+<~D7QbY1g9 z?lC@cw&|Ar+O|Stt1ctcE=%xXcg1Du)`dhzgE?|4ht@`9$*qlID9kFlhkj#gb)9({ zrOWk|LmTfmdR*VtIo-Y@I#Q 5LyJ7H@z~+`}L(%AVCvjUM-F-D$D>7gVvYD_54fr98}k?a5^SJ z6T(NbvP^9D^G~@p#!N(##}$A!O{85K5dc0m*b0C?Y@4Wp7x>s<2Z3UZLgCwPa2tw3 zA$Smhm}0(46M`GI&5Cn~>4xt6ksq5g0bZhey(IMMpfGqwL3K-?S3rX#27EAMyPw=_ z%ZF6T2zj)UfT@Bp|3bJAk(Z5AjHz%w!aGI)GzfyN6@8if-1$%#dWLq&-82C_O9<{~ zgy{m!hX~}aPjEiMqSKL_Ex@ULru0vfV%ol?3OTt=lgq&(Y6Wx!u%q?^?jVF(pWFfW zMva0pzlFCrJhVcXFCK#*6ev1}u8RxME$F2#0B*)Gu{GXXkZ7I)-C+)bV4jMoZS!-d z#Xvbs!0mGv15*cMZQ$F_r%$t9iU3m!!BKUGLc~)=tq)58cM}Gkf=_WpX!Dmt^aTWG zr8<@ZQwd>Qb%!Sp>H*%8!TU)DRlQ`5809Yl-d=n%4Q-k Z0x#sWng$_x|zhT;bk59 zXY(mMr>$UpkD0=7g|$^s@Ar)=ib308WY1x ?y z-^{QwXpBjn^VeN0m#sJrBecV2oF=JxHpeb(MnKy|lQ9#cG2QFL`MI>}s~kT8C3}$A z3*%?2Fzr$OFY*=7c?02}T`ksNnh*1Qo7u@8hEh^@H-z_ISvWJ==&$P(cLk*Db<3NA z*2~haGz3({m%FWSK7f)&=K286S5fp#$bTQ?BwNvT=(Dwj6v|4?+&I!#$lqJ8z$O`G z>v~Be*?9GtNs?z~pL^AJ7nDCxA`K>h&gsVHTcRc);u2_wQcrebXNe)%lP|s`r1T}U z9cSaNlbR@7jg`HasNR7~s=i~)E1bmTFQFVYHcO5DGP+c-PDdfQ$Y0pm9OX|d&SlHb zig5D!qm=2+Ky-a?*9)|hiQ76>C0HkE#LclZm|^z*$mUc8cDts2uk8GF=s3Z%Z9((~ zdw?7Id~jp>HE21P8$HvII{HS@mH;b%R$Nb>SzoR#k(amIN-NnxyY-%>N{`jn#u(C8 zhc~+Ahu+vfx09C;(LCxd F6lS1hb+4FKxJ20?8XNaFm-eBC5!SN>$=k`!c=Nn z44cte^nNoZtQgdPB>kNNSkpoCRQ$7soWf6h4th_Y3ZSc{zF5qM$aqfC$+Xzt;fz2x z>i}|C;u2d7+IE7b&VYJjj>`(TdlS8(t((V$z;itkNiI3?=fHPZpr`qMIlm@!u7`!7 za;)}^o*+L}O*o=)GgVP;IH3p$j7?HQkFyAne+itag8M64ck#zZb%BlV21XZw=Mq#e z5XoS;Tak#Ks4PQIF6|z~;RFSh-!f2?{w^Bm2R(_Mia`mk`Zg*-4C(buo<*bY76 f|SC_YqG(8$-g4tMwZCQrFhP%eX&0RfwPer%2>fbwpr zE7JYgwATx8^or2-Ibqn-fiQyR4gzkwC9IH-<=4TF)u_T^yn 6(fbi64;v1h7JHA?`ZQ&6o5CG`)EHvk?egJ DEL zH4X54sQx!GJ^N>M&cWzwPqWdh^{j2cD&&_23&X?K{KkPw?z88|7emW3jJB`q<@&q1 zVvxNCqn&Efp>`QO04St_dHu^>0S-k}lmisOya}x_YxXq-w-*PcOk||tXcG;$Cxg-n z_tCjui{PXpM*H!>;c;*Me)8|bsP?MNp~|!z`LhibBLC)gN5(Do2^Pa|iGf@1(9Vin zvqb`QIz6aC y1Op2i*^IABdO3~+(YA6LjVA0??vsza;a^;~vd5fJb7I&xfz*uq zoWaM#DvCV^=xQ+$JE417atuTF0b?LDgZsL>?{5v0-~R|K80~a@)AKAh3|-m)J4`I; J&$c{~`F*%MMRBizz0k;=ZcCtDQRX5OQ+M8+MWxSJ^{$y#ZY zm=U6qrLtrlJJ}fw#=O7o-@bpq=UnGp&vU)5=j(A^=el0k`Qaqk+gXbVD+&Vu#B7dQ zo&*53xkUjidQ)ni?`+r eN-qw$~3 zKYn7!RJD$(=l|%85BC`F{~ @*yrwK>5vD R;L1-F?*G4%O1V*#rpKgn&o{J za%FR}Xz{+-koWX8zMZ^~5i?AhWY*-gy9Fil)$0{!B%GB_@1B#>P>*&{j88#Drz4?L zlUU=uM?|hW@S|olas8+6$X<3KIsEH}WjYR=>>Mnm#y1t-rk%Pio99Ameg870QVl0+ z%oOtp(C*23Ae(2;cSraKVgEU`bH( 1}yScb-hDB7QR`%TG+tH@>Hm*9GYt66GZ9@KApQ zbo9!#rbA;7(jJLIrGef}!MtuApl^Z@{yw;_m}0?xTJJ?w0@volv`Q +k=rT3Zyt-+g6C;<74YQX*IJCw}cx5d&LpbFvKG6^K-?2F}NWpei4s+n=y4 z{W%jK85AEamkk3GZ?rq_=SgeH5^m$2)IN-D>s<2>2uk6Jm(sNH+ H{x23iRN`;&AjdxM0(T5ObprZgZ^YM>VAiQ zzU9|dkaxGC@QE9itU uE_{bP;J7|C}*M34rcX=VV7TrFrz33m8O|ePGN-#9KUOe>t zL-W+C;qCWgnOQ&5hDOe@t~-!jct(t+R;Qa=%gue=1#%)|-p#@TnbU;7-K6NBDqw9_ zA6%wKXsx{7_eoWeul7|jFYc?91Pe8+T?;>UKSunr1KCC>&4=X4L0*Sl__B2fU+~5o z)mepH8~b_M(Xd#m@&0+&J>x6SuoUAs(F4R8LwH{K(aycz`jdQ2XWsJQHA$5sxW|H6 zlS T>AJtK zy#>J)ImwNVbkg>c3v>NRH`&2r<30eLorzkKqG(6)cjV>O?ndS5;Jo2%3*dRA)ShUD z2q_hPHm0hzfI}kmfnC4s1q @+k zEXuAVgye3;kRjGN@ 3Mud`y&qi9O+4WLzjZ4Z>zr8VAxs274@8TuGaT${Ho{?D}6lvK^(+OVz9 zEN>`b3!8X3G;kMA>x#Tu>9n;3TDOZiE0fZUv?|lE=jT|@(D77|{AZtdrwotj0frCY z^7E{n)bTVV=a4Y))C85NGwYa=ZN@TyB2pWv&oUO8Y8L}4hyhemj4qF41yrDKC)2>x zUzFS9vryIrG`?QB#Q`iF7Q$y+mWjkf3Ls?u*#uc)6&m}Oy0=FGiq6(ToXO(!&`q{9 z)RI7+A_& Oa;i;)fiXu*P? zP|$sZ2BgKk-#gv>R}}QdlB4=u;qoHPXASQxVbB&&_G8xJg&^;9(W0G|tJa72fby~6 zpkJ{PD;FrIRY5}%nbRvdOli^fi8z&ulAVS0%-q4$1W>V%DVacl95tlju5XqCYUfS2 z@@-EOpo$Rm&527tR4jm%s%Wc4ksRgwd+6h`=18m|{4GSFg}d++4nzmt2-e f zh;Ae{q43J_VlkIQ;cRaG^SPch7Z7(?{-3Srcg-_K5UUtuNa(Rv^nt^ENK)S$De#1V z&~**Hx7cB(LYfr1o$3TK)AytYr`iz*`;w1mVxqE9EY3&QyMjCQz<50|CV5-~mFcu6 zBT^l{MN7WtDYI6vZ5KEZBU2a_B=HQc&x!QJITI>s%=A)kA7R*obO6zJaI=8X`aNK@ zT)WE)vaPcOPve1uKl`j1cAv1idjZ~sH)ah-oISw`FctnRVqad2+M0rJOaW&O=mq&2 zW@gDD>T0s~M>~*uEF6MjIdADZo^eY|J6}HL#=P!!lyHQ(-3-oE>>QkH?VvB9VTNQ1 z+oz&f2b4=X{c#3{8amG S{907cfgGHzsp Ww8+X(>B+@Mh50) ziRvYgEdvG?Cg%QZhl}LvGUH(g<7{5F9Tj^TCT%3gPYey@3Aoh~O)nj>JcaRefIbX1 zbzWGAJxUu9*70f32X?;TOq+^N(lSq#{3`vi4zSAuU$X|=6V9-v#} GYNTXN3u4-jz-T~10W7QT_LRoMwT @gqaN0m7SHlpXa=I(xVnYaAVr>#GpM{r&ZF?C;PNZDVOJ7E28fT5 z1&BF#>}`rHi@Ft77sbaQQG(;zM9 Iw`yg5PL zL9eH)an;N#5(2{6=NGP`07s8+jb=XsxVIoY7HlVEjn*TVa8B^;&4-VC*|X?nAm9{& zqwG*jgav>Vo0-L^MuFqhlkfv_@*sIX+$7AF4ShxlY$m&-rUH0d{Hiz4kr%wI1n^@q zFI6|&A7Ysnyc~#IY}OukQ$WMvg11+@TG?vCEel&rvk|=DuM$EMt&vH`9j#_EP{%sY zC(^zVj62BpN#L0(PTbx(u;#>wYJ~H;F_-EHzs 6Os?C+dx*1Lj^QEL&re7zx=Dd(Zb>tReD@YVuJot5#Rx@}l^)NpU^>k`xJV^Zh zS7uPBajQ!;`7x^ep-?rCWbcDq3|SCP;BA=-QZ$@8@mz~<(j;k9O@4 #X_l;bY%Ls^*7T)3o^t9b`tg!OIEiGdw{H zvr1=n8+>3(D6VR15*JW27vp9rrt^^*hD6u%XC|zJuH$TL3D?_}E`>|FrkXzavzPVp z<32>shp)YRA;V_*_GR5Xa2z)^L0T;GC3nk~`Mp+?SXQPw4bMJrWZuD(F9=#nMaf&F z&3-5JJRUvX!XM&wblVyUe8Tj~b9;C{c#)06#f(3@&z70r5KH1*vUH4o6K>M@XiCG1 z^F-8hxo$Qf ^!60YxbK|q z!RQV)axv0z>of_M>LJC<7rUWlJxcUW>*RB_b;r^Kb_I2*NqB^|`h9cp&p$CUbUlOk zZ}$03-`m|Di)qFLzS|9{Byy>t$mrPbWjM@*cg3wKK&q%^Ch*`!cO9mh+i}cj*B>`C zk@Vf~c}pEM5;n7$b26GS(qF@wE@leuX;ayFCg-u0S+%ib;jJG1L4Y$)#_ABRt*a6Q zwEi?Y vcIlQcf3o_$!?W3J)gd>yt*)_i?3*?fL)o|+w*q&Pt(RPth~ zUll@3tSpnXHo3z3m?uRos`DpMyGA2u69m5>Xur#4+^V_trL}9UsV}tWgh=m;(pw5U z<`Sm9ovOamTgqdS <<2S(WzDL+82+EJ>nGMlbcdRFlX@Qmb0@Cj1p zmFNdZ?N4@+yp`UIUQR`5n98WQ*dXmAX65l^6g9Sa`h_M%O{eT%wWt6>I8M~l*Xa@& zXRw2B^Bc2qq?1;eCCQ` m+LNuud5x@Oaf j+wSskcMLoB@OI0JbJ)(GNQB`CI$s9M%J>HY19#+<4m7o;Hpm43)&j-dj z5vq$5?CyE3UN)+pKfu$VI2|qE7Z*JI-7K$XI79jjzBkKzFVeoQp|9e9@=mxI IZq&zhC-(WAue(Ig%AD6(XjvKmgikTUgaYax=Dh<~$mqZ|MG<<3upvs)$1 za@g#>4O6@!e>c1RW^eF&d^qRHeLg9kil+VurhT^fR@%fG<4vE4kJql9F^GO{Q1Kn5 z^~CF`$g`^Z>(nxSX<;|BJ+ezc{D1z{0$AN#A eVg#@x9i6CegN<_vtNi--`q=ZP#AA;0dMVl86V(&^G^^E z5TM|7&BxEf{raB@zBh4C=QTwDkN{`&PuT>f&5eYVI@^Vb{}>yhrENW+MipPV%Uk79 zD)(DT(u+9L6T5yqP$os1J-vj@e&TNO@JYqt#O%)dXAb_S@}1df?Cm{gq|XhzHEG`A zII5X;8k~8zSLxm3qntWQRmTS}{5(Q$z%OWptnwe;`|{BGmyj-d+}QHQwg-LGZ;k2j za)CMT-|wKoj_QB;jV@Y5rhLtcZ;3nw{$RGRoe3`F^ob)XOhg&7+5Qxzws9QJprK zo3EEJk&s5=c 3G?zh+*?dS(p9ljju9VFYDz>jr*yO zmspdor8Z12cE1qxr(1vt?-3z-=rHQ(0X})AQ})kFV&Hl4KaL+d6iW=~!!!nUn5J*n zQryA2&KmBf?a`|`2NK560z#`8eh 4D(^vUm`_7%xJ&QThUTeJZhAt)#MU zDME6oV@r%!wialz_+oN$Qb&6^iciZ0yQj&p-w$zN(67tXFMmuxfW|Muudn~XAWp|Q z-RbpOp}5*leYz4jXlageySC7uVV*E5C{To$yzQZND1kY%lHAHtb{6O$H-js`7bpOp zt;^xkv_Y*Vx$CFZ$4!gU!o8;RTXh_;JWYmW`ADT|-|y2&6V;qzoMwk}l9)6bXGU<% z^wV-^uRP+#)AVJusKhLRc?s?Aw*Qc^CF8@2sraxpcDHUK=_U9O7CICELbhH `|7k zEALj%H(rdpzKE-Ee&RP%?iW%u6pzd_l9mI@(DRd$;n&~WyUACPlSXwK1HQ+@b+g3o z(Y4l`lOk|rVEtZ{_cdsIVf1QN+m6heo7K-Yg^}-qn3|kefKMK76jop=_wFA#KeM(G zcA`W^Y?oVK*ud_l>UpL(k$9rL<#u?R@6+_b?S)?c(5uhz{~=heI7@+jrgN^lg(6P= zwbK4K`L*ML^|TN#`tKlXY8WL!GgcqBMV0GjkQWN9*Vq0IbBxGm+bz$ ariX93&-6N`AklPP aO|W&27pVV4`LPBsZLr$`U1S*{Y9V8-2g0nBoxVDp^U%oIy+MZoxnH ztB KTBxAG1-qAD%flkU2N1RQGMPwai%-p*+ z kH^YSE+{dcc#kQw}hfSgo zQ$i?k{s^n%R;^#_oAe?@S< {#J1V+i{Pp{j_z&~y>rY^@ z7Cu4(pM;4&ZKuQCZ;XA=IVOg3lZQsN%hRF}T8+5jg~ X8-srxIGiiZo2M@}qvn@S@t@S?!x(F{lOE3fc{58{)<ke%O?fh) z#}y+P?&W^#dvbF~)tsCd=hsVu03CCz784O3KGr|*SYmgKBnoiiWN&WP|Gj*9?ZeLE zxPv${X!^=CS1sOj?u)& zV;ak=#L`IN$lr}b&k77o=5N+_Du&M{P=W}HSwPo*Ibr$f%zIWyhpqVt1cs6}bVWdY z{61!~y1#=oQ?=d0G%}?jPM$;oLvvNDF9|b0-Kf(XPm6 ;?h%0W{KONc^FU8djwtqT35`8!5 zh`%Y N?mZivB2CScLoXz7hjT*1T z0I;XIUVWTY^d)$>&vtD4CS6GejyaE78*Gl`rD!jzk`rT2XdsYEm+1M}ajE4HoOXFB zZsxv8j<6k+WU|u}>zbfz3m=~HkJL?mp}4<`MFQP37=yZeTk}!%t;Hwe7_rM~@SZV* z&}+7D&;8;+spVd@910LDEhj~5h1RZynKsB{$<0^r@Rm|X>u 8V*@z(@UG-3jmbv zEOiL2b=Rrj2J%iVa`7~Ink+{DU4J6t0`{FD8D6ik+Fp7ydbLDO%tH$H2WT(#C6-zp zZn%r0eo}<}m}>IVCC3k3Q;HFff$~3(?yGj!<>QI5`UsFIa5HYKJ0o4a93K~Z8h*xf z**m>2Q4qVBWdVR^Od6%+yB6&lhU6i|{`}DIK*9Vmlc>SnFsmX*j9x10io@WPO}i9b zehz*XN{Rc(j^SM5^!ZI8vYs*tW@94T*zQqR&(1jBwkyFT%JUEC)KM&snMg}>#p)+k znsRwY_l=5pjc*f`h4U(3<3$O!?-OeM1Xi7> Zrs1N8M>OL@48(}8!bgRFDrX{_noqgOG!J=lp1!;tTjWDlj^J)EJ9 zX_kM#sYxq93(xtnu4X64_qYCYL5R>5#8P-;_7IFEJ2*n0T1{KscE76v*(8@WKsms zrDgKKYx*I3+WD9JHzQTkQJJaA9s9ou=63~=rIg$}?17bvGZxw8x$Jkd`Ctc9sfslO z3jW;R6iM?%gLe;Lqvv6a0EFWe?&9RfSekxnjm-1Z;Gq~+-_U eK?~+IYZHKCxJ{~5ocgE^I^(qbL%5^i_6pqfi7IL(ciKc z=-`q%kU=CmVFh>x29Xb5C`7k)Fn_01$cNoNPEkMcJe7E1P&}cQ+}q<8>xBAseeByf ze@srlP0I_MVYUtSH{Sj_WY3W3zG0S(71Xmcpgr%X (PzH0Iwx`OVa8a_R^WtVy^q?mxx#c2S?ZQ?0lOP5&QM&g34#_ayOZp7y-0%y6@?D zIDv9`cpI5!^9e&DM0yz_JkJ? xM4D6?hTA-7dgSHdgJoW%jmpxU7@I z#q1F1BO@ER{G*3fXPpIBt?0@iCK)RkCUKLo*;VYLT{(Ie1F|w*;x@n1o@=kLB&Q!y zya3uCqy5UNI^ss~z&uxf@a_V@-ND2Ewq0r=db4Rxfe8xD;!>)6+s72gRvjDD*JoXN z{|ZNCCOH`~`fypbth)loqD*oSnL#IwT4wCJTt6o+d|`ZW87l-y7K-}o9}i|}|M*N~ zn$PZXtE=;TU3qhcGE%}|x{PLnJ@ziz=n 0#QnaxY-|fR{yVsBd_E<2e zIg- oKZS$AKY1_UI=39pMlqVz 5QRHCc;+B&yx<0N)ky#t!6 zD{9{IlR#y5L#xY74y9--4O)iU=0P|zt$u=qKwH{c0nX C1qy#FRtvbt{4F2`0AG1+69X z%{L=D;M@a0tm0|JRJ@asR)jCSX{iW}Jv~9FLF6MzQH%qa9Wyu&Hs5wd0A&NQy#3EW zp=+4h(wn 6}xxSLZ-6YcI=Nk9^7|gM*d5u5gpRC67pkJa} zn8}rSWB&2bYVBBheKA;(QPkPL@gr+z+D&S;=vD|S)5z!+vx7aNcpf{_RU5~+gX~EZ zT`jDHkL)@}Um6)xTjSx@ #wEy_|sWpY(=u|SWedBqTyHhx=ZKjBk; zilkyF88#VHXG}K4ytbb5iL?AsZjYunwj{lMSP0ML&0Wnb7;^rkJv*keX0B<2L7i8n zH *Pp8*w6f(Fn-D~E~Z;_<8;D*`ZbAKaHwqP0$ zHEj7vZxti2iv%rxdw-0}v=tE2v+?6?5k?r0^KD+7z=`b{Qf4u&>va)okAl^wgLZrn zTr9?aJ9xlsRRr}_aA`Y?%^)z}iD|u C5W>wI1oM~~)uRe%eF-V4E`_T-UXf{?fZ zY@~t{m;EuM@VOe~_5T>nGmD^WmeaRJUWcnF+5j`j?h$J&6096;ZS9?`ZLCR6kp k*jd<{)zP*^44q`;^%zZ`8CM`e`<^#fG842`gZv>MMF04{!#p_- z0kqma4pSSm1PQ)3*7 F7g 9)fVfywEDX! YYB4pMPtCq4zQ2lM~YfRcdjIk4|V6 E&N4YNgOafynfJpFU9aQTEzU}> zUR8vBxb}lvv-2}QRxj)))cyEGoDcn#vY7@xmQjp7BA2!Y)|=Xvqu c*CDUBDrZV{&zVYa~ z1j; @X|di`9nP)NDmI8GPOm67H_jxQyMcFkUi&%)qL-F zWeRE0JtAaTlEf~fJTA>`@v?t-bax81nY!}!9% 8@Q%a8L8nJ3y%WdA+6m%CF3E z>TE3J^4bG7Gu-B@IN8}4aY1@G5CtW_?#H8F-i Ay%nF&2u4EmPW4f=Li&itmC z-a%&kAOR(@Q>XJ+7wR^9n>D{h%7UOt3u?386V2ZMgN<_DfVoZBewFt#;o|t$?(;pk zc1G0#@jihzj}c=t!Ndfe;&Vu3%}ezx;{E-2eYSeD3zhuMjH%&0AqaMociC~If6F8- z&_j^$e;H_F1Tw2ZRq@DPl!RjFk>@T@kU{Xnf^S#ZdA9^t7(BYY|An{}%{Lq|)n(vP z0oCR584PdO9IH&k6~ujE{0nf^%BY4l)`eI_z;;$w)!ezNc4~IjP>2xv^I$?shTP8G zv%Wxhr#kOsE$BP8Y$XM54yyt6T3@;A4!1q@tCOA!Wjv#(i#UR%Z9B=AY!xsynS`_` z;sk!l(7=$!{HPsPU*DQXH$WT8f+;N1L*yB&nrDt!1ARRnU9EtC3lNUIcqvy`Y_nyo z+%K;(QinEbYE7fm@^8SPwM2sGi#wdCo|Eu+JHTd{yJ_})k~Fwb^tQ`pW`wLKT428e zZTlT)3#z^_y`^J|Z7mbA1+X*tFY(yeNvUj$e=J2_zqF ?t9A5flVUZS3`DknAYD?G>KAs!YN3Qy}0z8au^cZg1N>mNCqu!F` t5v2h#28j$TRE6divb7liM$Cy`M<72Fa z=a5R3T9TDJq(zk-b-*^$WAF&LlY%<~5bWRD5?9b@fo-A3TtOJmJu#m1`!(~ulorH8 zf;{+iG?4{7(;ju*49C&;794+$%8XX_x2Nv~Jy|QyR |pW2Usjr+=QBL|rIKI0i813{^I?erbMmbq)l(6Smbm)&=pnirwer z&GbF~#v%&H0roys0A#AFhuye1@G0Y%Se8(hEpWgYqy`%P>QhRNi9NHEf@8h6AWPn; znX74Nz!P0!EfB^DFW3TiLpv=!U`~pxx8i+?TQ@cER(5~#FUd?*VF!o#Z*Uw%o#o;( zVi)BNvq1K}+!yKA|Eeag<_9ki*{|@eu^_>FlS1@N* (dMMCi9qINGI1`d8Hr6vRA=qTy%-yRCtUPdr!+YvwJFu1bA9eixWJ*Dh|F;<9W( zN6%PRz-QwOD!Sx^;ld=}^pj?Z*;W9XNSMO(yG5V7V##`icCV2ShIZHkGaiY5JHJ6u z?=QH3Ft$!H%r?vGajl@N&c zc0mGNOd!D|O$7AI23Y5Ogkoiz4Jz17u{`^<=E}OANz_!zGa-WVjZ^wth3**#K>rb1 z>~WYpIM`oN3ndL#oXFRhgC~ZITtgTa!Lt;;)g(~rqTU)p=^7B1C1qtqI)MB eMXVX-Ma@)})`ak36puax8t zT=7!AkJ;MkfGC9u$h*>(M=GhU#S>4VO%TQ;oMA=xp?7&8(|3t8Z9AaPf?Kz;jj99v zD?9PA;TfDJ910&G70*NwINLDS&O%Yo$H$!#4n*W0RlJvUlq*aGOcmJJ9lZ5Z=i+XZ z#OF;R!uOz8^~ ^`>rMm?0GYMavXLTyj9@rg6IlVu7&BE(Fbg; z? GWeWNFHn>m_vsYxeSAZ>D<2eKM0M31H^$+I2? z;*PdJltK^~21g8)ZIw|DN4mo;OKOdpm5LTokE5w6yY5CcQ)^V0TlWvxt}V~{cFwV` z)Au%0)*(~Pu?!g6a$wK-|AT#ZdIaKe! _oBIY}O$|%>chPBw5pG{^ie$i^Xtfg9^ww?$sR48(#6F`Kx>FR-#{ShgxVcHx zPD+oM%OYFvaUA2;RSB}p_O@>1;{tjKR$8|pL50Zyuf&~xf1+sm>p8MsQcnu<0ma5< zpV0b*1yEAPyw#wrsfsC(vi@SiGMp30`xLK-XzJ-(4b v!`5v5^n)G+g~n_s1w zw95R+kOFf>@KkW^FgMs^Nn*o4+h2%~4685|M -xei=cyZJIFlL?N{K zG+mTjR1eNNUuK(H4@|668~54!A#&MW*$s*o$$2331wPucv z)z&(N29Zal9a)D;ateYv*zM*~gD+z>v(t_yG_*>AIKq=8>@|J|VTd3wJKBa=`|SM@ zo 3p!1>Ryw9BHf;`D1iF9+9L}eGd^xx%KZ=W%#ouQ~3e$L}*TKQ8TAyN>2 zM>4L9d(QYyIczwB;nDSJXK&Wdwnscx_{^}OqqF9-Q4;6U#6N0>JhlgJ^$j13vA%L* z&wn#>0I~tl&$I0tc9gXdE>oK4oqa-tKB!;x2U(!0=1bqGf2W3NlxOt59aj_b@44d; zgvz0@`KpL2Jn^Xd4aDFjxa)p*AzHM=IAwupNS8RbRDpcp@Knk_-C2?ctjHN{Zgdq7 z%*m6oywa=oxuuQ@B(Qr(gcY;%o>`BGVgA{H9bXc@FMznmpSD z1_F}LGu?3mpA?v3Kjs8rszW5nc@OQu*Ig9ngx-j>!Bq)^ybS;lvh3dijA=W;ZylE4 zMCHozOMKv`0%n| $2jRESp~b1hZ{VWf@&8`F*oT`|I5D+U_U \ No newline at end of file diff --git a/src/assets/icon/tag.png b/src/assets/icon/tag.png deleted file mode 100644 index dccd2d222f3f88a11c48ab4cbbcbee0944d39f61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7158 zcmaJ`c{Eh<+n+JUG8o%fL$;W#W0$cGqfwTTB_WLLQg*T%#@Lr4Ynl;5vXiAEjID%` zLa3yKh!!F1JN@4GocI0fJ>PrI^L_4pp3nF5e4g*U=bn4hu$JdJAi@v;0Kj2}F}VZ) zFwmzA02UD4P$|+QbTff9w?)(K8F6u`)Bk&{UkLlZ?*B7CY_r}D^FDcLMvvLN5V5&; zq#!M+sU*GKcm7})gVKgu8^ae&Z=%j9x?0L>NWmvf{JuRwFSZzW=(|2dUKup )9}K#gQ{v`>(Fp>927!_<)1~fqV*CF1P9jW4xpFG% zv?a>3n62&0cyc}?g_EzCom0>A9vpa(>UKN-T3}gAg$hp!na0$bs0#(rDn4~61PCU# zEG;q=jX=vhaNI}s2mwx>eVB8p8(?*KDOI0QXAp7!K34tBnL&6b_Yq_}by9ggVwe)Z z8L->@F`xZ;I&oW;CXQ~j=-@w*`_^bw6P)7OFEXcLJAOVVRxt_|7IJQ@R)iXIIUoGy zg7~ohV0=C2*s}Vz_})YGwrs*P?p>$T+4rk0igAJxN6c@o7}nMe^0t2u%B@?q5wsmj zG;il?oc-pa{-Xe$?+`rVoD4y~4_)alPvxRf5{CFmJP;oj^;vb`+;qZ*xNWZY;MD>n z)>3@$y6#9B!No} kPcaSs<}Cn;tDu+|SQ=q*95fawzWYK^gQ1vJAx-HExY_`M zOCB0_58Taijn8`<7g`m1U8C2gq^u#|uK{S;??Wv6pit(;5!k3xt;H5L4LF5+@}zR* zy!tfYJnoqevz|dk!p#^CTD9jMY9hx+8?qxYL`vdWfO_e&Ja`E7u*9Yv;PS@<*oSOE z&Q68c@%uBUq`5sDRd^Ibo4iA}W{3Dd+4$~5UJ`eaAIFa=9irHd?l?bV?nqVxFm9EU zVUWb_uvqd_qnDGfElu|Mtqns8|FzdkGEYJyslk;Ry%Et1CWX+`NQh>-@M38IQ|#>N zoz2j50fOlah)q=WdRu(xb)k)>u6&daNkaR&*R2z8zbT3hL_i_$QTCZV7x7mnYOAYC z+THPZI0)9ow~-5z=~g&5`c<{J-H-9k2jqeD4 eD|Efs!# z3wXB>*#1Ws>v1qYHd8W?J^Cxr^~0 7UOypyZm)!XUy%*4^m&ZGVlTKrx)MVEo46jb(BJR$=L>w zxSjY1oc$B>{Z~JmKWB8oFP>qa*L@w88lbvac~pz2 sohaBBlp7Zhp@ykLa;m^JvR)RFobo`7)Zry!8_fnSo zOAnW77iX5z@d1E91Vl9-I4jdKgm P{y)02%_D|tZP}E ~~(&v2HFb*{gpE<;}_^KiW?cBnr&dxymJ{YfJ8 zjZh*Tc%M|4r28BD8}KWFsImQ&Dw2+O&cHntH+dvJ!@$@mX d)g_Qlf{Q;9 zuTU-SW({j=LS_c2)D85&vCSi~DV?Fj?{F8P1Zd)@p;`V3H$)4*EeNhZ4O@}}(cZS- zB6+06w#c=^ZemxhU~S#>TuI%*9tEu0<+G*&0oai&_(+Ff`$aE9wCXN@ RATPc*6;te)l8{xtuExf!5{V zGc#~fJs?8^Q`aZdWB6BhhaC`t54o`hZIyupE2U&z;RJ}H>HIuyMF`TjYSDKdOg!{a z1?kLtTwMn4S_`ZaZqoyDW+GewUuAcay$DRNbmVXL#*U >?e-^9GAh2I#sFOfD)y z@L-Gj_Lfus4e(gWW>ZCD-f`cDcW@1EMx#!9ydi>AqxEp~DA@)-kU^F+VdRngc3^NP z-+{+N^VOGEo?iF1SQT0~0=7bTU#H{##$7yC2^=~sbiiW19t0XYjKg*muZfwy?WCGq zG(xE;++k$t<4Qh7kwxbq&D&tkeFuSHg*)tf!0S#eU_x>hkpE+S%+*c?FKFj(9zV?S zo!}z8)@0ljsK$ITHY52h#$d)?%EB!9w-Bg9d=Uu =1Bk#cKP0Av~UQoZB9&xaTLI4aPo`S@lEi8h{IQhZzRnTOU) C#X1N zwS2WPkye1Wsn_!zcUY0-f|Mo2Cq P$mbj%-Rt2XL%_Er9I-xE5L%t_?7iL_p-0CjPFbPXmSwl{lFq!iQ^Qnqzkcr% zMm(QH)4#cIzcSS n7g{r8U`amTrA5=V;0Yv}*F8^>7k1`*e #QFCNoQEpp3#{RU1k_8V-rA{3J-ya*Tq%%N zVO7jpOFv5vP|%>AaxFNLoM?HrS}0&_6u+N}%v|9dsv=<{1bYDN_mLa1(X7(UgzG?B zmADe9U Ybw03(dJiZ`LMgJ^$4pj!Zn?j*jIcOjGYrbwmJw!CM|^0L z4_q?z!1}}=`ReLD3pk*if< 1k 2I3mX^r*7-W$T2|p9$gNkV<1D^EU|O z` Y6a&9S0&MBcnc+H}B e?75z%Re%vl)*vD-YyftwSMHCD*2_5@W`M7C;?)J_T-1|~SVUCOn*zh74-7U4iG zhDoc*2w>!biH{j|r^(5c#+K}I5Qs*ZnUSP7ZW^-%e7S!xH=uIsmkMjar5}TL&5R&E zA?6#;*=fA6C{`J;*_R)J&!Ke3?*_oZG{G=!0}x;k jCO{Sd|&WDMdHwE+k zqZYUx-(?4U6Ad6-3gpE$NM0+K_-$vcXGH$4$bB;+y*im$ME?`yp9TWIBOmzO7Wo<( z@j8wHZA89`h!9NN?tgEEFYf{U3jm&C%@y2623{<)5^!Po7D9Xs@Dvt`pE_m1>>FrA z9#Xr57pY|;eCeWU0(;Y`tF|1Fv=Cyz%_3wb_@@-9+H@cAN_0r#8HpwzLTqMHf_q%b zy~tApTL7^^g2dw(VO`YnVr1s|$HHqNA;gEoHt;IFUlx#GEDfgny$d*n{zrM5XFJpX z-AW^-3@*2O{VEmV0}pCpuoY-4iR;c&;k6sPtkFf~q}(oQ=d-o)xNyMckKjH@+GnW$ zrXx0Wc;G0ARmp*Y9|kE ^n9*prp?{+FoA@pF#ZJ~${ zJKB00ujzPn_;w(z^uhKUOeyS3Ip8qOy5JHGkFteCz9L^{b-=>4gAKI _hS_UNj0JvaZ0HGH2z%ig1`9uiFJ9HV6S-0))6ibbK#0bphS1 zUQNm1%Q_gh840gMWsD#Yb_kt-B=}?OYh`+p$u1$~Zv|ZsmWAC^oA)?-DN#Wi!=F#7 zb*4HBab|sp_c(r-q{=p?53qnUcz5o>d+7>zx~ebg!K6=2F)PWiz7nnAYn=f+Iq8V` z=~>dg(bawL+-})peRsEsy09XAt!UI7G=vWlWcp c!xx^!cWeZGRWR7g zm4)Em`iPa_uEyz2 $OO)c<8UI^HLzMKhts6P|c z{Ki7gP3^*tl+&qK{t!YcXlENsY#`XkSTx*2WSC4tq9h1OK6DMvp-ca%Tb3t7r*i58 z6gdo4v+Ti+l!*?(@@KgqgF~%!3=aud%Rj}sr-gj|=~UqRLTgsD^eivB@;}WM8BaYA z7bMdzQb-_VCKet=*KA107e(I2)*P87U`LeSp~&vz7~X%9H&I#s)yPTEmI^3)9{0V8 zbCzD?zwyt`;wGA3dJ&6D@m2&>43AF`O9Z_et9`K0=>P5ty$RRoiyF<)bwF-#cvo_i z GmYUeQAL>C>;Gs>S5*{(qZ7sv&ysWJ&tl-x&68rlS)9vXO*=6lIt5jhcUSvD zPJ(2$IGM&qS#0sOuB6u~-CVHUEBPHkAq}7@Gl^P*$@D;e6!}GxWh%Xj=rK+{3h5j& zQ|&dRHEmmeb`mBHyCeq8ps0Nu(_>&EsH+(6b6_c?$L9g$+yNJDVW}Yh%>XVk_7~Tl z&JD)OvyqzL*u5*GJryG*crJex116&&$Uf-XPOV**UMO#oUH_ X&h25zCOQvVr^g$*aY^RTzcp$8=2oZ^r5%hVm zsiT{s2o%=UE|Y=)gLnF&wtoXQwGyza(&vBr8}565f~nDWlU8{DW3J+==JmX?Jj)Q{ ztx}VQ%!l+I=otWqPG*ra^=*mb*{wS;r}}{Jg~i6=($c|pj4-&%hm*&CQFV5ltWrW_ zue{=v7nwtf-k*4CzN3J@Pw}-^V4*DrfU=8ESsbl>1TOYV PHUvYi0;FeMV( zy?IsC^x393fFN526aQ847|#eV{%fZe+pTItd5B6R&?9B3Qd}Ow_uAKb!BFR6lLv{9 zu=4_x85qyw8<)#RfLwX~#3)qeR|D`aH2Skp6X8rz8gEiP+|~rc%dp1o`91q_1x>7! zy5fLOY{Mk*5k5FWMFQgi#H?@48n5S98QHxJQA!&%)_QlL4>YOn9w&ev_1cw@bku;J zb%=to+#it7VN0lBfQ@syC#EVJAP=#QNvPHpY?N5wGP2ZBsH;EIlpOGC&j2u!o5)9C zvBEq#d)NKR80U?V-gH#*c@J5KY}+5qv_0Q7M1R9#Fgrmm(H<6sHUN-rrdEVVO|dmq z(ByUAKdb(HK{aoU$ $0PG%v$TI&B9}abyQNpx0AL~8AWB!QgtaKo#NoE>?6{je z{WUBEdhS(|0x0bv-RmZ)F}d9`Dvx3flzb+Bk*F6uNzi3-C`s$}%B`Z7w+7`7GhUoB zH%Y ea1 zT$B;5)ijMJXDDGE&<+frwuoC_N;}q?T0@v&UoF14gT=R+Q%fk+U~|{apH{hmMXaf^ zZhTf-4w^j5g)x`(xVC7x@F-8C8?qB^C@Cg>`T_s-dW!T`V`>MN$UM+P+DYaorwy-hZlJNCp9P3 z;oxrMpQpZ(@>3dL0>x**KN{g}>K+D(3^y37l>DRi6>FX&(v> hnryw-h5H7cVRRvvh`QoU3` gcxY9Fv*f0I^=lh@uAha9K+rvn7dZ& zng{jc#L4ptjn^9#<$IIDy~7{lE!Gg>Q-zl5iL!5yh8HqW|E{cAjBcGgPpP1(im$|W z3CT2-8WVO6&}#_$slxa@kchll!m6{>)q=Hyngbr~$*PleIf$LlzNQ)VblKczdLlNA za+7j!X|FQ+aI^ o;XV;4U#rwv-eZ_%S=fu*fgs2$| zn`Z1uQ0?I_*)F*B-1eWfAF{1*>G|!W(LSr3xT7jQLakb?+WW$Rh=550G@9)Hj&gJ8 zp_X_2E&s}c&)-5_zx|kbbBMKvRh0JFt@Q*hX8e*;5w)*cI|WMPJxzR`tMS^dq({D{ z_=jvG+(a|hdxY)kuHKuneQp=n?VJ1idWXAmkhd?l3A~M=u2;|!e<{i$2b2T;x;zRW z;Ta;fI^^4rU8~)KV7`roG^GO%ZRIdm3ABV-?DEgVwWhenmKH0===UA_8n3 oIRnG!wKCCYrCdmo1oJyf^mep~s`mNm_a4d0FJOo>#*O z?)@LW|61}DZfn%)27DM7DHgo)j##i|*iU$WLy*a6v@focJD5wcZi6~Hc{YY!g~~-* z>+#w@_FcIVZc88ovWa)0ip!6hw6o;1ENDf7-KDoqw4OeV_U4fvMhR7yeUuk5S^T(j z<`Pv$DV#sOr`c9yI;iDSdrbee(1H}ZjWQ17NiEeY)Y~m7ea81MpGvN{dA%xOS#bGQ z7yEMt)42^^r_w&v$P u-jSYtl6bK_uW&^iYe{hnMX$G=Y0Mi%qTs# z(aP}l?SfW}R8*Qnuple?<6B$f%j@_)1F%-b1jtgxv|_90=EJ&R4R*OgqYTTR@O_GD zFB^Pc1_R(ne^d_}J^nlO=wsuQT9N6b7A~F2nBL?2h+UU1U#uudIladz*FQ3|V#_q2 z^Cklk@& zrN>$0x*1uk9nZO|{LnV1#xm*_=iZDd-#c - - - - - - diff --git a/src/components/BaseFooter.astro b/src/components/BaseFooter.astro deleted file mode 100644 index 6bac2c8..0000000 --- a/src/components/BaseFooter.astro +++ /dev/null @@ -1,46 +0,0 @@ ---- -import { metadata } from "../consts"; - -const year = new Date().getFullYear(); ---- - - - - - diff --git a/src/components/BaseHeader.astro b/src/components/BaseHeader.astro deleted file mode 100644 index 73f3fc7..0000000 --- a/src/components/BaseHeader.astro +++ /dev/null @@ -1,113 +0,0 @@ ---- -import {metadata} from "../consts"; -import ThemeIcon from './ThemeIcon.astro' -import GitHubIcon from '@/assets/icon/github.svg?url' ---- - -
- - - - diff --git a/src/components/IndexPage.astro b/src/components/IndexPage.astro new file mode 100644 index 0000000..49ea51c --- /dev/null +++ b/src/components/IndexPage.astro @@ -0,0 +1,107 @@ +--- +import {siteConfig} from "@/consts.ts"; +import PostList from "@/components/Post/List.astro"; +import Pagination from "@/components/Post/Pagination.astro"; +import type {Post} from "@/types"; + +const {siteTitle} = siteConfig; + +interface Props { + posts: Post[] + page: number + totalPage: number +} + +const {posts, page, totalPage} = Astro.props +--- + +++ + diff --git a/src/components/IndexSidebar.astro b/src/components/IndexSidebar.astro deleted file mode 100644 index c672f71..0000000 --- a/src/components/IndexSidebar.astro +++ /dev/null @@ -1,152 +0,0 @@ ---- -import Folder from "@/assets/icon/folder.png?url"; -import TagIcon from "@/assets/icon/tag.png?url"; -import type { CategoriesStats,Tag } from "@/types"; -import { createHttp } from "@/lib/request"; -const http = createHttp(Astro.request.headers); - -const { data: categories } = - await http.get+ + +++{siteTitle}
+ + + + + + + +++did you stand too close to the fire?
+
+ like a liar looking for forgiveness from a stone.+ + + ++ + >("categories/stats"); - -const { data: tags } = - await http.get >("posts/tags"); ---- - - - - diff --git a/src/components/IndexView.astro b/src/components/IndexView.astro deleted file mode 100644 index 0a21d5d..0000000 --- a/src/components/IndexView.astro +++ /dev/null @@ -1,46 +0,0 @@ ---- -import type {Post} from "@/types/post"; -import IndexSidebar from "@/components/IndexSidebar.astro"; -import PostList from "@/components/Post/List.astro"; -import Pagination from "@/components/Post/Pagination.astro"; - -interface Props { - posts: Post[]; - page: number; - totalPage: number; -} - -const {posts, page, totalPage} = Astro.props; ---- - - -- - diff --git a/src/components/LazyImage.astro b/src/components/LazyImage.astro index 8ec026b..45d19a2 100644 --- a/src/components/LazyImage.astro +++ b/src/components/LazyImage.astro @@ -52,7 +52,6 @@ const { .placeholder { position: absolute; inset: 0; - background: #f3f4f6; background-image: linear-gradient( 90deg, #f3f4f6 0%, diff --git a/src/components/Post/Item.astro b/src/components/Post/Item.astro deleted file mode 100644 index aad7de3..0000000 --- a/src/components/Post/Item.astro +++ /dev/null @@ -1,185 +0,0 @@ ---- -import type {Post} from '@/types'; -import Eye from "@/assets/icon/eye.png?url"; -import Folder from "@/assets/icon/folder.png?url"; -import Calendar from "@/assets/icon/calendar.png?url"; -import LazyImage from "@/components/LazyImage.astro"; -import {formatDatetime} from "@/lib/format.ts"; - -interface Props { - post: Post -} - -const {post} = Astro.props; -const published_at = formatDatetime(post.published_at, 'YYYY-MM-DD') ---- - - ------ - - - - - - diff --git a/src/components/Post/List.astro b/src/components/Post/List.astro index 80b39c3..771a3c9 100644 --- a/src/components/Post/List.astro +++ b/src/components/Post/List.astro @@ -1,37 +1,70 @@ --- -import type {Post} from "@/types/post"; -import PostItem from '@/components/Post/Item.astro' +import type {Post} from "@/types"; +import {formatDatetime} from '@/lib/format.ts' interface Props { posts: Post[] } - const {posts} = Astro.props --- ---- - --- {post.title} -
-- {post.summary} -- -- +- {posts.map(post => ( --- ))} - + {posts.map(item => ( + + ))} +diff --git a/src/components/Post/Pagination.astro b/src/components/Post/Pagination.astro index bd46efc..16a3059 100644 --- a/src/components/Post/Pagination.astro +++ b/src/components/Post/Pagination.astro @@ -10,58 +10,40 @@ const {page, totalPage} = Astro.props {totalPage > 1 && } diff --git a/src/components/ThemeIcon.astro b/src/components/ThemeIcon.astro deleted file mode 100644 index 4f84c41..0000000 --- a/src/components/ThemeIcon.astro +++ /dev/null @@ -1,75 +0,0 @@ ---- ---- -- -- - - - diff --git a/src/consts.ts b/src/consts.ts index ab3587a..85cf289 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -1,5 +1,6 @@ -export const metadata = { +export const siteConfig = { site: "https://ua42.com", siteTitle: "Uroboros", - postPageSize: 6 + postPageSize: 7, + description: "Uroboros is a blog about programming, technology, and life." } diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 9f9820d..cb4e2e9 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -1,42 +1,48 @@ --- import "@/styles/global.css"; - -import BaseHeader from "@/components/BaseHeader.astro"; -import BaseFooter from "@/components/BaseFooter.astro"; -import BackTop from "@/components/BackTop.astro"; - -import { metadata } from "@/consts.ts"; -const { siteTitle } = metadata; +import {siteConfig} from "@/consts.ts"; +const {siteTitle} = siteConfig; interface Props { title?: string; description?: string; } -const { title, description } = Astro.props; +const {title, description} = Astro.props; const pageTitle = title ? `${title} - ${siteTitle}` : siteTitle; --- - - - - - - - -{pageTitle} - - -- - -- - - + + + + + + + + {pageTitle} + + +++ + + diff --git a/src/lib/highlight.js b/src/lib/highlight.js deleted file mode 100644 index b3c5501..0000000 --- a/src/lib/highlight.js +++ /dev/null @@ -1,85 +0,0 @@ -import {JSDOM} from 'jsdom' -import {createHighlighter} from 'shiki' - -const highlighter = await createHighlighter({ - themes: ['github-dark-dimmed'], - langs: [ - "bash", - "json", - "yaml", - "xml", - "html", - "css", - "scss", - "javascript", - "typescript", - "jsx", - "tsx", - "vue", - "markdown", - "sql", - "graphql", - "python", - "java", - "go", - "rust", - "c", - "cpp", - "csharp", - "php", - "ruby", - "kotlin", - "swift", - "dockerfile", - "nginx" - ] -}) - -const resolveLang = (lang) => { - const supported = highlighter.getLoadedLanguages?.() || [] - if (!lang) return 'text' - if (supported.includes(lang)) return lang - return 'text' -} - -export const highlightHtmlWithJsdom = async (rawHtml) => { - const dom = new JSDOM(rawHtml) - const document = dom.window.document - - const codeElements = document.querySelectorAll('pre code') - - for (const codeEl of codeElements) { - const preEl = codeEl.parentElement - if (!preEl || preEl.tagName !== 'PRE') continue - - const codeContent = codeEl.textContent?.trim() || '' - - // 提取语言 - let lang = 'text' - for (const cls of codeEl.classList) { - if (cls.startsWith('language-')) { - lang = cls.slice('language-'.length) - break - } - } - - lang = resolveLang(lang) - - // 生成高亮 HTML - const highlighted = highlighter.codeToHtml(codeContent, { - lang, - theme: 'github-dark-dimmed', - }) - - // 替换 DOM - const wrapper = document.createElement('div') - wrapper.innerHTML = highlighted.trim() - - const newNode = wrapper.firstChild - if (newNode && preEl.parentNode) { - preEl.parentNode.replaceChild(newNode, preEl) - } - } - - return dom.serialize() -} \ No newline at end of file diff --git a/src/lib/processHtml.ts b/src/lib/processHtml.ts new file mode 100644 index 0000000..8cbe07f --- /dev/null +++ b/src/lib/processHtml.ts @@ -0,0 +1,120 @@ +import {JSDOM} from 'jsdom' +import {createHighlighter} from 'shiki' + +const DEFAULT_THEME = 'github-dark-dimmed' + +const highlighter = await createHighlighter({ + themes: [DEFAULT_THEME], + langs: [ + "bash", + "json", + "yaml", + "xml", + "html", + "css", + "scss", + "javascript", + "typescript", + "jsx", + "tsx", + "vue", + "markdown", + "sql", + "python", + "go", + "dockerfile", + "nginx" + ] +}) + +const resolveLang = (lang: string) => { + const supported = highlighter.getLoadedLanguages?.() || [] + if (!lang) return 'text' + if (supported.includes(lang)) return lang + return 'text' +} + +export const processHtmlWithJsdom = async (rawHtml: string) => { + + const dom = new JSDOM(rawHtml) + const document = dom.window.document + + // 高亮处理代码块 + const codeBlocks = document.querySelectorAll('pre code') + + for (const codeBlock of codeBlocks) { + const preEl = codeBlock.parentElement + if (!preEl || preEl.tagName !== 'PRE') continue + + const codeContent = codeBlock.textContent || '' + let lang = 'text' + for (const cls of codeBlock.classList) { + if (cls.startsWith('language-')) { + lang = cls.slice('language-'.length) + break + } + } + + lang = resolveLang(lang) + + // 高亮 + const highlighted = highlighter.codeToHtml(codeContent, { + lang, + theme: DEFAULT_THEME, + }) + + // 替换 DOM + const wrapper = document.createElement('div') + wrapper.innerHTML = highlighted.trim() + + const newNode = wrapper.firstElementChild + if (newNode && preEl.parentNode) { + const container = document.createElement('div') + container.className = 'code-block' + + const header = document.createElement('div') + header.className = 'code-header' + + const headerLeft = document.createElement('div') + headerLeft.className = 'code-header-left' + + const headerRight = document.createElement('div') + headerRight.className = 'code-header-right' + + // 装饰点 + const actions = document.createElement('div') + actions.className = 'code-actions' + + const close = document.createElement('span') + close.className = 'dot close' + + const minimize = document.createElement('span') + minimize.className = 'dot minimize' + + const maximize = document.createElement('span') + maximize.className = 'dot maximize' + + actions.append(close, minimize, maximize) + + // 显示语言 + const langDisplay = document.createElement('div') + langDisplay.className = 'code-language' + langDisplay.textContent = lang ? lang : 'text' + + const copyBtn = document.createElement('div') + copyBtn.className = 'code-copy-btn' + copyBtn.textContent = '复制代码' + + headerLeft.append(actions, langDisplay) + headerRight.append(copyBtn) + + header.append(headerLeft, headerRight) + + container.append(header, newNode) + + preEl.parentNode.replaceChild(container, preEl) + } + } + + return dom.serialize() +} diff --git a/src/pages/404.astro b/src/pages/404.astro index f91ecdd..f94a2f7 100644 --- a/src/pages/404.astro +++ b/src/pages/404.astro @@ -2,28 +2,6 @@ import Layout from "@/layouts/Layout.astro"; --- -+ - -+404 Not Found
- 返回首页 -+ - - diff --git a/src/pages/archive.astro b/src/pages/archive.astro index dd1465a..e69de29 100644 --- a/src/pages/archive.astro +++ b/src/pages/archive.astro @@ -1,198 +0,0 @@ ---- -import Layout from "@/layouts/Layout.astro"; -import type {Archive} from "@/types/archive"; -import {createHttp} from "@/lib/request"; - -const http = createHttp(Astro.request.headers); - -const {data} = await http.get>("posts/archives"); ---- - - - - - diff --git a/src/pages/embed/gitea.astro b/src/pages/embed/gitea.astro index ecf3b48..3b582d4 100644 --- a/src/pages/embed/gitea.astro +++ b/src/pages/embed/gitea.astro @@ -1,6 +1,5 @@ --- const noindex = true; -import {metadata} from '@/consts.ts' --- diff --git a/src/pages/index.astro b/src/pages/index.astro index e2c08f3..2a093e5 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,25 +1,23 @@ --- import Layout from "@/layouts/Layout.astro"; -import IndexView from "@/components/IndexView.astro"; -import type { Post } from "@/types/post"; -import { createHttp } from "@/lib/request"; -import { metadata } from "@/consts.ts"; +import {siteConfig} from "@/consts.ts"; +import {createHttp} from "@/lib/request.ts"; +import type {Post} from "@/types"; +import IndexPage from "@/components/IndexPage.astro"; + +const {postPageSize, description} = siteConfig; const http = createHttp(Astro.request.headers); -const { list, total } = await http.get--- { - data.map((year) => ( ---- )) - } -- {year.year} - 共 {year.total} 篇 -
-- {year.list.map((month) => ( ---- ))} -{month.month} 月
-- {month.list.map((post) => ( -
-- - - {post.published_at_display} - - {post.title} - {post.category_name} -
- ))} ->("posts", { +const {list, total} = await http.get >("posts", { searchParams: { page: 1, - page_size: metadata.postPageSize, + page_size: postPageSize, }, }); -const totalPage = Math.ceil(total / metadata.postPageSize); +const totalPage = Math.ceil(total / postPageSize); --- - - + + diff --git a/src/pages/page/[...page].astro b/src/pages/page/[...page].astro index a1b2f9b..4fa2c03 100644 --- a/src/pages/page/[...page].astro +++ b/src/pages/page/[...page].astro @@ -1,36 +1,34 @@ --- import Layout from "@/layouts/Layout.astro"; -import type { Post } from "@/types/post"; -import { createHttp } from "@/lib/request"; -import { metadata } from "@/consts.ts"; -import IndexView from "@/components/IndexView.astro"; +import {siteConfig} from "@/consts.ts"; +import {createHttp} from "@/lib/request.ts"; +import type {Post} from "@/types"; +import IndexPage from "@/components/IndexPage.astro"; +const {page} = Astro.params; -const { page } = Astro.params; +const pageInt = Number(page); -if (isNaN(Number(page))) { +if (isNaN(pageInt) || pageInt <= 1) { return Astro.redirect("/"); } +const {postPageSize,description} = siteConfig; + const http = createHttp(Astro.request.headers); -const { list, total } = await http.get>("posts", { +const {list, total} = await http.get >("posts", { searchParams: { - page, - page_size: metadata.postPageSize, + page: pageInt, + page_size: postPageSize, }, }); +const totalPage = Math.ceil(total / postPageSize); -const totalPage = Math.ceil(total / metadata.postPageSize); - -if (totalPage < Number(page)) { +if (totalPage < pageInt) { return Astro.redirect("/404"); } --- - - + + diff --git a/src/pages/post/[...slug].astro b/src/pages/post/[...slug].astro index 416ab79..efff5d3 100644 --- a/src/pages/post/[...slug].astro +++ b/src/pages/post/[...slug].astro @@ -3,159 +3,186 @@ import "@/styles/github-markdown.css"; import "@/styles/github-markdown-reset.css"; import "photoswipe/dist/photoswipe.css"; -import Layout from "@/layouts/Layout.astro"; -import { createHttp } from "@/lib/request.ts"; -import { highlightHtmlWithJsdom } from "@/lib/highlight.js"; -import { formatDatetime } from "@/lib/format.ts"; -import type { Post } from "@/types"; +import Layout from '@/layouts/Layout.astro'; +import {createHttp} from "@/lib/request.ts"; +import type {Post} from "@/types"; +import {processHtmlWithJsdom} from "@/lib/processHtml.ts"; +import {siteConfig} from '@/consts' +import {formatDatetime} from "@/lib/format.ts"; -const { slug } = Astro.params; +const {siteTitle} = siteConfig -let data: Post; +const {slug} = Astro.params; const http = createHttp(Astro.request.headers); +let data: Post; + try { const res = await http.get>(`posts/${slug}`); data = res.data; } catch (error) { return Astro.redirect("/404"); } -const content = await highlightHtmlWithJsdom(data.content); -const published_at = formatDatetime(data.published_at, "YYYY 年 M 月 D 日"); + +const content = await processHtmlWithJsdom(data.content); +const published_at = formatDatetime(data.published_at, "YYYY.MM.DD"); --- - - --{data.title}
++ + -