From ae6b5b2be71e76031deb6ebf5fad4e0f66ef5cbd Mon Sep 17 00:00:00 2001 From: Mahdi Dibaiee Date: Fri, 6 Oct 2017 18:41:43 +0330 Subject: [PATCH] feat(TOC): Table of Contents post(typoclassopedia): alternative formulations for Applicative --- Resume.pdf | Bin 40456 -> 0 bytes _config.yml | 3 + _layouts/default.html | 6 +- _plugins/tocGenerator.rb | 132 ++++++++++ ...-09-27-typoclassopedia-exercise-answers.md | 229 +++++++++++++++++- _sass/toc.scss | 29 +++ css/main.scss | 3 +- 7 files changed, 399 insertions(+), 3 deletions(-) delete mode 100644 Resume.pdf create mode 100644 _plugins/tocGenerator.rb create mode 100644 _sass/toc.scss diff --git a/Resume.pdf b/Resume.pdf deleted file mode 100644 index ac97cbb3c7cde95640e717dccda522c79d7ad110..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40456 zcmb??1yEeewl*5v2?QS;f(-61L4&)yySo$IgL{DB?jGC{B)A9n;4b-xS z?q5?iv!`cvul{;p{OA0fqGy=%jq`B;0p=cxh(1MC zmCKHL;Gw4Gnl8I@0p8Kv%ofMIE6jbSw{>TWhwkFyb;H$tV|QEZ9;nIV z3*}Hxr}Ok6?&i{PBlzazHXL#WC1o8Cc{kyBV=9@;A(Zr?cfoft-Slb^4-AZl;Dlv5 z!xq}mtjld0NpC5@zT%XLBO)+$O|DUUo{O79wINJn87ie)%&&_Yag`U{FT95oD5mK} zgnTpsTlG!kQc0%a#?O{STXShh|I|G)#3xU71-eLDkclWv+mBPT7pLWlyfBMo{`!e| z!UL;uI*jOI@siFx0^g0%gJLx{!`rCM%XgD6B|IT&5C3`-t^^gi5^tANCnO48l}wg_ zzED2`UBjS=Tq2hU-AJ+Ccu^VyDt%<~-03_!hd*qAA+ZAQZsgjE~n)b~mduk{Q z#ZYx-5{%y&g;L7}z&+RUeYhi_vNI&Vzs7do>TpzN5u4&pIMjN(bBgFH6gw5>{E5L_ zJZ<|OI+_7P_CDKnLwQ;a?jqmUQa#$2-Owx*DD*5|pGhQ6k1B1Ek97!iRtZ-ijWkw; z2|Mu?(LZFlKSW`W>?UfbP@q|(gyy0*-QlppooH)DU;3FXBBJ(wvsjE~^;$8)^6z+^ z4%a^=5qeZ;UgBLv5b~nh1GUc2J!c9jwn8qzNz-bvWoUOUGg|+kxXhR^9!fjCpN#RF zN9nsk0s(uJJOAkYJ=VF|b65^uQDiB zB{M!yB`jx1?AZ0&2RH~*^F&{g;aKiqN#ky=q>GQHI-MZ59}p*V##0NB{9x_UE*QM& zHdPk)K=muEY3%!f>g*K|;za{x&cT#T{g|jI+-(}ZYT&mMbie^Vl&M=K*%3>33nPA} z@ZkR`GDVEp83z+gY-tq7ev6A$?1Lx-5{Avou-$G`@m?)+ys+5sygDQ&EZdQ3uPuZ^ z6TZlh+0bji(OSnAg_@~dIYaItugFNZs0Wu0(cW>wh@fIy!I%q3nPEHQ1<2lnehu1w zXBj!Rx;5jVr}Jjs3-UAhk6XKOr$?lMTn7W0Nc`@Rurn?Kr{O2TK4mx7nZOzAc6hq1 z`*{h^U6&KeMB&#po?k!b+v#sK55D$QyjEh8R^ue*V}M2(fRWbXfmF@A3{(WTVw-!RoE^z%{mD^TN`Y zfmm+zE;Gd9O5FVo@aQ5==2j&%;q4?+#Tj?H6KGG5E&EgM9@N1T$#F+fKh&E zcN{@~vRqn~=Y*o=OeTnoYOLV-(sp5(jz~}NtHEmv>uHSoL9XQjk1p+(ZPQ(sa5(MZ z=x&72UIhHN8DwF_>pgH>s9l2@_=beD^rEgB6ttAe!&PL^(7fUfP=$$F$Vv=0ZX^jn zYAFjSQ-^?kzFtCYme+5H1ssuCQMb`X>?w^c`y${q(D(^_&eTX76)|!(@Y&!pRU>gz z?+U{073c?hw%?uScpwrFV!}rgTBPfCYMp9I2nP!YBo-^K%QoitlX<)+kY~3X;mL6F zCZyysWXGhXraTBn4p}$+N`EH)sH*dlV|1Jnzp223_VO`@^4nDYiDc4}=;i$@&Ytkv z{qe{m;=>|HMa#ER319Xb;NL~>HuDvc4PBwcQD??)4p8^LeH*v44)yYVNnetG8Bfsu z`dU>DXZ=VZ)5l3??z3u*%u!UUUQGBti;Ay>BFRr8^(t1{!*k;Le5wIR`)-P>M(S#) z`R}dIHLq-V!;HaF1VbK*>c?uk*T)4f<>^j-(8ZHu6>&AcmS~0@LQmNfe31w=k~j@X zmlKcwN(`A|q@fuh-~0Lii+rt0%QyZLt+FP1?E8{EInTpS5`Y|jAPL}bq@^Oc1*1aj zZOj3YLx1doI~1R!%Vw*_X(tTe^p@0&D?b8Er1)+%|3F`sN*AJjT$E@Kqwl415sU?j zAU@^&^d#8O2PLS93{e%o)3DNSXjfC&w=)WHVeS_S9L(rY!VdbfUzr`cz%jqzyvL@^ zHT@!{aGtF^giPJ#i`hrU0`t1VmYme>c*<`W!xcE9(IOsl>2)&KC(2@@(o=QF zX%kY0VI-=fdtGU#DAy!(ar@vk=*7_m=*9Mvul&Y_E9O(cN?4qE@`?>z-^>#f)(Fzs z1kw?* zcjoxmZBivDewntUM-Wzi*kb;=R20Xl0OP;|`c9cDO$BM66f!LW8w;kM zrQeES4+1#Kxctbf6PH5%LE3_zDnW9*0h;MyW%hH-u9YEdruEx32th@yQ{?{7M^HLK zZ=*k-E)2sjNjNk$f2vPI92jqa%m~I(N0S@Af*`wmcMP^ym)$&8Agz@(%xJd>^mYZa zhIq@tX_)w-CZ!C8g?uJp2&Nr+m$}@T)}E=4LgxHzyM(@`5KcUXXeLMsej6f!vlOn> zh_8pqE?aNB74F>Ar=mh+&p0`eZ;zKtwLf20dbj2SiVmz`8qZbybWU~KA>(J|^}5m{ zEN9jd$V6_MFt>VHaxB6q8YZ>zvpEGuNm>h~D;0RxJe;$}{j7lAq zLM_oY@op_Fr2poF>RhamLUpj2eI7X_0=q%D?OrXM3cLq(;hY~26ts z%g#V}Q#6DID_8npTK`Fk_)S?iU16WGh0Z=hzzE)BPkw@?+2-RoTKgTe;3l1_1KV7W zGY=_$AmZC9D;Bw3pa@o?Z?vzn-- zyzlPZTGxTB4m?*w2UVdJH7eS7JacdetGok&SJTL2Ezw`hw>k)%7i|U_D{*;u3QWhO zWW%RURNk-5i)dMt>}+Ar>u@HwxVSNc9UGK6AD@23nam1^P7R=!L5glGQQZFYwd<== zo_?AE4m}ny5tteQ(Q!u&rX^hCX4m#EKFByJ}Prfc7?UF<0< zr4h=O%NP%}@{R9yg&J;Nns$z5826I#jk6BJGH6Ax9S4uTg$g!W67j}RTKRTSGhMA+ z-;Woym17a55Y)-t8z>KJK>EL4hi@6btOj0|Z6<%^B_(Q4qWeSo>*)k^l83cY=g#z6H;^AHz8Cre|=#7u^glUHFkI0{WhvSS;! zcFq@JpN~)3;p_?c6B)M7k&jpJ5HsEN{)5uS2Gub zR&uW;@lY&bF+IXPJR5*Oo33%25Q^T(uRZ}f9*hp8lz*8zhyc9EqJnNryi=&m!w_;H z^4R)>-vP@h7Ht>K%MDDjB+q{X`-PqXyOTRGtWZrI}MpSD*ld=f+c2M1nA*Z8w4v-f^DK zyM)WW0HA#1xh|$E;qhyWdWzT5HeZRL(a>LaEVUT0Avk2a_P?R^5-BuwZ}qF7Ki1M5 zila&vMnAN7aAQT6h!-ZR?rI&(q8~75-2b405lQZ1v{gxOaqwd*@XMT|b@vNwQS!Nx&H_E3^AOS@b!py=|yEXgt{6=WCvLuzT;_u8&E}rY=UwEb~D|+3c1^ zZ{~mpgWFE?1m0DoBceK%bNKxwgm9P5(N-NYnpN2|am!?a40CZvky<&V?_)=xH|f== zD6#ub6)12u<}EP96vR}X`kl&7lS?0i_yziCWC4CnSi?5e&nhyD_OQ4 z1ws6LX+bbr0l{wU9~_Zz&7N}AzRu?Tc6`w1cQCeb0xT}h04VqzZLtA`S^z*1 zV;6HnV=)JP_y0QzQ=kf?q&S3|r5P^($W^7zCH>;(lrJI)3uuRBGe8#y1ieDX?0rXH z@ok|mz*rPpRNIOM!m=+QxG&t84#i1cZl*5)Np*DziuHR(?Q!P0!)B4#S#Tk_ ziWZET4xRf-W^`S--axH^HL5l2Q+P0eelUUgPYJ`DU}j4}POWzO_{e@A z=`$=*j)RT#zF>(%F`>nDCD}{8va%5bPhQ(v>l1(fayzv5N0)`cbN7=-&`2_-qj{^H{OX3js!d|+siP9165y6U@N%*6ntMPgt@YR)Ydx=qj z7_UFT9U|F_6*I6x8c-1llPhju0FZ-H;&fk04ORzpM5tnBL02>P8ViAk3?}gQE*b?7 zL3JYZn%)M4iid6x`_RWbDk#4~p?NJsygSb3B~i?PUxCqb!tB13A`(hK{PY%Jg3*$L zkFNY$mdvP|b4ZgUn$js)P>YyK;SP2upV>j*f+gP*Two@7L?NtwoX|lenkpR99`59<6o*~AiPUsHkiFZm0uu)K|s|>2dO9QG4h4C_n3PZ>t z8ss^c6=*eyGaD2f7(_^7sDvRf8`9!Gj5=H6`QAvJ2Plh~JsNQ9o3EOdPx`IX9E2%5 zuZD4C`Vo#0DZ?|`w;GO4gjk}ORov!|G)rc>#!(qa?sZEbSW zo3mBkjL1P$zVLW&>nsuE;tF^)@YbBySNzn}adX4@X|8nh?I9xNTY=7H^+n8DWJQYadMSnxe2QDkc8S$zyunN zDgpo|j?SM+wIqWIkkli-L*?4~gPdr;KEFiz(hE&F_iGlyR*8uP8x^%kBI;dO_^s#D z)WO4nS!rGIv3!Jcv{7oa5?6DDl{nxLAMHgPe^>X7>S@kWRCDtD*i!$}7q70i>)=55 zz+3Lxgl6apo-P#wm}*ir=9z$c$QK#)dX!ZrzG!f3*M>-s@#T+Azaps*~AIJk%;?(FT{LqVXi5DmXF-dZ+l z#n5~FC4Ju?`=lGC=OPzOad+k-W+yBqERTvnrBd|R7p!5QoXkQH`xAH3(T!1*cZgdU zCffC|g(#>Ti*y{bxzb*K4|CKLlLAA`2)_TO-;=WIVE9e=f5$B@vvDD@SZv;qyr19|+3u$N=BrRhSo&tY7i~Z=R2?e1xG;xchZhJd(ol%e zK|5>xCk7tfl^FJ8#BN}2arteXfc_(%;4(GQo-k}Uxix}8)ReBu4+Ib0Ey5!Y0;mt$ zqTRM`5aQ6OdQ2Beu(ia26V#CB0?%lERG7$mtPvT;&>IIdxDNuuvA5zcYarBP ztOWPtyv3OvAUH#`-q;W?ixZvUyN4JQu~~#_e2Ctqnj$jJtu}kj1@}d?Ft=bA!U?Vg zt6bDIFKQR=0%9S|C0BM_5K&Jfh0!Fi+3-n?BgxNLpECt9JxbYNT8(Z7Y|I|d<>f*5 zU3DV|4*MsZChpH7ELrc)Pt0$uycjzOSN+-73r|Yj*!lc?0Tbd_WU2~)FkxKTVe+?> z%CRL9&iR4)lU3JOu{v=>MusUw{3(sn4utL$?u_oF?kKk$w@kO-?y*9-De_v>UGJgb zlSvAdlcMc9*9HlWZvQT z@btXyAwuFtgo(U}YK!_BW%6qJ6#?TuQ-35u6lcG|MnV65R3%;~b2W>8Dy%eCDoctM zqq{X%H_K-wJq`1gfx5|yOq?Ftue7UH&GW>yt=mn_5$^G~PUmm83%}fpy^4m#?ZT7i zH24v!ODBhb9bpuails@nK=*>KoOV7*VZ=F!lJ34dvb?+OtV~6npnkuWtqQpsOTDs& z&*U*hzgLg3H?lrbF%ldPA>9lw_zPA#ayqdlrs)*lMAOy>7mBai^KAx zf%)Y5K4v%i1v+F^OuV?JsV>l=lAsdMXE#nGq(&}DUNsfuu z@aqA$h4hBp^1p}t0qcM=jIw|;#occnsrR{o5hcJnu(?Y!pjGG<@jUTrh*R)Fkb|(L z@Nvj|@M+I}H(~XgnlrUlb=d)?f#H5a{Ch4Q1}~MHQ&`#n0(qPXv|^%EtY*G5o%hyC zHd7Tv;0-9A6!&f{)Ld*H?iWbW>n2m$4fS&sbUdwv^cH-7TkIU!{vluL1N(!p>~uJa+aGdb)auSw}q0f`|$@ z3@{1nAk%dy885MWvu0deS|_x?N@usQZw^_brml^qz*1Z!VFUYv+Des!rbFHdI|OqU zvoke|@9`62J5D^#5jj11gd}0&o5UvujO?NGc?}aqw#qV3EX$ds`N6~DTFsrgFX{}1 zru3fQqur<6Z_j;q;v(iO~>~mbH~-P^S+79RANA3wIDqyE?FW;TbHoKYXH9eWdRLg z8Gd7p{YyjTt&-%@!ZJS9Bkgu~Bs%p^8Y0dFD$atov-_JWWbAD{DCokIiHb%&A%Wvh_v>iGTS0Gj_ zhK>K|R(3J>&3^Cn38R^kuujIj-P_?|$P#osbIyq7^}dpxN=>jXYcMno93$kzcB{B; z`*ACb?FD3MxUVC6=-WvSBqYzG&8xf zP`lIJa6PIb{UN=*v9~enQRCrY{HXcFL&sh9+UAls!n6Jd?rkNnc89iD3u(*Zap6+u zqu=$nAzRVT_G9&v*sH3$xXZjdoywISZ+Y)zLRq(^bCElvqRw^K_EmNsXP>)CB7NUF zlt`jocM8v|)7y1y6JSHpq({7biLC#M^o;Cry&WS(8BfAn2{I#SQh6*Ds<`)`ly*#Z0It^p;4g@yDTjg0_5 zy)Xs9UtZbYJ>1`3*&lAL49LIzSFcP#Oz8i1$}*E&l@#Z(LdM$J+sDyK0OS|A9&muK z+~O~xCBD%F4X$f~+ z&U(I*_Bf!vI=|C6J8ydIJ=+2%_YeTp?W6|o$C9gt`Td|v3ms#m_Zs3ADmbzl_@^}! z6DYA85s0aWcHY#~BJuv(tMBxFMy-pqopKb8Ge3OeNZ5tRUVy=iPP6g&P+)ICyjQI4 z!(sXXHGGjs&Ge3u2`d-wLmA0NZ>7~$;Wka{P)ahzW-hM!C{7zoR%EN(N*eiEUL;hm zRtoty(>yO2<8~#9G_b8}s>#Wl3~4Y1%v9aaI~2KAVN9Z!IN!t0Ai!YX_j0y5AV=JC znq`5xeKg$+hYFK0_=q-}V!pLIXmWR2t9Wa`Nb|nu?OLdt^w>omVl)G`U!`r5C^)&g zb*fq1Q91t6k^0QG*=^_iDxr_!Bk!Qcz49r=;aHYnWS07>)nOU19SiJ=Oe3A3wj)s) ztj_v{z}8xs>@fiB3>vI%CF7j%os~{}?>ZtSLd4;rl_PkzB|Xh9`+atR?QrKi&g;~X z@AoR)AF=uUNhMw~8;fpzEc_@X^7%6&a`Kqb<2CA!jZd8BUxs>UGqOKnp9b$L%kRF2 z3kox94d(Gzi={V$5AvN}^L@oe34`O4X^Cm(tPAEH%qiC-0W)aJ3nokoNoK?E0pWe1 ziOL8+*wJQI9#`oY!{qU_b4P@r6>hU8El8rceT5if3(2cE^B zo&kbZ4+-Co*$#3A02bsYjtZFsNiPmzE&x>{$TtTDFUU9t?h|)JK{FYw(+|;>L#+>mK8#P$GQxTz9H8OBCV#_#^e28Mv zv{>YPyyhtJIQvb=7a_U&DX*~laW+EKBi9U6^k)nt8KzSVQ&gm}x7kcknf-4A3Jj*J zKdMod@w>pWp`}OB^{VK_=xJ6ZS3}O}A9CX(4}8K|$G7uodZoo=!&(8=h%y`5>UYqC zv_^62*7kY@^Ed#d%kjj(i?{>c7vGm~HHN6alQI@g1IjW0g*XX7W<{oiiVM2~`xu1Q z%_8q#B30$qy!c~vU8Z`SI% zd4nZH(>^2`gc_t7gc$^`v-Zi8x5fL%H=@fH3+z>WB`+Yx6`Cw?|JqddwvKDTc!7aH zj6MH;GGVXpf@rt>0?wG+SaXYN3x5lDt9Dr7MK^=q4YLAHL1aQ?Yh=th%XahF#@HfT zrMb?JHtNLN*EX-c5=jzG62TK=N~D!-r!l89ORP&|rx+|KEc7krE$*l3OQXgL$6T|< zGId#gY(9kSSG9zBG~HQT_U!ZSC*Y>xcHrXRD&r=z^t0lm*`y7nZKdt74AhxvAk;%? zY-#M&>o6pye*dgwLS7renOk0QR7f|$m%m)fTW(lXt7e)fQ#*>G9Z#>xF4(BmsOTyr zD+N>o>Q>4h=km#CmuKg9igjxG4u2X4Ea*iDrgs(PhUa$bXX)py8IqR7l}^0Q)5zoQ z=P+!r4?pGG(4?pe%an+hh#GpUI5)MTq}MW5H->1rZAQUT%Gx^cp=wE8z3k0Q4rdR~ zpjV!I`YjCtZ-iPzCe|{RF6|MmBHaNkkvg?Hw3>C@e$`#iLT{R-wxRdHJBtm&+R=~8 z+x6webgM3%N8a3N+EvR~tun1+SIAc+_Z0VxFuWmdA??W5b51T)twG+?Xa~D%O{1rg z8!(ifl+}|Gg{ztBqtv5Fqj?C3*eBRibgvvH?AMy`9pdPX=p%LA>~g1+7ZW!$4(>j` zosHUY>9y`%p5vW=Y`UjGkwS?Rix_xcn6QI8hM*IgT&WtTTG<$XZE$RHT*$}87seOG zhtc8EQR)r6(SL+^bh%qTpFP>Ro4uEX;(#iH+l9}EdIO~b!-v2GhYsxw)zbyu)fzwq z{HjZ)HH8Hs^dRgK%mc@YsQvQJ@fAHSOBuzXdy}%8kDDtLoq?!`aBr)4%;48Sv4|)v zDJ<7FLt=fR(_(K$Jw=m6rIOWX)oVB3L~29=KJsD_;l1=Eb8#rX{<W?st?&2-!iVNLl*Da{ogw~Mz_?>>5ov2go z8{>yKsN|rUpb3%WUhObLi3*9A5*rY*g7x2=Yjn^2H;doLzR#m(E}kge9t2W^)Q}Q|TRULX}wa452Ld`<*YwdKSn#fjtRxhoNmQ8BQEf$kW zbS5qhM%KgEWyzP~4_4K^Rd1I+Uj-et7hDzGyMA+lbzNHCYdKd-HBi@?AFuePUB31C z?88}OtLkBgioT}39*TL4QA{0EQBAvKrG?mZ;eP(UKWcYO84ZL^O|p zjR?aI;Zk+tYpL7(npsg*u`=SHT&Z)~>`=Vee*d7HTxwdusm<-3>D_+x?lEeHur(`5 z_t3|Dum0G&eb27;F=?Ybx&zvK=T7?`xN_Cvy%qf<6Av=t#oc%M4$mJtOT2sDD~}T} z#V9)bpFKDp%^nR8H$G6p%f8Mk;V*xjzL_;CZofFpnbjMs4KwUYa!BFps<-|cMzvN0$ z2j|_)mGzF%?&hSc`SHiX@RiaI{wx2-+?nR$FSv&@HwtT$?bYj` z^ZS2urhPt!KA&Hi*ch39pJ|^{4F7Vb{gtcu>rDGQlk>NdPNqLHGyhjjXMx&~10FkS z`v%P&tV&;=I>X{b{7cQ~_u&yvoXRf9;XFw%<&DU`Dr8j3LI%#JL}6-E6Nn)D>k#U= z@_*)S&+`nw1y-I@l@~EdC{16CkHct8Obk)vmLidVw{`40c%AUZSk$#G_fvAg;|HBy z`Lro#oaDOA;Py)0y@>Pol=2p5B!z9E@h#GWQ!`r13aP1sDNKg5!z~@A$!rz9^mO}m zGR3sRMJ3XLs;*9LIg`-oB0-0XQ_2}TQ$EA+E77Lmq}es5XBF)n;Ts&eeJ{yH4_Y1@ zoAUDdx`nE4KJdjq6{O1JCOpZUFQ#uf2s7UWV%aXbeO$^nSL$`&>yfFMX}T}e*hpoT zv3fZA43Qk$;Y6hHHRjBmua-KlqdN_zthu_AO!CK(s+DgyI`Zhz?Q}Vy{ppa11(col zkvMo`-h@Zzwegnr+fz3`$Jk>?7goV)_N{Jo)z0H_52`LJ9*@O2vA4A=<13oZbdzD@ zbBTK*JuHNVC_M)lStNyb$|yx&7q=%rA>fUAPD6is8<{`N^o&It#`N5rrTX<5tuedk`d$qV-UKCt2URvPI=gfLG**l?;3eAIG79HA-jT=WV43ywB>Jw_G#9k zY0;(rYj@%&BKz;yaab1%vOrH_JE6ed>#vI;*kA!IAI6rwUt7Kfy!n0=a`*` z@Ctj$e7iFo=5m;)W%D9{MUhqd8WKsAEyy;BuuS*sOp-d*LY9THO{iU=JZ!xe>G!5z zYb>Flu1VNEwSntby_YYG8b)fq4zTIy&`haG`3cCFQFn%N5`PH;nrGzDiYDCv352Yi z5-wr#%D8a$!0;o9ifn8OZEQx&-dgr^$y(YFb~q#wtmez^KxfTqLRuFm2%5#=IOPD`qtJ0`q1K5YNIt!Tonw#$(r7_omgNdNpHuY{{ z!zABajX;ImvKP#Y#<~un6`DR8UNMcNVy}4GmeNrZxAhY5i);`KuqB{sI5WJCs{cLH z{6^ETTDm0WnU#birGS{xusYPc+tMr7M+B5fS6x~vK1|udTk0-Zp<|JiYss$C;t#Z@ zFJHG6h^Vi~WZYq*U-7(x!#WKX>t5_3t;Y*xIfztT6iSH?tf>jmqR5SkczMv577R18 z=Btjds#VdHac#QdiopbIdhESYK)V(_Mfs>>v{Xj`rzcn7*1+wGrSEd#$>lmCuK~Zq z2YYz4SpPOnbEzZXFdg|8*R#A@H79qTh*zz>uH*0L>L4-$OJR)+$1jgmlbxg)R~7n?>-NCOvp=hTa^WMWi=6&Yt%+ z4ET%QFt4;<1DMrZ++jb4B=5N&DESaNZgD?_pr4}_5qG*I`y{ED1sKR>F+$-_Ikqeq z85fccdpQ9iC>H7xi94KS51bP6A4~)*j_!f8pYyMtB4)U*{UWTcR)ML(H4eZ%rmXsg zo)~dgZnNeMp4Or+1mNI`sN>pMpb4c8koI7N6v6daJ3O z`=$GBrMqA5&F3L1x((nZM8a62MW3Ng8?2^elrOa}b+DMTEt=}47*JvHn1@?{*Ar(oiAr( zVf`zC|M&9#|0ILY^ec%CO055p!e{!G!Hk4gN0o2~y_LjNBU_diGV%W5+H%E~kUssLdAm49dcWk8vK#eJB6<@WzHr@zhc zGlIWn(D8q-YIv?pa0ZneFady4=0=X7x`kgdn0|H+ul={O0_MM)>t6zd^_}#sY)yYv zTR8qvX7N`c!p{-@o>V~q^B=Zd$kxFK^t^^9NCnR?P<6zw-hS!^0914~aQa!oA#HAB z2>>b>8-mIySlQ^=IM`VMpd~}k$iW7hRt9!@1~!n=S=gEAIT#t4wc-CJ`1ca~Yc2#0 zoy=`*K)nNi$_f&{-k5*aUHo1JKO3G0Ol9WeWXA;ry1Kf8wwaxkF}9 z*#(um*gPWx+Bq8lt@X`}%;}8G4fM^8je(rZKm#TNpgsfpU$FlkgA@d?{92p9{|fdm zlpxg1Ahc{u09Hm;dQMIbj=$snDd_*k&GKuL{Du2x!=KuG#%S1nWrB82d`|H!z z!4&B1XzZYC=U{7MZe`35TFvG*yw-or0yztVzOB_i>i${E@48@d z8)zwml+Vh{PS488^bgwqDe1T1|5^JizsTWlv+#Sd{;B<6;LY`I9O<9&8{5z+D*~N? zZ=dxK{7c)<>isPb1oRi%{C7bAfCW-FD?O-s3#4vV&Y#=)AJqM?rr_UgUY1{c|2Lq& z`RVuO{X>cL<_>>?`bn#Q1NHxbk$yt}aB|YKJ`)lv2gAP*63c%^NG$(MNIx5%$NQ)9 zOwFCloDF_%+TW}6Pjo*^x&DUkzu+Y%1~z(j&|3V-L+s2TieqMDr3Zmy1g%UKwtrw- zmj8^GSpJ!pem49G?tf(4pLJ?~pNhO|K}~o`p?Akv*Ax*&&2b0zA+K2!6AUiWX11Cs#OiXP53hwW0{=b0xXFg&57e4v7tm#7U-h2GHA zoZsAtmywZ`nURC#FVuhE5g^q61--B^fKC7`e}f5HrHsGK2@?w^Jrij4{+(Zbiuw<< z`p^8r`p^9G?+*t*Yb}3w4+8dIP|Tm|{6l>JW>7`yvwHs>s=v?Y|Dw)+W*FArtM5;S z`H$4e0b)63j=!||cg_ZZ{x6t^9i%Z<02>=<1v5PFOAus`r2w^XfU0pB{%M2$XUxO; z&&>0);pYam)(1U2Y|HhVN(KJe-2bb9pB1`)9a5DXoQ;1?_jBU**N;+?(r@2L(#YBw z+bDvpES-?8mC>)#UJ+wQLkDv^CtC-2wm*1G)CTmxvbhcD5dBu)P{Gz(-{!BDH|7qG zPQqsT4gk>6A1JN=#}`IW8X2f+ZscV4^T5u=0RPgNJ{{ucx2aL)p=H|zkGpN_-x9jxpeAnBa{;D`Ji;O`CgYwDk;{jaJ0HPtfu)}RXI z|3MX2`lcXv1vID6cM5?jzTq|L*g)o!j)@cGS}=pI7#Y|&L7s^O$iXo;6tpq5G6oF? zDClVTTu=V|<8$@%uWvtZ0t)Nfi5r`nnmNIA z2AUR-@VEMIzrOvH_;W0vxTi4_fbE|x%Fl-1nEy!sgUr~^>hND*89`mLKLh$d9)>Sa z_jJNkPV3Zdzss!HzaX7^r&Jh^oYE`6MfM{0y+q5o2u3`Iw*OH6P)`ntzaRWA<1UGn z@C**oZp*otSFE#^3Qf1ci5osqL5=G3Mc#OdJ-xK_FH3bVmOGT$(u2%9}S!^D_s)BATZ;;KFlDElK*M%3x5>d7>GX<5SGN%X6CSea$Ea!7A&e7maESzf1bP;O z2$``F0kOcR;QK!Kd;PAB5nmPW8?lu{U5t?Bj0YEMvy6_m$AN81`XoYG zb{-6?HPO66aFY0Tgl@P}vC~f3{uv!85b0!1avi%fgdKzd7x}_Jg!<;x$W+YUe&oHi z%iDa5GU1Fl*7M8Hu+enK?nl&O;Vt@wUjbf)P zNJ;x{a*gv%jcCfhz<4uC$;5o4Bo?~KyIJZd+LF~mMwkse%MAJ~qj>8o+atSbukvlZ zr#2f8<#QI3&YQ5Yrqi=qU(1m*QqH%dc?l6i_nXjqCj_0Fh_^v)em2KsBGzh)<>akg z+%t8J%XW|ZGfCSY``?MQbyQq&)tgM$)2Px`c6=;xnEy&{teTue`#Ky8i|RJ64ZoAj zqn3xhu*U|&E!x=c{UFyxzjK3J5;`?`MLw>S)TZ00oVU4zmc+%rgXB#0`UgqUs~mBO zJ%`FNv1&X_?$QGaV4w@nM80O+TzRdUt_BC%U2F6jxT5RURQgFCR{Ra-&>q# zMx-I3u#uo;=xd0UCvJGGU*$TrVOs}DB-hFm~P*;r4xak(ZgLPKZ%wH8wgu2np5{y9$wW;WKv5H3R6Qt^0P{ArrC+4 z5d|VVtS&?83)-Qsi3fF8*-DZhROiMtP?k4H&xGg#EYzz%GPl?5OgCobix(pc@Qu7}=qyyt5noOfn+jwIPv-|0akKT6o#XR1RR7&dcK{P9A4C$B}o zRGSN&Q=%~c)SrHc%U0R6y9n_5cGChnIrpG9(am<-@m>zu;yv1Kzd;0Sri6C6Snrh5 zJF?Rua$^qC=?LUSfyafcsgd{k%av0av_jylG#$C5<}%g!_RG432`e3+Y1?U|9pmm! zS&SD}_lM=3wkjSM#vP_g>nLO5<_?R8;5ofG-n`VW^NE}g zh*)y$zJR)048%$9yTs7ZfyNvT(dNzCE)Ety<7aaR-c(&ls4V)V1}sllGeNT{5} zh*W7zWCs?S@j@bNjJ)ySJr^-sT}h*x1?5togi^$zTHkIm>FtNDyCYIJc?8a9_2Aw* zySq+mHD)x>&=HvL!;#kl1V_@Hg!U?QNY@$|rR4glQVNaHdR7siF7ivhek$CIos?Ac z)z}lSU=cI?-pt(=xPKLgWwuvFN7u!o#$Ehr)w&~G!D!vf{s6)cL|-VIyQHVbUA6{v&&zFo*iwz3hN z%r~>)bj7}}bmPvz8k3VXPx1S@zNhdV%023Iqun4)+Mas|bM@V&4U_R=$R+CD8XtiD zj09)LVTh}2)*h&@E!Cg;Ws~@On|jP78$l0W*sARimkT%bMt@iW9%)c2Krtvsw`?&x z9d`4j)kr=!X;=S`S_U`SdP!sz{1t;>DU~|yv!_Q@?iJO{-e6Zx4IVOtY@If643f3k zkX5U7O7JpsxUZUcNe~Z>N%#Pw*h)Q49%Nm{sL!j6L^TD6bccC|1BbIq=r-)vB*$Be zw~!C!Pnu+(EX`6dj%{eG8p?4u;E-L1(F5iCJJr;&NUvx z18vZYb9-IB!QBM6gMq9+#v&>kub*%jvt@v7YM-LsA}d`#gC0Aca%A+Z4JN&8guKdy z8(8%zuUjo@3`&NHre)8e#quF1r35NH=yk#CP_R{#NW9kX%q#xG1XV=wFM1F!KWFU3 zj9w4~08JZA>l|5&GAZ3HuuO$5;69-@C=2tY44U|9w~(1sa6>0bbNgNhom-hSobZia zC2Z{{`mEb=jvtoM#!wC-fD>)#K_y3hA%S4!QNcJ*m4O*C8p0MzDE^Xj1L0&J3eMX8 zfk_iwg|VMtzJG@Sd>O(j0B!?g=7{0SjysC7@eA2R0A+KQZF(xHlvtOqKFazWGxwL^ z8&?T54j?wjpeEAq!O`R0Ds;WoyE1H^(d@geh&ectB%E(S56)BH ziYhR?qN&tUL5srD{z6+y6`BYm++e0Ogbnee$AF3GK)i9?pB>HP^}*6^Bc6!Q?#H9G z-u*^WLi&B?GrJagZ0*BX~cob^sJTl!^c_v3az`X_}#RHzF8Ia zN`9GUAJT=+fWRd3=q_Up9AkHZeCBj>0_!Beq@6eLC55Z$&9$#-z-=Pz~!} z6w4a0fJvkK3<&5tbJ{>n&?!I(4#m)y7L}D~sN`-ghQGGQ0Ee@J`0j5LO`xT(`#9w- zi+_I*Je%G6WA%m3{e!D7+e)kVbvw$c*O*~(Qn9J-O{%ckoz*=M=IN2&L@4r;{m^%9 z?ib_R_I0>ueK&KuCUD5Cw(qja)aD-AY-~C9 zQQxN5ZT2SOwE46Y#s%JIL*Su0tnw;KEc)R>7ln`~bV-e!`-@L+6hKF{*xxGV3)UHf zbgV0@S;}C$nY!I*jWllV;Au@zYW|W#BiRQy<#+%?AoI?eq+Q#So9l))=o#m?gl6VG zQ)5~P&2kG|nVM!irqYRtc-X`6s6@lcd~)Qt+Lt zXhp|h_Q(l(p5aJb^bHGF?=p#q2@YW8z8!oU5rydZ;99uqbz4(r^u^Bf(*Ds-FQ5zOWMDzoi+2wmPyU8eV>I&7v{r5uOM~d|eRNND|{RYDd zdO7k@|AFGkjWaID$Z`q8&_3db>6F-0t5VP=dU)l{QpwB0I5EKpURs3ylqE)J-n1qJ z>-#WxxW`kGE}EtkTswb=_*B(%Zjdy&QN5TcQyC#w%u5sTG6Q@jLNKNn^Ez;~`Blv* zqzAH54K^>>iDBjoHjWOwl2fRn5R_ACw=F)4pur11gv>W?CMfu;dOUPDrfEncxNa!r z`Vv_8b|bej&+Z9fAoW$=DgI*YC_* z-PI(pT;sk}%au8-ykx(U)Aedl3ny4P>*xMFcXjmRZ2L23#g6|~^!4h8W{0H{M=?1| zw(U$VR(>&5E16BR3Nwr?*aI@cm`?B^i|d7MvIlK9Q!060-^ZMcoalANEj`J)&!PHQ zXUq`X$?oIgDja;Y;r&Cl;k7omW9+ilZjYqQ=NYd~_^bHM%23mMne-pN-kj@iq_f<| zrn>1NQ4k^!T_M*gkp-9Z-bg!Iv5bids_(=&JG-e2F+(vnm;{2 z#T5!gS*3yfRqK9Rad1RdvJ)+FJ*@B1_Q;=`(bk@u_903Rhp8P$04KOmWCG>$cAjX& z_3Jyi{mad|`{cTujQ~t|C1YM~sz{ad*~CUB9hBj+LY+ut%8c4K-kWJ^75IKGY>nZX z&@Q(2JvqrGh+ilq%`O+KI)DI}t*589NeIn{*X_I)7pl-jK~ci%0pa9Mu%d;TQD@iJ z?f8;}Zt9jc^Q%#`vBeGXU(|x06^|-WJC+N!quU&@y4}y^0Ms`ntg!&>Ka|y52Rj5b1aeWgW`)}k(uxDT8QOCW zZRf{ts-t%~h@3g)oE|t9#jV?z{(ztGO&SD2R$$qh3w-0_?#nR?Zb*A{V2Vu}Qu{=qwVX_u{c9fGi>Hhp&K`!IQ8C>tyXBh63gwICRiM}YOs>UkNfiU~RF<7W> z0wI3*;9J4{q2+f<*8?2d%?+am!pYVHMU(5RX0mfaY|!+ugLx1N^v;YPfUVXO3tRFG zo{PIX4g9?Zivu6*G!NlfA1Fi*WF5Hqhcz9nrXFb1k8d?N8FF~J!C_xMf2v0|H@DIL zW=7Mc@3!3(GjB~))R<{A@Dcy0+s#rN`|l>h9|H56$}lng(|r3AwEq{X`6r(GmwxU4 z3K>dkh>NHS{sS3G{RTYmK>rc*A27zq0$_#!=Ew->&;d|HK)qSmetQM~>>C6K1OM#I{AZ*5*Ua$$ z+!lY(Av+87KhPn*CN(ny0{|TY>IERPbiaEy>HiZtr2ftR{yTOE{ZDp?|KG4fKv(uZ z*&#FF@%{@tqzBynKiMHPfY<&{j0IK>wvcqULI5$P* zl!vZ|>)B%S>+7|o>BFMfCOyp;lvM=^;$rF5S>QJqX^HRRnTtty6b(u^{N=E6eK~>) z`d6mPLHyWP!f_NnRijZY`GJ#_ldPvTXMmr$bT{6|r8#vHYpL81BnP5P8{XENokv-o zliUxl8;P*C%gdqjW~ej63+*gSVf$p?u|k?XMMIuIrK|(4%s#epEK%sV(FqR1ITzRG za{Lxx5EU9lp9OY6ql)z^!+;1s?LE;=hF9Wraek_Jha23^aPAau%lOn{Wqo|U{~k8| z#3^X`f_%zIMVA6w^#x0&=TMvO9BX|#RV(%la)%vi)!7!-5hj9=u?>y_F_=v$s!h+B zW)!LHW7Vg<>De+VgOD-jm$h8{$VxYhv9u4JH~XF1D3D#r53(yD-O=+C zBFLhuv{$}zP>vr%i4FaF_Tgo}#(p%h*fxG&_|nAeiPLnj*)pLs_2QQGtA1gQN0VjI zgtK0Eyf~F6d@TcOw@KszTyxWFGW9fVZ;YwmT7uNZ@TA2$e97DrNE|$Lv!tgX)*gs8 zy0IbAC%*X9zhbg|m1Rx;E**z72j0>-&=l9%PdjU*aYgENd)d)AKacd%5Rmqa!nDF7H)>*th zH(9;4^Nrze3*;${Pr^Ku)8rxg29pu#@tkx_N^;ZOOdYj+J|Q6}hS%P34NmnUN&YDm zGK46rrEFzvu7O}kd!VnMf_76O-&Zvm64>o9i*aK?eZTCMu1fX&X z&`MDnb8Y4$Ua#As=(LYhOL2l{kb|_GDLFxWbUigKC2y{cB{KoB8}m!<+>OlVn%a{C zk>%){3XQpS`5g^~kB9j`TA$oo9fPpjCk*E8HKaW(8nAO1Gs=3F>yG=-#E2&FIb$2k*B5k6ouCq`67tAxbDOi|Eu} z%cLAFH&^oYs}Q|1meiac=_DGsq1(9um27Eiwx$89ggDvS4{`3in&tJ~hk1=(_k8mD zfu%@%$Z>MfR0>9xLPb;wcz%lEW@LDjUPNt{0fOAUz|Lxrp>3~(fM5IMzrsaa!`guD zv*jo!UuJTs^$K`u zB9x-TG~ZmV)jGG6&E_dDH_hm|Fyn9gk`mFuU_ek=HKQ<|W!dH70`<>) z_60takG&(=|4IWHrW7Z)nUFcL{ zM0VU>6sh-EA*vc8gpev)F;IbaU8jYB0j)fvI5z{5fgU92fIjdrUCmd6S~_wpFjv9| zApZGl*oG(L6wpN?EK4EOGiitL0o?82=?5Y4LL{^>s=NVTX!c#ap~IWSJ$NQOFpE#r z8J75?*Ie?xExHY0-}Q&veKu_yBddVi*zg};fQip~1a5djer@|3@>e#zd|3+`Op)Pr zTfmK@2;%FfZ_U04Lwa2d!hqzXCt(eKP*mXnf??;o)JcOpw{VLbT}OSi)3d{r1YXjf zc&SC3s03&3ckd{vW@(M-VTAtQ@X4T>={LW>0OYB zm|U@67Vwq2pdFN^hS>CtPo69!B$AF3^GkSmn7a`rSv0{K*G}@F%g5cc^B^!I0cV`? z7)dmR2Tav!9ENIT;tr;!;P|?jO&YGWZBimD*@iq#v^ie@a9yW9&#j5sQd+Ja*zFWn_6~9Jj`>#CKM^Z{e+kvP-;R?^k@r^yFr-Re33$nf>s#~ zbFz%OVJ@>7c$#W%wfMks3s#AtC2R|yD4*>1j9U3vh8jIIrIvrtAP+`@<_pK$&;sQ0 zKC9I}DMC;r32^$Shv-m*M7|Z&FrmOt30A|fRsOzI2Kw|Z;%cxFH5T$Dx2*$Az0#L5 z0j{K%RK1j7&0!N5%c2Aq8N#p^_sKq-g~Yt4mCU2w5?pA0`N#)66b6%db4f@9uTT~P z=!L2$6iH*aB02Py^1St6%rmaNkdDt3^RlgbnB&@|P&u+*%UcB=z>NCyeO56a@z2-` zb1?FxX#A%q)a3bUvFH5w8s`K^PSaE#V0yT15VOkf(~NWcfShWfm$wg)g@&ZDg!Jo| zCh^EceBI>&=6(>}!%A?o0uYsg9)7UHkQ-etf_Zb0^k0wr%$B8n6XY2rqzsj`DystmbTtfW zPS27r*`-;f-UtOY7&`^+uSXLgZ_o`I7avWJC5Z!Kex@oOr|?B!vcpJ7emzoU8c1UdjhsAH3qJkIKPm8dVMMCPO$ z%O*EJoGs7rRgD;fC~OWwnf0M58hZ@hT~E$0knP)Sy^@U5xT47jbwf|3p-WGHP2eN# zE5!niA|R;aD-l&zE+SbT4xn*=I>7J9_j;dD^3l|z#DS3Qe16GlbC!!C=a$9wMyDiD9Nld2jiA3D#7G-Fk#!qQ!-Ge znuZq)nU()^#C$9r69Ijei%31~evo{NR^j@5vlwDWFIdZi=VPuH??2(P`>@DG_BJ<_ zLM_=BAuJs$jjNoM^?E-Y@$tyc&DAK|_BtH_5+#h4lT8%O7{e_Y+1vi6S0qu4xjPVZ ztv#p&U55F6HmGtFXm|d(%`c+`c3hT628RvDiE_+NiNmZH-*3fj!^;~?yD9B!4y|Sc zu%f)@hsHRK)q7!Mn6C=g8}Ov9xV$Nc!Q;g;e(7Gxy8YFy{J4#mHEu z5930umt$Z3Y?POZ{zy%z*9gkU&L7YgqTH>G@`m~)H%kjPUchqe@ehR3R?gI_D*N1;@ z)eW9#Kk)F-a6eYv?th8;x#^pnvc>Czv4jgcKv(&OPBG*y?~+1X>V;F{``PUrdigXo~^{DvZ{RmbI_`8qP?F%=K~+e@S@ z5AWEfvhbvA$2D7)Zm8A%Ymx*U82&(z$s3+d866v4OK@8+WgQlF;{$C`l!s-t6LQD( zk3uK=i}}%>tBt#ds*r*}$@O{bEu9}8CkSr)Oy};d*Vl&#q-z&1C;BJ1NGAn_GPfpd zp5RK|T&XkVSKyT@g-RM-reF!mDF(wg6@zq{QBm6X>Yyu@z|A!hc8G5KuC%WXQ_Zn9 z7>P3C)hjEZuJ4a|+P90m$;k>4@Ow|Jx`WcT?`GQvOVE_?ozv65^qJ6Q4W*?a=EL1W zj0%_PSyp&RC->p(+?pi5mm?UJH;R3tsU`ifD4#0`AEu+gjr^o-j+liy@+&AbNg`As zSKY-@T-d#~oAUIUeS)2zt)+UWX*}lVcAWBK$cxEnmnZ`kN2~H$8aH!BNz7R@v!<%8 zPm^)o&53vU6x6j}a+~6E^^%!_DBxJ) zB%?-33(LwxrEn-Arq0slwgNK)D4{3L>SE7Vm`vQ$IA#tk&ez`$2*mZG6}HyKmTZ0W z`Z?J)sE?r1c5Ndb@>ne64viZVW(}5SpG?%v!v*Qsjw_s5F4U$5^xXAzl=I?@4YSw^ zX0>$>Cdrtw8iuy~?wJ&DO5(<4TWa^rSan3YI{Gp^f|hLnw!o(cjC zzIsVt#ya~7fo9%UvBQXBvMzFUN$z^~hy55@1j*K@8{I|QWgd@@CeP5iukFRD@}lQD zHS=WN&m||6BR6zk*+qN5Xf)~|Y)(6#tbR;`x9jd}weHZEOr@Iu$48~pExnf0ZjZjuzy~=d zCgqu#Uj&@HSV{h^Q)%Q$mcp0-s7^)nNKatE_u&zAHTFXjEj|e%PQ`Dx2iWh(<$}*@ zv^F6>Yp$C!UCuns>MHh@i3+(o9PwPce4fdy{BKuy&)Dx)s|!mu^_9MS;16W7e%wO3 z;0`{8L*`kgs~mGwRyj#yDOk<{azqK(jcegtPsEc)5(DGYd{&%Smklmk-tcycB72`Q z`10d4U1h?0b%xDDC_wJb*>!CKpBLq;ErlC%?E0a_7i*S2@d@m2KjEesQ@UI-VThN+ zSIANob{S;X4-gaOf`+wazIoH$|AoyqnWE;qT+lXity@_C#4WD3o+x%Vrwv%*f$8vd3sou-z@s9CMt z-KR*E@3%VbY}=h$GJ(JjNJ)MCG$QaB9A&9IEBam4O`TJ7?WCvgi5cN? z#w2@I>6?q5r<3ZGCe_hQRs}ZIGtxtOWPRiTh~A%k*d+riWd}6CnA|5B$Qs~W%rM8} z%nF5n4CXw1PcJgU8M`can-j%2YIu{=Gh=nuN7mqwde#`AkE4e%Zks1%Hq}2?`kt}Q zAS1R1JDnajMv1Ogv>s0U1*v{SUc7K_(*iEjvE=qq#88!Ef(Cj!T2dQpaW+(&KRhqS z+e>jtbFKp8Xue(6idT%Ab%Xx>IA3z!(a82VW>2@b1dqg5HN|tzlJ*e|Lvh-O;nI;L zGMNpm!~jjEZyzQS+>$=jSuGZBIZXPJngB!-RWLAblgFjTwy&p+PA6c^4g!7$cRjMN z1>s>261T_lQp1Z(CluleoGU2w3bKo`mMA1`;5sQ7Iwr-1#f{SfItAf=W94(3W2yOe z%&?t&pPktRA1&3hty)?A)_(!*{?a&^7+C+2g5^(2&A%AQKl#xA0PXk{L{yZd{{ij( z9n}5Z{rrCbbqs(cp8q|lV*m(%4D2j_=HHSW13(F72Ka1%B?}9{)Mout_PhM|{I^g1 zwFOv0|F!C z)I)lJbO^ZW?-~HqK?cA%09OLIpTF1G0kKfOOaI7)fTR8#Nyi2_8Xy${_W$0;3;=+v ztZdNC00WO100fy>{(_EwUGx8P`7coO|MEyc&Huyne|08$*8hYr|6T6=@0G`Ye=GmZ zcKnSj0dhMv11miMSppsuJslIkk^X6@d8~D5J z_@ABRKX2Gy-^Ra)ULEmZzby5oX}yH?V{>ZLdL8dv=VV^7%lC1hAG zBnY8R6y$JzIAk{F9kU!A6FTbrtf2)CuH$AM)-o;Q5kaN*TP!b=m^*dvctI_;=B3p|Z^sMK54qr#auT3*R~sez zGB-Fob%&6Xwwc_v9);Sv!FQHN^P5QOIbKo559_P!cRTNx%Q?5^SxfWSGzb`BdrK@d zrLngVyeSLk{V+lEL7wEYJ*G(J1n>;;mq7%i3H-%+vLH{G4=|5?0%s~y;dnNk3v6c) z`GeLw&J1LZ(bw-wY4l4?A)CqwZIh(lH^`%-_^E%il2-w$@zU}`~#Ifwm&fTpdgFL$n zs#CBPplDL>OtHXSwwR0rgzDEloy}2kwz0A7R2al{gfDbB=~#msHjY?UvS1Bi zri1Qb5*ae-urdIH6k>H0df=+dWRq?oP73J-gSZ_BKya3m78WJDmQ|^yKrEmo2HN@3 znFD)256VJAKR}4z6^^{a`#Jk7BXIFS?~VnkqrCFFdgXGdh2j-I!b4C%GBFnwNn2a! zq={4?HWZs25IxI9&?_S01VpoqPFJO*Ma;D6uNoVjEq3 zo4%_)P+sazay68Wl5*eq*nyr)sU)BrAv0oBmtBmf-uJ0Pjv6NDXZ5%)^y_Z35IA^@ zuy2mSQPfebqCRR>;l538cN^^aY;y~m=!t-~m+^j5C|EEcOYH;pA`y) z^rkkpN`sQFl2}}k_|u}~G0=)S##%p8L*pDKV=kafL7&cf#FRd);90LtNexx1pgu)) zQ?2CnFadEtQ7WPR03u*5zN;(h)hge#(j1T=qLT6H06E{{RpJ{zDc~P!8fn&I(8dUeeZf15Eo>>Pd776lRYz2k{zICayZ* zKf=5>Af3!Nq+H`<;h~+BralcPI*GyX#1V(!^;K7ExA4`i>`o@yVR6XDD=DEoY0e`C zQnn$@keKU>lwL!42Zzz?0tD3v4set0uvIMLWhsfJt9QMSd5i{eFnyXI(9kL~<4``v zVl7SNW?#^VndgWK0x*TyKC5?^20LJZ`A?EWKj0B=o_-t;yR>ItC0HSo_y5c_M0HSi zkdN%P5uwW)R1S4u?fd2G9?%7(z=r>H3X=2-QLyZz=iu^(H9@t~(-@i9!5-ODe0jFt ztiYFJCoP4Ui{kj#s!OI}KYn^~rx#50FFi4&m3HWRp-ObHIsD2AVa-rTRr3mi)EI~N zfssORqFuJYdcg?Q8-CJIzF;sp}<^-v9AH&I{h-R1g|D||TuC(eg|uxS;FQRi7V zKrNuML=NW^m}z6A(kGp4_>}2Di@}}eR{xNd7n&*1V-J7@JJK&tQhoAF@xX_f5#m~| z)T0R)*Rx-R!&cY_7o|KPuZlPIS<}L@c4-b%cnbO~0Y$+;z&|V*7*tndTZ7pgogfRQ zA+T}Ek|#z9yfM3TBd>3R5wN~Yn7r61hVt5%v{@>f(wZ{eNL`3MS^@oBQeZ)O9Jl>` zg~QY0`-Av{0OgtRLG|f@z9*`j0@CTWm*s(L>6-&Vr&1E#F-FD&c+WUYIz&ITxN+Wmta2-Rre_C zobHG}7&!v^lE`S3_-Kt%)4-Ep8(4+UIY!BSVVN4{K}&0pAQHeo@F8a*i4&QCKOs5s zM=R+f&P#wb@Z>BWg`R?GR3|_OYy)9;0UuNmLOxbzoIT`aKsW1{usZ{m??&~N06Cb(I4W>c*zssinD3%R{g`1U{mqR zrpGhoYvTF{QQi}*L&8$L@oW1&@lsGT#F(w&6EgdV*pg)ns)ItZs0=jWrr-#}xz+v~ z&i!|y`WE*7fH#B+tguMWsIYZ~Te}RqZ<55r*#y#$HoGbDq{WH-j&owr4`91|_?&Fj z*YM?siTL05HkF^j&3&5?hq6iP)0)MBn||$2BcNS}C64u95$Z1&6e1VLshN1P;_U02p^LvK}Y}4*>P0PDCfVcB#%fOIM`*} zmHml&NBz^~&UpfH0we>W(SEgab*zo;n=Y%Ys{q0?@Eg%{HEbtbbV%-wWx<47g?;Ch z^4|Sh6PG6N4Ibm!S{)b(l`Yl zuD*4rFx#QW+p5%B$5lr);Sf`eUBQkeyegW&?5Eq4*C4|@d7Bnrf6J?Yg+`2%c!J#P zMe>*(D^Wy(6J-mO&lCtfnA2yAiD}57YSro_Gf`)^#q}M&Xw^Uyq*O!qp4I`OpI3aPO&<*FaNVD}GiY4yq ziR&Va|HpZw_+w;adahjCp!c z8bd_ADA~rwu+#QYQ866#%js=2CK;B*-q1|Hz0L)I4`&1zR&0Zi=A_5oGT`Y!PU$O$ z00YG|9=e?=U!r-{xHGEQcKLi#NxVRO#>i2@7b;P$-vhRQ7?F*fC1drBV;$3PhEg!N zKHPB^6#2aGE;@mwti)ttWY04|`BV0gD7b4e5O&8c#h6MyiO`)N_^@F5iA7>YcdQ0a z&_t_y{BDR`CUP~mddh@=!ymGi-on$J@4G?t!6%l_pYZAR@d@We+Qh=6R*bGp)cM>q zlCi2jSb25cuSOqKeSW^1o=!G};@PaNjCv7PCur)iQ~9;)`Fo{y$n((n0#neT`ift> z2VoiV9Xbbz2tGebSpXB7IcI4U0XG8CLw1qS_9dX}v+Og+8cj~3fht40r7yXL-JiL> z+D&OpI=I$*_hf^`g)kZ%21xGeivCJDbR6^>m8b;Y-qj+NcJC<+NTdJ6Veh0lIo!mR zjg8T}Z$u^;&gO}+5CskRDwJ{JsepfhsBX8sR&;(}s>*u5o^iaUKm6&@V!Cw*K}My; zZMFWYZF`|fr0cE7<6lb=_#AIn|5(sM27`HcYQ3`nTcBJUbf8`V=LW+|n#)p7^;w0a zhV>rfKn6Mv{Yf!iTzp5iCjjDs8tUt|iT9-&dF%WZD>rnbVm|f1oy^)4``5(s*$lDRAQ! zas~Xz`n9m6w1ho7w|ek{G_LS+RLTfA&ae|-sQGL6r;_%_txAM0^6IX;tMJxw&%8i! z>9e{iS*^GOd)eEEChO43M=g`7&#m*~^!12&qkOAu(?3w33)$)y_xR1mtsD|$EW_}= zOk=^aEFMxJEE}lXTLCR-CMlpcb%cS2?!cVl?v6OD##_LiM$1V{5OV=n#3|IQVaEj1 z!Al&*VspM#{Kt_)n1EUQ+if)T%~)# zmFs$&JcKmWwMW{nE%`n6-$JB@JfeyPOo4Kd=E=3zjHdxn=8{aP3IzoOQ$d%?p8;Ks z&!5AbmC149bsH~Ko65m3ZJ#S9Z;<8RVV_DmV&9BM4|?l_-X+AaCP82r~=IIxF1Y&pP9;lqS$}afra@BOC~E zL==Woy#AT`V6(dP)%V(%)u?g(YGJpV>)LLufR@XP7FNBia*g6S0{gL$hSJ?U(n5_ z9y5?xFoiJ{T1VuuDlD4N(XnX4Ca4UQ4uYp`)qMjq_jD93t&UrY`z1G`M&kdoBg<-@ z4PMd>WjM+SeMC#4G_SSBU~mDip>2H95tUYvgE=piBT zf(b^?i^w1>?l>I!gvM(TiBau{dFkLyX9^c=Dz&?MM2!f4EOeE$KRXFD$AJ_XV8AVc zQ4_koetH)a2b(JGxOLEEb3ED4rk|{uHOjz|+g@dvq_hgrUU;|)oF5JhgFPb*RHbz; z<6fnQ0OAELD&L@H4(^MNk6N}X{35VB!XQq^{a&OgRY=0mc2;`4%62c;zDHguPBgDQ zk4nMwqveOqY!JOwC$Y^p*{7&=W_x9{%23Q6{?jLrYsPCC%xk~qU!q#u1DTIR!w%pH zN2e1Q4TP8TdwT3>p%e_oOt}Ye;7qhZf;YQxlx71G6dChY_W8~?HMlCkv_QzZJ$cOE z@+RLr(*o|Ky0o^=G zzu~7(#8)TQ;J^_#>%&DQ`?e7>{z9z(sNJsBC8*y^51hLG<{7)*$*Gb^=6gFkWVQ3^ znK}t&4e4FyvG+z#8j0@4IJYNCp7Jo%UKE2xO=Q^M%hmbm;B8B;7VQv<_O+nfjX|>n5aUIr4 z0@{?NvF1Md(h!mt`|ne}93UVBkxv3P$*R}it~;-Fb6JUXEQN?7JqMjva_qIK8)*YX zK(LYg=T5+!&4HBR`Yww;g@8$$1K9vydcFww^WjOguH>{&)nVopjn7ZRo1kqyg=MW` z<@;DVkuZ;359HZ`Rzg;aytD_GRuqsAZfVf1Ya4-?S;Wf3CWdyo5eu;UuqjLmyXvDD zVh(O2x9VK=D@Uj#ES-!OeZm>ylmvN|CVcln-=;5UD8LXsDGg&vwy6)r0oh{F^_JSC zt>%P$m(=Z2xg6zxf_TEYy$B)1j!$^1pWL5^);k426YaH)P9+CdZGYiXP_ii*6bo>ZB4!S z8&t^G>7lLRabZ}k>iASakg8m=E1pgjR5%f4$v77b@UK>Z0flPJES1p^2is08{H)H? z$F*~|mb|32uGTdh^my75A2apbPXVHw=6dp3Gp77g5M)s`pT5bZ$CpdQz8P_n+*jvV z!(FKKl!c*D;1FGR_-*>>Os}2g($@of$bl11Pt0!Qe~%WykDmzGuTgY`T8Kg4I;Q!g zNsuYj=Mq&g6?WOQZi8ryW4rn+^Ptpqqk$RfL)Y#)G^5)csh1%lO3KhA_sybD%tKg`AZOAp?MSBbWkrJlJf0q#uk!BgugJ<6av;IS>ay*NsL%IX zydSq4-GaydycAQy?-qU@YSgTwvcnf6CHOGUdFa^`Inb7fF%EuM6iL4#=kPa?rur@B z?2JD}i^!Ex8Gk~Pq~B8fkslSZIzC8HLU6c|yWDIfzKgYAe?7qct0w6LW!C2Dwy}UL z)}gK27e#<8Nb5_^dW}qPK!;*)0MY^NS}1%Q$W!n_?rW__GEWmz?vauTD!0?ljc)ic zox|K!o(yo?F>>iUqY4icULGMch5+1cVr{-;ha$cV@u!; zF*I+b)$P*$Bpi&NB3fl%WdIjq;H_|&=y`JBfGcpT-xgB*{o{L`kTdopkapX z7e!8}A36t)yBi2fwxRMB-)BjVc}?(qy4_C(5f z#-|`rRBdkzW75w@^ohhdE1+0tAugZmhaEh!$O&n7jyWO>z9gdx>r=?oq{k+2CHM|* zJ>9G7vfX~&TJavMzAo85H+gVD$MZTlplO2H5$={{244yN0R|V~)25-d`#v<2!FnDVc|A>J$2rc8k6?TbMQzxY-j{cjCZ9*| zAp=!RCYh={91)kr>{yA9vRl$S`@XE4r9G(9#gwoNre zh5_@;yHvPXr+YkmmsGwoex|EXNPex|)v8k1Xr_&Rb+Z5@N=5R_#n2weou`Vehf^*q z?sn(whcEm&m;A>{Qc^{bBSxB{?5d57zz4M`i5#ghCAYzWqGUElzZ$}nX5F*x=GBm; zu7?bZ)v1~1!3lfprb?UTmneFuV9Hb#YT2n(PbwqL>S*0M(Fop)ismAYV zN0hfD7FjX{^5|1P)tW_Rom?W-4F?M$fvMQSzO(t=?~slUgVJ+5s2~AyUy?(`@1u$f zTUSdT;Or~)Q&1g@Z$5NC-LL<`>2sRhWs$e?Dd=>zd`VeUu}OIKf5my<#8G|n(@VV2 z*6DVfh)kvV#^!s!u9>7G9k#=~j=GC~Y>XwpRJwvuk}Ena)gKTyV`HO_rXNPefG!QJe$BA<3li0Itp#(wsI|fOflv3Oh)PSZ;M@_Lk_mJv zFs89tn@Onsv4ztLP>U4I&E=Uqz89GlN0YRR6)jCK`$MbER+d{W)~ChYd<>+z(Q#dd z>uPMzV+RAFGLpJkEp~_B9g)bX!@f`+a)vx38!*XGkLCB@JFqtnd@4zV1V%w7D^1~-1$$RY)0 z*aZzfw)O6Pc%?dqD{)_wbFtF#Mw?`Dbxigp2y}e%;Az*I<6E-6T#s72U|@bOzjNts zB#26Ke9>&~zMoC;8X|F$fYSVYWTJxu{f9swXnB@AFAu5j%>AsS+)HS%IdiZgnSUbp z%(tOzay%An+yoU8DocLZKoW|&=rN)3+rITzF@_~pLTVSg1R8y|9CI+rsawgjT?;BBw=L~ER5eV!m$XMZ`&yEb3Ci5ZY z5vMpa=t}U%2%nloQIIK=lsYAVQTo_2(ub8Rr60ptAo9bZp_)yLg0rk%cNugqlHadt z#~aj*6Lpp!I$mpEs~@`5X4Yw^RF%A6UaF<25+=S|PGx7cKlQ)1lWuIhUf`i`4kV99 z#UIA{T&Js&(C0+hc}Jlx30At_!J4{h-pz6&$)G*Ldfo`vjK@8}{b`dIhaKGmsfe@DVUXuK`(~h?g9bR4e#bJbXyFwe<_c!zrhc*p^RVE3(+c7$%dOoej+a zZ(Ft7dTKbV0K!=Aj9FuT&lRC*Q*O5&LpWi@?5et<+Ma3d`0PB-S44}Qj--$XVZpWh z2rKyV*;l$>#;u4v92B&gO^zkQM({cCkq7U2%u#fj*#ygNvimH-OCjMcERxtfQon$) zF!Rqs2x;4ppt@bP%segl4b-$IqD+huNTJ5MUwV^=PDyWO29(5_ALEwe^u~h_1rNW)At(~oy<5_ z$Kxfz;Xe1n87HboQdf>Qt5X)G`S&y@H-n8ETlsQfHt?Oscqv`jTKSaPG8~t0t40DL z^yy54AJO_gW3;S#dFypYP|zXGmhY6+3O4LsGU~2geCkY<(Iq<>9OLW;4Ynj6Xz~LC z7TBedQk5sH&@HCxeou^~p(fbF((Hme8Kl0h#&f2=pc~1NdS^a1ONz3;Hs6j)R?~=| zJfD7j)_V^jC6MN!*7ZEyi{0dT`Lxi$KTigetnDe*HHA}gp!Ai#mrw(lL`E`7#M8dV zOyP?#`iZmRf{0PE>9LS{q^uB88L0Ip9dhYG;m?$x&<&TRP7ex#WtQzz6wj+iK96_J zsxFNTnrlnkPleW6#uGyBEpZzhWdb~8ADLJ(_dj-)5^27*Jg%0-mP+%9IihI=Q@2xW z_6`mVWEgB@v!%{qY_&HF+BTNUy=2@LvgLm8rqc+YP0IyuAd*CT^hF$q{5;E+-a>@RIqs= zunIRXJiaI9y=je{HnZ-1#h|Q_Zjr#72kHD#3vAnoM2QN4P3o__wVe}XcZ+-ngr+Sc zn{6WkLjiJG1KOz7j~g5a)^t)ohew0yn)~y-@g{q{j^U%P0H;0l{b^I!^|o5`Vb?-z zZC0hB@xl*kp=*Tby4*B%tNr_a*N?jR6C&`VC?7<9sTQB~l>zhu_~Mz|iQ>g_YAW=- zc{S<9nNNXJMoI*EN=O0&-+m&o%0W_iPwNzv2u2%MEy*zQvOpM$S4Y`ToRM|cczfEz zMaAi+waHa$RI&E4nOFSUbD4zysKibGT-ONfVYFi zRsBOO#TfOg<%ylp<+Ee6hp)lA+l04SrhD@Fa)Fa*^0D4TFWSOwAyQ&OX(anLlScLz zob71*7Rob73p9 zBY~xZ!>}m$NMHROj;%(5u{{nu3YRBbIgZmA`@3cJe^^m4?Wl1%p7#stjd#xI#l%ct zhiQy^)qTVLnB9)eLwM!gzyw9$fA3QcVx;%WBMmtN=4c^oYr#^|z0HY%Jr2w4f&CnX zVWl_paceIC+b@9Kl8fGNn9ufUU93*1PzNuHDuI4&9vwmdnIEfA&=&&;Gfiu&6UW09cOSERBKg))5)T0>>6iJJP*p{A#h0#Z% z3gO(AQOlQSDe!|U3iHk&lfMNj-lVI-Qdj4ywXj-k8GLR2^%XT-Cvo0{|vAEmx=Pf_QKRuC4|L={|{c+-}2GXD%mRAm;_y)*__D>lMkQf#qLoxh^_{KlS|5eYw8#4g6=kMqIJzz6Hm9YYh*(_xI z=X!w1$iELv=JrWDuGgjyA2#HID>(L79-+Q!5R-FxQeT_-3a+1Dc-&{cAnfaV#)i{E zocBQA7e?O0qa9<&E+F5jnJBfMCq2e0`!R6+A1e@xFg2S=o(o*{$Ng-*dtINkLbeIT zMt~k62rNf9v9qnSF4a1lt>|Cq`gTsaSWMRyo(I7M{bMM=KI44%TsSF52i=^W(<{3e z^CA3cyXzYRtdgQQ}8{w_kCpp;nt zY5sDnx2^2`F@D;LU9rU_C8hoF>Jwh7B>loerVmi9faAfxxA>n2^!uR!;#L1@a6n$S z|9zn7zqj)r(+bd7zvZUiY32U^C0hM)0e=q`{@309DfrK?&EKPo|MnIEj64Q_j`u%$ zR^L>mt-cJQ`P7g3DiW6QjujbCdPs@D7fD<{iz=X5N?MqYHW-SdCTg?Sh=(hc5;g^k zF(fqbCkGQ_t~k( zkxc?Igvad@b>@zw7Huyt>b;igIWLDV57RZ|YYUZC4lbrz^H6sV$KApmS@*-%UTzTg&*+?tX`+?%$a^s!p8->_8;_ew35HKA#x}K{`cET}>>kDMLfOhM@V4+9g|%gUh<+OSbb?ug`$@(3>8aJWv%? zL+=#O&wOx~+e~ZVUiI&>TUEU49SR>uhwWibHW8~&yczY)HSo4QcsoazC~h#D{>*NH zK{Wz=oc1n*Owe;rWh3E?Q`tPpob1`$@iRlSWfztOLphjFo0rquwFRQ!&o5nTYjbZ( zgg$=1R1Lma$J>>*nydC)+<2_hV6tE2WuZFL44D%v8gNh=dwP~`s^gsgno%zvHV=2e z)`ChAh7+jlH;=ytg)hRfi?=jm|DcwfsGV=37Eg=m34`n<_oW*=22W3Cx_ny2V5IOh z)vDM;4cszdI1#Ff|8|wC+kGcj1&vggo!X%P;);nt% zL7|yPE3s#Z_{XlqokF^-6xOqvlKl8)w*BV#G)g(Xb^Crc)59vw32;?JAIJAQFDva0 z$UZB2OsaZ^6R^NBk}S)SHsj6_B5|L%=&Qi$w;~kw@=IKn;+w+DjLg-T#1{_YopZM| z`BS8AhvmL0dmPR<1(2)$zF0o;)}%wDQ8}SV6FXHZ%09EfuNpvE&?C%&P!y1;~&oa9CX^>4}X+@ZtH3k`Nn&ToCVzrx+L60{KpB?odX~glB8M3L{Y8RW7N{z+M#c+>eVss zWaQP^uWDM`=7Y}?66}71E+4E;jl?k@%AQX>P&hOOlhlr~PGs^c%a56&SZ#SHg~@jZ z7NGzGAIUsV5OxESmt!t6dg{P}Or%iEiRA?KM?-HTy^$0pbA(X!-NR0l0urkg|Ji9_ z@5?fwtszB81R|pO35g45^1+s*=QSfy5fr2Fm>iFoA$=iZKQz)=9Nbef zv*_(q(dHH*gYAwYPPZKTqDuF`Vd7qPc`U@_SA_cLfSCdjsF(w|9|pZ2;fQuvz5+yQ z0XXDfYD=j=yh0D-N`10@TQ*_-n38(UO)dc;-V-aOULu?3O919#)PR_~U8Jqqv13_}1;Wth1b$ylqtJi@Ezs!s{>0S%IVq#i46c4~9PtV9 zg4zeTIj}HX$dV1lQOGT@a`9DTzE({bX2OYqW_ub^JB{83;#0{AH@HN2$ib}oK%##) zD+hI?z*D?>V?;5V)wI86Al?rs&X~3S7(>Ere1sZ_hzkP>|5#|R`Ce||hdNX;9MF>L z-PX))(3g|?kO0vHpQE`_G#_%8(f-s3w0Fzu(@*P(=X|OA{$HwMbI00&wSk5UT9$Ua zk-4U$3IZbIdW{X~*$|d4T|cz@&v!P6{2pL1JEq_LC0!(GR$!)GOJzyCEpj-fx5|Z* z3?DnmVtLKe&(KBR2&1Yw0|X zTKNe#@{5k6oRlcnC5DuU+Qs(zhj86Xp15Oj`c-fq8On!hxzu0@@Vtt@5XZdcl(wl}4_Xjsm zyVq@Nx3Ce=BXbwufbZ_7P^p?jf&dS=hZD=Pqx?l zecn^oEZZ&4-!NF@p}v(V_$(A!Q(_?ZlL2x z3>*s6=D1W&-Xh5ngMSiD}c`1OnqcHH9?0q!s@*&HHx>ziO_N3#A z8IzvC*41(3*_TM>AY$s0#`wNwKP=VK&8K)kOHfFpernIU060936#_jZ~O zz$qg*Kg7KpSA7Q~gti;(&#v#Ev8Ldq|7x}B!L8dYE@uzR zRfUnr3(eUS?p^OOl5j)q+@;o)Ma+w3oTWSu(bHlMA*++g|3fzaVm

- {{ content }} + {% if page.toc %} + {{ content | toc_generate }} + {% else %} + {{ content }} + {% endif %}
diff --git a/_plugins/tocGenerator.rb b/_plugins/tocGenerator.rb new file mode 100644 index 0000000..9f4e868 --- /dev/null +++ b/_plugins/tocGenerator.rb @@ -0,0 +1,132 @@ +require 'nokogiri' + +module Jekyll + + module TOCGenerator + + TOGGLE_HTML = '

%1

' + TOC_CONTAINER_HTML = '
%1%2
    %3
' + HIDE_HTML = '' + + def toc_generate(html) + # No Toc can be specified on every single page + # For example the index page has no table of contents + return html if (@context.environments.first["page"]["noToc"] || false) + + config = @context.registers[:site].config + + # Minimum number of items needed to show TOC, default 0 (0 means no minimum) + min_items_to_show_toc = config["minItemsToShowToc"] || 0 + + anchor_prefix = config["anchorPrefix"] || 'tocAnchor-' + + # better for traditional page seo, commonlly use h1 as title + toc_top_tag = config["tocTopTag"] || 'h1' + toc_top_tag = toc_top_tag.gsub(/h/, '').to_i + + toc_top_tag = 5 if toc_top_tag > 5 + + toc_sec_tag = toc_top_tag + 1 + toc_top_tag = "h#{toc_top_tag}" + toc_sec_tag = "h#{toc_sec_tag}" + + + # Text labels + contents_label = config["contentsLabel"] || 'Contents' + hide_label = config["hideLabel"] || 'hide' + # show_label = config["showLabel"] || 'show' # unused + show_toggle_button = config["showToggleButton"] + + toc_html = '' + toc_level = 1 + toc_section = 1 + item_number = 1 + level_html = '' + + doc = Nokogiri::HTML(html) + + # Find H1 tag and all its H2 siblings until next H1 + doc.css(toc_top_tag).each do |tag| + # TODO This XPATH expression can greatly improved + ct = tag.xpath("count(following-sibling::#{toc_top_tag})") + sects = tag.xpath("following-sibling::#{toc_sec_tag}[count(following-sibling::#{toc_top_tag})=#{ct}]") + + level_html = '' + inner_section = 0 + + sects.each do |sect| + inner_section += 1 + anchor_id = [ + anchor_prefix, toc_level, '-', toc_section, '-', + inner_section + ].map(&:to_s).join '' + + sect['id'] = "#{anchor_id}" + + level_html += create_level_html(anchor_id, + toc_level + 1, + toc_section + inner_section, + item_number.to_s + '.' + inner_section.to_s, + sect.text, + '') + end + + level_html = '
    ' + level_html + '
' if level_html.length > 0 + + anchor_id = anchor_prefix + toc_level.to_s + '-' + toc_section.to_s + tag['id'] = "#{anchor_id}" + + toc_html += create_level_html(anchor_id, + toc_level, + toc_section, + item_number, + tag.text, + level_html) + + toc_section += 1 + inner_section + item_number += 1 + end + + # for convenience item_number starts from 1 + # so we decrement it to obtain the index count + toc_index_count = item_number - 1 + + return html unless toc_html.length > 0 + + hide_html = '' + hide_html = HIDE_HTML.gsub('%1', hide_label) if (show_toggle_button) + + if min_items_to_show_toc <= toc_index_count + replaced_toggle_html = TOGGLE_HTML + .gsub('%1', contents_label) + + toc_table = TOC_CONTAINER_HTML + .gsub('%1', replaced_toggle_html) + .gsub('%2', hide_html) + .gsub('%3', toc_html) + + doc.css('.post-header').after(toc_table) + end + + doc.css('body').children.to_xhtml + end + + private + + def create_level_html(anchor_id, toc_level, toc_section, tocNumber, tocText, tocInner) + link = '%2 %3%4' + .gsub('%1', anchor_id.to_s) + .gsub('%2', tocNumber.to_s) + .gsub('%3', tocText) + .gsub('%4', tocInner ? tocInner : '') + '
  • %3
  • ' + .gsub('%1', toc_level.to_s) + .gsub('%2', toc_section.to_s) + .gsub('%3', link) + end + + end + +end + +Liquid::Template.register_filter(Jekyll::TOCGenerator) diff --git a/_posts/2017-09-27-typoclassopedia-exercise-answers.md b/_posts/2017-09-27-typoclassopedia-exercise-answers.md index 934425b..157357b 100644 --- a/_posts/2017-09-27-typoclassopedia-exercise-answers.md +++ b/_posts/2017-09-27-typoclassopedia-exercise-answers.md @@ -5,9 +5,10 @@ date: 2017-09-27 permalink: typoclassopedia-exercise-solutions/ categories: programming math: true +toc: true --- -I wanted to get proficient in Haskell so I decided to follow [An [Essential] Haskell Reading List](http://www.stephendiehl.com/posts/essential_haskell.html), there I stumbled upon [Typoclassopedia](https://wiki.haskell.org/Typeclassopedia), while the material is great, I couldn't find solutions for the exercises to check against, so I decided I would write my own and hopefully the solutions would get fixed in case I have gone wrong by others. So if you think a solution is wrong, let me know in the comments! +I wanted to get proficient in Haskell so I decided to follow [An [Essential] Haskell Reading List](http://www.stephendiehl.com/posts/essential_haskell.html). There I stumbled upon [Typoclassopedia](https://wiki.haskell.org/Typeclassopedia), while the material is great, I couldn't find solutions for the exercises to check against, so I decided I would write my own and hopefully the solutions would get fixed in case I have gone wrong by others. So if you think a solution is wrong, let me know in the comments! In each section below, I left some reference material for the exercises and then the solutions. @@ -347,3 +348,229 @@ You can check the type of `(flip ($) f) . (flip ($))` is something like this (de ``` Also see [this question on Stack Overflow](https://stackoverflow.com/questions/46503793/applicative-prove-pure-f-x-pure-flip-x-pure-f/46505868#46505868) which includes alternative proofs. + +## Instances + +Applicative instance of lists as a collection of values: + +```haskell +newtype ZipList a = ZipList { getZipList :: [a] } + +instance Applicative ZipList where + pure :: a -> ZipList a + pure = undefined -- exercise + + (<*>) :: ZipList (a -> b) -> ZipList a -> ZipList b + (ZipList gs) <*> (ZipList xs) = ZipList (zipWith ($) gs xs) +``` + +Applicative instance of lists as a non-deterministic computation context: + +```haskell +instance Applicative [] where + pure :: a -> [a] + pure x = [x] + + (<*>) :: [a -> b] -> [a] -> [b] + gs <*> xs = [ g x | g <- gs, x <- xs ] +``` + +### Exercises + +1. Implement an instance of `Applicative` for `Maybe`. + + **Solution**: + + ```haskell + instance Applicative (Maybe a) where + pure :: a -> Maybe a + pure x = Just x + + (<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b + _ <*> Nothing = Nothing + Nothing <*> _ = Nothing + (Just f) <*> (Just x) = Just (f x) + ``` + +2. Determine the correct definition of `pure` for the `ZipList` instance of `Applicative`—there is only one implementation that satisfies the law relating `pure` and `(<*>)`. + + **Solution**: + + ```haskell + newtype ZipList a = ZipList { getZipList :: [a] } + + instance Functor ZipList where + fmap f (ZipList list) = ZipList { getZipList = fmap f list } + + instance Applicative ZipList where + pure = ZipList . pure + + (ZipList gs) <*> (ZipList xs) = ZipList (zipWith ($) gs xs) + ``` + + You can check the Applicative laws for this implementation. + +## Utility functions + +### Exercises + +1. Implement a function + `sequenceAL :: Applicative f => [f a] -> f [a]` + There is a generalized version of this, `sequenceA`, which works for any `Traversable` (see the later section on `Traversable`), but implementing this version specialized to lists is a good exercise. + + **Solution**: + + ```haskell + createList = replicate 1 + + sequenceAL :: Applicative f => [f a] -> f [a] + sequenceAL = foldr (\x b -> ((++) . createList <$> x) <*> b) (pure []) + ``` + + Explanation: + + First, `createList` is a simple function for creating a list of a single element, e.g. `createList 2 == [2]`. + + Now let's take `sequenceAL` apart, first, it does a fold over the list `[f a]`, and `b` is initialized to `pure []`, which results in `f [a]` as required by the function's output. + + Inside the function, `createList <$> x` applies `createList` to the value inside `f a`, resulting in `f [a]`, and then `(++)` is applied to the value again, so it becomes `f ((++) [a])`, now we can apply the function `(++) [a]` to `b` by `((++) . createList <$> x) <*> b`, which results in `f ([a] ++ b)`. + +## Alternative formulation + +### Definition + +```haskell +class Functor f => Monoidal f where + unit :: f () + (**) :: f a -> f b -> f (a,b) +``` + +### Laws: + +1. Left identity + + ```haskell + unit ** v ≅ v + ``` + +2. Right identity + + ```haskell + u ** unit ≅ u + ``` + +3. Associativity + + ```haskell + u ** (v ** w) ≅ (u ** v) ** w + ``` + +4. Neutrality + + ```haskell + fmap (g *** h) (u ** v) = fmap g u ** fmap h v + ``` + +### Isomorphism + +In the laws above, `≅` refers to isomorphism rather than equality. In particular we consider: + +```haskell +(x,()) ≅ x ≅ ((),x) +((x,y),z) ≅ (x,(y,z)) +``` + + +### Exercises + +instance Applicative [] where + pure :: a -> [a] + pure x = [x] + + (<*>) :: [a -> b] -> [a] -> [b] + gs <*> xs = [ g x | g <- gs, x <- xs ] + + ```haskell + pure id <*> v = v + ``` + ```haskell + pure f <*> pure x = pure (f x) + ``` + + ```haskell + u <*> pure y = pure ($ y) <*> u + ``` + + ```haskell + u <*> (v <*> w) = pure (.) <*> u <*> v <*> w + ``` + +1. Implement `pure` and `<*>` in terms of `unit` and `**`, and vice versa. + + ```haskell + unit :: f () + unit = pure () + + (**) :: f a -> f b -> f (a, b) + a ** b = fmap (,) a <*> b + + pure :: a -> f a + pure x = unit ** x + + (<*>) :: f (a -> b) -> f a -> f b + f <*> a = fmap (uncurry ($)) (f ** a) = fmap (\(f, a) -> f a) (f ** a) + ``` + +2. Are there any `Applicative` instances for which there are also functions `f () -> ()` and `f (a,b) -> (f a, f b)`, satisfying some "reasonable" laws? + + The [`Arrow`](https://wiki.haskell.org/Typeclassopedia#Arrow) type class seems to satisfy these criteria. + + ```haskell + first unit = () + + (id *** f) (a, b) = (f a, f b) + ``` + +3. (Tricky) Prove that given your implementations from the first exercise, the usual Applicative laws and the Monoidal laws stated above are equivalent. + + 1. Identity Law + + ```haskell + pure id <*> v + = fmap (uncurry ($)) ((unit ** id) ** v) + = fmap (uncurry ($)) (id ** v) + = fmap id v + = v + ``` + + 2. Homomorphism + + ```haskell + pure f <*> pure x + = (unit ** f) <*> (unit ** x) + = fmap (\(f, a) -> f a) (unit ** f) (unit ** x) + = fmap (\(f, a) -> f a) (f ** x) + = fmap f x + = pure (f x) + ``` + + 3. Interchange + + ```haskell + u <*> pure y + = fmap (uncurry ($)) (u ** (unit ** y)) + = fmap (uncurry ($)) (u ** y) + = fmap (u $) y + = fmap ($ y) u + = pure ($ y) <*> u + + 4. Composition + + ```haskell + u <*> (v <*> w) + = fmap (uncurry ($)) (u ** (fmap (uncurry ($)) (v ** w))) + = fmap (uncurry ($)) (u ** (fmap v w)) + = fmap u (fmap v w) + = fmap (u . v) w + = pure (.) <*> u <*> v <*> w = + ``` diff --git a/_sass/toc.scss b/_sass/toc.scss new file mode 100644 index 0000000..1431123 --- /dev/null +++ b/_sass/toc.scss @@ -0,0 +1,29 @@ +#toc-container { + h2 { + display: inline-block; + } + + input, input + span { + margin-left: 1rem; + } + + input { + position: absolute; + width: 50px; + height: 20px; + opacity: 0; + margin-top: 10px; + } + + input + span::before { + content: '[hide]'; + } + + input:checked ~ ul { + display: none; + } + + input:checked + span::before { + content: '[show]'; + } +} diff --git a/css/main.scss b/css/main.scss index ccbae5a..b802182 100644 --- a/css/main.scss +++ b/css/main.scss @@ -47,5 +47,6 @@ $on-laptop: 800px; @import "base", "layout", - "syntax-highlighting" + "syntax-highlighting", + "toc" ;