From 76b472d017f3bf456db8204158de6ac4746447b3 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Wed, 22 Jul 2020 02:38:23 +0100 Subject: [PATCH 001/106] feat(egf): import as new package --- assets/egf/egf-readme.png | Bin 0 -> 259598 bytes packages/egf/LICENSE | 201 +++++++++++++++++++++++++++++ packages/egf/README.md | 219 ++++++++++++++++++++++++++++++++ packages/egf/api-extractor.json | 3 + packages/egf/package.json | 72 +++++++++++ packages/egf/src/api.ts | 71 +++++++++++ packages/egf/src/dot.ts | 49 +++++++ packages/egf/src/index.ts | 5 + packages/egf/src/parser.ts | 169 ++++++++++++++++++++++++ packages/egf/src/tags.ts | 67 ++++++++++ packages/egf/src/utils.ts | 20 +++ packages/egf/test/prefix.ts | 44 +++++++ packages/egf/test/ref.ts | 109 ++++++++++++++++ packages/egf/test/tsconfig.json | 11 ++ packages/egf/tpl.readme.md | 198 +++++++++++++++++++++++++++++ packages/egf/tsconfig.json | 11 ++ 16 files changed, 1249 insertions(+) create mode 100644 assets/egf/egf-readme.png create mode 100644 packages/egf/LICENSE create mode 100644 packages/egf/README.md create mode 100644 packages/egf/api-extractor.json create mode 100644 packages/egf/package.json create mode 100644 packages/egf/src/api.ts create mode 100644 packages/egf/src/dot.ts create mode 100644 packages/egf/src/index.ts create mode 100644 packages/egf/src/parser.ts create mode 100644 packages/egf/src/tags.ts create mode 100644 packages/egf/src/utils.ts create mode 100644 packages/egf/test/prefix.ts create mode 100644 packages/egf/test/ref.ts create mode 100644 packages/egf/test/tsconfig.json create mode 100644 packages/egf/tpl.readme.md create mode 100644 packages/egf/tsconfig.json diff --git a/assets/egf/egf-readme.png b/assets/egf/egf-readme.png new file mode 100644 index 0000000000000000000000000000000000000000..5ed70d3d0839a223236610db96276e4afa07f98a GIT binary patch literal 259598 zcma&O1yq#V_dZUi3Q7q|2ucbF2+|Cwq@;9>L8o*#NQr=mC@tL}T>~hB2+}chcMA+1 z|HHi!uFL29``@*$>vd+%dC%Tw@8|6O?0xi?lM%a&LxzKdgmhU#{E-3@5>5;f5_%vO z3i#xarqgXCq)QTp4%sf~olQCt0k9f`owwmN+)dpISWP znn)lOl~Uf-cMuVOwp)I^p}Itx6@KpJ37OOZIp`rpFIWR#*fFybD=PQYd0q~Gz!0A~ z1G5`;Yx#As)+#gtWw%?tgydMnpMD>&8y>r=n za!N|n_)Gjp4CXlxjp>DOJU(7iYh1>+wkzDau61DtcrCw#Whhvk@Qp3yae1EHjhOzew;wmP zJ@PIt_4?`<(hcd`fs%4lmlkX}?2HO=I;oaF=+xH>n_&Is`vNh=W0NFeNO;G&nZ^Tc z@!&*#;x~j|nP=eFeCut=h;*;7q7R&cnKJkyoQOw@iE{lBT=a+9%V~UEzf8buA zbFrz(j2E z0@Fk%08MG%7Jm=-PUvScR};$*cd3PqS(_s8CIguX{mZ_nYidzR26U_~j;?q8j)DwQ zzt0Q9wD(^7&4yZr<^6mta`20kh(taY^a%qqmULT-3qx}tynjORxptDIIqH|P%6syB zBzTPOxC*twKO}L-!|q#*f8wcR`yFY&N{x@oO?4^H9i{lmJ)%h@3nx3P2m8sS{z&{( zsC^Ku!NN!n()9VO*oy?hY}>fhw?gn*aFv2_gl~1Zk#!k4J_t#sU{-8xKo7pvg4s@m zcc`4EFM$C|b{CVQIc(vhtdGQuGFo&ZzhU&EkgN`gRm!~P-F2BuG@@5&{8~y$DZDX9 z+4Ar_no+mv4loi9UdY-%nWf^V(xjosE=lo|(ixeoMS1CQ&C#!II(o;Zr4&^M@$KPn zNCRG(1+5vz;HrEZ!416ERj~LEi9wp-2PK0?4P%)Z#!K|egzwqCuZdXf+NR_L=D?`} zGg6=`;snOi&$M{FXhwEtoRtibokiV@{h7aSzDWJ@vR7@9s^^kw@6{~y3U_jav9C%S z;;;aW$~$QjKYjSeSN4Aw3Mz%auXs>uSLW9Bh6pQAagS#7Nq9?$f5Bt)yIg}iK6i7x zg`BT9)ehB?BX!$7Dv*Y~$f(A{S|21CLSaPmcz1Ys=moWIr$p-2zl@}`^LWOd)C}`g zu24aAZU~W)b!i3-5@VZ}`Fn;uwBj1<=?UaYVI(Z%v1gb3P$j4?KY6W0{1tH*we#!U zdz9}zaPlr?VRS!3?L{m0hu#kr`32^;R}AS-xeK{7&v#0A!vERlF#M?dBb(P(f< z!gcU>hOoVVP4<~M4V4!K@wm_6ex$dINI|=y0h@XNi*RNeuQg`BH^sx&M7Z3Y-AhY# zNGV=yY{tJXuh(&_-u&=Z_c^=C73H@|FKkq4dT@?rm_A-xs2`qq6zx&)>OrYz;;K$` zux#zjXy9)n=NrS`aW%Q4TfZsxIXqsHHc7TO$|Won8$w)m9SoFs0)WB3_PC>}ubTO2)!y+gg@O2^d> zT?M*1ay4I*$D34QA)P<3Sz?#HtBi5}==^Eldr+)BwfE^hg9Rb7E`~0HE=O{>WoU=Q zTq2nqdAdi}ZKEqTf<*!S;sO$|hc3y9i7yi;QaNPAvN&W@CG|^MNMrVRR}5d@Cn59Y z3QdV;{%o2|o;;KQOX!@tvVrf&3v;jX)|M5LsTOlfZE7RWY3e4LZRyT#H|>CB?P&%l z=;!|EiON#RQb{jSSxL|?5qvx%9GBSI8J7r6bb}ndcFjeueU>B~EnM~Wh1U{>{^eM* zcbCX7)m}z_o%}lLQt%ByooAOcFnqu2-+gAH7p-GWb~Wf`P^l=7D3K^%P=Ao)o6A9B zq^Z|QNa5Eh*_GMZQc%O1e!XPTU4E{u?|S_Oo43FtZk_g!`dbmcm7JtT*IrQHXL!)3 zYuP;M#n5zr@IKtS%&=fii(~Ltok?_`bpb+;uDRTo?DFO7jg;zw)~#(qzvQh**3s5K zO-KD={kWyBs{Tk_oViE+X31=^j{0lWY1N#3ev>}kx;&ixYZ}@4ye|-RO&{y@roLpT z(y0pcO!vt5;4B37EcLi>z2*AJb%(3MWVv6#)Wx*GM5V8|Z?jjeFQ_O=7yfL^SDy-|%Z))?Rj4jv6u#zJHTPPv>VtPbjN^CjT}CCxwc@TO^`<;m9m^@TdQ#6vxR5cue4UZ@CWdP8$N{4 zndsYIal+hlNOMZNYwb3x@m5HmYsTO@F)^t!MGuA9_1K%*yEhIaS@r~#k zotlRlQ+})-re5x^0}nf7miGSUQ+pcHofiP_g!Nhja(?_Um_= zKmF4`JPk~-71v7ERhYVeWSE(XXh_i2nDldgSD9RcMbXPjA5ADkzf6Kb)I(Sm70d2o z9x5D~H2dvR1ZkiiKf_!4LtR?IFrfm|4~VRtg5_4d)?seUPhmW%ra4Q49c3}=)H9}0 zvN3UdM_bpn-Vxo&B}rm2U@oGMQQ2MfZJ;D;v~JSTec*a&+oD#)`Lq4=J?hrS#w0E* zB=6%gU*)D{ZI^zm-X4^tam(0Eca!LOx0yUF1!tvU3A&#hay|!i0lJZ=8P(30`-E-o=RK!r2!jHn+UjX zmigebFP~r3`o`4>jSOBd`;y-BImeQ~;^|n*kEo|yaffwV5xdNK8jQux{fvDXgCFvi z9>HW?4s6$#q;9lfJbnm&>(9rsbZMZkW45Q%g2YOt&MZ&k%U&y#!xdIV=O{a%Jpv2b zTiohi)?Z{b7m3unkGLNg8P06TOpaN9)4=$$!O+pb>PRs~p`fZ&!**LoZC7ow?_Mw= z<(vScK)=h~z24el2Gf$@U?Eq;_fmo-x9QmR?Rc8 z)(2Xv<#|VTxg%R8P9+btHp+S}f37GP|CoJS8{x%DS#iyFs!M6Pdma8F*G5ye%5}Z| z`;EpZ&nQ{*sUgSTVq=spB{M^}1{ta|-AdMCcVOjiJV(Y69U2a^uDu7ic-JTgT^roC z7en{kf3$S`*!U4Hn-$w7gs^waV@g=)h$A>$bf$Ibfop9>e1#UZ#>B4d@lCGa3QRch zLL0OZH7NAy@mZN%TZmCPf$#S3N9UiGgFU)PM1*oZyUv&E4zw6YsH#~cjnbjY$fPk#W->|Z=++)3Hn6;ta z{}^`s&A-F`k?Y^r@gGmdD`#l0YohkZ&{WsV3M@^Ko$cN|{(s){pRdkVdTyxd*-#D+ zuD^z!`|8}#ESjIt9_J|A)K*%+J2S5*#B&Dnz~n6Io#f?r8PqMj>hP zOuL#qIvYdv9EArR9UYtRI;P0kr++Po?1eGc#x`yn*o}xz^4SWbaPs4j7$89(&$1@x$tQn_B5`%~&ThaubGvNgPxjgPCnK%#Undn# zmgn&uH)Mfs_&v>q@`w1Kg!)&}#xQlYiUf3MT25}bOfN^&hq;_c?(qvBSjQWSNyd{2 zPh|SXSj3~;S=-@~Yo`5$x7t~o?YC1_0^eI#-;Z4kJTU=pt$58|R`)}izZQL}e=_vS z^(Ox~0#1CEI+FCahOLaHyN_c0CeA?3Tf}{5_w#jHUjLIR&%UE_hm4|C`d8`AfS~@Z zD?7%|g;B@M*z$@^k zOWT+(#7q=MNKJH(M`)#tsqxx^ZNUEizBR&o{Y=M6s_vRXb)(T&E_^FK?&S2eQGOMR zyC#oT;w&szq`eA*T1#N8@?_aaC=3MjVfh>u)EB-VA1l{=+?izFxRE=ou9NeSkqI|v`x^D!So$3JV z_CuihpK?>D+Wcz=bl$qJy==yXBYOMy?(S2Bd{+99`v@A-UT|3s!YlgV%wVpu)Hok_ zhgm`{l!aZ)U1AKGQtAQ37XG-#NownCpd>9M2g?3n^Fr*UT1VH^`z5&|OkuLcg#Bnw zn1Xiq^~nO?i@MuvOC|oOIxq041?ptEcf6?EDd!hCa1Z_xxX!6lPDC>bOLjW@^&NbA zW4FkNXR@}!7rMR2C1URV)mj^y#y6C1`@b(${rXi}SbK%-BnJ^-}TnXy6;?lMt=A% z?F-(8I6!(g-o97FrLLCL`O_ymLtqlbGYiFUepT@1V4YZDgC2lX6AG6c@{>=_W4;GH z%H}|fqh5<0Vazj?vQN9^JT$!m$#!Q;t-}W^c=4?L6xse7{)Qy4XfS-1Lro~@Wp)v< zNtIyrXZ((cjeVfeW4WmVcgF%CnJ$iWZX4J zn&f*{*AEuHPAE_1y&){J-@EMH}2O6FGp&iD2g6WduT>D{FB_`>7kg<5*{!G9;mb%kJT~o$BW=14g+Ol5@#^ zqCSX#_Q`DTmzQC*(uCeZh_0t%wux=>xMDCZ6(07io+XX1fCktM;O4F_>&?#O-Kvz}&no z{;LWCTloN6W z-X~xFqjU&Ais8=V&E=triu*95?u?meD;b>-w}tGIE9AUgTHn6=6I9qN^dvkEEH)i5 zk~vBY7Bq^Aby_aNWhsSBA){jOA8t<=!*i6>ekkr#uD4iKu&U)hdVci#2W74&R}AUccMLT?=4OC3KA)AO2TF$A$O9nHxTEW+2j=vzPl=^k zY}M@c%-F9G-6|!+`>!wG$jB1c{#vP&q0$`5SwQI4l_n3@ zc3NtQ;Ui&IxBfwHS9-VFurpi#x z*T!EwS5Gi5e+~(%Cn$63-bZ=0SN1yN4kwccMWAj6h@cw}1c615 z*iQs0XRG(6R95m66_y`LKNw2-miN5&ZkLLh@dT4`iC$yBQrqG_+sk_TZzYY@hlt#R zy{$NQ-GG#SxAo=+>J&%765D8{JMA8@0bw38VbUj+Xl-Pf&6epkN8;>h>1L}J(Mm_^ zu-dSGYYb=F>eHu;ImpP&$#0x)j;da7;ZwJXcSOvS^IE?;*gAOP&i4!lr~LCRbp0{H zGaHp40{+U#iYfL#1T_5Ao9#W!ZZEJvHy;y$vc0!l(W-3}S%nknXWld_8_TcOUgc!c zoA))cIZkK<2RL22MoCV1ZsnRJlffY@#^C5+OC{(^^5bpJrz6F{5i}OiRCk8#Mq)UP zKQ!vcI_OO`hG%!g$_no2G&hvwf0!!qRB&e6U$(2xRL+hJM=WZI*C?fAJxlzQ!^fpy z`ziYDJi+j=?0XfeNprGWCr8!4(s|26)`!Bsn-7&M#Xw8UhJH}GWqBG6CT!Wt`>wd8 zEjD-AXtixBsZ+YrDw*d%bEy7xBOqaSd zBV1`9tV5<~W?{LnfMKc!DU+?5O7=As4rYetXHGmi(JSNwR>*?>Pl(m0lTZGFU_xg6 znzAA3$omdJJKcztsy(x@Z$6A^qEZ_qE^Iy}ZA&O#7?<;l4&XUjnb-$-g4?5EvVso# zzkdwK*iwh%agVw;)Ryug9phv}cGo#S40&~Iu-puo=Mtl{ouzU{F;li{OK{QPfyNgZ z!?j_KMK}RFxHveH63%cfJAtG9_2tnxw?l_OV&)XtxMjYqn0A%)Sk-2LPR>y%2zG;q zr1Up=Pg5*!DG+IDPCPb03EBUGeenhcI@smspND?mFyqp>oyH4tI%r{XN9{R?Tu74 zA`#z(n|G#2BkhSsoW*JZcR;Lmmxb)~0j6_L}nvZEheFIgPrm3p#I$QMx4UVPrLDsTC+1 z^cSYXx}seXUmKSl0M00z^<;g@ykv6gV~H`^hrqX|(bE4N!7DI7Lw*%cZ0@$%r!PHL zJYe?pGf=~(Li#>|EdO&|r{OZI8FUiO_?_KIpOx%j^oy&zMLodE|sFk9R{>H@==N_DUzl>Aq0C2HD`H zn_QFx7ETq1PB)Curd;{cWcnQNE@E}PQu?oADoUZ*&S)mwUZ0V`7<<2{6 zAfh=~GIz5&AZ2^;D2CT&F*#+?IFoqhsFw2Zp80U4FNI?o5Uh9(ytxQ{A7QyM+s-2cJYOwO2={FoL+fC5Jg#6ujPNYRzq->nFOcmDdLel{* zR@PSa<=!t3VMX~pOYlf!sI@L?z}5DrT!AfZi#A!3ypzPAnbGcW1Iz zZNFG4M+qY1B;&I+S?I~`e$wtVRBi)MWnt*?RBD`SKXa5@Gbg5&DF^w$2*Gv6)*Wj~g9@!kX% zpYIHQn-MHp^Vbf57mBVB6j@*ypu674RXltxa`PYo`*bZ3LqK9kF*O{XM~c%G>cqMy zxHRwd*f22440kUL!<+_7ExFJ4Y6OnUaQ0We7L|csLCt9UrU>pXk^t(z!%{ns~CTj+c6CD9gAM8>&XuBZODoM(t zQ^E>g8|=gCTXKPmBbqW4^{ye;+?Yb{vbJPC-p{Uc`@J_#d<@G2fFl-$Kg)&731LBw zAf+?!aV=+I=4e^K@N;5ie+el&O|z*oz-UF{bL`*AmK@JNdW5EFnFUu5fg%gtN50x- zgrojcIObLtUV~rT`BM+cUg)d8P`G+K;q$Iz)DuK&K zcN(5{fP*lO#o-(cbGlO?<(o$v{J#7sCO7?y3cq(JLnqwccoYrkWYC~ zq=O4phvY$x4oKGklc!l2*wym!s`{ewmb{7-?#rvup^g1~^IJ~Z=U zZ}{NeG2)F@v$M0a%U~BHu~5U*uTp<=AiG`&nmRH!KZPU9GS;W zSIo@&&Sz}lDIx&vLsZf3-e6HP4<8r9_!+Qn^F(0rqx``8MeD^WwC~0(RD1+DCwl}T z#sR_JSiIHGlTS`x0+g@D7>_-|@;W$<%Jx}qSKsvVg1fR`B`VdSReJ~1Xi<^j?r`?| zGf&MI17bSWM>3sm={X~6u=N<9-YuT5iVgH$r)^8xdu&-}HX4;kc|`wR@UF($EZ>+Q zIh4a+63=hjB}uqJ|-q)Z>1*3YTag&Y{9)mEVOCf91vRsSjyU-lE%4{1K;e))Gb z`A$ALZ%os;+X>^`tfluuops7{!>+CV2!UU3{=^~H>Zr zJ&Q$8pBkKz?|g5BYsqBcDl3{qEM>pJ35|UV~lUOn9mXPKFqae9zkrKwtPj*G|?`Wn2$+)%=~+5OyU?zUT%(yjdmOr=eq&uP^W zU~^ZLmFR`b4Y>8}))(_zc2nPzKk1m4xf=Bh2OlZeBnQ-Y58v6Xa@m@mNKIFesE$P_ zv@*Ds{;J9&9NB&8!qj{{dAppO{7ls$$E-U)@5bd5TstpZCOY9QI<6MGNMf1PJ0x~4 zep;_ct8pB^8)Rj!YWqDt%z@d3W!}xgcc89lg)Esq)j_qR=L?PXsxEh5;6OiJxJMqy z@O*WXX6a7fd*=0!Vk~<8w`4O5yMf^f`X3`y@9MI$zX*02)2_YFmp6kV$nCywX}MBOp=|+h%a6SOtkSQ&xJ#{u<>W~I}NO|&vc7*`!VnnhOCHoV7PVHKx{}%5_ATw=T_l&=b1&7dfI3|Lqls*6HSX9 z)wzAZhs3J_45=GWV7ovrB$Re^oTzx&Xv(2L^;4q)yWpn*7HY;wcCqu_f<#jai=dyM z@V09F6VKourzO?1odm@});y3`f;gS_h(G$X9CF=GSy>tA+;A+uv&G3ObaW*2F%e3C z^Ts)uAo1J(RGsTa0tL>0d;%;T46gvU*Btd=1w`6U^y%`~2D$j45oT&tr1W*iT4-u* zv_m5aIXOX^G8G>&vK6bIoOZpZfFPl~-&M z!2Mrb#i8;?IVNlBNTAVa1dIJeP2`eOmv3;DMi4%M2)lM6Hj8jlh==sw3a${GSG2eX z(!y#g(x<2AtosD1{I7oGws-+JqroqC6$Jq~5X`q+icLUU>PQ5Lwg(PtI+>*Rp4EWN zM{lYLynKJXbp)jB$LUk9+rffAUF>lVd`!lE^}=k8_LU6+dB(=9Q3K$Wv^NVKfml~lBpicQqa3*ImcEIMnwjf!VA6#%(Q;>??}CoE_u zYCFa=kz3%14|tvscFxNGh*Hyvg2%sFv%j+*=elbcZrqdQFzhgs-UhsnDW~+9&hC({ zJQ|#RP(9b335Oo8Mf4XL4@fnCtDgFxQ6F>zp8hly{LcAdv^5>Q0*@Z4PNU8wVKpJnV1~|8wU!Sbz(^E61K@L3MU$n3>*QvBTP_hCTSAz=g-A~*? zUA1B}=bXO51e{#ID4;q2t*Nq0$LDE6;prc%0g=yWz<3lu#KfqaWk8a9-4(n_XlF7E zaP+!A+N)fgH0+N62hs6uFXs@*1p_<+A|F%*0JC*;pX3OL*75}e9vjqM7nvUuOPJq_RiI*uhPNF97el)bg<&4;w12a zMXNtcjf1&A7ek}igp|wVqj8zp5U+}Mp+Tq_*(=ssg=e0ws-gj|e}Pq*;L3SB{j(4% zD>RHNH+z$%NVJ04w?QT6SN;)Te?`MqhBkJ4RWx9ZHbq@5Mkz#lfTyT%-mwfXvOWT= ze&t?&KT<|tv1wF^;Hd8SzB?ZN(0L&}j{7vk35?FkVrHJO&$*kUPZb=>=U zlgaU~0$TO8RaW?BW>Dohb3WBNRt5yrR%j|xB&GXG95uMy8s9TGrkCx72H|D`_A9_N z<7w*K1Q(_SZI5sLn3dWVu4ZOtfcc13QZ^5tomp|2oSI6%xq8?sa2~5bvrXLA8KRy( zg~+1-)Q|@Rhm8clp50@L`{!=tSGRG0x_YGHddLF>lvnUVTuU*9kT4p<+^$Zbl5Ho%2KI5Q!ueyZP+dX4mIbD;j7g|JE>TQY0^x%_nu4)FQ^#E*1oqIss#W6OYjuCk?M*J+q-Ph3h` zHaOTtbbdc5^xie|tinZvPZ_tP2w)+GkmS$%p2wT3&#GMOFWn*eZ#SCS?f5bTD1_!} zmRSPkGf}&k`bfRVh`|vMrS@GIW>tsa5VxKE?8~BFDBi?N;k5XLh*8n6Upw3=&!jKE zE|6p)#RC-C6f+dl^FByq=zF@pd&YCdY64e8(~Q@w*%Le0IdXzP$Y|8)ji3k{rLbbm zVK&I!y#ee|g%XiWJ6-~Ki2t<8PyYbJ5`d0j~z3(g-NdfO-}Kw95Ip*r$8XzX1l`MFX5> zP5`5J8K17c!`@|pOrNX00!eJa>6I5ubrItx!T>t^I2oW#8231Z-oKPcJr|BZsD7eM zy>oWH@>jBQvY{Z$tKx><5Z`cX|LlEwSR4npj|iyX!6_nVx$@b!kOXvR|Eh6kfsHU^ zN12UuZtWiI*&(7M&SPZZ?BQz*e@SAWSikw4=@cU&3Lw!AYi#;@er5k2g&rm(a-$j7 z5z7@Tw)l-=YL+90I###X-`M$An1`+C-fOS?T3uoSLkvUk%Q!!(Jjy-OxhGA?Q#m>O z=;5}%;`Kis51d_&n9rb%%A8s%A&$-K#)QbApN9B~c0Ws11l!xN5a~POZJoUj&CQnt zk<6tlFvJwlZJ!wpO9mTu-#Mv32T}Jr zj8~*q?%Ua^nxm?G`XDlSr{WG~me4T9u%(5Qal|4^bXRq$d*Lbh`Hcm5*yh!wqmvCe zr)4=bLJf9dA$l+Qc~?~|t?|j>J8e0mQnOkv=}u%lsP->iSB8*shKT|yMQW{+k`5mS zw4VhRG2oP%ef{Rj8T)mbym%1EABH|rPx>FzB>3Wx(J+-x$emL}D0qnh;1MkFj;^~38 zCwTY1JyXc(6aKCE#kQzfCfeIA!4OF+pQ#En;ws0NobnaA!nv``)plj(UG<8uMQUKk zT^ivCzjo80(i_&_4zJ6d@r?fm`|T|YX^(%<0!OFEz1@!20x@#G+Yo$pT-`ZSpL&1v zl4hghixqsnm_|oJTO-)RjW*>Mhu{3tPPbHn0kA5PrY(O(g8y!>w-RJ0?m>IWuizTi zrP_203yw7!4)rEogvr$^M`KRI6)tkD_wKO3EGfo?t9=46tHtKTJ$vdBh0`iJRmgF6 zp@VDXe4?n+Er(DIq7ctiq{;SC5NvdECy@DZdpS!z@9b5QA=gHBib_9XoW1IBOUQTM zNq?PSU2I(LbXL$msVPL7ag*RY`2Xu>STOf*{3~cKTEQ>)uN`y+XC`Nm;l}W?KQA&- zYR!rX+5P-8mSa9BwL)T%{Q3^9B5c^hF%9yI6^-J=q9N>{niuxDk?jK4$H%2FS*P6% zSOA9)e>8E7quAF057^cDBj#-L=NWcPx@hm1@%g4pwo-Q?^>K?HquYOG4N(F~p&I9) z=3nRQza}o1=B{gFH{w!aES#`HuOR0aIz=#DQhTQl>!C5bJIdanbir2VuP_s{zkO``a z+<$LP^hbLrps+%jHWtruHp|HqMDiFp^L0K9%6>%(nL6ealC&Tz>pWJ|X*Yay_wRPa zZL%et+&{pl278TvnON%rg8v%LaWl5uwS(^s_56}u+|adt{{e;gPAdfVU;DE0+6id;}S4EcnD(_JaG%%s@k75*iRw^uLcsXc-87mW|;A_}c7 zU$0_CLb`l*vA4aro@|^%2%dn1q%6GpS?EN#Q~z{_D4)eq3<41zUMwVl3K0C zdPG7s8oVrWnu_8}1EY(?vAJM)3fA_xv(|@ZLj6elHPO<0R<*Lj4m|8Aw}|NPj_SJ{ zhFqZ^`onB{=p1v955r&nm013Z<8vgd$xYvP7_ML23qt)lP^OcEDP$Fb;vf@BiV})k z-7_--mD9V#qT=yq<^M-@*Mq?CNralEP`cM-g^$RLLUgc$LNkxO9`5YJC;n9xqD&kv zBOWKv=yCV>s=_znnRov&c`6Qc@rb8FIib@}SY;0AU)4V$^5b=hvle>l8@2GK2;$KT zZ2OB#Z@`&CPoBIXH4!WvYW(OgUpwH0@Svm6;`4yfaa$OFPA;7&0LjHc-0-vJ>Jz4l z^iIvYJws9%^Tq}(LPJs%nMhNV@-PtY@R(V+Do?i-KR`MiHMv`fd3Ma6JbA2QZ_@@Y zpa2Ot0^YSYH`~l8lr~g8PZdV?(81kSo}Qt6mj9JU@XuP%j_Xt0FNI}K#-E{!$8iK9 zXyMwfgKabxMkn_qgvnPpz858Fua5R5<{xOos)m%ULQzys1UP3XIzH~KDzxpgQ)y1A zb2M?14lO>ABzKM5waODE`YNP-v8PoIDpa(OxpBx|4R`+I+z?vaV>4qcvkds55$46r z-Q}Q!W$9cBC?&xDJlX}M&~Y;zq5>pppe z60{6zfAdS;_1TEX%ZLdrzdB?LND&b7zpOGul|99p}>lBc?YwEgD3|tX-*!0ByAk zfWrcGor~!*=wb6f#oT2qn4AJlI4+>c<4K(0kQ2;izH6@c%LHIu2S8TrOX=EMk>0SD zCZAY1F<55Roe#27a~MK7wBmM>hv;!u$lDci>mkOa>-ZBN=LbMqMkgCTej}X5& zTHmw_jz(1;iTiJ&3aVP;{jmkfyK*Vto$}9s_{7pdS@j*7N%t1$Tp+T>(fx^&xk1$> zd(Hm2Z#RDL6BmIdq0!G(IpaYOhI@g|c4p#Ma?+$CSZ+KpE0lwVt7uyIOfSS)cS!U= z9IB_^9}{_MH|7HuwkLvB(x3%;(si|Q&TBtG!`6NK)lncx5GjY~m#qgQ&J*`0?kZ*~ zFNHk3;$L8a5=BHv*xO#n_;9h7;#CbY$U&{GcALU+w{nZ-y#RkWkNQ;VY3~m`6XdfZ z*k=NeWL_A20h6OwQ>34=WI+EJkmX59r#~4|Dp3<~sn$l!$4rReO2f9cO*InGaCUT9nGU+AfU@ zsdu4OmB2bd2W@O-a6$YHl=sV-7K}3sM7cG>G2%W7tI?>ASr4azh4IeEg0aR=2x zP~hl$Z@4>0E?KuT54rx(#ijz}^D?a(!+=^<(~m)bHQ6onEJ2TUReW%WGz$s|L5o^a zY|>Pht-^uGS3sg<-{fI9?p7>aE??-1Z_r)pw8zHgDFRJEd-3n50}2cMAMfpIb|>EV zeE~fQ+(5cGxhs6*>h5V6c8XAa)bYI%7FDe6fJ4B44GlwN-xyPO72+BKEa&~FP$3F8 zz?mJb#~pPUEqxg<&RjD&DBu6Utns375L6C8A9MCsS)qeM{Z2V=gJ&Pz@kv!BT#4)%)YlUoo6TO(pUV%dEI zMfQ8d2rLWbdg3;7wCxY+aLHS?lW12YqqU^%IUesh&gShJNN<1Tp*l&OLPSB(a(~>) z=tR!b0JT9B6aum~>y6&ZDx15Qh`tNhj2H=v&km7aXiwA|P9@Yjqf8`Z4N9s;+=bz`K60 z#?Gw<)CedXXK#_G0yN=mG0ughZ0;?&%(BC?)Cl&-iV&axWeS=~vp>0pL#o-TEvF<` zwCAfoJXk%<@h}|%B(*LgBVuOGypKIBpaM z6gPb`5FFcTb@Z!#w8d+d{oa?sfbhzSQ5-E9vjnTz9v%4McgKoHtX<4`3Fg;6>bc+#} zt-fWTzHUW(>E9(ox#jbW1AvDcLC6$Qa+&l>(8Wx)q^+tpgR)R+BseqY7S$O?+r=o0 zFl@aUo~F=a*;ULoIHvpB$kHhVzXT7@R#?=quGnhgPiu`eJQW;OfUKK6PEtg`871 zO$LfiMf-qe&YB8jt?C68iIO?c!P}#})qzva3@M3v)U)swhtIFPJ^d*i_=j7DVOkHe zR=?r08f3nW*E;Tz7Nc-Tay{71fh}{$74&+I^F6D9su$+A_PTF{EuXd+{l?v=JxnRQ zsB@bB6GSH=H}V~M0PG!e$n&y8a3i)jbYf<#IoM$6)Z8;49pb=)fwXM>;+V4D{ z17%<#;6_HtsKaDKC~s)EjlMfy1E{r;aBk`?f%<95P?2)Aaf+wUE^mBh7xhk$LWMz} zTetDrF1g*{^Ki$Wxnn9WOB<%%xlmN^-pzz-C*~*rN@eD4N)(25bXvu%FLu_a1Z#La zxVod9KEnMfeA!?=YMH2w`e^qt>QMSK1Smy9vy+z<+mt8rr6s3`V8%uJm=yLkVzUlVsBb##Wtvs*0fc^|*n|+I8hX%h)1RAw<5tOdmpEHkk7jlOrnBgVTK9>Uq z*a*>^5H{VPXPIM8wKNXyg}LrUebE08G(e~rP$EUM>dFyv-_r;T4%1NR1Qf*^ceoAG z(M^(o9Xy?I9PbFCvd5c04?a|GJ?IC-wJD!bMmY{}C8c>c(3xJA2)gCx zrlZVzI<|P5Y~Wg{zf`{z7Bd>ynHGvyHA+rt1u^yVu5Ky_{mzNk^0zrUJkavW%&qEg zROhczm_NSL1Fd$=@pxxg#4{W3^_G9Ffho7LV?Nxr0)q{wWY}>5)G0I@vOgRb8O^-x zx5s>8)ws{Z+H^DGsg6K^VfW+x>u_+_PE2JEXTE?KmJ5PJnK9*t2NFf?{)I}_!q1k9 zRKJZJ9ojXI!q*P3y<(_fckMQ2I|2n`;~{j79Eg|hL~`AZEdTFE-4$Wwp7rf!d~K%4 z%Le@!6_kU7Zn@P1Y(~igWUHQg?nQ1b$Scfeb*}NN^y3kQ<2-1l|Bbql(VS6m!rsq1 z(cBS{oNqt*w*Z<^R1_CGXrWHp7-BV|%rs(>pDh8xvcNVvuJ?n`HrjF-(8dFg=Z5Rm zep=lfz@{#Mi#pnj;>zqWP^<5yT`71V(vxx6 zpA=UJSoG48ASPqaJphK;5iI`j(5U-{<7CmVzF{l(Fr(zK+kSrNdqw>^bODWjv-f4r z6u1Vn(Qlj!Ec2+tMlIPj;qa4wto%*@Q_ibqMY&74hpnVG3 z+S;P8zu#$p9`_#iSFAt<=yG3%&lV|Gh}bpNC2l@8%+ZL@F6b`W1Gm}eWTFj%VC!%# z5ooTqz{uwemE0WX-EI|Vch-Sb3r{M@Ak=NO8S+!!?5T@Zb^UTuGWxj-YVD3CtFQ{@e1B(n2tQsh8eH`1OqDGO(J)>ar~*-Y=?Yck-f~Ly z9+v~OoR7lVV|e#lV-76W;{#J3*@3qQAX$@LalRT=mXN4QgXAR}e-mrO?&oHQHXr_yQ5EGjnVF?!d}G(2WHd;}GCde;!@G3sYdEqvtAZ|Tat)cbX4e5YI~;d`o8 z)1~iLXeEm7xnBs@hYiP!U$WZpD7OXS%HK%qAa5R^GDDc6bX zcn|_2;ld^l$ZK2!¬NKD)#iOxIgR_MXKW*kfvUI@b>DG{iDBQ3| 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%0D`DdPfH{fZN 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�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 N-QNw4 + +# ![egf](https://media.thi.ng/umbrella/banners/thing-egf.svg?6d6aa209) + +[![npm version](https://img.shields.io/npm/v/@thi.ng/egf.svg)](https://www.npmjs.com/package/@thi.ng/egf) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/egf.svg) +[![Twitter Follow](https://img.shields.io/twitter/follow/thing_umbrella.svg?style=flat-square&label=twitter)](https://twitter.com/thing_umbrella) + +This project is part of the +[@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. + +- [About](#about) + - [Built-in tag parsers](#built-in-tag-parsers) + - [Status](#status) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [API](#api) + - [Basic example](#basic-example) +- [Authors](#authors) +- [License](#license) + +## About + +Extensible Graph Format. + +Striving to be both easily readable & writable for humans and machines, this +line based, plain text data format and package supports: + +- Definition of different types of graph based data (e.g. RDF-style or Labeled + Property Graph topologies) +- Full support for cyclic references, arbitrary order (automatic forward + declarations) +- Choice of inlining referenced nodes for direct access or via special node ref + values +- Arbitrary property values (extensible via tagged literals and custom tag + parsers a la [EDN](https://github.com/edn-format/edn)) +- Optionally prefixed node and property IDs with (also optional) auto-expansion + via declared prefixes (for [Linked + Data](https://en.wikipedia.org/wiki/Linked_data) use cases) +- Inclusion of sub-graphs from external files +- Loading of individual property values from referenced file paths +- Optionally GPG encrypted property values (where needed) +- Multi-line values +- Line comments +- Configurable parser behavior & syntax feature flags +- Hand-optimized parser, largely regexp free +- GraphViz DOT conversion + +![example graph](https://raw.githubusercontent.com/thi-ng/umbrella/feature/egf/assets/egf/egf-readme.png) + +([Source for this example graph is further below](#basic-example)) + +### Built-in tag parsers + +The following parsers for tagged property values are available by default. +Custom parsers can be registered via `registerTag()`. + +| Tag | Description | Result | +|-----------|---------------------------------------------|--------------------| +| `#base64` | Base64 encoded binary data | `Uint8Array` | +| `#date` | `Date.parse()` compatible string | `Date` | +| `#file` | File path to read value from | `string` | +| `#gpg` | Calls `gpg` to decrypt given armored string | `string` | +| `#hex` | hex 32bit int (no prefix) | `number` | +| `#json` | Arbitrary JSON value | `any` | +| `#list` | Whitespace separated list | `string[]` | +| `#num` | Floating point value | `number` | +| `#ref` | Inlines node for given ID | `{ $ref: string }` | + +**Note:** In this reference implementation, the `#file` and `#gpg` tag parsers +are only available in NodeJS. + +### Status + +**ALPHA** - bleeding edge / work-in-progress + +## Installation + +```bash +yarn add @thi.ng/egf +``` + +```html +// ES module + + +// UMD + +``` + +Package sizes (gzipped, pre-treeshake): ESM: 2.06 KB / CJS: 2.14 KB / UMD: 2.14 KB + +## Dependencies + +- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/api) +- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/checks) +- [@thi.ng/defmulti](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/defmulti) +- [@thi.ng/dot](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/dot) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/errors) +- [@thi.ng/prefixes](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/prefixes) +- [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/strings) +- [@thi.ng/transducers-binary](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/transducers-binary) + +## API + +[Generated API docs](https://docs.thi.ng/umbrella/egf/) + +TODO - Full docs forthcoming... + +- [api.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Data structures & options +- [dot.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Graphviz export +- [parser.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Parser +- [tags.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Tagged value parsers + +### Basic example + +```text +; file: readme.egf + +; prefix declaration (optional feature) +@prefix thi: thi.ng/ + +; a single node/subject definition +; properties are indented +; `thi:` prefix will be expanded +thi:egf + type project + ; tagged value property (here: node ref) + part-of #ref thi:umbrella + status alpha + description Extensible Graph Format + url https://thi.ng/egf + creator #ref toxi + ; multi-line value + ; read as whitespace separated list/array (via #list) + tag #list >>> +graph +extensible +format +linked-data +<<< + +thi:umbrella + type project + url https://thi.ng/umbrella + creator #ref toxi + +toxi + type person + name Karsten Schmidt + location London + account #ref toxi@twitter + account #ref postspectacular@gh + +toxi@twitter + type account + name @toxi + url http://twitter.com/toxi + +postspectacular@gh + type account + name @postspectacular + url http://github.com/postspectacular +``` + +```ts +import { parseFile } from "@thi.ng/egf"; + +// enable prefix expansion in parser +const graph = parseFile("readme.egf", { opts: { prefixes: true } }).nodes; + +console.log(Object.keys(graph)); +// [ +// 'thi.ng/egf', +// 'thi.ng/umbrella', +// 'toxi', +// 'toxi@twitter', +// 'postspectacular@gh' +// ] + +console.log(graph.toxi); +// { +// '$id': 'toxi', +// type: 'person', +// name: 'Karsten Schmidt', +// location: 'London', +// account: [ +// { +// '$ref': 'toxi@twitter', +// deref: [Function: deref], +// equiv: [Function: equiv] +// }, +// { +// '$ref': 'postspectacular@gh', +// deref: [Function: deref], +// equiv: [Function: equiv] +// } +// ] +// } + +// in this example inlining of referenced nodes is disabled (default) +// therefore refs are encoded as objects implementing the `IDeref` interface +// to obtain the referenced node +console.log(graph.toxi.account[0].deref()); +// { +// '$id': 'toxi@twitter', +// type: 'account', +// name: '@toxi', +// url: 'http://twitter.com/toxi' +// } +``` + +## Authors + +Karsten Schmidt + +## License + +© 2020 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/egf/api-extractor.json b/packages/egf/api-extractor.json new file mode 100644 index 0000000000..94972e6bed --- /dev/null +++ b/packages/egf/api-extractor.json @@ -0,0 +1,3 @@ +{ + "extends": "../../api-extractor.json" +} diff --git a/packages/egf/package.json b/packages/egf/package.json new file mode 100644 index 0000000000..07fe9ca705 --- /dev/null +++ b/packages/egf/package.json @@ -0,0 +1,72 @@ +{ + "name": "@thi.ng/egf", + "version": "0.0.1", + "description": "Extensible Graph Format", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", + "typings": "./index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/thi-ng/umbrella.git" + }, + "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/egf#readme", + "funding": { + "type": "patreon", + "url": "https://patreon.com/thing_umbrella" + }, + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "build": "yarn clean && yarn build:es6 && node ../../scripts/bundle-module", + "build:release": "yarn clean && yarn build:es6 && node ../../scripts/bundle-module all", + "build:es6": "tsc --declaration", + "build:test": "rimraf build && tsc -p test/tsconfig.json", + "test": "mocha test", + "cover": "nyc mocha test && nyc report --reporter=lcov", + "clean": "rimraf *.js *.d.ts *.map .nyc_output build coverage doc lib", + "doc:readme": "ts-node -P ../../tools/tsconfig.json ../../tools/src/readme.ts", + "doc:ae": "mkdir -p .ae/doc .ae/temp && node_modules/.bin/api-extractor run --local --verbose", + "doc": "node_modules/.bin/typedoc --mode modules --out doc src", + "pub": "yarn build:release && yarn publish --access public" + }, + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@microsoft/api-extractor": "^7.8.0", + "@types/mocha": "^7.0.2", + "@types/node": "^14.0.1", + "mocha": "^8.0.1", + "nyc": "^15.1.0", + "ts-node": "^8.10.1", + "typedoc": "^0.17.6", + "typescript": "^3.9.5" + }, + "dependencies": { + "@thi.ng/api": "^6.11.3", + "@thi.ng/checks": "^2.7.3", + "@thi.ng/defmulti": "^1.2.20", + "@thi.ng/dot": "^1.2.12", + "@thi.ng/errors": "^1.2.16", + "@thi.ng/prefixes": "^0.1.0", + "@thi.ng/strings": "^1.9.0", + "@thi.ng/transducers-binary": "^0.5.23" + }, + "files": [ + "*.js", + "*.d.ts", + "lib" + ], + "keywords": [ + "ES6", + "typescript" + ], + "publishConfig": { + "access": "public" + }, + "sideEffects": false, + "thi.ng": { + "branch": "feature/egf", + "status": "alpha", + "year": 2020 + } +} diff --git a/packages/egf/src/api.ts b/packages/egf/src/api.ts new file mode 100644 index 0000000000..fdab55ce74 --- /dev/null +++ b/packages/egf/src/api.ts @@ -0,0 +1,71 @@ +import type { IDeref, ILogger } from "@thi.ng/api"; +import { isNode } from "@thi.ng/checks"; +import { unsupported } from "@thi.ng/errors"; + +export interface Node { + $id: string; + [id: string]: any; +} + +export interface NodeRef extends IDeref { + $ref: string; +} + +export type Nodes = Record; + +export type Prefixes = Record; + +export interface ParseOpts { + /** + * If true, parser will include referenced source files and read tagged + * `#file` values. + * + * @defaultValue true + */ + includes: boolean; + /** + * If true, `#ref`-tagged values will be resolved and used as value instead + * of their referred node ID. Circular dependencies ARE supported. + * + * If false, `#ref` values will be stored as {@link NodeRef} values in the + * result object to allow them to be identified as references. + * + * In both cases, if the `prefixes` option is enabled, the referenced IDs + * will/might first be expanded (iff they match the `prefix:name` pattern). + * + * @defaultValue false + */ + resolve: boolean; + /** + * If true, IDs of the `prefix:name` form, will be expanded using + * pre-declared `@prefix`es. If enabled and a prefix cannot be resolved, the + * parser will throw an error. + * + * Prefixes can be overridden on a per-file basis. If an included file + * defines its own prefixes, they will only be in scope for triples defined + * in that file. + * + * @defaultValue false + */ + prefixes: boolean; + /** + * If true, tagged `#gpg` values will be decrypted. + * + * @defaultValue false + */ + decrypt: boolean; + [id: string]: any; +} + +export interface ParseContext { + cwd: string; + file: string; + prefixes: Prefixes; + nodes: Nodes; + opts: Partial; + logger: ILogger; +} + +export const IS_NODE = isNode(); + +export const NODE_ONLY = () => unsupported("only available in NodeJS"); diff --git a/packages/egf/src/dot.ts b/packages/egf/src/dot.ts new file mode 100644 index 0000000000..ae2d9b927e --- /dev/null +++ b/packages/egf/src/dot.ts @@ -0,0 +1,49 @@ +import type { IObjectOf } from "@thi.ng/api"; +import { isArray } from "@thi.ng/checks"; +import { Edge, GraphAttribs, Node, serializeGraph } from "@thi.ng/dot"; +import type { Nodes } from "./api"; +import { isRef } from "./utils"; +import { slugify } from "@thi.ng/strings"; + +export interface GraphvizOpts { + onlyRefs: boolean; + ignore: Iterable; + attribs: Partial; +} + +export const toDot = (graph: Nodes, opts: Partial) => { + opts = { onlyRefs: true, ...opts }; + const nodes: IObjectOf> = {}; + const edges: Edge[] = []; + const ignore = new Set(opts.ignore); + + const addEdge = (src: string, prop: string, val: any) => { + if (isRef(val)) { + edges.push({ src, dest: val.$ref, label: prop }); + } else if (val.$id) { + edges.push({ src, dest: val.$id, label: prop }); + } else if (!opts.onlyRefs) { + const id = `lit-${slugify(String(val))}`; + nodes[id] = { label: String(val).replace(/\n/g, "\\n") }; + edges.push({ src, dest: id, label: prop }); + } + }; + + Object.entries(graph).forEach(([id, node]) => { + nodes[id] = { label: node.name || node.$id }; + Object.entries(node).forEach(([prop, val]) => { + if (ignore.has(prop)) return; + if (isArray(val)) { + val.forEach((v) => addEdge(id, prop, v)); + } else { + addEdge(id, prop, val); + } + }); + }); + + return serializeGraph({ + attribs: opts.attribs, + nodes, + edges, + }); +}; diff --git a/packages/egf/src/index.ts b/packages/egf/src/index.ts new file mode 100644 index 0000000000..48b73925eb --- /dev/null +++ b/packages/egf/src/index.ts @@ -0,0 +1,5 @@ +export * from "./api"; +export * from "./dot"; +export * from "./parser"; +export * from "./tags"; +export * from "./utils"; diff --git a/packages/egf/src/parser.ts b/packages/egf/src/parser.ts new file mode 100644 index 0000000000..c15d095ede --- /dev/null +++ b/packages/egf/src/parser.ts @@ -0,0 +1,169 @@ +import { NULL_LOGGER } from "@thi.ng/api"; +import { isArray } from "@thi.ng/checks"; +import { illegalState } from "@thi.ng/errors"; +import * as $prefixes from "@thi.ng/prefixes"; +import { readFileSync } from "fs"; +import { dirname, resolve as resolvePath } from "path"; +import { IS_NODE, Node, ParseContext, ParseOpts } from "./api"; +import { parseTag } from "./tags"; +import { qualifiedID } from "./utils"; + +const INCLUDE = "@include "; +const PREFIX = "@prefix "; +const OPEN = ">>>"; +const CLOSE = "<<<"; +const EOF = "unterminated value, EOF reached"; + +export const parse = (src: string, ctx: ParseContext) => { + const lines = src.split(/\r?\n/); + const nodes = ctx.nodes; + const usePrefixes = ctx.opts.prefixes; + for (let i = 0, n = lines.length; i < n; ) { + let subj = lines[i++]; + if (!subj.length || subj[0] === ";") continue; + if (subj[0] === "@") { + if (subj.startsWith(INCLUDE)) { + parseInclude(subj, ctx); + continue; + } else if (subj.startsWith(PREFIX)) { + usePrefixes && parsePrefix(subj, ctx); + continue; + } + } + usePrefixes && (subj = qualifiedID(ctx.prefixes, subj)); + const curr: Node = nodes[subj] || (nodes[subj] = { $id: subj }); + while (i < n) { + let line = lines[i]; + if (line[0] === "\t" || line.startsWith(" ")) { + i = parseProp(curr, ctx, line, lines, i); + } else if (!line.length) { + i++; + break; + } else if (line[0] === ";") { + i++; + } else illegalState(`expected property or comment @ line: ${i}`); + } + } + return ctx; +}; + +const parseInclude = (line: string, ctx: ParseContext) => { + const path = line.substr(INCLUDE.length); + if (IS_NODE && ctx.opts.includes) { + parseFile(path, { + ...ctx, + cwd: dirname(ctx.file), + prefixes: { ...ctx.prefixes }, + }); + } else { + ctx.logger.debug("skipping include:", path); + } +}; + +const RE_PREFIX = /^([a-z0-9-_$]*)$/i; + +const parsePrefix = (line: string, ctx: ParseContext) => { + const idx = line.indexOf(": ", PREFIX.length); + if (idx > 0) { + const id = line.substring(PREFIX.length, idx); + if (RE_PREFIX.test(id)) { + const val = line.substr(idx + 2).trim(); + if (val.length) { + ctx.logger.debug(`declare prefix: ${id} = ${val}`); + ctx.prefixes[id] = val; + return; + } + } + } + illegalState(`invalid prefix decl: ${line}`); +}; + +const parseProp = ( + acc: Node, + ctx: ParseContext, + line: string, + lines: string[], + i: number +) => { + const idx0 = line[0] === "\t" ? 1 : 4; + if (line[idx0] === ";") return ++i; + let idx = line.indexOf(" ", idx0); + let key = line.substring(idx0, idx); + ctx.opts.prefixes && (key = qualifiedID(ctx.prefixes, key)); + let tag: string | undefined; + let body: string; + idx++; + if (line[idx] === "#") { + const tstart = idx + 1; + idx = line.indexOf(" ", tstart); + tag = line.substring(tstart, idx); + idx++; + } + if (line.substr(idx, 3) === OPEN) { + body = line.substr(idx + 3); + idx = body.indexOf(CLOSE); + if (idx < 0) { + const n = lines.length; + let closed = false; + while (++i < n) { + line = lines[i]; + idx = line.indexOf(CLOSE); + if (idx >= 0) { + body += "\n" + line.substr(0, idx); + closed = true; + i++; + break; + } else { + body += "\n" + line; + } + } + !closed && illegalState(EOF); + } else { + body = body.substr(0, idx); + i++; + } + } else { + body = line.substr(idx); + i++; + } + body = body.trim(); + const val = tag ? parseTag(tag, body, ctx) : body; + const exist = acc[key]; + if (exist) { + isArray(exist) ? exist.push(val) : (acc[key] = [exist, val]); + } else { + acc[key] = val; + } + return i; +}; + +const initContext = (ctx: Partial = {}) => { + const opts = { + includes: true, + prefixes: false, + decrypt: false, + resolve: false, + ...ctx.opts, + }; + return { + cwd: ctx.cwd || ".", + file: ctx.file || "", + pid: -1, + nodes: ctx.nodes || {}, + prefixes: ctx.prefixes + ? { ...ctx.prefixes } + : { ...$prefixes, void: $prefixes.VOID }, + logger: ctx.logger || NULL_LOGGER, + opts, + }; +}; + +export const parseFile = (path: string, ctx?: Partial) => { + const $ctx = initContext(ctx); + $ctx.file = path = resolvePath($ctx.cwd, path); + $ctx.logger.debug("loading file:", path); + return parse(readFileSync(path).toString(), $ctx); +}; + +export const parseString = (src: string, ctx?: Partial) => + parse(src, initContext(ctx)); diff --git a/packages/egf/src/tags.ts b/packages/egf/src/tags.ts new file mode 100644 index 0000000000..152c65010c --- /dev/null +++ b/packages/egf/src/tags.ts @@ -0,0 +1,67 @@ +import type { Fn3 } from "@thi.ng/api"; +import { defmulti, DEFAULT } from "@thi.ng/defmulti"; +import { maybeParseFloat, maybeParseInt } from "@thi.ng/strings"; +import { base64Decode } from "@thi.ng/transducers-binary"; +import { execSync } from "child_process"; +import { readFileSync } from "fs"; +import { resolve as resolvePath } from "path"; +import { IS_NODE, NODE_ONLY, ParseContext } from "./api"; +import { qualifiedID } from "./utils"; + +export const parseTag = defmulti( + (tag) => tag +); + +parseTag.addAll({ + base64: IS_NODE + ? (_, body) => { + const buf = Buffer.from(body, "base64"); + return new Uint8Array(buf.buffer, 0, buf.length); + } + : (_, body) => new Uint8Array([...base64Decode(body)]), + date: (_, body) => new Date(Date.parse(body)), + file: (_, path, ctx) => { + if (IS_NODE && ctx.opts.includes) { + path = resolvePath(ctx.opts.root!, path); + ctx.logger.debug("loading value from:", path); + return readFileSync(path).toString(); + } else { + ctx.logger.debug("skipping file value:", path); + return path; + } + }, + gpg: IS_NODE + ? (_, body, ctx) => + (ctx.opts.decrypt + ? execSync(`echo "${body}" | gpg --decrypt`).toString() + : body + ).trim() + : NODE_ONLY, + hex: (_, body) => maybeParseInt(body, 0, 16), + json: (_, body) => JSON.parse(body), + list: (_, body) => body.split(/[\n\r\t ]+/g), + num: (_, body) => maybeParseFloat(body, 0), + ref: (_, id, ctx) => { + id = ctx.opts.prefixes ? qualifiedID(ctx.prefixes, id) : id; + return ctx.opts.resolve + ? ctx.nodes[id] || (ctx.nodes[id] = { $id: id }) + : { + $ref: id, + deref() { + return ctx.nodes[id]; + }, + equiv(o: any) { + return o != null && o.$ref === this.$ref; + }, + }; + }, +}); + +export const registerTag = ( + tag: string, + fn: Fn3 +) => parseTag.add(tag, fn); + +export const enableUnknownTags = () => parseTag.add(DEFAULT, (_, x) => x); + +export const disableUnknownTags = () => parseTag.remove(DEFAULT); diff --git a/packages/egf/src/utils.ts b/packages/egf/src/utils.ts new file mode 100644 index 0000000000..1955880e4d --- /dev/null +++ b/packages/egf/src/utils.ts @@ -0,0 +1,20 @@ +import { isPlainObject } from "@thi.ng/checks"; +import { illegalArgs } from "@thi.ng/errors"; +import type { NodeRef, Prefixes } from "./api"; + +export const isRef = (x: any): x is NodeRef => isPlainObject(x) && "$ref" in x; + +const RE_QFN = /^([a-z0-9-_$]*):([a-z0-9-_$.+]+)$/i; + +export const qualifiedID = (prefixes: Prefixes, id: string) => { + if (id.indexOf(":") !== -1) { + const match = RE_QFN.exec(id); + if (match) { + const prefix = prefixes[match[1]]; + return prefix + ? prefix + match[2] + : illegalArgs(`unknown prefix: ${id}`); + } + } + return id; +}; diff --git a/packages/egf/test/prefix.ts b/packages/egf/test/prefix.ts new file mode 100644 index 0000000000..a9de5fb7f1 --- /dev/null +++ b/packages/egf/test/prefix.ts @@ -0,0 +1,44 @@ +import * as assert from "assert"; +import { ParseContext, parseString, qualifiedID } from "../src"; + +const $ctx: Partial = { opts: { prefixes: true } }; + +describe("egf @prefix", () => { + it("@prefix decl", () => { + assert.throws(() => parseString(`@prefix :`, $ctx), "1"); + assert.throws(() => parseString(`@prefix : `, $ctx), "2"); + assert.throws(() => parseString(`@prefix a&b: abc`, $ctx), "3"); + assert.equal(parseString(`@prefix : abc`, $ctx).prefixes[""], "abc"); + // prettier-ignore + assert.equal(parseString(`@prefix _: abc`, $ctx).prefixes["_"], "abc"); + // prettier-ignore + assert.equal(parseString(`@prefix $1a-b_C: abc`, $ctx).prefixes["$1a-b_C"], "abc"); + }); + + it("qfn", () => { + const qfn = (id: string) => + qualifiedID({ "": "self/", thi: "thi.ng/" }, id); + assert.equal(qfn(":a"), "self/a"); + assert.equal(qfn("thi:a"), "thi.ng/a"); + assert.throws(() => qfn("foo:a")); + }); + + it("resolve w/ prefix", () => { + const { nodes, prefixes } = parseString( + ` +@prefix : self/ +@prefix thi: thi.ng/ +:a + partof #ref thi:b + +thi:b + parentof #ref :a +`, + { opts: { prefixes: true, resolve: true } } + ); + assert.equal(prefixes[""], "self/"); + assert.equal(prefixes["thi"], "thi.ng/"); + assert.equal(nodes["self/a"].partof.$id, "thi.ng/b"); + assert.equal(nodes["thi.ng/b"].parentof.$id, "self/a"); + }); +}); diff --git a/packages/egf/test/ref.ts b/packages/egf/test/ref.ts new file mode 100644 index 0000000000..97d824c59e --- /dev/null +++ b/packages/egf/test/ref.ts @@ -0,0 +1,109 @@ +import { equiv } from "@thi.ng/equiv"; +import * as assert from "assert"; +import { parseString } from "../src"; + +const $ref = (id: string) => ({ $ref: id }); + +describe("egf #ref", () => { + it("resolve w/ prefix", () => { + const db = parseString( + ` +@prefix thi: thi.ng/ +thi:a + partof #ref thi:b + knows #ref alt.thi.ng/c + +@prefix thi: alt.thi.ng/ +thi:c + diff #ref thi:a +`, + { opts: { prefixes: true, resolve: true } } + ).nodes; + assert.deepEqual(db["thi.ng/a"].partof, { $id: "thi.ng/b" }); + assert.equal(db["thi.ng/a"].knows.$id, "alt.thi.ng/c"); + assert.equal(db["alt.thi.ng/c"].diff.$id, "alt.thi.ng/a"); + }); + + it("resolve circular", () => { + const db = parseString( + ` +a + knows #ref b + +b + knows #ref a +`, + { opts: { resolve: true } } + ).nodes; + assert.equal(db.a.knows.$id, "b"); + assert.equal(db.b.knows.$id, "a"); + }); + + it("ref array item (unresolved)", () => { + assert( + equiv( + parseString( + ` +a + knows #ref b + knows #ref c + knows #ref d + +b + name bb + +c + name cc + +d + name dd +` + ).nodes, + { + a: { $id: "a", knows: [$ref("b"), $ref("c"), $ref("d")] }, + b: { $id: "b", name: "bb" }, + c: { $id: "c", name: "cc" }, + d: { $id: "d", name: "dd" }, + } + ) + ); + }); + + it("ref array item (resolved)", () => { + assert( + equiv( + parseString( + ` +a + knows #ref b + knows #ref c + knows #ref d + +b + name bb + +c + name cc + +d + name dd +`, + { opts: { resolve: true } } + ).nodes, + { + a: { + $id: "a", + knows: [ + { $id: "b", name: "bb" }, + { $id: "c", name: "cc" }, + { $id: "d", name: "dd" }, + ], + }, + b: { $id: "b", name: "bb" }, + c: { $id: "c", name: "cc" }, + d: { $id: "d", name: "dd" }, + } + ) + ); + }); +}); diff --git a/packages/egf/test/tsconfig.json b/packages/egf/test/tsconfig.json new file mode 100644 index 0000000000..f6e63560dd --- /dev/null +++ b/packages/egf/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs" + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} diff --git a/packages/egf/tpl.readme.md b/packages/egf/tpl.readme.md new file mode 100644 index 0000000000..111e3201f6 --- /dev/null +++ b/packages/egf/tpl.readme.md @@ -0,0 +1,198 @@ +# ${pkg.banner} + +[![npm version](https://img.shields.io/npm/v/${pkg.name}.svg)](https://www.npmjs.com/package/${pkg.name}) +![npm downloads](https://img.shields.io/npm/dm/${pkg.name}.svg) +[![Twitter Follow](https://img.shields.io/twitter/follow/thing_umbrella.svg?style=flat-square&label=twitter)](https://twitter.com/thing_umbrella) + +This project is part of the +[@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. + + + +## About + +${pkg.description} + +Striving to be both easily readable & writable for humans and machines, this +line based, plain text data format and package supports: + +- Definition of different types of graph based data (e.g. RDF-style or Labeled + Property Graph topologies) +- Full support for cyclic references, arbitrary order (automatic forward + declarations) +- Choice of inlining referenced nodes for direct access or via special node ref + values +- Arbitrary property values (extensible via tagged literals and custom tag + parsers a la [EDN](https://github.com/edn-format/edn)) +- Optionally prefixed node and property IDs with (also optional) auto-expansion + via declared prefixes (for [Linked + Data](https://en.wikipedia.org/wiki/Linked_data) use cases) +- Inclusion of sub-graphs from external files +- Loading of individual property values from referenced file paths +- Optionally GPG encrypted property values (where needed) +- Multi-line values +- Line comments +- Configurable parser behavior & syntax feature flags +- Hand-optimized parser, largely regexp free +- GraphViz DOT conversion + +![example graph](https://raw.githubusercontent.com/thi-ng/umbrella/feature/egf/assets/egf/egf-readme.png) + +([Source for this example graph is further below](#basic-example)) + +### Built-in tag parsers + +The following parsers for tagged property values are available by default. +Custom parsers can be registered via `registerTag()`. + +| Tag | Description | Result | +|-----------|---------------------------------------------|--------------------| +| `#base64` | Base64 encoded binary data | `Uint8Array` | +| `#date` | `Date.parse()` compatible string | `Date` | +| `#file` | File path to read value from | `string` | +| `#gpg` | Calls `gpg` to decrypt given armored string | `string` | +| `#hex` | hex 32bit int (no prefix) | `number` | +| `#json` | Arbitrary JSON value | `any` | +| `#list` | Whitespace separated list | `string[]` | +| `#num` | Floating point value | `number` | +| `#ref` | Inlines node for given ID | `{ $ref: string }` | + +**Note:** In this reference implementation, the `#file` and `#gpg` tag parsers +are only available in NodeJS. + +${status} + +${supportPackages} + +${relatedPackages} + +${blogPosts} + +## Installation + +${pkg.install} + +${pkg.size} + +## Dependencies + +${pkg.deps} + +${examples} + +## API + +${docLink} + +TODO - Full docs forthcoming... + +- [api.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Data structures & options +- [dot.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Graphviz export +- [parser.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Parser +- [tags.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Tagged value parsers + +### Basic example + +```text +; file: readme.egf + +; prefix declaration (optional feature) +@prefix thi: thi.ng/ + +; a single node/subject definition +; properties are indented +; `thi:` prefix will be expanded +thi:egf + type project + ; tagged value property (here: node ref) + part-of #ref thi:umbrella + status alpha + description Extensible Graph Format + url https://thi.ng/egf + creator #ref toxi + ; multi-line value + ; read as whitespace separated list/array (via #list) + tag #list >>> +graph +extensible +format +linked-data +<<< + +thi:umbrella + type project + url https://thi.ng/umbrella + creator #ref toxi + +toxi + type person + name Karsten Schmidt + location London + account #ref toxi@twitter + account #ref postspectacular@gh + +toxi@twitter + type account + name @toxi + url http://twitter.com/toxi + +postspectacular@gh + type account + name @postspectacular + url http://github.com/postspectacular +``` + +```ts +import { parseFile } from "@thi.ng/egf"; + +// enable prefix expansion in parser +const graph = parseFile("readme.egf", { opts: { prefixes: true } }).nodes; + +console.log(Object.keys(graph)); +// [ +// 'thi.ng/egf', +// 'thi.ng/umbrella', +// 'toxi', +// 'toxi@twitter', +// 'postspectacular@gh' +// ] + +console.log(graph.toxi); +// { +// '$id': 'toxi', +// type: 'person', +// name: 'Karsten Schmidt', +// location: 'London', +// account: [ +// { +// '$ref': 'toxi@twitter', +// deref: [Function: deref], +// equiv: [Function: equiv] +// }, +// { +// '$ref': 'postspectacular@gh', +// deref: [Function: deref], +// equiv: [Function: equiv] +// } +// ] +// } + +// in this example inlining of referenced nodes is disabled (default) +// therefore refs are encoded as objects implementing the `IDeref` interface +// to obtain the referenced node +console.log(graph.toxi.account[0].deref()); +// { +// '$id': 'toxi@twitter', +// type: 'account', +// name: '@toxi', +// url: 'http://twitter.com/toxi' +// } +``` + +## Authors + +${authors} + +## License + +© ${copyright} // ${license} diff --git a/packages/egf/tsconfig.json b/packages/egf/tsconfig.json new file mode 100644 index 0000000000..893b9979c5 --- /dev/null +++ b/packages/egf/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} From 058fb7e46afbab9abad369782c82c7ec4f3fcdb4 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Wed, 22 Jul 2020 02:47:42 +0100 Subject: [PATCH 002/106] docs(egf): update graph/readme --- assets/egf/egf-readme.png | Bin 259598 -> 0 bytes assets/egf/egf-readme2.png | Bin 0 -> 211984 bytes packages/egf/README.md | 2 +- packages/egf/tpl.readme.md | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 assets/egf/egf-readme.png create mode 100644 assets/egf/egf-readme2.png diff --git a/assets/egf/egf-readme.png b/assets/egf/egf-readme.png deleted file mode 100644 index 5ed70d3d0839a223236610db96276e4afa07f98a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 259598 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¬NKD)#iOxIgR_MXKW*kfvUI@b>DG{iDBQ3| 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%0D`DdPfH{fZN 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�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%0ANvz{v2Uh=@xj4Dw5z)57og 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

x=T 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%0D0-Yh#U(ec$@=rjmz^IR^+!PEW1_k6xNu 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

qKXzIPBNh+ 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 Date: Wed, 22 Jul 2020 02:59:49 +0100 Subject: [PATCH 003/106] docs: add WIP pkg link (egf) --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 83b2a68167..9de7451ad0 100644 --- a/README.md +++ b/README.md @@ -110,10 +110,12 @@ fairly detailed overview for contributors here: ## Projects - +feature or `develop` branches) + +- [@thi.ng/egf](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf) - Extensible Graph Format ### Fundamentals From 55b119ce497f67e939ba865c25930348aaaad380 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Wed, 22 Jul 2020 11:30:32 +0100 Subject: [PATCH 004/106] feat(egf): update tag parser handling - remove defmulti dependency - add TagParser type alias - add `tags` and `defaultTag` to ParseContext - update parseTag() and initContext() --- packages/egf/src/api.ts | 12 ++++++++++-- packages/egf/src/parser.ts | 19 +++++++++++++------ packages/egf/src/tags.ts | 22 ++++------------------ 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/packages/egf/src/api.ts b/packages/egf/src/api.ts index fdab55ce74..19a0549e7d 100644 --- a/packages/egf/src/api.ts +++ b/packages/egf/src/api.ts @@ -1,4 +1,4 @@ -import type { IDeref, ILogger } from "@thi.ng/api"; +import type { Fn3, IDeref, ILogger, IObjectOf } from "@thi.ng/api"; import { isNode } from "@thi.ng/checks"; import { unsupported } from "@thi.ng/errors"; @@ -49,7 +49,8 @@ export interface ParseOpts { */ prefixes: boolean; /** - * If true, tagged `#gpg` values will be decrypted. + * If true, tagged `#gpg` values will be decrypted. NodeJS only and requires + * GPG with all keys used to encrypt the values installed on host. * * @defaultValue false */ @@ -57,11 +58,18 @@ export interface ParseOpts { [id: string]: any; } +/** + * Function signature for tagged value parsers. + */ +export type TagParser = Fn3; + export interface ParseContext { cwd: string; file: string; prefixes: Prefixes; nodes: Nodes; + tags: IObjectOf; + defaultTag?: TagParser; opts: Partial; logger: ILogger; } diff --git a/packages/egf/src/parser.ts b/packages/egf/src/parser.ts index c15d095ede..a6a334aa94 100644 --- a/packages/egf/src/parser.ts +++ b/packages/egf/src/parser.ts @@ -1,18 +1,17 @@ import { NULL_LOGGER } from "@thi.ng/api"; import { isArray } from "@thi.ng/checks"; -import { illegalState } from "@thi.ng/errors"; +import { illegalState, unsupported } from "@thi.ng/errors"; import * as $prefixes from "@thi.ng/prefixes"; import { readFileSync } from "fs"; import { dirname, resolve as resolvePath } from "path"; -import { IS_NODE, Node, ParseContext, ParseOpts } from "./api"; -import { parseTag } from "./tags"; +import { IS_NODE, Node, ParseContext, ParseOpts, TagParser } from "./api"; +import { BUILTINS } from "./tags"; import { qualifiedID } from "./utils"; const INCLUDE = "@include "; const PREFIX = "@prefix "; const OPEN = ">>>"; const CLOSE = "<<<"; -const EOF = "unterminated value, EOF reached"; export const parse = (src: string, ctx: ParseContext) => { const lines = src.split(/\r?\n/); @@ -78,6 +77,13 @@ const parsePrefix = (line: string, ctx: ParseContext) => { illegalState(`invalid prefix decl: ${line}`); }; +const parseTag: TagParser = (tag, body, ctx) => { + const parser = ctx.tags[tag] || ctx.defaultTag; + return parser + ? parser(tag, body, ctx) + : unsupported(`missing parser for tag: ${tag}`); +}; + const parseProp = ( acc: Node, ctx: ParseContext, @@ -117,7 +123,7 @@ const parseProp = ( body += "\n" + line; } } - !closed && illegalState(EOF); + !closed && illegalState("unterminated value, EOF reached"); } else { body = body.substr(0, idx); i++; @@ -148,8 +154,9 @@ const initContext = (ctx: Partial = {}) => { return { cwd: ctx.cwd || ".", file: ctx.file || "", - pid: -1, nodes: ctx.nodes || {}, + tags: { ...BUILTINS, ...ctx.tags }, + defaultTag: ctx.defaultTag, prefixes: ctx.prefixes ? { ...ctx.prefixes } : { ...$prefixes, void: $prefixes.VOID }, diff --git a/packages/egf/src/tags.ts b/packages/egf/src/tags.ts index 152c65010c..89686e4ac2 100644 --- a/packages/egf/src/tags.ts +++ b/packages/egf/src/tags.ts @@ -1,18 +1,13 @@ -import type { Fn3 } from "@thi.ng/api"; -import { defmulti, DEFAULT } from "@thi.ng/defmulti"; +import type { IObjectOf } from "@thi.ng/api"; import { maybeParseFloat, maybeParseInt } from "@thi.ng/strings"; import { base64Decode } from "@thi.ng/transducers-binary"; import { execSync } from "child_process"; import { readFileSync } from "fs"; import { resolve as resolvePath } from "path"; -import { IS_NODE, NODE_ONLY, ParseContext } from "./api"; +import { IS_NODE, NODE_ONLY, TagParser } from "./api"; import { qualifiedID } from "./utils"; -export const parseTag = defmulti( - (tag) => tag -); - -parseTag.addAll({ +export const BUILTINS: IObjectOf = { base64: IS_NODE ? (_, body) => { const buf = Buffer.from(body, "base64"); @@ -55,13 +50,4 @@ parseTag.addAll({ }, }; }, -}); - -export const registerTag = ( - tag: string, - fn: Fn3 -) => parseTag.add(tag, fn); - -export const enableUnknownTags = () => parseTag.add(DEFAULT, (_, x) => x); - -export const disableUnknownTags = () => parseTag.remove(DEFAULT); +}; From 5aca174cd4ceef7c03c08cb27d736eb5dd1fd35c Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Wed, 22 Jul 2020 13:25:35 +0100 Subject: [PATCH 005/106] feat(egf): add <> escape hatch for prefix IDs --- packages/egf/src/tags.ts | 2 +- packages/egf/src/utils.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/egf/src/tags.ts b/packages/egf/src/tags.ts index 89686e4ac2..fbf578401e 100644 --- a/packages/egf/src/tags.ts +++ b/packages/egf/src/tags.ts @@ -37,7 +37,7 @@ export const BUILTINS: IObjectOf = { list: (_, body) => body.split(/[\n\r\t ]+/g), num: (_, body) => maybeParseFloat(body, 0), ref: (_, id, ctx) => { - id = ctx.opts.prefixes ? qualifiedID(ctx.prefixes, id) : id; + ctx.opts.prefixes && (id = qualifiedID(ctx.prefixes, id)); return ctx.opts.resolve ? ctx.nodes[id] || (ctx.nodes[id] = { $id: id }) : { diff --git a/packages/egf/src/utils.ts b/packages/egf/src/utils.ts index 1955880e4d..d57097b36d 100644 --- a/packages/egf/src/utils.ts +++ b/packages/egf/src/utils.ts @@ -7,6 +7,9 @@ export const isRef = (x: any): x is NodeRef => isPlainObject(x) && "$ref" in x; const RE_QFN = /^([a-z0-9-_$]*):([a-z0-9-_$.+]+)$/i; export const qualifiedID = (prefixes: Prefixes, id: string) => { + if (id[0] === "<" && id[id.length - 1] === ">") { + return id.substring(1, id.length - 1); + } if (id.indexOf(":") !== -1) { const match = RE_QFN.exec(id); if (match) { From 73bef03bd58a013063fa882c2407c5ec64c740f1 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Wed, 22 Jul 2020 13:26:35 +0100 Subject: [PATCH 006/106] docs(egf): update readme (add syntax docs) --- packages/egf/README.md | 229 ++++++++++++++++++++++++++++++++++++- packages/egf/tpl.readme.md | 222 ++++++++++++++++++++++++++++++++++- 2 files changed, 445 insertions(+), 6 deletions(-) diff --git a/packages/egf/README.md b/packages/egf/README.md index 7b6730d1a1..3c32ea3941 100644 --- a/packages/egf/README.md +++ b/packages/egf/README.md @@ -16,6 +16,10 @@ This project is part of the - [Dependencies](#dependencies) - [API](#api) - [Basic example](#basic-example) +- [Syntax](#syntax) + - [Node references](#node-references) + - [Prefixed IDs](#prefixed-ids) + - [Includes](#includes) - [Authors](#authors) - [License](#license) @@ -44,7 +48,7 @@ line based, plain text data format and package supports: - Line comments - Configurable parser behavior & syntax feature flags - Hand-optimized parser, largely regexp free -- GraphViz DOT conversion +- Configurable GraphViz DOT export ![example graph](https://raw.githubusercontent.com/thi-ng/umbrella/feature/egf/assets/egf/egf-readme2.png) @@ -53,7 +57,7 @@ line based, plain text data format and package supports: ### Built-in tag parsers The following parsers for tagged property values are available by default. -Custom parsers can be registered via `registerTag()`. +Custom parsers can be provided via config options. | Tag | Description | Result | |-----------|---------------------------------------------|--------------------| @@ -88,13 +92,12 @@ yarn add @thi.ng/egf ``` -Package sizes (gzipped, pre-treeshake): ESM: 2.06 KB / CJS: 2.14 KB / UMD: 2.14 KB +Package sizes (gzipped, pre-treeshake): ESM: 2.04 KB / CJS: 2.12 KB / UMD: 2.13 KB ## Dependencies - [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/api) - [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/checks) -- [@thi.ng/defmulti](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/defmulti) - [@thi.ng/dot](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/dot) - [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/errors) - [@thi.ng/prefixes](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/prefixes) @@ -210,6 +213,224 @@ console.log(graph.toxi.account[0].deref()); // } ``` +## Syntax + +EGF is a plain text format and largely line based, though supports multi-line +values. An EGF file consists of node definitions, each with zero or more +properties and their (optionally tagged) values. EGF does not prescribe any +other schema or structure and it's entirely up to the user to e.g. allow +properties themselves to be defined as nodes with their own properties, thus +allowing the definition of LPG ([Labeled Property +Graph](https://en.wikipedia.org/wiki/Graph_database#Labeled-property_graph)) +topologies as well. + +```text +; Comment line + +; First node definition +node1 + prop1 value + prop2 #tag value + prop3 <<< long, potentially +multiline +value >>> + prop4 #tag <<< tagged multi-line value >>> + +node2 + ; property comment + prop1 value +... +``` + +### Node references + +Properties with reference values (via `#ref` tag) to another node constitute +edges in the graph. + +The following graph defines two nodes with circular references between them. +Each node has a literal (string, by default) property `name` and a reference to +another node via the `#ref` tag followed by the target node ID. The order of +references is arbitrary and the parser will automatically produce forward +declarations for nodes not yet known. + +```text +alice + name Alice + knows #ref bob + +bob + name Robert + knows #ref alice +``` + +Using default parser options, this produces an object as follows. Note, the +references are encoded as objects with a `$ref` property and implement the +`IDeref` and `IEquiv` interfaces defined in the +[@thi.ng/api](https://github.com/thi-ng/umbrella/tree/develop/packages/api) +package. + +```js +{ + alice: { + '$id': 'alice', + name: 'Alice', + knows: { + '$ref': 'bob', + deref: [Function: deref], + equiv: [Function: equiv] + } + }, + bob: { + '$id': 'bob', + name: 'Robert', + knows: { + '$ref': 'alice', + deref: [Function: deref], + equiv: [Function: equiv] + } + } +} +``` + +```ts +// access bob's name via alice +graph.alice.knows.deref().name +// "Robert" +``` + +If node resolution is enabled (via the `resolve` option) in the parser, the +referenced nodes will be inlined directly and produce circular references in the +JS result object. In many cases this more desirable and fine, however will stop +the graph from being serializable to JSON (for example). + +```text +{ + alice: { + '$id': 'alice', + name: 'Alice', + knows: { '$id': 'bob', name: 'Robert', knows: [Circular *1] } + }, + bob: { + '$id': 'bob', + name: 'Robert', + knows: { + '$id': 'alice', + name: 'Alice', + knows: [Circular *2] + } + } +} +``` + +### Prefixed IDs + +To enable namespacing and simplify re-use of existing data vocabularies, we're +borrowing from existing Linked Data formats & tooling to allow node and property +IDs to be defined in a `prefix:name` format alongside `@prefix` declarations. +These IDs will be expanded during parsing and usually form complete URIs, but +could be any string. The various (50+) commonly used Linked Data vocabulary +prefixes bundled in +[@thi.ng/prefixes](https://github.com/thi-ng/umbrella/tree/develop/packages/prefixes) +are available by default, though can be overridden, of course... + +```text +; prefix declaration +@prefix thi: http://thi.ng/ + +thi:toxi + rdf:type #ref foaf:person +``` + +Result: + +```js +{ + 'thi.ng/toxi': { + '$id': 'thi.ng/toxi', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { + '$id': 'http://xmlns.com/foaf/0.1/person' + } + }, + 'http://xmlns.com/foaf/0.1/person': { + '$id': 'http://xmlns.com/foaf/0.1/person' + } +} +``` + +### Includes + +Currently in NodeJS only, external graph definitions can be included in the main +graph via the `@include` directive. Any `@prefix` declarations in the included +file will only be available in that file, however will inherit any pre-existing +prefixes declared in the main file. + +Relative file paths will be relative to the path of the currently processed +file: + +```text + |- include + | |- sub1.egf + | |- sub2.egf + |- main.egf +``` + +(These examples make use of the [schema.org](https://schema.org) ontology) + +```text +; main.egf +; declare an empty prefix +@prefix : http://thi.ng/ + +@include include/sub1.egf + +; use empty prefix for this node +:toxi + rdf:type #ref schema:Person +``` + +```text +; sub1.egf +@include sub2.egf + +:sub1.egf + rdf:type #ref schema:Dataset + schema:dateCreated #date 2020-07-19 +``` + +```text +; sub2.egf + +:sub2.egf + rdf:type #ref schema:Dataset + schema:creator #ref :toxi +``` + +Parsing the `main.egf` file (with node resolution/inlining) produces: + +```js +{ + 'http://thi.ng/sub2.egf': { + '$id': 'http://thi.ng/sub2.egf', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Dataset' }, + 'http://schema.org/creator': { + '$id': 'http://thi.ng/toxi', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Person' } + } + }, + 'http://schema.org/Dataset': { '$id': 'http://schema.org/Dataset' }, + 'http://thi.ng/toxi': { + '$id': 'http://thi.ng/toxi', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Person' } + }, + 'http://thi.ng/sub1.egf': { + '$id': 'http://thi.ng/sub1.egf', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Dataset' }, + 'http://schema.org/dateCreated': 2020-07-19T00:00:00.000Z + }, + 'http://schema.org/Person': { '$id': 'http://schema.org/Person' } +} +``` + ## Authors Karsten Schmidt diff --git a/packages/egf/tpl.readme.md b/packages/egf/tpl.readme.md index 70dd9e5e43..22891ad519 100644 --- a/packages/egf/tpl.readme.md +++ b/packages/egf/tpl.readme.md @@ -34,7 +34,7 @@ line based, plain text data format and package supports: - Line comments - Configurable parser behavior & syntax feature flags - Hand-optimized parser, largely regexp free -- GraphViz DOT conversion +- Configurable GraphViz DOT export ![example graph](https://raw.githubusercontent.com/thi-ng/umbrella/feature/egf/assets/egf/egf-readme2.png) @@ -43,7 +43,7 @@ line based, plain text data format and package supports: ### Built-in tag parsers The following parsers for tagged property values are available by default. -Custom parsers can be registered via `registerTag()`. +Custom parsers can be provided via config options. | Tag | Description | Result | |-----------|---------------------------------------------|--------------------| @@ -189,6 +189,224 @@ console.log(graph.toxi.account[0].deref()); // } ``` +## Syntax + +EGF is a plain text format and largely line based, though supports multi-line +values. An EGF file consists of node definitions, each with zero or more +properties and their (optionally tagged) values. EGF does not prescribe any +other schema or structure and it's entirely up to the user to e.g. allow +properties themselves to be defined as nodes with their own properties, thus +allowing the definition of LPG ([Labeled Property +Graph](https://en.wikipedia.org/wiki/Graph_database#Labeled-property_graph)) +topologies as well. + +```text +; Comment line + +; First node definition +node1 + prop1 value + prop2 #tag value + prop3 <<< long, potentially +multiline +value >>> + prop4 #tag <<< tagged multi-line value >>> + +node2 + ; property comment + prop1 value +... +``` + +### Node references + +Properties with reference values (via `#ref` tag) to another node constitute +edges in the graph. + +The following graph defines two nodes with circular references between them. +Each node has a literal (string, by default) property `name` and a reference to +another node via the `#ref` tag followed by the target node ID. The order of +references is arbitrary and the parser will automatically produce forward +declarations for nodes not yet known. + +```text +alice + name Alice + knows #ref bob + +bob + name Robert + knows #ref alice +``` + +Using default parser options, this produces an object as follows. Note, the +references are encoded as objects with a `$ref` property and implement the +`IDeref` and `IEquiv` interfaces defined in the +[@thi.ng/api](https://github.com/thi-ng/umbrella/tree/develop/packages/api) +package. + +```js +{ + alice: { + '$id': 'alice', + name: 'Alice', + knows: { + '$ref': 'bob', + deref: [Function: deref], + equiv: [Function: equiv] + } + }, + bob: { + '$id': 'bob', + name: 'Robert', + knows: { + '$ref': 'alice', + deref: [Function: deref], + equiv: [Function: equiv] + } + } +} +``` + +```ts +// access bob's name via alice +graph.alice.knows.deref().name +// "Robert" +``` + +If node resolution is enabled (via the `resolve` option) in the parser, the +referenced nodes will be inlined directly and produce circular references in the +JS result object. In many cases this more desirable and fine, however will stop +the graph from being serializable to JSON (for example). + +```text +{ + alice: { + '$id': 'alice', + name: 'Alice', + knows: { '$id': 'bob', name: 'Robert', knows: [Circular *1] } + }, + bob: { + '$id': 'bob', + name: 'Robert', + knows: { + '$id': 'alice', + name: 'Alice', + knows: [Circular *2] + } + } +} +``` + +### Prefixed IDs + +To enable namespacing and simplify re-use of existing data vocabularies, we're +borrowing from existing Linked Data formats & tooling to allow node and property +IDs to be defined in a `prefix:name` format alongside `@prefix` declarations. +These IDs will be expanded during parsing and usually form complete URIs, but +could be any string. The various (50+) commonly used Linked Data vocabulary +prefixes bundled in +[@thi.ng/prefixes](https://github.com/thi-ng/umbrella/tree/develop/packages/prefixes) +are available by default, though can be overridden, of course... + +```text +; prefix declaration +@prefix thi: http://thi.ng/ + +thi:toxi + rdf:type #ref foaf:person +``` + +Result: + +```js +{ + 'thi.ng/toxi': { + '$id': 'thi.ng/toxi', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { + '$id': 'http://xmlns.com/foaf/0.1/person' + } + }, + 'http://xmlns.com/foaf/0.1/person': { + '$id': 'http://xmlns.com/foaf/0.1/person' + } +} +``` + +### Includes + +Currently in NodeJS only, external graph definitions can be included in the main +graph via the `@include` directive. Any `@prefix` declarations in the included +file will only be available in that file, however will inherit any pre-existing +prefixes declared in the main file. + +Relative file paths will be relative to the path of the currently processed +file: + +```text + |- include + | |- sub1.egf + | |- sub2.egf + |- main.egf +``` + +(These examples make use of the [schema.org](https://schema.org) ontology) + +```text +; main.egf +; declare an empty prefix +@prefix : http://thi.ng/ + +@include include/sub1.egf + +; use empty prefix for this node +:toxi + rdf:type #ref schema:Person +``` + +```text +; sub1.egf +@include sub2.egf + +:sub1.egf + rdf:type #ref schema:Dataset + schema:dateCreated #date 2020-07-19 +``` + +```text +; sub2.egf + +:sub2.egf + rdf:type #ref schema:Dataset + schema:creator #ref :toxi +``` + +Parsing the `main.egf` file (with node resolution/inlining) produces: + +```js +{ + 'http://thi.ng/sub2.egf': { + '$id': 'http://thi.ng/sub2.egf', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Dataset' }, + 'http://schema.org/creator': { + '$id': 'http://thi.ng/toxi', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Person' } + } + }, + 'http://schema.org/Dataset': { '$id': 'http://schema.org/Dataset' }, + 'http://thi.ng/toxi': { + '$id': 'http://thi.ng/toxi', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Person' } + }, + 'http://thi.ng/sub1.egf': { + '$id': 'http://thi.ng/sub1.egf', + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Dataset' }, + 'http://schema.org/dateCreated': 2020-07-19T00:00:00.000Z + }, + 'http://schema.org/Person': { '$id': 'http://schema.org/Person' } +} +``` + ## Authors ${authors} From e6efb3295568cb2adbfe540c660f3f23515b6f51 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Wed, 22 Jul 2020 13:28:33 +0100 Subject: [PATCH 007/106] build(egf): update deps & pkg meta --- packages/egf/package.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/egf/package.json b/packages/egf/package.json index 07fe9ca705..9a67ba7b0c 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -44,7 +44,6 @@ "dependencies": { "@thi.ng/api": "^6.11.3", "@thi.ng/checks": "^2.7.3", - "@thi.ng/defmulti": "^1.2.20", "@thi.ng/dot": "^1.2.12", "@thi.ng/errors": "^1.2.16", "@thi.ng/prefixes": "^0.1.0", @@ -57,7 +56,13 @@ "lib" ], "keywords": [ - "ES6", + "es6", + "file format", + "graph", + "graphviz", + "linked data", + "semweb", + "tagged values", "typescript" ], "publishConfig": { From b30f9087903776d1b7ae878b84028a568488757d Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 23 Jul 2020 00:18:12 +0100 Subject: [PATCH 008/106] docs(egf): update readme & pkg meta --- packages/egf/README.md | 12 ++++++++++++ packages/egf/package.json | 6 +++++- packages/egf/tpl.readme.md | 11 +++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/egf/README.md b/packages/egf/README.md index 3c32ea3941..b54ff42f95 100644 --- a/packages/egf/README.md +++ b/packages/egf/README.md @@ -12,6 +12,7 @@ This project is part of the - [About](#about) - [Built-in tag parsers](#built-in-tag-parsers) - [Status](#status) + - [Feature ideas](#feature-ideas) - [Installation](#installation) - [Dependencies](#dependencies) - [API](#api) @@ -78,6 +79,17 @@ are only available in NodeJS. **ALPHA** - bleeding edge / work-in-progress +#### Feature ideas + +(Non-exhaustive list) + +- [ ] JSON -> EGF conversion +- [ ] Async tag parsing +- [ ] URL support for `#file` tag +- [ ] Tag declarations & tag parser import from URL (needs trust config opts) +- [ ] `#md` tag parser for markdown content +- [ ] `#gpg` fallback behavior options + ## Installation ```bash diff --git a/packages/egf/package.json b/packages/egf/package.json index 9a67ba7b0c..0342a360ad 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -28,7 +28,8 @@ "doc:readme": "ts-node -P ../../tools/tsconfig.json ../../tools/src/readme.ts", "doc:ae": "mkdir -p .ae/doc .ae/temp && node_modules/.bin/api-extractor run --local --verbose", "doc": "node_modules/.bin/typedoc --mode modules --out doc src", - "pub": "yarn build:release && yarn publish --access public" + "pub": "yarn build:release && yarn publish --access public", + "pub:wip": "yarn publish --access public --no-git-tag-version" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", @@ -56,11 +57,14 @@ "lib" ], "keywords": [ + "datastructure", "es6", "file format", "graph", "graphviz", "linked data", + "lpg", + "rdf", "semweb", "tagged values", "typescript" diff --git a/packages/egf/tpl.readme.md b/packages/egf/tpl.readme.md index 22891ad519..ebf58966c3 100644 --- a/packages/egf/tpl.readme.md +++ b/packages/egf/tpl.readme.md @@ -62,6 +62,17 @@ are only available in NodeJS. ${status} +#### Feature ideas + +(Non-exhaustive list) + +- [ ] JSON -> EGF conversion +- [ ] Async tag parsing +- [ ] URL support for `#file` tag +- [ ] Tag declarations & tag parser import from URL (needs trust config opts) +- [ ] `#md` tag parser for markdown content +- [ ] `#gpg` fallback behavior options + ${supportPackages} ${relatedPackages} From 3e726e1faee73c81ac07405b93211fb83e770d88 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 23 Jul 2020 00:19:20 +0100 Subject: [PATCH 009/106] publish(egf): 0.1.0 --- packages/egf/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/egf/package.json b/packages/egf/package.json index 0342a360ad..4bd1025aa3 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/egf", - "version": "0.0.1", + "version": "0.1.0", "description": "Extensible Graph Format", "module": "./index.js", "main": "./lib/index.js", From 553c7c0a0ff7bc9fc7f68f19a8d50ac25d511eef Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 23 Jul 2020 10:23:54 +0100 Subject: [PATCH 010/106] docs(egf): update readme --- packages/egf/README.md | 9 +++++++++ packages/egf/tpl.readme.md | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/packages/egf/README.md b/packages/egf/README.md index b54ff42f95..d56ac82511 100644 --- a/packages/egf/README.md +++ b/packages/egf/README.md @@ -18,6 +18,7 @@ This project is part of the - [API](#api) - [Basic example](#basic-example) - [Syntax](#syntax) + - [Grammar](#grammar) - [Node references](#node-references) - [Prefixed IDs](#prefixed-ids) - [Includes](#includes) @@ -79,6 +80,8 @@ are only available in NodeJS. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Begf%5D) + #### Feature ideas (Non-exhaustive list) @@ -254,6 +257,12 @@ node2 ... ``` +### Grammar + +A full grammar definition is forthcoming. In the meantime, please see a somewhat outdated older version and related comments in +[#234](https://github.com/thi-ng/umbrella/issues/234#issuecomment-662878452) for +more details. + ### Node references Properties with reference values (via `#ref` tag) to another node constitute diff --git a/packages/egf/tpl.readme.md b/packages/egf/tpl.readme.md index ebf58966c3..8ada320dcb 100644 --- a/packages/egf/tpl.readme.md +++ b/packages/egf/tpl.readme.md @@ -229,6 +229,12 @@ node2 ... ``` +### Grammar + +A full grammar definition is forthcoming. In the meantime, please see a somewhat outdated older version and related comments in +[#234](https://github.com/thi-ng/umbrella/issues/234#issuecomment-662878452) for +more details. + ### Node references Properties with reference values (via `#ref` tag) to another node constitute From 1fc984c0585c8de0c76aac882c322af82aa1ec0f Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 23 Jul 2020 10:24:43 +0100 Subject: [PATCH 011/106] feat(tools): update packageStatus() tpl - add link to issue tracker --- tools/src/partials/package.ts | 8 +++++++- tools/src/readme.ts | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/src/partials/package.ts b/tools/src/partials/package.ts index e283e8460b..c74d454a41 100644 --- a/tools/src/partials/package.ts +++ b/tools/src/partials/package.ts @@ -55,12 +55,18 @@ export const packageDeps = (pkg: Package) => { return deps.length ? list(deps) : "None"; }; -export const packageStatus = (id = "stable") => { +export const packageStatus = (pkgName: string, id = "stable") => { const status = CONFIG.statuses[id]; + const name = shortName(pkgName); return [ "### Status", "", `**${id.toUpperCase()}**${status ? " - " + status : ""}`, + "", + link( + "Search or submit any issues for this package", + `https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5B${name}%5D` + ), ].join("\n"); }; diff --git a/tools/src/readme.ts b/tools/src/readme.ts index acf18e5696..fd1988eb09 100644 --- a/tools/src/readme.ts +++ b/tools/src/readme.ts @@ -31,7 +31,7 @@ try { "pkg.size": packageSize, "pkg.banner": () => packageBanner(CONFIG.root.name), "pkg.install": () => packageInstallation(CONFIG.root), - status: () => packageStatus(CONFIG.meta.status), + status: () => packageStatus(CONFIG.root.name, CONFIG.meta.status), examples: () => examplesTable(CONFIG.root.name), supportPackages: () => supportPackages(CONFIG.root.name), relatedPackages: () => relatedPackages(CONFIG.meta.related), From 0dd2f2d4efe21afce28a00191ee1047a7fe462b6 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 23 Jul 2020 19:49:56 +0100 Subject: [PATCH 012/106] feat(egf): fix #235, replace #ref tag w/ `->` form - update parseProp() logic - add parseRef() - extract addProp() - update tests --- packages/egf/src/parser.ts | 37 +++++++++++++++++++++++++++++-------- packages/egf/src/tags.ts | 15 --------------- packages/egf/test/prefix.ts | 6 +++--- packages/egf/test/ref.ts | 24 ++++++++++++------------ 4 files changed, 44 insertions(+), 38 deletions(-) diff --git a/packages/egf/src/parser.ts b/packages/egf/src/parser.ts index a6a334aa94..82dac3e1f3 100644 --- a/packages/egf/src/parser.ts +++ b/packages/egf/src/parser.ts @@ -10,8 +10,6 @@ import { qualifiedID } from "./utils"; const INCLUDE = "@include "; const PREFIX = "@prefix "; -const OPEN = ">>>"; -const CLOSE = "<<<"; export const parse = (src: string, ctx: ParseContext) => { const lines = src.split(/\r?\n/); @@ -85,7 +83,7 @@ const parseTag: TagParser = (tag, body, ctx) => { }; const parseProp = ( - acc: Node, + node: Node, ctx: ParseContext, line: string, lines: string[], @@ -99,21 +97,24 @@ const parseProp = ( let tag: string | undefined; let body: string; idx++; - if (line[idx] === "#") { + if (line[idx] === "-" && line[idx + 1] === ">") { + addProp(node, key, parseRef(line.substr(idx + 2).trim(), ctx)); + return ++i; + } else if (line[idx] === "#") { const tstart = idx + 1; idx = line.indexOf(" ", tstart); tag = line.substring(tstart, idx); idx++; } - if (line.substr(idx, 3) === OPEN) { + if (line[idx] === ">" && line[idx + 1] === ">" && line[idx + 2] === ">") { body = line.substr(idx + 3); - idx = body.indexOf(CLOSE); + idx = body.indexOf("<<<"); if (idx < 0) { const n = lines.length; let closed = false; while (++i < n) { line = lines[i]; - idx = line.indexOf(CLOSE); + idx = line.indexOf("<<<"); if (idx >= 0) { body += "\n" + line.substr(0, idx); closed = true; @@ -133,13 +134,33 @@ const parseProp = ( i++; } body = body.trim(); - const val = tag ? parseTag(tag, body, ctx) : body; + addProp(node, key, tag ? parseTag(tag, body, ctx) : body); + return i; +}; + +const addProp = (acc: Node, key: string, val: any) => { const exist = acc[key]; if (exist) { isArray(exist) ? exist.push(val) : (acc[key] = [exist, val]); } else { acc[key] = val; } +}; + +const parseRef = (id: string, ctx: ParseContext) => { + ctx.opts.prefixes && (id = qualifiedID(ctx.prefixes, id)); + return ctx.opts.resolve + ? ctx.nodes[id] || (ctx.nodes[id] = { $id: id }) + : { + $ref: id, + deref() { + return ctx.nodes[id]; + }, + equiv(o: any) { + return o != null && o.$ref === this.$ref; + }, + }; +}; return i; }; diff --git a/packages/egf/src/tags.ts b/packages/egf/src/tags.ts index fbf578401e..811f9be0ac 100644 --- a/packages/egf/src/tags.ts +++ b/packages/egf/src/tags.ts @@ -5,7 +5,6 @@ import { execSync } from "child_process"; import { readFileSync } from "fs"; import { resolve as resolvePath } from "path"; import { IS_NODE, NODE_ONLY, TagParser } from "./api"; -import { qualifiedID } from "./utils"; export const BUILTINS: IObjectOf = { base64: IS_NODE @@ -36,18 +35,4 @@ export const BUILTINS: IObjectOf = { json: (_, body) => JSON.parse(body), list: (_, body) => body.split(/[\n\r\t ]+/g), num: (_, body) => maybeParseFloat(body, 0), - ref: (_, id, ctx) => { - ctx.opts.prefixes && (id = qualifiedID(ctx.prefixes, id)); - return ctx.opts.resolve - ? ctx.nodes[id] || (ctx.nodes[id] = { $id: id }) - : { - $ref: id, - deref() { - return ctx.nodes[id]; - }, - equiv(o: any) { - return o != null && o.$ref === this.$ref; - }, - }; - }, }; diff --git a/packages/egf/test/prefix.ts b/packages/egf/test/prefix.ts index a9de5fb7f1..c6be626b4d 100644 --- a/packages/egf/test/prefix.ts +++ b/packages/egf/test/prefix.ts @@ -3,7 +3,7 @@ import { ParseContext, parseString, qualifiedID } from "../src"; const $ctx: Partial = { opts: { prefixes: true } }; -describe("egf @prefix", () => { +describe("@prefix", () => { it("@prefix decl", () => { assert.throws(() => parseString(`@prefix :`, $ctx), "1"); assert.throws(() => parseString(`@prefix : `, $ctx), "2"); @@ -29,10 +29,10 @@ describe("egf @prefix", () => { @prefix : self/ @prefix thi: thi.ng/ :a - partof #ref thi:b + partof -> thi:b thi:b - parentof #ref :a + parentof -> :a `, { opts: { prefixes: true, resolve: true } } ); diff --git a/packages/egf/test/ref.ts b/packages/egf/test/ref.ts index 97d824c59e..70dacc3843 100644 --- a/packages/egf/test/ref.ts +++ b/packages/egf/test/ref.ts @@ -4,18 +4,18 @@ import { parseString } from "../src"; const $ref = (id: string) => ({ $ref: id }); -describe("egf #ref", () => { +describe("refs", () => { it("resolve w/ prefix", () => { const db = parseString( ` @prefix thi: thi.ng/ thi:a - partof #ref thi:b - knows #ref alt.thi.ng/c + partof -> thi:b + knows -> alt.thi.ng/c @prefix thi: alt.thi.ng/ thi:c - diff #ref thi:a + diff -> thi:a `, { opts: { prefixes: true, resolve: true } } ).nodes; @@ -28,10 +28,10 @@ thi:c const db = parseString( ` a - knows #ref b + knows -> b b - knows #ref a + knows -> a `, { opts: { resolve: true } } ).nodes; @@ -45,9 +45,9 @@ b parseString( ` a - knows #ref b - knows #ref c - knows #ref d + knows -> b + knows -> c + knows -> d b name bb @@ -75,9 +75,9 @@ d parseString( ` a - knows #ref b - knows #ref c - knows #ref d + knows -> b + knows -> c + knows -> d b name bb From 634a118e2b612d5979fca7b897ed3d8bf512f28b Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 23 Jul 2020 20:05:55 +0100 Subject: [PATCH 013/106] feat(egf): add prune option & pruneNodes() --- packages/egf/src/api.ts | 12 ++++++++++++ packages/egf/src/parser.ts | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/egf/src/api.ts b/packages/egf/src/api.ts index 19a0549e7d..729b53384f 100644 --- a/packages/egf/src/api.ts +++ b/packages/egf/src/api.ts @@ -48,6 +48,18 @@ export interface ParseOpts { * @defaultValue false */ prefixes: boolean; + /** + * Only used if `resolve` option is enabled. If true, nodes with only the + * reserved `$id` property (and no other user defined properties) will be + * removed from the graph after parsing is complete. + * + * Such nodes are usually only indirectly created through forward node + * references and they're only removed as top-level items in the result + * graph object. Any references from other nodes will remain intact. + * + * @defaultValue false + */ + prune: boolean; /** * If true, tagged `#gpg` values will be decrypted. NodeJS only and requires * GPG with all keys used to encrypt the values installed on host. diff --git a/packages/egf/src/parser.ts b/packages/egf/src/parser.ts index 82dac3e1f3..760ee1d458 100644 --- a/packages/egf/src/parser.ts +++ b/packages/egf/src/parser.ts @@ -41,6 +41,7 @@ export const parse = (src: string, ctx: ParseContext) => { } else illegalState(`expected property or comment @ line: ${i}`); } } + ctx.opts.resolve && ctx.opts.prune && pruneNodes(ctx); return ctx; }; @@ -51,6 +52,7 @@ const parseInclude = (line: string, ctx: ParseContext) => { ...ctx, cwd: dirname(ctx.file), prefixes: { ...ctx.prefixes }, + opts: { ...ctx.opts, prune: false }, }); } else { ctx.logger.debug("skipping include:", path); @@ -161,14 +163,23 @@ const parseRef = (id: string, ctx: ParseContext) => { }, }; }; - return i; + +const pruneNodes = ({ nodes, logger }: ParseContext) => { + for (let id in nodes) { + const keys = Object.keys(nodes[id]); + if (keys.length === 1 && keys[0] === "$id") { + logger.debug("pruning node:", id); + delete nodes[id]; + } + } }; const initContext = (ctx: Partial = {}) => { const opts = { + decrypt: false, includes: true, prefixes: false, - decrypt: false, + prune: false, resolve: false, ...ctx.opts, }; From 41a70eeaada5b91d7507a52b6b45083548002cda Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 23 Jul 2020 20:07:27 +0100 Subject: [PATCH 014/106] feat(egf): update DOT export prop filter - replace w/ `filter` predicate --- packages/egf/src/dot.ts | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/egf/src/dot.ts b/packages/egf/src/dot.ts index ae2d9b927e..7f0f05b828 100644 --- a/packages/egf/src/dot.ts +++ b/packages/egf/src/dot.ts @@ -1,28 +1,31 @@ -import type { IObjectOf } from "@thi.ng/api"; +import type { Fn2, IObjectOf } from "@thi.ng/api"; import { isArray } from "@thi.ng/checks"; -import { Edge, GraphAttribs, Node, serializeGraph } from "@thi.ng/dot"; -import type { Nodes } from "./api"; -import { isRef } from "./utils"; +import { Edge, GraphAttribs, serializeGraph } from "@thi.ng/dot"; import { slugify } from "@thi.ng/strings"; +import type { Node, Nodes } from "./api"; +import { isRef } from "./utils"; export interface GraphvizOpts { - onlyRefs: boolean; - ignore: Iterable; + /** + * Predicate function called for each property of each node. If the function + * returns false, no edge will be created for that property. + */ + filter: Fn2; attribs: Partial; } export const toDot = (graph: Nodes, opts: Partial) => { - opts = { onlyRefs: true, ...opts }; const nodes: IObjectOf> = {}; const edges: Edge[] = []; - const ignore = new Set(opts.ignore); + const filter = opts.filter || (() => true); const addEdge = (src: string, prop: string, val: any) => { if (isRef(val)) { edges.push({ src, dest: val.$ref, label: prop }); } else if (val.$id) { edges.push({ src, dest: val.$id, label: prop }); - } else if (!opts.onlyRefs) { + } else { + // FIXME hash string const id = `lit-${slugify(String(val))}`; nodes[id] = { label: String(val).replace(/\n/g, "\\n") }; edges.push({ src, dest: id, label: prop }); @@ -32,12 +35,10 @@ export const toDot = (graph: Nodes, opts: Partial) => { Object.entries(graph).forEach(([id, node]) => { nodes[id] = { label: node.name || node.$id }; Object.entries(node).forEach(([prop, val]) => { - if (ignore.has(prop)) return; - if (isArray(val)) { - val.forEach((v) => addEdge(id, prop, v)); - } else { - addEdge(id, prop, val); - } + if (!filter(prop, node)) return; + isArray(val) + ? val.forEach((v) => addEdge(id, prop, v)) + : addEdge(id, prop, val); }); }); From bc2e8fcba4dab94e39a2262813b37dcc893b5128 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 23 Jul 2020 20:07:45 +0100 Subject: [PATCH 015/106] docs(egf): update readme --- packages/egf/README.md | 99 ++++++++++++++++++++------------------ packages/egf/tpl.readme.md | 97 +++++++++++++++++++------------------ 2 files changed, 101 insertions(+), 95 deletions(-) diff --git a/packages/egf/README.md b/packages/egf/README.md index d56ac82511..48f7359881 100644 --- a/packages/egf/README.md +++ b/packages/egf/README.md @@ -61,17 +61,16 @@ line based, plain text data format and package supports: The following parsers for tagged property values are available by default. Custom parsers can be provided via config options. -| Tag | Description | Result | -|-----------|---------------------------------------------|--------------------| -| `#base64` | Base64 encoded binary data | `Uint8Array` | -| `#date` | `Date.parse()` compatible string | `Date` | -| `#file` | File path to read value from | `string` | -| `#gpg` | Calls `gpg` to decrypt given armored string | `string` | -| `#hex` | hex 32bit int (no prefix) | `number` | -| `#json` | Arbitrary JSON value | `any` | -| `#list` | Whitespace separated list | `string[]` | -| `#num` | Floating point value | `number` | -| `#ref` | Inlines node for given ID | `{ $ref: string }` | +| Tag | Description | Result | +|-----------|-------------------------------------------------|--------------| +| `#base64` | Base64 encoded binary data | `Uint8Array` | +| `#date` | `Date.parse()` compatible string (e.g. ISO8601) | `Date` | +| `#file` | File path to read value from | `string` | +| `#gpg` | Calls `gpg` to decrypt given armored string | `string` | +| `#hex` | hex 32bit int (no prefix) | `number` | +| `#json` | Arbitrary JSON value | `any` | +| `#list` | Whitespace separated list | `string[]` | +| `#num` | Floating point value | `number` | **Note:** In this reference implementation, the `#file` and `#gpg` tag parsers are only available in NodeJS. @@ -107,7 +106,7 @@ yarn add @thi.ng/egf ``` -Package sizes (gzipped, pre-treeshake): ESM: 2.04 KB / CJS: 2.12 KB / UMD: 2.13 KB +Package sizes (gzipped, pre-treeshake): ESM: 2.14 KB / CJS: 2.21 KB / UMD: 2.23 KB ## Dependencies @@ -123,12 +122,13 @@ Package sizes (gzipped, pre-treeshake): ESM: 2.04 KB / CJS: 2.12 KB / UMD: 2.13 [Generated API docs](https://docs.thi.ng/umbrella/egf/) -TODO - Full docs forthcoming... +**TODO - Full docs forthcoming...** - [api.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Data structures & options -- [dot.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Graphviz export -- [parser.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Parser -- [tags.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Tagged value parsers +- [dot.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/dot.ts) - Graphviz export (via + [@thi.ng/dot](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/)) +- [parser.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/parser.ts) - Main parser +- [tags.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/tags.ts) - Tagged value parsers ### Basic example @@ -144,11 +144,11 @@ TODO - Full docs forthcoming... thi:egf type project ; tagged value property (here: node ref) - part-of #ref thi:umbrella + part-of -> thi:umbrella status alpha description Extensible Graph Format url https://thi.ng/egf - creator #ref toxi + creator -> toxi ; multi-line value ; read as whitespace separated list/array (via #list) tag #list >>> @@ -161,14 +161,14 @@ linked-data thi:umbrella type project url https://thi.ng/umbrella - creator #ref toxi + creator -> toxi toxi type person name Karsten Schmidt location London - account #ref toxi@twitter - account #ref postspectacular@gh + account -> toxi@twitter + account -> postspectacular@gh toxi@twitter type account @@ -230,9 +230,9 @@ console.log(graph.toxi.account[0].deref()); ## Syntax -EGF is a plain text format and largely line based, though supports multi-line -values. An EGF file consists of node definitions, each with zero or more -properties and their (optionally tagged) values. EGF does not prescribe any +EGF is a UTF-8 plain text format and largely line based, though supports +multi-line values. An EGF file consists of node definitions, each with zero or +more properties and their (optionally tagged) values. EGF does not prescribe any other schema or structure and it's entirely up to the user to e.g. allow properties themselves to be defined as nodes with their own properties, thus allowing the definition of LPG ([Labeled Property @@ -244,12 +244,16 @@ topologies as well. ; First node definition node1 + ; property with string value prop1 value - prop2 #tag value - prop3 <<< long, potentially + ; property with reference to another node + prop2 -> node2 + ; property with tagged value + prop3 #tag value + prop4 <<< long, potentially multiline value >>> - prop4 #tag <<< tagged multi-line value >>> + prop5 #tag <<< tagged multi-line value >>> node2 ; property comment @@ -259,29 +263,30 @@ node2 ### Grammar -A full grammar definition is forthcoming. In the meantime, please see a somewhat outdated older version and related comments in +A full grammar definition is forthcoming. In the meantime, please see a somewhat +outdated older version and related comments in [#234](https://github.com/thi-ng/umbrella/issues/234#issuecomment-662878452) for more details. ### Node references -Properties with reference values (via `#ref` tag) to another node constitute -edges in the graph. +Properties with reference values to another node constitute edges in the graph. +References are encoded via `property -> nodeid`. The following graph defines two nodes with circular references between them. -Each node has a literal (string, by default) property `name` and a reference to -another node via the `#ref` tag followed by the target node ID. The order of -references is arbitrary and the parser will automatically produce forward -declarations for nodes not yet known. +Each node has a literal (string, by default) property `name` and a reference +property `knows` to another node (via its ID). The order of references is +arbitrary and the parser will automatically produce forward declarations for +nodes not yet known. ```text alice name Alice - knows #ref bob + knows -> bob bob name Robert - knows #ref alice + knows -> alice ``` Using default parser options, this produces an object as follows. Note, the @@ -348,9 +353,9 @@ the graph from being serializable to JSON (for example). To enable namespacing and simplify re-use of existing data vocabularies, we're borrowing from existing Linked Data formats & tooling to allow node and property IDs to be defined in a `prefix:name` format alongside `@prefix` declarations. -These IDs will be expanded during parsing and usually form complete URIs, but -could be any string. The various (50+) commonly used Linked Data vocabulary -prefixes bundled in +Such prefix IDs will be expanded during parsing and usually form complete URIs, +but could expand to any string. The various (50+) commonly used Linked Data +vocabulary prefixes bundled in [@thi.ng/prefixes](https://github.com/thi-ng/umbrella/tree/develop/packages/prefixes) are available by default, though can be overridden, of course... @@ -359,7 +364,7 @@ are available by default, though can be overridden, of course... @prefix thi: http://thi.ng/ thi:toxi - rdf:type #ref foaf:person + rdf:type -> foaf:person ``` Result: @@ -406,7 +411,7 @@ file: ; use empty prefix for this node :toxi - rdf:type #ref schema:Person + rdf:type -> schema:Person ``` ```text @@ -414,7 +419,7 @@ file: @include sub2.egf :sub1.egf - rdf:type #ref schema:Dataset + rdf:type -> schema:Dataset schema:dateCreated #date 2020-07-19 ``` @@ -422,11 +427,11 @@ file: ; sub2.egf :sub2.egf - rdf:type #ref schema:Dataset - schema:creator #ref :toxi + rdf:type -> schema:Dataset + schema:creator -> :toxi ``` -Parsing the `main.egf` file (with node resolution/inlining) produces: +Parsing the `main.egf` file (with node resolution/inlining and pruning) produces: ```js { @@ -438,7 +443,6 @@ Parsing the `main.egf` file (with node resolution/inlining) produces: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Person' } } }, - 'http://schema.org/Dataset': { '$id': 'http://schema.org/Dataset' }, 'http://thi.ng/toxi': { '$id': 'http://thi.ng/toxi', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Person' } @@ -447,8 +451,7 @@ Parsing the `main.egf` file (with node resolution/inlining) produces: '$id': 'http://thi.ng/sub1.egf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Dataset' }, 'http://schema.org/dateCreated': 2020-07-19T00:00:00.000Z - }, - 'http://schema.org/Person': { '$id': 'http://schema.org/Person' } + } } ``` diff --git a/packages/egf/tpl.readme.md b/packages/egf/tpl.readme.md index 8ada320dcb..185fa03410 100644 --- a/packages/egf/tpl.readme.md +++ b/packages/egf/tpl.readme.md @@ -45,17 +45,16 @@ line based, plain text data format and package supports: The following parsers for tagged property values are available by default. Custom parsers can be provided via config options. -| Tag | Description | Result | -|-----------|---------------------------------------------|--------------------| -| `#base64` | Base64 encoded binary data | `Uint8Array` | -| `#date` | `Date.parse()` compatible string | `Date` | -| `#file` | File path to read value from | `string` | -| `#gpg` | Calls `gpg` to decrypt given armored string | `string` | -| `#hex` | hex 32bit int (no prefix) | `number` | -| `#json` | Arbitrary JSON value | `any` | -| `#list` | Whitespace separated list | `string[]` | -| `#num` | Floating point value | `number` | -| `#ref` | Inlines node for given ID | `{ $ref: string }` | +| Tag | Description | Result | +|-----------|-------------------------------------------------|--------------| +| `#base64` | Base64 encoded binary data | `Uint8Array` | +| `#date` | `Date.parse()` compatible string (e.g. ISO8601) | `Date` | +| `#file` | File path to read value from | `string` | +| `#gpg` | Calls `gpg` to decrypt given armored string | `string` | +| `#hex` | hex 32bit int (no prefix) | `number` | +| `#json` | Arbitrary JSON value | `any` | +| `#list` | Whitespace separated list | `string[]` | +| `#num` | Floating point value | `number` | **Note:** In this reference implementation, the `#file` and `#gpg` tag parsers are only available in NodeJS. @@ -95,12 +94,13 @@ ${examples} ${docLink} -TODO - Full docs forthcoming... +**TODO - Full docs forthcoming...** - [api.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Data structures & options -- [dot.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Graphviz export -- [parser.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Parser -- [tags.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Tagged value parsers +- [dot.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/dot.ts) - Graphviz export (via + [@thi.ng/dot](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/)) +- [parser.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/parser.ts) - Main parser +- [tags.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/tags.ts) - Tagged value parsers ### Basic example @@ -116,11 +116,11 @@ TODO - Full docs forthcoming... thi:egf type project ; tagged value property (here: node ref) - part-of #ref thi:umbrella + part-of -> thi:umbrella status alpha description Extensible Graph Format url https://thi.ng/egf - creator #ref toxi + creator -> toxi ; multi-line value ; read as whitespace separated list/array (via #list) tag #list >>> @@ -133,14 +133,14 @@ linked-data thi:umbrella type project url https://thi.ng/umbrella - creator #ref toxi + creator -> toxi toxi type person name Karsten Schmidt location London - account #ref toxi@twitter - account #ref postspectacular@gh + account -> toxi@twitter + account -> postspectacular@gh toxi@twitter type account @@ -202,9 +202,9 @@ console.log(graph.toxi.account[0].deref()); ## Syntax -EGF is a plain text format and largely line based, though supports multi-line -values. An EGF file consists of node definitions, each with zero or more -properties and their (optionally tagged) values. EGF does not prescribe any +EGF is a UTF-8 plain text format and largely line based, though supports +multi-line values. An EGF file consists of node definitions, each with zero or +more properties and their (optionally tagged) values. EGF does not prescribe any other schema or structure and it's entirely up to the user to e.g. allow properties themselves to be defined as nodes with their own properties, thus allowing the definition of LPG ([Labeled Property @@ -216,12 +216,16 @@ topologies as well. ; First node definition node1 + ; property with string value prop1 value - prop2 #tag value - prop3 <<< long, potentially + ; property with reference to another node + prop2 -> node2 + ; property with tagged value + prop3 #tag value + prop4 <<< long, potentially multiline value >>> - prop4 #tag <<< tagged multi-line value >>> + prop5 #tag <<< tagged multi-line value >>> node2 ; property comment @@ -231,29 +235,30 @@ node2 ### Grammar -A full grammar definition is forthcoming. In the meantime, please see a somewhat outdated older version and related comments in +A full grammar definition is forthcoming. In the meantime, please see a somewhat +outdated older version and related comments in [#234](https://github.com/thi-ng/umbrella/issues/234#issuecomment-662878452) for more details. ### Node references -Properties with reference values (via `#ref` tag) to another node constitute -edges in the graph. +Properties with reference values to another node constitute edges in the graph. +References are encoded via `property -> nodeid`. The following graph defines two nodes with circular references between them. -Each node has a literal (string, by default) property `name` and a reference to -another node via the `#ref` tag followed by the target node ID. The order of -references is arbitrary and the parser will automatically produce forward -declarations for nodes not yet known. +Each node has a literal (string, by default) property `name` and a reference +property `knows` to another node (via its ID). The order of references is +arbitrary and the parser will automatically produce forward declarations for +nodes not yet known. ```text alice name Alice - knows #ref bob + knows -> bob bob name Robert - knows #ref alice + knows -> alice ``` Using default parser options, this produces an object as follows. Note, the @@ -320,9 +325,9 @@ the graph from being serializable to JSON (for example). To enable namespacing and simplify re-use of existing data vocabularies, we're borrowing from existing Linked Data formats & tooling to allow node and property IDs to be defined in a `prefix:name` format alongside `@prefix` declarations. -These IDs will be expanded during parsing and usually form complete URIs, but -could be any string. The various (50+) commonly used Linked Data vocabulary -prefixes bundled in +Such prefix IDs will be expanded during parsing and usually form complete URIs, +but could expand to any string. The various (50+) commonly used Linked Data +vocabulary prefixes bundled in [@thi.ng/prefixes](https://github.com/thi-ng/umbrella/tree/develop/packages/prefixes) are available by default, though can be overridden, of course... @@ -331,7 +336,7 @@ are available by default, though can be overridden, of course... @prefix thi: http://thi.ng/ thi:toxi - rdf:type #ref foaf:person + rdf:type -> foaf:person ``` Result: @@ -378,7 +383,7 @@ file: ; use empty prefix for this node :toxi - rdf:type #ref schema:Person + rdf:type -> schema:Person ``` ```text @@ -386,7 +391,7 @@ file: @include sub2.egf :sub1.egf - rdf:type #ref schema:Dataset + rdf:type -> schema:Dataset schema:dateCreated #date 2020-07-19 ``` @@ -394,11 +399,11 @@ file: ; sub2.egf :sub2.egf - rdf:type #ref schema:Dataset - schema:creator #ref :toxi + rdf:type -> schema:Dataset + schema:creator -> :toxi ``` -Parsing the `main.egf` file (with node resolution/inlining) produces: +Parsing the `main.egf` file (with node resolution/inlining and pruning) produces: ```js { @@ -410,7 +415,6 @@ Parsing the `main.egf` file (with node resolution/inlining) produces: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Person' } } }, - 'http://schema.org/Dataset': { '$id': 'http://schema.org/Dataset' }, 'http://thi.ng/toxi': { '$id': 'http://thi.ng/toxi', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Person' } @@ -419,8 +423,7 @@ Parsing the `main.egf` file (with node resolution/inlining) produces: '$id': 'http://thi.ng/sub1.egf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': { '$id': 'http://schema.org/Dataset' }, 'http://schema.org/dateCreated': 2020-07-19T00:00:00.000Z - }, - 'http://schema.org/Person': { '$id': 'http://schema.org/Person' } + } } ``` From eb4d7d138524fca7421c414a743824ae40807338 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 24 Jul 2020 01:23:00 +0100 Subject: [PATCH 016/106] feat(egf): add include cycle breaker, prop merge logic - related to #237: merging repeated props into an array now also works if the first prop value already is an array (e.g. via #list). adding a per-noder and per-prop value counter/index to `ParseContext` to keep track of number values assigned - also adding `files` array of already processes files to context, in order to be able to break include cycles (file A -> B -> C -> A...) --- packages/egf/src/api.ts | 2 ++ packages/egf/src/parser.ts | 32 +++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/packages/egf/src/api.ts b/packages/egf/src/api.ts index 729b53384f..cb4330a1ab 100644 --- a/packages/egf/src/api.ts +++ b/packages/egf/src/api.ts @@ -78,8 +78,10 @@ export type TagParser = Fn3; export interface ParseContext { cwd: string; file: string; + files: string[]; prefixes: Prefixes; nodes: Nodes; + index: IObjectOf; tags: IObjectOf; defaultTag?: TagParser; opts: Partial; diff --git a/packages/egf/src/parser.ts b/packages/egf/src/parser.ts index 760ee1d458..836a6ce9ed 100644 --- a/packages/egf/src/parser.ts +++ b/packages/egf/src/parser.ts @@ -1,5 +1,4 @@ -import { NULL_LOGGER } from "@thi.ng/api"; -import { isArray } from "@thi.ng/checks"; +import { IObjectOf, NULL_LOGGER } from "@thi.ng/api"; import { illegalState, unsupported } from "@thi.ng/errors"; import * as $prefixes from "@thi.ng/prefixes"; import { readFileSync } from "fs"; @@ -100,7 +99,12 @@ const parseProp = ( let body: string; idx++; if (line[idx] === "-" && line[idx + 1] === ">") { - addProp(node, key, parseRef(line.substr(idx + 2).trim(), ctx)); + addProp( + ctx.index, + node, + key, + parseRef(line.substr(idx + 2).trim(), ctx) + ); return ++i; } else if (line[idx] === "#") { const tstart = idx + 1; @@ -136,16 +140,23 @@ const parseProp = ( i++; } body = body.trim(); - addProp(node, key, tag ? parseTag(tag, body, ctx) : body); + addProp(ctx.index, node, key, tag ? parseTag(tag, body, ctx) : body); return i; }; -const addProp = (acc: Node, key: string, val: any) => { +const addProp = ( + index: IObjectOf, + acc: Node, + key: string, + val: any +) => { const exist = acc[key]; - if (exist) { - isArray(exist) ? exist.push(val) : (acc[key] = [exist, val]); + const id = acc.$id + "~" + key; + if (exist !== undefined) { + ++index[id] > 2 ? exist.push(val) : (acc[key] = [exist, val]); } else { acc[key] = val; + index[id] = 1; } }; @@ -186,7 +197,9 @@ const initContext = (ctx: Partial = {}) => { return { cwd: ctx.cwd || ".", file: ctx.file || "", + files: ctx.files || [], nodes: ctx.nodes || {}, + index: ctx.index || {}, tags: { ...BUILTINS, ...ctx.tags }, defaultTag: ctx.defaultTag, prefixes: ctx.prefixes @@ -200,6 +213,11 @@ const initContext = (ctx: Partial = {}) => { export const parseFile = (path: string, ctx?: Partial) => { const $ctx = initContext(ctx); $ctx.file = path = resolvePath($ctx.cwd, path); + if ($ctx.files.includes(path)) { + $ctx.logger.warn("file already processed, skipping:", path); + return $ctx; + } + $ctx.files.push(path); $ctx.logger.debug("loading file:", path); return parse(readFileSync(path).toString(), $ctx); }; From 246c058ec53301f8bd283a16dabd6a4a004c07d1 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 24 Jul 2020 21:52:03 +0100 Subject: [PATCH 017/106] refactor(egf): simplify base64 tag impl for nodejs --- packages/egf/src/tags.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/egf/src/tags.ts b/packages/egf/src/tags.ts index 811f9be0ac..ddee8c3e8e 100644 --- a/packages/egf/src/tags.ts +++ b/packages/egf/src/tags.ts @@ -8,10 +8,7 @@ import { IS_NODE, NODE_ONLY, TagParser } from "./api"; export const BUILTINS: IObjectOf = { base64: IS_NODE - ? (_, body) => { - const buf = Buffer.from(body, "base64"); - return new Uint8Array(buf.buffer, 0, buf.length); - } + ? (_, body) => Buffer.from(body, "base64") : (_, body) => new Uint8Array([...base64Decode(body)]), date: (_, body) => new Date(Date.parse(body)), file: (_, path, ctx) => { From ed6d3a8d0e7140ed12a5948057f736aa634ca7f6 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 24 Jul 2020 21:55:47 +0100 Subject: [PATCH 018/106] feat(egf): add toEGF() implementation - add IToEGFConvert interface - add toEGF(), toEGFNode(), toEGFProp() - add defPrefixer() HOF for reverse op of qualifiedID() - add isNode() & isToEGF() predicates - add thi.ng/associative dep --- packages/egf/package.json | 1 + packages/egf/src/api.ts | 8 +++- packages/egf/src/convert.ts | 86 +++++++++++++++++++++++++++++++++++++ packages/egf/src/index.ts | 1 + packages/egf/src/utils.ts | 27 +++++++++++- 5 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 packages/egf/src/convert.ts diff --git a/packages/egf/package.json b/packages/egf/package.json index 4bd1025aa3..4902e7552f 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -44,6 +44,7 @@ }, "dependencies": { "@thi.ng/api": "^6.11.3", + "@thi.ng/associative": "^4.5.1", "@thi.ng/checks": "^2.7.3", "@thi.ng/dot": "^1.2.12", "@thi.ng/errors": "^1.2.16", diff --git a/packages/egf/src/api.ts b/packages/egf/src/api.ts index cb4330a1ab..7bb6871010 100644 --- a/packages/egf/src/api.ts +++ b/packages/egf/src/api.ts @@ -1,4 +1,4 @@ -import type { Fn3, IDeref, ILogger, IObjectOf } from "@thi.ng/api"; +import type { Fn3, IDeref, IEquiv, ILogger, IObjectOf } from "@thi.ng/api"; import { isNode } from "@thi.ng/checks"; import { unsupported } from "@thi.ng/errors"; @@ -7,10 +7,14 @@ export interface Node { [id: string]: any; } -export interface NodeRef extends IDeref { +export interface NodeRef extends IDeref, IEquiv { $ref: string; } +export interface IToEGFConvert { + toEGF(): string; +} + export type Nodes = Record; export type Prefixes = Record; diff --git a/packages/egf/src/convert.ts b/packages/egf/src/convert.ts new file mode 100644 index 0000000000..d1932dc7b6 --- /dev/null +++ b/packages/egf/src/convert.ts @@ -0,0 +1,86 @@ +import type { Fn, Fn2 } from "@thi.ng/api"; +import { + isArray, + isDate, + isNumber, + isPlainObject, + isString, + isTypedArray, +} from "@thi.ng/checks"; +import * as $prefixes from "@thi.ng/prefixes"; +import { base64Encode } from "@thi.ng/transducers-binary"; +import type { Node, Prefixes } from "./api"; +import { defPrefixer, isNode, isRef, isToEGF } from "./utils"; + +export const toEGF = ( + nodes: Iterable, + prefixes?: Prefixes, + propFn?: Fn2 +) => { + prefixes = { ...$prefixes, ...prefixes }; + const { used, prefixID } = defPrefixer(prefixes); + const res: string[] = []; + for (let node of nodes) { + res.push(toEGFNode(node, prefixID, propFn), "\n"); + } + const pre: string[] = []; + for (let id of used) { + pre.push(`@prefix ${id}: ${prefixes[id]}`); + } + return pre.join("\n") + "\n\n" + res.join("\n"); +}; + +export const toEGFNode = ( + node: Node, + prefix: Fn, + propFn: Fn2 = toEGFProp +) => { + if (isToEGF(node)) return node.toEGF(); + const res: string[] = [prefix(node.$id) || node.$id]; + + const $prop = (p: string, pid: string, v: any) => + res.push( + `\t${pid} ` + + (isNode(v) + ? `-> ${prefix(v.$id) || v.$id}` + : isRef(v) + ? `-> ${prefix(v.$ref) || v.$ref}` + : isToEGF(v) + ? v.toEGF() + : propFn(p, v)) + ); + + for (let p in node) { + if (p === "$id") continue; + const pid = prefix(p) || p; + const val = node[p]; + if (isArray(val)) { + for (let v of val) { + $prop(p, pid, v); + } + } else { + $prop(p, pid, val); + } + } + return res.join("\n"); +}; + +export const toEGFProp = (_: string, x: any) => + isString(x) + ? x.indexOf("\n") >= 0 + ? multiline(x) + : x + : isNumber(x) + ? `#num ${x}` + : isDate(x) + ? `#date ${x.toISOString()}` + : isTypedArray(x) + ? "#base64 " + + multiline( + base64Encode(new Uint8Array(x.buffer, x.byteOffset, x.byteLength)) + ) + : isArray(x) || isPlainObject(x) + ? `#json ${JSON.stringify(x)}` + : x; + +const multiline = (x: any) => `>>>${x}<<<`; diff --git a/packages/egf/src/index.ts b/packages/egf/src/index.ts index 48b73925eb..306fbfe92f 100644 --- a/packages/egf/src/index.ts +++ b/packages/egf/src/index.ts @@ -1,4 +1,5 @@ export * from "./api"; +export * from "./convert"; export * from "./dot"; export * from "./parser"; export * from "./tags"; diff --git a/packages/egf/src/utils.ts b/packages/egf/src/utils.ts index d57097b36d..c6d0ab0b3b 100644 --- a/packages/egf/src/utils.ts +++ b/packages/egf/src/utils.ts @@ -1,9 +1,15 @@ -import { isPlainObject } from "@thi.ng/checks"; +import { TrieMap } from "@thi.ng/associative"; +import { implementsFunction, isPlainObject } from "@thi.ng/checks"; import { illegalArgs } from "@thi.ng/errors"; -import type { NodeRef, Prefixes } from "./api"; +import type { IToEGFConvert, Node, NodeRef, Prefixes } from "./api"; + +export const isNode = (x: any): x is Node => isPlainObject(x) && "$id" in x; export const isRef = (x: any): x is NodeRef => isPlainObject(x) && "$ref" in x; +export const isToEGF = (x: any): x is IToEGFConvert => + implementsFunction(x, "toEGF"); + const RE_QFN = /^([a-z0-9-_$]*):([a-z0-9-_$.+]+)$/i; export const qualifiedID = (prefixes: Prefixes, id: string) => { @@ -21,3 +27,20 @@ export const qualifiedID = (prefixes: Prefixes, id: string) => { } return id; }; + +export const defPrefixer = (prefixes: Prefixes) => { + const rev = new TrieMap(); + const used = new Set(); + Object.entries(prefixes).forEach(([id, url]) => rev.set(url, id)); + return { + used, + prefixID(id: string) { + const known = rev.knownPrefix(id); + if (known) { + const pre = rev.get(known)!; + used.add(pre); + return pre + ":" + id.substr(known.length); + } + }, + }; +}; From 8b8957361fc4c0efdad51fb81fa245a2aa529ad8 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 25 Jul 2020 13:53:08 +0100 Subject: [PATCH 019/106] refactor(egf): update toEGF() handling - don't use default prefixes (only those given by user) - simplify defPrefixer() - add defVocab() - update toEGFProp() - add initial test --- packages/egf/src/convert.ts | 29 +++++++++------------ packages/egf/src/utils.ts | 22 +++++++--------- packages/egf/test/serialize.ts | 46 ++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 packages/egf/test/serialize.ts diff --git a/packages/egf/src/convert.ts b/packages/egf/src/convert.ts index d1932dc7b6..ed406a34e1 100644 --- a/packages/egf/src/convert.ts +++ b/packages/egf/src/convert.ts @@ -7,27 +7,25 @@ import { isString, isTypedArray, } from "@thi.ng/checks"; -import * as $prefixes from "@thi.ng/prefixes"; import { base64Encode } from "@thi.ng/transducers-binary"; import type { Node, Prefixes } from "./api"; import { defPrefixer, isNode, isRef, isToEGF } from "./utils"; export const toEGF = ( nodes: Iterable, - prefixes?: Prefixes, + prefixes: Prefixes = {}, propFn?: Fn2 ) => { - prefixes = { ...$prefixes, ...prefixes }; - const { used, prefixID } = defPrefixer(prefixes); + const prefixID = defPrefixer(prefixes); const res: string[] = []; - for (let node of nodes) { - res.push(toEGFNode(node, prefixID, propFn), "\n"); + for (let id in prefixes) { + res.push(`@prefix ${id}: ${prefixes[id]}`); } - const pre: string[] = []; - for (let id of used) { - pre.push(`@prefix ${id}: ${prefixes[id]}`); + res.push(""); + for (let node of nodes) { + res.push(toEGFNode(node, prefixID, propFn), ""); } - return pre.join("\n") + "\n\n" + res.join("\n"); + return res.join("\n"); }; export const toEGFNode = ( @@ -68,19 +66,16 @@ export const toEGFNode = ( export const toEGFProp = (_: string, x: any) => isString(x) ? x.indexOf("\n") >= 0 - ? multiline(x) + ? `>>>${x}<<<` : x : isNumber(x) ? `#num ${x}` : isDate(x) ? `#date ${x.toISOString()}` : isTypedArray(x) - ? "#base64 " + - multiline( - base64Encode(new Uint8Array(x.buffer, x.byteOffset, x.byteLength)) - ) + ? `#base64 ${base64Encode( + new Uint8Array(x.buffer, x.byteOffset, x.byteLength) + )}` : isArray(x) || isPlainObject(x) ? `#json ${JSON.stringify(x)}` : x; - -const multiline = (x: any) => `>>>${x}<<<`; diff --git a/packages/egf/src/utils.ts b/packages/egf/src/utils.ts index c6d0ab0b3b..8d17ef9c96 100644 --- a/packages/egf/src/utils.ts +++ b/packages/egf/src/utils.ts @@ -29,18 +29,14 @@ export const qualifiedID = (prefixes: Prefixes, id: string) => { }; export const defPrefixer = (prefixes: Prefixes) => { - const rev = new TrieMap(); - const used = new Set(); - Object.entries(prefixes).forEach(([id, url]) => rev.set(url, id)); - return { - used, - prefixID(id: string) { - const known = rev.knownPrefix(id); - if (known) { - const pre = rev.get(known)!; - used.add(pre); - return pre + ":" + id.substr(known.length); - } - }, + const uriToID = new TrieMap(); + Object.entries(prefixes).forEach(([id, url]) => uriToID.set(url, id)); + return (uri: string) => { + const known = uriToID.knownPrefix(uri); + return known + ? uriToID.get(known)! + ":" + uri.substr(known.length) + : undefined; }; }; + +export const defVocab = (uri: string) => (name = "") => uri + name; diff --git a/packages/egf/test/serialize.ts b/packages/egf/test/serialize.ts new file mode 100644 index 0000000000..4974eb5915 --- /dev/null +++ b/packages/egf/test/serialize.ts @@ -0,0 +1,46 @@ +import * as assert from "assert"; +import { toEGF } from "../src"; +import { rdf, schema } from "@thi.ng/prefixes"; +import { writeFileSync } from "fs"; + +describe("serialize", () => { + it("basics", () => { + const res = toEGF( + [ + { + $id: "thi:egf", + "rdf:type": { $ref: "schema:SoftwareSourceCode" }, + "schema:isPartOf": { $id: "http://thi.ng/umbrella" }, + "schema:dateCreated": new Date("2020-02-16"), + }, + { + $id: "thi:umbrella", + "rdf:type": { $ref: "schema:SoftwareSourceCode" }, + "schema:programmingLanguage": "TypeScript", + }, + ], + { + thi: "http://thi.ng/", + schema, + rdf, + } + ); + writeFileSync("out.egf", res); + assert.equal( + res, + `@prefix thi: http://thi.ng/ +@prefix schema: http://schema.org/ +@prefix rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# + +thi:egf +\trdf:type -> schema:SoftwareSourceCode +\tschema:isPartOf -> thi:umbrella +\tschema:dateCreated #date 2020-02-16T00:00:00.000Z + +thi:umbrella +\trdf:type -> schema:SoftwareSourceCode +\tschema:programmingLanguage TypeScript +` + ); + }); +}); From 68af37fe7cb2062e6bdfa1b6c168d8e346f342f4 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 25 Jul 2020 13:53:54 +0100 Subject: [PATCH 020/106] refactor(egf): minor update #date parser --- packages/egf/src/tags.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/egf/src/tags.ts b/packages/egf/src/tags.ts index ddee8c3e8e..a303d89bc0 100644 --- a/packages/egf/src/tags.ts +++ b/packages/egf/src/tags.ts @@ -10,7 +10,7 @@ export const BUILTINS: IObjectOf = { base64: IS_NODE ? (_, body) => Buffer.from(body, "base64") : (_, body) => new Uint8Array([...base64Decode(body)]), - date: (_, body) => new Date(Date.parse(body)), + date: (_, body) => new Date(body), file: (_, path, ctx) => { if (IS_NODE && ctx.opts.includes) { path = resolvePath(ctx.opts.root!, path); From 3607551fd7c91183bdbc2ad5248b14fdcb2d79a3 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 25 Jul 2020 13:54:12 +0100 Subject: [PATCH 021/106] docs(egf): update readme --- packages/egf/README.md | 60 ++++++++++++++++++++++++++++++++++++-- packages/egf/tpl.readme.md | 56 +++++++++++++++++++++++++++++++++-- 2 files changed, 111 insertions(+), 5 deletions(-) diff --git a/packages/egf/README.md b/packages/egf/README.md index 48f7359881..eac38b71dd 100644 --- a/packages/egf/README.md +++ b/packages/egf/README.md @@ -22,6 +22,7 @@ This project is part of the - [Node references](#node-references) - [Prefixed IDs](#prefixed-ids) - [Includes](#includes) + - [EGF generation / serialization](#egf-generation---serialization) - [Authors](#authors) - [License](#license) @@ -70,7 +71,7 @@ Custom parsers can be provided via config options. | `#hex` | hex 32bit int (no prefix) | `number` | | `#json` | Arbitrary JSON value | `any` | | `#list` | Whitespace separated list | `string[]` | -| `#num` | Floating point value | `number` | +| `#num` | Floating point value (IEEE754) | `number` | **Note:** In this reference implementation, the `#file` and `#gpg` tag parsers are only available in NodeJS. @@ -85,7 +86,7 @@ are only available in NodeJS. (Non-exhaustive list) -- [ ] JSON -> EGF conversion +- [x] JSON -> EGF conversion - [ ] Async tag parsing - [ ] URL support for `#file` tag - [ ] Tag declarations & tag parser import from URL (needs trust config opts) @@ -106,11 +107,12 @@ yarn add @thi.ng/egf ``` -Package sizes (gzipped, pre-treeshake): ESM: 2.14 KB / CJS: 2.21 KB / UMD: 2.23 KB +Package sizes (gzipped, pre-treeshake): ESM: 2.70 KB / CJS: 2.77 KB / UMD: 2.76 KB ## Dependencies - [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/api) +- [@thi.ng/associative](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/associative) - [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/checks) - [@thi.ng/dot](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/dot) - [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/errors) @@ -455,6 +457,58 @@ Parsing the `main.egf` file (with node resolution/inlining and pruning) produces } ``` +### EGF generation / serialization + +Complying JS objects can be converted to EGF using the `toEGF()` function. This +function takes an iterable of +[Node](https://github.com/thi-ng/umbrella/blob/feature/egf/packages/egf/src/api.ts#L5) +objects, optional prefix mappings and an optional property serialization +function to deal with custom tagged values. The default property formatter +(`toEGFProp()`) handles various values for built-in tags and can be used in +combination with any additional user provided logic. + +```js +import { rdf, schema } from "@thi.ng/prefixes"; + +const res = toEGF([ + { + $id: "thi:egf", + "rdf:type": { $ref: "schema:SoftwareSourceCode" }, + "schema:isPartOf": { $id: "http://thi.ng/umbrella" }, + "schema:dateCreated": new Date("2020-02-16") + }, + { + $id: "thi:umbrella", + "rdf:type": { $ref: "schema:SoftwareSourceCode" }, + "schema:programmingLanguage": "TypeScript" + } + ], + // prefix mappings (optional) + { + thi: "http://thi.ng/", + schema, + rdf + } + // property serializer (optional) + toEGFProp +); +``` + +```text +@prefix thi: http://thi.ng/ +@prefix schema: http://schema.org/ +@prefix rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# + +thi:egf + rdf:type -> schema:SoftwareSourceCode + schema:isPartOf -> thi:umbrella + schema:dateCreated #date 2020-02-16T00:00:00.000Z + +thi:umbrella + rdf:type -> schema:SoftwareSourceCode + schema:programmingLanguage TypeScript +``` + ## Authors Karsten Schmidt diff --git a/packages/egf/tpl.readme.md b/packages/egf/tpl.readme.md index 185fa03410..209af21f21 100644 --- a/packages/egf/tpl.readme.md +++ b/packages/egf/tpl.readme.md @@ -54,7 +54,7 @@ Custom parsers can be provided via config options. | `#hex` | hex 32bit int (no prefix) | `number` | | `#json` | Arbitrary JSON value | `any` | | `#list` | Whitespace separated list | `string[]` | -| `#num` | Floating point value | `number` | +| `#num` | Floating point value (IEEE754) | `number` | **Note:** In this reference implementation, the `#file` and `#gpg` tag parsers are only available in NodeJS. @@ -65,7 +65,7 @@ ${status} (Non-exhaustive list) -- [ ] JSON -> EGF conversion +- [x] JSON -> EGF conversion - [ ] Async tag parsing - [ ] URL support for `#file` tag - [ ] Tag declarations & tag parser import from URL (needs trust config opts) @@ -427,6 +427,58 @@ Parsing the `main.egf` file (with node resolution/inlining and pruning) produces } ``` +### EGF generation / serialization + +Complying JS objects can be converted to EGF using the `toEGF()` function. This +function takes an iterable of +[Node](https://github.com/thi-ng/umbrella/blob/feature/egf/packages/egf/src/api.ts#L5) +objects, optional prefix mappings and an optional property serialization +function to deal with custom tagged values. The default property formatter +(`toEGFProp()`) handles various values for built-in tags and can be used in +combination with any additional user provided logic. + +```js +import { rdf, schema } from "@thi.ng/prefixes"; + +const res = toEGF([ + { + $id: "thi:egf", + "rdf:type": { $ref: "schema:SoftwareSourceCode" }, + "schema:isPartOf": { $id: "http://thi.ng/umbrella" }, + "schema:dateCreated": new Date("2020-02-16") + }, + { + $id: "thi:umbrella", + "rdf:type": { $ref: "schema:SoftwareSourceCode" }, + "schema:programmingLanguage": "TypeScript" + } + ], + // prefix mappings (optional) + { + thi: "http://thi.ng/", + schema, + rdf + } + // property serializer (optional) + toEGFProp +); +``` + +```text +@prefix thi: http://thi.ng/ +@prefix schema: http://schema.org/ +@prefix rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# + +thi:egf + rdf:type -> schema:SoftwareSourceCode + schema:isPartOf -> thi:umbrella + schema:dateCreated #date 2020-02-16T00:00:00.000Z + +thi:umbrella + rdf:type -> schema:SoftwareSourceCode + schema:programmingLanguage TypeScript +``` + ## Authors ${authors} From 8e946f0d73337e4762d9e1abfb92ddadd4edde5f Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 25 Jul 2020 17:19:17 +0100 Subject: [PATCH 022/106] publish(egf): 0.2.0 --- packages/egf/package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/egf/package.json b/packages/egf/package.json index 4902e7552f..ffdf3d65ed 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/egf", - "version": "0.1.0", + "version": "0.2.0", "description": "Extensible Graph Format", "module": "./index.js", "main": "./lib/index.js", @@ -44,7 +44,7 @@ }, "dependencies": { "@thi.ng/api": "^6.11.3", - "@thi.ng/associative": "^4.5.1", + "@thi.ng/associative": "^5.0.0", "@thi.ng/checks": "^2.7.3", "@thi.ng/dot": "^1.2.12", "@thi.ng/errors": "^1.2.16", @@ -63,6 +63,7 @@ "file format", "graph", "graphviz", + "json", "linked data", "lpg", "rdf", From 0e28bc5bd4b46726330f696b5fc6275ab50a557a Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 25 Jul 2020 18:04:00 +0100 Subject: [PATCH 023/106] build(egf): update deps --- packages/egf/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/egf/package.json b/packages/egf/package.json index ffdf3d65ed..b649482b7a 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -44,7 +44,7 @@ }, "dependencies": { "@thi.ng/api": "^6.11.3", - "@thi.ng/associative": "^5.0.0", + "@thi.ng/associative": "^5.0.1", "@thi.ng/checks": "^2.7.3", "@thi.ng/dot": "^1.2.12", "@thi.ng/errors": "^1.2.16", From 4c6e20ee4e3414316eeaade611e8b6a69c2ba144 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 28 Jul 2020 23:04:16 +0100 Subject: [PATCH 024/106] publish(egf): 0.2.1 --- packages/egf/README.md | 2 +- packages/egf/package.json | 27 ++++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/egf/README.md b/packages/egf/README.md index eac38b71dd..9633db5e4f 100644 --- a/packages/egf/README.md +++ b/packages/egf/README.md @@ -107,7 +107,7 @@ yarn add @thi.ng/egf ``` -Package sizes (gzipped, pre-treeshake): ESM: 2.70 KB / CJS: 2.77 KB / UMD: 2.76 KB +Package sizes (gzipped, pre-treeshake): ESM: 2.70 KB / CJS: 2.77 KB / UMD: 2.77 KB ## Dependencies diff --git a/packages/egf/package.json b/packages/egf/package.json index b649482b7a..db0fc851b4 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/egf", - "version": "0.2.0", + "version": "0.2.1", "description": "Extensible Graph Format", "module": "./index.js", "main": "./lib/index.js", @@ -33,24 +33,25 @@ }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@microsoft/api-extractor": "^7.8.0", - "@types/mocha": "^7.0.2", - "@types/node": "^14.0.1", + "@microsoft/api-extractor": "^7.9.2", + "@thi.ng/equiv": "^1.0.27", + "@types/mocha": "^8.0.0", + "@types/node": "^14.0.26", "mocha": "^8.0.1", "nyc": "^15.1.0", "ts-node": "^8.10.1", "typedoc": "^0.17.6", - "typescript": "^3.9.5" + "typescript": "^3.9.7" }, "dependencies": { - "@thi.ng/api": "^6.11.3", - "@thi.ng/associative": "^5.0.1", - "@thi.ng/checks": "^2.7.3", - "@thi.ng/dot": "^1.2.12", - "@thi.ng/errors": "^1.2.16", - "@thi.ng/prefixes": "^0.1.0", - "@thi.ng/strings": "^1.9.0", - "@thi.ng/transducers-binary": "^0.5.23" + "@thi.ng/api": "^6.12.0", + "@thi.ng/associative": "^5.0.2", + "@thi.ng/checks": "^2.7.4", + "@thi.ng/dot": "^1.2.13", + "@thi.ng/errors": "^1.2.17", + "@thi.ng/prefixes": "^0.1.1", + "@thi.ng/strings": "^1.9.1", + "@thi.ng/transducers-binary": "^0.5.24" }, "files": [ "*.js", From d5ed97ab59886dd89b287a5627afc58932820e19 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 21 Aug 2020 21:08:16 +0100 Subject: [PATCH 025/106] build(egf): update deps --- packages/egf/package.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/egf/package.json b/packages/egf/package.json index db0fc851b4..39bdb76a1d 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -34,24 +34,24 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.2", - "@thi.ng/equiv": "^1.0.27", + "@thi.ng/equiv": "^1.0.29", "@types/mocha": "^8.0.0", "@types/node": "^14.0.26", - "mocha": "^8.0.1", + "mocha": "^8.1.1", "nyc": "^15.1.0", "ts-node": "^8.10.1", - "typedoc": "^0.17.6", + "typedoc": "^0.18.0", "typescript": "^3.9.7" }, "dependencies": { - "@thi.ng/api": "^6.12.0", - "@thi.ng/associative": "^5.0.2", - "@thi.ng/checks": "^2.7.4", - "@thi.ng/dot": "^1.2.13", - "@thi.ng/errors": "^1.2.17", - "@thi.ng/prefixes": "^0.1.1", - "@thi.ng/strings": "^1.9.1", - "@thi.ng/transducers-binary": "^0.5.24" + "@thi.ng/api": "^6.12.2", + "@thi.ng/associative": "^5.0.4", + "@thi.ng/checks": "^2.7.6", + "@thi.ng/dot": "^1.2.15", + "@thi.ng/errors": "^1.2.19", + "@thi.ng/prefixes": "^0.1.3", + "@thi.ng/strings": "^1.9.4", + "@thi.ng/transducers-binary": "^0.5.27" }, "files": [ "*.js", From e7ce8f20673327489a72498af37c6c40cb0826cc Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 30 Aug 2020 12:01:45 +0100 Subject: [PATCH 026/106] publish(egf): 0.2.2, update deps --- packages/egf/package.json | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/egf/package.json b/packages/egf/package.json index 39bdb76a1d..6d1d5751b7 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/egf", - "version": "0.2.1", + "version": "0.2.2", "description": "Extensible Graph Format", "module": "./index.js", "main": "./lib/index.js", @@ -33,25 +33,25 @@ }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@microsoft/api-extractor": "^7.9.2", - "@thi.ng/equiv": "^1.0.29", - "@types/mocha": "^8.0.0", - "@types/node": "^14.0.26", - "mocha": "^8.1.1", + "@microsoft/api-extractor": "^7.9.11", + "@thi.ng/equiv": "^1.0.30", + "@types/mocha": "^8.0.3", + "@types/node": "^14.6.1", + "mocha": "^8.1.2", "nyc": "^15.1.0", - "ts-node": "^8.10.1", + "ts-node": "^9.0.0", "typedoc": "^0.18.0", - "typescript": "^3.9.7" + "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.12.2", - "@thi.ng/associative": "^5.0.4", - "@thi.ng/checks": "^2.7.6", - "@thi.ng/dot": "^1.2.15", - "@thi.ng/errors": "^1.2.19", - "@thi.ng/prefixes": "^0.1.3", - "@thi.ng/strings": "^1.9.4", - "@thi.ng/transducers-binary": "^0.5.27" + "@thi.ng/api": "^6.12.3", + "@thi.ng/associative": "^5.0.5", + "@thi.ng/checks": "^2.7.7", + "@thi.ng/dot": "^1.2.16", + "@thi.ng/errors": "^1.2.20", + "@thi.ng/prefixes": "^0.1.4", + "@thi.ng/strings": "^1.9.5", + "@thi.ng/transducers-binary": "^0.5.28" }, "files": [ "*.js", From ef9f1c00fcabfc80ef51ae20dfc8feef2abe6e9b Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 13:11:30 +0100 Subject: [PATCH 027/106] docs: updatew main readme --- README.md | 83 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 294535cf2f..c83f8eb1f7 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ > the composer of. Geared towards versatility, not any specific type of music." > — [@loganpowell](https://twitter.com/logantpowell/status/1186334119812304901) via Twitter -Mono-repository for 137+ thi.ng TypeScript/ES6 projects, a wide +Mono-repository for 138+ thi.ng TypeScript/ES6 projects, a wide collection of largely data transformation oriented packages and building blocks for: @@ -24,6 +24,13 @@ blocks for: - Reactive programming, stream / transducer based dataflow graphs / pipelines - WebWorker workflow abstractions +- 2D geometry generation, shape primitives, processing, conversion & + visualization +- Canvas abstraction & SVG conversion +- Semi-declarative WebGL 1/2 abstraction layer +- DSL for shader functions defined in TypeScript and cross-compilation + to GLSL, JS, VEX etc. +- Date/time iterators, formatters - Data structures & data transformations for wide range of use cases (list, sets, maps, joins, spatial indexing) - Immutable data handling, state containers, transacted state updates, @@ -34,17 +41,11 @@ blocks for: - PEG-style parser combinators, FSM primitives - Forth-style pointfree DSL for functional composition - S-expression parser & runtime infrastructure for custom DSL creation -- DSL for shader functions defined in TypeScript and cross-compilation - to GLSL, JS, VEX etc. -- 2D geometry generation, shape primitives, processing, conversion & - visualization - Multi-format pixel buffers, conversions, Porter-Duff alpha-blending operators - Color space/format conversions, matrix based color manipulation, cosine gradients -- Canvas abstraction & SVG conversion - Canvas-based Immediate mode GUI components -- Declarative WebGL 1/2 abstraction layer - Low-level tooling for binary data, shared memory/WASM/WebGL interop - etc. (see package overview below) @@ -119,7 +120,7 @@ fairly detailed overview for contributors here: feature or `develop` branches) - [@thi.ng/egf](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf) - Extensible Graph Format -- [@thi.ng/viz](https://github.com/thi-ng/umbrella/tree/develop/packages/viz) - Declarative, functional & multi-format data visualization toolkit +- [@thi.ng/viz](https://github.com/thi-ng/umbrella/tree/develop/packages/viz) - ### Fundamentals @@ -131,6 +132,7 @@ feature or `develop` branches) | [`@thi.ng/colored-noise`](./packages/colored-noise) | [![version](https://img.shields.io/npm/v/@thi.ng/colored-noise.svg)](https://www.npmjs.com/package/@thi.ng/colored-noise) | [changelog](./packages/colored-noise/CHANGELOG.md) | 1D colored noise generators | | [`@thi.ng/compare`](./packages/compare) | [![version](https://img.shields.io/npm/v/@thi.ng/compare.svg)](https://www.npmjs.com/package/@thi.ng/compare) | [changelog](./packages/compare/CHANGELOG.md) | Comparators | | [`@thi.ng/compose`](./packages/compose) | [![version](https://img.shields.io/npm/v/@thi.ng/compose.svg)](https://www.npmjs.com/package/@thi.ng/compose) | [changelog](./packages/compose/CHANGELOG.md) | Functional composition helpers | +| [`@thi.ng/date`](./packages/date) | [![version](https://img.shields.io/npm/v/@thi.ng/date.svg)](https://www.npmjs.com/package/@thi.ng/date) | [changelog](./packages/date/CHANGELOG.md) | Date/time iterators, formatters, rounding | | [`@thi.ng/defmulti`](./packages/defmulti) | [![version](https://img.shields.io/npm/v/@thi.ng/defmulti.svg)](https://www.npmjs.com/package/@thi.ng/defmulti) | [changelog](./packages/defmulti/CHANGELOG.md) | Dynamic multiple dispatch | | [`@thi.ng/dsp`](./packages/dsp) | [![version](https://img.shields.io/npm/v/@thi.ng/dsp.svg)](https://www.npmjs.com/package/@thi.ng/dsp) | [changelog](./packages/dsp/CHANGELOG.md) | DSP utils, oscillators | | [`@thi.ng/dual-algebra`](./packages/dual-algebra) | [![version](https://img.shields.io/npm/v/@thi.ng/dual-algebra.svg)](https://www.npmjs.com/package/@thi.ng/dual-algebra) | [changelog](./packages/dual-algebra/CHANGELOG.md) | Dual number algebra / automatic differentiation | @@ -229,38 +231,39 @@ feature or `develop` branches) ### Geometry & visualization -| Project | Version | Changelog | Description | -|---------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------|------------------------------------------| -| [`@thi.ng/color`](./packages/color) | [![version](https://img.shields.io/npm/v/@thi.ng/color.svg)](https://www.npmjs.com/package/@thi.ng/color) | [changelog](./packages/color/CHANGELOG.md) | Color conversions, gradients | -| [`@thi.ng/dgraph-dot`](./packages/dgraph-dot) | [![version](https://img.shields.io/npm/v/@thi.ng/dgraph-dot.svg)](https://www.npmjs.com/package/@thi.ng/dgraph-dot) | [changelog](./packages/dgraph-dot/CHANGELOG.md) | Dependency graph -> Graphviz | -| [`@thi.ng/dot`](./packages/dot) | [![version](https://img.shields.io/npm/v/@thi.ng/dot.svg)](https://www.npmjs.com/package/@thi.ng/dot) | [changelog](./packages/dot/CHANGELOG.md) | Graphviz DOM & export | -| [`@thi.ng/geom`](./packages/geom) | [![version](https://img.shields.io/npm/v/@thi.ng/geom.svg)](https://www.npmjs.com/package/@thi.ng/geom) | [changelog](./packages/geom/CHANGELOG.md) | 2D only geometry types & ops | -| [`@thi.ng/geom-accel`](./packages/geom-accel) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-accel.svg)](https://www.npmjs.com/package/@thi.ng/geom-accel) | [changelog](./packages/geom-accel/CHANGELOG.md) | Spatial indexing data structures | -| [`@thi.ng/geom-api`](./packages/geom-api) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-api.svg)](https://www.npmjs.com/package/@thi.ng/geom-api) | [changelog](./packages/geom-api/CHANGELOG.md) | Shared types & interfaces | -| [`@thi.ng/geom-arc`](./packages/geom-arc) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-arc.svg)](https://www.npmjs.com/package/@thi.ng/geom-arc) | [changelog](./packages/geom-arc/CHANGELOG.md) | 2D elliptic arc utils | -| [`@thi.ng/geom-clip-line`](./packages/geom-clip-line) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-clip-line.svg)](https://www.npmjs.com/package/@thi.ng/geom-clip-line) | [changelog](./packages/geom-clip-line/CHANGELOG.md) | 2D line clipping | -| [`@thi.ng/geom-clip-poly`](./packages/geom-clip-poly) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-clip-poly.svg)](https://www.npmjs.com/package/@thi.ng/geom-clip-poly) | [changelog](./packages/geom-clip-poly/CHANGELOG.md) | 2D convex polygon clipping | -| [`@thi.ng/geom-closest-point`](./packages/geom-closest-point) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-closest-point.svg)](https://www.npmjs.com/package/@thi.ng/geom-closest-point) | [changelog](./packages/geom-closest-point/CHANGELOG.md) | Closest point helpers | -| [`@thi.ng/geom-fuzz`](./packages/geom-fuzz) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-fuzz.svg)](https://www.npmjs.com/package/@thi.ng/geom-fuzz) | [changelog](./packages/geom-fuzz/CHANGELOG.md) | Fuzzy 2D shape drawing / filling | -| [`@thi.ng/geom-hull`](./packages/geom-hull) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-hull.svg)](https://www.npmjs.com/package/@thi.ng/geom-hull) | [changelog](./packages/geom-hull/CHANGELOG.md) | 2D convex hull (Graham scan) | -| [`@thi.ng/geom-io-obj`](./packages/geom-io-obj) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-io-obj.svg)](https://www.npmjs.com/package/@thi.ng/geom-io-obj) | [changelog](./packages/geom-io-obj/CHANGELOG.md) | Wavefront OBJ model parser | -| [`@thi.ng/geom-isec`](./packages/geom-isec) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-isec.svg)](https://www.npmjs.com/package/@thi.ng/geom-isec) | [changelog](./packages/geom-isec/CHANGELOG.md) | Point & shape intersection tests | -| [`@thi.ng/geom-isoline`](./packages/geom-isoline) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-isoline.svg)](https://www.npmjs.com/package/@thi.ng/geom-isoline) | [changelog](./packages/geom-isoline/CHANGELOG.md) | 2D contour line extraction | -| [`@thi.ng/geom-poly-utils`](./packages/geom-poly-utils) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-poly-utils.svg)](https://www.npmjs.com/package/@thi.ng/geom-poly-utils) | [changelog](./packages/geom-poly-utils/CHANGELOG.md) | 2D polygon helpers | -| [`@thi.ng/geom-resample`](./packages/geom-resample) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-resample.svg)](https://www.npmjs.com/package/@thi.ng/geom-resample) | [changelog](./packages/geom-resample/CHANGELOG.md) | nD polyline / curve resampling | -| [`@thi.ng/geom-splines`](./packages/geom-splines) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-splines.svg)](https://www.npmjs.com/package/@thi.ng/geom-splines) | [changelog](./packages/geom-splines/CHANGELOG.md) | nD cubic / quadratic spline ops | -| [`@thi.ng/geom-subdiv-curve`](./packages/geom-subdiv-curve) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-subdiv-curve.svg)](https://www.npmjs.com/package/@thi.ng/geom-subdiv-curve) | [changelog](./packages/geom-subdiv-curve/CHANGELOG.md) | nD iterative subdivision curves | -| [`@thi.ng/geom-tessellate`](./packages/geom-tessellate) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-tessellate.svg)](https://www.npmjs.com/package/@thi.ng/geom-tessellate) | [changelog](./packages/geom-tessellate/CHANGELOG.md) | nD convex polygon tessellators | -| [`@thi.ng/geom-voronoi`](./packages/geom-voronoi) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-voronoi.svg)](https://www.npmjs.com/package/@thi.ng/geom-voronoi) | [changelog](./packages/geom-voronoi/CHANGELOG.md) | 2D iterative delaunay/voronoi | -| [`@thi.ng/iges`](./packages/iges) | [![version](https://img.shields.io/npm/v/@thi.ng/iges.svg)](https://www.npmjs.com/package/@thi.ng/iges) | [changelog](./packages/iges/CHANGELOG.md) | IGES format geometry serialization | -| [`@thi.ng/lsys`](./packages/lsys) | [![version](https://img.shields.io/npm/v/@thi.ng/lsys.svg)](https://www.npmjs.com/package/@thi.ng/lsys) | [changelog](./packages/lsys/CHANGELOG.md) | Extensible L-System architecture | -| [`@thi.ng/matrices`](./packages/matrices) | [![version](https://img.shields.io/npm/v/@thi.ng/matrices.svg)](https://www.npmjs.com/package/@thi.ng/matrices) | [changelog](./packages/matrices/CHANGELOG.md) | Matrix operations | -| [`@thi.ng/pixel`](./packages/pixel) | [![version](https://img.shields.io/npm/v/@thi.ng/pixel.svg)](https://www.npmjs.com/package/@thi.ng/pixel) | [changelog](./packages/pixel/CHANGELOG.md) | Multi-format pixel buffers | -| [`@thi.ng/poisson`](./packages/poisson) | [![version](https://img.shields.io/npm/v/@thi.ng/poisson.svg)](https://www.npmjs.com/package/@thi.ng/poisson) | [changelog](./packages/poisson/CHANGELOG.md) | nD Poisson disk sampling | -| [`@thi.ng/porter-duff`](./packages/porter-duff) | [![version](https://img.shields.io/npm/v/@thi.ng/porter-duff.svg)](https://www.npmjs.com/package/@thi.ng/porter-duff) | [changelog](./packages/porter-duff/CHANGELOG.md) | Alpha blending / compositing ops | -| [`@thi.ng/scenegraph`](./packages/scenegraph) | [![version](https://img.shields.io/npm/v/@thi.ng/scenegraph.svg)](https://www.npmjs.com/package/@thi.ng/scenegraph) | [changelog](./packages/scenegraph/CHANGELOG.md) | Extensible 2D/3D scenegraph | -| [`@thi.ng/simd`](./packages/simd) | [![version](https://img.shields.io/npm/v/@thi.ng/simd.svg)](https://www.npmjs.com/package/@thi.ng/simd) | [changelog](./packages/simd/CHANGELOG.md) | WebAssembly SIMD vector batch processing | -| [`@thi.ng/vectors`](./packages/vectors) | [![version](https://img.shields.io/npm/v/@thi.ng/vectors.svg)](https://www.npmjs.com/package/@thi.ng/vectors) | [changelog](./packages/vectors/CHANGELOG.md) | Fixed & arbitrary-length vector ops | +| Project | Version | Changelog | Description | +|---------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------|-----------------------------------------------------| +| [`@thi.ng/color`](./packages/color) | [![version](https://img.shields.io/npm/v/@thi.ng/color.svg)](https://www.npmjs.com/package/@thi.ng/color) | [changelog](./packages/color/CHANGELOG.md) | Color conversions, gradients | +| [`@thi.ng/dgraph-dot`](./packages/dgraph-dot) | [![version](https://img.shields.io/npm/v/@thi.ng/dgraph-dot.svg)](https://www.npmjs.com/package/@thi.ng/dgraph-dot) | [changelog](./packages/dgraph-dot/CHANGELOG.md) | Dependency graph -> Graphviz | +| [`@thi.ng/dot`](./packages/dot) | [![version](https://img.shields.io/npm/v/@thi.ng/dot.svg)](https://www.npmjs.com/package/@thi.ng/dot) | [changelog](./packages/dot/CHANGELOG.md) | Graphviz DOM & export | +| [`@thi.ng/geom`](./packages/geom) | [![version](https://img.shields.io/npm/v/@thi.ng/geom.svg)](https://www.npmjs.com/package/@thi.ng/geom) | [changelog](./packages/geom/CHANGELOG.md) | 2D only geometry types & ops | +| [`@thi.ng/geom-accel`](./packages/geom-accel) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-accel.svg)](https://www.npmjs.com/package/@thi.ng/geom-accel) | [changelog](./packages/geom-accel/CHANGELOG.md) | Spatial indexing data structures | +| [`@thi.ng/geom-api`](./packages/geom-api) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-api.svg)](https://www.npmjs.com/package/@thi.ng/geom-api) | [changelog](./packages/geom-api/CHANGELOG.md) | Shared types & interfaces | +| [`@thi.ng/geom-arc`](./packages/geom-arc) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-arc.svg)](https://www.npmjs.com/package/@thi.ng/geom-arc) | [changelog](./packages/geom-arc/CHANGELOG.md) | 2D elliptic arc utils | +| [`@thi.ng/geom-clip-line`](./packages/geom-clip-line) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-clip-line.svg)](https://www.npmjs.com/package/@thi.ng/geom-clip-line) | [changelog](./packages/geom-clip-line/CHANGELOG.md) | 2D line clipping | +| [`@thi.ng/geom-clip-poly`](./packages/geom-clip-poly) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-clip-poly.svg)](https://www.npmjs.com/package/@thi.ng/geom-clip-poly) | [changelog](./packages/geom-clip-poly/CHANGELOG.md) | 2D convex polygon clipping | +| [`@thi.ng/geom-closest-point`](./packages/geom-closest-point) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-closest-point.svg)](https://www.npmjs.com/package/@thi.ng/geom-closest-point) | [changelog](./packages/geom-closest-point/CHANGELOG.md) | Closest point helpers | +| [`@thi.ng/geom-fuzz`](./packages/geom-fuzz) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-fuzz.svg)](https://www.npmjs.com/package/@thi.ng/geom-fuzz) | [changelog](./packages/geom-fuzz/CHANGELOG.md) | Fuzzy 2D shape drawing / filling | +| [`@thi.ng/geom-hull`](./packages/geom-hull) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-hull.svg)](https://www.npmjs.com/package/@thi.ng/geom-hull) | [changelog](./packages/geom-hull/CHANGELOG.md) | 2D convex hull (Graham scan) | +| [`@thi.ng/geom-io-obj`](./packages/geom-io-obj) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-io-obj.svg)](https://www.npmjs.com/package/@thi.ng/geom-io-obj) | [changelog](./packages/geom-io-obj/CHANGELOG.md) | Wavefront OBJ model parser | +| [`@thi.ng/geom-isec`](./packages/geom-isec) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-isec.svg)](https://www.npmjs.com/package/@thi.ng/geom-isec) | [changelog](./packages/geom-isec/CHANGELOG.md) | Point & shape intersection tests | +| [`@thi.ng/geom-isoline`](./packages/geom-isoline) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-isoline.svg)](https://www.npmjs.com/package/@thi.ng/geom-isoline) | [changelog](./packages/geom-isoline/CHANGELOG.md) | 2D contour line extraction | +| [`@thi.ng/geom-poly-utils`](./packages/geom-poly-utils) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-poly-utils.svg)](https://www.npmjs.com/package/@thi.ng/geom-poly-utils) | [changelog](./packages/geom-poly-utils/CHANGELOG.md) | 2D polygon helpers | +| [`@thi.ng/geom-resample`](./packages/geom-resample) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-resample.svg)](https://www.npmjs.com/package/@thi.ng/geom-resample) | [changelog](./packages/geom-resample/CHANGELOG.md) | nD polyline / curve resampling | +| [`@thi.ng/geom-splines`](./packages/geom-splines) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-splines.svg)](https://www.npmjs.com/package/@thi.ng/geom-splines) | [changelog](./packages/geom-splines/CHANGELOG.md) | nD cubic / quadratic spline ops | +| [`@thi.ng/geom-subdiv-curve`](./packages/geom-subdiv-curve) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-subdiv-curve.svg)](https://www.npmjs.com/package/@thi.ng/geom-subdiv-curve) | [changelog](./packages/geom-subdiv-curve/CHANGELOG.md) | nD iterative subdivision curves | +| [`@thi.ng/geom-tessellate`](./packages/geom-tessellate) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-tessellate.svg)](https://www.npmjs.com/package/@thi.ng/geom-tessellate) | [changelog](./packages/geom-tessellate/CHANGELOG.md) | nD convex polygon tessellators | +| [`@thi.ng/geom-voronoi`](./packages/geom-voronoi) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-voronoi.svg)](https://www.npmjs.com/package/@thi.ng/geom-voronoi) | [changelog](./packages/geom-voronoi/CHANGELOG.md) | 2D iterative delaunay/voronoi | +| [`@thi.ng/iges`](./packages/iges) | [![version](https://img.shields.io/npm/v/@thi.ng/iges.svg)](https://www.npmjs.com/package/@thi.ng/iges) | [changelog](./packages/iges/CHANGELOG.md) | IGES format geometry serialization | +| [`@thi.ng/lsys`](./packages/lsys) | [![version](https://img.shields.io/npm/v/@thi.ng/lsys.svg)](https://www.npmjs.com/package/@thi.ng/lsys) | [changelog](./packages/lsys/CHANGELOG.md) | Extensible L-System architecture | +| [`@thi.ng/matrices`](./packages/matrices) | [![version](https://img.shields.io/npm/v/@thi.ng/matrices.svg)](https://www.npmjs.com/package/@thi.ng/matrices) | [changelog](./packages/matrices/CHANGELOG.md) | Matrix operations | +| [`@thi.ng/pixel`](./packages/pixel) | [![version](https://img.shields.io/npm/v/@thi.ng/pixel.svg)](https://www.npmjs.com/package/@thi.ng/pixel) | [changelog](./packages/pixel/CHANGELOG.md) | Multi-format pixel buffers | +| [`@thi.ng/poisson`](./packages/poisson) | [![version](https://img.shields.io/npm/v/@thi.ng/poisson.svg)](https://www.npmjs.com/package/@thi.ng/poisson) | [changelog](./packages/poisson/CHANGELOG.md) | nD Poisson disk sampling | +| [`@thi.ng/porter-duff`](./packages/porter-duff) | [![version](https://img.shields.io/npm/v/@thi.ng/porter-duff.svg)](https://www.npmjs.com/package/@thi.ng/porter-duff) | [changelog](./packages/porter-duff/CHANGELOG.md) | Alpha blending / compositing ops | +| [`@thi.ng/scenegraph`](./packages/scenegraph) | [![version](https://img.shields.io/npm/v/@thi.ng/scenegraph.svg)](https://www.npmjs.com/package/@thi.ng/scenegraph) | [changelog](./packages/scenegraph/CHANGELOG.md) | Extensible 2D/3D scenegraph | +| [`@thi.ng/simd`](./packages/simd) | [![version](https://img.shields.io/npm/v/@thi.ng/simd.svg)](https://www.npmjs.com/package/@thi.ng/simd) | [changelog](./packages/simd/CHANGELOG.md) | WebAssembly SIMD vector batch processing | +| [`@thi.ng/vectors`](./packages/vectors) | [![version](https://img.shields.io/npm/v/@thi.ng/vectors.svg)](https://www.npmjs.com/package/@thi.ng/vectors) | [changelog](./packages/vectors/CHANGELOG.md) | Fixed & arbitrary-length vector ops | +| [`@thi.ng/viz`](./packages/viz) | [![version](https://img.shields.io/npm/v/@thi.ng/viz.svg)](https://www.npmjs.com/package/@thi.ng/viz) | [changelog](./packages/viz/CHANGELOG.md) | Declarative & functional data visualization toolkit | ### WebGL / GPGPU From 7f59a734a1cb204c108259191753a2a1e3dc8486 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 16:25:05 +0100 Subject: [PATCH 028/106] feat(examples): add ellipse-proximity example --- assets/examples/ellipse-proximity.png | Bin 0 -> 23571 bytes examples/ellipse-proximity/.gitignore | 8 +++ examples/ellipse-proximity/README.md | 13 ++++ examples/ellipse-proximity/index.html | 31 +++++++++ examples/ellipse-proximity/package.json | 43 ++++++++++++ examples/ellipse-proximity/src/index.ts | 67 +++++++++++++++++++ examples/ellipse-proximity/src/webpack.d.ts | 4 ++ examples/ellipse-proximity/tsconfig.json | 11 +++ examples/ellipse-proximity/webpack.config.js | 23 +++++++ 9 files changed, 200 insertions(+) create mode 100644 assets/examples/ellipse-proximity.png create mode 100644 examples/ellipse-proximity/.gitignore create mode 100644 examples/ellipse-proximity/README.md create mode 100644 examples/ellipse-proximity/index.html create mode 100644 examples/ellipse-proximity/package.json create mode 100644 examples/ellipse-proximity/src/index.ts create mode 100644 examples/ellipse-proximity/src/webpack.d.ts create mode 100644 examples/ellipse-proximity/tsconfig.json create mode 100644 examples/ellipse-proximity/webpack.config.js diff --git a/assets/examples/ellipse-proximity.png b/assets/examples/ellipse-proximity.png new file mode 100644 index 0000000000000000000000000000000000000000..2c86dad61b41d5f1a000013eab3e1c1064a2a3a5 GIT binary patch literal 23571 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 literal 0 HcmV?d00001 diff --git a/examples/ellipse-proximity/.gitignore b/examples/ellipse-proximity/.gitignore new file mode 100644 index 0000000000..5d62218c54 --- /dev/null +++ b/examples/ellipse-proximity/.gitignore @@ -0,0 +1,8 @@ +.cache +out +node_modules +yarn.lock +*.js +*.map +!src/*.d.ts +!*.config.js diff --git a/examples/ellipse-proximity/README.md b/examples/ellipse-proximity/README.md new file mode 100644 index 0000000000..76a9b30914 --- /dev/null +++ b/examples/ellipse-proximity/README.md @@ -0,0 +1,13 @@ +# ellipse-proximity + +[Live demo](http://demo.thi.ng/umbrella/ellipse-proximity/) + +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2020 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/ellipse-proximity/index.html b/examples/ellipse-proximity/index.html new file mode 100644 index 0000000000..c0e00d0186 --- /dev/null +++ b/examples/ellipse-proximity/index.html @@ -0,0 +1,31 @@ + + + + + + + ellipse-proximity + + + + + +

+ + + + diff --git a/examples/ellipse-proximity/package.json b/examples/ellipse-proximity/package.json new file mode 100644 index 0000000000..47a23ed099 --- /dev/null +++ b/examples/ellipse-proximity/package.json @@ -0,0 +1,43 @@ +{ + "name": "ellipse-proximity", + "version": "0.0.1", + "description": "Interactive visualization of closest points on ellipses", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report --experimental-scope-hoisting", + "build:webpack": "../../node_modules/.bin/webpack --mode production", + "start": "parcel index.html -p 8080 --open --no-cache" + }, + "devDependencies": { + "parcel-bundler": "^1.12.4", + "terser": "^5.1.0", + "typescript": "^3.9.7" + }, + "dependencies": { + "@thi.ng/geom-closest-point": "latest", + "@thi.ng/rdom": "latest", + "@thi.ng/rdom-canvas": "latest", + "@thi.ng/rstream-gestures": "latest", + "@thi.ng/transducers": "latest", + "@thi.ng/vectors": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + }, + "thi.ng": { + "readme": [ + "geom-closest-point", + "rdom", + "rdom-canvas", + "rstream-gestures", + "vectors" + ], + "screenshot": "examples/ellipse-proximity.png" + } +} diff --git a/examples/ellipse-proximity/src/index.ts b/examples/ellipse-proximity/src/index.ts new file mode 100644 index 0000000000..121abffec6 --- /dev/null +++ b/examples/ellipse-proximity/src/index.ts @@ -0,0 +1,67 @@ +import { closestPointEllipse } from "@thi.ng/geom-closest-point"; +import { $compile } from "@thi.ng/rdom"; +import { $canvas } from "@thi.ng/rdom-canvas"; +import { merge, reactive } from "@thi.ng/rstream"; +import { gestureStream } from "@thi.ng/rstream-gestures"; +import { mapcat, repeatedly } from "@thi.ng/transducers"; +import { add2, normalCCW, random2 } from "@thi.ng/vectors"; + +const W = 600; + +// define random ellipses ([origin, radius] tuples) +const ELLIPSES = [ + ...repeatedly(() => [random2([], 50, W - 50), random2([], 10, W / 2)], 5), +]; + +// compile & mount reactive canvas component +$compile( + $canvas( + // stream merge + merge({ + src: [ + // #1 initial call to action... + reactive([ + "g", + {}, + [ + "text", + { align: "center", fill: "black" }, + [W / 2, W / 2], + "Move your mouse / finger!", + ], + ]), + // #2 stream of mouse/touch coordinates (main) + gestureStream(document.body).map( + (e) => + [ + "g", + // disable canvas clearing if no mouse buttons pressed + { fill: "none", __clear: !!e.buttons }, + // semi-transparent white rect to fade previous frame + ["rect", { fill: [1, 1, 1, 0.2] }, [0, 0], W, W], + // declare ellipses, closest points and tangents + ...mapcat(([o, r]) => { + const p = closestPointEllipse(e.pos, o, r); + return [ + ["ellipse", { stroke: "#ccc" }, o, r], + ["circle", { stroke: "#f0f" }, p, 5], + ["line", { stroke: "#666" }, e.pos, p], + [ + "line", + { stroke: "#6c0" }, + p, + add2( + null, + normalCCW([], p, e.pos, 100), + p + ), + ], + ]; + }, ELLIPSES), + ] + ), + ], + }), + [W, W] + ) +).mount(document.getElementById("app")!); diff --git a/examples/ellipse-proximity/src/webpack.d.ts b/examples/ellipse-proximity/src/webpack.d.ts new file mode 100644 index 0000000000..2966449833 --- /dev/null +++ b/examples/ellipse-proximity/src/webpack.d.ts @@ -0,0 +1,4 @@ +declare module "*.jpg"; +declare module "*.png"; +declare module "*.svg"; +declare module "*.json"; diff --git a/examples/ellipse-proximity/tsconfig.json b/examples/ellipse-proximity/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/ellipse-proximity/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/ellipse-proximity/webpack.config.js b/examples/ellipse-proximity/webpack.config.js new file mode 100644 index 0000000000..bf16021356 --- /dev/null +++ b/examples/ellipse-proximity/webpack.config.js @@ -0,0 +1,23 @@ +module.exports = { + entry: "./src/index.ts", + output: { + filename: "bundle.[hash].js", + path: __dirname + "/out" + }, + resolve: { + extensions: [".ts", ".js"] + }, + module: { + rules: [ + { + test: /\.(png|jpg|gif)$/, + loader: "file-loader", + options: { name: "[path][hash].[ext]" } + }, + { test: /\.ts$/, use: "ts-loader" } + ] + }, + node: { + process: false + } +}; From cedf7587763cbf661bbe7c685561d4eba3808160 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 16:27:29 +0100 Subject: [PATCH 029/106] minor(geom-closest-point): minor refactoring --- packages/geom-closest-point/src/circle.ts | 4 ++-- packages/geom-closest-point/src/ellipse.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/geom-closest-point/src/circle.ts b/packages/geom-closest-point/src/circle.ts index 63c3419da1..732b9b8faa 100644 --- a/packages/geom-closest-point/src/circle.ts +++ b/packages/geom-closest-point/src/circle.ts @@ -1,10 +1,10 @@ -import { add, normalize, ReadonlyVec, sub, Vec } from "@thi.ng/vectors"; +import { add, direction, ReadonlyVec, Vec } from "@thi.ng/vectors"; export const closestPointCircle = ( p: ReadonlyVec, c: ReadonlyVec, r: number, out: Vec = [] -) => add(out, c, normalize(out, sub(out, p, c), r)); +) => add(out, c, direction(out, c, p, r)); export const closestPointSphere = closestPointCircle; diff --git a/packages/geom-closest-point/src/ellipse.ts b/packages/geom-closest-point/src/ellipse.ts index 48f8438b74..0e1f7f8e61 100644 --- a/packages/geom-closest-point/src/ellipse.ts +++ b/packages/geom-closest-point/src/ellipse.ts @@ -29,8 +29,8 @@ export const closestPointEllipse = ( let tx = SQRT2_2; let ty = tx; for (; --n >= 0; ) { - const _ex = ab * (tx * tx * tx); - const _ey = ba * (ty * ty * ty); + const _ex = ab * tx * tx * tx; + const _ey = ba * ty * ty * ty; const qx = apx - _ex; const qy = apy - _ey; const q = Math.hypot(rx * tx - _ex, ry * ty - _ey) / Math.hypot(qx, qy); From 95557f6716071a92433868ce8536ca1c38a54073 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 16:42:21 +0100 Subject: [PATCH 030/106] feat(geom-closest-point): add support for custom dist fn --- packages/geom-closest-point/src/points.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/geom-closest-point/src/points.ts b/packages/geom-closest-point/src/points.ts index 0ff21361da..138c76e3d1 100644 --- a/packages/geom-closest-point/src/points.ts +++ b/packages/geom-closest-point/src/points.ts @@ -1,14 +1,25 @@ +import type { FnU2 } from "@thi.ng/api"; import { distSq, ReadonlyVec, set, Vec } from "@thi.ng/vectors"; +/** + * Returns closest point to `p` in given point array, optionally using custom + * distance function `dist` (default: {@link @thi.ng/vectors#distSq}). + * + * @param p + * @param pts + * @param out + * @param dist + */ export const closestPointArray = ( p: ReadonlyVec, pts: Vec[], - out: Vec = [] + out: Vec = [], + dist: FnU2 = distSq ) => { let minD = Infinity; let closest: Vec | undefined; for (let i = pts.length; --i >= 0; ) { - const d = distSq(pts[i], p); + const d = dist(pts[i], p); if (d < minD) { minD = d; closest = pts[i]; From 72ecd413150692728eb5d68a0428d94d5f702455 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 16:45:27 +0100 Subject: [PATCH 031/106] docs(geom-closest-point): add docstrings --- packages/geom-closest-point/src/circle.ts | 11 +++++++++++ packages/geom-closest-point/src/ellipse.ts | 2 +- packages/geom-closest-point/src/plane.ts | 21 +++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/geom-closest-point/src/circle.ts b/packages/geom-closest-point/src/circle.ts index 732b9b8faa..0d64861d98 100644 --- a/packages/geom-closest-point/src/circle.ts +++ b/packages/geom-closest-point/src/circle.ts @@ -1,5 +1,13 @@ import { add, direction, ReadonlyVec, Vec } from "@thi.ng/vectors"; +/** + * Returns closest point to `p` on circle defined by origin `c` and radius `r`. + * + * @param p + * @param c + * @param r + * @param out + */ export const closestPointCircle = ( p: ReadonlyVec, c: ReadonlyVec, @@ -7,4 +15,7 @@ export const closestPointCircle = ( out: Vec = [] ) => add(out, c, direction(out, c, p, r)); +/** + * Same as {@link closestPointCircle}. + */ export const closestPointSphere = closestPointCircle; diff --git a/packages/geom-closest-point/src/ellipse.ts b/packages/geom-closest-point/src/ellipse.ts index 0e1f7f8e61..2adbd95aa5 100644 --- a/packages/geom-closest-point/src/ellipse.ts +++ b/packages/geom-closest-point/src/ellipse.ts @@ -1,5 +1,5 @@ import { clamp01, SQRT2_2 } from "@thi.ng/math"; -import { ReadonlyVec } from "@thi.ng/vectors"; +import type { ReadonlyVec } from "@thi.ng/vectors"; /** * @remarks diff --git a/packages/geom-closest-point/src/plane.ts b/packages/geom-closest-point/src/plane.ts index e24ab27e12..a1cc6a38ef 100644 --- a/packages/geom-closest-point/src/plane.ts +++ b/packages/geom-closest-point/src/plane.ts @@ -1,8 +1,29 @@ import { dot, normalize, ReadonlyVec, sub, Vec } from "@thi.ng/vectors"; +/** + * Returns signed distance between point `p` and plane defined by normal `n` and + * `w`. In 2D this also works for lines. + * + * @remarks + * If result is > 0 the point lies "above" the plane, if < 0 below the plane or + * if zero on the plane. + * + * @param p + * @param n + * @param w + */ export const distToPlane = (p: ReadonlyVec, n: ReadonlyVec, w: number) => dot(n, p) - w; +/** + * Returns closest point to `p` on the plane defined by normal `n` and `w`. In + * 2D this also works for lines. + * + * @param p + * @param normal + * @param w + * @param out + */ export const closestPointPlane = ( p: ReadonlyVec, normal: ReadonlyVec, From 10bb58ac0c5b7463f21976f74a7afc748e8fd10d Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 16:49:10 +0100 Subject: [PATCH 032/106] docs: update readmes --- examples/README.md | 181 +++++++++++++------------- packages/geom-closest-point/README.md | 15 ++- packages/rdom-canvas/README.md | 7 +- packages/rdom/README.md | 17 +-- packages/rstream-gestures/README.md | 23 ++-- packages/vectors/README.md | 1 + 6 files changed, 131 insertions(+), 113 deletions(-) diff --git a/examples/README.md b/examples/README.md index a31381d155..dd08570b5e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,7 +1,7 @@ # @thi.ng/umbrella examples -This directory contains a growing number (currently 98) of standalone +This directory contains a growing number (currently 99) of standalone example projects, including live online versions, build instructions and commented source code. @@ -19,93 +19,94 @@ in touch via PR, issue tracker, email or twitter! | 007 | | [commit-table-ssr](./commit-table-ssr/) | Filterable commit log UI w/ minimal server to provide commit history | | 008 | | [crypto-chart](./crypto-chart/) | Basic crypto-currency candle chart with multiple moving averages plots | | 009 | | [devcards](./devcards/) | BMI calculator in a devcards format | -| 010 | | [fft-synth](./fft-synth/) | Interactive inverse FFT toy synth | -| 011 | | [geom-convex-hull](./geom-convex-hull/) | Convex hull & shape clipping of 2D polygons | -| 012 | | [geom-fuzz-basics](./geom-fuzz-basics/) | geom-fuzz basic shape & fill examples | -| 013 | | [geom-knn](./geom-knn/) | Doodle w/ K-nearest neighbor search result visualization | -| 014 | | [geom-tessel](./geom-tessel/) | Animated, recursive polygon tessellations | -| 015 | | [geom-voronoi-mst](./geom-voronoi-mst/) | Poisson-disk shape-aware sampling, Voronoi & Minimum Spanning Tree visualization | -| 016 | | [gesture-analysis](./gesture-analysis/) | Mouse gesture / stroke analysis, simplification, corner detection | -| 017 | | [grid-iterators](./grid-iterators/) | Visualization of different grid iterator strategies | -| 018 | | [hdom-basics](./hdom-basics/) | Minimal hdom usage example | -| 019 | | [hdom-benchmark](./hdom-benchmark/) | hdom update performance benchmark (old version) | -| 020 | | [hdom-benchmark2](./hdom-benchmark2/) | hdom update performance benchmark w/ config options | -| 021 | | [hdom-canvas-clock](./hdom-canvas-clock/) | Realtime analog clock demo | -| 022 | | [hdom-canvas-draw](./hdom-canvas-draw/) | Interactive pattern drawing demo using transducers | -| 023 | | [hdom-canvas-particles](./hdom-canvas-particles/) | 2D Bezier curve-guided particle system | -| 024 | | [hdom-canvas-shapes](./hdom-canvas-shapes/) | Various hdom-canvas shape drawing examples & SVG conversion / export | -| 025 | | [hdom-dropdown](./hdom-dropdown/) | Custom dropdown UI component for hdom | -| 026 | | [hdom-dropdown-fuzzy](./hdom-dropdown-fuzzy/) | Custom dropdown UI component w/ fuzzy search | -| 027 | | [hdom-dyn-context](./hdom-dyn-context/) | Using custom hdom context for dynamic UI theming | -| 028 | | [hdom-elm](./hdom-elm/) | Using hdom in an Elm-like manner | -| 029 | | [hdom-inner-html](./hdom-inner-html/) | Higher-order component for rendering HTML strings | -| 030 | | [hdom-local-render](./hdom-local-render/) | Isolated, component-local DOM updates | -| 031 | | [hdom-localstate](./hdom-localstate/) | UI component w/ local state stored in hdom context | -| 032 | | [hdom-skip](./hdom-skip/) | Skipping UI updates for selected component(s) | -| 033 | | [hdom-skip-nested](./hdom-skip-nested/) | Skipping UI updates for nested component(s) | -| 034 | | [hdom-theme](./hdom-theme/) | Example for themed components proposal | -| 035 | | [hdom-toggle](./hdom-toggle/) | Customizable slide toggle component demo | -| 036 | | [hdom-vscroller](./hdom-vscroller/) | Virtual scroller component for large tables / lists | -| 037 | | [hiccup-canvas-arcs](./hiccup-canvas-arcs/) | Animated arcs & drawing using hiccup-canvas | -| 038 | | [hmr-basics](./hmr-basics/) | hdom & hot module replacement | -| 039 | | [hydrate-basics](./hydrate-basics/) | Hiccup / hdom DOM hydration example | -| 040 | | [imgui](./imgui/) | Canvas based Immediate Mode GUI components | -| 041 | | [imgui-basics](./imgui-basics/) | Minimal IMGUI usage example | -| 042 | | [interceptor-basics](./interceptor-basics/) | Event handling w/ interceptors and side effects | -| 043 | | [interceptor-basics2](./interceptor-basics2/) | Event handling w/ interceptors and side effects | -| 044 | | [iso-plasma](./iso-plasma/) | Animated sine plasma effect visualized using contour lines | -| 045 | | [json-components](./json-components/) | Transforming JSON into UI components | -| 046 | | [login-form](./login-form/) | Basic SPA example with atom-based UI router | -| 047 | | [mandelbrot](./mandelbrot/) | Worker based, interactive Mandelbrot visualization | -| 048 | | [markdown](./markdown/) | Minimal Markdown to Hiccup to HTML parser / transformer | -| 049 | | [multitouch](./multitouch/) | Basic rstream-gestures multi-touch demo | -| 050 | | [package-stats](./package-stats/) | CLI util to visualize umbrella pkg stats | -| 051 | | [parse-playground](./parse-playground/) | Parser grammar livecoding editor/playground & codegen | -| 052 | | [pixel-basics](./pixel-basics/) | Pixel buffer manipulations | -| 053 | | [pointfree-svg](./pointfree-svg/) | Generate SVG using pointfree DSL | -| 054 | | [poisson-circles](./poisson-circles/) | 2D Poisson-disc sampler with procedural gradient map | -| 055 | | [poly-spline](./poly-spline/) | Polygon to cubic curve conversion & visualization | -| 056 | | [porter-duff](./porter-duff/) | Port-Duff image compositing / alpha blending | -| 057 | | [ramp-synth](./ramp-synth/) | Unison wavetable synth with waveform editor | -| 058 | | [rdom-basics](./rdom-basics/) | Demonstates various rdom usage patterns | -| 059 | | [rdom-dnd](./rdom-dnd/) | rdom drag & drop example | -| 060 | | [rdom-lissajous](./rdom-lissajous/) | rdom & hiccup-canvas interop test | -| 061 | | [rdom-search-docs](./rdom-search-docs/) | Full umbrella repo doc string search w/ paginated results | -| 062 | | [rdom-svg-nodes](./rdom-svg-nodes/) | rdom powered SVG graph with draggable nodes | -| 063 | | [rotating-voronoi](./rotating-voronoi/) | Animated Voronoi diagram, cubic splines & SVG download | -| 064 | | [router-basics](./router-basics/) | Complete mini SPA app w/ router & async content loading | -| 065 | | [rstream-dataflow](./rstream-dataflow/) | Minimal rstream dataflow graph | -| 066 | | [rstream-event-loop](./rstream-event-loop/) | Minimal demo of using rstream constructs to form an interceptor-style event loop | -| 067 | | [rstream-grid](./rstream-grid/) | Interactive grid generator, SVG generation & export, undo/redo support | -| 068 | | [rstream-hdom](./rstream-hdom/) | rstream based UI updates & state handling | -| 069 | | [rstream-spreadsheet](./rstream-spreadsheet/) | rstream based spreadsheet w/ S-expression formula DSL | -| 070 | | [scenegraph](./scenegraph/) | 2D scenegraph & shape picking | -| 071 | | [scenegraph-image](./scenegraph-image/) | 2D scenegraph & image map based geometry manipulation | -| 072 | | [shader-ast-canvas2d](./shader-ast-canvas2d/) | 2D canvas shader emulation | -| 073 | | [shader-ast-evo](./shader-ast-evo/) | Evolutionary shader generation using genetic programming | -| 074 | | [shader-ast-noise](./shader-ast-noise/) | HOF shader procedural noise function composition | -| 075 | | [shader-ast-raymarch](./shader-ast-raymarch/) | WebGL & JS canvas2D raymarch shader cross-compilation | -| 076 | | [shader-ast-sdf2d](./shader-ast-sdf2d/) | WebGL & JS canvas 2D SDF | -| 077 | | [shader-ast-tunnel](./shader-ast-tunnel/) | WebGL & Canvas2D textured tunnel shader | -| 078 | | [shader-ast-workers](./shader-ast-workers/) | Fork-join worker-based raymarch renderer | -| 079 | | [shader-graph](./shader-graph/) | Minimal shader graph developed during livestream #2 | -| 080 | | [soa-ecs](./soa-ecs/) | Entity Component System w/ 100k 3D particles | -| 081 | | [stratified-grid](./stratified-grid/) | 2D Stratified grid sampling example | -| 082 | | [svg-barchart](./svg-barchart/) | Simplistic SVG bar chart component | -| 083 | | [svg-particles](./svg-particles/) | Basic 2D particle system w/ SVG shapes | -| 084 | | [svg-waveform](./svg-waveform/) | Additive waveform synthesis & SVG visualization with undo/redo | -| 085 | | [talk-slides](./talk-slides/) | hdom based slide deck viewer & slides from my ClojureX 2018 keynote | -| 086 | | [text-canvas](./text-canvas/) | 3D wireframe textmode demo | -| 087 | | [todo-list](./todo-list/) | Obligatory to-do list example with undo/redo | -| 088 | | [transducers-hdom](./transducers-hdom/) | Transducer & rstream based hdom UI updates | -| 089 | | [triple-query](./triple-query/) | Triple store query results & sortable table | -| 090 | | [webgl-cube](./webgl-cube/) | WebGL multi-colored cube mesh | -| 091 | | [webgl-cubemap](./webgl-cubemap/) | WebGL cube maps with async texture loading | -| 092 | | [webgl-grid](./webgl-grid/) | WebGL instancing, animated grid | -| 093 | | [webgl-msdf](./webgl-msdf/) | WebGL MSDF text rendering & particle system | -| 094 | | [webgl-multipass](./webgl-multipass/) | Minimal multi-pass / GPGPU example | -| 095 | | [webgl-shadertoy](./webgl-shadertoy/) | Shadertoy-like WebGL setup | -| 096 | | [webgl-ssao](./webgl-ssao/) | WebGL screenspace ambient occlusion | -| 097 | | [wolfram](./wolfram/) | 1D Wolfram automata with OBJ point cloud export | -| 098 | | [xml-converter](./xml-converter/) | XML/HTML/SVG to hiccup/JS conversion | +| 010 | | [ellipse-proximity](./ellipse-proximity/) | Interactive visualization of closest points on ellipses | +| 011 | | [fft-synth](./fft-synth/) | Interactive inverse FFT toy synth | +| 012 | | [geom-convex-hull](./geom-convex-hull/) | Convex hull & shape clipping of 2D polygons | +| 013 | | [geom-fuzz-basics](./geom-fuzz-basics/) | geom-fuzz basic shape & fill examples | +| 014 | | [geom-knn](./geom-knn/) | Doodle w/ K-nearest neighbor search result visualization | +| 015 | | [geom-tessel](./geom-tessel/) | Animated, recursive polygon tessellations | +| 016 | | [geom-voronoi-mst](./geom-voronoi-mst/) | Poisson-disk shape-aware sampling, Voronoi & Minimum Spanning Tree visualization | +| 017 | | [gesture-analysis](./gesture-analysis/) | Mouse gesture / stroke analysis, simplification, corner detection | +| 018 | | [grid-iterators](./grid-iterators/) | Visualization of different grid iterator strategies | +| 019 | | [hdom-basics](./hdom-basics/) | Minimal hdom usage example | +| 020 | | [hdom-benchmark](./hdom-benchmark/) | hdom update performance benchmark (old version) | +| 021 | | [hdom-benchmark2](./hdom-benchmark2/) | hdom update performance benchmark w/ config options | +| 022 | | [hdom-canvas-clock](./hdom-canvas-clock/) | Realtime analog clock demo | +| 023 | | [hdom-canvas-draw](./hdom-canvas-draw/) | Interactive pattern drawing demo using transducers | +| 024 | | [hdom-canvas-particles](./hdom-canvas-particles/) | 2D Bezier curve-guided particle system | +| 025 | | [hdom-canvas-shapes](./hdom-canvas-shapes/) | Various hdom-canvas shape drawing examples & SVG conversion / export | +| 026 | | [hdom-dropdown](./hdom-dropdown/) | Custom dropdown UI component for hdom | +| 027 | | [hdom-dropdown-fuzzy](./hdom-dropdown-fuzzy/) | Custom dropdown UI component w/ fuzzy search | +| 028 | | [hdom-dyn-context](./hdom-dyn-context/) | Using custom hdom context for dynamic UI theming | +| 029 | | [hdom-elm](./hdom-elm/) | Using hdom in an Elm-like manner | +| 030 | | [hdom-inner-html](./hdom-inner-html/) | Higher-order component for rendering HTML strings | +| 031 | | [hdom-local-render](./hdom-local-render/) | Isolated, component-local DOM updates | +| 032 | | [hdom-localstate](./hdom-localstate/) | UI component w/ local state stored in hdom context | +| 033 | | [hdom-skip](./hdom-skip/) | Skipping UI updates for selected component(s) | +| 034 | | [hdom-skip-nested](./hdom-skip-nested/) | Skipping UI updates for nested component(s) | +| 035 | | [hdom-theme](./hdom-theme/) | Example for themed components proposal | +| 036 | | [hdom-toggle](./hdom-toggle/) | Customizable slide toggle component demo | +| 037 | | [hdom-vscroller](./hdom-vscroller/) | Virtual scroller component for large tables / lists | +| 038 | | [hiccup-canvas-arcs](./hiccup-canvas-arcs/) | Animated arcs & drawing using hiccup-canvas | +| 039 | | [hmr-basics](./hmr-basics/) | hdom & hot module replacement | +| 040 | | [hydrate-basics](./hydrate-basics/) | Hiccup / hdom DOM hydration example | +| 041 | | [imgui](./imgui/) | Canvas based Immediate Mode GUI components | +| 042 | | [imgui-basics](./imgui-basics/) | Minimal IMGUI usage example | +| 043 | | [interceptor-basics](./interceptor-basics/) | Event handling w/ interceptors and side effects | +| 044 | | [interceptor-basics2](./interceptor-basics2/) | Event handling w/ interceptors and side effects | +| 045 | | [iso-plasma](./iso-plasma/) | Animated sine plasma effect visualized using contour lines | +| 046 | | [json-components](./json-components/) | Transforming JSON into UI components | +| 047 | | [login-form](./login-form/) | Basic SPA example with atom-based UI router | +| 048 | | [mandelbrot](./mandelbrot/) | Worker based, interactive Mandelbrot visualization | +| 049 | | [markdown](./markdown/) | Minimal Markdown to Hiccup to HTML parser / transformer | +| 050 | | [multitouch](./multitouch/) | Basic rstream-gestures multi-touch demo | +| 051 | | [package-stats](./package-stats/) | CLI util to visualize umbrella pkg stats | +| 052 | | [parse-playground](./parse-playground/) | Parser grammar livecoding editor/playground & codegen | +| 053 | | [pixel-basics](./pixel-basics/) | Pixel buffer manipulations | +| 054 | | [pointfree-svg](./pointfree-svg/) | Generate SVG using pointfree DSL | +| 055 | | [poisson-circles](./poisson-circles/) | 2D Poisson-disc sampler with procedural gradient map | +| 056 | | [poly-spline](./poly-spline/) | Polygon to cubic curve conversion & visualization | +| 057 | | [porter-duff](./porter-duff/) | Port-Duff image compositing / alpha blending | +| 058 | | [ramp-synth](./ramp-synth/) | Unison wavetable synth with waveform editor | +| 059 | | [rdom-basics](./rdom-basics/) | Demonstates various rdom usage patterns | +| 060 | | [rdom-dnd](./rdom-dnd/) | rdom drag & drop example | +| 061 | | [rdom-lissajous](./rdom-lissajous/) | rdom & hiccup-canvas interop test | +| 062 | | [rdom-search-docs](./rdom-search-docs/) | Full umbrella repo doc string search w/ paginated results | +| 063 | | [rdom-svg-nodes](./rdom-svg-nodes/) | rdom powered SVG graph with draggable nodes | +| 064 | | [rotating-voronoi](./rotating-voronoi/) | Animated Voronoi diagram, cubic splines & SVG download | +| 065 | | [router-basics](./router-basics/) | Complete mini SPA app w/ router & async content loading | +| 066 | | [rstream-dataflow](./rstream-dataflow/) | Minimal rstream dataflow graph | +| 067 | | [rstream-event-loop](./rstream-event-loop/) | Minimal demo of using rstream constructs to form an interceptor-style event loop | +| 068 | | [rstream-grid](./rstream-grid/) | Interactive grid generator, SVG generation & export, undo/redo support | +| 069 | | [rstream-hdom](./rstream-hdom/) | rstream based UI updates & state handling | +| 070 | | [rstream-spreadsheet](./rstream-spreadsheet/) | rstream based spreadsheet w/ S-expression formula DSL | +| 071 | | [scenegraph](./scenegraph/) | 2D scenegraph & shape picking | +| 072 | | [scenegraph-image](./scenegraph-image/) | 2D scenegraph & image map based geometry manipulation | +| 073 | | [shader-ast-canvas2d](./shader-ast-canvas2d/) | 2D canvas shader emulation | +| 074 | | [shader-ast-evo](./shader-ast-evo/) | Evolutionary shader generation using genetic programming | +| 075 | | [shader-ast-noise](./shader-ast-noise/) | HOF shader procedural noise function composition | +| 076 | | [shader-ast-raymarch](./shader-ast-raymarch/) | WebGL & JS canvas2D raymarch shader cross-compilation | +| 077 | | [shader-ast-sdf2d](./shader-ast-sdf2d/) | WebGL & JS canvas 2D SDF | +| 078 | | [shader-ast-tunnel](./shader-ast-tunnel/) | WebGL & Canvas2D textured tunnel shader | +| 079 | | [shader-ast-workers](./shader-ast-workers/) | Fork-join worker-based raymarch renderer | +| 080 | | [shader-graph](./shader-graph/) | Minimal shader graph developed during livestream #2 | +| 081 | | [soa-ecs](./soa-ecs/) | Entity Component System w/ 100k 3D particles | +| 082 | | [stratified-grid](./stratified-grid/) | 2D Stratified grid sampling example | +| 083 | | [svg-barchart](./svg-barchart/) | Simplistic SVG bar chart component | +| 084 | | [svg-particles](./svg-particles/) | Basic 2D particle system w/ SVG shapes | +| 085 | | [svg-waveform](./svg-waveform/) | Additive waveform synthesis & SVG visualization with undo/redo | +| 086 | | [talk-slides](./talk-slides/) | hdom based slide deck viewer & slides from my ClojureX 2018 keynote | +| 087 | | [text-canvas](./text-canvas/) | 3D wireframe textmode demo | +| 088 | | [todo-list](./todo-list/) | Obligatory to-do list example with undo/redo | +| 089 | | [transducers-hdom](./transducers-hdom/) | Transducer & rstream based hdom UI updates | +| 090 | | [triple-query](./triple-query/) | Triple store query results & sortable table | +| 091 | | [webgl-cube](./webgl-cube/) | WebGL multi-colored cube mesh | +| 092 | | [webgl-cubemap](./webgl-cubemap/) | WebGL cube maps with async texture loading | +| 093 | | [webgl-grid](./webgl-grid/) | WebGL instancing, animated grid | +| 094 | | [webgl-msdf](./webgl-msdf/) | WebGL MSDF text rendering & particle system | +| 095 | | [webgl-multipass](./webgl-multipass/) | Minimal multi-pass / GPGPU example | +| 096 | | [webgl-shadertoy](./webgl-shadertoy/) | Shadertoy-like WebGL setup | +| 097 | | [webgl-ssao](./webgl-ssao/) | WebGL screenspace ambient occlusion | +| 098 | | [wolfram](./wolfram/) | 1D Wolfram automata with OBJ point cloud export | +| 099 | | [xml-converter](./xml-converter/) | XML/HTML/SVG to hiccup/JS conversion | diff --git a/packages/geom-closest-point/README.md b/packages/geom-closest-point/README.md index 05c946d8b8..95930d0270 100644 --- a/packages/geom-closest-point/README.md +++ b/packages/geom-closest-point/README.md @@ -13,6 +13,7 @@ This project is part of the - [Status](#status) - [Installation](#installation) - [Dependencies](#dependencies) +- [Usage examples](#usage-examples) - [API](#api) - [Authors](#authors) - [License](#license) @@ -43,7 +44,7 @@ yarn add @thi.ng/geom-closest-point ``` -Package sizes (gzipped, pre-treeshake): ESM: 1.00 KB / CJS: 1.10 KB / UMD: 1.14 KB +Package sizes (gzipped, pre-treeshake): CJS: 1.10 KB ## Dependencies @@ -51,6 +52,18 @@ Package sizes (gzipped, pre-treeshake): ESM: 1.00 KB / CJS: 1.10 KB / UMD: 1.14 - [@thi.ng/math](https://github.com/thi-ng/umbrella/tree/develop/packages/math) - [@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/develop/packages/vectors) +## Usage examples + +Several demos in this repo's +[/examples](https://github.com/thi-ng/umbrella/tree/develop/examples) +directory are using this package. + +A selection: + +| Screenshot | Description | Live demo | Source | +| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| | Interactive visualization of closest points on ellipses | [Demo](https://demo.thi.ng/umbrella/ellipse-proximity/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/ellipse-proximity) | + ## API [Generated API docs](https://docs.thi.ng/umbrella/geom-closest-point/) diff --git a/packages/rdom-canvas/README.md b/packages/rdom-canvas/README.md index acaf91e05b..3e9946f4fa 100644 --- a/packages/rdom-canvas/README.md +++ b/packages/rdom-canvas/README.md @@ -69,9 +69,10 @@ directory are using this package. A selection: -| Screenshot | Description | Live demo | Source | -| --------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------- | -| | rdom & hiccup-canvas interop test | [Demo](https://demo.thi.ng/umbrella/rdom-lissajous/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-lissajous) | +| Screenshot | Description | Live demo | Source | +| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| | Interactive visualization of closest points on ellipses | [Demo](https://demo.thi.ng/umbrella/ellipse-proximity/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/ellipse-proximity) | +| | rdom & hiccup-canvas interop test | [Demo](https://demo.thi.ng/umbrella/rdom-lissajous/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-lissajous) | ## API diff --git a/packages/rdom/README.md b/packages/rdom/README.md index f0f0a1497c..555d9cb860 100644 --- a/packages/rdom/README.md +++ b/packages/rdom/README.md @@ -93,14 +93,15 @@ directory are using this package. A selection: -| Screenshot | Description | Live demo | Source | -| ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------- | -| | Parser grammar livecoding editor/playground & codegen | [Demo](https://demo.thi.ng/umbrella/parse-playground/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/parse-playground) | -| | Demonstates various rdom usage patterns | [Demo](https://demo.thi.ng/umbrella/rdom-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-basics) | -| | rdom drag & drop example | [Demo](https://demo.thi.ng/umbrella/rdom-dnd/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-dnd) | -| | rdom & hiccup-canvas interop test | [Demo](https://demo.thi.ng/umbrella/rdom-lissajous/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-lissajous) | -| | Full umbrella repo doc string search w/ paginated results | [Demo](https://demo.thi.ng/umbrella/rdom-search-docs/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-search-docs) | -| | rdom powered SVG graph with draggable nodes | [Demo](https://demo.thi.ng/umbrella/rdom-svg-nodes/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-svg-nodes) | +| Screenshot | Description | Live demo | Source | +| ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| | Interactive visualization of closest points on ellipses | [Demo](https://demo.thi.ng/umbrella/ellipse-proximity/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/ellipse-proximity) | +| | Parser grammar livecoding editor/playground & codegen | [Demo](https://demo.thi.ng/umbrella/parse-playground/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/parse-playground) | +| | Demonstates various rdom usage patterns | [Demo](https://demo.thi.ng/umbrella/rdom-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-basics) | +| | rdom drag & drop example | [Demo](https://demo.thi.ng/umbrella/rdom-dnd/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-dnd) | +| | rdom & hiccup-canvas interop test | [Demo](https://demo.thi.ng/umbrella/rdom-lissajous/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-lissajous) | +| | Full umbrella repo doc string search w/ paginated results | [Demo](https://demo.thi.ng/umbrella/rdom-search-docs/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-search-docs) | +| | rdom powered SVG graph with draggable nodes | [Demo](https://demo.thi.ng/umbrella/rdom-svg-nodes/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-svg-nodes) | ## API diff --git a/packages/rstream-gestures/README.md b/packages/rstream-gestures/README.md index b7dd9d863f..76f0f8b9af 100644 --- a/packages/rstream-gestures/README.md +++ b/packages/rstream-gestures/README.md @@ -70,17 +70,18 @@ directory are using this package. A selection: -| Screenshot | Description | Live demo | Source | -| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------- | -| | Canvas based dial widget | [Demo](https://demo.thi.ng/umbrella/canvas-dial/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/canvas-dial) | -| | Doodle w/ K-nearest neighbor search result visualization | [Demo](https://demo.thi.ng/umbrella/geom-knn/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/geom-knn) | -| | Mouse gesture / stroke analysis, simplification, corner detection | [Demo](https://demo.thi.ng/umbrella/gesture-analysis/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/gesture-analysis) | -| | Interactive pattern drawing demo using transducers | [Demo](https://demo.thi.ng/umbrella/hdom-canvas-draw/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/hdom-canvas-draw) | -| | Canvas based Immediate Mode GUI components | [Demo](https://demo.thi.ng/umbrella/imgui/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/imgui) | -| | Minimal IMGUI usage example | [Demo](https://demo.thi.ng/umbrella/imgui-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/imgui-basics) | -| | Worker based, interactive Mandelbrot visualization | [Demo](https://demo.thi.ng/umbrella/mandelbrot/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/mandelbrot) | -| | Basic rstream-gestures multi-touch demo | [Demo](https://demo.thi.ng/umbrella/multitouch/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/multitouch) | -| | Minimal shader graph developed during livestream #2 | [Demo](https://demo.thi.ng/umbrella/shader-graph/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/shader-graph) | +| Screenshot | Description | Live demo | Source | +| ------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| | Canvas based dial widget | [Demo](https://demo.thi.ng/umbrella/canvas-dial/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/canvas-dial) | +| | Interactive visualization of closest points on ellipses | [Demo](https://demo.thi.ng/umbrella/ellipse-proximity/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/ellipse-proximity) | +| | Doodle w/ K-nearest neighbor search result visualization | [Demo](https://demo.thi.ng/umbrella/geom-knn/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/geom-knn) | +| | Mouse gesture / stroke analysis, simplification, corner detection | [Demo](https://demo.thi.ng/umbrella/gesture-analysis/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/gesture-analysis) | +| | Interactive pattern drawing demo using transducers | [Demo](https://demo.thi.ng/umbrella/hdom-canvas-draw/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/hdom-canvas-draw) | +| | Canvas based Immediate Mode GUI components | [Demo](https://demo.thi.ng/umbrella/imgui/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/imgui) | +| | Minimal IMGUI usage example | [Demo](https://demo.thi.ng/umbrella/imgui-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/imgui-basics) | +| | Worker based, interactive Mandelbrot visualization | [Demo](https://demo.thi.ng/umbrella/mandelbrot/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/mandelbrot) | +| | Basic rstream-gestures multi-touch demo | [Demo](https://demo.thi.ng/umbrella/multitouch/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/multitouch) | +| | Minimal shader graph developed during livestream #2 | [Demo](https://demo.thi.ng/umbrella/shader-graph/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/shader-graph) | ## API diff --git a/packages/vectors/README.md b/packages/vectors/README.md index 2a6c8dc3a7..333cd0773f 100644 --- a/packages/vectors/README.md +++ b/packages/vectors/README.md @@ -178,6 +178,7 @@ A selection: | Screenshot | Description | Live demo | Source | | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------- | | | Canvas based dial widget | [Demo](https://demo.thi.ng/umbrella/canvas-dial/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/canvas-dial) | +| | Interactive visualization of closest points on ellipses | [Demo](https://demo.thi.ng/umbrella/ellipse-proximity/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/ellipse-proximity) | | | Doodle w/ K-nearest neighbor search result visualization | [Demo](https://demo.thi.ng/umbrella/geom-knn/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/geom-knn) | | | Mouse gesture / stroke analysis, simplification, corner detection | [Demo](https://demo.thi.ng/umbrella/gesture-analysis/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/gesture-analysis) | | | Realtime analog clock demo | [Demo](https://demo.thi.ng/umbrella/hdom-canvas-clock/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/hdom-canvas-clock) | From 94f7229f8c095bf54bd226325fb6b47a40ac39ea Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 17:11:49 +0100 Subject: [PATCH 033/106] build: update pkg meta --- packages/colored-noise/package.json | 14 ++++++++++---- packages/date/package.json | 14 ++++++++++---- packages/dual-algebra/package.json | 14 ++++++++++---- packages/prefixes/package.json | 14 ++++++++++---- packages/rdom-canvas/package.json | 14 ++++++++++---- packages/rdom-components/package.json | 14 ++++++++++---- packages/viz/package.json | 14 ++++++++++---- 7 files changed, 70 insertions(+), 28 deletions(-) diff --git a/packages/colored-noise/package.json b/packages/colored-noise/package.json index dd58ff450d..a243dc4b7a 100644 --- a/packages/colored-noise/package.json +++ b/packages/colored-noise/package.json @@ -11,10 +11,16 @@ "url": "https://github.com/thi-ng/umbrella.git" }, "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/colored-noise#readme", - "funding": { - "type": "patreon", - "url": "https://patreon.com/thing_umbrella" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/postspectacular" + }, + { + "type": "patreon", + "url": "https://patreon.com/thing_umbrella" + } + ], "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { diff --git a/packages/date/package.json b/packages/date/package.json index 6487cd106b..3e2aedd4ad 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -11,10 +11,16 @@ "url": "https://github.com/thi-ng/umbrella.git" }, "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/date#readme", - "funding": { - "type": "patreon", - "url": "https://patreon.com/thing_umbrella" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/postspectacular" + }, + { + "type": "patreon", + "url": "https://patreon.com/thing_umbrella" + } + ], "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { diff --git a/packages/dual-algebra/package.json b/packages/dual-algebra/package.json index fa7d958e5d..c193095656 100644 --- a/packages/dual-algebra/package.json +++ b/packages/dual-algebra/package.json @@ -11,10 +11,16 @@ "url": "https://github.com/thi-ng/umbrella.git" }, "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/dual-algebra#readme", - "funding": { - "type": "patreon", - "url": "https://patreon.com/thing_umbrella" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/postspectacular" + }, + { + "type": "patreon", + "url": "https://patreon.com/thing_umbrella" + } + ], "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { diff --git a/packages/prefixes/package.json b/packages/prefixes/package.json index 216f1208a8..2b643b641c 100644 --- a/packages/prefixes/package.json +++ b/packages/prefixes/package.json @@ -11,10 +11,16 @@ "url": "https://github.com/thi-ng/umbrella.git" }, "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/prefixes#readme", - "funding": { - "type": "patreon", - "url": "https://patreon.com/thing_umbrella" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/postspectacular" + }, + { + "type": "patreon", + "url": "https://patreon.com/thing_umbrella" + } + ], "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { diff --git a/packages/rdom-canvas/package.json b/packages/rdom-canvas/package.json index ae14fafef6..5879fa5630 100644 --- a/packages/rdom-canvas/package.json +++ b/packages/rdom-canvas/package.json @@ -11,10 +11,16 @@ "url": "https://github.com/thi-ng/umbrella.git" }, "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/rdom-canvas#readme", - "funding": { - "type": "patreon", - "url": "https://patreon.com/thing_umbrella" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/postspectacular" + }, + { + "type": "patreon", + "url": "https://patreon.com/thing_umbrella" + } + ], "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { diff --git a/packages/rdom-components/package.json b/packages/rdom-components/package.json index 06bf186a00..8a27fb07b2 100644 --- a/packages/rdom-components/package.json +++ b/packages/rdom-components/package.json @@ -11,10 +11,16 @@ "url": "https://github.com/thi-ng/umbrella.git" }, "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/rdom-components#readme", - "funding": { - "type": "patreon", - "url": "https://patreon.com/thing_umbrella" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/postspectacular" + }, + { + "type": "patreon", + "url": "https://patreon.com/thing_umbrella" + } + ], "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { diff --git a/packages/viz/package.json b/packages/viz/package.json index 453bb9fc26..82db7eeada 100644 --- a/packages/viz/package.json +++ b/packages/viz/package.json @@ -11,10 +11,16 @@ "url": "https://github.com/thi-ng/umbrella.git" }, "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/viz#readme", - "funding": { - "type": "patreon", - "url": "https://patreon.com/thing_umbrella" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/postspectacular" + }, + { + "type": "patreon", + "url": "https://patreon.com/thing_umbrella" + } + ], "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { From 86e3bed65ea5938484a7b94646e4148a3049996f Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 17:12:50 +0100 Subject: [PATCH 034/106] build: update make-module script --- scripts/make-module | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/scripts/make-module b/scripts/make-module index 398c2d0e0f..9d6f10cbe9 100755 --- a/scripts/make-module +++ b/scripts/make-module @@ -56,10 +56,16 @@ cat << EOF > "$MODULE"/package.json "url": "https://github.com/thi-ng/umbrella.git" }, "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/$1#readme", - "funding": { - "type": "patreon", - "url": "https://patreon.com/thing_umbrella" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/postspectacular" + }, + { + "type": "patreon", + "url": "https://patreon.com/thing_umbrella" + } + ], "author": "$AUTHOR <$EMAIL>", "license": "Apache-2.0", "scripts": { @@ -87,7 +93,7 @@ cat << EOF > "$MODULE"/package.json "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.12.3" + "@thi.ng/api": "^6.13.0" }, "files": [ "*.js", @@ -95,7 +101,6 @@ cat << EOF > "$MODULE"/package.json "lib" ], "keywords": [ - "ES6", "typescript" ], "publishConfig": { From a28f5069f54928d4c2824a73dc5b4e2ffbc9939f Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 18:17:11 +0100 Subject: [PATCH 035/106] build: update upload-examples & stats scripts --- scripts/stats | 33 +++++++++++++++++++++++++++------ scripts/upload-examples | 12 ++++++++++-- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/scripts/stats b/scripts/stats index 5ff32bf769..8d098c5bdd 100755 --- a/scripts/stats +++ b/scripts/stats @@ -1,12 +1,33 @@ #!/bin/sh -mod="packages/*" -echo "package,files,comments,sloc" > cloc.csv +# usage: stats packages stats.csv (default) +# usage: stats examples stats-ex.csv -for m in $mod; do - echo "$m" - echo "$m,$(cloc "$m"/src --csv | grep "TypeScript" | cut -d ',' -f1 -f4-5)" >> cloc.csv +if [ $# -gt 0 ]; then + modules="$1/*" +else + modules="packages/*" +fi + +if [ $# -gt 1 ]; then + out="$2" +else + out=stats.csv +fi + +echo "package,files,comments,sloc" > $out + +for m in $modules; do + if [ -d "$m" ]; then + skip=$(grep -e '"skip": true' "$m/package.json") + if [ -e "$m/.skip" ] || [ -n "$skip" ]; then + echo "\tskipping $m" + else + echo "$m $skip" + echo "$m,$(cloc "$m"/src --csv | grep "TypeScript" | cut -d ',' -f1 -f4-5)" >> $out + fi + fi done echo "---" -awk -F ',' '{ files+=$2; comments+=$3; sloc+=$4 } END { print "files:", files, "\tcode:", sloc, "\ttotal:", sloc + comments }' cloc.csv \ No newline at end of file +awk -F ',' '{ files+=$2; comments+=$3; sloc+=$4 } END { print "files:", files, "\tcode:", sloc, "\ttotal:", sloc + comments }' $out diff --git a/scripts/upload-examples b/scripts/upload-examples index 1281133d06..7ee0c02491 100755 --- a/scripts/upload-examples +++ b/scripts/upload-examples @@ -1,7 +1,10 @@ #!/bin/bash -readonly target="s3://demo.thi.ng/umbrella" -readonly opts="--profile toxi-s3 --acl public-read" +readonly s3basepath=umbrella +readonly target="s3://demo.thi.ng/$s3basepath" +readonly cloudfrontid=EL2F1HMDPZ2RL +readonly awsprofile=toxi-full +readonly opts="--profile $awsprofile --acl public-read" if [ $# = 1 ]; then modules="examples/$1" @@ -38,5 +41,10 @@ for m in $modules; do aws s3 cp "$m"/out/"$js" "$dest"/"$js2" $opts --content-type "application/javascript; charset=utf-8" --content-encoding gzip done aws s3 cp "$m"/out/index.html "$dest"/ $opts --cache-control "max-age=900" + + aws cloudfront create-invalidation \ + --distribution-id $cloudfrontid \ + --paths "/$s3basepath/$m/*" \ + --profile $awsprofile fi done From fdcad62a9871f77a84d523eb5fb6d8fac14075c0 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 21:03:45 +0100 Subject: [PATCH 036/106] docs(dual-algebra): update readme --- packages/dual-algebra/README.md | 48 +++++++++++++++++++++++++++-- packages/dual-algebra/tpl.readme.md | 48 +++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/packages/dual-algebra/README.md b/packages/dual-algebra/README.md index b9301d32aa..c28ed4142b 100644 --- a/packages/dual-algebra/README.md +++ b/packages/dual-algebra/README.md @@ -24,6 +24,8 @@ Multivariate dual number algebra, automatic differentiation. - [Wikipedia: Dual numbers](https://en.wikipedia.org/wiki/Dual_number) - [Wikipedia: Automatic_differentiation](https://en.wikipedia.org/wiki/Automatic_differentiation#Automatic_differentiation_using_dual_numbers) +(Package name with hat tip to [@paniq](https://www.shadertoy.com/view/4dVGzw)) + Dual numbers are an elegant solution to compute **precise**(1) derivatives of functions which otherwise require complex & brittle numerical solutions. Furthermore, multivariate dual numbers can be used to obtain (in parallel) @@ -93,6 +95,16 @@ Trigonometry: - `tan(a)` - `atan(a)` +Polynomials: + +- `quadratic(x, a, b, c)` +- `cubic(x, a, b, c, d)` +- `quartic(x, a, b, c, d)` + +For each polynomial, there're scalar versions available too, taking only +rational numbers as arguments (rather than dual numbers already). These versions +are suffixed with `S` (for "scalar"): `quadraticS`, `cubicS` and `quarticS`... + ### Status **ALPHA** - bleeding edge / work-in-progress @@ -138,17 +150,47 @@ const f = (x: number, y: number) => { // `evalFn2()` is higher order fn syntax sugar to simplify // dealing w/ scalars, here same with that wrapper: -const g = evalFn2( - (x, y) => add(neg(mul(x, x)), mul($2(3), sin(y))) -); +const g = evalFn2((x, y) => add(neg(mul(x, x)), mul($2(3), sin(y)))); f(0, 0); // [0, 0, 3] => [f(x,y), dFdx(f(x,y)), dFdy(f(x,y))] +g(0, 0); +// [0, 0, 3] + f(1, Math.PI); // [-0.9999999999999997, -2, -3] ``` +Polynomial example (see [interactive +graph](https://www.desmos.com/calculator/5ot2dpgv0a) of this function): + +```ts +import { add, mul, pow, cubicS } from "@thi.ng/dual-algebra"; + +// compute the cubic polynomial: f(x) = 2x^3 - 3x^2 - 4x + 5 + +// using `cubicS()` polynomial helper +const f1 = (x: number) => cubicS(x, 2, -3, -4, 5); + +// ...or expanded out +const f2 = (x: number) => + add( + add( + add( + mul([2, 0], pow([x, 1], 3)), + mul([-3, 0], pow([x, 1], 2)) + ), + mul([-4, 0], [x, 1]) + ), + [5, 0] + ); + +f2(0) // [5, -4] [f(x), dFdx(f(x))] +f2(1) // [0, -4] +f2(2) // [1, 8] +``` + ## Authors Karsten Schmidt diff --git a/packages/dual-algebra/tpl.readme.md b/packages/dual-algebra/tpl.readme.md index 740b44128d..fa540e52f7 100644 --- a/packages/dual-algebra/tpl.readme.md +++ b/packages/dual-algebra/tpl.readme.md @@ -16,6 +16,8 @@ ${pkg.description} - [Wikipedia: Dual numbers](https://en.wikipedia.org/wiki/Dual_number) - [Wikipedia: Automatic_differentiation](https://en.wikipedia.org/wiki/Automatic_differentiation#Automatic_differentiation_using_dual_numbers) +(Package name with hat tip to [@paniq](https://www.shadertoy.com/view/4dVGzw)) + Dual numbers are an elegant solution to compute **precise**(1) derivatives of functions which otherwise require complex & brittle numerical solutions. Furthermore, multivariate dual numbers can be used to obtain (in parallel) @@ -85,6 +87,16 @@ Trigonometry: - `tan(a)` - `atan(a)` +Polynomials: + +- `quadratic(x, a, b, c)` +- `cubic(x, a, b, c, d)` +- `quartic(x, a, b, c, d)` + +For each polynomial, there're scalar versions available too, taking only +rational numbers as arguments (rather than dual numbers already). These versions +are suffixed with `S` (for "scalar"): `quadraticS`, `cubicS` and `quarticS`... + ${status} ${supportPackages} @@ -126,17 +138,47 @@ const f = (x: number, y: number) => { // `evalFn2()` is higher order fn syntax sugar to simplify // dealing w/ scalars, here same with that wrapper: -const g = evalFn2( - (x, y) => add(neg(mul(x, x)), mul($2(3), sin(y))) -); +const g = evalFn2((x, y) => add(neg(mul(x, x)), mul($2(3), sin(y)))); f(0, 0); // [0, 0, 3] => [f(x,y), dFdx(f(x,y)), dFdy(f(x,y))] +g(0, 0); +// [0, 0, 3] + f(1, Math.PI); // [-0.9999999999999997, -2, -3] ``` +Polynomial example (see [interactive +graph](https://www.desmos.com/calculator/5ot2dpgv0a) of this function): + +```ts +import { add, mul, pow, cubicS } from "@thi.ng/dual-algebra"; + +// compute the cubic polynomial: f(x) = 2x^3 - 3x^2 - 4x + 5 + +// using `cubicS()` polynomial helper +const f1 = (x: number) => cubicS(x, 2, -3, -4, 5); + +// ...or expanded out +const f2 = (x: number) => + add( + add( + add( + mul([2, 0], pow([x, 1], 3)), + mul([-3, 0], pow([x, 1], 2)) + ), + mul([-4, 0], [x, 1]) + ), + [5, 0] + ); + +f2(0) // [5, -4] [f(x), dFdx(f(x))] +f2(1) // [0, -4] +f2(2) // [1, 8] +``` + ## Authors ${authors} From fe2e13c821484714ee0bab363590c742e4910d4c Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 13 Sep 2020 21:48:21 +0100 Subject: [PATCH 037/106] docs(date): update readme --- packages/date/README.md | 39 +++++++++++++++++++++++++++++++++++++ packages/date/tpl.readme.md | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/packages/date/README.md b/packages/date/README.md index 7b391d93ae..4633873b7e 100644 --- a/packages/date/README.md +++ b/packages/date/README.md @@ -14,6 +14,7 @@ This project is part of the - [Installation](#installation) - [Dependencies](#dependencies) - [API](#api) + - [Formatters](#formatters) - [Authors](#authors) - [License](#license) @@ -51,6 +52,44 @@ Package sizes (gzipped, pre-treeshake): ESM: 1.19 KB / CJS: 1.33 KB / UMD: 1.31 TODO - Please see tests and doc strings in source for now... +### Formatters + +Custom date/time formatters can be assembled via +[`defFormat()`](https://github.com/thi-ng/umbrella/blob/develop/packages/date/src/format.ts#L85), +using the following partial format identifiers. + +| ID | Description | +|--------|------------------------------------------| +| `yyyy` | Full year (4 digits) | +| `yy` | Short year (2 digits) | +| `MMM` | 3-letter month name (e.g. `Feb`) | +| `MM` | Zero-padded 2-digit month | +| `M` | Unpadded month | +| `dd` | Zero-padded 2-digit day of month | +| `d` | Unpadded day of month | +| `E` | 3-letter weekday name (e.g. `Mon`) | +| `HH` | Zero-padded 2-digit hour of day (0-23) | +| `h` | Unpadded hour of day (1-12) | +| `mm` | Zero-padded 2-digit minute of hour | +| `m` | Unpadded minute of hour | +| `ss` | Zero-padded 2-digit second of minute | +| `s` | Unpadded second of minute | +| `S` | Unpadded millisecond of second | +| `A` | 12-hour AM/PM marker | +| `Z` | Timezone offset in signed `HH:mm` format | + +Furthermore, the following preset formatters are available: + +- `FMT_yyyyMMdd` - `"2020-09-13"` +- `FMT_MMddyyyy` - `"09/13/2020"` +- `FMT_MMMddyyyy` - `"Sep 13 2020"` +- `FMT_ddMMyyyy` - `"13/09/2020"` +- `FMT_ddMMMyyyy` - `"13 Sep 2020"` +- `FMT_HHmm` - `"21:42"` +- `FMT_hm` - `"9:42 PM"` +- `FMT_HHmmss` - `"21:42:07"` +- `FMT_hms` - `"9:42:07 PM"` + ## Authors Karsten Schmidt diff --git a/packages/date/tpl.readme.md b/packages/date/tpl.readme.md index d4cb929cac..2bf2969ec4 100644 --- a/packages/date/tpl.readme.md +++ b/packages/date/tpl.readme.md @@ -39,6 +39,44 @@ ${docLink} TODO - Please see tests and doc strings in source for now... +### Formatters + +Custom date/time formatters can be assembled via +[`defFormat()`](https://github.com/thi-ng/umbrella/blob/develop/packages/date/src/format.ts#L85), +using the following partial format identifiers. + +| ID | Description | +|--------|------------------------------------------| +| `yyyy` | Full year (4 digits) | +| `yy` | Short year (2 digits) | +| `MMM` | 3-letter month name (e.g. `Feb`) | +| `MM` | Zero-padded 2-digit month | +| `M` | Unpadded month | +| `dd` | Zero-padded 2-digit day of month | +| `d` | Unpadded day of month | +| `E` | 3-letter weekday name (e.g. `Mon`) | +| `HH` | Zero-padded 2-digit hour of day (0-23) | +| `h` | Unpadded hour of day (1-12) | +| `mm` | Zero-padded 2-digit minute of hour | +| `m` | Unpadded minute of hour | +| `ss` | Zero-padded 2-digit second of minute | +| `s` | Unpadded second of minute | +| `S` | Unpadded millisecond of second | +| `A` | 12-hour AM/PM marker | +| `Z` | Timezone offset in signed `HH:mm` format | + +Furthermore, the following preset formatters are available: + +- `FMT_yyyyMMdd` - `"2020-09-13"` +- `FMT_MMddyyyy` - `"09/13/2020"` +- `FMT_MMMddyyyy` - `"Sep 13 2020"` +- `FMT_ddMMyyyy` - `"13/09/2020"` +- `FMT_ddMMMyyyy` - `"13 Sep 2020"` +- `FMT_HHmm` - `"21:42"` +- `FMT_hm` - `"9:42 PM"` +- `FMT_HHmmss` - `"21:42:07"` +- `FMT_hms` - `"9:42:07 PM"` + ## Authors ${authors} From 1e4a7384d5671c1b5cc1aede37d0f831745484d1 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 15 Sep 2020 14:06:18 +0100 Subject: [PATCH 038/106] build(egf): update deps --- packages/egf/package.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/egf/package.json b/packages/egf/package.json index 6d1d5751b7..370cef466e 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -34,7 +34,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/equiv": "^1.0.30", + "@thi.ng/equiv": "^1.0.31", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", @@ -44,14 +44,14 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.12.3", - "@thi.ng/associative": "^5.0.5", - "@thi.ng/checks": "^2.7.7", - "@thi.ng/dot": "^1.2.16", - "@thi.ng/errors": "^1.2.20", - "@thi.ng/prefixes": "^0.1.4", - "@thi.ng/strings": "^1.9.5", - "@thi.ng/transducers-binary": "^0.5.28" + "@thi.ng/api": "^6.13.0", + "@thi.ng/associative": "^5.0.6", + "@thi.ng/checks": "^2.7.8", + "@thi.ng/dot": "^1.2.17", + "@thi.ng/errors": "^1.2.21", + "@thi.ng/prefixes": "^0.1.5", + "@thi.ng/strings": "^1.9.6", + "@thi.ng/transducers-binary": "^0.5.29" }, "files": [ "*.js", From 24ae6e3e35d207688906da064fc262869b1ecb23 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 15 Sep 2020 22:54:38 +0100 Subject: [PATCH 039/106] build: update pkg meta/keywords --- packages/adapt-dpi/package.json | 1 - packages/adjacency/package.json | 1 - packages/api/package.json | 1 - packages/arrays/package.json | 1 - packages/associative/package.json | 1 - packages/atom/package.json | 1 - packages/bench/package.json | 1 - packages/bencode/package.json | 1 - packages/binary/package.json | 1 - packages/bitfield/package.json | 1 - packages/bitstream/package.json | 1 - packages/cache/package.json | 1 - packages/checks/package.json | 1 - packages/color/package.json | 1 - packages/colored-noise/package.json | 1 - packages/compare/package.json | 1 - packages/compose/package.json | 1 - packages/csp/package.json | 1 - packages/date/package.json | 1 - packages/dcons/package.json | 1 - packages/defmulti/package.json | 1 - packages/dgraph-dot/package.json | 1 - packages/dgraph/package.json | 1 - packages/diff/package.json | 1 - packages/dl-asset/package.json | 1 - packages/dlogic/package.json | 1 - packages/dot/package.json | 1 - packages/dsp-io-wav/package.json | 1 - packages/dsp/package.json | 1 - packages/dual-algebra/package.json | 1 - packages/dynvar/package.json | 1 - packages/ecs/package.json | 1 - packages/egf/package.json | 2 +- packages/equiv/package.json | 1 - packages/errors/package.json | 1 - packages/fsm/package.json | 1 - packages/geom-accel/package.json | 1 - packages/geom-api/package.json | 1 - packages/geom-arc/package.json | 1 - packages/geom-clip-line/package.json | 1 - packages/geom-clip-poly/package.json | 1 - packages/geom-closest-point/package.json | 1 - packages/geom-fuzz/package.json | 1 - packages/geom-hull/package.json | 1 - packages/geom-io-obj/package.json | 1 - packages/geom-isec/package.json | 1 - packages/geom-isoline/package.json | 1 - packages/geom-poly-utils/package.json | 1 - packages/geom-resample/package.json | 1 - packages/geom-splines/package.json | 1 - packages/geom-subdiv-curve/package.json | 1 - packages/geom-tessellate/package.json | 1 - packages/geom-voronoi/package.json | 1 - packages/geom/package.json | 1 - packages/gp/package.json | 1 - packages/grid-iterators/package.json | 1 - packages/hdiff/package.json | 1 - packages/hdom-canvas/package.json | 1 - packages/hdom-components/package.json | 1 - packages/hdom-mock/package.json | 1 - packages/hdom/package.json | 1 - packages/heaps/package.json | 1 - packages/hiccup-canvas/package.json | 1 - packages/hiccup-carbon-icons/package.json | 1 - packages/hiccup-css/package.json | 1 - packages/hiccup-html/package.json | 1 - packages/hiccup-markdown/package.json | 1 - packages/hiccup-svg/package.json | 1 - packages/hiccup/package.json | 1 - packages/idgen/package.json | 1 - packages/iges/package.json | 1 - packages/imgui/package.json | 1 - packages/interceptors/package.json | 1 - packages/intervals/package.json | 1 - packages/iterators/package.json | 1 - packages/layout/package.json | 1 - packages/leb128/package.json | 1 - packages/lsys/package.json | 1 - packages/malloc/package.json | 1 - packages/math/package.json | 1 - packages/matrices/package.json | 1 - packages/memoize/package.json | 1 - packages/mime/package.json | 1 - packages/morton/package.json | 1 - packages/oquery/package.json | 1 - packages/parse/package.json | 1 - packages/paths/package.json | 1 - packages/pixel/package.json | 1 - packages/pointfree-lang/package.json | 1 - packages/pointfree/package.json | 1 - packages/poisson/package.json | 1 - packages/porter-duff/package.json | 1 - packages/quad-edge/package.json | 1 - packages/ramp/package.json | 1 - packages/random/package.json | 1 - packages/range-coder/package.json | 1 - packages/rdom-canvas/package.json | 1 - packages/rdom-components/package.json | 1 - packages/rdom/package.json | 1 - packages/resolve-map/package.json | 1 - packages/rle-pack/package.json | 1 - packages/router/package.json | 1 - packages/rstream-csp/package.json | 1 - packages/rstream-dot/package.json | 1 - packages/rstream-gestures/package.json | 1 - packages/rstream-graph/package.json | 1 - packages/rstream-log-file/package.json | 1 - packages/rstream-log/package.json | 1 - packages/rstream-query/package.json | 1 - packages/rstream/package.json | 1 - packages/sax/package.json | 1 - packages/scenegraph/package.json | 1 - packages/seq/package.json | 1 - packages/sexpr/package.json | 1 - packages/shader-ast-glsl/package.json | 1 - packages/shader-ast-js/package.json | 1 - packages/shader-ast-stdlib/package.json | 1 - packages/shader-ast/package.json | 1 - packages/simd/package.json | 1 - packages/soa/package.json | 1 - packages/sparse/package.json | 1 - packages/strings/package.json | 1 - packages/system/package.json | 1 - packages/text-canvas/package.json | 1 - packages/transducers-binary/package.json | 1 - packages/transducers-fsm/package.json | 1 - packages/transducers-hdom/package.json | 1 - packages/transducers-patch/package.json | 1 - packages/transducers-stats/package.json | 1 - packages/transducers/package.json | 1 - packages/unionstruct/package.json | 1 - packages/vector-pools/package.json | 1 - packages/vectors/package.json | 1 - packages/viz/package.json | 1 - packages/webgl-msdf/package.json | 1 - packages/webgl-shadertoy/package.json | 1 - packages/webgl/package.json | 1 - packages/zipper/package.json | 1 - 138 files changed, 1 insertion(+), 138 deletions(-) diff --git a/packages/adapt-dpi/package.json b/packages/adapt-dpi/package.json index 49cc10229f..5a241c6796 100644 --- a/packages/adapt-dpi/package.json +++ b/packages/adapt-dpi/package.json @@ -55,7 +55,6 @@ "keywords": [ "canvas", "dpi", - "es6", "hdpi", "retina", "typescript" diff --git a/packages/adjacency/package.json b/packages/adjacency/package.json index 5d9a4d7041..b234fe37f1 100644 --- a/packages/adjacency/package.json +++ b/packages/adjacency/package.json @@ -68,7 +68,6 @@ "degree", "directed", "disjointset", - "es6", "graph", "laplacian", "matrix", diff --git a/packages/api/package.json b/packages/api/package.json index a8617a00e3..6629dc5116 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -63,7 +63,6 @@ "assert", "constants", "decorators", - "es6", "generic", "interface", "mixin", diff --git a/packages/arrays/package.json b/packages/arrays/package.json index 51eff3162c..e901dce28e 100644 --- a/packages/arrays/package.json +++ b/packages/arrays/package.json @@ -64,7 +64,6 @@ "keywords": [ "array", "binary", - "es6", "fuzzy", "search", "shuffle", diff --git a/packages/associative/package.json b/packages/associative/package.json index ec3e35950c..e28801e87d 100644 --- a/packages/associative/package.json +++ b/packages/associative/package.json @@ -68,7 +68,6 @@ "keywords": [ "datastructure", "equality", - "es6", "hashmap", "intersection", "join", diff --git a/packages/atom/package.json b/packages/atom/package.json index b33ec0b32a..90323a43cf 100644 --- a/packages/atom/package.json +++ b/packages/atom/package.json @@ -63,7 +63,6 @@ "keywords": [ "cursor", "datastructure", - "es6", "history", "immutable", "redo", diff --git a/packages/bench/package.json b/packages/bench/package.json index b3ceac337d..bebc3ba5a3 100644 --- a/packages/bench/package.json +++ b/packages/bench/package.json @@ -59,7 +59,6 @@ "keywords": [ "benchmark", "bigint", - "es6", "execution", "functional", "hrtime", diff --git a/packages/bencode/package.json b/packages/bencode/package.json index 5ff421928e..febdf47401 100644 --- a/packages/bencode/package.json +++ b/packages/bencode/package.json @@ -67,7 +67,6 @@ "binary", "bittorrent", "encode", - "es6", "fileformat", "transducer", "typescript" diff --git a/packages/binary/package.json b/packages/binary/package.json index 23b0169555..c909b2990f 100644 --- a/packages/binary/package.json +++ b/packages/binary/package.json @@ -62,7 +62,6 @@ "binary", "bitwise", "conversion", - "es6", "graycode", "logic", "math", diff --git a/packages/bitfield/package.json b/packages/bitfield/package.json index b6fa68ee75..72fdfbdb38 100644 --- a/packages/bitfield/package.json +++ b/packages/bitfield/package.json @@ -63,7 +63,6 @@ "2d", "binary", "bitwise", - "es6", "matrix", "typescript", "typedarray", diff --git a/packages/bitstream/package.json b/packages/bitstream/package.json index 8e32bdb7db..2713cf0c2d 100644 --- a/packages/bitstream/package.json +++ b/packages/bitstream/package.json @@ -60,7 +60,6 @@ "binary", "bits", "datastructure", - "es6", "iterator", "stream", "typescript" diff --git a/packages/cache/package.json b/packages/cache/package.json index 4a28c494a7..ef75fca0e3 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -61,7 +61,6 @@ "keywords": [ "cache", "datastructure", - "es6", "lru", "map", "mru", diff --git a/packages/checks/package.json b/packages/checks/package.json index 58436e6c13..57a2844e57 100644 --- a/packages/checks/package.json +++ b/packages/checks/package.json @@ -59,7 +59,6 @@ "keywords": [ "check", "detect", - "es6", "feature", "reflect", "typescript", diff --git a/packages/color/package.json b/packages/color/package.json index 62dd1638a0..9aa00da0a6 100644 --- a/packages/color/package.json +++ b/packages/color/package.json @@ -73,7 +73,6 @@ "color", "conversion", "cosine", - "es6", "filter", "gradient", "hcy", diff --git a/packages/colored-noise/package.json b/packages/colored-noise/package.json index a243dc4b7a..a3a30422ac 100644 --- a/packages/colored-noise/package.json +++ b/packages/colored-noise/package.json @@ -65,7 +65,6 @@ "keywords": [ "blue", "brown", - "es6", "fft", "filter", "generator", diff --git a/packages/compare/package.json b/packages/compare/package.json index e48bfa2047..4d944bbfdb 100644 --- a/packages/compare/package.json +++ b/packages/compare/package.json @@ -58,7 +58,6 @@ ], "keywords": [ "comparator", - "es6", "sort", "typescript" ], diff --git a/packages/compose/package.json b/packages/compose/package.json index fc0c5e80e4..5571bb55c5 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -60,7 +60,6 @@ "keywords": [ "async", "composition", - "es6", "functional", "typescript" ], diff --git a/packages/csp/package.json b/packages/csp/package.json index 53972acfb6..62acd8577c 100644 --- a/packages/csp/package.json +++ b/packages/csp/package.json @@ -70,7 +70,6 @@ "csp", "channel", "datastructure", - "es6", "multiplex", "pipeline", "promise", diff --git a/packages/date/package.json b/packages/date/package.json index 3e2aedd4ad..13bda4b30f 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -57,7 +57,6 @@ ], "keywords": [ "date", - "es6", "format", "interval", "iterator", diff --git a/packages/dcons/package.json b/packages/dcons/package.json index d977bf4015..4f868ba49d 100644 --- a/packages/dcons/package.json +++ b/packages/dcons/package.json @@ -64,7 +64,6 @@ ], "keywords": [ "datastructure", - "es6", "iterator", "linkedlist", "list", diff --git a/packages/defmulti/package.json b/packages/defmulti/package.json index 1d030870ea..7169890291 100644 --- a/packages/defmulti/package.json +++ b/packages/defmulti/package.json @@ -59,7 +59,6 @@ ], "keywords": [ "arity", - "es6", "functional", "hierarchy", "inheritance", diff --git a/packages/dgraph-dot/package.json b/packages/dgraph-dot/package.json index 66bb031eeb..40c8025033 100644 --- a/packages/dgraph-dot/package.json +++ b/packages/dgraph-dot/package.json @@ -59,7 +59,6 @@ "lib" ], "keywords": [ - "es6", "dependency", "fileformat", "graph", diff --git a/packages/dgraph/package.json b/packages/dgraph/package.json index 930bb79c1d..9a73fe8ea8 100644 --- a/packages/dgraph/package.json +++ b/packages/dgraph/package.json @@ -64,7 +64,6 @@ "dag", "datastructure", "dependency", - "es6", "graph", "query", "sort", diff --git a/packages/diff/package.json b/packages/diff/package.json index 4fc879c6ca..b19937207f 100644 --- a/packages/diff/package.json +++ b/packages/diff/package.json @@ -60,7 +60,6 @@ "array", "diff", "editlog", - "es6", "object", "typescript" ], diff --git a/packages/dl-asset/package.json b/packages/dl-asset/package.json index d6166ae549..b378bc63bc 100644 --- a/packages/dl-asset/package.json +++ b/packages/dl-asset/package.json @@ -59,7 +59,6 @@ "lib" ], "keywords": [ - "es6", "file", "typescript" ], diff --git a/packages/dlogic/package.json b/packages/dlogic/package.json index ba08232752..7e64ed7941 100644 --- a/packages/dlogic/package.json +++ b/packages/dlogic/package.json @@ -60,7 +60,6 @@ "keywords": [ "boolean", "digital", - "es6", "functional", "gates", "logic", diff --git a/packages/dot/package.json b/packages/dot/package.json index 388af68340..eb43a278cb 100644 --- a/packages/dot/package.json +++ b/packages/dot/package.json @@ -58,7 +58,6 @@ "lib" ], "keywords": [ - "es6", "fileformat", "graph", "graphviz", diff --git a/packages/dsp-io-wav/package.json b/packages/dsp-io-wav/package.json index 1746a20a55..240fae0e5b 100644 --- a/packages/dsp-io-wav/package.json +++ b/packages/dsp-io-wav/package.json @@ -62,7 +62,6 @@ "keywords": [ "audio", "dsp", - "es6", "export", "fileformat", "typescript" diff --git a/packages/dsp/package.json b/packages/dsp/package.json index f25fb62408..2975d9b6f8 100644 --- a/packages/dsp/package.json +++ b/packages/dsp/package.json @@ -76,7 +76,6 @@ "delay", "dsp", "envelope", - "es6", "feedback", "fft", "filter", diff --git a/packages/dual-algebra/package.json b/packages/dual-algebra/package.json index c193095656..33e55a4c1c 100644 --- a/packages/dual-algebra/package.json +++ b/packages/dual-algebra/package.json @@ -61,7 +61,6 @@ "derivative", "descend", "dual", - "es6", "gradient", "math", "multivariate", diff --git a/packages/dynvar/package.json b/packages/dynvar/package.json index c9889361ac..9e485d03f0 100644 --- a/packages/dynvar/package.json +++ b/packages/dynvar/package.json @@ -59,7 +59,6 @@ "keywords": [ "binding", "dynamic", - "es6", "scope", "state", "typescript", diff --git a/packages/ecs/package.json b/packages/ecs/package.json index 5736c547e8..a9d03b2cff 100644 --- a/packages/ecs/package.json +++ b/packages/ecs/package.json @@ -71,7 +71,6 @@ "component", "datastructure", "entity", - "es6", "memory-mapped", "simd", "typedarray", diff --git a/packages/egf/package.json b/packages/egf/package.json index 370cef466e..b9f479c0ec 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -59,8 +59,8 @@ "lib" ], "keywords": [ + "conversion", "datastructure", - "es6", "file format", "graph", "graphviz", diff --git a/packages/equiv/package.json b/packages/equiv/package.json index 4177efd030..7dd7d86a3e 100644 --- a/packages/equiv/package.json +++ b/packages/equiv/package.json @@ -56,7 +56,6 @@ ], "keywords": [ "deep", - "es6", "equality", "interface", "typescript", diff --git a/packages/errors/package.json b/packages/errors/package.json index 27824aa8dc..ed41ed423c 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -58,7 +58,6 @@ ], "keywords": [ "error", - "es6", "typescript" ], "publishConfig": { diff --git a/packages/fsm/package.json b/packages/fsm/package.json index f5f799dbd9..94adcc7a15 100644 --- a/packages/fsm/package.json +++ b/packages/fsm/package.json @@ -62,7 +62,6 @@ "lib" ], "keywords": [ - "es6", "composition", "declarative", "fsm", diff --git a/packages/geom-accel/package.json b/packages/geom-accel/package.json index 541dc37220..37c6279e15 100644 --- a/packages/geom-accel/package.json +++ b/packages/geom-accel/package.json @@ -71,7 +71,6 @@ "3d", "acceleration", "datastructure", - "es6", "graphics", "grid", "kd-tree", diff --git a/packages/geom-api/package.json b/packages/geom-api/package.json index 17101eadde..c108e85d13 100644 --- a/packages/geom-api/package.json +++ b/packages/geom-api/package.json @@ -58,7 +58,6 @@ "lib" ], "keywords": [ - "es6", "geometry", "interface", "type", diff --git a/packages/geom-arc/package.json b/packages/geom-arc/package.json index 99bffb1800..f20e33810c 100644 --- a/packages/geom-arc/package.json +++ b/packages/geom-arc/package.json @@ -67,7 +67,6 @@ "circle", "circumcenter", "elliptic", - "es6", "geometry", "interpolation", "sample", diff --git a/packages/geom-clip-line/package.json b/packages/geom-clip-line/package.json index 68b71bbab7..e4b8f90566 100644 --- a/packages/geom-clip-line/package.json +++ b/packages/geom-clip-line/package.json @@ -60,7 +60,6 @@ ], "keywords": [ "clipping", - "es6", "geometry", "graphics", "liang-barsky", diff --git a/packages/geom-clip-poly/package.json b/packages/geom-clip-poly/package.json index 437c2aa35f..ca74369171 100644 --- a/packages/geom-clip-poly/package.json +++ b/packages/geom-clip-poly/package.json @@ -63,7 +63,6 @@ "2d", "convex", "clipping", - "es6", "geometry", "graphics", "polygon", diff --git a/packages/geom-closest-point/package.json b/packages/geom-closest-point/package.json index 123ca0cb98..b879fbd96d 100644 --- a/packages/geom-closest-point/package.json +++ b/packages/geom-closest-point/package.json @@ -63,7 +63,6 @@ "circle", "distance", "ellipse", - "es6", "geometry", "line", "points", diff --git a/packages/geom-fuzz/package.json b/packages/geom-fuzz/package.json index 4cb9c31854..8f381f5a74 100644 --- a/packages/geom-fuzz/package.json +++ b/packages/geom-fuzz/package.json @@ -67,7 +67,6 @@ "keywords": [ "canvas", "dots", - "es6", "fuzzy", "drawing", "hatching", diff --git a/packages/geom-hull/package.json b/packages/geom-hull/package.json index 1eccb0ffbd..72efdd4dc3 100644 --- a/packages/geom-hull/package.json +++ b/packages/geom-hull/package.json @@ -60,7 +60,6 @@ "keywords": [ "2d", "convex", - "es6", "geometry", "graphics", "hull", diff --git a/packages/geom-io-obj/package.json b/packages/geom-io-obj/package.json index 595875853b..6756fdd33c 100644 --- a/packages/geom-io-obj/package.json +++ b/packages/geom-io-obj/package.json @@ -58,7 +58,6 @@ "lib" ], "keywords": [ - "es6", "fileformat", "geometry", "mesh", diff --git a/packages/geom-isec/package.json b/packages/geom-isec/package.json index ff0fddeaf4..e5a7d4c35b 100644 --- a/packages/geom-isec/package.json +++ b/packages/geom-isec/package.json @@ -65,7 +65,6 @@ "3d", "aabb", "circle", - "es6", "geometry", "intersection", "line", diff --git a/packages/geom-isoline/package.json b/packages/geom-isoline/package.json index 7e455d952a..8413a7c939 100644 --- a/packages/geom-isoline/package.json +++ b/packages/geom-isoline/package.json @@ -61,7 +61,6 @@ "keywords": [ "2d", "contours", - "es6", "isoline", "iterator", "marchingsquares", diff --git a/packages/geom-poly-utils/package.json b/packages/geom-poly-utils/package.json index ac5ccd1316..2401738946 100644 --- a/packages/geom-poly-utils/package.json +++ b/packages/geom-poly-utils/package.json @@ -62,7 +62,6 @@ ], "keywords": [ "2d", - "es6", "area", "bbox", "centroid", diff --git a/packages/geom-resample/package.json b/packages/geom-resample/package.json index df6084c1c1..ccbdb344be 100644 --- a/packages/geom-resample/package.json +++ b/packages/geom-resample/package.json @@ -65,7 +65,6 @@ "3d", "nd", "curve", - "es6", "distance", "geometry", "interpolation", diff --git a/packages/geom-splines/package.json b/packages/geom-splines/package.json index d10e968641..d34a1464c3 100644 --- a/packages/geom-splines/package.json +++ b/packages/geom-splines/package.json @@ -74,7 +74,6 @@ "cubic", "curve", "elliptic", - "es6", "geometry", "interpolation", "proximity", diff --git a/packages/geom-subdiv-curve/package.json b/packages/geom-subdiv-curve/package.json index af14cb9b8a..d963fc2785 100644 --- a/packages/geom-subdiv-curve/package.json +++ b/packages/geom-subdiv-curve/package.json @@ -65,7 +65,6 @@ "chaikin", "cubic", "curve", - "es6", "iterative", "polyline", "recursive", diff --git a/packages/geom-tessellate/package.json b/packages/geom-tessellate/package.json index 806cb14d95..631dd7682a 100644 --- a/packages/geom-tessellate/package.json +++ b/packages/geom-tessellate/package.json @@ -65,7 +65,6 @@ "2d", "3d", "convex", - "es6", "geometry", "polygon", "tessellation", diff --git a/packages/geom-voronoi/package.json b/packages/geom-voronoi/package.json index 461dd2d907..c1c922f9da 100644 --- a/packages/geom-voronoi/package.json +++ b/packages/geom-voronoi/package.json @@ -71,7 +71,6 @@ "delaunay", "dual", "edges", - "es6", "geometry", "graph", "incremental", diff --git a/packages/geom/package.json b/packages/geom/package.json index 6b55ef0de9..50e50eabbd 100644 --- a/packages/geom/package.json +++ b/packages/geom/package.json @@ -89,7 +89,6 @@ "2d", "centroid", "conversion", - "es6", "intersection", "geometry", "graphics", diff --git a/packages/gp/package.json b/packages/gp/package.json index 5af1100a2b..97ccc009e1 100644 --- a/packages/gp/package.json +++ b/packages/gp/package.json @@ -63,7 +63,6 @@ "keywords": [ "ast", "crossover", - "es6", "evolutionary", "generative", "genetic", diff --git a/packages/grid-iterators/package.json b/packages/grid-iterators/package.json index 4251de407d..03a73253a8 100644 --- a/packages/grid-iterators/package.json +++ b/packages/grid-iterators/package.json @@ -64,7 +64,6 @@ "keywords": [ "2d", "diagonal", - "es6", "grid", "hilbert", "iterator", diff --git a/packages/hdiff/package.json b/packages/hdiff/package.json index 4258f86842..924df98cce 100644 --- a/packages/hdiff/package.json +++ b/packages/hdiff/package.json @@ -67,7 +67,6 @@ "cli", "css", "diff", - "es6", "file", "git", "hiccup", diff --git a/packages/hdom-canvas/package.json b/packages/hdom-canvas/package.json index 0b1b8097f2..75f24bc2c9 100644 --- a/packages/hdom-canvas/package.json +++ b/packages/hdom-canvas/package.json @@ -61,7 +61,6 @@ "lib" ], "keywords": [ - "es6", "canvas", "datadriven", "drawing", diff --git a/packages/hdom-components/package.json b/packages/hdom-components/package.json index 11c36d0de2..9e732da35d 100644 --- a/packages/hdom-components/package.json +++ b/packages/hdom-components/package.json @@ -63,7 +63,6 @@ "utils" ], "keywords": [ - "es6", "typescript" ], "publishConfig": { diff --git a/packages/hdom-mock/package.json b/packages/hdom-mock/package.json index 460d450166..d761354c36 100644 --- a/packages/hdom-mock/package.json +++ b/packages/hdom-mock/package.json @@ -59,7 +59,6 @@ "lib" ], "keywords": [ - "es6", "typescript" ], "publishConfig": { diff --git a/packages/hdom/package.json b/packages/hdom/package.json index 47a42265b8..7e404ac838 100644 --- a/packages/hdom/package.json +++ b/packages/hdom/package.json @@ -70,7 +70,6 @@ "declarative", "diff", "dom", - "es6", "functional", "ioc", "iterator", diff --git a/packages/heaps/package.json b/packages/heaps/package.json index b2d6d07f21..78fa98282b 100644 --- a/packages/heaps/package.json +++ b/packages/heaps/package.json @@ -61,7 +61,6 @@ "keywords": [ "datastructure", "d-heap", - "es6", "heap", "pairing-heap", "priority-queue", diff --git a/packages/hiccup-canvas/package.json b/packages/hiccup-canvas/package.json index 01bd793637..180ebcf7ac 100644 --- a/packages/hiccup-canvas/package.json +++ b/packages/hiccup-canvas/package.json @@ -64,7 +64,6 @@ "canvas", "declarative", "draw", - "es6", "graphics", "hiccup", "scenegraph", diff --git a/packages/hiccup-carbon-icons/package.json b/packages/hiccup-carbon-icons/package.json index 77e9146779..55aea93eaa 100644 --- a/packages/hiccup-carbon-icons/package.json +++ b/packages/hiccup-carbon-icons/package.json @@ -59,7 +59,6 @@ ], "keywords": [ "carbon", - "es6", "hdom", "hiccup", "ibm", diff --git a/packages/hiccup-css/package.json b/packages/hiccup-css/package.json index a454117c85..f57d5ff4cb 100644 --- a/packages/hiccup-css/package.json +++ b/packages/hiccup-css/package.json @@ -62,7 +62,6 @@ "keywords": [ "clojure", "component", - "es6", "hiccup", "html", "iterator", diff --git a/packages/hiccup-html/package.json b/packages/hiccup-html/package.json index ae49001a36..9ff29572c7 100644 --- a/packages/hiccup-html/package.json +++ b/packages/hiccup-html/package.json @@ -57,7 +57,6 @@ ], "keywords": [ "attributes", - "es6", "hiccup", "html", "typecheck", diff --git a/packages/hiccup-markdown/package.json b/packages/hiccup-markdown/package.json index 3070f24bf3..389c87d43b 100644 --- a/packages/hiccup-markdown/package.json +++ b/packages/hiccup-markdown/package.json @@ -66,7 +66,6 @@ "lib" ], "keywords": [ - "es6", "ast", "conversion", "DOM", diff --git a/packages/hiccup-svg/package.json b/packages/hiccup-svg/package.json index f26b7bdc18..9a62999e5a 100644 --- a/packages/hiccup-svg/package.json +++ b/packages/hiccup-svg/package.json @@ -61,7 +61,6 @@ "keywords": [ "component", "conversion", - "es6", "generator", "hiccup", "hdom", diff --git a/packages/hiccup/package.json b/packages/hiccup/package.json index 58fddb071e..b942853648 100644 --- a/packages/hiccup/package.json +++ b/packages/hiccup/package.json @@ -63,7 +63,6 @@ "keywords": [ "clojure", "component", - "es6", "functional", "hiccup", "html", diff --git a/packages/idgen/package.json b/packages/idgen/package.json index 22d33a8f3e..f58d69153d 100644 --- a/packages/idgen/package.json +++ b/packages/idgen/package.json @@ -59,7 +59,6 @@ ], "keywords": [ "counter", - "es6", "freelist", "identifier", "typescript", diff --git a/packages/iges/package.json b/packages/iges/package.json index f4c7aaba7f..227621eed5 100644 --- a/packages/iges/package.json +++ b/packages/iges/package.json @@ -64,7 +64,6 @@ "keywords": [ "bezier", "cad", - "es6", "export", "fileformat", "iges", diff --git a/packages/imgui/package.json b/packages/imgui/package.json index 4322f00e0d..ca25ca9707 100644 --- a/packages/imgui/package.json +++ b/packages/imgui/package.json @@ -70,7 +70,6 @@ "keywords": [ "canvas", "component", - "es6", "gui", "hiccup", "imgui", diff --git a/packages/interceptors/package.json b/packages/interceptors/package.json index 691d15f576..da3ec49f2d 100644 --- a/packages/interceptors/package.json +++ b/packages/interceptors/package.json @@ -61,7 +61,6 @@ "lib" ], "keywords": [ - "es6", "event", "functional", "queue", diff --git a/packages/intervals/package.json b/packages/intervals/package.json index bc406b2945..fe5fc8d785 100644 --- a/packages/intervals/package.json +++ b/packages/intervals/package.json @@ -62,7 +62,6 @@ "keywords": [ "datastructure", "difference", - "es6", "intersection", "interval", "math", diff --git a/packages/iterators/package.json b/packages/iterators/package.json index 5fc3d64de0..4ce28b8dd7 100644 --- a/packages/iterators/package.json +++ b/packages/iterators/package.json @@ -61,7 +61,6 @@ "keywords": [ "clojure", "composition", - "es6", "functional", "generator", "iterator", diff --git a/packages/layout/package.json b/packages/layout/package.json index 5c9687f787..03de66d0be 100644 --- a/packages/layout/package.json +++ b/packages/layout/package.json @@ -57,7 +57,6 @@ "lib" ], "keywords": [ - "es6", "grid", "layout", "recursive", diff --git a/packages/leb128/package.json b/packages/leb128/package.json index babebd198a..8255784783 100644 --- a/packages/leb128/package.json +++ b/packages/leb128/package.json @@ -63,7 +63,6 @@ "LEB128", "binary", "conversion", - "es6", "typescript", "WASM" ], diff --git a/packages/lsys/package.json b/packages/lsys/package.json index f6f9419bc7..bc1aa5cb0d 100644 --- a/packages/lsys/package.json +++ b/packages/lsys/package.json @@ -67,7 +67,6 @@ "1d", "2d", "3d", - "es6", "generative", "geometry", "l-system", diff --git a/packages/malloc/package.json b/packages/malloc/package.json index 2c38334e67..c2675dd071 100644 --- a/packages/malloc/package.json +++ b/packages/malloc/package.json @@ -62,7 +62,6 @@ "keywords": [ "align", "allocator", - "es6", "memory", "memory-mapped", "pool", diff --git a/packages/math/package.json b/packages/math/package.json index 3a31f02396..de9642dd67 100644 --- a/packages/math/package.json +++ b/packages/math/package.json @@ -57,7 +57,6 @@ "lib" ], "keywords": [ - "es6", "cubic", "hermite", "interpolation", diff --git a/packages/matrices/package.json b/packages/matrices/package.json index f1ee410857..c04f4b1c0e 100644 --- a/packages/matrices/package.json +++ b/packages/matrices/package.json @@ -63,7 +63,6 @@ "keywords": [ "2d", "3d", - "es6", "codegen", "conversion", "euler-angles", diff --git a/packages/memoize/package.json b/packages/memoize/package.json index bd19c86c32..819ceddce5 100644 --- a/packages/memoize/package.json +++ b/packages/memoize/package.json @@ -58,7 +58,6 @@ ], "keywords": [ "cache", - "es6", "functional", "memoization", "typescript" diff --git a/packages/mime/package.json b/packages/mime/package.json index 5f66a8aba7..b6a3a359b0 100644 --- a/packages/mime/package.json +++ b/packages/mime/package.json @@ -58,7 +58,6 @@ ], "keywords": [ "database", - "es6", "fileformat", "mime", "mimedb", diff --git a/packages/morton/package.json b/packages/morton/package.json index 8cacb85b86..76dde18978 100644 --- a/packages/morton/package.json +++ b/packages/morton/package.json @@ -64,7 +64,6 @@ "conversion", "decode", "encode", - "es6", "hash", "morton", "nd", diff --git a/packages/oquery/package.json b/packages/oquery/package.json index 949392ddfc..0cdeeb2944 100644 --- a/packages/oquery/package.json +++ b/packages/oquery/package.json @@ -61,7 +61,6 @@ ], "keywords": [ "datalog", - "es6", "object", "pattern", "predicate", diff --git a/packages/parse/package.json b/packages/parse/package.json index b621056196..f4aad52d7e 100644 --- a/packages/parse/package.json +++ b/packages/parse/package.json @@ -71,7 +71,6 @@ "compiler", "composition", "dsl", - "es6", "functional", "grammar", "parser", diff --git a/packages/paths/package.json b/packages/paths/package.json index 01cfdf955d..f8cf2dc8c5 100644 --- a/packages/paths/package.json +++ b/packages/paths/package.json @@ -62,7 +62,6 @@ "accessor", "array", "deep", - "es6", "delete", "getter", "immutable", diff --git a/packages/pixel/package.json b/packages/pixel/package.json index c0743460a5..fd245f1fc3 100644 --- a/packages/pixel/package.json +++ b/packages/pixel/package.json @@ -60,7 +60,6 @@ "lib" ], "keywords": [ - "es6", "alpha", "blend", "blit", diff --git a/packages/pointfree-lang/package.json b/packages/pointfree-lang/package.json index 9874950c2e..b3046b2cd9 100644 --- a/packages/pointfree-lang/package.json +++ b/packages/pointfree-lang/package.json @@ -72,7 +72,6 @@ "dataflow", "cli", "dsl", - "es6", "forth", "functional", "grammar", diff --git a/packages/pointfree/package.json b/packages/pointfree/package.json index 86f3ea5bb1..533ec18fa9 100644 --- a/packages/pointfree/package.json +++ b/packages/pointfree/package.json @@ -65,7 +65,6 @@ "concatenative", "dataflow", "dsl", - "es6", "forth", "functional", "pipeline", diff --git a/packages/poisson/package.json b/packages/poisson/package.json index 0a51cc90e1..c8a897687f 100644 --- a/packages/poisson/package.json +++ b/packages/poisson/package.json @@ -66,7 +66,6 @@ "3d", "nd", "density", - "es6", "grid", "points", "poisson", diff --git a/packages/porter-duff/package.json b/packages/porter-duff/package.json index 58aee4da0f..e8b59b9c80 100644 --- a/packages/porter-duff/package.json +++ b/packages/porter-duff/package.json @@ -62,7 +62,6 @@ "blend", "color", "composition", - "es6", "pixel", "porter-duff", "premultiply", diff --git a/packages/quad-edge/package.json b/packages/quad-edge/package.json index 8e8b235fe2..572bddf565 100644 --- a/packages/quad-edge/package.json +++ b/packages/quad-edge/package.json @@ -55,7 +55,6 @@ ], "keywords": [ "dual", - "es6", "geometry", "graph", "mesh", diff --git a/packages/ramp/package.json b/packages/ramp/package.json index c23710743c..82a96741e4 100644 --- a/packages/ramp/package.json +++ b/packages/ramp/package.json @@ -62,7 +62,6 @@ ], "keywords": [ "animation", - "es6", "hermite", "interpolation", "interval", diff --git a/packages/random/package.json b/packages/random/package.json index 8183192fd7..a27e5d64af 100644 --- a/packages/random/package.json +++ b/packages/random/package.json @@ -58,7 +58,6 @@ "lib" ], "keywords": [ - "es6", "generator", "PRNG", "random", diff --git a/packages/range-coder/package.json b/packages/range-coder/package.json index e021d42876..1c37e1f574 100644 --- a/packages/range-coder/package.json +++ b/packages/range-coder/package.json @@ -61,7 +61,6 @@ "binary", "compression", "entropy", - "es6", "packer", "typescript" ], diff --git a/packages/rdom-canvas/package.json b/packages/rdom-canvas/package.json index 5879fa5630..980926f099 100644 --- a/packages/rdom-canvas/package.json +++ b/packages/rdom-canvas/package.json @@ -67,7 +67,6 @@ "component", "declarative", "hiccup", - "es6", "scenegraph", "typescript", "wrapper" diff --git a/packages/rdom-components/package.json b/packages/rdom-components/package.json index 8a27fb07b2..4cecfc3cc2 100644 --- a/packages/rdom-components/package.json +++ b/packages/rdom-components/package.json @@ -62,7 +62,6 @@ "lib" ], "keywords": [ - "es6", "typescript" ], "publishConfig": { diff --git a/packages/rdom/package.json b/packages/rdom/package.json index af5667966e..7686848aa6 100644 --- a/packages/rdom/package.json +++ b/packages/rdom/package.json @@ -68,7 +68,6 @@ "css", "compiler", "dom", - "es6", "component", "hiccup", "html", diff --git a/packages/resolve-map/package.json b/packages/resolve-map/package.json index c05009617a..d5fd9c5f7b 100644 --- a/packages/resolve-map/package.json +++ b/packages/resolve-map/package.json @@ -61,7 +61,6 @@ "keywords": [ "configuration", "datastructure", - "es6", "DAG", "graph", "JSON", diff --git a/packages/rle-pack/package.json b/packages/rle-pack/package.json index 982bb51394..63f94d5d82 100644 --- a/packages/rle-pack/package.json +++ b/packages/rle-pack/package.json @@ -62,7 +62,6 @@ "binary", "bitwise", "compression", - "es6", "packer", "rle", "typescript", diff --git a/packages/router/package.json b/packages/router/package.json index bfae19bd2a..62034f28ff 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -63,7 +63,6 @@ "keywords": [ "browser", "declarative", - "es6", "html", "history", "parametric", diff --git a/packages/rstream-csp/package.json b/packages/rstream-csp/package.json index 57d8109b5c..d96f559b06 100644 --- a/packages/rstream-csp/package.json +++ b/packages/rstream-csp/package.json @@ -64,7 +64,6 @@ "reactive", "stream", "rstream", - "es6", "typescript" ], "publishConfig": { diff --git a/packages/rstream-dot/package.json b/packages/rstream-dot/package.json index 6f0828826c..99172fa477 100644 --- a/packages/rstream-dot/package.json +++ b/packages/rstream-dot/package.json @@ -59,7 +59,6 @@ "keywords": [ "conversion", "dataflow", - "es6", "fileformat", "graph", "graphviz", diff --git a/packages/rstream-gestures/package.json b/packages/rstream-gestures/package.json index 462e92ec0d..d37e2b8e4f 100644 --- a/packages/rstream-gestures/package.json +++ b/packages/rstream-gestures/package.json @@ -62,7 +62,6 @@ ], "keywords": [ "dataflow", - "es6", "event", "interaction", "mouse", diff --git a/packages/rstream-graph/package.json b/packages/rstream-graph/package.json index 9d4726eafa..9089a88d38 100644 --- a/packages/rstream-graph/package.json +++ b/packages/rstream-graph/package.json @@ -67,7 +67,6 @@ "keywords": [ "compute", "dataflow", - "es6", "graph", "reactive", "stream", diff --git a/packages/rstream-log-file/package.json b/packages/rstream-log-file/package.json index 623437b844..9c468c4528 100644 --- a/packages/rstream-log-file/package.json +++ b/packages/rstream-log-file/package.json @@ -57,7 +57,6 @@ "lib" ], "keywords": [ - "es6", "file", "logger", "node", diff --git a/packages/rstream-log/package.json b/packages/rstream-log/package.json index bcc61de09d..045079ae19 100644 --- a/packages/rstream-log/package.json +++ b/packages/rstream-log/package.json @@ -63,7 +63,6 @@ "xform" ], "keywords": [ - "es6", "logger", "multilevel", "multiplex", diff --git a/packages/rstream-query/package.json b/packages/rstream-query/package.json index f94b82c5c7..7e9b79ead0 100644 --- a/packages/rstream-query/package.json +++ b/packages/rstream-query/package.json @@ -68,7 +68,6 @@ "database", "dataflow", "datalog", - "es6", "graph", "query", "reactive", diff --git a/packages/rstream/package.json b/packages/rstream/package.json index bc21818138..08dfcba05a 100644 --- a/packages/rstream/package.json +++ b/packages/rstream/package.json @@ -69,7 +69,6 @@ "async", "datastructure", "event", - "es6", "graph", "pipeline", "pubsub", diff --git a/packages/sax/package.json b/packages/sax/package.json index 49621b4682..c92b378a70 100644 --- a/packages/sax/package.json +++ b/packages/sax/package.json @@ -59,7 +59,6 @@ "lib" ], "keywords": [ - "es6", "FSM", "parser", "SAX", diff --git a/packages/scenegraph/package.json b/packages/scenegraph/package.json index c2a4e7d1d1..968bc4966f 100644 --- a/packages/scenegraph/package.json +++ b/packages/scenegraph/package.json @@ -62,7 +62,6 @@ "keywords": [ "2d", "3d", - "es6", "scenegraph", "typescript" ], diff --git a/packages/seq/package.json b/packages/seq/package.json index 91a9484034..e6894dfe01 100644 --- a/packages/seq/package.json +++ b/packages/seq/package.json @@ -58,7 +58,6 @@ "lib" ], "keywords": [ - "es6", "typescript" ], "publishConfig": { diff --git a/packages/sexpr/package.json b/packages/sexpr/package.json index f6b9e8c9a2..b5f7ffbda1 100644 --- a/packages/sexpr/package.json +++ b/packages/sexpr/package.json @@ -61,7 +61,6 @@ "keywords": [ "ast", "dsl", - "es6", "interpreter", "lisp", "parser", diff --git a/packages/shader-ast-glsl/package.json b/packages/shader-ast-glsl/package.json index 037999126a..f7b16ae067 100644 --- a/packages/shader-ast-glsl/package.json +++ b/packages/shader-ast-glsl/package.json @@ -63,7 +63,6 @@ "ast", "codegen", "dsl", - "es6", "glsl", "gpgpu", "shader", diff --git a/packages/shader-ast-js/package.json b/packages/shader-ast-js/package.json index 64efc4c201..3496f42373 100644 --- a/packages/shader-ast-js/package.json +++ b/packages/shader-ast-js/package.json @@ -70,7 +70,6 @@ "compiler", "dsl", "emulator", - "es6", "glsl", "shader", "typescript", diff --git a/packages/shader-ast-stdlib/package.json b/packages/shader-ast-stdlib/package.json index d38e1059df..fc73914d09 100644 --- a/packages/shader-ast-stdlib/package.json +++ b/packages/shader-ast-stdlib/package.json @@ -71,7 +71,6 @@ "ast", "blur", "dsl", - "es6", "fog", "functional", "higher-order", diff --git a/packages/shader-ast/package.json b/packages/shader-ast/package.json index 1b81a6931c..063f8a931f 100644 --- a/packages/shader-ast/package.json +++ b/packages/shader-ast/package.json @@ -68,7 +68,6 @@ "codegen", "compiler", "dsl", - "es6", "gpgpu", "glsl", "shader", diff --git a/packages/simd/package.json b/packages/simd/package.json index 6ff6ab33aa..9a076fb449 100644 --- a/packages/simd/package.json +++ b/packages/simd/package.json @@ -62,7 +62,6 @@ "keywords": [ "assemblyscript", "batchprocess", - "es6", "simd", "typescript", "vector", diff --git a/packages/soa/package.json b/packages/soa/package.json index fe11324ea6..aadd0ee669 100644 --- a/packages/soa/package.json +++ b/packages/soa/package.json @@ -64,7 +64,6 @@ "aos", "data-oriented", "datastructure", - "es6", "interop", "memory-mapped", "layout", diff --git a/packages/sparse/package.json b/packages/sparse/package.json index 5bb2155600..0a179b7641 100644 --- a/packages/sparse/package.json +++ b/packages/sparse/package.json @@ -61,7 +61,6 @@ "adjacency", "COO", "CSR", - "es6", "graph", "matrix", "sparse", diff --git a/packages/strings/package.json b/packages/strings/package.json index f7a858d93e..743c76aee8 100644 --- a/packages/strings/package.json +++ b/packages/strings/package.json @@ -63,7 +63,6 @@ "center", "composition", "conversion", - "es6", "float", "format", "functional", diff --git a/packages/system/package.json b/packages/system/package.json index 1f1b9dd0b4..8be54d4a62 100644 --- a/packages/system/package.json +++ b/packages/system/package.json @@ -60,7 +60,6 @@ "keywords": [ "component", "dependency", - "es6", "graph", "injection", "topology", diff --git a/packages/text-canvas/package.json b/packages/text-canvas/package.json index b3653205b9..eebfb57003 100644 --- a/packages/text-canvas/package.json +++ b/packages/text-canvas/package.json @@ -72,7 +72,6 @@ "format", "HTML", "line", - "es6", "rect", "table", "text", diff --git a/packages/transducers-binary/package.json b/packages/transducers-binary/package.json index b87aae9c15..926fb7d04a 100644 --- a/packages/transducers-binary/package.json +++ b/packages/transducers-binary/package.json @@ -68,7 +68,6 @@ "bytes", "decode", "encode", - "es6", "hexdump", "iterator", "partition", diff --git a/packages/transducers-fsm/package.json b/packages/transducers-fsm/package.json index c820dd526a..cc4e43ae53 100644 --- a/packages/transducers-fsm/package.json +++ b/packages/transducers-fsm/package.json @@ -58,7 +58,6 @@ "lib" ], "keywords": [ - "es6", "fsm", "transducer", "typescript" diff --git a/packages/transducers-hdom/package.json b/packages/transducers-hdom/package.json index d7e3f4dc0b..4d0e4dd6e5 100644 --- a/packages/transducers-hdom/package.json +++ b/packages/transducers-hdom/package.json @@ -60,7 +60,6 @@ ], "keywords": [ "diff", - "es6", "hdom", "rstream", "transducer", diff --git a/packages/transducers-patch/package.json b/packages/transducers-patch/package.json index e0a4ba50f8..31752790cb 100644 --- a/packages/transducers-patch/package.json +++ b/packages/transducers-patch/package.json @@ -63,7 +63,6 @@ "keywords": [ "array", "diff", - "es6", "immutable", "object", "patch", diff --git a/packages/transducers-stats/package.json b/packages/transducers-stats/package.json index f8c8d08851..637c9b5eba 100644 --- a/packages/transducers-stats/package.json +++ b/packages/transducers-stats/package.json @@ -63,7 +63,6 @@ "bollinger", "donchian", "ema", - "es6", "macd", "math", "moving-average", diff --git a/packages/transducers/package.json b/packages/transducers/package.json index 62c702a534..3b990ce318 100644 --- a/packages/transducers/package.json +++ b/packages/transducers/package.json @@ -71,7 +71,6 @@ "keywords": [ "array", "composition", - "es6", "functional", "generator", "iterator", diff --git a/packages/unionstruct/package.json b/packages/unionstruct/package.json index d79a677e05..fd4571c8b6 100644 --- a/packages/unionstruct/package.json +++ b/packages/unionstruct/package.json @@ -59,7 +59,6 @@ "bitfield", "c", "cpp", - "es6", "interop", "struct", "typescript", diff --git a/packages/vector-pools/package.json b/packages/vector-pools/package.json index fa4fdac012..187cbcd9ca 100644 --- a/packages/vector-pools/package.json +++ b/packages/vector-pools/package.json @@ -62,7 +62,6 @@ "lib" ], "keywords": [ - "es6", "memory", "memory-mapped", "pool", diff --git a/packages/vectors/package.json b/packages/vectors/package.json index b7022388aa..5925f1c4fa 100644 --- a/packages/vectors/package.json +++ b/packages/vectors/package.json @@ -78,7 +78,6 @@ "distance", "dotproduct", "equality", - "es6", "geometry", "graphics", "glsl", diff --git a/packages/viz/package.json b/packages/viz/package.json index 82db7eeada..8e2965c11b 100644 --- a/packages/viz/package.json +++ b/packages/viz/package.json @@ -73,7 +73,6 @@ "area", "chart", "declarative", - "es6", "hiccup", "interval", "line", diff --git a/packages/webgl-msdf/package.json b/packages/webgl-msdf/package.json index 89ac95445a..e7b5353e9c 100644 --- a/packages/webgl-msdf/package.json +++ b/packages/webgl-msdf/package.json @@ -62,7 +62,6 @@ "lib" ], "keywords": [ - "es6", "font", "layout", "msdf", diff --git a/packages/webgl-shadertoy/package.json b/packages/webgl-shadertoy/package.json index d5e9f22bf2..55fc2df317 100644 --- a/packages/webgl-shadertoy/package.json +++ b/packages/webgl-shadertoy/package.json @@ -60,7 +60,6 @@ "lib" ], "keywords": [ - "es6", "graphics", "shader-ast", "shadertoy", diff --git a/packages/webgl/package.json b/packages/webgl/package.json index 9f1ea0cadb..64b20a8063 100644 --- a/packages/webgl/package.json +++ b/packages/webgl/package.json @@ -76,7 +76,6 @@ ], "keywords": [ "declarative", - "es6", "FBO", "GPGPU", "graphics", diff --git a/packages/zipper/package.json b/packages/zipper/package.json index 56a8891c35..f332c0a20d 100644 --- a/packages/zipper/package.json +++ b/packages/zipper/package.json @@ -61,7 +61,6 @@ "keywords": [ "datastructure", "edit", - "es6", "functional", "immutable", "navigation", From 43a26ccfdf863e6690b5eff19383832070d8bf4e Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 15 Sep 2020 22:55:05 +0100 Subject: [PATCH 040/106] docs(egf): update readme --- packages/egf/README.md | 3 ++- packages/egf/tpl.readme.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/egf/README.md b/packages/egf/README.md index 9633db5e4f..50720a8236 100644 --- a/packages/egf/README.md +++ b/packages/egf/README.md @@ -86,6 +86,7 @@ are only available in NodeJS. (Non-exhaustive list) +- [x] [VSCode syntax highlighting](https://github.com/thi-ng/egf-language-support) - [x] JSON -> EGF conversion - [ ] Async tag parsing - [ ] URL support for `#file` tag @@ -107,7 +108,7 @@ yarn add @thi.ng/egf ``` -Package sizes (gzipped, pre-treeshake): ESM: 2.70 KB / CJS: 2.77 KB / UMD: 2.77 KB +Package sizes (gzipped, pre-treeshake): ESM: 2.70 KB / CJS: 2.77 KB / UMD: 2.78 KB ## Dependencies diff --git a/packages/egf/tpl.readme.md b/packages/egf/tpl.readme.md index 209af21f21..ee346f4e2c 100644 --- a/packages/egf/tpl.readme.md +++ b/packages/egf/tpl.readme.md @@ -65,6 +65,7 @@ ${status} (Non-exhaustive list) +- [x] [VSCode syntax highlighting](https://github.com/thi-ng/egf-language-support) - [x] JSON -> EGF conversion - [ ] Async tag parsing - [ ] URL support for `#file` tag From f9775ca0bba369ce46c0d13f81536e6661d45abb Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 15 Sep 2020 23:00:27 +0100 Subject: [PATCH 041/106] docs: update main readme (pkg list) --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c83f8eb1f7..cf1128a675 100644 --- a/README.md +++ b/README.md @@ -114,13 +114,10 @@ fairly detailed overview for contributors here: ## Projects -### New / unreleased packages in development + ### Fundamentals @@ -193,6 +190,7 @@ feature or `develop` branches) | [`@thi.ng/dcons`](./packages/dcons) | [![version](https://img.shields.io/npm/v/@thi.ng/dcons.svg)](https://www.npmjs.com/package/@thi.ng/dcons) | [changelog](./packages/dcons/CHANGELOG.md) | Doubly-linked list | | [`@thi.ng/diff`](./packages/diff) | [![version](https://img.shields.io/npm/v/@thi.ng/diff.svg)](https://www.npmjs.com/package/@thi.ng/diff) | [changelog](./packages/diff/CHANGELOG.md) | Array & object diffing | | [`@thi.ng/dgraph`](./packages/dgraph) | [![version](https://img.shields.io/npm/v/@thi.ng/dgraph.svg)](https://www.npmjs.com/package/@thi.ng/dgraph) | [changelog](./packages/dgraph/CHANGELOG.md) | Dependency graph | +| [`@thi.ng/egf`](./packages/egf) | [![version](https://img.shields.io/npm/v/@thi.ng/egf.svg)](https://www.npmjs.com/package/@thi.ng/egf) | [changelog](./packages/egf/CHANGELOG.md) | Extensible Graph Format | | [`@thi.ng/gp`](./packages/gp) | [![version](https://img.shields.io/npm/v/@thi.ng/gp.svg)](https://www.npmjs.com/package/@thi.ng/gp) | [changelog](./packages/gp/CHANGELOG.md) | Genetic programming helpers / AST gen | | [`@thi.ng/heaps`](./packages/heaps) | [![version](https://img.shields.io/npm/v/@thi.ng/heaps.svg)](https://www.npmjs.com/package/@thi.ng/heaps) | [changelog](./packages/heaps/CHANGELOG.md) | Binary & d-ary heap impls | | [`@thi.ng/idgen`](./packages/idgen) | [![version](https://img.shields.io/npm/v/@thi.ng/idgen.svg)](https://www.npmjs.com/package/@thi.ng/idgen) | [changelog](./packages/idgen/CHANGELOG.md) | Versioned ID generation / free-list | From 9d69ff73949a0090af0088a6fcda43aafea93823 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 15 Sep 2020 23:16:31 +0100 Subject: [PATCH 042/106] docs(egf): fix branch links in readme --- packages/egf/README.md | 28 ++++++++++++++-------------- packages/egf/package.json | 1 - packages/egf/tpl.readme.md | 12 ++++++------ 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/packages/egf/README.md b/packages/egf/README.md index 50720a8236..ad93c7ee88 100644 --- a/packages/egf/README.md +++ b/packages/egf/README.md @@ -53,7 +53,7 @@ line based, plain text data format and package supports: - Hand-optimized parser, largely regexp free - Configurable GraphViz DOT export -![example graph](https://raw.githubusercontent.com/thi-ng/umbrella/feature/egf/assets/egf/egf-readme2.png) +![example graph](https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/egf/egf-readme2.png) ([Source for this example graph is further below](#basic-example)) @@ -112,14 +112,14 @@ Package sizes (gzipped, pre-treeshake): ESM: 2.70 KB / CJS: 2.77 KB / UMD: 2.78 ## Dependencies -- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/api) -- [@thi.ng/associative](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/associative) -- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/checks) -- [@thi.ng/dot](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/dot) -- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/errors) -- [@thi.ng/prefixes](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/prefixes) -- [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/strings) -- [@thi.ng/transducers-binary](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/transducers-binary) +- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/develop/packages/api) +- [@thi.ng/associative](https://github.com/thi-ng/umbrella/tree/develop/packages/associative) +- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/develop/packages/checks) +- [@thi.ng/dot](https://github.com/thi-ng/umbrella/tree/develop/packages/dot) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/develop/packages/errors) +- [@thi.ng/prefixes](https://github.com/thi-ng/umbrella/tree/develop/packages/prefixes) +- [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/develop/packages/strings) +- [@thi.ng/transducers-binary](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers-binary) ## API @@ -127,11 +127,11 @@ Package sizes (gzipped, pre-treeshake): ESM: 2.70 KB / CJS: 2.77 KB / UMD: 2.78 **TODO - Full docs forthcoming...** -- [api.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Data structures & options -- [dot.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/dot.ts) - Graphviz export (via +- [api.ts](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/src/api.ts) - Data structures & options +- [dot.ts](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/src/dot.ts) - Graphviz export (via [@thi.ng/dot](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/)) -- [parser.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/parser.ts) - Main parser -- [tags.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/tags.ts) - Tagged value parsers +- [parser.ts](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/src/parser.ts) - Main parser +- [tags.ts](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/src/tags.ts) - Tagged value parsers ### Basic example @@ -462,7 +462,7 @@ Parsing the `main.egf` file (with node resolution/inlining and pruning) produces Complying JS objects can be converted to EGF using the `toEGF()` function. This function takes an iterable of -[Node](https://github.com/thi-ng/umbrella/blob/feature/egf/packages/egf/src/api.ts#L5) +[Node](https://github.com/thi-ng/umbrella/blob/develop/packages/egf/src/api.ts#L5) objects, optional prefix mappings and an optional property serialization function to deal with custom tagged values. The default property formatter (`toEGFProp()`) handles various values for built-in tags and can be used in diff --git a/packages/egf/package.json b/packages/egf/package.json index b9f479c0ec..174706c4e3 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -77,7 +77,6 @@ }, "sideEffects": false, "thi.ng": { - "branch": "feature/egf", "status": "alpha", "year": 2020 } diff --git a/packages/egf/tpl.readme.md b/packages/egf/tpl.readme.md index ee346f4e2c..bdb256d8c9 100644 --- a/packages/egf/tpl.readme.md +++ b/packages/egf/tpl.readme.md @@ -36,7 +36,7 @@ line based, plain text data format and package supports: - Hand-optimized parser, largely regexp free - Configurable GraphViz DOT export -![example graph](https://raw.githubusercontent.com/thi-ng/umbrella/feature/egf/assets/egf/egf-readme2.png) +![example graph](https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/egf/egf-readme2.png) ([Source for this example graph is further below](#basic-example)) @@ -97,11 +97,11 @@ ${docLink} **TODO - Full docs forthcoming...** -- [api.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/api.ts) - Data structures & options -- [dot.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/dot.ts) - Graphviz export (via +- [api.ts](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/src/api.ts) - Data structures & options +- [dot.ts](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/src/dot.ts) - Graphviz export (via [@thi.ng/dot](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/)) -- [parser.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/parser.ts) - Main parser -- [tags.ts](https://github.com/thi-ng/umbrella/tree/feature/egf/packages/egf/src/tags.ts) - Tagged value parsers +- [parser.ts](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/src/parser.ts) - Main parser +- [tags.ts](https://github.com/thi-ng/umbrella/tree/develop/packages/egf/src/tags.ts) - Tagged value parsers ### Basic example @@ -432,7 +432,7 @@ Parsing the `main.egf` file (with node resolution/inlining and pruning) produces Complying JS objects can be converted to EGF using the `toEGF()` function. This function takes an iterable of -[Node](https://github.com/thi-ng/umbrella/blob/feature/egf/packages/egf/src/api.ts#L5) +[Node](https://github.com/thi-ng/umbrella/blob/develop/packages/egf/src/api.ts#L5) objects, optional prefix mappings and an optional property serialization function to deal with custom tagged values. The default property formatter (`toEGFProp()`) handles various values for built-in tags and can be used in From 0e31c69942c2b88df9239a13051f158efe7fc38c Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 17 Sep 2020 12:16:06 +0100 Subject: [PATCH 043/106] feat(date): add DateTime, defIterator, add/update iterators --- packages/date/README.md | 4 +- packages/date/src/api.ts | 7 +++ packages/date/src/datetime.ts | 80 +++++++++++++++++++++++++++++++++ packages/date/src/days.ts | 28 ------------ packages/date/src/format.ts | 7 +++ packages/date/src/hours.ts | 31 ------------- packages/date/src/index.ts | 9 +--- packages/date/src/iterators.ts | 82 ++++++++++++++++++++++++++++++++++ packages/date/src/minutes.ts | 34 -------------- packages/date/src/months.ts | 25 ----------- packages/date/src/seconds.ts | 37 --------------- packages/date/src/utils.ts | 11 ----- packages/date/src/years.ts | 24 ---------- 13 files changed, 181 insertions(+), 198 deletions(-) create mode 100644 packages/date/src/datetime.ts delete mode 100644 packages/date/src/days.ts delete mode 100644 packages/date/src/hours.ts create mode 100644 packages/date/src/iterators.ts delete mode 100644 packages/date/src/minutes.ts delete mode 100644 packages/date/src/months.ts delete mode 100644 packages/date/src/seconds.ts delete mode 100644 packages/date/src/utils.ts delete mode 100644 packages/date/src/years.ts diff --git a/packages/date/README.md b/packages/date/README.md index 4633873b7e..3d3916fb60 100644 --- a/packages/date/README.md +++ b/packages/date/README.md @@ -26,6 +26,8 @@ Date/timestamp iterators, formatters, rounding. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdate%5D) + ## Installation ```bash @@ -40,7 +42,7 @@ yarn add @thi.ng/date ``` -Package sizes (gzipped, pre-treeshake): ESM: 1.19 KB / CJS: 1.33 KB / UMD: 1.31 KB +Package sizes (gzipped, pre-treeshake): ESM: 1.28 KB / CJS: 1.43 KB / UMD: 1.42 KB ## Dependencies diff --git a/packages/date/src/api.ts b/packages/date/src/api.ts index be76bb08e6..78100c5d4a 100644 --- a/packages/date/src/api.ts +++ b/packages/date/src/api.ts @@ -6,6 +6,8 @@ export const WEEK = 7 * DAY; export const MONTH = 30.4375 * DAY; export const YEAR = 365.25 * DAY; +export type Precision = "y" | "M" | "d" | "h" | "m" | "s" | "t"; + export const DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; export const MONTH_NAMES = [ @@ -25,4 +27,9 @@ export const MONTH_NAMES = [ export const WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; +export interface EpochIteratorConstructor { + ([from, to]: number[]): EpochIterator; + (from: number, to: number): EpochIterator; +} + export type EpochIterator = IterableIterator; diff --git a/packages/date/src/datetime.ts b/packages/date/src/datetime.ts new file mode 100644 index 0000000000..8579d9900d --- /dev/null +++ b/packages/date/src/datetime.ts @@ -0,0 +1,80 @@ +import { DAYS_IN_MONTH, Precision } from "./api"; + +export class DateTime { + t: number; + s: number; + m: number; + h: number; + d: number; + M: number; + y: number; + + constructor(epoch: number, id: Precision = "t") { + const x = new Date(epoch); + const prec = "yMdhmst".indexOf(id); + this.y = prec >= 0 ? x.getUTCFullYear() : 1970; + this.M = prec >= 1 ? x.getUTCMonth() : 0; + this.d = prec >= 2 ? x.getUTCDate() : 1; + this.h = prec >= 3 ? x.getUTCHours() : 0; + this.m = prec >= 4 ? x.getUTCMinutes() : 0; + this.s = prec >= 5 ? x.getUTCSeconds() : 0; + this.t = prec >= 6 ? x.getUTCMilliseconds() : 0; + } + + getTime() { + return Date.UTC(this.y, this.M, this.d, this.h, this.m, this.s, this.t); + } + + incMillisecond() { + if (++this.t > 999) { + this.t = 0; + this.incSecond(); + } + return this.t; + } + + incSecond() { + if (++this.s > 59) { + this.s = 0; + this.incMinute(); + } + return this.s; + } + + incMinute() { + if (++this.m > 59) { + this.m = 0; + this.incHour(); + } + return this.m; + } + + incHour() { + if (++this.h > 23) { + this.h = 0; + this.incDay(); + } + return this.h; + } + + incDay() { + if (++this.d > DAYS_IN_MONTH[this.M]) { + this.d = 1; + this.incMonth(); + } + return this.d; + } + + incMonth() { + if (++this.M > 11) { + this.M = 0; + ++this.y; + } + return this.M; + } + + incYear() { + // TODO epoch overflow handling, throw error? + return ++this.y; + } +} diff --git a/packages/date/src/days.ts b/packages/date/src/days.ts deleted file mode 100644 index ac8c8f4f89..0000000000 --- a/packages/date/src/days.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { DAYS_IN_MONTH, EpochIterator } from "./api"; -import { dateParts } from "./utils"; - -/** - * Yields iterator of UTC timestamps in given semi-open interval in daily - * precision (each timestamp is at midnight/beginning of each day). - * - * @param from - * @param to - */ -export function days([from, to]: number[]): EpochIterator; -export function days(from: number, to: number): EpochIterator; -export function* days(...xs: any[]): EpochIterator { - const [from, to] = xs.length > 1 ? xs : xs[0]; - let [y, m, d] = dateParts(from); - let epoch = from; - while (epoch < to) { - epoch = Date.UTC(y, m, d); - if (epoch >= from && epoch < to) yield epoch; - if (++d > DAYS_IN_MONTH[m]) { - d = 1; - if (++m > 11) { - m = 0; - ++y; - } - } - } -} diff --git a/packages/date/src/format.ts b/packages/date/src/format.ts index 06e7f7833f..d2b50bff44 100644 --- a/packages/date/src/format.ts +++ b/packages/date/src/format.ts @@ -40,6 +40,13 @@ export const FORMATTERS: Record> = { * Zero-padded 2-digit hour of day (0-23) */ HH: (d) => Z2(d.getHours()), + /** + * Zero-padded hour of day (1-12) + */ + hh: (d) => { + const h = d.getHours() % 12; + return Z2(h > 0 ? h : 12); + }, /** * Unpadded hour of day (1-12) */ diff --git a/packages/date/src/hours.ts b/packages/date/src/hours.ts deleted file mode 100644 index 93c661447e..0000000000 --- a/packages/date/src/hours.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { DAYS_IN_MONTH, EpochIterator } from "./api"; -import { dateParts } from "./utils"; - -/** - * Yields iterator of UTC timestamps in given semi-open interval in hourly - * precision. - * - * @param from - * @param to - */ -export function hours([from, to]: number[]): EpochIterator; -export function hours(from: number, to: number): EpochIterator; -export function* hours(...xs: any[]): EpochIterator { - const [from, to] = xs.length > 1 ? xs : xs[0]; - let [y, m, d, h] = dateParts(from); - let epoch = from; - while (epoch < to) { - epoch = Date.UTC(y, m, d, h); - if (epoch >= from && epoch < to) yield epoch; - if (++h > 23) { - h = 0; - if (++d > DAYS_IN_MONTH[m]) { - d = 1; - if (++m > 11) { - m = 0; - ++y; - } - } - } - } -} diff --git a/packages/date/src/index.ts b/packages/date/src/index.ts index 16f716b6b4..070cb24250 100644 --- a/packages/date/src/index.ts +++ b/packages/date/src/index.ts @@ -1,10 +1,5 @@ export * from "./api"; -export * from "./days"; +export * from "./datetime"; export * from "./format"; -export * from "./hours"; -export * from "./minutes"; -export * from "./months"; +export * from "./iterators"; export * from "./round"; -export * from "./seconds"; -export * from "./utils"; -export * from "./years"; diff --git a/packages/date/src/iterators.ts b/packages/date/src/iterators.ts new file mode 100644 index 0000000000..a9e2ebc44a --- /dev/null +++ b/packages/date/src/iterators.ts @@ -0,0 +1,82 @@ +import type { Fn } from "@thi.ng/api"; +import type { EpochIterator, EpochIteratorConstructor, Precision } from "./api"; +import { DateTime } from "./datetime"; + +export const defIterator = ( + prec: Precision, + tick: Fn +): EpochIteratorConstructor => { + return function* (...xs: any[]): EpochIterator { + const [from, to] = xs.length > 1 ? xs : xs[0]; + let state = new DateTime(from, prec); + let epoch = from; + while (epoch < to) { + epoch = state.getTime(); + if (epoch >= from && epoch < to) yield epoch; + tick(state); + } + }; +}; + +/** + * Yields iterator of UTC timestamps in given semi-open interval in yearly + * precision (each timestamp is at beginning of each year). + * + * @param from + * @param to + */ +export const years = defIterator("y", (d) => d.incYear()); + +/** + * Yields iterator of UTC timestamps in given semi-open interval in monthly + * precision (each timestamp is at beginning of each month). + * + * @param from + * @param to + */ +export const months = defIterator("M", (d) => d.incMonth()); + +/** + * Yields iterator of UTC timestamps in given semi-open interval in daily + * precision (each timestamp is at midnight/beginning of each day). + * + * @param from + * @param to + */ +export const days = defIterator("d", (d) => d.incDay()); + +/** + * Yields iterator of UTC timestamps in given semi-open interval in hourly + * precision. + * + * @param from + * @param to + */ +export const hours = defIterator("h", (d) => d.incHour()); + +/** + * Yields iterator of UTC timestamps in given semi-open interval in minute + * precision. + * + * @param from + * @param to + */ +export const minutes = defIterator("m", (d) => d.incMinute()); + +/** + * Yields iterator of UTC timestamps in given semi-open interval in second + * precision. + * + * @param from + * @param to + */ +export const seconds = defIterator("s", (d) => d.incSecond()); + +/** + * Yields iterator of UTC timestamps in given semi-open interval in millisecond + * precision. + * + * @param from + * @param to + */ +export const milliseconds = defIterator("t", (d) => d.incMillisecond()); diff --git a/packages/date/src/minutes.ts b/packages/date/src/minutes.ts deleted file mode 100644 index 8ae32a3164..0000000000 --- a/packages/date/src/minutes.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { DAYS_IN_MONTH, EpochIterator } from "./api"; -import { dateParts } from "./utils"; - -/** - * Yields iterator of UTC timestamps in given semi-open interval in minute - * precision. - * - * @param from - * @param to - */ -export function minutes([from, to]: number[]): EpochIterator; -export function minutes(from: number, to: number): EpochIterator; -export function* minutes(...xs: any[]): EpochIterator { - const [from, to] = xs.length > 1 ? xs : xs[0]; - let [y, m, d, h, mm] = dateParts(from); - let epoch = from; - while (epoch < to) { - epoch = Date.UTC(y, m, d, h, mm); - if (epoch >= from && epoch < to) yield epoch; - if (++mm > 59) { - mm = 0; - if (++h > 23) { - h = 0; - if (++d > DAYS_IN_MONTH[m]) { - d = 1; - if (++m > 11) { - m = 0; - ++y; - } - } - } - } - } -} diff --git a/packages/date/src/months.ts b/packages/date/src/months.ts deleted file mode 100644 index d3dbb85d81..0000000000 --- a/packages/date/src/months.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { EpochIterator } from "./api"; -import { dateParts } from "./utils"; - -/** - * Yields iterator of UTC timestamps in given semi-open interval in monthly - * precision (each timestamp is at beginning of each month). - * - * @param from - * @param to - */ -export function months([from, to]: number[]): EpochIterator; -export function months(from: number, to: number): EpochIterator; -export function* months(...xs: any[]): EpochIterator { - const [from, to] = xs.length > 1 ? xs : xs[0]; - let [y, m] = dateParts(from); - let epoch = from; - while (epoch < to) { - epoch = Date.UTC(y, m); - if (epoch >= from && epoch < to) yield epoch; - if (++m > 11) { - m = 0; - ++y; - } - } -} diff --git a/packages/date/src/seconds.ts b/packages/date/src/seconds.ts deleted file mode 100644 index 406e898d7c..0000000000 --- a/packages/date/src/seconds.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { DAYS_IN_MONTH, EpochIterator } from "./api"; -import { dateParts } from "./utils"; - -/** - * Yields iterator of UTC timestamps in given semi-open interval in second - * precision. - * - * @param from - * @param to - */ -export function seconds([from, to]: number[]): EpochIterator; -export function seconds(from: number, to: number): EpochIterator; -export function* seconds(...xs: any[]): EpochIterator { - const [from, to] = xs.length > 1 ? xs : xs[0]; - let [y, m, d, h, mm, s] = dateParts(from); - let epoch = from; - while (epoch < to) { - epoch = Date.UTC(y, m, d, h, mm, s); - if (epoch >= from && epoch < to) yield epoch; - if (++s > 59) { - s = 0; - if (++mm > 59) { - mm = 0; - if (++h > 23) { - h = 0; - if (++d > DAYS_IN_MONTH[m]) { - d = 1; - if (++m === 12) { - m = 0; - ++y; - } - } - } - } - } - } -} diff --git a/packages/date/src/utils.ts b/packages/date/src/utils.ts deleted file mode 100644 index 237829fe1d..0000000000 --- a/packages/date/src/utils.ts +++ /dev/null @@ -1,11 +0,0 @@ -export const dateParts = (epoch: number) => { - const d = new Date(epoch); - return [ - d.getUTCFullYear(), - d.getUTCMonth(), - d.getUTCDate(), - d.getUTCHours(), - d.getUTCMinutes(), - d.getUTCSeconds(), - ]; -}; diff --git a/packages/date/src/years.ts b/packages/date/src/years.ts deleted file mode 100644 index b978f26160..0000000000 --- a/packages/date/src/years.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { EpochIterator } from "./api"; - -/** - * Yields iterator of UTC timestamps in given semi-open interval in yearly - * precision (each timestamp is at beginning of each year). - * - * @param from - * @param to - */ -export function years([from, to]: number[]): EpochIterator; -export function years(from: number, to: number): EpochIterator; -export function* years(...xs: any[]): EpochIterator { - const [from, to] = xs.length > 1 ? xs : xs[0]; - const d1 = new Date(from); - const d2 = new Date(to); - for ( - let y1 = d1.getUTCFullYear(), y2 = d2.getUTCFullYear(); - y1 <= y2; - y1++ - ) { - const epoch = Date.UTC(y1, 0); - if (epoch >= from) yield epoch; - } -} From 65ea3894f70eee8a0577ff99d6a0bb12fcb2bc65 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 17 Sep 2020 12:16:45 +0100 Subject: [PATCH 044/106] refactor(geom): de-dupe asCubic() for polygon/polyline --- packages/geom/src/ops/as-cubic.ts | 47 ++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/packages/geom/src/ops/as-cubic.ts b/packages/geom/src/ops/as-cubic.ts index 7fb3a30982..91e89afaea 100644 --- a/packages/geom/src/ops/as-cubic.ts +++ b/packages/geom/src/ops/as-cubic.ts @@ -1,5 +1,6 @@ +import type { IObjectOf } from "@thi.ng/api"; import { defmulti, Implementation1, MultiFn1O } from "@thi.ng/defmulti"; -import { CubicOpts, IShape, Type } from "@thi.ng/geom-api"; +import { CubicOpts, IShape, PCLike, Type } from "@thi.ng/geom-api"; import { closedCubicFromBreakPoints, closedCubicFromControlPoints, @@ -8,6 +9,7 @@ import { } from "@thi.ng/geom-splines"; import { TAU } from "@thi.ng/math"; import { mapcat } from "@thi.ng/transducers"; +import { ReadonlyVec, Vec } from "@thi.ng/vectors"; import { Circle } from "../api/circle"; import { Cubic } from "../api/cubic"; import { Group } from "../api/group"; @@ -26,7 +28,6 @@ import { import { copyAttribs } from "../internal/copy-attribs"; import { dispatch } from "../internal/dispatch"; import { asPolygon } from "./as-polygon"; -import type { IObjectOf } from "@thi.ng/api"; export const asCubic: MultiFn1O, Cubic[]> = defmulti( dispatch @@ -50,21 +51,21 @@ asCubic.addAll(>>{ ...mapcat((s) => (s.geo ? asCubic(s.geo) : null), $.segments), ], - [Type.POLYGON]: ($: Polygon, opts: Partial = {}) => { - opts = { breakPoints: false, scale: 1 / 3, uniform: false, ...opts }; - return (opts.breakPoints - ? closedCubicFromBreakPoints($.points, opts.scale, opts.uniform) - : closedCubicFromControlPoints($.points, opts.scale, opts.uniform) - ).map((pts) => new Cubic(pts, copyAttribs($))); - }, + [Type.POLYGON]: ($: Polygon, opts: Partial = {}) => + polyCubic( + $, + opts, + closedCubicFromBreakPoints, + closedCubicFromControlPoints + ), - [Type.POLYLINE]: ($: Polyline, opts: Partial = {}) => { - opts = { breakPoints: false, scale: 1 / 3, uniform: false, ...opts }; - return (opts.breakPoints - ? openCubicFromBreakPoints($.points, opts.scale, opts.uniform) - : openCubicFromControlPoints($.points, opts.scale, opts.uniform) - ).map((pts) => new Cubic(pts, copyAttribs($))); - }, + [Type.POLYLINE]: ($: Polyline, opts: Partial = {}) => + polyCubic( + $, + opts, + openCubicFromBreakPoints, + openCubicFromControlPoints + ), [Type.QUADRATIC]: ({ attribs, points }: Quadratic) => [ cubicFromQuadratic(points[0], points[1], points[2], { ...attribs }), @@ -75,3 +76,17 @@ asCubic.addAll(>>{ }); asCubic.isa(Type.ELLIPSE, Type.CIRCLE); + +// prettier-ignore +const polyCubic = ( + $: PCLike, + opts: Partial, + breakPoints: (pts: ReadonlyVec[], t?: number, uniform?: boolean) => Vec[][], + controlPoints: (pts: ReadonlyVec[], t?: number, uniform?: boolean) => Vec[][] +) => { + opts = { breakPoints: false, scale: 1 / 3, uniform: false, ...opts }; + return (opts.breakPoints + ? breakPoints($.points, opts.scale, opts.uniform) + : controlPoints($.points, opts.scale, opts.uniform) + ).map((pts) => new Cubic(pts, copyAttribs($))); +}; From 122cf486fdcb38810c3c05068b6f11959ee3a588 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Thu, 17 Sep 2020 12:17:46 +0100 Subject: [PATCH 045/106] refactor(geom-io-obj): minor refactoring parseOBJ() --- packages/geom-io-obj/src/parser.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/geom-io-obj/src/parser.ts b/packages/geom-io-obj/src/parser.ts index da5749846b..4fab1d6737 100644 --- a/packages/geom-io-obj/src/parser.ts +++ b/packages/geom-io-obj/src/parser.ts @@ -48,11 +48,6 @@ export const parseOBJ = (src: string, opts?: Partial) => { newGroup("default", force); }; - const addID = (acc: number[], x: string, num: number) => { - const v = parseInt(x); - acc.push(v < 0 ? v + num : v - 1); - }; - const readFace = (line: string[]) => { const face = { v: [] }; const n = line.length; @@ -69,7 +64,7 @@ export const parseOBJ = (src: string, opts?: Partial) => { case 2: opts!.uvs && (face.uv = []); for (let i = 1; i < n; i++) { - const f = line[i].split("/"); + const f = line[i].split("/"); addID(face.v, f[0], nv); face.uv && addID(face.uv!, f[1], nuv); } @@ -78,7 +73,7 @@ export const parseOBJ = (src: string, opts?: Partial) => { opts!.uvs && items[1].length && (face.uv = []); opts!.normals && items[2].length && (face.n = []); for (let i = 1; i < n; i++) { - const f = line[i].split("/"); + const f = line[i].split("/"); addID(face.v, f[0], nv); face.uv && addID(face.uv!, f[1], nuv); face.n && addID(face.n!, f[2], nn); @@ -165,6 +160,11 @@ export const parseOBJ = (src: string, opts?: Partial) => { return result; }; +const addID = (acc: number[], x: string, num: number) => { + const v = parseInt(x); + acc.push(v < 0 ? v + num : v - 1); +}; + const readVec2 = (items: string[]) => [ parseFloat(items[1]), parseFloat(items[2]), From 924466bc5d5f16ced3da95fa2f24dab2bfad0679 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 01:55:53 +0100 Subject: [PATCH 046/106] feat(strings): add unescape() --- packages/strings/src/case.ts | 12 ++++++----- packages/strings/src/index.ts | 1 + packages/strings/src/unescape.ts | 36 ++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 packages/strings/src/unescape.ts diff --git a/packages/strings/src/case.ts b/packages/strings/src/case.ts index 0b81d2761a..3f284b14bf 100644 --- a/packages/strings/src/case.ts +++ b/packages/strings/src/case.ts @@ -25,11 +25,6 @@ export const capitalize: FnS = (x) => x[0].toUpperCase() + x.substr(1); * Converts a CamelCase string into kebab case, with optional custom * delimiter (`-` by default). * - * TODO: Switch back to currently broken Regex w/ positive lookbehind, - * once avail in FF & Safari (currently TC39 stage 4) - * - * {@link https://github.com/tc39/proposal-regexp-lookbehind} - * * @example * ```ts * kebab("FooBar23Baz"); @@ -57,6 +52,13 @@ export const kebab: Stringer = (x, delim = "-") => */ export const snake: FnS = (x) => kebab(x, "_"); +/** + * Uppercase version of {@link snake}. + * + * @param x + */ +export const upperSnake: FnS = (x) => snake(x).toUpperCase(); + /** * Converts a kebab-case or snake_case string into CamelCase. Uses `-` * as default delimiter. diff --git a/packages/strings/src/index.ts b/packages/strings/src/index.ts index b18c32397b..07005cbeb4 100644 --- a/packages/strings/src/index.ts +++ b/packages/strings/src/index.ts @@ -20,6 +20,7 @@ export * from "./splice"; export * from "./trim"; export * from "./truncate"; export * from "./truncate-left"; +export * from "./unescape"; export * from "./units"; export * from "./uuid"; export * from "./wrap"; diff --git a/packages/strings/src/unescape.ts b/packages/strings/src/unescape.ts new file mode 100644 index 0000000000..4a58451008 --- /dev/null +++ b/packages/strings/src/unescape.ts @@ -0,0 +1,36 @@ +export const ESCAPES: Record = { + 0: "\0", + b: "\b", + t: "\t", + r: "\r", + v: "\v", + f: "\f", + n: "\n", + "\\": "\\", +}; + +/** + * Replaces `\uxxxx` UTF-16 unicode escapes and other well-known backslash + * escape sequences (see {@link ESCAPES}) with their actual characters. + * + * @remarks + * Any unknown escape sequences will remain as is. Any unicode chars outside the + * UTF-16 range will need to be encoded using surrogate pairs. + * + * - https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF + * - https://www.branah.com/unicode-converter + * + * @example + * ```ts + * unescape("\\ud83d\\ude0e") + * // '😎' + * ``` + * + * @param src + */ +export const unescape = (src: string) => + src + .replace(/\\u([0-9a-fA-F]{4})/g, (_, id) => + String.fromCharCode(parseInt(id, 16)) + ) + .replace(/\\(\w)/g, (_, id) => ESCAPES[id] || `\\${id}`); From ec94064d1a5714bae055297986b77d2677006440 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 01:57:10 +0100 Subject: [PATCH 047/106] refactor(parse): update ESC parse preset - re-use ESCAPES LUT from strings pkgs --- packages/parse/src/presets/escape.ts | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/packages/parse/src/presets/escape.ts b/packages/parse/src/presets/escape.ts index 5909d79c4c..55581e44c5 100644 --- a/packages/parse/src/presets/escape.ts +++ b/packages/parse/src/presets/escape.ts @@ -1,4 +1,4 @@ -import type { IObjectOf } from "@thi.ng/api"; +import { ESCAPES } from "@thi.ng/strings"; import { repeat } from "../combinators/repeat"; import { seq } from "../combinators/seq"; import { xform } from "../combinators/xform"; @@ -8,20 +8,10 @@ import { stringD } from "../prims/string"; import { xfInt } from "../xform/number"; import { HEX_DIGIT } from "./hex"; -const ESC_VALUES: IObjectOf = { - 0: "\0", - b: "\b", - t: "\t", - n: "\n", - v: "\v", - f: "\f", - r: "\r", -}; - export const ESC = xform(seq([litD("\\"), always()], "esc"), ($) => { const id = $!.children![0].result; - const resolved = ESC_VALUES[id]; - $!.result = resolved !== undefined ? resolved : id; + const resolved = ESCAPES[id]; + $!.result = resolved !== undefined ? resolved : `\\${id}`; $!.children = null; return $; }); From e0d5f1edcdf78b075908c4973586a0f1732fe006 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 12:29:41 +0100 Subject: [PATCH 048/106] feat(strings): add escape(), update unescape(), add tests --- packages/strings/src/escape.ts | 78 ++++++++++++++++++++++++++++++++ packages/strings/src/index.ts | 2 +- packages/strings/src/unescape.ts | 36 --------------- packages/strings/test/escape.ts | 14 ++++++ 4 files changed, 93 insertions(+), 37 deletions(-) create mode 100644 packages/strings/src/escape.ts delete mode 100644 packages/strings/src/unescape.ts create mode 100644 packages/strings/test/escape.ts diff --git a/packages/strings/src/escape.ts b/packages/strings/src/escape.ts new file mode 100644 index 0000000000..867c267ca9 --- /dev/null +++ b/packages/strings/src/escape.ts @@ -0,0 +1,78 @@ +import { U16, U32 } from "./radix"; + +export const ESCAPES: Record = { + 0: "\0", + b: "\b", + t: "\t", + r: "\r", + v: "\v", + f: "\f", + n: "\n", + "'": "'", + '"': '"', + "\\": "\\", +}; + +export const ESCAPES_REV: Record = { + 0: "0", + 8: "b", + 9: "t", + 10: "n", + 11: "v", + 12: "f", + 13: "r", + 33: "'", + 34: '"', + 92: "\\", +}; + +/** + * Escapes all non-ASCII characters (and well-known 0x0x control chars) using + * backslash escape sequences. + * + * @remarks + * - Well-known low-ASCII control chars will be escaped using simple `\`, e.g. + * 0x0a => `\n` + * - Non-BMP chars will be escaped using `\Uxxxxxxxx` + * - Chars outside 0x20 - 0x7e range will be escaped using `\uxxxxx` + * + * @param src + */ +export const escape = (src: string) => + src + .replace( + /[\0\b\t\n\v\f\r'"\\]/g, + (x) => `\\${ESCAPES_REV[x.charCodeAt(0)!]}` + ) + .replace(/[\ud800-\udfff]{2}/g, (x) => `\\U${U32(x.codePointAt(0)!)}`) + .replace(/[^\u0020-\u007e]/g, (x) => `\\u${U16(x.charCodeAt(0))}`); + +/** + * Replaces `\uxxxx` UTF-16 escapes, full `\Uxxxxxxxx` UTF-32 codepoint escapes + * and other well-known backslash escape sequences (see {@link ESCAPES}) with + * the characters they represent. + * + * @remarks + * Any unknown named escape sequences (e.g. `\1`) will remain as is. + * + * - https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF + * - https://www.unicode.org/charts/ + * - https://www.branah.com/unicode-converter + * + * @example + * ```ts + * unescape("\\ud83d\\ude0e \\U0001f60e") + * // '😎' + * ``` + * + * @param src + */ +export const unescape = (src: string) => + src + .replace(/\\u([0-9a-fA-F]{4})/g, (_, id) => + String.fromCharCode(parseInt(id, 16)) + ) + .replace(/\\U([0-9a-fA-F]{8})/g, (_, id) => + String.fromCodePoint(parseInt(id, 16)) + ) + .replace(/\\([0btnvfr'"\\])/g, (_, id) => ESCAPES[id]); diff --git a/packages/strings/src/index.ts b/packages/strings/src/index.ts index 07005cbeb4..4ab6966d9e 100644 --- a/packages/strings/src/index.ts +++ b/packages/strings/src/index.ts @@ -2,6 +2,7 @@ export * from "./api"; export * from "./case"; export * from "./center"; export * from "./cursor"; +export * from "./escape"; export * from "./float"; export * from "./format"; export * from "./groups"; @@ -20,7 +21,6 @@ export * from "./splice"; export * from "./trim"; export * from "./truncate"; export * from "./truncate-left"; -export * from "./unescape"; export * from "./units"; export * from "./uuid"; export * from "./wrap"; diff --git a/packages/strings/src/unescape.ts b/packages/strings/src/unescape.ts deleted file mode 100644 index 4a58451008..0000000000 --- a/packages/strings/src/unescape.ts +++ /dev/null @@ -1,36 +0,0 @@ -export const ESCAPES: Record = { - 0: "\0", - b: "\b", - t: "\t", - r: "\r", - v: "\v", - f: "\f", - n: "\n", - "\\": "\\", -}; - -/** - * Replaces `\uxxxx` UTF-16 unicode escapes and other well-known backslash - * escape sequences (see {@link ESCAPES}) with their actual characters. - * - * @remarks - * Any unknown escape sequences will remain as is. Any unicode chars outside the - * UTF-16 range will need to be encoded using surrogate pairs. - * - * - https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF - * - https://www.branah.com/unicode-converter - * - * @example - * ```ts - * unescape("\\ud83d\\ude0e") - * // '😎' - * ``` - * - * @param src - */ -export const unescape = (src: string) => - src - .replace(/\\u([0-9a-fA-F]{4})/g, (_, id) => - String.fromCharCode(parseInt(id, 16)) - ) - .replace(/\\(\w)/g, (_, id) => ESCAPES[id] || `\\${id}`); diff --git a/packages/strings/test/escape.ts b/packages/strings/test/escape.ts new file mode 100644 index 0000000000..a7a82b7d22 --- /dev/null +++ b/packages/strings/test/escape.ts @@ -0,0 +1,14 @@ +import * as assert from "assert"; +import { escape, unescape } from "../src"; + +const SRC = "\ta\nb😎c£\\\x00"; + +describe("escape", () => { + it("escape", () => { + assert.strictEqual(escape(SRC), "\\ta\\nb\\U0001f60ec\\u00a3\\\\\\0"); + }); + + it("roundtrip", () => { + assert.strictEqual(unescape(escape(SRC)), SRC); + }); +}); From b6751fc506a28a075ea9fee1a5f6d3520449f5af Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 12:34:50 +0100 Subject: [PATCH 049/106] feat(strings): add BOM const, update pkg meta --- packages/strings/package.json | 2 ++ packages/strings/src/api.ts | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/packages/strings/package.json b/packages/strings/package.json index 743c76aee8..c8bf4e5e40 100644 --- a/packages/strings/package.json +++ b/packages/strings/package.json @@ -63,6 +63,7 @@ "center", "composition", "conversion", + "escape", "float", "format", "functional", @@ -75,6 +76,7 @@ "slugify", "string", "typescript", + "unicode", "wordwrap" ], "publishConfig": { diff --git a/packages/strings/src/api.ts b/packages/strings/src/api.ts index c7f56b07f3..7e2184e0d3 100644 --- a/packages/strings/src/api.ts +++ b/packages/strings/src/api.ts @@ -1,5 +1,11 @@ import type { FnU } from "@thi.ng/api"; +/** + * UTF-8 Byte Order Mark character + * https://en.wikipedia.org/wiki/Byte_order_mark + */ +export const BOM = "\ufeff"; + export type Stringer = (x: T, ...xs: any[]) => string; export type FnS = FnU; From c7fe807fb726388d707e839140249a09028533db Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 12:42:07 +0100 Subject: [PATCH 050/106] feat(egf): add escape seq support in parser - escape sequences supported in: - subjects/node and property IDs - tags names - string values - @include paths - @prefix IDs and values - tagged #file values - tagged #list values --- packages/egf/src/parser.ts | 51 ++++++++++++++++++++++++++++++-------- packages/egf/src/tags.ts | 8 +++--- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/packages/egf/src/parser.ts b/packages/egf/src/parser.ts index 836a6ce9ed..b87fffb24b 100644 --- a/packages/egf/src/parser.ts +++ b/packages/egf/src/parser.ts @@ -1,6 +1,7 @@ import { IObjectOf, NULL_LOGGER } from "@thi.ng/api"; import { illegalState, unsupported } from "@thi.ng/errors"; import * as $prefixes from "@thi.ng/prefixes"; +import { unescape } from "@thi.ng/strings"; import { readFileSync } from "fs"; import { dirname, resolve as resolvePath } from "path"; import { IS_NODE, Node, ParseContext, ParseOpts, TagParser } from "./api"; @@ -26,6 +27,7 @@ export const parse = (src: string, ctx: ParseContext) => { continue; } } + subj = unescape(subj); usePrefixes && (subj = qualifiedID(ctx.prefixes, subj)); const curr: Node = nodes[subj] || (nodes[subj] = { $id: subj }); while (i < n) { @@ -45,9 +47,9 @@ export const parse = (src: string, ctx: ParseContext) => { }; const parseInclude = (line: string, ctx: ParseContext) => { - const path = line.substr(INCLUDE.length); + const path = unescape(line.substr(INCLUDE.length)); if (IS_NODE && ctx.opts.includes) { - parseFile(path, { + $parseFile(path, { ...ctx, cwd: dirname(ctx.file), prefixes: { ...ctx.prefixes }, @@ -63,9 +65,9 @@ const RE_PREFIX = /^([a-z0-9-_$]*)$/i; const parsePrefix = (line: string, ctx: ParseContext) => { const idx = line.indexOf(": ", PREFIX.length); if (idx > 0) { - const id = line.substring(PREFIX.length, idx); + const id = unescape(line.substring(PREFIX.length, idx)); if (RE_PREFIX.test(id)) { - const val = line.substr(idx + 2).trim(); + const val = unescape(line.substr(idx + 2).trim()); if (val.length) { ctx.logger.debug(`declare prefix: ${id} = ${val}`); ctx.prefixes[id] = val; @@ -93,7 +95,7 @@ const parseProp = ( const idx0 = line[0] === "\t" ? 1 : 4; if (line[idx0] === ";") return ++i; let idx = line.indexOf(" ", idx0); - let key = line.substring(idx0, idx); + let key = unescape(line.substring(idx0, idx)); ctx.opts.prefixes && (key = qualifiedID(ctx.prefixes, key)); let tag: string | undefined; let body: string; @@ -103,13 +105,13 @@ const parseProp = ( ctx.index, node, key, - parseRef(line.substr(idx + 2).trim(), ctx) + parseRef(unescape(line.substr(idx + 2).trim()), ctx) ); return ++i; } else if (line[idx] === "#") { const tstart = idx + 1; idx = line.indexOf(" ", tstart); - tag = line.substring(tstart, idx); + tag = unescape(line.substring(tstart, idx)); idx++; } if (line[idx] === ">" && line[idx + 1] === ">" && line[idx + 2] === ">") { @@ -140,7 +142,12 @@ const parseProp = ( i++; } body = body.trim(); - addProp(ctx.index, node, key, tag ? parseTag(tag, body, ctx) : body); + addProp( + ctx.index, + node, + key, + tag ? parseTag(tag, body, ctx) : unescape(body) + ); return i; }; @@ -210,7 +217,8 @@ const initContext = (ctx: Partial = {}) => { }; }; -export const parseFile = (path: string, ctx?: Partial) => { +/** @interal */ +export const $parseFile = (path: string, ctx?: Partial) => { const $ctx = initContext(ctx); $ctx.file = path = resolvePath($ctx.cwd, path); if ($ctx.files.includes(path)) { @@ -222,5 +230,26 @@ export const parseFile = (path: string, ctx?: Partial) => { return parse(readFileSync(path).toString(), $ctx); }; -export const parseString = (src: string, ctx?: Partial) => - parse(src, initContext(ctx)); +/** + * Parses EGF graph from given local file name, using provided options (if any) + * to customize the parser. Returns object of graph `nodes` and `prefixes`. + * + * @param path + * @param ctx + */ +export const parseFile = (path: string, ctx?: Partial) => { + const res = $parseFile(path, ctx); + return { nodes: res.nodes, prefixes: res.prefixes }; +}; + +/** + * Parses EGF graph from given string and provided options (if any) to customize + * the parser. Returns object of graph `nodes` and `prefixes`. + * + * @param path + * @param ctx + */ +export const parseString = (src: string, ctx?: Partial) => { + const res = parse(src, initContext(ctx)); + return { nodes: res.nodes, prefixes: res.prefixes }; +}; diff --git a/packages/egf/src/tags.ts b/packages/egf/src/tags.ts index a303d89bc0..d4fb004ab7 100644 --- a/packages/egf/src/tags.ts +++ b/packages/egf/src/tags.ts @@ -1,5 +1,5 @@ import type { IObjectOf } from "@thi.ng/api"; -import { maybeParseFloat, maybeParseInt } from "@thi.ng/strings"; +import { maybeParseFloat, maybeParseInt, unescape } from "@thi.ng/strings"; import { base64Decode } from "@thi.ng/transducers-binary"; import { execSync } from "child_process"; import { readFileSync } from "fs"; @@ -13,7 +13,7 @@ export const BUILTINS: IObjectOf = { date: (_, body) => new Date(body), file: (_, path, ctx) => { if (IS_NODE && ctx.opts.includes) { - path = resolvePath(ctx.opts.root!, path); + path = resolvePath(ctx.opts.root!, unescape(path)); ctx.logger.debug("loading value from:", path); return readFileSync(path).toString(); } else { @@ -29,7 +29,7 @@ export const BUILTINS: IObjectOf = { ).trim() : NODE_ONLY, hex: (_, body) => maybeParseInt(body, 0, 16), - json: (_, body) => JSON.parse(body), - list: (_, body) => body.split(/[\n\r\t ]+/g), + json: (_, body) => JSON.parse(unescape(body)), + list: (_, body) => body.split(/[\n\r\t ]+/g).map(unescape), num: (_, body) => maybeParseFloat(body, 0), }; From b3775b08e1c33cf7c2e94e0a4b119b33e4a104ba Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 15:38:04 +0100 Subject: [PATCH 051/106] feat(geom-isec): update ray-line/polyline fns - add minD/maxD params for: - intersectRayLine() - intersectRayPolyline/All() - refactor/dedupe intersectLinePolylineAll() - add tests --- packages/geom-isec/src/line-poly.ts | 38 +++----- packages/geom-isec/src/ray-line.ts | 6 +- packages/geom-isec/src/ray-poly.ts | 41 ++++---- packages/geom-isec/test/polyline.ts | 141 ++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 53 deletions(-) create mode 100644 packages/geom-isec/test/polyline.ts diff --git a/packages/geom-isec/src/line-poly.ts b/packages/geom-isec/src/line-poly.ts index 93b7e19bc3..1dadafc58c 100644 --- a/packages/geom-isec/src/line-poly.ts +++ b/packages/geom-isec/src/line-poly.ts @@ -1,7 +1,6 @@ -import { IntersectionResult, IntersectionType } from "@thi.ng/geom-api"; -import { maddN2, mag, normalize, ReadonlyVec, sub, Vec } from "@thi.ng/vectors"; -import { NONE } from "./api"; -import { intersectRayLine } from "./ray-line"; +import { IntersectionResult } from "@thi.ng/geom-api"; +import { mag, normalize, ReadonlyVec, sub } from "@thi.ng/vectors"; +import { intersectRayPolylineAll } from "./ray-poly"; export const intersectLinePolylineAll = ( a: ReadonlyVec, @@ -11,27 +10,12 @@ export const intersectLinePolylineAll = ( ): IntersectionResult => { const dir = sub([], b, a); const maxD = mag(dir); - normalize(null, dir); - const n = pts.length - 1; - let i, j; - if (closed) { - i = pts[n]; - j = pts[0]; - } else { - i = pts[0]; - j = pts[1]; - } - const res: [number, Vec][] = []; - for (let k = 0; k <= n; i = j, j = pts[++k]) { - const d = intersectRayLine(a, dir, i, j).alpha; - if (d !== undefined && d >= 0 && d <= maxD) { - res.push([d, maddN2([], dir, d, a)]); - } - } - return res.length - ? { - type: IntersectionType.INTERSECT, - isec: res.sort((a, b) => a[0] - b[0]).map((x) => x[1]), - } - : NONE; + return intersectRayPolylineAll( + a, + normalize(null, dir), + pts, + closed, + 0, + maxD + ); }; diff --git a/packages/geom-isec/src/ray-line.ts b/packages/geom-isec/src/ray-line.ts index bc6fa2bba3..f35167ae8d 100644 --- a/packages/geom-isec/src/ray-line.ts +++ b/packages/geom-isec/src/ray-line.ts @@ -7,7 +7,9 @@ export const intersectRayLine = ( rpos: ReadonlyVec, dir: ReadonlyVec, a: ReadonlyVec, - b: ReadonlyVec + b: ReadonlyVec, + minD = 0, + maxD = Infinity ) => { const bax = b[0] - a[0]; const bay = b[1] - a[1]; @@ -19,7 +21,7 @@ export const intersectRayLine = ( const ary = a[1] - rpos[1]; const t = (bay * arx - bax * ary) / d; const s = (dir[1] * arx - dir[0] * ary) / d; - return t >= 0 && s >= 0 && s <= 1 + return t >= minD && t <= maxD && s >= 0 && s <= 1 ? { type: IntersectionType.INTERSECT, isec: maddN([], dir, t, rpos), diff --git a/packages/geom-isec/src/ray-poly.ts b/packages/geom-isec/src/ray-poly.ts index 934524e2d0..08807baad0 100644 --- a/packages/geom-isec/src/ray-poly.ts +++ b/packages/geom-isec/src/ray-poly.ts @@ -3,36 +3,34 @@ import { maddN2, ReadonlyVec, Vec } from "@thi.ng/vectors"; import { NONE } from "./api"; import { intersectRayLine } from "./ray-line"; +const startPoints = (pts: ReadonlyVec[], closed: boolean) => + closed ? [pts[pts.length - 1], pts[0]] : [pts[0], pts[1]]; + export const intersectRayPolyline = ( rpos: ReadonlyVec, dir: ReadonlyVec, pts: ReadonlyVec[], - closed = false + closed = false, + minD = 0, + maxD = Infinity ): IntersectionResult => { const n = pts.length - 1; - let minD = Infinity; + let alpha = maxD; let cross = 0; - let i, j; - if (closed) { - i = pts[n]; - j = pts[0]; - } else { - i = pts[0]; - j = pts[1]; - } + let [i, j] = startPoints(pts, closed); for (let k = 0; k <= n; i = j, j = pts[++k]) { - const d = intersectRayLine(rpos, dir, i, j).alpha; + const d = intersectRayLine(rpos, dir, i, j, minD, maxD).alpha; if (d !== undefined) { cross++; - if (d < minD) minD = d; + if (d < alpha) alpha = d; } } return cross > 0 ? { type: IntersectionType.INTERSECT, - isec: maddN2([], dir, minD, rpos), + isec: maddN2([], dir, alpha, rpos), inside: !(cross & 1), - alpha: minD, + alpha, } : NONE; }; @@ -41,20 +39,15 @@ export const intersectRayPolylineAll = ( rpos: ReadonlyVec, dir: ReadonlyVec, pts: ReadonlyVec[], - closed = false + closed = false, + minD = 0, + maxD = Infinity ): IntersectionResult => { const n = pts.length - 1; - let i, j; - if (closed) { - i = pts[n]; - j = pts[0]; - } else { - i = pts[0]; - j = pts[1]; - } + let [i, j] = startPoints(pts, closed); const res: [number, Vec][] = []; for (let k = 0; k <= n; i = j, j = pts[++k]) { - const d = intersectRayLine(rpos, dir, i, j).alpha; + const d = intersectRayLine(rpos, dir, i, j, minD, maxD).alpha; if (d !== undefined) { res.push([d, maddN2([], dir, d, rpos)]); } diff --git a/packages/geom-isec/test/polyline.ts b/packages/geom-isec/test/polyline.ts new file mode 100644 index 0000000000..3a392be946 --- /dev/null +++ b/packages/geom-isec/test/polyline.ts @@ -0,0 +1,141 @@ +import { IntersectionType } from "@thi.ng/geom-api"; +import * as assert from "assert"; +import { intersectLinePolylineAll, intersectRayPolylineAll } from "../src"; + +const pts = [ + [0, 0], + [100, 0], + [100, 50], + [0, 100], +]; + +describe("polyline", () => { + it("ray (x)", () => { + assert.deepStrictEqual( + intersectRayPolylineAll([-50, 25], [1, 0], pts, false), + { + type: IntersectionType.INTERSECT, + isec: [[100, 25]], + } + ); + assert.deepStrictEqual( + intersectRayPolylineAll([-50, 25], [1, 0], pts, true), + { + type: IntersectionType.INTERSECT, + isec: [ + [0, 25], + [100, 25], + ], + } + ); + }); + + it("ray (y)", () => { + assert.deepStrictEqual( + intersectRayPolylineAll([50, -50], [0, 1], pts, false), + { + type: IntersectionType.INTERSECT, + isec: [ + [50, 0], + [50, 75], + ], + } + ); + assert.deepStrictEqual( + intersectRayPolylineAll([50, -50], [0, 1], pts, true), + { + type: IntersectionType.INTERSECT, + isec: [ + [50, 0], + [50, 75], + ], + } + ); + }); + + it("line (x)", () => { + assert.deepStrictEqual( + intersectLinePolylineAll([-50, 25], [50, 25], pts, false), + { + type: IntersectionType.NONE, + } + ); + assert.deepStrictEqual( + intersectLinePolylineAll([-50, 25], [110, 25], pts, false), + { + type: IntersectionType.INTERSECT, + isec: [[100, 25]], + } + ); + assert.deepStrictEqual( + intersectLinePolylineAll([-50, 25], [50, 25], pts, true), + { + type: IntersectionType.INTERSECT, + isec: [[0, 25]], + } + ); + assert.deepStrictEqual( + intersectLinePolylineAll([-50, 25], [110, 25], pts, true), + { + type: IntersectionType.INTERSECT, + isec: [ + [0, 25], + [100, 25], + ], + } + ); + }); + + it("line (y)", () => { + assert.deepStrictEqual( + intersectLinePolylineAll([50, -25], [50, -20], pts, false), + { + type: IntersectionType.NONE, + } + ); + assert.deepStrictEqual( + intersectLinePolylineAll([50, -25], [50, 50], pts, false), + { + type: IntersectionType.INTERSECT, + isec: [[50, 0]], + } + ); + assert.deepStrictEqual( + intersectLinePolylineAll([50, -25], [50, 100], pts, false), + { + type: IntersectionType.INTERSECT, + isec: [ + [50, 0], + [50, 75], + ], + } + ); + }); + + it("ray minD/maxD", () => { + const I = Infinity; + assert.deepStrictEqual( + intersectRayPolylineAll([50, 25], [1, 0], pts, true, -I, I), + { + type: IntersectionType.INTERSECT, + isec: [ + [0, 25], + [100, 25], + ], + } + ); + assert.deepStrictEqual( + intersectRayPolylineAll([-50, 25], [1, 0], pts, true, 60), + { + type: IntersectionType.INTERSECT, + isec: [[100, 25]], + } + ); + assert.deepStrictEqual( + intersectRayPolylineAll([50, 25], [1, 0], pts, true, 0, 10), + { + type: IntersectionType.NONE, + } + ); + }); +}); From b341e1ca056a2400f7ba020387ce416f31bda659 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 16:16:22 +0100 Subject: [PATCH 052/106] refactor(vectors): update/dedupe heading fns --- packages/vectors/src/heading-segment.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/vectors/src/heading-segment.ts b/packages/vectors/src/heading-segment.ts index 11dc9c2331..b8c0fdc883 100644 --- a/packages/vectors/src/heading-segment.ts +++ b/packages/vectors/src/heading-segment.ts @@ -2,6 +2,9 @@ import type { FnU2 } from "@thi.ng/api"; import { atan2Abs } from "@thi.ng/math"; import type { ReadonlyVec } from "./api"; +const $ = (u: number, v: number): FnU2 => (a, b) => + atan2Abs(b[u] - a[u], b[v] - a[v]); + /** * Computes direction angle (in radians) of line segment `a` -> `b` in * XY plane. @@ -9,8 +12,7 @@ import type { ReadonlyVec } from "./api"; * @param a - * @param b - */ -export const headingSegmentXY: FnU2 = (a, b) => - atan2Abs(b[1] - a[1], b[0] - a[0]); +export const headingSegmentXY = $(1, 0); /** * Computes direction angle (in radians) of line segment `a` -> `b` in @@ -19,8 +21,7 @@ export const headingSegmentXY: FnU2 = (a, b) => * @param a - * @param b - */ -export const headingSegmentXZ: FnU2 = (a, b) => - atan2Abs(b[2] - a[2], b[0] - a[0]); +export const headingSegmentXZ = $(2, 0); /** * Computes direction angle (in radians) of line segment `a` -> `b` in @@ -29,8 +30,7 @@ export const headingSegmentXZ: FnU2 = (a, b) => * @param a - * @param b - */ -export const headingSegmentYZ: FnU2 = (a, b) => - atan2Abs(b[2] - a[2], b[1] - a[1]); +export const headingSegmentYZ = $(2, 1); /** * Same as {@link headingSegmentXY}. From 096b7c7ffd3c35d262b476df4874f6dab948fd30 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 17:23:34 +0100 Subject: [PATCH 053/106] refactor(matrices): add/update types, minor refactor --- packages/matrices/src/api.ts | 2 ++ packages/matrices/src/concat.ts | 2 +- packages/matrices/src/frustum.ts | 2 +- packages/matrices/src/lookat.ts | 2 +- packages/matrices/src/ortho.ts | 2 +- packages/matrices/src/perspective.ts | 2 +- packages/matrices/src/quat-axis-angle.ts | 2 +- packages/matrices/src/quat-m33.ts | 6 +++--- packages/matrices/src/quat-m44.ts | 4 ++-- packages/matrices/src/rotation-around-axis.ts | 2 +- packages/matrices/src/rotation.ts | 18 +++++++++--------- packages/matrices/src/scale.ts | 12 ++++++------ packages/matrices/src/shear.ts | 4 ++-- packages/matrices/src/skew.ts | 5 ++--- packages/matrices/src/translation.ts | 4 ++-- packages/matrices/src/viewport.ts | 2 +- 16 files changed, 36 insertions(+), 35 deletions(-) diff --git a/packages/matrices/src/api.ts b/packages/matrices/src/api.ts index 93fdb7550f..5eea979da3 100644 --- a/packages/matrices/src/api.ts +++ b/packages/matrices/src/api.ts @@ -14,8 +14,10 @@ export type MultiMatOp = MultiVecOp; export type MatOp1 = (out: Mat | null) => Mat; export type MatOpM = (out: Mat | null, a: ReadonlyMat) => Mat; +export type MatOpV = (out: Mat | null, a: ReadonlyVec) => Mat; export type MatOpMU = (out: Mat | null, a: ReadonlyMat) => Mat | undefined; export type MatOpN = (out: Mat | null, n: number) => Mat; +export type MatOpNV = (out: Mat | null, n: number | ReadonlyVec) => Mat; export type MatOpMM = (out: Mat | null, a: ReadonlyMat, b: ReadonlyMat) => Mat; export type MatOpMV = (out: Vec | null, a: ReadonlyMat, b: ReadonlyVec) => Vec; export type MatOpMN = (out: Mat | null, a: ReadonlyMat, n: number) => Mat; diff --git a/packages/matrices/src/concat.ts b/packages/matrices/src/concat.ts index 5c11c03e7b..c1591bbbe4 100644 --- a/packages/matrices/src/concat.ts +++ b/packages/matrices/src/concat.ts @@ -16,4 +16,4 @@ export const concat = ( a: ReadonlyMat, b: ReadonlyMat, ...xs: ReadonlyMat[] -) => xs.reduce((acc: Mat, x) => mulM(acc, acc, x), mulM(out, a, b)); +): Mat => xs.reduce((acc: Mat, x) => mulM(acc, acc, x), mulM(out, a, b)); diff --git a/packages/matrices/src/frustum.ts b/packages/matrices/src/frustum.ts index a790a306c9..1125172dd8 100644 --- a/packages/matrices/src/frustum.ts +++ b/packages/matrices/src/frustum.ts @@ -22,7 +22,7 @@ export const frustum = ( top: number, near: number, far: number -) => { +): Mat => { const dx = 1 / (right - left); const dy = 1 / (top - bottom); const dz = 1 / (far - near); diff --git a/packages/matrices/src/lookat.ts b/packages/matrices/src/lookat.ts index faf19be8a7..c671d56c0f 100644 --- a/packages/matrices/src/lookat.ts +++ b/packages/matrices/src/lookat.ts @@ -23,7 +23,7 @@ export const lookAt = ( eye: ReadonlyVec, target: ReadonlyVec, up: ReadonlyVec -) => { +): Mat => { const z = normalize(null, sub3([], eye, target)); const x = normalize(null, cross3([], up, z)); const y = normalize(null, cross3([], z, x)); diff --git a/packages/matrices/src/ortho.ts b/packages/matrices/src/ortho.ts index 4e9eff65e3..baf5ab6fcc 100644 --- a/packages/matrices/src/ortho.ts +++ b/packages/matrices/src/ortho.ts @@ -21,7 +21,7 @@ export const ortho = ( top: number, near: number, far: number -) => { +): Mat => { const dx = 1 / (right - left); const dy = 1 / (top - bottom); const dz = 1 / (far - near); diff --git a/packages/matrices/src/perspective.ts b/packages/matrices/src/perspective.ts index 23b02d4aec..fa22987830 100644 --- a/packages/matrices/src/perspective.ts +++ b/packages/matrices/src/perspective.ts @@ -17,7 +17,7 @@ export const perspective = ( aspect: number, near: number, far: number -) => { +): Mat => { const f = frustumBounds(fov, aspect, near, far); return frustum(out, f.left, f.right, f.bottom, f.top, f.near, f.far); }; diff --git a/packages/matrices/src/quat-axis-angle.ts b/packages/matrices/src/quat-axis-angle.ts index 58ab625b10..d617366022 100644 --- a/packages/matrices/src/quat-axis-angle.ts +++ b/packages/matrices/src/quat-axis-angle.ts @@ -9,7 +9,7 @@ import { normalize, ReadonlyVec } from "@thi.ng/vectors"; * @param theta - */ export const quatFromAxisAngle = (axis: ReadonlyVec, theta: number) => { - theta /= 2; + theta *= 0.5; return normalize([0, 0, 0, Math.cos(theta)], axis, Math.sin(theta)); }; diff --git a/packages/matrices/src/quat-m33.ts b/packages/matrices/src/quat-m33.ts index 84be661560..932889e1ab 100644 --- a/packages/matrices/src/quat-m33.ts +++ b/packages/matrices/src/quat-m33.ts @@ -1,5 +1,5 @@ -import { ReadonlyVec, setC } from "@thi.ng/vectors"; -import type { Mat } from "./api"; +import { setC } from "@thi.ng/vectors"; +import type { MatOpV } from "./api"; /** * Converts quaternion into 3x3 matrix and writes result to `out`. @@ -7,7 +7,7 @@ import type { Mat } from "./api"; * @param out - * @param q - */ -export const quatToMat33 = (out: Mat | null, q: ReadonlyVec) => { +export const quatToMat33: MatOpV = (out, q) => { const [x, y, z, w] = q; const x2 = x + x; const y2 = y + y; diff --git a/packages/matrices/src/quat-m44.ts b/packages/matrices/src/quat-m44.ts index b6bfe61e4e..4dd01ac5c8 100644 --- a/packages/matrices/src/quat-m44.ts +++ b/packages/matrices/src/quat-m44.ts @@ -2,8 +2,8 @@ import { ReadonlyVec, setC, ZERO3 } from "@thi.ng/vectors"; import type { Mat } from "./api"; /** - * Converts quaternion into 4x4 matrix with optional translation offset - * `t`, then writes result to `out`. + * Converts quaternion into 4x4 matrix with optional 3D translation offset `t`, + * then writes result to `out`. * * @param out - * @param q - diff --git a/packages/matrices/src/rotation-around-axis.ts b/packages/matrices/src/rotation-around-axis.ts index 8598623500..563191c205 100644 --- a/packages/matrices/src/rotation-around-axis.ts +++ b/packages/matrices/src/rotation-around-axis.ts @@ -18,7 +18,7 @@ export const rotationAroundAxis33 = ( axis: ReadonlyVec, theta: number, normalize = false -) => { +): Mat => { const [x, y, z] = normalize ? _normalize([], axis) : axis; const [s, c] = sincos(theta); const t = 1 - c; diff --git a/packages/matrices/src/rotation.ts b/packages/matrices/src/rotation.ts index 993dc65d3f..1f803f02e5 100644 --- a/packages/matrices/src/rotation.ts +++ b/packages/matrices/src/rotation.ts @@ -1,6 +1,6 @@ import { sincos } from "@thi.ng/math"; import { setC, setC4, setC6 } from "@thi.ng/vectors"; -import type { Mat } from "./api"; +import type { MatOpN } from "./api"; /** * Constructs a 2x2 matrix rotation matrix for given `theta`. @@ -8,7 +8,7 @@ import type { Mat } from "./api"; * @param out - * @param theta - */ -export const rotation22 = (out: Mat | null, theta: number) => { +export const rotation22: MatOpN = (out, theta) => { const [s, c] = sincos(theta); return setC4(out || [], c, s, -s, c); }; @@ -19,7 +19,7 @@ export const rotation22 = (out: Mat | null, theta: number) => { * @param out - * @param theta - */ -export const rotation23 = (out: Mat | null, theta: number) => { +export const rotation23: MatOpN = (out, theta) => { const [s, c] = sincos(theta); return setC6(out || [], c, s, -s, c, 0, 0); }; @@ -30,7 +30,7 @@ export const rotation23 = (out: Mat | null, theta: number) => { * @param out - * @param theta - */ -export const rotationX33 = (out: Mat | null, theta: number) => { +export const rotationX33: MatOpN = (out, theta) => { const [s, c] = sincos(theta); return setC(out || [], 1, 0, 0, 0, c, s, 0, -s, c); }; @@ -41,7 +41,7 @@ export const rotationX33 = (out: Mat | null, theta: number) => { * @param out - * @param theta - */ -export const rotationY33 = (out: Mat | null, theta: number) => { +export const rotationY33: MatOpN = (out, theta) => { const [s, c] = sincos(theta); return setC(out || [], c, 0, -s, 0, 1, 0, s, 0, c); }; @@ -52,7 +52,7 @@ export const rotationY33 = (out: Mat | null, theta: number) => { * @param out - * @param theta - */ -export const rotationZ33 = (out: Mat | null, theta: number) => { +export const rotationZ33: MatOpN = (out, theta) => { const [s, c] = sincos(theta); return setC(out || [], c, s, 0, -s, c, 0, 0, 0, 1); }; @@ -63,7 +63,7 @@ export const rotationZ33 = (out: Mat | null, theta: number) => { * @param out - * @param theta - */ -export const rotationX44 = (out: Mat | null, theta: number) => { +export const rotationX44: MatOpN = (out, theta) => { const [s, c] = sincos(theta); return setC(out || [], 1, 0, 0, 0, 0, c, s, 0, 0, -s, c, 0, 0, 0, 0, 1); }; @@ -74,7 +74,7 @@ export const rotationX44 = (out: Mat | null, theta: number) => { * @param out - * @param theta - */ -export const rotationY44 = (out: Mat | null, theta: number) => { +export const rotationY44: MatOpN = (out, theta) => { const [s, c] = sincos(theta); return setC(out || [], c, 0, -s, 0, 0, 1, 0, 0, s, 0, c, 0, 0, 0, 0, 1); }; @@ -85,7 +85,7 @@ export const rotationY44 = (out: Mat | null, theta: number) => { * @param out - * @param theta - */ -export const rotationZ44 = (out: Mat | null, theta: number) => { +export const rotationZ44: MatOpN = (out, theta) => { const [s, c] = sincos(theta); return setC(out || [], c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }; diff --git a/packages/matrices/src/scale.ts b/packages/matrices/src/scale.ts index 781ceec4d8..b189e07210 100644 --- a/packages/matrices/src/scale.ts +++ b/packages/matrices/src/scale.ts @@ -1,6 +1,6 @@ import { isNumber } from "@thi.ng/checks"; -import { ReadonlyVec, setC, setC4, setC6 } from "@thi.ng/vectors"; -import type { Mat } from "./api"; +import { setC, setC4, setC6 } from "@thi.ng/vectors"; +import type { MatOpNV } from "./api"; /** * Computes 2x2 matrix scale matrix and writes result to `out`. If `s` @@ -9,7 +9,7 @@ import type { Mat } from "./api"; * @param m - * @param s - */ -export const scale22 = (m: Mat | null, s: number | ReadonlyVec) => ( +export const scale22: MatOpNV = (m, s) => ( (s = isNumber(s) ? [s, s] : s), setC4(m || [], s[0], 0, 0, s[1]) ); @@ -20,7 +20,7 @@ export const scale22 = (m: Mat | null, s: number | ReadonlyVec) => ( * @param m - * @param s - */ -export const scale23 = (m: Mat | null, s: number | ReadonlyVec) => ( +export const scale23: MatOpNV = (m, s) => ( (s = isNumber(s) ? [s, s] : s), setC6(m || [], s[0], 0, 0, s[1], 0, 0) ); @@ -31,7 +31,7 @@ export const scale23 = (m: Mat | null, s: number | ReadonlyVec) => ( * @param m - * @param s - */ -export const scale33 = (m: Mat | null, s: number | ReadonlyVec) => ( +export const scale33: MatOpNV = (m, s) => ( (s = isNumber(s) ? [s, s, s] : s), setC(m || [], s[0], 0, 0, 0, s[1], 0, 0, 0, s[2]) ); @@ -43,7 +43,7 @@ export const scale33 = (m: Mat | null, s: number | ReadonlyVec) => ( * @param m - * @param s - */ -export const scale44 = (m: Mat | null, s: number | ReadonlyVec) => ( +export const scale44: MatOpNV = (m, s) => ( (s = isNumber(s) ? [s, s, s] : s), setC( m || [], diff --git a/packages/matrices/src/shear.ts b/packages/matrices/src/shear.ts index 54f8d73a4d..41b275f098 100644 --- a/packages/matrices/src/shear.ts +++ b/packages/matrices/src/shear.ts @@ -1,7 +1,7 @@ -import type { Mat, MatOp1 } from "./api"; +import type { MatOp1, MatOpN } from "./api"; import { identity22, identity23, identity33, identity44 } from "./identity"; -const $ = (f: MatOp1) => (i: number) => (m: Mat | null, x: number) => ( +const $ = (f: MatOp1) => (i: number): MatOpN => (m, x) => ( !m && (m = []), f(m), (m[i] = x), m ); diff --git a/packages/matrices/src/skew.ts b/packages/matrices/src/skew.ts index 768af3e674..29a14c3bcd 100644 --- a/packages/matrices/src/skew.ts +++ b/packages/matrices/src/skew.ts @@ -1,4 +1,4 @@ -import type { Mat, MatOpN } from "./api"; +import type { MatOpN } from "./api"; import { shearX22, shearX23, @@ -18,8 +18,7 @@ import { shearZY44, } from "./shear"; -const $ = (f: MatOpN) => (m: Mat | null, theta: number) => - f(m, Math.tan(theta)); +const $ = (f: MatOpN): MatOpN => (m, theta) => f(m, Math.tan(theta)); export const skewX22 = $(shearX22); export const skewY22 = $(shearY22); diff --git a/packages/matrices/src/translation.ts b/packages/matrices/src/translation.ts index 98e303e1b6..ac789658b1 100644 --- a/packages/matrices/src/translation.ts +++ b/packages/matrices/src/translation.ts @@ -7,7 +7,7 @@ import type { Mat } from "./api"; * @param out - * @param v - */ -export const translation23 = (m: Mat | null, v: ReadonlyVec) => +export const translation23 = (m: Mat | null, v: ReadonlyVec): Mat => setC6(m || [], 1, 0, 0, 1, v[0], v[1]); /** @@ -16,5 +16,5 @@ export const translation23 = (m: Mat | null, v: ReadonlyVec) => * @param out - * @param v - */ -export const translation44 = (m: Mat | null, v: ReadonlyVec) => +export const translation44 = (m: Mat | null, v: ReadonlyVec): Mat => setC(m || [], 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, v[0], v[1], v[2], 1); diff --git a/packages/matrices/src/viewport.ts b/packages/matrices/src/viewport.ts index 0bc7609525..5771ea4d6f 100644 --- a/packages/matrices/src/viewport.ts +++ b/packages/matrices/src/viewport.ts @@ -19,7 +19,7 @@ export const viewport = ( right: number, bottom: number, top: number -) => { +): Mat => { const x = (left + right) / 2; const y = (bottom + top) / 2; const w = (right - left) / 2; From 19095b0f6f44bf341fc6ef39e9b42b8b0ce67f88 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 17:26:46 +0100 Subject: [PATCH 054/106] refactor(geom): update fitIntoBounds() fns --- packages/geom/src/ops/fit-into-bounds.ts | 50 +++++++++++------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/packages/geom/src/ops/fit-into-bounds.ts b/packages/geom/src/ops/fit-into-bounds.ts index e1e0653be4..926e5ca0ab 100644 --- a/packages/geom/src/ops/fit-into-bounds.ts +++ b/packages/geom/src/ops/fit-into-bounds.ts @@ -1,6 +1,9 @@ +import type { IShape } from "@thi.ng/geom-api"; import { minNonZero2, minNonZero3, safeDiv } from "@thi.ng/math"; import { concat, + MatOpNV, + MatOpV, scale23, scale44, translation23, @@ -16,9 +19,10 @@ import { centroid } from "./centroid"; import { mapPoint } from "./map-point"; import { transform } from "./transform"; import { unmapPoint } from "./unmap-point"; -import type { IShape } from "@thi.ng/geom-api"; -const translateScale2 = ( +const translateScale = ( + tmat: MatOpV, + smat: MatOpNV, shape: IShape, preTrans: ReadonlyVec, postTrans: ReadonlyVec, @@ -26,28 +30,7 @@ const translateScale2 = ( ) => transform( shape, - concat( - [], - translation23([], postTrans), - scale23([], scale), - translation23([], preTrans) - ) - ); - -const translateScale3 = ( - shape: IShape, - preTrans: ReadonlyVec, - postTrans: ReadonlyVec, - scale: ReadonlyVec | number -) => - transform( - shape, - concat( - [], - translation44([], postTrans), - scale44([], scale), - translation44([], preTrans) - ) + concat([], tmat([], postTrans), smat([], scale), tmat([], preTrans)) ); export const fitIntoBounds2 = (shape: IShape, dest: Rect) => { @@ -55,7 +38,9 @@ export const fitIntoBounds2 = (shape: IShape, dest: Rect) => { if (!src) return; const c = centroid(src); if (!c) return; - return translateScale2( + return translateScale( + translation23, + scale23, shape, neg(null, c), centroid(dest)!, @@ -71,7 +56,9 @@ export const fitIntoBounds3 = (shape: IShape, dest: AABB) => { if (!src) return; const c = centroid(src); if (!c) return; - return translateScale3( + return translateScale( + translation44, + scale44, shape, neg(null, c), centroid(dest)!, @@ -100,7 +87,16 @@ export const fitAllIntoBounds2 = (shapes: IShape[], dest: Rect) => { const sc = centroid(s, c1); if (sc) { unmapPoint(b, mapPoint(src, sc), c2); - res.push(translateScale2(s, neg(null, c1), c2, smat)); + res.push( + translateScale( + translation23, + scale23, + s, + neg(null, c1), + c2, + smat + ) + ); } else { res.push(s); } From 95a29b199077c741c83f4f78871f9627264f198d Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 17:59:05 +0100 Subject: [PATCH 055/106] fix(geom-isec): testCenteredAABBSphere() --- packages/geom-isec/src/rect-circle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/geom-isec/src/rect-circle.ts b/packages/geom-isec/src/rect-circle.ts index 71131303de..a8249523b8 100644 --- a/packages/geom-isec/src/rect-circle.ts +++ b/packages/geom-isec/src/rect-circle.ts @@ -99,7 +99,7 @@ export const testCenteredAABBSphere = testCenteredBoxSphere.add( (boxPos, { 0: w, 1: h, 2: d }, spherePos, r) => axis(spherePos[0], boxPos[0] - w, w * 2) + axis(spherePos[1], boxPos[1] - h, h * 2) + - axis(spherePos[2], boxPos[2] - w, d * 2) <= + axis(spherePos[2], boxPos[2] - d, d * 2) <= r * r ); From b42071ed3af7a0148cc08d97f9a866e53a3970a7 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 17:59:41 +0100 Subject: [PATCH 056/106] minor(geom-isec): update intersectRayCircle() --- packages/geom-isec/src/ray-circle.ts | 32 +++++++++++++--------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/packages/geom-isec/src/ray-circle.ts b/packages/geom-isec/src/ray-circle.ts index 4ae7080dcf..434a74afe4 100644 --- a/packages/geom-isec/src/ray-circle.ts +++ b/packages/geom-isec/src/ray-circle.ts @@ -11,21 +11,19 @@ export const intersectRayCircle = ( const delta = sub([], spos, rpos); const w = dot(delta, dir); let d = r * r + w * w - magSq(delta); - if (d >= 0) { - d = Math.sqrt(d); - const a = w + d; - const b = w - d; - const isec = - a >= 0 - ? b >= 0 - ? a > b - ? [maddN(delta, dir, b, rpos), maddN([], dir, a, rpos)] - : [maddN(delta, dir, a, rpos), maddN([], dir, b, rpos)] - : [maddN(delta, dir, a, rpos)] - : b >= 0 - ? [maddN(delta, dir, b, rpos)] - : undefined; - return isec ? { type: IntersectionType.INTERSECT, isec } : NONE; - } - return NONE; + if (d < 0) return NONE; + d = Math.sqrt(d); + const a = w + d; + const b = w - d; + const isec = + a >= 0 + ? b >= 0 + ? a > b + ? [maddN(delta, dir, b, rpos), maddN([], dir, a, rpos)] + : [maddN(delta, dir, a, rpos), maddN([], dir, b, rpos)] + : [maddN(delta, dir, a, rpos)] + : b >= 0 + ? [maddN(delta, dir, b, rpos)] + : undefined; + return isec ? { type: IntersectionType.INTERSECT, isec } : NONE; }; From 1358bac1a95359340b19adb91b1813edf3e1645a Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 18:40:59 +0100 Subject: [PATCH 057/106] fix(geom-closest-point): update closestPointPolyline() - add check if at least a single closest point has been found --- packages/geom-closest-point/src/line.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/geom-closest-point/src/line.ts b/packages/geom-closest-point/src/line.ts index 093e0e8708..dc445887c9 100644 --- a/packages/geom-closest-point/src/line.ts +++ b/packages/geom-closest-point/src/line.ts @@ -144,7 +144,7 @@ export const closestPointPolyline = ( } } } - return out; + return minD < Infinity ? out : undefined; }; /** From 3167a3d75f802855ce9982e50f93b681f5e21da1 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 18:46:42 +0100 Subject: [PATCH 058/106] refactor(geom-poly-utils): update convexity() --- packages/geom-poly-utils/src/convexity.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/geom-poly-utils/src/convexity.ts b/packages/geom-poly-utils/src/convexity.ts index 8454c59623..d98c09b86c 100644 --- a/packages/geom-poly-utils/src/convexity.ts +++ b/packages/geom-poly-utils/src/convexity.ts @@ -11,16 +11,13 @@ export const convexity = (pts: ReadonlyVec[], eps = EPS) => { let a = pts[n - 2]; let b = pts[n - 1]; let c = pts[0]; - for (let i = 0; i < n; a = b, b = c, c = pts[++i]) { + for (let i = 0; i < n && type < 3; a = b, b = c, c = pts[++i]) { const t = corner2(a, b, c, eps); - if (t < 0) { - type |= 1; - } else if (t > 0) { - type |= 2; - } - if (type === 3) { - return Convexity.CONCAVE; - } + type |= t < 0 ? 1 : t > 0 ? 2 : 0; } - return type > 0 ? Convexity.CONVEX : Convexity.COLINEAR; + return type === 3 + ? Convexity.CONCAVE + : type > 0 + ? Convexity.CONVEX + : Convexity.COLINEAR; }; From 62472f50ef5d9a93750d49f782ad4f94ee96f02c Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 18:47:46 +0100 Subject: [PATCH 059/106] refactor(geom-resample): update Sampler.closestPoint() - re-use closestPointPolyline() --- packages/geom-resample/src/sampler.ts | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/geom-resample/src/sampler.ts b/packages/geom-resample/src/sampler.ts index ccb15ff3c0..6aa2066eac 100644 --- a/packages/geom-resample/src/sampler.ts +++ b/packages/geom-resample/src/sampler.ts @@ -1,4 +1,8 @@ -import { closestPointSegment, closestT } from "@thi.ng/geom-closest-point"; +import { + closestPointPolyline, + closestPointSegment, + closestT, +} from "@thi.ng/geom-closest-point"; import { fit01 } from "@thi.ng/math"; import { dist, @@ -59,20 +63,7 @@ export class Sampler { } closestPoint(p: ReadonlyVec) { - const pts = this.points; - const tmp: Vec = []; - const closest: Vec = []; - let minD = Infinity; - for (let i = 0, n = pts.length - 1; i < n; i++) { - if (closestPointSegment(p, pts[i], pts[i + 1], tmp)) { - const d = distSq(p, tmp); - if (d < minD) { - minD = d; - set(closest, tmp); - } - } - } - return minD < Infinity ? closest : undefined; + return closestPointPolyline(p, this.points); } closestT(p: ReadonlyVec) { From 1bdc0f1fd26b5c8c68ca1c4a4b932a0496838e14 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 20:38:03 +0100 Subject: [PATCH 060/106] refactor(scenegraph): update toHiccup() impls --- packages/scenegraph/src/hiccup.ts | 30 ++++++++++++++++++++++++++++++ packages/scenegraph/src/node2.ts | 24 ++++++------------------ packages/scenegraph/src/node3.ts | 24 ++++++------------------ 3 files changed, 42 insertions(+), 36 deletions(-) create mode 100644 packages/scenegraph/src/hiccup.ts diff --git a/packages/scenegraph/src/hiccup.ts b/packages/scenegraph/src/hiccup.ts new file mode 100644 index 0000000000..deeae52588 --- /dev/null +++ b/packages/scenegraph/src/hiccup.ts @@ -0,0 +1,30 @@ +import { deref, IToHiccup } from "@thi.ng/api"; +import { isFunction } from "@thi.ng/checks"; +import type { ANode } from "./anode"; + +/** + * `IToHiccup` implementation Node2D/3D + * + * @param node + * @param ctx + * + * @internal + */ +export const toHiccup = & IToHiccup>( + node: T, + ctx?: any +) => { + const body = isFunction(node.body) ? node.body(ctx) : deref(node.body); + return node.enabled && node.display + ? node.children.length + ? [ + "g", + {}, + node.body ? ["g", { transform: node.mat }, body] : undefined, + ...node.children.map((c) => c.toHiccup(ctx)), + ] + : body + ? ["g", { transform: node.mat }, body] + : undefined + : undefined; +}; diff --git a/packages/scenegraph/src/node2.ts b/packages/scenegraph/src/node2.ts index 5fbe43b5c0..b272a33c85 100644 --- a/packages/scenegraph/src/node2.ts +++ b/packages/scenegraph/src/node2.ts @@ -1,11 +1,13 @@ -import { deref, ICopy, IToHiccup, Nullable } from "@thi.ng/api"; -import { isFunction, isNumber } from "@thi.ng/checks"; +import { ICopy, IToHiccup, Nullable } from "@thi.ng/api"; +import { isNumber } from "@thi.ng/checks"; import { invert23, mulM23, mulV23, transform23 } from "@thi.ng/matrices"; import { ReadonlyVec, set2, Vec } from "@thi.ng/vectors"; import { ANode } from "./anode"; import type { ISceneNode } from "./api"; +import { toHiccup } from "./hiccup"; -export class Node2D extends ANode +export class Node2D + extends ANode implements ICopy, ISceneNode, IToHiccup { translate: Vec; rotate: number; @@ -70,20 +72,6 @@ export class Node2D extends ANode * @param ctx - arbitrary user data */ toHiccup(ctx?: any): any { - const body = isFunction(this.body) ? this.body(ctx) : deref(this.body); - return this.enabled && this.display - ? this.children.length - ? [ - "g", - {}, - this.body - ? ["g", { transform: this.mat }, body] - : undefined, - ...this.children.map((c) => c.toHiccup(ctx)), - ] - : body - ? ["g", { transform: this.mat }, body] - : undefined - : undefined; + return toHiccup(this, ctx); } } diff --git a/packages/scenegraph/src/node3.ts b/packages/scenegraph/src/node3.ts index 72bc40cfdc..0874936116 100644 --- a/packages/scenegraph/src/node3.ts +++ b/packages/scenegraph/src/node3.ts @@ -1,11 +1,13 @@ -import { deref, ICopy, IToHiccup, Nullable } from "@thi.ng/api"; -import { isFunction, isNumber } from "@thi.ng/checks"; +import { ICopy, IToHiccup, Nullable } from "@thi.ng/api"; +import { isNumber } from "@thi.ng/checks"; import { invert44, mulM44, mulV344, transform44 } from "@thi.ng/matrices"; import { ReadonlyVec, set3, Vec } from "@thi.ng/vectors"; import { ANode } from "./anode"; import type { ISceneNode } from "./api"; +import { toHiccup } from "./hiccup"; -export class Node3D extends ANode +export class Node3D + extends ANode implements ICopy, ISceneNode, IToHiccup { translate: Vec; rotate: Vec; @@ -69,20 +71,6 @@ export class Node3D extends ANode * @param ctx - arbitrary user data */ toHiccup(ctx?: any): any { - const body = isFunction(this.body) ? this.body(ctx) : deref(this.body); - return this.enabled && this.display - ? this.children.length - ? [ - "g", - {}, - this.body - ? ["g", { transform: this.mat }, body] - : undefined, - ...this.children.map((c) => c.toHiccup(ctx)), - ] - : body - ? ["g", { transform: this.mat }, body] - : undefined - : undefined; + return toHiccup(this, ctx); } } From 933920d0d4ed125a9ea687e0a44509a5312bd008 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 21:09:26 +0100 Subject: [PATCH 061/106] refactor(geom-subdiv-curve): update MID_OPEN, THIRDS_OPEN --- packages/geom-subdiv-curve/src/api.ts | 28 +++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/geom-subdiv-curve/src/api.ts b/packages/geom-subdiv-curve/src/api.ts index 3478ee6bda..3de989626f 100644 --- a/packages/geom-subdiv-curve/src/api.ts +++ b/packages/geom-subdiv-curve/src/api.ts @@ -1,14 +1,10 @@ +import type { FnU } from "@thi.ng/api"; +import type { SubdivKernel } from "@thi.ng/geom-api"; import { wrapSides } from "@thi.ng/transducers"; -import { mixN, ReadonlyVec } from "@thi.ng/vectors"; +import { addmN, mixN, ReadonlyVec } from "@thi.ng/vectors"; import { kernel3 } from "./kernels"; -import type { SubdivKernel } from "@thi.ng/geom-api"; - -const CHAIKIN_FIRST = kernel3([1 / 2, 1 / 2, 0], [0, 3 / 4, 1 / 4]); -const CHAIKIN_MAIN = kernel3([1 / 4, 3 / 4, 0], [0, 3 / 4, 1 / 4]); -const CHAIKIN_LAST = kernel3([1 / 4, 3 / 4, 0], [0, 1 / 2, 1 / 2]); -const CUBIC_MAIN = kernel3([1 / 8, 3 / 4, 1 / 8], [0, 1 / 2, 1 / 2]); -const MIDP = ([a, b]: ReadonlyVec[]) => [a, mixN([], a, b, 0.5)]; +const MIDP = ([a, b]: ReadonlyVec[]) => [a, addmN([], a, b, 0.5)]; const THIRDS = ([a, b]: ReadonlyVec[]) => [ a, mixN([], a, b, 1 / 3), @@ -18,12 +14,18 @@ const THIRDS = ([a, b]: ReadonlyVec[]) => [ const wrap2 = (pts: ReadonlyVec[]) => wrapSides(pts, 0, 1); const wrap3 = (pts: ReadonlyVec[]) => wrapSides(pts, 1, 1); +const subdivWith = (fn: FnU): SubdivKernel["fn"] => ( + pts, + i, + n +) => (i < n - 2 ? fn(pts) : [...fn(pts), pts[1]]); + /** * Splits each curve / line segment into halves at midpoint. Version for * open curves. */ export const SUBDIV_MID_OPEN: SubdivKernel = { - fn: (pts, i, n) => (i < n - 2 ? MIDP(pts) : [...MIDP(pts), pts[1]]), + fn: subdivWith(MIDP), size: 2, }; @@ -42,7 +44,7 @@ export const SUBDIV_MID_CLOSED: SubdivKernel = { * open curves. */ export const SUBDIV_THIRDS_OPEN: SubdivKernel = { - fn: (pts, i, n) => (i < n - 2 ? THIRDS(pts) : [...THIRDS(pts), pts[1]]), + fn: subdivWith(THIRDS), size: 2, }; @@ -56,6 +58,10 @@ export const SUBDIV_THIRDS_CLOSED: SubdivKernel = { size: 2, }; +const CHAIKIN_FIRST = kernel3([1 / 2, 1 / 2, 0], [0, 3 / 4, 1 / 4]); +const CHAIKIN_MAIN = kernel3([1 / 4, 3 / 4, 0], [0, 3 / 4, 1 / 4]); +const CHAIKIN_LAST = kernel3([1 / 4, 3 / 4, 0], [0, 1 / 2, 1 / 2]); + /** * Chaikin subdivision scheme for open curves. */ @@ -78,6 +84,8 @@ export const SUBDIV_CHAIKIN_CLOSED: SubdivKernel = { size: 3, }; +const CUBIC_MAIN = kernel3([1 / 8, 3 / 4, 1 / 8], [0, 1 / 2, 1 / 2]); + /** * Cubic bezier subdivision scheme for closed curves. */ From 4f3d6e02a0ff3fe7307cd03404277c03123f83e9 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 21:35:44 +0100 Subject: [PATCH 062/106] feat(transducers): add mapcatIndexed() xform --- packages/transducers/src/index.ts | 1 + .../transducers/src/xform/mapcat-indexed.ts | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 packages/transducers/src/xform/mapcat-indexed.ts diff --git a/packages/transducers/src/index.ts b/packages/transducers/src/index.ts index 8f5f27df8e..36b070c1cb 100644 --- a/packages/transducers/src/index.ts +++ b/packages/transducers/src/index.ts @@ -64,6 +64,7 @@ export * from "./xform/map-nth"; export * from "./xform/map-vals"; export * from "./xform/map"; export * from "./xform/mapcat"; +export * from "./xform/mapcat-indexed"; export * from "./xform/match-first"; export * from "./xform/match-last"; export * from "./xform/moving-average"; diff --git a/packages/transducers/src/xform/mapcat-indexed.ts b/packages/transducers/src/xform/mapcat-indexed.ts new file mode 100644 index 0000000000..a620672883 --- /dev/null +++ b/packages/transducers/src/xform/mapcat-indexed.ts @@ -0,0 +1,37 @@ +import type { Fn2 } from "@thi.ng/api"; +import type { Transducer } from "../api"; +import { comp } from "../func/comp"; +import { $iter, iterator } from "../iterator"; +import { cat } from "./cat"; +import { mapIndexed } from "./map-indexed"; + +/** + * Transducer. Similar to {@link (mapcat:1)}, but given `fn` takes two + * arguments: `index` and `value` to transform. + * + * @remarks + * An optional start index `offset` can be provided (default 0). Also see + * {@link (mapIndexed:1)}. + * + * @param fn - transformation function + * @param offset - initial index + */ +export function mapcatIndexed( + fn: Fn2 | null | undefined>, + offset?: number +): Transducer; +export function mapcatIndexed( + fn: Fn2 | null | undefined>, + src: Iterable +): IterableIterator; +export function mapcatIndexed( + fn: Fn2 | null | undefined>, + offset: number, + src: Iterable +): IterableIterator; +export function mapcatIndexed(...args: any[]): any { + return ( + $iter(mapcatIndexed, args, iterator) || + comp(mapIndexed>(args[0], args[1]), cat()) + ); +} From be79f2e7b749c92b18a530d854b72fb85678dc7b Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 21:36:57 +0100 Subject: [PATCH 063/106] refactor(geom-subdiv-curve): update subdivide() - use mapcatIndexed() to simplify composed xform --- packages/geom-subdiv-curve/src/subdivide.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/geom-subdiv-curve/src/subdivide.ts b/packages/geom-subdiv-curve/src/subdivide.ts index 04e9f3618e..2f074a4b6f 100644 --- a/packages/geom-subdiv-curve/src/subdivide.ts +++ b/packages/geom-subdiv-curve/src/subdivide.ts @@ -1,7 +1,6 @@ import { comp, - indexed, - mapcat, + mapcatIndexed, partition, push, transduce, @@ -26,8 +25,7 @@ export const subdivide = ( pts = transduce( comp( partition(size, 1), - indexed(), - mapcat(([i, pts]) => fn(pts, i, nump)) + mapcatIndexed((i, pts) => fn(pts, i, nump)) ), push(), pre ? pre(pts) : pts From 19396cff8086edce608d6bacecae3a3c9b0977d5 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 21:39:16 +0100 Subject: [PATCH 064/106] refactor(viz): update stackedIntervals() - use mapcatIndexed() to simplify composed xform --- packages/viz/src/plot/stacked-intervals.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/viz/src/plot/stacked-intervals.ts b/packages/viz/src/plot/stacked-intervals.ts index 860a6397a2..3de201c732 100644 --- a/packages/viz/src/plot/stacked-intervals.ts +++ b/packages/viz/src/plot/stacked-intervals.ts @@ -2,10 +2,9 @@ import type { Fn, Fn2 } from "@thi.ng/api"; import { comp, filter, - indexed, iterator, map, - mapcat, + mapcatIndexed, push, some, transduce, @@ -38,10 +37,10 @@ const rowStacking = (data: [number[], T][], pad = 0) => } }, []>[]); -const processRow = (mapper: Fn, [d1, d2]: Domain) => ([ - i, - row, -]: [number, Row]) => +const processRow = (mapper: Fn, [d1, d2]: Domain) => ( + i: number, + row: Row +) => map( ([[a, b], item]) => <[number[], number[], T, number]>[ @@ -64,8 +63,7 @@ export const stackedIntervals = ( opts.attribs, ...iterator( comp( - indexed(), - mapcat(processRow(mapper, domain)), + mapcatIndexed(processRow(mapper, domain)), map((x) => opts.shape(x, mapper)) ), rowStacking( From 9919c56181340c949d126bff34c288677d509b00 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 21:47:37 +0100 Subject: [PATCH 065/106] refactor(associative): remove obsolete string coercions --- packages/associative/src/trie-map.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/associative/src/trie-map.ts b/packages/associative/src/trie-map.ts index 756f1ee65f..3175b2d3c6 100644 --- a/packages/associative/src/trie-map.ts +++ b/packages/associative/src/trie-map.ts @@ -75,7 +75,7 @@ export class TrieMap { find(key: string) { let node: TrieMap | undefined = this; for (let i = 0, n = key.length; i < n; i++) { - node = node!.next[key[i].toString()]; + node = node!.next[key[i]]; if (!node) return; } return node; @@ -107,7 +107,7 @@ export class TrieMap { set(key: string, val: T) { let node: TrieMap = this; for (let i = 0, n = key.length; i < n; i++) { - const k = key[i].toString(); + const k = key[i]; const next = node.next[k]; node = !next ? (node.n++, (node.next[k] = new TrieMap())) : next; } @@ -128,7 +128,7 @@ export class TrieMap { let i = 0; let node: TrieMap | undefined = this; for (; i < n; i++) { - const k = prefix[i].toString(); + const k = prefix[i]; key.push(k); path.push(node); node = node.next[k]; From 0c965c95623420e5f8b76a14a0c427b838c64a28 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 22:08:10 +0100 Subject: [PATCH 066/106] refactor(hiccup): extract mergeEmmetAttribs() - simplify normalize() and improve external re-use in hdom/rdom --- .../hiccup/src/{classes.ts => attribs.ts} | 24 ++++++++++++++++ packages/hiccup/src/index.ts | 2 +- packages/hiccup/src/normalize.ts | 28 ++++++------------- 3 files changed, 33 insertions(+), 21 deletions(-) rename packages/hiccup/src/{classes.ts => attribs.ts} (62%) diff --git a/packages/hiccup/src/classes.ts b/packages/hiccup/src/attribs.ts similarity index 62% rename from packages/hiccup/src/classes.ts rename to packages/hiccup/src/attribs.ts index ee34468d9f..eb446f4242 100644 --- a/packages/hiccup/src/classes.ts +++ b/packages/hiccup/src/attribs.ts @@ -36,3 +36,27 @@ export const mergeClasses = (existing: string, val: any) => { } return [...classes].join(" "); }; + +/** + * Takes an attrib object and optional element ID and CSS class names from Emmet-style + * hiccup tag, then transforms and merges definitions, returns attribs. + * + * @param attribs + * @param id + * @param classes + */ +export const mergeEmmetAttribs = ( + attribs: any, + id?: string, + classes?: string +) => { + id && (attribs.id = id); + let aclass = deref(attribs.class); + if (classes) { + classes = classes.replace(/\./g, " "); + attribs.class = aclass ? mergeClasses(classes, aclass) : classes; + } else if (aclass) { + attribs.class = isString(aclass) ? aclass : mergeClasses("", aclass); + } + return attribs; +}; diff --git a/packages/hiccup/src/index.ts b/packages/hiccup/src/index.ts index 8e3e307591..9ea2128cd7 100644 --- a/packages/hiccup/src/index.ts +++ b/packages/hiccup/src/index.ts @@ -1,5 +1,5 @@ export * from "./api"; -export * from "./classes"; +export * from "./attribs"; export * from "./css"; export * from "./deref"; export * from "./escape"; diff --git a/packages/hiccup/src/normalize.ts b/packages/hiccup/src/normalize.ts index 27e23180ee..a7dff95e9e 100644 --- a/packages/hiccup/src/normalize.ts +++ b/packages/hiccup/src/normalize.ts @@ -1,35 +1,23 @@ -import { deref } from "@thi.ng/api"; import { isPlainObject, isString } from "@thi.ng/checks"; import { illegalArgs } from "@thi.ng/errors"; import { RE_TAG } from "./api"; -import { mergeClasses } from "./classes"; +import { mergeEmmetAttribs } from "./attribs"; export const normalize = (tag: any[]) => { - let el = tag[0]; + let name = tag[0]; let match: RegExpExecArray | null; - let id: string; - let clazz: string; const hasAttribs = isPlainObject(tag[1]); const attribs: any = hasAttribs ? { ...tag[1] } : {}; - if (!isString(el) || !(match = RE_TAG.exec(el))) { - illegalArgs(`"${el}" is not a valid tag name`); - } - el = match![1]; - id = match![2]; - clazz = match![3]; - id && (attribs.id = id); - let aclass = deref(attribs.class); - if (clazz) { - clazz = clazz.replace(/\./g, " "); - attribs.class = aclass ? mergeClasses(clazz, aclass) : clazz; - } else if (aclass) { - attribs.class = isString(aclass) ? aclass : mergeClasses("", aclass); + if (!isString(name) || !(match = RE_TAG.exec(name))) { + illegalArgs(`"${name}" is not a valid tag name`); } + name = match![1]; + mergeEmmetAttribs(attribs, match![2], match![3]); if (tag.length > 1) { tag = tag.slice(hasAttribs ? 2 : 1).filter((x) => x != null); if (tag.length > 0) { - return [el, attribs, tag]; + return [name, attribs, tag]; } } - return [el, attribs]; + return [name, attribs]; }; From b310c6146afcb6b5e68e6f86c2e654c57c2b0a8d Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 22:08:52 +0100 Subject: [PATCH 067/106] refactor(hdom): simplify normalizeElement() --- packages/hdom/src/normalize.ts | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/packages/hdom/src/normalize.ts b/packages/hdom/src/normalize.ts index 371f513f89..abe871d001 100644 --- a/packages/hdom/src/normalize.ts +++ b/packages/hdom/src/normalize.ts @@ -2,16 +2,14 @@ import { isArray as isa, isNotStringAndIterable as isi, isPlainObject as iso, - isString as iss, } from "@thi.ng/checks"; import { illegalArgs } from "@thi.ng/errors"; -import { mergeClasses, NO_SPANS, RE_TAG } from "@thi.ng/hiccup"; +import { mergeEmmetAttribs, NO_SPANS, RE_TAG } from "@thi.ng/hiccup"; import type { HDOMOpts } from "./api"; const isArray = isa; const isNotStringAndIterable = isi; const isPlainObject = iso; -const isString = iss; /** * Expands single hiccup element/component into its canonical form: @@ -46,32 +44,21 @@ export const normalizeElement = (spec: any[], keys: boolean) => { let tag = spec[0]; let hasAttribs = isPlainObject(spec[1]); let match: RegExpExecArray | null; - let mtag: string; - let id: string; - let clazz: string; + let name: string; let attribs; if (typeof tag !== "string" || !(match = RE_TAG.exec(tag))) { illegalArgs(`${tag} is not a valid tag name`); } - mtag = match![1]; + name = match![1]; // return orig if already normalized and satisfies key requirement - if (tag === mtag && hasAttribs && (!keys || spec[1].key)) { + if (tag === name && hasAttribs && (!keys || spec[1].key)) { return spec; } attribs = hasAttribs ? { ...spec[1] } : {}; - id = match![2]; - clazz = match![3]; - id && (attribs.id = id); - const aclass = attribs.class; - if (clazz) { - clazz = clazz.replace(/\./g, " "); - attribs.class = aclass ? mergeClasses(clazz, aclass) : clazz; - } else if (aclass) { - attribs.class = isString(aclass) ? aclass : mergeClasses("", aclass); - } + mergeEmmetAttribs(attribs, match![2], match![3]); return attribs.__skip && spec.length < 3 - ? [mtag, attribs] - : [mtag, attribs, ...spec.slice(hasAttribs ? 2 : 1)]; + ? [name, attribs] + : [name, attribs, ...spec.slice(hasAttribs ? 2 : 1)]; }; /** From b777cf14f722b71f40f45cd410b68d463a743dee Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 22:09:55 +0100 Subject: [PATCH 068/106] refactor(rdom): simplify $el() attrib handling --- packages/rdom/src/dom.ts | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/packages/rdom/src/dom.ts b/packages/rdom/src/dom.ts index 2d23444b6d..fa44829f84 100644 --- a/packages/rdom/src/dom.ts +++ b/packages/rdom/src/dom.ts @@ -12,6 +12,7 @@ import { ATTRIB_JOIN_DELIMS, formatPrefixes, mergeClasses, + mergeEmmetAttribs, NO_SPANS, RE_TAG, SVG_TAGS, @@ -121,19 +122,8 @@ export const $el = ( ) => { const match = RE_TAG.exec(tag); if (match) { - let [, mtag, id, clazz] = match; - attribs = { ...attribs }; - id && (attribs.id = id); - const aclass = deref(attribs.class); - if (clazz) { - clazz = clazz.replace(/\./g, " "); - attribs.class = aclass ? mergeClasses(clazz, aclass) : clazz; - } else if (aclass) { - attribs.class = isString(aclass) - ? aclass - : mergeClasses("", aclass); - } - tag = mtag; + attribs = mergeEmmetAttribs({ ...attribs }, match[2], match[3]); + tag = match[1]; } let el: Element; const qidx = tag.indexOf(":"); From ebab5a0da505d0f199e3599281668a06907b9d44 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 22:27:54 +0100 Subject: [PATCH 069/106] refactor(rstream): add isFirstOrLastInput(), update StreamMerge/Sync --- packages/rstream/src/stream-merge.ts | 10 +++------- packages/rstream/src/stream-sync.ts | 16 +++------------- packages/rstream/src/utils/checks.ts | 9 +++++++++ 3 files changed, 15 insertions(+), 20 deletions(-) create mode 100644 packages/rstream/src/utils/checks.ts diff --git a/packages/rstream/src/stream-merge.ts b/packages/rstream/src/stream-merge.ts index c751808ca9..01097618e1 100644 --- a/packages/rstream/src/stream-merge.ts +++ b/packages/rstream/src/stream-merge.ts @@ -1,5 +1,6 @@ -import { CloseMode, ISubscribable, State, TransformableOpts } from "./api"; +import { ISubscribable, State, TransformableOpts } from "./api"; import { Subscription } from "./subscription"; +import { isFirstOrLastInput } from "./utils/checks"; import { optsWithID } from "./utils/idgen"; export interface StreamMergeOpts extends TransformableOpts { @@ -145,11 +146,6 @@ export class StreamMerge extends Subscription { protected markDone(src: ISubscribable) { this.remove(src); - if ( - this.closeIn === CloseMode.FIRST || - (this.closeIn === CloseMode.LAST && !this.sources.size) - ) { - this.done(); - } + isFirstOrLastInput(this.closeIn, this.sources.size) && this.done(); } } diff --git a/packages/rstream/src/stream-sync.ts b/packages/rstream/src/stream-sync.ts index d2fdfc17fb..d965abebd3 100644 --- a/packages/rstream/src/stream-sync.ts +++ b/packages/rstream/src/stream-sync.ts @@ -6,14 +6,9 @@ import { partitionSync, PartitionSync, } from "@thi.ng/transducers"; -import { - CloseMode, - ISubscribable, - LOGGER, - State, - TransformableOpts, -} from "./api"; +import { ISubscribable, LOGGER, State, TransformableOpts } from "./api"; import { Subscription } from "./subscription"; +import { isFirstOrLastInput } from "./utils/checks"; import { optsWithID } from "./utils/idgen"; export type SyncTuple>> = { @@ -283,11 +278,6 @@ export class StreamSync< protected markDone(src: ISubscribable) { this.remove(src); - if ( - this.closeIn === CloseMode.FIRST || - (this.closeIn === CloseMode.LAST && !this.sources.size) - ) { - this.done(); - } + isFirstOrLastInput(this.closeIn, this.sources.size) && this.done(); } } diff --git a/packages/rstream/src/utils/checks.ts b/packages/rstream/src/utils/checks.ts new file mode 100644 index 0000000000..77ba0b27ec --- /dev/null +++ b/packages/rstream/src/utils/checks.ts @@ -0,0 +1,9 @@ +import { CloseMode } from "../api"; + +/** + * Returns true if mode is FIRST, or if mode is LAST *and* `num = 0`. + * + * @internal + */ +export const isFirstOrLastInput = (mode: CloseMode, num: number) => + mode === CloseMode.FIRST || (mode === CloseMode.LAST && !num); From 13a68e7a0b4a8cf033bdae49f03f308aff801306 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 18 Sep 2020 22:42:31 +0100 Subject: [PATCH 070/106] refactor(pointfree-lang): update visitWord(), extract pushLocals() --- packages/pointfree-lang/src/index.ts | 30 ++++++++++++++++------------ 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/pointfree-lang/src/index.ts b/packages/pointfree-lang/src/index.ts index 9893ad0eeb..64ca03c414 100644 --- a/packages/pointfree-lang/src/index.ts +++ b/packages/pointfree-lang/src/index.ts @@ -1,4 +1,4 @@ -import { Fn2, ILogger, IObjectOf, NULL_LOGGER } from "@thi.ng/api"; +import { Fn, Fn2, FnU, ILogger, IObjectOf, NULL_LOGGER } from "@thi.ng/api"; import { illegalArgs, illegalState } from "@thi.ng/errors"; import * as pf from "@thi.ng/pointfree"; import { ALIASES, ASTNode, NodeType, VisitorState } from "./api"; @@ -142,7 +142,7 @@ const storevar = (id: string) => (ctx: pf.StackContext) => { * * @param id - */ -const beginvar = (id: string) => (ctx: pf.StackContext) => { +const beginvar = (id: string): FnU => (ctx) => { pf.ensureStack(ctx[0], 1); const v = ctx[2].__vars[id]; if (v === undefined) { @@ -161,7 +161,7 @@ const beginvar = (id: string) => (ctx: pf.StackContext) => { * * @param id - */ -const endvar = (id: string) => (ctx: pf.StackContext) => { +const endvar = (id: string): FnU => (ctx) => { const v = ctx[2].__vars[id]; if (v === undefined || v.length === 0) { illegalState(`can't end scope for var: ${id}`); @@ -261,6 +261,18 @@ const visitStore = ( return state.word ? (ctx[0].push(store), ctx) : store(ctx); }; +const pushLocals = ( + fn: Fn, + wctx: pf.StackContext, + locals: string[] +) => { + if (locals) { + for (let stack = wctx[0], i = locals.length; --i >= 0; ) { + stack.push(fn(locals[i])); + } + } +}; + /** * WORD visitor to create new word definition. Sets `state.word` to * true, builds temp stack context and calls {@link visit} for all child @@ -289,19 +301,11 @@ const visitWord = ( let wctx = pf.ctx([], ctx[2]); state.word = { name: id, loc: node.loc }; const locals = node.locals; - if (locals) { - for (let stack = wctx[0], i = locals.length; --i >= 0; ) { - stack.push(beginvar(locals[i])); - } - } + pushLocals(beginvar, wctx, locals); for (let n of node.body) { wctx = visit(n, wctx, state); } - if (locals) { - for (let stack = wctx[0], i = locals.length; --i >= 0; ) { - stack.push(endvar(locals[i])); - } - } + pushLocals(endvar, wctx, locals); const w = pf.defWord(wctx[0]); (w).__meta = state.word; ctx[2].__words[id] = w; From 498e4e5b35cd5181bc039b4b742e2fa4a34ddde2 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 00:16:09 +0100 Subject: [PATCH 071/106] refactor(oquery): dedupe, simplify sub-query fns --- packages/oquery/src/query.ts | 71 ++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/packages/oquery/src/query.ts b/packages/oquery/src/query.ts index db5ae5ee38..48419091fc 100644 --- a/packages/oquery/src/query.ts +++ b/packages/oquery/src/query.ts @@ -4,13 +4,13 @@ import { defmulti } from "@thi.ng/defmulti"; import { equiv } from "@thi.ng/equiv"; import type { FTerm, + OTerm, QueryImpl, QueryImpls, QueryObj, QueryOpts, - SPTerm, - OTerm, SPInputTerm, + SPTerm, } from "./api"; const classify = (x: any) => (x != null ? (isFunction(x) ? "f" : "l") : "n"); @@ -51,11 +51,7 @@ const queryLL: QueryImpl = (res, db, s, p, o, opts) => const queryLF: QueryImpl = (res, db, s, p, o, opts) => { const sval = db[s]; - if (sval != null) { - for (let q in sval) { - (p)(q) && collect(res, s, q, o, sval[q], opts); - } - } + sval != null && collectSP(res, sval, s, p, o, opts); }; const queryLN: QueryImpl = (res, db, s, _, o, opts) => { @@ -75,12 +71,7 @@ const queryFL: QueryImpl = (res, db, s, p, o, opts) => { const queryFF: QueryImpl = (res, db, s, p, o, opts) => { for (let $s in db) { - if ((s)($s)) { - const sval = db[$s]; - for (let $p in sval) { - (p)($p) && collect(res, $s, $p, o, sval[$p], opts); - } - } + (s)($s) && collectSP(res, db[$s], $s, p, o, opts); } }; @@ -119,6 +110,33 @@ const queryNN: QueryImpl = (res, db, _, __, o, opts) => { } }; +const collectSP = ( + res: QueryObj, + sval: any, + s: SPTerm, + p: SPTerm, + o: any, + opts: QueryOpts +) => { + for (let $p in sval) { + (p)($p) && collect(res, s, $p, o, sval[$p], opts); + } +}; + +const querySP = (res: QueryObj, sval: any, s: SPTerm, p: SPTerm) => { + for (let q in sval) { + if ((p)(q)) { + const val = sval[q]; + val != null && addTriple(res, s, q, val); + } + } +}; + +const queryO = (res: QueryObj, db: QueryObj, s: SPTerm, p: SPTerm) => { + const val = db[s]?.[p]; + val != null && addTriple(res, s, p, val); +}; + const impl = defmulti< QueryObj, QueryObj, @@ -132,22 +150,12 @@ const impl = defmulti< impl.addAll({ lll: queryLL, llf: queryLL, - lln: (res, db, s, p, _) => { - const val = db[s]?.[p]; - val != null && addTriple(res, s, p, val); - }, + lln: queryO, lfl: queryLF, lff: queryLF, lfn: (res, db, s, p, _) => { const sval = db[s]; - if (sval != null) { - for (let q in sval) { - if ((p)(q)) { - const val = sval[q]; - val != null && addTriple(res, s, q, val); - } - } - } + sval != null && querySP(res, sval, s, p); }, lnl: queryLN, lnf: queryLN, @@ -161,10 +169,7 @@ impl.addAll({ flf: queryFL, fln: (res, db, s, p, _) => { for (let $s in db) { - if ((s)($s)) { - const val = db[$s]?.[p]; - val != null && addTriple(res, $s, p, val); - } + (s)($s) && queryO(res, db, $s, p); } }, ffl: queryFF, @@ -203,13 +208,7 @@ impl.addAll({ nff: queryNF, nfn: (res, db, _, p, __) => { for (let s in db) { - const sval = db[s]; - for (let $p in sval) { - if ((p)($p)) { - const val = sval[$p]; - val != null && addTriple(res, s, $p, val); - } - } + querySP(res, db[s], s, p); } }, nnl: queryNN, From 4fb9b4b7ac5e7e310e7171ba0c14c53f52a056f8 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 00:34:09 +0100 Subject: [PATCH 072/106] refactor(oquery): further sub-query extraction/re-use --- packages/oquery/src/query.ts | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/packages/oquery/src/query.ts b/packages/oquery/src/query.ts index 48419091fc..76ba7dd7ad 100644 --- a/packages/oquery/src/query.ts +++ b/packages/oquery/src/query.ts @@ -56,11 +56,7 @@ const queryLF: QueryImpl = (res, db, s, p, o, opts) => { const queryLN: QueryImpl = (res, db, s, _, o, opts) => { const sval = db[s]; - if (sval != null) { - for (let q in sval) { - collect(res, s, q, o, sval[q], opts); - } - } + sval != null && collectSO(res, sval, s, o, opts); }; const queryFL: QueryImpl = (res, db, s, p, o, opts) => { @@ -77,12 +73,7 @@ const queryFF: QueryImpl = (res, db, s, p, o, opts) => { const queryFN: QueryImpl = (res, db, s, _, o, opts) => { for (let $s in db) { - if ((s)($s)) { - const sval = db[$s]; - for (let p in sval) { - collect(res, $s, p, o, sval[p], opts); - } - } + (s)($s) && collectSO(res, db[$s], $s, o, opts); } }; @@ -94,19 +85,13 @@ const queryNL: QueryImpl = (res, db, _, p, o, opts) => { const queryNF: QueryImpl = (res, db, _, p, o, opts) => { for (let s in db) { - const sval = db[s]; - for (let $p in sval) { - (p)($p) && collect(res, s, $p, o, sval[$p], opts); - } + collectSP(res, db[s], s, p, o, opts); } }; const queryNN: QueryImpl = (res, db, _, __, o, opts) => { for (let s in db) { - const sval = db[s]; - for (let p in sval) { - collect(res, s, p, o, sval[p], opts); - } + collectSO(res, db[s], s, o, opts); } }; @@ -123,6 +108,18 @@ const collectSP = ( } }; +const collectSO = ( + res: QueryObj, + sval: any, + s: SPTerm, + o: any, + opts: QueryOpts +) => { + for (let p in sval) { + collect(res, s, p, o, sval[p], opts); + } +}; + const querySP = (res: QueryObj, sval: any, s: SPTerm, p: SPTerm) => { for (let q in sval) { if ((p)(q)) { From 24f9a67d82be845a44c5e5be12c1d959979d10a4 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 01:21:04 +0100 Subject: [PATCH 073/106] refactor(hiccup-css): update css() --- packages/hiccup-css/src/css.ts | 34 +++++++++++++++---------------- packages/hiccup-css/test/index.ts | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/hiccup-css/src/css.ts b/packages/hiccup-css/src/css.ts index 4a3be72337..6bf37379d5 100644 --- a/packages/hiccup-css/src/css.ts +++ b/packages/hiccup-css/src/css.ts @@ -1,10 +1,10 @@ import { isArray, isFunction, - isIterable, + isNotStringAndIterable, isPlainObject, - isString, } from "@thi.ng/checks"; +import { illegalArgs } from "@thi.ng/errors"; import { COMPACT, CSSOpts, DEFAULT_VENDORS } from "./api"; import { expand, formatDecls } from "./impl"; @@ -16,19 +16,19 @@ export const css = (rules: any, opts?: Partial) => { depth: 0, ...opts, }; - if (isPlainObject(rules)) { - return formatDecls(rules, opts); - } - if (isArray(opts.autoprefix)) { - opts.autoprefix = new Set(opts.autoprefix); - } - if (isIterable(rules) && !isString(rules)) { - rules = [...rules]; - } - if (isArray(rules)) { - return expand([], [], rules, opts).join(opts.format!.rules); - } - if (isFunction(rules)) { - return rules([], opts).join(opts.format!.rules); - } + isArray(opts.autoprefix) && (opts.autoprefix = new Set(opts.autoprefix)); + return isPlainObject(rules) + ? formatDecls(rules, opts) + : isFunction(rules) + ? rules([], opts).join(opts.format!.rules) + : expand( + [], + [], + isArray(rules) + ? rules + : isNotStringAndIterable(rules) + ? [...rules] + : illegalArgs(`invalid rules`), + opts + ).join(opts.format!.rules); }; diff --git a/packages/hiccup-css/test/index.ts b/packages/hiccup-css/test/index.ts index a5098a171b..3ca50c922c 100644 --- a/packages/hiccup-css/test/index.ts +++ b/packages/hiccup-css/test/index.ts @@ -17,7 +17,7 @@ const rules = { describe("hiccup-css", () => { it("rules only", () => { - assert.strictEqual(css("a"), undefined); + assert.throws(() => css("a")); assert.strictEqual(css({}), ""); assert.strictEqual(css(rules.a), "color:red;"); assert.strictEqual(css(rules.b), "border:0;"); From 32ac755a8a99371d8f70200eea17aaac96b39963 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 01:24:11 +0100 Subject: [PATCH 074/106] refactor(hiccup): update/split serialization fns - extract serializeTag() --- packages/hiccup/src/serialize.ts | 138 +++++++++++++++---------------- 1 file changed, 67 insertions(+), 71 deletions(-) diff --git a/packages/hiccup/src/serialize.ts b/packages/hiccup/src/serialize.ts index 8ad16baef9..c7f0b0090f 100644 --- a/packages/hiccup/src/serialize.ts +++ b/packages/hiccup/src/serialize.ts @@ -168,30 +168,22 @@ const _serialize = ( span: boolean, keys: boolean, path: any[] -): string => { - if (tree == null) { - return ""; - } - if (Array.isArray(tree)) { - return serializeElement(tree, ctx, esc, span, keys, path); - } - if (isFunction(tree)) { - return _serialize(tree(ctx), ctx, esc, span, keys, path); - } - if (implementsFunction(tree, "toHiccup")) { - return _serialize(tree.toHiccup(ctx), ctx, esc, span, keys, path); - } - if (isDeref(tree)) { - return _serialize(tree.deref(), ctx, esc, span, keys, path); - } - if (isNotStringAndIterable(tree)) { - return serializeIter(tree, ctx, esc, span, keys, path); - } - tree = esc ? escape(tree.toString()) : tree; - return span +): string => + tree == null + ? "" + : Array.isArray(tree) + ? serializeElement(tree, ctx, esc, span, keys, path) + : isFunction(tree) + ? _serialize(tree(ctx), ctx, esc, span, keys, path) + : implementsFunction(tree, "toHiccup") + ? _serialize(tree.toHiccup(ctx), ctx, esc, span, keys, path) + : isDeref(tree) + ? _serialize(tree.deref(), ctx, esc, span, keys, path) + : isNotStringAndIterable(tree) + ? serializeIter(tree, ctx, esc, span, keys, path) + : ((tree = esc ? escape(String(tree)) : String(tree)), span) ? `${tree}` : tree; -}; const serializeElement = ( tree: any[], @@ -201,56 +193,60 @@ const serializeElement = ( keys: boolean, path: any[] ) => { - if (!tree.length) { - return ""; - } let tag = tree[0]; - if (isFunction(tag)) { - return _serialize( - tag.apply(null, [ctx, ...tree.slice(1)]), - ctx, - esc, - span, - keys, - path - ); - } - if (implementsFunction(tag, "render")) { - return _serialize( - tag.render.apply(null, [ctx, ...tree.slice(1)]), - ctx, - esc, - span, - keys, - path - ); - } - if (tag === COMMENT) { - return serializeComment(tree); - } - if (tag == CDATA) { - return serializeCData(tree); - } - if (isString(tag)) { - tree = normalize(tree); - tag = tree[0]; - const attribs = tree[1]; - if (attribs.__skip || attribs.__serialize === false) return ""; - const body = tree[2]; - let res = `<${tag}`; - keys && attribs.key === undefined && (attribs.key = path.join("-")); - res += serializeAttribs(attribs, esc); - res += body - ? serializeBody(tag, body, ctx, esc, span, keys, path) - : !VOID_TAGS[tag] && !NO_CLOSE_EMPTY[tag] - ? `>` - : PROC_TAGS[tag] || "/>"; - return res; - } - if (isNotStringAndIterable(tree)) { - return serializeIter(tree, ctx, esc, span, keys, path); - } - return illegalArgs(`invalid tree node: ${tree}`); + return !tree.length + ? "" + : isFunction(tag) + ? _serialize( + tag.apply(null, [ctx, ...tree.slice(1)]), + ctx, + esc, + span, + keys, + path + ) + : implementsFunction(tag, "render") + ? _serialize( + tag.render.apply(null, [ctx, ...tree.slice(1)]), + ctx, + esc, + span, + keys, + path + ) + : tag === COMMENT + ? serializeComment(tree) + : tag == CDATA + ? serializeCData(tree) + : isString(tag) + ? serializeTag(tree, ctx, esc, span, keys, path) + : isNotStringAndIterable(tree) + ? serializeIter(tree, ctx, esc, span, keys, path) + : illegalArgs(`invalid tree node: ${tree}`); +}; + +const serializeTag = ( + tree: any[], + ctx: any, + esc: boolean, + span: boolean, + keys: boolean, + path: any[] +) => { + tree = normalize(tree); + const tag = tree[0]; + const attribs = tree[1]; + if (attribs.__skip || attribs.__serialize === false) return ""; + const body = tree[2]; + let res = `<${tag}`; + keys && attribs.key === undefined && (attribs.key = path.join("-")); + res += serializeAttribs(attribs, esc); + res += body + ? serializeBody(tag, body, ctx, esc, span, keys, path) + : !VOID_TAGS[tag] && !NO_CLOSE_EMPTY[tag] + ? `>` + : PROC_TAGS[tag] || "/>"; + return res; }; const serializeAttribs = (attribs: any, esc: boolean) => { From e988d0d45330be35750f171d338d3b248494bca7 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 01:24:46 +0100 Subject: [PATCH 075/106] refactor(checks): update isNode() --- packages/checks/src/is-node.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/checks/src/is-node.ts b/packages/checks/src/is-node.ts index 230a37edea..e8e5850190 100644 --- a/packages/checks/src/is-node.ts +++ b/packages/checks/src/is-node.ts @@ -1,12 +1,6 @@ declare var process: any; -export const isNode = () => { - if (typeof process === "object") { - if (typeof process.versions === "object") { - if (typeof process.versions.node !== "undefined") { - return true; - } - } - } - return false; -}; +export const isNode = () => + typeof process === "object" && + typeof process.versions === "object" && + typeof process.versions.node !== "undefined"; From cdf483b0666da05eec28cbd337eed1191295b2a7 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 02:08:27 +0100 Subject: [PATCH 076/106] refactor(hiccup): update/split serializeAttribs() --- packages/hiccup/src/serialize.ts | 63 ++++++++++++++++---------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/packages/hiccup/src/serialize.ts b/packages/hiccup/src/serialize.ts index c7f0b0090f..9d00007408 100644 --- a/packages/hiccup/src/serialize.ts +++ b/packages/hiccup/src/serialize.ts @@ -234,53 +234,54 @@ const serializeTag = ( path: any[] ) => { tree = normalize(tree); - const tag = tree[0]; const attribs = tree[1]; if (attribs.__skip || attribs.__serialize === false) return ""; - const body = tree[2]; - let res = `<${tag}`; keys && attribs.key === undefined && (attribs.key = path.join("-")); - res += serializeAttribs(attribs, esc); - res += body - ? serializeBody(tag, body, ctx, esc, span, keys, path) + const tag = tree[0]; + const body = tree[2] + ? serializeBody(tag, tree[2], ctx, esc, span, keys, path) : !VOID_TAGS[tag] && !NO_CLOSE_EMPTY[tag] ? `>` : PROC_TAGS[tag] || "/>"; - return res; + return `<${tag}${serializeAttribs(attribs, esc)}${body}`; }; const serializeAttribs = (attribs: any, esc: boolean) => { let res = ""; for (let a in attribs) { if (a.startsWith("__")) continue; - let v = deref(attribs[a]); - if (v == null) continue; - if (isFunction(v) && (/^on\w+/.test(a) || (v = v(attribs)) == null)) - continue; - if (v === true) { - res += " " + a; - continue; - } else if (v === false) { - continue; - } - if (a === "data") { - res += serializeDataAttribs(v, esc); - continue; - } - if (a === "style" && isPlainObject(v)) { - v = css(v); - } else if (a === "prefix" && isPlainObject(v)) { - v = formatPrefixes(v); - } else { - v = isArray(v) - ? v.join(ATTRIB_JOIN_DELIMS[a] || " ") - : v.toString(); - } - v.length && (res += ` ${a}="${esc ? escape(v) : v}"`); + const v = serializeAttrib(attribs, a, deref(attribs[a]), esc); + v != null && (res += v); } return res; }; +const serializeAttrib = (attribs: any, a: string, v: any, esc: boolean) => { + return v == null + ? null + : isFunction(v) && (/^on\w+/.test(a) || (v = v(attribs)) == null) + ? null + : v === true + ? " " + a + : v === false + ? null + : a === "data" + ? serializeDataAttribs(v, esc) + : attribPair(a, v, esc); +}; + +const attribPair = (a: string, v: any, esc: boolean) => { + v = + a === "style" && isPlainObject(v) + ? css(v) + : a === "prefix" && isPlainObject(v) + ? formatPrefixes(v) + : isArray(v) + ? v.join(ATTRIB_JOIN_DELIMS[a] || " ") + : v.toString(); + return v.length ? ` ${a}="${esc ? escape(v) : v}"` : null; +}; + const serializeDataAttribs = (data: any, esc: boolean) => { let res = ""; for (let id in data) { From de159e09576c77c26aa9cacd88eb95f6a190aee4 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 10:19:25 +0100 Subject: [PATCH 077/106] refactor(rdom): split $tree() --- packages/rdom/src/dom.ts | 91 +++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/packages/rdom/src/dom.ts b/packages/rdom/src/dom.ts index fa44829f84..3cb4d71fcf 100644 --- a/packages/rdom/src/dom.ts +++ b/packages/rdom/src/dom.ts @@ -7,7 +7,7 @@ import { isNumber, isString, } from "@thi.ng/checks"; -import { illegalArgs } from "@thi.ng/errors"; +import { unsupported } from "@thi.ng/errors"; import { ATTRIB_JOIN_DELIMS, formatPrefixes, @@ -47,53 +47,58 @@ export const $tree = async ( tree: any, parent: Element, idx: NumOrElement = -1 -): Promise => { - if (isArray(tree)) { - const tag = tree[0]; - // [tag, attribs, ...body] - if (isString(tag)) { - const n = tree.length; - const { 1: attribs, 2: body } = tree; - if (n === 3 && (isString(body) || isNumber(body))) { - // emmet-free base tag - const tmp = /^\w+/.exec(tag); - if (tmp && NO_SPANS[tmp[0]]) { - // don't wrap single body in here - parent = $el(tag, attribs, body, parent, idx); - return parent; - } - } - parent = $el(tag, attribs, null, parent, idx); - for (let i = 2; i < n; i++) { - $tree(tree[i], parent); - } +): Promise => + isArray(tree) + ? $treeElem(tree, parent, idx) + : isComponent(tree) + ? tree.mount(parent, idx) + : isDeref(tree) + ? $tree(tree.deref(), parent) + : isNotStringAndIterable(tree) + ? $treeIter(tree, parent) + : tree != null + ? $el("span", null, tree, parent, idx) + : null; + +const $treeElem = (tree: any, parent: Element, idx: NumOrElement) => { + const tag = tree[0]; + // [tag, attribs, ...body] + return isString(tag) + ? $treeTag(tree, parent, idx) + : // [icomponent, ...args] + isComponent(tag) + ? tag.mount(parent, idx, ...tree.slice(1)) + : // [fn, ...args] + isFunction(tag) + ? $tree(tag.apply(null, tree.slice(1)), parent) + : // unsupported + unsupported(`tag: ${tag}`); +}; + +const $treeTag = (tree: any, parent: Element, idx: NumOrElement) => { + const n = tree.length; + const { 0: tag, 1: attribs, 2: body } = tree; + if (n === 3 && (isString(body) || isNumber(body))) { + // emmet-free base tag + const tmp = /^\w+/.exec(tag); + if (tmp && NO_SPANS[tmp[0]]) { + // don't wrap single body in here + parent = $el(tag, attribs, body, parent, idx); return parent; } - // [icomponent, ...args] - if (isComponent(tag)) { - return tag.mount(parent, idx, ...tree.slice(1)); - } - // [fn, ...args] - if (isFunction(tag)) { - return $tree(tag.apply(null, tree.slice(1)), parent); - } - illegalArgs(`tag not supported: ${tag}`); - } - if (isComponent(tree)) { - return tree.mount(parent, idx); } - if (isDeref(tree)) { - return $tree(tree.deref(), parent); + parent = $el(tag, attribs, null, parent, idx); + for (let i = 2; i < n; i++) { + $tree(tree[i], parent); } - if (isNotStringAndIterable(tree)) { - for (let t of tree) { - $tree(t, parent); - } - return; + return parent; +}; + +const $treeIter = (tree: any, parent: Element) => { + for (let t of tree) { + $tree(t, parent); } - return tree != null - ? $el("span", null, tree, parent, idx) - : null; + return null; }; /** From 91b43292e71f1bad02714a516f3a305f6a89b385 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 10:28:47 +0100 Subject: [PATCH 078/106] refactor(webgl): split Texture.configure() --- packages/webgl/src/texture.ts | 68 +++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/packages/webgl/src/texture.ts b/packages/webgl/src/texture.ts index b8b91ba8de..096a26fe60 100644 --- a/packages/webgl/src/texture.ts +++ b/packages/webgl/src/texture.ts @@ -13,19 +13,16 @@ import { import { isGL2Context } from "./checks"; import { error } from "./error"; -export const bindTextures = (textures?: ITexture[]) => { +const $bind = (op: "bind" | "unbind") => (textures?: ITexture[]) => { if (!textures) return; for (let i = textures.length, tex; --i >= 0; ) { - (tex = textures[i]) && tex.bind(i); + (tex = textures[i]) && tex[op](i); } }; -export const unbindTextures = (textures?: ITexture[]) => { - if (!textures) return; - for (let i = textures.length, tex; --i >= 0; ) { - (tex = textures[i]) && tex.unbind(i); - } -}; +export const bindTextures = $bind("bind"); + +export const unbindTextures = $bind("unbind"); export class Texture implements ITexture { gl: WebGLRenderingContext; @@ -49,19 +46,15 @@ export class Texture implements ITexture { configure(opts: Partial = {}, unbind = true) { const gl = this.gl; - const isGL2 = isGL2Context(gl); const target = opts.target || this.target || TextureTarget.TEXTURE_2D; const format = opts.format || this.format || TextureFormat.RGBA; const decl = TEX_FORMATS[format]; - const baseFormat = decl.format; const type = opts.type || this.type || decl.types[0]; !this.target && (this.target = target); this.format = format; this.type = type; - let t1: GLenum, t2: GLenum, t3: GLenum; - gl.bindTexture(this.target, this.tex); opts.flip !== undefined && @@ -73,6 +66,29 @@ export class Texture implements ITexture { opts.premultiply ? 1 : 0 ); + this.configureImage(target, opts); + + opts.mipmap && gl.generateMipmap(target); + + this.configureFilter(target, opts); + this.configureWrap(target, opts); + this.configureLOD(target, opts); + this.configureLevels(target, opts); + + unbind && gl.bindTexture(this.target, null); + + return true; + } + + protected configureImage( + target: TextureTarget, + opts: Partial + ) { + const gl = this.gl; + const decl = TEX_FORMATS[this.format]; + const baseFormat = decl.format; + const type = this.type; + const format = this.format; if (opts.image !== undefined) { const level = opts.level || 0; const pos = opts.pos || [0, 0, 0]; @@ -170,10 +186,15 @@ export class Texture implements ITexture { } } } + } - opts.mipmap && gl.generateMipmap(target); - + protected configureFilter( + target: TextureTarget, + opts: Partial + ) { + const gl = this.gl; const flt = opts.filter || this.filter || TextureFilter.NEAREST; + let t1: GLenum, t2: GLenum; if (isArray(flt)) { t1 = flt[0]; t2 = flt[1] || t1; @@ -184,8 +205,12 @@ export class Texture implements ITexture { } gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, t1); gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, t2); + } + protected configureWrap(target: TextureTarget, opts: Partial) { + const gl = this.gl; const wrap = opts.wrap || this.wrap || TextureRepeat.CLAMP; + let t1: GLenum, t2: GLenum, t3: GLenum; if (isArray(wrap)) { t1 = wrap[0]; t2 = wrap[1] || t1; @@ -197,14 +222,17 @@ export class Texture implements ITexture { } gl.texParameteri(target, gl.TEXTURE_WRAP_S, t1); gl.texParameteri(target, gl.TEXTURE_WRAP_T, t2); - isGL2 && + isGL2Context(gl) && target === (gl).TEXTURE_3D && gl.texParameteri( target, (gl).TEXTURE_WRAP_R, t3 ); + } + protected configureLOD(target: TextureTarget, opts: Partial) { + const gl = this.gl; if (opts.lod) { const [t1, t2] = opts.lod; t1 && @@ -220,7 +248,13 @@ export class Texture implements ITexture { t2 ); } + } + protected configureLevels( + target: TextureTarget, + opts: Partial + ) { + const gl = this.gl; if (opts.minMaxLevel) { const [t1, t2] = opts.minMaxLevel; gl.texParameteri( @@ -234,10 +268,6 @@ export class Texture implements ITexture { t2 ); } - - unbind && gl.bindTexture(this.target, null); - - return true; } bind(id = 0) { From 088bf37ff3ca02324ca460cedf0c6eb5a5a7c336 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 11:15:01 +0100 Subject: [PATCH 079/106] refactor(rstream-graph): update prepareNodeInputs/Outputs() --- packages/rstream-graph/src/graph.ts | 87 ++++++++++++++++------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/packages/rstream-graph/src/graph.ts b/packages/rstream-graph/src/graph.ts index f0b8c6189e..98d392993b 100644 --- a/packages/rstream-graph/src/graph.ts +++ b/packages/rstream-graph/src/graph.ts @@ -1,4 +1,4 @@ -import type { IObjectOf, Tuple } from "@thi.ng/api"; +import type { IObjectOf, Path, Tuple } from "@thi.ng/api"; import type { IAtom } from "@thi.ng/atom"; import { isFunction, isPlainObject, isString } from "@thi.ng/checks"; import { illegalArgs } from "@thi.ng/errors"; @@ -114,24 +114,20 @@ const prepareNodeInputs = ( const res: NodeInputs = {}; if (!ins) return res; for (let id in ins) { - let s; const i = ins[id]; - if (i.path) { - s = fromViewUnsafe(state, { path: i.path }); - } else if (i.stream) { - s = isString(i.stream) ? resolve(i.stream) : i.stream(resolve); - } else if (i.const != null) { - s = fromIterableSync( - [isFunction(i.const) ? i.const(resolve) : i.const], - { closeIn: CloseMode.NEVER } - ); - } else { - illegalArgs(`invalid node input: ${id}`); - } - if (i.xform) { - s = s.subscribe(i.xform, id); - } - res[id] = s; + const src = i.path + ? fromViewUnsafe(state, { path: i.path }) + : i.stream + ? isString(i.stream) + ? resolve(i.stream) + : i.stream(resolve) + : i.const !== undefined + ? fromIterableSync( + [isFunction(i.const) ? i.const(resolve) : i.const], + { closeIn: CloseMode.NEVER } + ) + : illegalArgs(`invalid node input: ${id}`); + res[id] = i.xform ? src.subscribe(i.xform, id) : src; } return res; }; @@ -145,31 +141,44 @@ const prepareNodeOutputs = ( const res: NodeOutputs = {}; if (!outs) return res; for (let id in outs) { - const o = outs[id]; - if (isFunction(o)) { - res[id] = o(node, id); - } else if (id == "*") { - res[id] = ((path) => - node.subscribe( - { - next: (x) => state.resetIn(path, x), - }, - { id: `out-${nodeID}` } - ))(o); - } else { - res[id] = ((path, id) => - node.subscribe( - { - next: (x) => state.resetIn(path, x), - }, - map((x) => (x != null ? x[id] : x)), - { id: `out-${nodeID}-${id}` } - ))(o, id); - } + const out = outs[id]; + res[id] = isFunction(out) + ? out(node, id) + : id == "*" + ? nodeOutAll(node, state, nodeID, out) + : nodeOutID(node, state, nodeID, out, id); } return res; }; +const nodeOutAll = ( + node: ISubscribable, + state: IAtom, + nodeID: string, + path: Path +) => + node.subscribe( + { + next: (x) => state.resetIn(path, x), + }, + { id: `out-${nodeID}` } + ); + +const nodeOutID = ( + node: ISubscribable, + state: IAtom, + nodeID: string, + path: Path, + id: string +) => + node.subscribe( + { + next: (x) => state.resetIn(path, x), + }, + map((x) => (x != null ? x[id] : x)), + { id: `out-${nodeID}-${id}` } + ); + /** * Compiles given {@link NodeSpec} and adds it to graph. Returns compiled * {@link Node} object for the given spec. Throws error if the graph already From 45156b2411abf38d2bc4420bcedda06af6521d91 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 11:48:11 +0100 Subject: [PATCH 080/106] refactor(rdom): split $compile() - extract complexComponent(), basicComponent() --- packages/rdom/src/compile.ts | 106 +++++++++++++++++------------------ 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/packages/rdom/src/compile.ts b/packages/rdom/src/compile.ts index 2347ba4b02..d6b3874770 100644 --- a/packages/rdom/src/compile.ts +++ b/packages/rdom/src/compile.ts @@ -28,59 +28,16 @@ import { $wrapText } from "./wrap"; * * @param tree */ -export const $compile = (tree: any): IComponent => { - if (isArray(tree)) { - return isComplexComponent(tree) - ? { - async mount(parent: Element, index: NumOrElement = -1) { - this.subs = []; - walk((x, path) => { - isSubscribable(x) && - this.subs!.push( - x.subscribe(new $SubA(this, path)) - ); - }, tree[1]); - this.children = []; - this.el = $el(tree[0], tree[1], null, parent, index); - for (let i = 2; i < tree.length; i++) { - const child = $compile(tree[i]); - child.mount(this.el, i - 2); - this.children.push(child); - } - return this.el; - }, - async unmount() { - SCHEDULER.cancel(this); - if (this.children) { - for (let c of this.children) { - await c.unmount(); - } - } - this.subs && this.subs.forEach((s) => s.unsubscribe()); - $remove(this.el!); - this.children = undefined; - this.subs = undefined; - this.el = undefined; - }, - update() {}, - } - : { - async mount(parent: Element, index: NumOrElement = -1) { - return (this.el = await $tree(tree, parent, index)); - }, - async unmount() { - $remove(this.el!); - this.el = undefined; - }, - update() {}, - }; - } else if (isComponent(tree)) { - return tree; - } else if (isSubscribable(tree)) { - return $sub(tree, "span"); - } - return $wrapText("span", null, tree); -}; +export const $compile = (tree: any): IComponent => + isArray(tree) + ? isComplexComponent(tree) + ? complexComponent(tree) + : basicComponent(tree) + : isComponent(tree) + ? tree + : isSubscribable(tree) + ? $sub(tree, "span") + : $wrapText("span", null, tree); const walk = ( f: Fn2, @@ -107,3 +64,46 @@ const isComplexComponent = (x: any) => { } return isSubscribable(x) || isComponent(x); }; + +const complexComponent = (tree: any[]): CompiledComponent => ({ + async mount(parent: Element, index: NumOrElement = -1) { + this.subs = []; + walk((x, path) => { + isSubscribable(x) && + this.subs!.push(x.subscribe(new $SubA(this, path))); + }, tree[1]); + this.children = []; + this.el = $el(tree[0], tree[1], null, parent, index); + for (let i = 2; i < tree.length; i++) { + const child = $compile(tree[i]); + child.mount(this.el, i - 2); + this.children.push(child); + } + return this.el; + }, + async unmount() { + SCHEDULER.cancel(this); + if (this.children) { + for (let c of this.children) { + await c.unmount(); + } + } + this.subs && this.subs.forEach((s) => s.unsubscribe()); + $remove(this.el!); + this.children = undefined; + this.subs = undefined; + this.el = undefined; + }, + update() {}, +}); + +const basicComponent = (tree: any): CompiledComponent => ({ + async mount(parent: Element, index: NumOrElement = -1) { + return (this.el = await $tree(tree, parent, index)); + }, + async unmount() { + $remove(this.el!); + this.el = undefined; + }, + update() {}, +}); From 83b8cbde4f9fcf0b42fbcfb54f1eacb1c8444b43 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 13:51:11 +0100 Subject: [PATCH 081/106] refactor(geom-accel): dedupe into() impls --- packages/geom-accel/src/aspatial-grid.ts | 7 ++----- packages/geom-accel/src/kd-tree-map.ts | 8 ++------ packages/geom-accel/src/nd-quadtree-map.ts | 8 ++------ packages/geom-accel/src/utils.ts | 23 +++++++++++++++++++++- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/packages/geom-accel/src/aspatial-grid.ts b/packages/geom-accel/src/aspatial-grid.ts index e803f3fad7..9fa7ed6695 100644 --- a/packages/geom-accel/src/aspatial-grid.ts +++ b/packages/geom-accel/src/aspatial-grid.ts @@ -11,6 +11,7 @@ import { subN, VecOpRoVV, } from "@thi.ng/vectors"; +import { into } from "./utils"; /** * Common base class for {@link SpatialGrid2} and {@link SpatialGrid3}. @@ -95,11 +96,7 @@ export abstract class ASpatialGrid } into(pairs: Iterable>, eps = EPS) { - let ok = true; - for (let [k, v] of pairs) { - ok = this.set(k, v, eps) && ok; - } - return ok; + return into(this, pairs, eps); } remove(k: K) { diff --git a/packages/geom-accel/src/kd-tree-map.ts b/packages/geom-accel/src/kd-tree-map.ts index 0f1f6588ae..65a9138b74 100644 --- a/packages/geom-accel/src/kd-tree-map.ts +++ b/packages/geom-accel/src/kd-tree-map.ts @@ -5,7 +5,7 @@ import { Heap } from "@thi.ng/heaps"; import { EPS } from "@thi.ng/math"; import { map } from "@thi.ng/transducers"; import { distSq, ReadonlyVec, Vec } from "@thi.ng/vectors"; -import { addResults, CMP } from "./utils"; +import { addResults, CMP, into } from "./utils"; type MaybeKdNode = KdNode | undefined; @@ -139,11 +139,7 @@ export class KdTreeMap } into(pairs: Iterable>, eps = EPS) { - let ok = true; - for (let [k, v] of pairs) { - ok = this.set(k, v, eps) && ok; - } - return ok; + return into(this, pairs, eps); } remove(key: K) { diff --git a/packages/geom-accel/src/nd-quadtree-map.ts b/packages/geom-accel/src/nd-quadtree-map.ts index 1d183b492b..250b6fa146 100644 --- a/packages/geom-accel/src/nd-quadtree-map.ts +++ b/packages/geom-accel/src/nd-quadtree-map.ts @@ -15,7 +15,7 @@ import { submN, vop, } from "@thi.ng/vectors"; -import { addResults, CMP } from "./utils"; +import { addResults, CMP, into } from "./utils"; export class NdQtNode { pos: ReadonlyVec; @@ -273,11 +273,7 @@ export class NdQuadtreeMap } into(pairs: Iterable>, eps = EPS) { - let ok = true; - for (let [k, v] of pairs) { - ok = this.set(k, v, eps) && ok; - } - return ok; + return into(this, pairs, eps); } remove(p: K) { diff --git a/packages/geom-accel/src/utils.ts b/packages/geom-accel/src/utils.ts index 4916c22d9b..241fc36ecf 100644 --- a/packages/geom-accel/src/utils.ts +++ b/packages/geom-accel/src/utils.ts @@ -1,4 +1,4 @@ -import type { Fn, Nullable } from "@thi.ng/api"; +import type { Fn, Fn3, Nullable, Pair } from "@thi.ng/api"; /** @internal */ export const CMP = (a: [number, any?], b: [number, any?]) => b[0] - a[0]; @@ -15,3 +15,24 @@ export const addResults = ( } return acc; }; + +/** + * Shared `into()` impl for spatial map types. + * + * @param map + * @param pairs + * @param eps + * + * @internal + */ +export const into = ( + map: { set: Fn3 }, + pairs: Iterable>, + eps: number +) => { + let ok = true; + for (let p of pairs) { + ok = map.set(p[0], p[1], eps) && ok; + } + return ok; +}; From ff2b31869d63b309ada66b2935b4564051a24b5f Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 14:21:49 +0100 Subject: [PATCH 082/106] refactor(imgui): dedupe dial/ring value labels - extract dialValueLabel() helper --- packages/imgui/src/components/dial.ts | 18 ++++++++++-------- packages/imgui/src/components/ring.ts | 18 ++++++++++-------- packages/imgui/src/components/textlabel.ts | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/packages/imgui/src/components/dial.ts b/packages/imgui/src/components/dial.ts index 335bbbdd13..38b6a4357b 100644 --- a/packages/imgui/src/components/dial.ts +++ b/packages/imgui/src/components/dial.ts @@ -6,8 +6,7 @@ import { cartesian2, hash } from "@thi.ng/vectors"; import { dialVal } from "../behaviors/dial"; import { handleSlider1Keys, isHoverSlider } from "../behaviors/slider"; import { IMGUI } from "../gui"; -import { valHash } from "../hash"; -import { textLabelRaw } from "./textlabel"; +import { dialValueLabel } from "./textlabel"; import { tooltipRaw } from "./tooltip"; export const dial = ( @@ -131,12 +130,15 @@ export const dialRaw = ( {} ) ); - const valLabel = gui.resource(id, valHash(key, v, gui.disabled), () => - textLabelRaw( - [x + lx, y + ly], - gui.textColor(false), - (label ? label + " " : "") + (fmt ? fmt(v!) : v) - ) + const valLabel = dialValueLabel( + gui, + id, + key, + v, + x + lx, + y + ly, + label, + fmt ); bgShape.attribs.fill = gui.bgColor(hover || focused); bgShape.attribs.stroke = gui.focusColor(id); diff --git a/packages/imgui/src/components/ring.ts b/packages/imgui/src/components/ring.ts index 92585f5c11..2f6785690d 100644 --- a/packages/imgui/src/components/ring.ts +++ b/packages/imgui/src/components/ring.ts @@ -8,8 +8,7 @@ import { cartesian2, hash, Vec } from "@thi.ng/vectors"; import { dialVal } from "../behaviors/dial"; import { handleSlider1Keys } from "../behaviors/slider"; import { IMGUI } from "../gui"; -import { valHash } from "../hash"; -import { textLabelRaw } from "./textlabel"; +import { dialValueLabel } from "./textlabel"; import { tooltipRaw } from "./tooltip"; const ringHeight: FnN2 = (w, thetaGap) => @@ -188,12 +187,15 @@ export const ringRaw = ( {} ) ); - const valLabel = gui.resource(id, valHash(key, v, gui.disabled), () => - textLabelRaw( - [x + lx, y + ly], - gui.textColor(false), - (label ? label + " " : "") + (fmt ? fmt(v!) : v) - ) + const valLabel = dialValueLabel( + gui, + id, + key, + v, + x + lx, + y + ly, + label, + fmt ); bgShape.attribs.fill = gui.bgColor(hover || focused); bgShape.attribs.stroke = gui.focusColor(id); diff --git a/packages/imgui/src/components/textlabel.ts b/packages/imgui/src/components/textlabel.ts index f956212a6b..0e066ce7b7 100644 --- a/packages/imgui/src/components/textlabel.ts +++ b/packages/imgui/src/components/textlabel.ts @@ -1,8 +1,10 @@ +import { Fn } from "@thi.ng/api"; import { isPlainObject } from "@thi.ng/checks"; import { IGridLayout, isLayout, LayoutBox } from "@thi.ng/layout"; import type { ReadonlyVec } from "@thi.ng/vectors"; import type { Color, GUITheme } from "../api"; import { IMGUI } from "../gui"; +import { valHash } from "../hash"; export const textLabel = ( gui: IMGUI, @@ -42,3 +44,21 @@ export const textTransformV = ( w: number, h: number ) => [0, -1, 1, 0, x + w / 2 + theme.baseLine, y + h - theme.pad]; + +export const dialValueLabel = ( + gui: IMGUI, + id: string, + key: number, + v: number, + x: number, + y: number, + label: string | undefined, + fmt: Fn | undefined +) => + gui.resource(id, valHash(key, v, gui.disabled), () => + textLabelRaw( + [x, y], + gui.textColor(false), + (label ? label + " " : "") + (fmt ? fmt(v!) : v) + ) + ); From 27889d38a08c108dcba0e8373db40f3f760b6362 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 14:38:02 +0100 Subject: [PATCH 083/106] refactor(imgui): update textField() key/cursor handling --- packages/imgui/src/components/textfield.ts | 84 +++++----------------- 1 file changed, 16 insertions(+), 68 deletions(-) diff --git a/packages/imgui/src/components/textfield.ts b/packages/imgui/src/components/textfield.ts index 293d40072c..646ae6cafc 100644 --- a/packages/imgui/src/components/textfield.ts +++ b/packages/imgui/src/components/textfield.ts @@ -9,11 +9,6 @@ import { IMGUI } from "../gui"; import { textLabelRaw } from "./textlabel"; import { tooltipRaw } from "./tooltip"; -interface TextfieldState { - cursor: number; - offset: number; -} - export const textField = ( gui: IMGUI, layout: IGridLayout | LayoutBox, @@ -104,6 +99,16 @@ export const textFieldRaw = ( [xx, y + h - 4], ]); } + + const move = (next: number, delta: number) => { + state.cursor = next; + if (drawCursor + delta < 0) { + state.offset = Math.max(offset + delta, 0); + } else if (drawCursor + delta > maxLen) { + state.offset = Math.min(offset + delta, maxOffset); + } + }; + const k = gui.key; switch (k) { case "": @@ -118,15 +123,7 @@ export const textFieldRaw = ( const next = gui.isAltDown() ? prevNonAlpha(txt, cursor - 1) : cursor - 1; - move( - state, - next, - next - cursor, - drawCursor, - offset, - maxLen, - maxOffset - ); + move(next, next - cursor); return txt.substr(0, next) + txt.substr(cursor); } break; @@ -143,15 +140,7 @@ export const textFieldRaw = ( const next = gui.isAltDown() ? prevNonAlpha(txt, cursor - 1) : cursor - 1; - move( - state, - next, - next - cursor, - drawCursor, - offset, - maxLen, - maxOffset - ); + move(next, next - cursor); } break; case Key.RIGHT: @@ -159,42 +148,18 @@ export const textFieldRaw = ( const next = gui.isAltDown() ? nextNonAlpha(txt, cursor + 1) : cursor + 1; - move( - state, - next, - next - cursor, - drawCursor, - offset, - maxLen, - maxOffset - ); + move(next, next - cursor); } break; case Key.HOME: - move(state, 0, -cursor, drawCursor, offset, maxLen, maxOffset); + move(0, -cursor); break; case Key.END: - move( - state, - txtLen, - txtLen - cursor, - drawCursor, - offset, - maxLen, - maxOffset - ); + move(txtLen, txtLen - cursor); break; default: { if (k.length === 1 && filter(k)) { - move( - state, - cursor + 1, - 1, - drawCursor, - offset, - maxLen, - maxOffset - ); + move(cursor + 1, 1); return txt.substr(0, cursor) + k + txt.substr(cursor); } } @@ -217,20 +182,3 @@ const prevNonAlpha = (src: string, i: number) => { for (; i > 0 && !WS.test(src[i]); i--) {} return i; }; - -const move = ( - state: TextfieldState, - next: number, - delta: number, - drawCursor: number, - offset: number, - maxLen: number, - maxOffset: number -) => { - state.cursor = next; - if (drawCursor + delta < 0) { - state.offset = Math.max(offset + delta, 0); - } else if (drawCursor + delta > maxLen) { - state.offset = Math.min(offset + delta, maxOffset); - } -}; From 467159c22e26bf3c0a1655dfb3f9570962f599dc Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 15:16:49 +0100 Subject: [PATCH 084/106] refactor(imgui): dedupe button label handling/creation --- packages/imgui/src/components/button.ts | 63 ++++++++++++------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/packages/imgui/src/components/button.ts b/packages/imgui/src/components/button.ts index 21e5ed20b3..fcaa242f36 100644 --- a/packages/imgui/src/components/button.ts +++ b/packages/imgui/src/components/button.ts @@ -1,16 +1,37 @@ +import { Fn5 } from "@thi.ng/api"; import { rect } from "@thi.ng/geom"; import type { IShape } from "@thi.ng/geom-api"; import { IGridLayout, isLayout, LayoutBox } from "@thi.ng/layout"; import { hash, ZERO2 } from "@thi.ng/vectors"; -import type { Color, Hash } from "../api"; +import type { GUITheme, Hash } from "../api"; import { handleButtonKeys, isHoverButton } from "../behaviors/button"; import { IMGUI } from "../gui"; import { labelHash } from "../hash"; import { textLabelRaw, textTransformH, textTransformV } from "./textlabel"; import { tooltipRaw } from "./tooltip"; -const mkLabel = (transform: number[], fill: Color, label: string) => - textLabelRaw(ZERO2, { transform, fill }, label); +const mkLabel = ( + gui: IMGUI, + tx: Fn5, + id: string, + key: number, + x: number, + y: number, + w: number, + h: number, + hover: boolean, + label: string +) => + gui.resource(id, labelHash(key, label, gui.disabled), () => + textLabelRaw( + ZERO2, + { + transform: tx(gui.theme, x, y, w, h), + fill: gui.textColor(hover), + }, + label + ) + ); export const buttonH = ( gui: IMGUI, @@ -20,7 +41,6 @@ export const buttonH = ( labelHover = label, info?: string ) => { - const theme = gui.theme; const { x, y, w, h } = isLayout(layout) ? layout.next() : layout; const key = hash([x, y, w, h]); return buttonRaw( @@ -29,22 +49,11 @@ export const buttonH = ( gui.resource(id, key, () => rect([x, y], [w, h])), key, label - ? gui.resource(id, labelHash(key, label, gui.disabled), () => - mkLabel( - textTransformH(theme, x, y, w, h), - gui.textColor(false), - label - ) - ) + ? mkLabel(gui, textTransformH, id, key, x, y, w, h, false, label) : undefined, labelHover - ? gui.resource(id, labelHash(key, labelHover, gui.disabled), () => - mkLabel( - textTransformH(theme, x, y, w, h), - gui.textColor(true), - labelHover - ) - ) + ? // prettier-ignore + mkLabel(gui, textTransformH, id, key, x, y, w, h, true, labelHover) : undefined, info ); @@ -59,7 +68,6 @@ export const buttonV = ( labelHover = label, info?: string ) => { - const theme = gui.theme; const { x, y, w, h } = isLayout(layout) ? layout.next([1, rows]) : layout; const key = hash([x, y, w, h]); return buttonRaw( @@ -68,22 +76,11 @@ export const buttonV = ( gui.resource(id, key, () => rect([x, y], [w, h])), key, label - ? gui.resource(id, labelHash(key, label, gui.disabled), () => - mkLabel( - textTransformV(theme, x, y, w, h), - gui.textColor(false), - label - ) - ) + ? mkLabel(gui, textTransformV, id, key, x, y, w, h, false, label) : undefined, labelHover - ? gui.resource(id, labelHash(key, labelHover, gui.disabled), () => - mkLabel( - textTransformV(theme, x, y, w, h), - gui.textColor(true), - labelHover - ) - ) + ? // prettier-ignore + mkLabel(gui, textTransformV, id, key, x, y, w, h, true, labelHover) : undefined, info ); From 69332d9a45cd3d49bce3406064c8ad4d3f498313 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 15:18:50 +0100 Subject: [PATCH 085/106] refactor(imgui): dedupe dropdown caret --- packages/imgui/src/components/dropdown.ts | 40 +++++++++-------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/packages/imgui/src/components/dropdown.ts b/packages/imgui/src/components/dropdown.ts index 0c3e7bcbc4..631b5c0fd8 100644 --- a/packages/imgui/src/components/dropdown.ts +++ b/packages/imgui/src/components/dropdown.ts @@ -39,18 +39,7 @@ export const dropdown = ( const bt = buttonH(gui, box, `${id}-title`, title); draw && gui.add( - gui.resource(id, key + 1, () => - polygon( - [ - [tx - 4, ty + 2], - [tx + 4, ty + 2], - [tx, ty - 2], - ], - { - fill: gui.textColor(false), - } - ) - ) + gui.resource(id, key + 1, () => triangle(gui, tx, ty, true)) ); if (bt) { gui.setState(id, false); @@ -84,18 +73,7 @@ export const dropdown = ( } draw && gui.add( - gui.resource(id, key + 2, () => - polygon( - [ - [tx - 4, ty - 2], - [tx + 4, ty - 2], - [tx, ty + 2], - ], - { - fill: gui.textColor(false), - } - ) - ) + gui.resource(id, key + 2, () => triangle(gui, tx, ty, false)) ); } return res; @@ -105,3 +83,17 @@ const update = (gui: IMGUI, id: string, next: number) => { gui.focusID = `${id}-${next}`; return next; }; + +const triangle = (gui: IMGUI, x: number, y: number, open: boolean) => { + const s = open ? 2 : -2; + return polygon( + [ + [x - 4, y + s], + [x + 4, y + s], + [x, y - s], + ], + { + fill: gui.textColor(false), + } + ); +}; From aec84c654f46c78c403ffeecee2764b03b8468e7 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 15:19:56 +0100 Subject: [PATCH 086/106] refactor(imgui): minor updates IMGUI class - extract gc() method - update endTheme()/endDisabled() --- packages/imgui/src/gui.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/imgui/src/gui.ts b/packages/imgui/src/gui.ts index 7e039232d6..3b9bd7ee48 100644 --- a/packages/imgui/src/gui.ts +++ b/packages/imgui/src/gui.ts @@ -145,8 +145,7 @@ export class IMGUI implements IClear, IToHiccup { * Removes current theme from stack (unless only one theme left). */ endTheme() { - const stack = this.themeStack; - stack.length > 1 && stack.pop(); + popIfNotLast(this.themeStack); } /** @@ -178,8 +177,7 @@ export class IMGUI implements IClear, IToHiccup { * Removes current disabled flag from stack (unless only one theme left). */ endDisabled() { - const stack = this.disabledStack; - stack.length > 1 && stack.pop(); + popIfNotLast(this.disabledStack); } /** @@ -313,7 +311,13 @@ export class IMGUI implements IClear, IToHiccup { } this.key === Key.TAB && (this.focusID = ""); this.key = ""; - // garbage collect unused component state / resources + this.gc(); + } + + /** + * Garbage collect unused component state / resources. + */ + gc() { const prev = this.prevIDs; const curr = this.currIDs; for (let id of prev) { @@ -461,3 +465,5 @@ export class IMGUI implements IClear, IToHiccup { ]; } } + +const popIfNotLast = (stack: any[]) => stack.length > 1 && stack.pop(); From cc13a8fadde90f8558de53dfca24d924cfcc4617 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 16:58:47 +0100 Subject: [PATCH 087/106] refactor(malloc): update realloc(), add 0-checks - extract private reallocBlock() method - add checks to blockDataAddress/blockSelfAddress() --- packages/malloc/src/pool.ts | 62 +++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/packages/malloc/src/pool.ts b/packages/malloc/src/pool.ts index 7cc4ad7081..b4705b2998 100644 --- a/packages/malloc/src/pool.ts +++ b/packages/malloc/src/pool.ts @@ -162,34 +162,7 @@ export class MemPool implements IMemPool { let blockEnd = 0; while (block) { if (block === oldAddr) { - const blockSize = this.blockSize(block); - blockEnd = oldAddr + blockSize; - const isTop = blockEnd >= this.top; - const paddedSize = align(bytes + SIZEOF_MEM_BLOCK, this.align); - // shrink & possibly split existing block - if (paddedSize <= blockSize) { - if (this.doSplit) { - const excess = blockSize - paddedSize; - if (excess >= this.minSplit) { - this.splitBlock(block, paddedSize, excess); - } else if (isTop) { - this.top = oldAddr + paddedSize; - } - } else if (isTop) { - this.top = oldAddr + paddedSize; - } - newAddr = oldAddr; - break; - } - // try to enlarge block if current top - if (isTop && oldAddr + paddedSize < this.end) { - this.top = oldAddr + this.setBlockSize(block, paddedSize); - newAddr = oldAddr; - break; - } - // fallback to free & malloc - this.free(oldAddr); - newAddr = blockSelfAddress(this.malloc(bytes)); + [newAddr, blockEnd] = this.reallocBlock(block, bytes); break; } block = this.blockNext(block); @@ -205,6 +178,35 @@ export class MemPool implements IMemPool { return blockDataAddress(newAddr); } + private reallocBlock(block: number, bytes: number) { + const blockSize = this.blockSize(block); + const blockEnd = block + blockSize; + const isTop = blockEnd >= this.top; + const paddedSize = align(bytes + SIZEOF_MEM_BLOCK, this.align); + // shrink & possibly split existing block + if (paddedSize <= blockSize) { + if (this.doSplit) { + const excess = blockSize - paddedSize; + if (excess >= this.minSplit) { + this.splitBlock(block, paddedSize, excess); + } else if (isTop) { + this.top = block + paddedSize; + } + } else if (isTop) { + this.top = block + paddedSize; + } + return [block, blockEnd]; + } + // try to enlarge block if current top + if (isTop && block + paddedSize < this.end) { + this.top = block + this.setBlockSize(block, paddedSize); + return [block, blockEnd]; + } + // fallback to free & malloc + this.free(block); + return [blockSelfAddress(this.malloc(bytes)), blockEnd]; + } + reallocArray(array: T, num: number): T | undefined { if (array.buffer !== this.buf) { return; @@ -475,7 +477,7 @@ export class MemPool implements IMemPool { * @param blockAddress - */ const blockDataAddress = (blockAddress: number) => - blockAddress + SIZEOF_MEM_BLOCK; + blockAddress > 0 ? blockAddress + SIZEOF_MEM_BLOCK : 0; /** * Returns block start address for given data address and alignment. @@ -483,4 +485,4 @@ const blockDataAddress = (blockAddress: number) => * @param dataAddress - */ const blockSelfAddress = (dataAddress: number) => - dataAddress - SIZEOF_MEM_BLOCK; + dataAddress > 0 ? dataAddress - SIZEOF_MEM_BLOCK : 0; From 520fa763cb927667d1a730d82e0af3f5276730cf Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 16:59:17 +0100 Subject: [PATCH 088/106] refactor(dcons): minor update equiv() --- packages/dcons/src/index.ts | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/dcons/src/index.ts b/packages/dcons/src/index.ts index 7d6513a3c1..1a85986473 100644 --- a/packages/dcons/src/index.ts +++ b/packages/dcons/src/index.ts @@ -104,22 +104,20 @@ export class DCons equiv(o: any) { if ( - (o instanceof DCons || isArrayLike(o)) && - this._length === o.length + !(o instanceof DCons || isArrayLike(o)) || + this._length !== o.length ) { - if (this._length === 0) { - return true; - } - let cell = this.head; - for (let x of o) { - if (!equiv(cell!.value, x)) { - return false; - } - cell = cell!.next; + return false; + } + if (!this._length || this === o) return true; + let cell = this.head; + for (let x of o) { + if (!equiv(cell!.value, x)) { + return false; } - return true; + cell = cell!.next; } - return false; + return true; } *[Symbol.iterator]() { From 6fd0c1f4484ea2ee55f03b8db732641e5b736e01 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 17:11:00 +0100 Subject: [PATCH 089/106] refactor(malloc): update malloc() - extract private mallocTop() --- packages/malloc/src/pool.ts | 50 ++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/packages/malloc/src/pool.ts b/packages/malloc/src/pool.ts index b4705b2998..b8a4c89e36 100644 --- a/packages/malloc/src/pool.ts +++ b/packages/malloc/src/pool.ts @@ -119,24 +119,13 @@ export class MemPool implements IMemPool { const blockSize = this.blockSize(block); const isTop = block + blockSize >= top; if (isTop || blockSize >= paddedSize) { - if (isTop && block + paddedSize > end) { - return 0; - } - if (prev) { - this.unlinkBlock(prev, block); - } else { - this._free = this.blockNext(block); - } - this.setBlockNext(block, this._used); - this._used = block; - if (isTop) { - this.top = block + this.setBlockSize(block, paddedSize); - } else if (this.doSplit) { - const excess = blockSize - paddedSize; - excess >= this.minSplit && - this.splitBlock(block, paddedSize, excess); - } - return blockDataAddress(block); + return this.mallocTop( + block, + prev, + blockSize, + paddedSize, + isTop + ); } prev = block; block = this.blockNext(block); @@ -152,6 +141,31 @@ export class MemPool implements IMemPool { return 0; } + private mallocTop( + block: number, + prev: number, + blockSize: number, + paddedSize: number, + isTop: boolean + ) { + if (isTop && block + paddedSize > this.end) return 0; + if (prev) { + this.unlinkBlock(prev, block); + } else { + this._free = this.blockNext(block); + } + this.setBlockNext(block, this._used); + this._used = block; + if (isTop) { + this.top = block + this.setBlockSize(block, paddedSize); + } else if (this.doSplit) { + const excess = blockSize - paddedSize; + excess >= this.minSplit && + this.splitBlock(block, paddedSize, excess); + } + return blockDataAddress(block); + } + realloc(ptr: number, bytes: number) { if (bytes <= 0) { return 0; From 7e94bb411ab6c651a6042b72155530e3cd454be0 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 17:28:13 +0100 Subject: [PATCH 090/106] refactor(imgui): extract layoutBox() helper, re-use --- packages/imgui/src/components/button.ts | 7 ++++--- packages/imgui/src/components/sliderh.ts | 5 +++-- packages/imgui/src/components/sliderv.ts | 5 +++-- packages/imgui/src/components/textfield.ts | 5 +++-- packages/imgui/src/components/textlabel.ts | 5 +++-- packages/imgui/src/components/toggle.ts | 5 +++-- packages/imgui/src/layout.ts | 6 ++++++ 7 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 packages/imgui/src/layout.ts diff --git a/packages/imgui/src/components/button.ts b/packages/imgui/src/components/button.ts index fcaa242f36..2867a97f91 100644 --- a/packages/imgui/src/components/button.ts +++ b/packages/imgui/src/components/button.ts @@ -1,12 +1,13 @@ import { Fn5 } from "@thi.ng/api"; import { rect } from "@thi.ng/geom"; import type { IShape } from "@thi.ng/geom-api"; -import { IGridLayout, isLayout, LayoutBox } from "@thi.ng/layout"; +import type { IGridLayout, LayoutBox } from "@thi.ng/layout"; import { hash, ZERO2 } from "@thi.ng/vectors"; import type { GUITheme, Hash } from "../api"; import { handleButtonKeys, isHoverButton } from "../behaviors/button"; import { IMGUI } from "../gui"; import { labelHash } from "../hash"; +import { layoutBox } from "../layout"; import { textLabelRaw, textTransformH, textTransformV } from "./textlabel"; import { tooltipRaw } from "./tooltip"; @@ -41,7 +42,7 @@ export const buttonH = ( labelHover = label, info?: string ) => { - const { x, y, w, h } = isLayout(layout) ? layout.next() : layout; + const { x, y, w, h } = layoutBox(layout); const key = hash([x, y, w, h]); return buttonRaw( gui, @@ -68,7 +69,7 @@ export const buttonV = ( labelHover = label, info?: string ) => { - const { x, y, w, h } = isLayout(layout) ? layout.next([1, rows]) : layout; + const { x, y, w, h } = layoutBox(layout, [1, rows]); const key = hash([x, y, w, h]); return buttonRaw( gui, diff --git a/packages/imgui/src/components/sliderh.ts b/packages/imgui/src/components/sliderh.ts index 53fddbbc49..7b66d6d859 100644 --- a/packages/imgui/src/components/sliderh.ts +++ b/packages/imgui/src/components/sliderh.ts @@ -1,6 +1,6 @@ import type { Fn } from "@thi.ng/api"; import { rect } from "@thi.ng/geom"; -import { IGridLayout, isLayout, LayoutBox } from "@thi.ng/layout"; +import type { IGridLayout, LayoutBox } from "@thi.ng/layout"; import { fit, norm } from "@thi.ng/math"; import { hash } from "@thi.ng/vectors"; import { @@ -10,6 +10,7 @@ import { } from "../behaviors/slider"; import { IMGUI } from "../gui"; import { valHash } from "../hash"; +import { layoutBox } from "../layout"; import { textLabelRaw } from "./textlabel"; import { tooltipRaw } from "./tooltip"; @@ -25,7 +26,7 @@ export const sliderH = ( fmt?: Fn, info?: string ) => { - const box = isLayout(layout) ? layout.next() : layout; + const box = layoutBox(layout); return sliderHRaw( gui, id, diff --git a/packages/imgui/src/components/sliderv.ts b/packages/imgui/src/components/sliderv.ts index cf2dde02aa..df3abe27e6 100644 --- a/packages/imgui/src/components/sliderv.ts +++ b/packages/imgui/src/components/sliderv.ts @@ -1,6 +1,6 @@ import type { Fn } from "@thi.ng/api"; import { rect } from "@thi.ng/geom"; -import { IGridLayout, isLayout, LayoutBox } from "@thi.ng/layout"; +import type { IGridLayout, LayoutBox } from "@thi.ng/layout"; import { fit, norm } from "@thi.ng/math"; import { hash, ZERO2 } from "@thi.ng/vectors"; import { @@ -10,6 +10,7 @@ import { } from "../behaviors/slider"; import { IMGUI } from "../gui"; import { valHash } from "../hash"; +import { layoutBox } from "../layout"; import { textLabelRaw, textTransformV } from "./textlabel"; import { tooltipRaw } from "./tooltip"; @@ -26,7 +27,7 @@ export const sliderV = ( fmt?: Fn, info?: string ) => { - const box = isLayout(layout) ? layout.next([1, rows]) : layout; + const box = layoutBox(layout, [1, rows]); return sliderVRaw( gui, id, diff --git a/packages/imgui/src/components/textfield.ts b/packages/imgui/src/components/textfield.ts index 646ae6cafc..03418a37a5 100644 --- a/packages/imgui/src/components/textfield.ts +++ b/packages/imgui/src/components/textfield.ts @@ -1,11 +1,12 @@ import type { Predicate } from "@thi.ng/api"; import { rect } from "@thi.ng/geom"; -import { IGridLayout, isLayout, LayoutBox } from "@thi.ng/layout"; +import type { IGridLayout, LayoutBox } from "@thi.ng/layout"; import { fitClamped } from "@thi.ng/math"; import { hash } from "@thi.ng/vectors"; import { Key } from "../api"; import { isHoverSlider } from "../behaviors/slider"; import { IMGUI } from "../gui"; +import { layoutBox } from "../layout"; import { textLabelRaw } from "./textlabel"; import { tooltipRaw } from "./tooltip"; @@ -17,7 +18,7 @@ export const textField = ( filter: Predicate = () => true, info?: string ) => { - const box = isLayout(layout) ? layout.next() : layout; + const box = layoutBox(layout); return textFieldRaw( gui, id, diff --git a/packages/imgui/src/components/textlabel.ts b/packages/imgui/src/components/textlabel.ts index 0e066ce7b7..c2f214f200 100644 --- a/packages/imgui/src/components/textlabel.ts +++ b/packages/imgui/src/components/textlabel.ts @@ -1,10 +1,11 @@ import { Fn } from "@thi.ng/api"; import { isPlainObject } from "@thi.ng/checks"; -import { IGridLayout, isLayout, LayoutBox } from "@thi.ng/layout"; +import type { IGridLayout, LayoutBox } from "@thi.ng/layout"; import type { ReadonlyVec } from "@thi.ng/vectors"; import type { Color, GUITheme } from "../api"; import { IMGUI } from "../gui"; import { valHash } from "../hash"; +import { layoutBox } from "../layout"; export const textLabel = ( gui: IMGUI, @@ -13,7 +14,7 @@ export const textLabel = ( pad = false ) => { const theme = gui.theme; - const { x, y, h } = isLayout(layout) ? layout.next() : layout; + const { x, y, h } = layoutBox(layout); gui.draw && gui.add([ "text", diff --git a/packages/imgui/src/components/toggle.ts b/packages/imgui/src/components/toggle.ts index d0111385f7..ada56a1236 100644 --- a/packages/imgui/src/components/toggle.ts +++ b/packages/imgui/src/components/toggle.ts @@ -1,8 +1,9 @@ import { rect } from "@thi.ng/geom"; -import { IGridLayout, isLayout, LayoutBox } from "@thi.ng/layout"; +import type { IGridLayout, LayoutBox } from "@thi.ng/layout"; import { hash } from "@thi.ng/vectors"; import { handleButtonKeys, isHoverButton } from "../behaviors/button"; import { IMGUI } from "../gui"; +import { layoutBox } from "../layout"; import { textLabelRaw } from "./textlabel"; import { tooltipRaw } from "./tooltip"; @@ -28,7 +29,7 @@ export const toggle = ( label?: string, info?: string ) => { - const { x, y, w, h } = isLayout(layout) ? layout.next() : layout; + const { x, y, w, h } = layoutBox(layout); return toggleRaw( gui, id, diff --git a/packages/imgui/src/layout.ts b/packages/imgui/src/layout.ts new file mode 100644 index 0000000000..54d302b033 --- /dev/null +++ b/packages/imgui/src/layout.ts @@ -0,0 +1,6 @@ +import { IGridLayout, isLayout, LayoutBox } from "@thi.ng/layout"; + +export const layoutBox = ( + layout: IGridLayout | LayoutBox, + spans?: [number, number] +) => (isLayout(layout) ? layout.next(spans) : layout); From a2a4c3b4802f5768f263f398476de969a1ea7f72 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 17:37:31 +0100 Subject: [PATCH 091/106] refactor(imgui): update hoverButton() behavior, re-use --- packages/imgui/src/behaviors/button.ts | 10 +++++++++- packages/imgui/src/components/button.ts | 12 +++--------- packages/imgui/src/components/toggle.ts | 12 +++--------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/packages/imgui/src/behaviors/button.ts b/packages/imgui/src/behaviors/button.ts index 4182095554..64b83b76a3 100644 --- a/packages/imgui/src/behaviors/button.ts +++ b/packages/imgui/src/behaviors/button.ts @@ -1,15 +1,23 @@ import { pointInside } from "@thi.ng/geom"; import type { IShape } from "@thi.ng/geom-api"; import { Key } from "../api"; +import { tooltipRaw } from "../components/tooltip"; import { IMGUI } from "../gui"; -export const isHoverButton = (gui: IMGUI, id: string, shape: IShape) => { +export const hoverButton = ( + gui: IMGUI, + id: string, + shape: IShape, + info?: string +) => { if (gui.disabled) return false; const aid = gui.activeID; const hover = (aid === "" || aid === id) && pointInside(shape, gui.mouse); if (hover) { gui.setCursor("pointer"); gui.hotID = id; + gui.isMouseDown() && (gui.activeID = id); + info && gui.draw && tooltipRaw(gui, info); } return hover; }; diff --git a/packages/imgui/src/components/button.ts b/packages/imgui/src/components/button.ts index 2867a97f91..882ec7438d 100644 --- a/packages/imgui/src/components/button.ts +++ b/packages/imgui/src/components/button.ts @@ -4,12 +4,11 @@ import type { IShape } from "@thi.ng/geom-api"; import type { IGridLayout, LayoutBox } from "@thi.ng/layout"; import { hash, ZERO2 } from "@thi.ng/vectors"; import type { GUITheme, Hash } from "../api"; -import { handleButtonKeys, isHoverButton } from "../behaviors/button"; +import { handleButtonKeys, hoverButton } from "../behaviors/button"; import { IMGUI } from "../gui"; import { labelHash } from "../hash"; import { layoutBox } from "../layout"; import { textLabelRaw, textTransformH, textTransformV } from "./textlabel"; -import { tooltipRaw } from "./tooltip"; const mkLabel = ( gui: IMGUI, @@ -97,14 +96,9 @@ export const buttonRaw = ( info?: string ) => { gui.registerID(id, hash); - const hover = isHoverButton(gui, id, shape); - const draw = gui.draw; - if (hover) { - gui.isMouseDown() && (gui.activeID = id); - info && draw && tooltipRaw(gui, info); - } + const hover = hoverButton(gui, id, shape, info); const focused = gui.requestFocus(id); - if (draw) { + if (gui.draw) { shape.attribs = { fill: hover ? gui.fgColor(true) : gui.bgColor(focused), stroke: gui.focusColor(id), diff --git a/packages/imgui/src/components/toggle.ts b/packages/imgui/src/components/toggle.ts index ada56a1236..7d73cf506f 100644 --- a/packages/imgui/src/components/toggle.ts +++ b/packages/imgui/src/components/toggle.ts @@ -1,11 +1,10 @@ import { rect } from "@thi.ng/geom"; import type { IGridLayout, LayoutBox } from "@thi.ng/layout"; import { hash } from "@thi.ng/vectors"; -import { handleButtonKeys, isHoverButton } from "../behaviors/button"; +import { handleButtonKeys, hoverButton } from "../behaviors/button"; import { IMGUI } from "../gui"; import { layoutBox } from "../layout"; import { textLabelRaw } from "./textlabel"; -import { tooltipRaw } from "./tooltip"; /** * If `square` is true, the clickable area will not fill the entire @@ -61,17 +60,12 @@ export const toggleRaw = ( gui.registerID(id, key); let res: boolean | undefined; const box = gui.resource(id, key, () => rect([x, y], [w, h])); - const hover = isHoverButton(gui, id, box); - const draw = gui.draw; - if (hover) { - gui.isMouseDown() && (gui.activeID = id); - info && draw && tooltipRaw(gui, info); - } + const hover = hoverButton(gui, id, box, info); const focused = gui.requestFocus(id); let changed = !gui.buttons && gui.hotID === id && gui.activeID === id; focused && (changed = handleButtonKeys(gui) || changed); changed && (res = val = !val); - if (draw) { + if (gui.draw) { box.attribs = { fill: val ? gui.fgColor(hover) : gui.bgColor(hover), stroke: gui.focusColor(id), From 3c676aa2fad05fc529f0aba7f18c9654e1a8f1ee Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 17:59:41 +0100 Subject: [PATCH 092/106] refactor(imgui): extract handleTextfieldKeys() --- packages/imgui/src/behaviors/text.ts | 96 ++++++++++++++++++++++ packages/imgui/src/components/textfield.ts | 92 +++------------------ packages/imgui/src/index.ts | 1 + 3 files changed, 108 insertions(+), 81 deletions(-) create mode 100644 packages/imgui/src/behaviors/text.ts diff --git a/packages/imgui/src/behaviors/text.ts b/packages/imgui/src/behaviors/text.ts new file mode 100644 index 0000000000..b38cda645e --- /dev/null +++ b/packages/imgui/src/behaviors/text.ts @@ -0,0 +1,96 @@ +import { Predicate } from "@thi.ng/api"; +import { Key } from "../api"; +import { IMGUI } from "../gui"; + +const WS = /\s/; + +const nextNonAlpha = (src: string, i: number) => { + const n = src.length; + while (i < n && WS.test(src[i])) i++; + for (; i < n && !WS.test(src[i]); i++) {} + return i; +}; + +const prevNonAlpha = (src: string, i: number) => { + while (i > 0 && WS.test(src[i])) i--; + for (; i > 0 && !WS.test(src[i]); i--) {} + return i; +}; + +const getNext = (gui: IMGUI, txt: string, cursor: number, dir: -1 | 1) => { + cursor += dir; + return gui.isAltDown() + ? (dir < 0 ? prevNonAlpha : nextNonAlpha)(txt, cursor) + : cursor; +}; + +export const handleTextfieldKeys = ( + gui: IMGUI, + state: { cursor: number; offset: number }, + filter: Predicate, + txt: string, + cursor: number, + drawCursor: number, + maxLen: number +) => { + const txtLen = txt.length; + const move = (next: number, delta: number) => { + state.cursor = next; + if (drawCursor + delta < 0) { + state.offset = Math.max(state.offset + delta, 0); + } else if (drawCursor + delta > maxLen) { + state.offset = Math.min( + state.offset + delta, + Math.max(0, txtLen - maxLen) + ); + } + }; + + const k = gui.key; + switch (k) { + case "": + break; + case Key.TAB: + gui.switchFocus(); + break; + case Key.ENTER: + return txt; + case Key.BACKSPACE: + if (cursor > 0) { + const next = getNext(gui, txt, cursor, -1); + move(next, next - cursor); + return txt.substr(0, next) + txt.substr(cursor); + } + break; + case Key.DELETE: + if (cursor < txtLen) { + const next = getNext(gui, txt, cursor, 1); + return txt.substr(0, cursor) + txt.substr(next + 1); + } + break; + case Key.LEFT: + if (cursor > 0) { + const next = getNext(gui, txt, cursor, -1); + move(next, next - cursor); + } + break; + case Key.RIGHT: + if (cursor < txtLen) { + const next = getNext(gui, txt, cursor, 1); + move(next, next - cursor); + } + break; + case Key.HOME: + move(0, -cursor); + break; + case Key.END: + move(txtLen, txtLen - cursor); + break; + default: { + if (k.length === 1 && filter(k)) { + move(cursor + 1, 1); + return txt.substr(0, cursor) + k + txt.substr(cursor); + } + } + } +}; diff --git a/packages/imgui/src/components/textfield.ts b/packages/imgui/src/components/textfield.ts index 03418a37a5..ac4d502360 100644 --- a/packages/imgui/src/components/textfield.ts +++ b/packages/imgui/src/components/textfield.ts @@ -3,8 +3,8 @@ import { rect } from "@thi.ng/geom"; import type { IGridLayout, LayoutBox } from "@thi.ng/layout"; import { fitClamped } from "@thi.ng/math"; import { hash } from "@thi.ng/vectors"; -import { Key } from "../api"; import { isHoverSlider } from "../behaviors/slider"; +import { handleTextfieldKeys } from "../behaviors/text"; import { IMGUI } from "../gui"; import { layoutBox } from "../layout"; import { textLabelRaw } from "./textlabel"; @@ -48,7 +48,6 @@ export const textFieldRaw = ( const pad = theme.pad; const maxLen = Math.max(1, ((w - pad * 2) / cw) | 0); const txtLen = txt.length; - const maxOffset = Math.max(0, txtLen - maxLen); const state = gui.state(id, () => ({ cursor: 0, offset: 0 })); const drawTxt = txt.substr(state.offset, maxLen); const key = hash([x, y, w, h]); @@ -101,85 +100,16 @@ export const textFieldRaw = ( ]); } - const move = (next: number, delta: number) => { - state.cursor = next; - if (drawCursor + delta < 0) { - state.offset = Math.max(offset + delta, 0); - } else if (drawCursor + delta > maxLen) { - state.offset = Math.min(offset + delta, maxOffset); - } - }; - - const k = gui.key; - switch (k) { - case "": - break; - case Key.TAB: - gui.switchFocus(); - break; - case Key.ENTER: - return txt; - case Key.BACKSPACE: - if (cursor > 0) { - const next = gui.isAltDown() - ? prevNonAlpha(txt, cursor - 1) - : cursor - 1; - move(next, next - cursor); - return txt.substr(0, next) + txt.substr(cursor); - } - break; - case Key.DELETE: - if (cursor < txtLen) { - const next = gui.isAltDown() - ? nextNonAlpha(txt, cursor + 1) - : cursor + 1; - return txt.substr(0, cursor) + txt.substr(next + 1); - } - break; - case Key.LEFT: - if (cursor > 0) { - const next = gui.isAltDown() - ? prevNonAlpha(txt, cursor - 1) - : cursor - 1; - move(next, next - cursor); - } - break; - case Key.RIGHT: - if (cursor < txtLen) { - const next = gui.isAltDown() - ? nextNonAlpha(txt, cursor + 1) - : cursor + 1; - move(next, next - cursor); - } - break; - case Key.HOME: - move(0, -cursor); - break; - case Key.END: - move(txtLen, txtLen - cursor); - break; - default: { - if (k.length === 1 && filter(k)) { - move(cursor + 1, 1); - return txt.substr(0, cursor) + k + txt.substr(cursor); - } - } - } + const res = handleTextfieldKeys( + gui, + state, + filter, + txt, + cursor, + drawCursor, + maxLen + ); + if (res !== undefined) return res; } gui.lastID = id; }; - -const WS = /\s/; - -const nextNonAlpha = (src: string, i: number) => { - const n = src.length; - while (i < n && WS.test(src[i])) i++; - for (; i < n && !WS.test(src[i]); i++) {} - return i; -}; - -const prevNonAlpha = (src: string, i: number) => { - while (i > 0 && WS.test(src[i])) i--; - for (; i > 0 && !WS.test(src[i]); i--) {} - return i; -}; diff --git a/packages/imgui/src/index.ts b/packages/imgui/src/index.ts index 53e0378b71..309ab008b5 100644 --- a/packages/imgui/src/index.ts +++ b/packages/imgui/src/index.ts @@ -20,3 +20,4 @@ export * from "./components/xypad"; export * from "./behaviors/button"; export * from "./behaviors/dial"; export * from "./behaviors/slider"; +export * from "./behaviors/text"; From 76916500841453eb3ed6ba00762c0afb20201e0d Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 19 Sep 2020 20:54:24 +0100 Subject: [PATCH 093/106] test(egf): add/update tests (char escapes) --- packages/egf/src/convert.ts | 28 +++++------ packages/egf/test/escape.ts | 91 ++++++++++++++++++++++++++++++++++ packages/egf/test/prefix.ts | 21 ++++---- packages/egf/test/ref.ts | 10 ++-- packages/egf/test/serialize.ts | 2 +- 5 files changed, 123 insertions(+), 29 deletions(-) create mode 100644 packages/egf/test/escape.ts diff --git a/packages/egf/src/convert.ts b/packages/egf/src/convert.ts index ed406a34e1..4645e31cff 100644 --- a/packages/egf/src/convert.ts +++ b/packages/egf/src/convert.ts @@ -63,19 +63,19 @@ export const toEGFNode = ( return res.join("\n"); }; -export const toEGFProp = (_: string, x: any) => - isString(x) - ? x.indexOf("\n") >= 0 - ? `>>>${x}<<<` - : x - : isNumber(x) - ? `#num ${x}` - : isDate(x) - ? `#date ${x.toISOString()}` - : isTypedArray(x) +export const toEGFProp = (_: string, val: any) => + isString(val) + ? val.indexOf("\n") >= 0 + ? `>>>${val}<<<` + : val + : isNumber(val) + ? `#num ${val}` + : isDate(val) + ? `#date ${val.toISOString()}` + : isTypedArray(val) ? `#base64 ${base64Encode( - new Uint8Array(x.buffer, x.byteOffset, x.byteLength) + new Uint8Array(val.buffer, val.byteOffset, val.byteLength) )}` - : isArray(x) || isPlainObject(x) - ? `#json ${JSON.stringify(x)}` - : x; + : isArray(val) || isPlainObject(val) + ? `#json ${JSON.stringify(val)}` + : String(val); diff --git a/packages/egf/test/escape.ts b/packages/egf/test/escape.ts new file mode 100644 index 0000000000..a1625ca648 --- /dev/null +++ b/packages/egf/test/escape.ts @@ -0,0 +1,91 @@ +import * as assert from "assert"; +import { ParseContext, parseString } from "../src"; + +const $ctx: Partial = { opts: { prefixes: true } }; + +describe("escape", () => { + it("node id", () => { + assert.deepStrictEqual(parseString(`\\u0046oo`).nodes, { + Foo: { $id: "Foo" }, + }); + }); + + it("node id (qfn)", () => { + assert.deepStrictEqual( + parseString(`@prefix foo: FOO\n\\u0066oo:\\u0062ar`, $ctx).nodes, + { + FOObar: { $id: "FOObar" }, + } + ); + }); + + it("prefix decl", () => { + assert.strictEqual( + parseString(`@prefix \\u0066oo: \\u0046OO`, $ctx).prefixes.foo, + "FOO" + ); + }); + + it("prop name (qfn)", () => { + assert.deepStrictEqual( + parseString(`@prefix a: foo\nx\n\t\\u0061:\\u0062ar baz`, $ctx) + .nodes, + { + x: { $id: "x", foobar: "baz" }, + } + ); + }); + + it("tag id", () => { + assert.deepStrictEqual(parseString(`a\n\tfoo #\\u006eum 42`).nodes, { + a: { $id: "a", foo: 42 }, + }); + }); + + it("string value", () => { + assert.deepStrictEqual(parseString(`a\n\tfoo \\u0062ar`).nodes, { + a: { $id: "a", foo: "bar" }, + }); + }); + + it("string multi-line value", () => { + assert.deepStrictEqual( + parseString(`a\n\tfoo >>>abc\\ndef\nghi<<<`).nodes, + { + a: { $id: "a", foo: "abc\ndef\nghi" }, + } + ); + }); + + it("#list multi-line value", () => { + assert.deepStrictEqual( + parseString(`a\n\tfoo #list >>>\nabc\\ndef\nghi<<<`).nodes, + { + a: { $id: "a", foo: ["abc\ndef", "ghi"] }, + } + ); + }); + + it("ref", () => { + assert.deepStrictEqual( + parseString(`a\n\tfoo -> \\u0062`, { opts: { resolve: true } }) + .nodes, + { + a: { $id: "a", foo: { $id: "b" } }, + b: { $id: "b" }, + } + ); + }); + + it("ref <>", () => { + assert.deepStrictEqual( + parseString(`a\n\tfoo -> <\\u0062:b>`, { + opts: { prefixes: true, resolve: true }, + }).nodes, + { + a: { $id: "a", foo: { $id: "b:b" } }, + "b:b": { $id: "b:b" }, + } + ); + }); +}); diff --git a/packages/egf/test/prefix.ts b/packages/egf/test/prefix.ts index c6be626b4d..b066d52d56 100644 --- a/packages/egf/test/prefix.ts +++ b/packages/egf/test/prefix.ts @@ -8,18 +8,21 @@ describe("@prefix", () => { assert.throws(() => parseString(`@prefix :`, $ctx), "1"); assert.throws(() => parseString(`@prefix : `, $ctx), "2"); assert.throws(() => parseString(`@prefix a&b: abc`, $ctx), "3"); - assert.equal(parseString(`@prefix : abc`, $ctx).prefixes[""], "abc"); + assert.strictEqual( + parseString(`@prefix : abc`, $ctx).prefixes[""], + "abc" + ); // prettier-ignore - assert.equal(parseString(`@prefix _: abc`, $ctx).prefixes["_"], "abc"); + assert.strictEqual(parseString(`@prefix _: abc`, $ctx).prefixes["_"], "abc"); // prettier-ignore - assert.equal(parseString(`@prefix $1a-b_C: abc`, $ctx).prefixes["$1a-b_C"], "abc"); + assert.strictEqual(parseString(`@prefix $1a-b_C: abc`, $ctx).prefixes["$1a-b_C"], "abc"); }); it("qfn", () => { const qfn = (id: string) => qualifiedID({ "": "self/", thi: "thi.ng/" }, id); - assert.equal(qfn(":a"), "self/a"); - assert.equal(qfn("thi:a"), "thi.ng/a"); + assert.strictEqual(qfn(":a"), "self/a"); + assert.strictEqual(qfn("thi:a"), "thi.ng/a"); assert.throws(() => qfn("foo:a")); }); @@ -36,9 +39,9 @@ thi:b `, { opts: { prefixes: true, resolve: true } } ); - assert.equal(prefixes[""], "self/"); - assert.equal(prefixes["thi"], "thi.ng/"); - assert.equal(nodes["self/a"].partof.$id, "thi.ng/b"); - assert.equal(nodes["thi.ng/b"].parentof.$id, "self/a"); + assert.strictEqual(prefixes[""], "self/"); + assert.strictEqual(prefixes["thi"], "thi.ng/"); + assert.strictEqual(nodes["self/a"].partof.$id, "thi.ng/b"); + assert.strictEqual(nodes["thi.ng/b"].parentof.$id, "self/a"); }); }); diff --git a/packages/egf/test/ref.ts b/packages/egf/test/ref.ts index 70dacc3843..66242b8263 100644 --- a/packages/egf/test/ref.ts +++ b/packages/egf/test/ref.ts @@ -19,9 +19,9 @@ thi:c `, { opts: { prefixes: true, resolve: true } } ).nodes; - assert.deepEqual(db["thi.ng/a"].partof, { $id: "thi.ng/b" }); - assert.equal(db["thi.ng/a"].knows.$id, "alt.thi.ng/c"); - assert.equal(db["alt.thi.ng/c"].diff.$id, "alt.thi.ng/a"); + assert.deepStrictEqual(db["thi.ng/a"].partof, { $id: "thi.ng/b" }); + assert.strictEqual(db["thi.ng/a"].knows.$id, "alt.thi.ng/c"); + assert.strictEqual(db["alt.thi.ng/c"].diff.$id, "alt.thi.ng/a"); }); it("resolve circular", () => { @@ -35,8 +35,8 @@ b `, { opts: { resolve: true } } ).nodes; - assert.equal(db.a.knows.$id, "b"); - assert.equal(db.b.knows.$id, "a"); + assert.strictEqual(db.a.knows.$id, "b"); + assert.strictEqual(db.b.knows.$id, "a"); }); it("ref array item (unresolved)", () => { diff --git a/packages/egf/test/serialize.ts b/packages/egf/test/serialize.ts index 4974eb5915..3ab6f11ef6 100644 --- a/packages/egf/test/serialize.ts +++ b/packages/egf/test/serialize.ts @@ -26,7 +26,7 @@ describe("serialize", () => { } ); writeFileSync("out.egf", res); - assert.equal( + assert.strictEqual( res, `@prefix thi: http://thi.ng/ @prefix schema: http://schema.org/ From 38634a68bb9dc40d1771d9cf95791dc658f4761f Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 20 Sep 2020 11:43:15 +0100 Subject: [PATCH 094/106] build: update pkg meta (various) --- packages/date/package.json | 5 ++++- packages/dsp-io-wav/package.json | 3 ++- packages/egf/package.json | 2 +- packages/geom-arc/package.json | 1 + packages/geom-fuzz/package.json | 2 +- packages/geom-splines/package.json | 1 + packages/geom-subdiv-curve/package.json | 1 + packages/geom-tessellate/package.json | 2 ++ packages/geom/package.json | 2 +- packages/hiccup-canvas/package.json | 1 + packages/hiccup-css/package.json | 13 ++++++------- packages/hiccup-html/package.json | 3 ++- packages/hiccup-markdown/package.json | 3 ++- packages/hiccup-svg/package.json | 10 +++++++--- packages/hiccup/package.json | 2 +- 15 files changed, 33 insertions(+), 18 deletions(-) diff --git a/packages/date/package.json b/packages/date/package.json index 13bda4b30f..a7c9a0f100 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -61,8 +61,11 @@ "interval", "iterator", "math", + "presets", + "smpte", "time", - "typescript" + "typescript", + "utc" ], "publishConfig": { "access": "public" diff --git a/packages/dsp-io-wav/package.json b/packages/dsp-io-wav/package.json index 240fae0e5b..fa2d3c90aa 100644 --- a/packages/dsp-io-wav/package.json +++ b/packages/dsp-io-wav/package.json @@ -64,7 +64,8 @@ "dsp", "export", "fileformat", - "typescript" + "typescript", + "wav" ], "publishConfig": { "access": "public" diff --git a/packages/egf/package.json b/packages/egf/package.json index 174706c4e3..0a50a35784 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -61,7 +61,7 @@ "keywords": [ "conversion", "datastructure", - "file format", + "fileformat", "graph", "graphviz", "json", diff --git a/packages/geom-arc/package.json b/packages/geom-arc/package.json index f20e33810c..48ccf2c36d 100644 --- a/packages/geom-arc/package.json +++ b/packages/geom-arc/package.json @@ -70,6 +70,7 @@ "geometry", "interpolation", "sample", + "shape", "svg", "typescript" ], diff --git a/packages/geom-fuzz/package.json b/packages/geom-fuzz/package.json index 8f381f5a74..92eb6111a5 100644 --- a/packages/geom-fuzz/package.json +++ b/packages/geom-fuzz/package.json @@ -77,7 +77,7 @@ "npr", "polygon", "random", - "shapes", + "shape", "svg", "typescript" ], diff --git a/packages/geom-splines/package.json b/packages/geom-splines/package.json index d34a1464c3..d71179a746 100644 --- a/packages/geom-splines/package.json +++ b/packages/geom-splines/package.json @@ -79,6 +79,7 @@ "proximity", "quadratic", "sample", + "shape", "spline", "split", "typescript" diff --git a/packages/geom-subdiv-curve/package.json b/packages/geom-subdiv-curve/package.json index d963fc2785..4a51dfb086 100644 --- a/packages/geom-subdiv-curve/package.json +++ b/packages/geom-subdiv-curve/package.json @@ -68,6 +68,7 @@ "iterative", "polyline", "recursive", + "spline", "subdivision", "typescript" ], diff --git a/packages/geom-tessellate/package.json b/packages/geom-tessellate/package.json index 631dd7682a..e40c9bdfe9 100644 --- a/packages/geom-tessellate/package.json +++ b/packages/geom-tessellate/package.json @@ -67,6 +67,8 @@ "convex", "geometry", "polygon", + "shape", + "subdivision", "tessellation", "typescript" ], diff --git a/packages/geom/package.json b/packages/geom/package.json index 50e50eabbd..692d189f31 100644 --- a/packages/geom/package.json +++ b/packages/geom/package.json @@ -94,7 +94,7 @@ "graphics", "polymorphic", "sample", - "shapes", + "shape", "svg", "typescript" ], diff --git a/packages/hiccup-canvas/package.json b/packages/hiccup-canvas/package.json index 180ebcf7ac..61a53d470c 100644 --- a/packages/hiccup-canvas/package.json +++ b/packages/hiccup-canvas/package.json @@ -67,6 +67,7 @@ "graphics", "hiccup", "scenegraph", + "svg", "tree", "typescript" ], diff --git a/packages/hiccup-css/package.json b/packages/hiccup-css/package.json index f57d5ff4cb..0b3ca7b49e 100644 --- a/packages/hiccup-css/package.json +++ b/packages/hiccup-css/package.json @@ -60,17 +60,16 @@ "lib" ], "keywords": [ - "clojure", + "css", + "codegen", "component", - "hiccup", - "html", + "dsl", + "fileformat", "iterator", + "hiccup", "json", "serialization", - "svg", - "template", - "typescript", - "xml" + "typescript" ], "publishConfig": { "access": "public" diff --git a/packages/hiccup-html/package.json b/packages/hiccup-html/package.json index 9ff29572c7..df93c9e458 100644 --- a/packages/hiccup-html/package.json +++ b/packages/hiccup-html/package.json @@ -56,7 +56,8 @@ "lib" ], "keywords": [ - "attributes", + "dsl", + "fileformat", "hiccup", "html", "typecheck", diff --git a/packages/hiccup-markdown/package.json b/packages/hiccup-markdown/package.json index 389c87d43b..15ffbc0d8a 100644 --- a/packages/hiccup-markdown/package.json +++ b/packages/hiccup-markdown/package.json @@ -68,7 +68,8 @@ "keywords": [ "ast", "conversion", - "DOM", + "dom", + "fileformat", "hiccup", "markdown", "parser", diff --git a/packages/hiccup-svg/package.json b/packages/hiccup-svg/package.json index 9a62999e5a..9cf56ffa3a 100644 --- a/packages/hiccup-svg/package.json +++ b/packages/hiccup-svg/package.json @@ -59,17 +59,21 @@ "lib" ], "keywords": [ - "component", + "color", + "codegen", "conversion", - "generator", + "fileformat", + "gradient", "hiccup", "hdom", "svg", "serialization", + "shape", "tree", "typescript", "ui", - "visualization" + "visualization", + "xml" ], "publishConfig": { "access": "public" diff --git a/packages/hiccup/package.json b/packages/hiccup/package.json index b942853648..1fd0d4753b 100644 --- a/packages/hiccup/package.json +++ b/packages/hiccup/package.json @@ -61,8 +61,8 @@ "lib" ], "keywords": [ - "clojure", "component", + "fileformat", "functional", "hiccup", "html", From 27c8617be90153abea3098ef4120e348fac4934b Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 20 Sep 2020 11:46:15 +0100 Subject: [PATCH 095/106] feat(date): update/fix DateTime - add date/string/json conversions - add/fix leap year handling - add dateTime() factory --- packages/date/src/datetime.ts | 61 ++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/packages/date/src/datetime.ts b/packages/date/src/datetime.ts index 8579d9900d..68c83bbf11 100644 --- a/packages/date/src/datetime.ts +++ b/packages/date/src/datetime.ts @@ -1,6 +1,14 @@ +import type { ICopy } from "@thi.ng/api"; import { DAYS_IN_MONTH, Precision } from "./api"; -export class DateTime { +export const dateTime = (epoch?: Date | number, prec?: Precision) => + new DateTime(epoch, prec); + +/** + * Epoch abstraction with adjustable coarseness/precision. All date fields in + * UTC only. + */ +export class DateTime implements ICopy { t: number; s: number; m: number; @@ -9,22 +17,35 @@ export class DateTime { M: number; y: number; - constructor(epoch: number, id: Precision = "t") { - const x = new Date(epoch); - const prec = "yMdhmst".indexOf(id); - this.y = prec >= 0 ? x.getUTCFullYear() : 1970; - this.M = prec >= 1 ? x.getUTCMonth() : 0; - this.d = prec >= 2 ? x.getUTCDate() : 1; - this.h = prec >= 3 ? x.getUTCHours() : 0; - this.m = prec >= 4 ? x.getUTCMinutes() : 0; - this.s = prec >= 5 ? x.getUTCSeconds() : 0; - this.t = prec >= 6 ? x.getUTCMilliseconds() : 0; + constructor(epoch: Date | number = Date.now(), prec: Precision = "t") { + const x = typeof epoch === "number" ? new Date(epoch) : epoch; + const id = "yMdhmst".indexOf(prec); + this.y = x.getUTCFullYear(); + this.M = id >= 1 ? x.getUTCMonth() : 0; + this.d = id >= 2 ? x.getUTCDate() : 1; + this.h = id >= 3 ? x.getUTCHours() : 0; + this.m = id >= 4 ? x.getUTCMinutes() : 0; + this.s = id >= 5 ? x.getUTCSeconds() : 0; + this.t = id >= 6 ? x.getUTCMilliseconds() : 0; + } + + copy() { + return new DateTime(this.getTime()); } getTime() { return Date.UTC(this.y, this.M, this.d, this.h, this.m, this.s, this.t); } + daysInMonth() { + const days = DAYS_IN_MONTH[this.M]; + return days + (this.M === 1 && this.isLeapYear() ? 1 : 0); + } + + isLeapYear() { + return this.y % 4 === 0; + } + incMillisecond() { if (++this.t > 999) { this.t = 0; @@ -58,7 +79,7 @@ export class DateTime { } incDay() { - if (++this.d > DAYS_IN_MONTH[this.M]) { + if (++this.d > this.daysInMonth()) { this.d = 1; this.incMonth(); } @@ -77,4 +98,20 @@ export class DateTime { // TODO epoch overflow handling, throw error? return ++this.y; } + + toDate() { + return new Date(this.getTime()); + } + + toJSON() { + return this.toISOString(); + } + + toString() { + return this.toDate().toString(); + } + + toISOString() { + return this.toDate().toISOString(); + } } From 0c6c2cc8d75c7f89be14acec098c865d5b518f20 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 20 Sep 2020 11:47:13 +0100 Subject: [PATCH 096/106] fix(date): update ceilMonth(), add docstrings --- packages/date/src/round.ts | 40 ++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/packages/date/src/round.ts b/packages/date/src/round.ts index 20f5e9b81a..0e176a37d2 100644 --- a/packages/date/src/round.ts +++ b/packages/date/src/round.ts @@ -1,32 +1,64 @@ import type { FnN } from "@thi.ng/api"; -import { DAY, DAYS_IN_MONTH } from "./api"; +import { DAY } from "./api"; +/** + * Rounds down `epoch` to beginning of its day. + * + * @param epoch + */ export const floorDay: FnN = (epoch) => { const d = new Date(epoch); return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()); }; +/** + * Rounds down `epoch` to beginning of its month. + * + * @param epoch + */ export const floorMonth: FnN = (epoch) => { const d = new Date(epoch); return Date.UTC(d.getUTCFullYear(), d.getUTCMonth()); }; +/** + * Rounds down `epoch` to beginning of its year. + * + * @param epoch + */ export const floorYear: FnN = (epoch) => { const d = new Date(epoch); return Date.UTC(d.getUTCFullYear(), 0); }; +/** + * Rounds up `epoch` to beginning of following day. + * + * @param epoch + */ export const ceilDay: FnN = (epoch) => { const d = new Date(epoch + DAY); return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()); }; +/** + * Rounds up `epoch` to beginning of following month. + * + * @param epoch + */ export const ceilMonth: FnN = (epoch) => { - let d = new Date(epoch); - d = new Date(epoch + DAYS_IN_MONTH[d.getUTCMonth()] * DAY); - return Date.UTC(d.getUTCFullYear(), d.getUTCMonth()); + const d = new Date(epoch); + let y = d.getUTCFullYear(); + let m = d.getUTCMonth() + 1; + m > 11 && y++; + return Date.UTC(y, m % 12); }; +/** + * Rounds up `epoch` to beginning of following year (no overflow checking!). + * + * @param epoch + */ export const ceilYear: FnN = (epoch) => { const d = new Date(epoch); return Date.UTC(d.getUTCFullYear() + 1, 0); From c8e84ad2f2d7cfaa94684fd3873d55714eab88e7 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 20 Sep 2020 11:54:45 +0100 Subject: [PATCH 097/106] feat(date): add/update formatters, add locale - add LOCALE, setLocale() - add EN_SHORT, EN_LONG locales - update MMM and E formatters to use locale - update defFormat() to accept format fns in addition to strings - update/rename preset formatters --- packages/date/src/api.ts | 34 +++++++-------- packages/date/src/format.ts | 86 +++++++++++++++++++++++++++++-------- packages/date/src/i18n.ts | 54 +++++++++++++++++++++++ packages/date/src/index.ts | 1 + 4 files changed, 139 insertions(+), 36 deletions(-) create mode 100644 packages/date/src/i18n.ts diff --git a/packages/date/src/api.ts b/packages/date/src/api.ts index 78100c5d4a..17ffbf5991 100644 --- a/packages/date/src/api.ts +++ b/packages/date/src/api.ts @@ -1,3 +1,5 @@ +import type { Fn } from "@thi.ng/api"; + export const SECOND = 1000; export const MINUTE = 60 * SECOND; export const HOUR = 60 * MINUTE; @@ -6,26 +8,18 @@ export const WEEK = 7 * DAY; export const MONTH = 30.4375 * DAY; export const YEAR = 365.25 * DAY; -export type Precision = "y" | "M" | "d" | "h" | "m" | "s" | "t"; - export const DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; -export const MONTH_NAMES = [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", -]; - -export const WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; +export interface Locale { + /** + * Names of months + */ + months: string[]; + /** + * Names of weekdays (starting w/ Sunday) + */ + days: string[]; +} export interface EpochIteratorConstructor { ([from, to]: number[]): EpochIterator; @@ -33,3 +27,7 @@ export interface EpochIteratorConstructor { } export type EpochIterator = IterableIterator; + +export type Precision = "y" | "M" | "d" | "h" | "m" | "s" | "t"; + +export type FormatFn = Fn; diff --git a/packages/date/src/format.ts b/packages/date/src/format.ts index d2b50bff44..b97b74667d 100644 --- a/packages/date/src/format.ts +++ b/packages/date/src/format.ts @@ -1,9 +1,10 @@ -import type { Fn } from "@thi.ng/api"; -import { MONTH_NAMES, WEEKDAYS } from "./api"; +import { DAY, FormatFn, HOUR, MINUTE, SECOND } from "./api"; +import { DateTime } from "./datetime"; +import { LOCALE } from "./i18n"; const Z2 = (x: number) => (x < 10 ? "0" + x : String(x)); -export const FORMATTERS: Record> = { +export const FORMATTERS: Record = { /** * Full year (4 digits) */ @@ -15,7 +16,7 @@ export const FORMATTERS: Record> = { /** * 3-letter month name (e.g. `Feb`) */ - MMM: (d) => MONTH_NAMES[d.getMonth()], + MMM: (d) => LOCALE.months[d.getMonth()], /** * Zero-padded 2-digit month */ @@ -35,7 +36,7 @@ export const FORMATTERS: Record> = { /** * 3-letter weekday name (e.g. `Mon`) */ - E: (d) => WEEKDAYS[d.getDay()], + E: (d) => LOCALE.days[d.getDay()], /** * Zero-padded 2-digit hour of day (0-23) */ @@ -89,8 +90,10 @@ export const FORMATTERS: Record> = { }; /** - * Returns a new date formatter for given format string. The returned function - * accepts timestamps or `Date` instances. + * Returns a new date formatter for given array of format strings (or + * functions). The returned function accepts timestamps (epoch), `Date` or + * `DateTime` instances and accepts an optional boolean arg to output UTC + * instead of local time (default). * * @remarks * See {@link FORMATTERS} for available date component format IDs. @@ -99,29 +102,76 @@ export const FORMATTERS: Record> = { * ```ts * const fmt = defFormat(["yyyy", "-", "MM", "-", "dd"]); * - * fmt(Date.UTC(2015, 4, 23)) + * fmt(new Date(2015, 3, 23)) * // 2015-04-23 * ``` * * @param fmt */ -export const defFormat = (fmt: string[]) => (x: Date | number) => { - const d = typeof x === "number" ? new Date(x) : x; +export const defFormat = (fmt: (string | FormatFn)[]) => ( + x: DateTime | Date | number, + utc = false +) => { + let d = + typeof x === "number" + ? new Date(x) + : x instanceof DateTime + ? x.toDate() + : x; + utc && (d = new Date(d.getTime() + d.getTimezoneOffset() * MINUTE)); return fmt - .map((f) => { - const fmt = FORMATTERS[f]; - return fmt ? fmt(d) : f; + .map((x) => { + let fmt: FormatFn; + return typeof x === "string" + ? (fmt = FORMATTERS[x]) + ? fmt(d) + : x + : typeof x === "function" + ? x(d) + : x; }) .join(""); }; +/** + * Format preset, e.g. `2020-09-19` + */ export const FMT_yyyyMMdd = defFormat(["yyyy", "-", "MM", "-", "dd"]); -export const FMT_MMddyyyy = defFormat(["MM", "/", "dd", "/", "yyyy"]); -export const FMT_MMMddyyyy = defFormat(["MMM", " ", "dd", " ", "yyyy"]); -export const FMT_ddMMyyyy = defFormat(["dd", "/", "MM", "/", "yyyy"]); -export const FMT_ddMMMyyyy = defFormat(["dd", " ", "MMM", " ", "yyyy"]); - +/** + * Format preset, e.g. `9/19/2020` + */ +export const FMT_Mdyyyy = defFormat(["M", "/", "d", "/", "yyyy"]); +/** + * Format preset, e.g. `Sep 19 2020`. Uses current `LOCALE`, see + * {@link setLocale}. + */ +export const FMT_MMMdyyyy = defFormat(["MMM", " ", "d", " ", "yyyy"]); +/** + * Format preset, e.g. `19/9/2020` + */ +export const FMT_dMyyyy = defFormat(["d", "/", "M", "/", "yyyy"]); +/** + * Format preset, e.g. `19 Sep 2020` + */ +export const FMT_dMMMyyyy = defFormat(["d", " ", "MMM", " ", "yyyy"]); +/** + * Format preset, e.g. `17:08` + */ export const FMT_HHmm = defFormat(["HH", ":", "mm"]); +/** + * Format preset, e.g. `5:08 PM` + */ export const FMT_hm = defFormat(["h", ":", "mm", " ", "A"]); +/** + * Format preset, e.g. `17:08:01` + */ export const FMT_HHmmss = defFormat(["HH", ":", "mm", ":", "ss"]); +/** + * Format preset, e.g. `5:08:01 PM` + */ export const FMT_hms = defFormat(["h", ":", "mm", ":", "ss", " ", "A"]); +/** + * Format preset, e.g. `20200919-170801` + */ +// prettier-ignore +export const FMT_yyyyMMdd_HHmmss = defFormat(["yyyy", "MM", "dd", "-", "HH", "mm", "ss"]); diff --git a/packages/date/src/i18n.ts b/packages/date/src/i18n.ts new file mode 100644 index 0000000000..a6b5a5450d --- /dev/null +++ b/packages/date/src/i18n.ts @@ -0,0 +1,54 @@ +import { Locale } from "./api"; + +export const EN_SHORT: Locale = { + months: [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ], + days: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], +}; + +export const EN_LONG: Locale = { + months: [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ], + days: [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + ], +}; + +export let LOCALE = EN_SHORT; + +/** + * Sets {@link LOCALE} for formatting, default: {@link EN_SHORT}. + * + * @param locale + */ +export const setLocale = (locale: Locale) => (LOCALE = locale); diff --git a/packages/date/src/index.ts b/packages/date/src/index.ts index 070cb24250..7c8fa480f2 100644 --- a/packages/date/src/index.ts +++ b/packages/date/src/index.ts @@ -1,5 +1,6 @@ export * from "./api"; export * from "./datetime"; export * from "./format"; +export * from "./i18n"; export * from "./iterators"; export * from "./round"; From 42753e1e53e1c4af02928e6a6158f4e3be4f2e3a Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 20 Sep 2020 11:55:26 +0100 Subject: [PATCH 098/106] feat(date): add defTimecode() formatter --- packages/date/src/format.ts | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/packages/date/src/format.ts b/packages/date/src/format.ts index b97b74667d..6971509841 100644 --- a/packages/date/src/format.ts +++ b/packages/date/src/format.ts @@ -175,3 +175,55 @@ export const FMT_hms = defFormat(["h", ":", "mm", ":", "ss", " ", "A"]); */ // prettier-ignore export const FMT_yyyyMMdd_HHmmss = defFormat(["yyyy", "MM", "dd", "-", "HH", "mm", "ss"]); + +/** + * Returns a time formatter for given FPS (frames / second, in [1..100] range), + * e.g. `HH:mm:ss:ff`. The returned function takes a single arg (time in + * milliseconds) and returns formatted string. + * + * @remarks + * The timecode considers days too, but only includes them in the result if the + * day part is non-zero. The 4 separators between each field can be customized + * via 2nd arg (default: all `:`). + * + * @example + * ```ts + * a = defTimecode(30); + * a(HOUR + 2*MINUTE + 3*SECOND + 4*1000/30) + * // "01:02:03:04" + * + * a(DAY); + * // "01:00:00:00:00" + * + * b = defTimecode(30, ["d ", "h ", "' ", '" ']); + * b(Day + HOUR + 2*MINUTE + 3*SECOND + 999) + * // "01d 01h 02' 03" 29" + * ``` + * + * @param fps + * @param sep + */ +export const defTimecode = (fps: number, sep: ArrayLike = "::::") => { + const frame = 1000 / fps; + return (t: number) => { + const d = (t / DAY) | 0; + t -= d * DAY; + const h = (t / HOUR) | 0; + t -= h * HOUR; + const m = (t / MINUTE) | 0; + t -= m * MINUTE; + const s = (t / SECOND) | 0; + t -= s * SECOND; + const parts = [ + Z2(h), + sep[1], + Z2(m), + sep[2], + Z2(s), + sep[3], + Z2((t / frame) | 0), + ]; + d > 0 && parts.unshift(`${Z2(d)}${sep[0]}`); + return parts.join(""); + }; +}; From f106a206a449a9a13635b2e2365ceabf60983e07 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 20 Sep 2020 11:55:46 +0100 Subject: [PATCH 099/106] test(date): add/update tests --- packages/date/test/format.ts | 19 ++++++++++++++++++- packages/date/test/iterators.ts | 13 +++++++------ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/date/test/format.ts b/packages/date/test/format.ts index a7edf55e25..c753876912 100644 --- a/packages/date/test/format.ts +++ b/packages/date/test/format.ts @@ -1,5 +1,5 @@ import * as assert from "assert"; -import { defFormat } from "../src"; +import { DAY, defFormat, defTimecode, HOUR, MINUTE, SECOND } from "../src"; describe("date", () => { it("formatters", () => { @@ -27,4 +27,21 @@ describe("date", () => { check(["S"], "5", "17"); check(["yyyy", "-", "MM", "-", "dd"], "2020-09-01", "1996-12-13"); }); + + it("timecode", () => { + assert.strictEqual( + defTimecode(30)(HOUR + 2 * MINUTE + 3 * SECOND + (4 * 1000) / 30), + "01:02:03:04" + ); + assert.strictEqual( + defTimecode(30)(4 * DAY + HOUR + 2 * MINUTE + 3 * SECOND + 999), + "04:01:02:03:29" + ); + assert.strictEqual( + defTimecode(30, ["d ", "h ", "' ", '" '])( + 4 * DAY + HOUR + 2 * MINUTE + 3 * SECOND + 999 + ), + "04d 01h 02' 03\" 29" + ); + }); }); diff --git a/packages/date/test/iterators.ts b/packages/date/test/iterators.ts index 844f926167..6909fbdec4 100644 --- a/packages/date/test/iterators.ts +++ b/packages/date/test/iterators.ts @@ -3,13 +3,14 @@ import { days, defFormat, FMT_yyyyMMdd, hours, months, years } from "../src"; describe("date", () => { it("hours", () => { + const fmt = defFormat(["dd", " ", "h", ":", "mm", " ", "A"]); assert.deepStrictEqual( [ ...hours( Date.UTC(2019, 11, 30, 15, 1), Date.UTC(2019, 11, 31, 15, 1) ), - ].map(defFormat(["dd", " ", "h", ":", "mm", " ", "A"])), + ].map((x) => fmt(x)), [ "30 4:00 PM", "30 5:00 PM", @@ -41,9 +42,9 @@ describe("date", () => { it("days", () => { assert.deepStrictEqual( - [...days(Date.UTC(2019, 11, 30, 15), Date.UTC(2020, 1, 1, 1))].map( - FMT_yyyyMMdd - ), + [ + ...days(Date.UTC(2019, 11, 30, 15), Date.UTC(2020, 1, 1, 1)), + ].map((x) => FMT_yyyyMMdd(x)), [ "2019-12-31", "2020-01-01", @@ -86,7 +87,7 @@ describe("date", () => { assert.deepStrictEqual( [ ...months(Date.UTC(2019, 10, 30, 15), Date.UTC(2020, 10, 1, 1)), - ].map(FMT_yyyyMMdd), + ].map((x) => FMT_yyyyMMdd(x)), [ "2019-12-01", "2020-01-01", @@ -108,7 +109,7 @@ describe("date", () => { assert.deepStrictEqual( [ ...years(Date.UTC(1996, 10, 30, 15), Date.UTC(2005, 10, 1, 1)), - ].map(FMT_yyyyMMdd), + ].map((x) => FMT_yyyyMMdd(x)), [ "1997-01-01", "1998-01-01", From 1256201c20e4cd01e4f7e0a1d2fbc9a163a96ac4 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Mon, 21 Sep 2020 21:48:38 +0100 Subject: [PATCH 100/106] feat(date): add iterator arg coercions, refactor, add docs --- packages/date/src/api.ts | 32 ++++++++++++++++++++++++++++++-- packages/date/src/datetime.ts | 16 +++++++++++++--- packages/date/src/format.ts | 11 +++-------- packages/date/src/iterators.ts | 4 +++- packages/date/test/iterators.ts | 22 +++++++++++++++++++++- 5 files changed, 70 insertions(+), 15 deletions(-) diff --git a/packages/date/src/api.ts b/packages/date/src/api.ts index 17ffbf5991..8c74cf3b58 100644 --- a/packages/date/src/api.ts +++ b/packages/date/src/api.ts @@ -1,13 +1,37 @@ import type { Fn } from "@thi.ng/api"; +/** + * Second duration in milliseconds + */ export const SECOND = 1000; +/** + * Minute duration in milliseconds + */ export const MINUTE = 60 * SECOND; +/** + * Hour duration in milliseconds + */ export const HOUR = 60 * MINUTE; +/** + * Day duration in milliseconds + */ export const DAY = 24 * HOUR; +/** + * Week duration in milliseconds + */ export const WEEK = 7 * DAY; +/** + * Mean month duration (30.4375 days) in milliseconds + */ export const MONTH = 30.4375 * DAY; +/** + * Mean year duration (365.25 days) in milliseconds + */ export const YEAR = 365.25 * DAY; +/** + * Days per month LUT (non-leap year) + */ export const DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; export interface Locale { @@ -21,9 +45,13 @@ export interface Locale { days: string[]; } +export interface IEpoch { + getTime(): number; +} + export interface EpochIteratorConstructor { - ([from, to]: number[]): EpochIterator; - (from: number, to: number): EpochIterator; + ([from, to]: (number | IEpoch)[]): EpochIterator; + (from: number | IEpoch, to: number | IEpoch): EpochIterator; } export type EpochIterator = IterableIterator; diff --git a/packages/date/src/datetime.ts b/packages/date/src/datetime.ts index 68c83bbf11..dc730ead9c 100644 --- a/packages/date/src/datetime.ts +++ b/packages/date/src/datetime.ts @@ -17,8 +17,11 @@ export class DateTime implements ICopy { M: number; y: number; - constructor(epoch: Date | number = Date.now(), prec: Precision = "t") { - const x = typeof epoch === "number" ? new Date(epoch) : epoch; + constructor( + epoch: DateTime | Date | number = Date.now(), + prec: Precision = "t" + ) { + const x = ensureDate(epoch); const id = "yMdhmst".indexOf(prec); this.y = x.getUTCFullYear(); this.M = id >= 1 ? x.getUTCMonth() : 0; @@ -108,10 +111,17 @@ export class DateTime implements ICopy { } toString() { - return this.toDate().toString(); + return this.toDate().toUTCString(); } toISOString() { return this.toDate().toISOString(); } } + +export const ensureDate = (x: number | DateTime | Date) => + typeof x === "number" + ? new Date(x) + : x instanceof DateTime + ? x.toDate() + : x; diff --git a/packages/date/src/format.ts b/packages/date/src/format.ts index 6971509841..ee463685e2 100644 --- a/packages/date/src/format.ts +++ b/packages/date/src/format.ts @@ -1,5 +1,5 @@ import { DAY, FormatFn, HOUR, MINUTE, SECOND } from "./api"; -import { DateTime } from "./datetime"; +import { DateTime, ensureDate } from "./datetime"; import { LOCALE } from "./i18n"; const Z2 = (x: number) => (x < 10 ? "0" + x : String(x)); @@ -112,12 +112,7 @@ export const defFormat = (fmt: (string | FormatFn)[]) => ( x: DateTime | Date | number, utc = false ) => { - let d = - typeof x === "number" - ? new Date(x) - : x instanceof DateTime - ? x.toDate() - : x; + let d = ensureDate(x); utc && (d = new Date(d.getTime() + d.getTimezoneOffset() * MINUTE)); return fmt .map((x) => { @@ -177,7 +172,7 @@ export const FMT_hms = defFormat(["h", ":", "mm", ":", "ss", " ", "A"]); export const FMT_yyyyMMdd_HHmmss = defFormat(["yyyy", "MM", "dd", "-", "HH", "mm", "ss"]); /** - * Returns a time formatter for given FPS (frames / second, in [1..100] range), + * Returns a time formatter for given FPS (frames / second, in [1..1000] range), * e.g. `HH:mm:ss:ff`. The returned function takes a single arg (time in * milliseconds) and returns formatted string. * diff --git a/packages/date/src/iterators.ts b/packages/date/src/iterators.ts index a9e2ebc44a..344ddf7c5d 100644 --- a/packages/date/src/iterators.ts +++ b/packages/date/src/iterators.ts @@ -7,7 +7,9 @@ export const defIterator = ( tick: Fn ): EpochIteratorConstructor => { return function* (...xs: any[]): EpochIterator { - const [from, to] = xs.length > 1 ? xs : xs[0]; + let [from, to] = ((xs.length > 1 ? xs : xs[0])).map((x) => + new DateTime(x).getTime() + ); let state = new DateTime(from, prec); let epoch = from; while (epoch < to) { diff --git a/packages/date/test/iterators.ts b/packages/date/test/iterators.ts index 6909fbdec4..4ba152533c 100644 --- a/packages/date/test/iterators.ts +++ b/packages/date/test/iterators.ts @@ -1,5 +1,14 @@ import * as assert from "assert"; -import { days, defFormat, FMT_yyyyMMdd, hours, months, years } from "../src"; +import { + dateTime, + days, + defFormat, + FMT_yyyyMMdd, + hours, + months, + YEAR, + years, +} from "../src"; describe("date", () => { it("hours", () => { @@ -123,4 +132,15 @@ describe("date", () => { ] ); }); + + it("arg coercion", () => { + assert.deepStrictEqual( + [...years(dateTime(0), dateTime(YEAR))].map((x) => FMT_yyyyMMdd(x)), + ["1970-01-01", "1971-01-01"] + ); + assert.deepStrictEqual( + [...years(new Date(0), new Date(YEAR))].map((x) => FMT_yyyyMMdd(x)), + ["1970-01-01", "1971-01-01"] + ); + }); }); From d5c83c4e606ce87d9c544b5e7a078ad364d1c6f5 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Mon, 21 Sep 2020 21:48:57 +0100 Subject: [PATCH 101/106] docs(date): update readme --- packages/date/README.md | 183 ++++++++++++++++++++++++++++++------ packages/date/tpl.readme.md | 178 +++++++++++++++++++++++++++++------ 2 files changed, 304 insertions(+), 57 deletions(-) diff --git a/packages/date/README.md b/packages/date/README.md index 3d3916fb60..733ab6f485 100644 --- a/packages/date/README.md +++ b/packages/date/README.md @@ -14,7 +14,10 @@ This project is part of the - [Installation](#installation) - [Dependencies](#dependencies) - [API](#api) + - [DateTime & iterators](#datetime--iterators) - [Formatters](#formatters) + - [Timecodes](#timecodes) + - [Locales](#locales) - [Authors](#authors) - [License](#license) @@ -42,7 +45,7 @@ yarn add @thi.ng/date ``` -Package sizes (gzipped, pre-treeshake): ESM: 1.28 KB / CJS: 1.43 KB / UMD: 1.42 KB +Package sizes (gzipped, pre-treeshake): ESM: 1.74 KB / CJS: 1.90 KB / UMD: 1.88 KB ## Dependencies @@ -54,44 +57,166 @@ Package sizes (gzipped, pre-treeshake): ESM: 1.28 KB / CJS: 1.43 KB / UMD: 1.42 TODO - Please see tests and doc strings in source for now... +### DateTime & iterators + +The `DateTime` class acts as a thin wrapper around **UTC** epochs/timestamps, +with the constructor supporting coercions and varying granularity/precision +(from years to milliseconds). The main use case of this class is as backend for +the various epoch iterators provided by this package, which in turn are largely +intended for visualization purposes (axis tick label generators in +[@thi.ng/viz](https://github.com/thi-ng/umbrella/tree/develop/packages/viz)). + +```ts +// create w/ current date (or pass epoch, Date or DateTime instances) +const a = dateTime(); +// DateTime { y: 2020, M: 8, d: 19, h: 12, m: 17, s: 16, t: 884 } + +// provide additional precision (here year only) +const b = dateTime(a, "y"); +// DateTime { y: 2020, M: 0, d: 1, h: 0, m: 0, s: 0, t: 0 } + +a.toString(); +// Sat Sep 19 2020 12:17:16 GMT' +a.toISOString() +// '2020-09-19T12:17:16.884Z' + +b.toISOString(); +// 2020-01-01T00:00:00.000Z + +a.isLeapYear() +// true + +a.daysInMonth() +// 30 + +[...months(b, a)] +// [ +// 1577836800000, +// 1580515200000, +// 1583020800000, +// 1585699200000, +// 1588291200000, +// 1590969600000, +// 1593561600000, +// 1596240000000, +// 1598918400000 +// ] + +[...months(b, a)].map((x) => FMT_yyyyMMdd(x)) +// [ +// '2020-01-01', +// '2020-02-01', +// '2020-03-01', +// '2020-04-01', +// '2020-05-01', +// '2020-06-01', +// '2020-07-01', +// '2020-08-01', +// '2020-09-01' +// ] +``` + ### Formatters Custom date/time formatters can be assembled via -[`defFormat()`](https://github.com/thi-ng/umbrella/blob/develop/packages/date/src/format.ts#L85), -using the following partial format identifiers. - -| ID | Description | -|--------|------------------------------------------| -| `yyyy` | Full year (4 digits) | -| `yy` | Short year (2 digits) | -| `MMM` | 3-letter month name (e.g. `Feb`) | -| `MM` | Zero-padded 2-digit month | -| `M` | Unpadded month | -| `dd` | Zero-padded 2-digit day of month | -| `d` | Unpadded day of month | -| `E` | 3-letter weekday name (e.g. `Mon`) | -| `HH` | Zero-padded 2-digit hour of day (0-23) | -| `h` | Unpadded hour of day (1-12) | -| `mm` | Zero-padded 2-digit minute of hour | -| `m` | Unpadded minute of hour | -| `ss` | Zero-padded 2-digit second of minute | -| `s` | Unpadded second of minute | -| `S` | Unpadded millisecond of second | -| `A` | 12-hour AM/PM marker | -| `Z` | Timezone offset in signed `HH:mm` format | - -Furthermore, the following preset formatters are available: +[`defFormat()`](https://github.com/thi-ng/umbrella/blob/develop/packages/date/src/format.ts#L93), +using the following partial format identifiers. The `MMM` and `E` formatters use the currently active [locale](#locale). + +| ID | Description | +|--------|---------------------------------------------| +| `yyyy` | Full year (4 digits) | +| `yy` | Short year (2 digits) | +| `MMM` | Month name in current locale (e.g. `Feb`) | +| `MM` | Zero-padded 2-digit month | +| `M` | Unpadded month | +| `dd` | Zero-padded 2-digit day of month | +| `d` | Unpadded day of month | +| `E` | Weekday name in current locale (e.g. `Mon`) | +| `HH` | Zero-padded 2-digit hour of day (0-23) | +| `h` | Unpadded hour of day (1-12) | +| `mm` | Zero-padded 2-digit minute of hour | +| `m` | Unpadded minute of hour | +| `ss` | Zero-padded 2-digit second of minute | +| `s` | Unpadded second of minute | +| `S` | Unpadded millisecond of second | +| `A` | 12-hour AM/PM marker | +| `Z` | Timezone offset in signed `HH:mm` format | + +(Format IDs somewhat based on Java's [SimpleDateFormat](https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/text/SimpleDateFormat.html)) + +The following preset formatters are available: - `FMT_yyyyMMdd` - `"2020-09-13"` -- `FMT_MMddyyyy` - `"09/13/2020"` -- `FMT_MMMddyyyy` - `"Sep 13 2020"` -- `FMT_ddMMyyyy` - `"13/09/2020"` -- `FMT_ddMMMyyyy` - `"13 Sep 2020"` +- `FMT_Mdyyyy` - `"9/13/2020"` +- `FMT_MMMdyyyy` - `"Sep 13 2020"` +- `FMT_dMyyyy` - `"13/9/2020"` +- `FMT_dMMMyyyy` - `"13 Sep 2020"` +- `FMT_yyyyMMdd_HHmmss` - `20200913-214207` - `FMT_HHmm` - `"21:42"` - `FMT_hm` - `"9:42 PM"` - `FMT_HHmmss` - `"21:42:07"` - `FMT_hms` - `"9:42:07 PM"` +### Timecodes + +For timebased media applications, the higher-order `defTimecode()` can be used +to create a formatter for a given FPS (frames / second, in [1..1000] range), +e.g. `HH:mm:ss:ff`. The returned function takes a single arg (time in +milliseconds) and returns formatted string. + +The timecode considers days too, but only includes them in the result if the day +part is non-zero. The 4 separators between each field can be customized via 2nd +arg (default: all `:`). + +```ts +a = defTimecode(30); +a(HOUR + 2*MINUTE + 3*SECOND + 4*1000/30) +// "01:02:03:04" + +a(DAY); +// "01:00:00:00:00" + +b = defTimecode(30, ["d ", "h ", "' ", '" ']); +b(Day + HOUR + 2*MINUTE + 3*SECOND + 999) +// "01d 01h 02' 03" 29" +``` + +### Locales + +The `MMM` (month) and `E` (weekday) formatters make use of the strings provided +by the current `LOCALE` (default: `EN_SHORT`) and can be set/changed via the +`setLocale()` function: + +```ts +const fmt = defFormat(["E", " ", "d", " ", "MMM", " ", "yyyy"]); + +setLocale(EN_SHORT); // default +// { +// months: [ +// 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', +// 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' +// ], +// days: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ] +// } + +fmt(dateTime()); +// Sat 19 Sep 2020 + +setLocale(EN_LONG); +// { +// months: [ +// 'January', 'February', 'March', 'April', 'May', 'June', +// 'July', 'August', 'September', 'October', 'November', 'December' +// ], +// days: [ +// 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' +// ] +// } + +fmt(dateTime()); +// Saturday 19 September 2020 +``` + ## Authors Karsten Schmidt diff --git a/packages/date/tpl.readme.md b/packages/date/tpl.readme.md index 2bf2969ec4..d492eee8dd 100644 --- a/packages/date/tpl.readme.md +++ b/packages/date/tpl.readme.md @@ -39,44 +39,166 @@ ${docLink} TODO - Please see tests and doc strings in source for now... +### DateTime & iterators + +The `DateTime` class acts as a thin wrapper around **UTC** epochs/timestamps, +with the constructor supporting coercions and varying granularity/precision +(from years to milliseconds). The main use case of this class is as backend for +the various epoch iterators provided by this package, which in turn are largely +intended for visualization purposes (axis tick label generators in +[@thi.ng/viz](https://github.com/thi-ng/umbrella/tree/develop/packages/viz)). + +```ts +// create w/ current date (or pass epoch, Date or DateTime instances) +const a = dateTime(); +// DateTime { y: 2020, M: 8, d: 19, h: 12, m: 17, s: 16, t: 884 } + +// provide additional precision (here year only) +const b = dateTime(a, "y"); +// DateTime { y: 2020, M: 0, d: 1, h: 0, m: 0, s: 0, t: 0 } + +a.toString(); +// Sat Sep 19 2020 12:17:16 GMT' +a.toISOString() +// '2020-09-19T12:17:16.884Z' + +b.toISOString(); +// 2020-01-01T00:00:00.000Z + +a.isLeapYear() +// true + +a.daysInMonth() +// 30 + +[...months(b, a)] +// [ +// 1577836800000, +// 1580515200000, +// 1583020800000, +// 1585699200000, +// 1588291200000, +// 1590969600000, +// 1593561600000, +// 1596240000000, +// 1598918400000 +// ] + +[...months(b, a)].map((x) => FMT_yyyyMMdd(x)) +// [ +// '2020-01-01', +// '2020-02-01', +// '2020-03-01', +// '2020-04-01', +// '2020-05-01', +// '2020-06-01', +// '2020-07-01', +// '2020-08-01', +// '2020-09-01' +// ] +``` + ### Formatters Custom date/time formatters can be assembled via -[`defFormat()`](https://github.com/thi-ng/umbrella/blob/develop/packages/date/src/format.ts#L85), -using the following partial format identifiers. - -| ID | Description | -|--------|------------------------------------------| -| `yyyy` | Full year (4 digits) | -| `yy` | Short year (2 digits) | -| `MMM` | 3-letter month name (e.g. `Feb`) | -| `MM` | Zero-padded 2-digit month | -| `M` | Unpadded month | -| `dd` | Zero-padded 2-digit day of month | -| `d` | Unpadded day of month | -| `E` | 3-letter weekday name (e.g. `Mon`) | -| `HH` | Zero-padded 2-digit hour of day (0-23) | -| `h` | Unpadded hour of day (1-12) | -| `mm` | Zero-padded 2-digit minute of hour | -| `m` | Unpadded minute of hour | -| `ss` | Zero-padded 2-digit second of minute | -| `s` | Unpadded second of minute | -| `S` | Unpadded millisecond of second | -| `A` | 12-hour AM/PM marker | -| `Z` | Timezone offset in signed `HH:mm` format | - -Furthermore, the following preset formatters are available: +[`defFormat()`](https://github.com/thi-ng/umbrella/blob/develop/packages/date/src/format.ts#L93), +using the following partial format identifiers. The `MMM` and `E` formatters use the currently active [locale](#locale). + +| ID | Description | +|--------|---------------------------------------------| +| `yyyy` | Full year (4 digits) | +| `yy` | Short year (2 digits) | +| `MMM` | Month name in current locale (e.g. `Feb`) | +| `MM` | Zero-padded 2-digit month | +| `M` | Unpadded month | +| `dd` | Zero-padded 2-digit day of month | +| `d` | Unpadded day of month | +| `E` | Weekday name in current locale (e.g. `Mon`) | +| `HH` | Zero-padded 2-digit hour of day (0-23) | +| `h` | Unpadded hour of day (1-12) | +| `mm` | Zero-padded 2-digit minute of hour | +| `m` | Unpadded minute of hour | +| `ss` | Zero-padded 2-digit second of minute | +| `s` | Unpadded second of minute | +| `S` | Unpadded millisecond of second | +| `A` | 12-hour AM/PM marker | +| `Z` | Timezone offset in signed `HH:mm` format | + +(Format IDs somewhat based on Java's [SimpleDateFormat](https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/text/SimpleDateFormat.html)) + +The following preset formatters are available: - `FMT_yyyyMMdd` - `"2020-09-13"` -- `FMT_MMddyyyy` - `"09/13/2020"` -- `FMT_MMMddyyyy` - `"Sep 13 2020"` -- `FMT_ddMMyyyy` - `"13/09/2020"` -- `FMT_ddMMMyyyy` - `"13 Sep 2020"` +- `FMT_Mdyyyy` - `"9/13/2020"` +- `FMT_MMMdyyyy` - `"Sep 13 2020"` +- `FMT_dMyyyy` - `"13/9/2020"` +- `FMT_dMMMyyyy` - `"13 Sep 2020"` +- `FMT_yyyyMMdd_HHmmss` - `20200913-214207` - `FMT_HHmm` - `"21:42"` - `FMT_hm` - `"9:42 PM"` - `FMT_HHmmss` - `"21:42:07"` - `FMT_hms` - `"9:42:07 PM"` +### Timecodes + +For timebased media applications, the higher-order `defTimecode()` can be used +to create a formatter for a given FPS (frames / second, in [1..1000] range), +e.g. `HH:mm:ss:ff`. The returned function takes a single arg (time in +milliseconds) and returns formatted string. + +The timecode considers days too, but only includes them in the result if the day +part is non-zero. The 4 separators between each field can be customized via 2nd +arg (default: all `:`). + +```ts +a = defTimecode(30); +a(HOUR + 2*MINUTE + 3*SECOND + 4*1000/30) +// "01:02:03:04" + +a(DAY); +// "01:00:00:00:00" + +b = defTimecode(30, ["d ", "h ", "' ", '" ']); +b(Day + HOUR + 2*MINUTE + 3*SECOND + 999) +// "01d 01h 02' 03" 29" +``` + +### Locales + +The `MMM` (month) and `E` (weekday) formatters make use of the strings provided +by the current `LOCALE` (default: `EN_SHORT`) and can be set/changed via the +`setLocale()` function: + +```ts +const fmt = defFormat(["E", " ", "d", " ", "MMM", " ", "yyyy"]); + +setLocale(EN_SHORT); // default +// { +// months: [ +// 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', +// 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' +// ], +// days: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ] +// } + +fmt(dateTime()); +// Sat 19 Sep 2020 + +setLocale(EN_LONG); +// { +// months: [ +// 'January', 'February', 'March', 'April', 'May', 'June', +// 'July', 'August', 'September', 'October', 'November', 'December' +// ], +// days: [ +// 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' +// ] +// } + +fmt(dateTime()); +// Saturday 19 September 2020 +``` + ## Authors ${authors} From 0a45ef8aa99d3dab1bb98c503cf87d1bef0ab8e2 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 22 Sep 2020 11:11:28 +0100 Subject: [PATCH 102/106] feat(geom-api): add Type.TEXT/3 --- packages/geom-api/src/shape.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/geom-api/src/shape.ts b/packages/geom-api/src/shape.ts index 6d77c86c54..fe3a573e6f 100644 --- a/packages/geom-api/src/shape.ts +++ b/packages/geom-api/src/shape.ts @@ -31,6 +31,9 @@ export enum Type { TRIANGLE3, RAY, RAY3, + + TEXT, + TEXT3, } export type Attribs = IObjectOf; From 9d1424d1c57e4d2c55fb6cfdd507f3ca7cd85dc3 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 22 Sep 2020 11:36:12 +0100 Subject: [PATCH 103/106] feat(geom): add basic text support --- packages/geom/src/api/text.ts | 25 +++++++++++++++++++++++++ packages/geom/src/ctors/text.ts | 6 ++++++ packages/geom/src/index.ts | 2 ++ packages/geom/src/ops/bounds.ts | 5 ++++- packages/geom/src/ops/centroid.ts | 3 ++- packages/geom/src/ops/transform.ts | 6 +++++- packages/geom/src/ops/translate.ts | 6 +++++- 7 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 packages/geom/src/api/text.ts create mode 100644 packages/geom/src/ctors/text.ts diff --git a/packages/geom/src/api/text.ts b/packages/geom/src/api/text.ts new file mode 100644 index 0000000000..f8f321a5b8 --- /dev/null +++ b/packages/geom/src/api/text.ts @@ -0,0 +1,25 @@ +import { Attribs, IHiccupShape, Type } from "@thi.ng/geom-api"; +import { set, Vec } from "@thi.ng/vectors"; +import { copyAttribs } from "../internal/copy-attribs"; + +/** + * Basic stub for text elements. Currently, only a minimal set of geometry + * operations are implemented for this type, however this type implements + * {@link @this.ng/api#IToHiccup} and so is useful as wrapper for inclusion of + * text elements in {@link Group}s with other shape types. + */ +export class Text implements IHiccupShape { + constructor(public pos: Vec, public body: any, public attribs?: Attribs) {} + + get type() { + return Type.TEXT; + } + + copy(): Text { + return new Text(set([], this.pos), this.body, copyAttribs(this)); + } + + toHiccup() { + return ["text", this.attribs, this.pos, this.body]; + } +} diff --git a/packages/geom/src/ctors/text.ts b/packages/geom/src/ctors/text.ts new file mode 100644 index 0000000000..2d0b9711b7 --- /dev/null +++ b/packages/geom/src/ctors/text.ts @@ -0,0 +1,6 @@ +import type { Attribs } from "@thi.ng/geom-api"; +import { Vec } from "@thi.ng/vectors"; +import { Text } from "../api/text"; + +export const text = (pos: Vec, body: any, attribs?: Attribs) => + new Text(pos, body, attribs); diff --git a/packages/geom/src/index.ts b/packages/geom/src/index.ts index 68b111a434..cfc695ac61 100644 --- a/packages/geom/src/index.ts +++ b/packages/geom/src/index.ts @@ -17,6 +17,7 @@ export * from "./api/quadratic"; export * from "./api/ray"; export * from "./api/rect"; export * from "./api/sphere"; +export * from "./api/text"; export * from "./api/triangle"; export * from "./ctors/aabb"; @@ -37,6 +38,7 @@ export * from "./ctors/quad"; export * from "./ctors/quadratic"; export * from "./ctors/ray"; export * from "./ctors/rect"; +export * from "./ctors/text"; export * from "./ctors/triangle"; export * from "./ops/arc-length"; diff --git a/packages/geom/src/ops/bounds.ts b/packages/geom/src/ops/bounds.ts index 8fe30e0e33..f224c42c77 100644 --- a/packages/geom/src/ops/bounds.ts +++ b/packages/geom/src/ops/bounds.ts @@ -1,3 +1,4 @@ +import type { IObjectOf } from "@thi.ng/api"; import { defmulti, Implementation1 } from "@thi.ng/defmulti"; import { AABBLike, IShape, PathSegment, PCLike, Type } from "@thi.ng/geom-api"; import { bounds as arcBounds } from "@thi.ng/geom-arc"; @@ -27,11 +28,11 @@ import { Line } from "../api/line"; import { Path } from "../api/path"; import { Quadratic } from "../api/quadratic"; import { Rect } from "../api/rect"; +import { Text } from "../api/text"; import { aabbFromMinMax } from "../ctors/aabb"; import { rectFromMinMax } from "../ctors/rect"; import { collBounds } from "../internal/coll-bounds"; import { dispatch } from "../internal/dispatch"; -import type { IObjectOf } from "@thi.ng/api"; export const bounds = defmulti(dispatch); @@ -84,6 +85,8 @@ bounds.addAll(>>{ rectFromMinMax(...quadraticBounds(points[0], points[1], points[2])), [Type.RECT]: ($: IShape) => $.copy(), + + [Type.TEXT]: ($: Text) => new Rect(set2([], $.pos), [0, 0]), }); bounds.isa(Type.AABB, Type.RECT); diff --git a/packages/geom/src/ops/centroid.ts b/packages/geom/src/ops/centroid.ts index 4b027b712b..32229002db 100644 --- a/packages/geom/src/ops/centroid.ts +++ b/packages/geom/src/ops/centroid.ts @@ -1,3 +1,4 @@ +import type { IObjectOf } from "@thi.ng/api"; import { defmulti, Implementation1O, MultiFn1O } from "@thi.ng/defmulti"; import { AABBLike, IShape, PCLike, Type } from "@thi.ng/geom-api"; import { @@ -13,7 +14,6 @@ import { Polygon } from "../api/polygon"; import { Triangle } from "../api/triangle"; import { dispatch } from "../internal/dispatch"; import { bounds } from "./bounds"; -import type { IObjectOf } from "@thi.ng/api"; export const centroid: MultiFn1O = defmulti( dispatch @@ -54,4 +54,5 @@ centroid.isa(Type.POINTS3, Type.POINTS); centroid.isa(Type.POLYLINE, Type.POINTS); centroid.isa(Type.QUAD, Type.POLYGON); centroid.isa(Type.SPHERE, Type.CIRCLE); +centroid.isa(Type.TEXT, Type.CIRCLE); centroid.isa(Type.TRIANGLE3, Type.TRIANGLE); diff --git a/packages/geom/src/ops/transform.ts b/packages/geom/src/ops/transform.ts index 6abeaa6595..e980e30575 100644 --- a/packages/geom/src/ops/transform.ts +++ b/packages/geom/src/ops/transform.ts @@ -1,3 +1,4 @@ +import type { IObjectOf } from "@thi.ng/api"; import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IHiccupShape, @@ -18,6 +19,7 @@ import { Polyline } from "../api/polyline"; import { Quad } from "../api/quad"; import { Quadratic } from "../api/quadratic"; import { Rect } from "../api/rect"; +import { Text } from "../api/text"; import { Triangle } from "../api/triangle"; import { copyAttribs } from "../internal/copy-attribs"; import { dispatch } from "../internal/dispatch"; @@ -27,7 +29,6 @@ import { } from "../internal/transform-points"; import { asPath } from "./as-path"; import { asPolygon } from "./as-polygon"; -import type { IObjectOf } from "@thi.ng/api"; /** * Transforms given shape with provided matrix. Some shape types will be @@ -89,6 +90,9 @@ transform.addAll(>>{ [Type.RECT]: ($: Rect, mat) => transform(asPolygon($), mat), + [Type.TEXT]: ($: Text, mat) => + new Text(mulV([], mat, $.pos!), $.body, copyAttribs($)), + [Type.TRIANGLE]: tx(Triangle), }); diff --git a/packages/geom/src/ops/translate.ts b/packages/geom/src/ops/translate.ts index 7baea5e840..d96a49ae8d 100644 --- a/packages/geom/src/ops/translate.ts +++ b/packages/geom/src/ops/translate.ts @@ -1,3 +1,4 @@ +import type { IObjectOf } from "@thi.ng/api"; import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IHiccupShape, IShape, Type } from "@thi.ng/geom-api"; import { add2, add3, ReadonlyVec, set2, set3 } from "@thi.ng/vectors"; @@ -15,11 +16,11 @@ import { Quad } from "../api/quad"; import { Ray } from "../api/ray"; import { Rect } from "../api/rect"; import { Sphere } from "../api/sphere"; +import { Text } from "../api/text"; import { Triangle } from "../api/triangle"; import { copyAttribs } from "../internal/copy-attribs"; import { dispatch } from "../internal/dispatch"; import { translatedShape as tx } from "../internal/translate-points"; -import type { IObjectOf } from "@thi.ng/api"; export const translate = defmulti(dispatch); @@ -82,5 +83,8 @@ translate.addAll(>>{ [Type.SPHERE]: ($: Sphere, delta) => new Sphere(add3([], $.pos, delta), $.r, copyAttribs($)), + [Type.TEXT]: ($: Text, delta) => + new Text(add2([], $.pos, delta), $.body, copyAttribs($)), + [Type.TRIANGLE]: tx(Triangle), }); From cda40f1df86e0f302ef03b45030bd4980f59e024 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 22 Sep 2020 11:38:13 +0100 Subject: [PATCH 104/106] refactor(hdom): update normalizeTree() - extract normalizeChildren() --- packages/hdom/src/normalize.ts | 121 ++++++++++++++++----------------- 1 file changed, 59 insertions(+), 62 deletions(-) diff --git a/packages/hdom/src/normalize.ts b/packages/hdom/src/normalize.ts index abe871d001..eff3c30dba 100644 --- a/packages/hdom/src/normalize.ts +++ b/packages/hdom/src/normalize.ts @@ -54,8 +54,11 @@ export const normalizeElement = (spec: any[], keys: boolean) => { if (tag === name && hasAttribs && (!keys || spec[1].key)) { return spec; } - attribs = hasAttribs ? { ...spec[1] } : {}; - mergeEmmetAttribs(attribs, match![2], match![3]); + attribs = mergeEmmetAttribs( + hasAttribs ? { ...spec[1] } : {}, + match![2], + match![3] + ); return attribs.__skip && spec.length < 3 ? [name, attribs] : [name, attribs, ...spec.slice(hasAttribs ? 2 : 1)]; @@ -144,69 +147,63 @@ const _normalizeTree = ( if (keys && nattribs.key === undefined) { nattribs.key = path.join("-"); } - if (norm.length > 2) { - const tag = norm[0]; - const res = [tag, nattribs]; - span = span && !NO_SPANS[tag]; - for (let i = 2, j = 2, k = 0, n = norm.length; i < n; i++) { - let el = norm[i]; - if (el != null) { - const isarray = isArray(el); - if ( - (isarray && isArray(el[0])) || - (!isarray && isNotStringAndIterable(el)) - ) { - for (let c of el) { - c = _normalizeTree( - c, - opts, - ctx, - path.concat(k), - keys, - span - ); - if (c !== undefined) { - res[j++] = c; - } - k++; - } - } else { - el = _normalizeTree( - el, - opts, - ctx, - path.concat(k), - keys, - span - ); - if (el !== undefined) { - res[j++] = el; - } - k++; + return norm.length > 2 + ? normalizeChildren(norm, nattribs, opts, ctx, path, keys, span) + : norm; + } + return typeof tree === "function" + ? _normalizeTree(tree(ctx), opts, ctx, path, keys, span) + : typeof tree.toHiccup === "function" + ? _normalizeTree(tree.toHiccup(opts.ctx), opts, ctx, path, keys, span) + : typeof tree.deref === "function" + ? _normalizeTree(tree.deref(), opts, ctx, path, keys, span) + : span + ? ["span", keys ? { key: path.join("-") } : {}, tree.toString()] + : tree.toString(); +}; + +const normalizeChildren = ( + norm: any[], + nattribs: any, + opts: Partial, + ctx: any, + path: number[], + keys: boolean, + span: boolean +) => { + const tag = norm[0]; + const res = [tag, nattribs]; + span = span && !NO_SPANS[tag]; + for (let i = 2, j = 2, k = 0, n = norm.length; i < n; i++) { + let el = norm[i]; + if (el != null) { + const isarray = isArray(el); + if ( + (isarray && isArray(el[0])) || + (!isarray && isNotStringAndIterable(el)) + ) { + for (let c of el) { + c = _normalizeTree( + c, + opts, + ctx, + path.concat(k), + keys, + span + ); + if (c !== undefined) { + res[j++] = c; } + k++; } + } else { + el = _normalizeTree(el, opts, ctx, path.concat(k), keys, span); + if (el !== undefined) { + res[j++] = el; + } + k++; } - return res; } - return norm; - } - if (typeof tree === "function") { - return _normalizeTree(tree(ctx), opts, ctx, path, keys, span); } - if (typeof tree.toHiccup === "function") { - return _normalizeTree( - tree.toHiccup(opts.ctx), - opts, - ctx, - path, - keys, - span - ); - } - if (typeof tree.deref === "function") { - return _normalizeTree(tree.deref(), opts, ctx, path, keys, span); - } - return span - ? ["span", keys ? { key: path.join("-") } : {}, tree.toString()] - : tree.toString(); + return res; }; From 656dd5f1f0c8fe74f932d2b49ea1371cf5599fdf Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 22 Sep 2020 11:55:43 +0100 Subject: [PATCH 105/106] docs: update all readmes --- packages/adapt-dpi/README.md | 2 ++ packages/adjacency/README.md | 2 ++ packages/api/README.md | 2 ++ packages/arrays/README.md | 2 ++ packages/associative/README.md | 4 +++- packages/atom/README.md | 2 ++ packages/bench/README.md | 2 ++ packages/bencode/README.md | 2 ++ packages/binary/README.md | 2 ++ packages/bitfield/README.md | 2 ++ packages/bitstream/README.md | 2 ++ packages/cache/README.md | 2 ++ packages/checks/README.md | 2 ++ packages/color/README.md | 2 ++ packages/colored-noise/README.md | 2 ++ packages/compare/README.md | 2 ++ packages/compose/README.md | 2 ++ packages/csp/README.md | 2 ++ packages/dcons/README.md | 2 ++ packages/defmulti/README.md | 2 ++ packages/dgraph-dot/README.md | 2 ++ packages/dgraph/README.md | 2 ++ packages/diff/README.md | 2 ++ packages/dl-asset/README.md | 2 ++ packages/dlogic/README.md | 2 ++ packages/dot/README.md | 2 ++ packages/dsp-io-wav/README.md | 2 ++ packages/dsp/README.md | 2 ++ packages/dual-algebra/README.md | 2 ++ packages/dynvar/README.md | 2 ++ packages/ecs/README.md | 2 ++ packages/egf/README.md | 2 +- packages/equiv/README.md | 2 ++ packages/errors/README.md | 2 ++ packages/fsm/README.md | 2 ++ packages/geom-accel/README.md | 4 +++- packages/geom-api/README.md | 4 +++- packages/geom-arc/README.md | 2 ++ packages/geom-clip-line/README.md | 2 ++ packages/geom-clip-poly/README.md | 2 ++ packages/geom-closest-point/README.md | 4 +++- packages/geom-fuzz/README.md | 2 ++ packages/geom-hull/README.md | 2 ++ packages/geom-io-obj/README.md | 4 +++- packages/geom-isec/README.md | 4 +++- packages/geom-isoline/README.md | 2 ++ packages/geom-poly-utils/README.md | 2 ++ packages/geom-resample/README.md | 4 +++- packages/geom-splines/README.md | 2 ++ packages/geom-subdiv-curve/README.md | 4 +++- packages/geom-tessellate/README.md | 2 ++ packages/geom-voronoi/README.md | 2 ++ packages/geom/README.md | 4 +++- packages/gp/README.md | 2 ++ packages/grid-iterators/README.md | 2 ++ packages/hdiff/README.md | 2 ++ packages/hdom-canvas/README.md | 2 ++ packages/hdom-components/README.md | 2 ++ packages/hdom-mock/README.md | 2 ++ packages/hdom/README.md | 4 +++- packages/heaps/README.md | 2 ++ packages/hiccup-canvas/README.md | 2 ++ packages/hiccup-carbon-icons/README.md | 2 ++ packages/hiccup-css/README.md | 4 +++- packages/hiccup-html/README.md | 2 ++ packages/hiccup-markdown/README.md | 2 ++ packages/hiccup-svg/README.md | 2 ++ packages/hiccup/README.md | 4 +++- packages/idgen/README.md | 2 ++ packages/iges/README.md | 2 ++ packages/imgui/README.md | 4 +++- packages/interceptors/README.md | 2 ++ packages/intervals/README.md | 2 ++ packages/iterators/README.md | 2 ++ packages/layout/README.md | 2 ++ packages/leb128/README.md | 2 ++ packages/lsys/README.md | 2 ++ packages/malloc/README.md | 4 +++- packages/math/README.md | 2 ++ packages/matrices/README.md | 2 ++ packages/memoize/README.md | 2 ++ packages/mime/README.md | 2 ++ packages/morton/README.md | 2 ++ packages/oquery/README.md | 4 +++- packages/parse/README.md | 4 +++- packages/paths/README.md | 2 ++ packages/pixel/README.md | 2 ++ packages/pointfree-lang/README.md | 4 +++- packages/pointfree/README.md | 2 ++ packages/poisson/README.md | 2 ++ packages/porter-duff/README.md | 2 ++ packages/prefixes/README.md | 2 ++ packages/quad-edge/README.md | 2 ++ packages/ramp/README.md | 2 ++ packages/random/README.md | 2 ++ packages/range-coder/README.md | 2 ++ packages/rdom-canvas/README.md | 2 ++ packages/rdom-components/README.md | 2 ++ packages/rdom/README.md | 4 +++- packages/resolve-map/README.md | 2 ++ packages/rle-pack/README.md | 2 ++ packages/router/README.md | 2 ++ packages/rstream-csp/README.md | 2 ++ packages/rstream-dot/README.md | 2 ++ packages/rstream-gestures/README.md | 2 ++ packages/rstream-graph/README.md | 4 +++- packages/rstream-log-file/README.md | 2 ++ packages/rstream-log/README.md | 2 ++ packages/rstream-query/README.md | 2 ++ packages/rstream/README.md | 4 +++- packages/sax/README.md | 2 ++ packages/scenegraph/README.md | 4 +++- packages/seq/README.md | 2 ++ packages/sexpr/README.md | 2 ++ packages/shader-ast-glsl/README.md | 2 ++ packages/shader-ast-js/README.md | 2 ++ packages/shader-ast-stdlib/README.md | 2 ++ packages/shader-ast/README.md | 2 ++ packages/simd/README.md | 2 ++ packages/soa/README.md | 2 ++ packages/sparse/README.md | 2 ++ packages/strings/README.md | 4 +++- packages/system/README.md | 2 ++ packages/text-canvas/README.md | 2 ++ packages/transducers-binary/README.md | 2 ++ packages/transducers-fsm/README.md | 2 ++ packages/transducers-hdom/README.md | 2 ++ packages/transducers-patch/README.md | 2 ++ packages/transducers-stats/README.md | 2 ++ packages/transducers/README.md | 4 +++- packages/unionstruct/README.md | 2 ++ packages/vector-pools/README.md | 2 ++ packages/vectors/README.md | 4 +++- packages/viz/README.md | 27 +++++++++++++------------- packages/viz/tpl.readme.md | 25 ++++++++++++------------ packages/webgl-msdf/README.md | 2 ++ packages/webgl-shadertoy/README.md | 2 ++ packages/webgl/README.md | 4 +++- packages/zipper/README.md | 2 ++ 139 files changed, 324 insertions(+), 52 deletions(-) diff --git a/packages/adapt-dpi/README.md b/packages/adapt-dpi/README.md index bf226356f7..004a82fd9d 100644 --- a/packages/adapt-dpi/README.md +++ b/packages/adapt-dpi/README.md @@ -32,6 +32,8 @@ buffer itself based on DPR (e.g. 2x size). **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Badapt-dpi%5D) + ## Installation ```bash diff --git a/packages/adjacency/README.md b/packages/adjacency/README.md index 68fa21f6d8..177f766045 100644 --- a/packages/adjacency/README.md +++ b/packages/adjacency/README.md @@ -26,6 +26,8 @@ Sparse & bitwise adjacency matrices and related functions for directed & undirec **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Badjacency%5D) + ## Installation ```bash diff --git a/packages/api/README.md b/packages/api/README.md index 70ca86b6cf..de563a89f5 100644 --- a/packages/api/README.md +++ b/packages/api/README.md @@ -38,6 +38,8 @@ repository. It defines: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bapi%5D) + ## Installation ```bash diff --git a/packages/arrays/README.md b/packages/arrays/README.md index c52b8a881e..e37caf182f 100644 --- a/packages/arrays/README.md +++ b/packages/arrays/README.md @@ -26,6 +26,8 @@ Array / Arraylike utilities. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Barrays%5D) + ## Installation ```bash diff --git a/packages/associative/README.md b/packages/associative/README.md index 0f15e88529..efe6cb356b 100644 --- a/packages/associative/README.md +++ b/packages/associative/README.md @@ -160,6 +160,8 @@ map.get([3,4], "n/a"); **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bassociative%5D) + ## Installation ```bash @@ -174,7 +176,7 @@ yarn add @thi.ng/associative ``` -Package sizes (gzipped, pre-treeshake): ESM: 6.22 KB / CJS: 6.42 KB / UMD: 6.20 KB +Package sizes (gzipped, pre-treeshake): ESM: 6.23 KB / CJS: 6.42 KB / UMD: 6.20 KB ## Dependencies diff --git a/packages/atom/README.md b/packages/atom/README.md index bf2e6ebde0..221b259069 100644 --- a/packages/atom/README.md +++ b/packages/atom/README.md @@ -55,6 +55,8 @@ reactive updates from performed state changes. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Batom%5D) + ## Breaking changes ### 4.0.0 diff --git a/packages/bench/README.md b/packages/bench/README.md index a57dfa5835..769adfa277 100644 --- a/packages/bench/README.md +++ b/packages/bench/README.md @@ -35,6 +35,8 @@ still only sourced via `Date.now()`. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bbench%5D) + ## Installation ```bash diff --git a/packages/bencode/README.md b/packages/bencode/README.md index 8d4f30a46b..419f45a0a2 100644 --- a/packages/bencode/README.md +++ b/packages/bencode/README.md @@ -52,6 +52,8 @@ semi-open `[1e-6,1e21)` interval can be encoded. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bbencode%5D) + ## Installation ```bash diff --git a/packages/binary/README.md b/packages/binary/README.md index 58c17fc67b..595c7d7787 100644 --- a/packages/binary/README.md +++ b/packages/binary/README.md @@ -26,6 +26,8 @@ This project is part of the **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bbinary%5D) + ## Installation ```bash diff --git a/packages/bitfield/README.md b/packages/bitfield/README.md index 585ac25cbd..1965c3b1c5 100644 --- a/packages/bitfield/README.md +++ b/packages/bitfield/README.md @@ -28,6 +28,8 @@ backing the width is always rounded to a multiple of 32. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bbitfield%5D) + ## Installation ```bash diff --git a/packages/bitstream/README.md b/packages/bitstream/README.md index e3a9d3e004..ecae3c1367 100644 --- a/packages/bitstream/README.md +++ b/packages/bitstream/README.md @@ -27,6 +27,8 @@ ES6 iterator based read/write bit streams with support for variable word widths. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bbitstream%5D) + ## Installation ```bash diff --git a/packages/cache/README.md b/packages/cache/README.md index 2b08068dbc..6114965a2b 100644 --- a/packages/cache/README.md +++ b/packages/cache/README.md @@ -47,6 +47,8 @@ strategies](https://en.wikipedia.org/wiki/Cache_replacement_policies). **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bcache%5D) + ## Installation ```bash diff --git a/packages/checks/README.md b/packages/checks/README.md index 0dc01b5a3e..b6f2cab299 100644 --- a/packages/checks/README.md +++ b/packages/checks/README.md @@ -27,6 +27,8 @@ Collection of 50+ type, feature & value checks. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bchecks%5D) + ## Installation ```bash diff --git a/packages/color/README.md b/packages/color/README.md index e9e5882e71..59ad5330f0 100644 --- a/packages/color/README.md +++ b/packages/color/README.md @@ -176,6 +176,8 @@ col.multiCosineGradient( **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bcolor%5D) + ## Installation ```bash diff --git a/packages/colored-noise/README.md b/packages/colored-noise/README.md index dbe163fa86..574e8cb5d2 100644 --- a/packages/colored-noise/README.md +++ b/packages/colored-noise/README.md @@ -343,6 +343,8 @@ white **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bcolored-noise%5D) + ### Related packages - [@thi.ng/dsp](https://github.com/thi-ng/umbrella/tree/develop/packages/dsp) - Composable signal generators, oscillators, filters, FFT, spectrum, windowing & related DSP utils diff --git a/packages/compare/README.md b/packages/compare/README.md index 829088abda..1c2dc4c662 100644 --- a/packages/compare/README.md +++ b/packages/compare/README.md @@ -36,6 +36,8 @@ comparator. See examples below. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bcompare%5D) + ## Installation ```bash diff --git a/packages/compose/README.md b/packages/compose/README.md index 9c6c9bf2bd..03b715ef08 100644 --- a/packages/compose/README.md +++ b/packages/compose/README.md @@ -25,6 +25,8 @@ Optimized functional composition helpers. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bcompose%5D) + ## Installation ```bash diff --git a/packages/csp/README.md b/packages/csp/README.md index dd3ab7fbdb..46d4846197 100644 --- a/packages/csp/README.md +++ b/packages/csp/README.md @@ -44,6 +44,8 @@ ES6 promise based CSP primitives & operations. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bcsp%5D) + This package might possibly become deprecated soon. See [@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/develop/packages/rstream) for a similar, but alternative (and actively maintained) approach. diff --git a/packages/dcons/README.md b/packages/dcons/README.md index dff6a90e2e..a56529886e 100644 --- a/packages/dcons/README.md +++ b/packages/dcons/README.md @@ -49,6 +49,8 @@ Double-linked list with comprehensive set of operations. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdcons%5D) + ## Installation ```bash diff --git a/packages/defmulti/README.md b/packages/defmulti/README.md index 1103785cec..ffe400a352 100644 --- a/packages/defmulti/README.md +++ b/packages/defmulti/README.md @@ -37,6 +37,8 @@ any actual JS type relationships). **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdefmulti%5D) + ## Installation ```bash diff --git a/packages/dgraph-dot/README.md b/packages/dgraph-dot/README.md index 6f444aff53..66c10a46f3 100644 --- a/packages/dgraph-dot/README.md +++ b/packages/dgraph-dot/README.md @@ -33,6 +33,8 @@ readme & source code for visualization options. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdgraph-dot%5D) + ## Installation ```bash diff --git a/packages/dgraph/README.md b/packages/dgraph/README.md index 91f8f0c282..2fb52f4147 100644 --- a/packages/dgraph/README.md +++ b/packages/dgraph/README.md @@ -37,6 +37,8 @@ maps & sets as backend. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdgraph%5D) + ### Support packages - [@thi.ng/dgraph-dot](https://github.com/thi-ng/umbrella/tree/develop/packages/dgraph-dot) - Customizable Graphviz DOT serialization for [@thi.ng/dgraph](https://github.com/thi-ng/umbrella/tree/develop/packages/dgraph) diff --git a/packages/diff/README.md b/packages/diff/README.md index b807eab840..6693d1558f 100644 --- a/packages/diff/README.md +++ b/packages/diff/README.md @@ -27,6 +27,8 @@ Customizable diff implementations for arrays (sequential) & objects (associative **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdiff%5D) + ## Installation ```bash diff --git a/packages/dl-asset/README.md b/packages/dl-asset/README.md index d71b45081c..43f01cbc99 100644 --- a/packages/dl-asset/README.md +++ b/packages/dl-asset/README.md @@ -26,6 +26,8 @@ Local asset download for web apps, with automatic MIME type detection. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdl-asset%5D) + ## Installation ```bash diff --git a/packages/dlogic/README.md b/packages/dlogic/README.md index bb2e39df37..5e44556e9e 100644 --- a/packages/dlogic/README.md +++ b/packages/dlogic/README.md @@ -32,6 +32,8 @@ for binary versions of most of the ops provided by this package. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdlogic%5D) + ## Installation ```bash diff --git a/packages/dot/README.md b/packages/dot/README.md index 49582f5432..e0fd3aab7a 100644 --- a/packages/dot/README.md +++ b/packages/dot/README.md @@ -37,6 +37,8 @@ details. **BETA** - possibly breaking changes forthcoming +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdot%5D) + ## Installation ```bash diff --git a/packages/dsp-io-wav/README.md b/packages/dsp-io-wav/README.md index c57e564b6b..aeaf6059f3 100644 --- a/packages/dsp-io-wav/README.md +++ b/packages/dsp-io-wav/README.md @@ -25,6 +25,8 @@ WAV file format generation. This is a support package for [@thi.ng/dsp](https:// **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdsp-io-wav%5D) + ## Installation ```bash diff --git a/packages/dsp/README.md b/packages/dsp/README.md index ab53ce9388..3b9722147b 100644 --- a/packages/dsp/README.md +++ b/packages/dsp/README.md @@ -45,6 +45,8 @@ Partially ported from other thi.ng projects (e.g. **BETA** - possibly breaking changes forthcoming +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdsp%5D) + Even though this library is now at v2.0.0 and still retains most of the features from earlier versions, all recently added features (IGen's, IProc's, composition ops etc.) should be considered "beta" and are diff --git a/packages/dual-algebra/README.md b/packages/dual-algebra/README.md index c28ed4142b..c4380dc9a4 100644 --- a/packages/dual-algebra/README.md +++ b/packages/dual-algebra/README.md @@ -109,6 +109,8 @@ are suffixed with `S` (for "scalar"): `quadraticS`, `cubicS` and `quarticS`... **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdual-algebra%5D) + ## Installation ```bash diff --git a/packages/dynvar/README.md b/packages/dynvar/README.md index 62a749eb5a..05866feb67 100644 --- a/packages/dynvar/README.md +++ b/packages/dynvar/README.md @@ -30,6 +30,8 @@ References: **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bdynvar%5D) + ## Installation ```bash diff --git a/packages/ecs/README.md b/packages/ecs/README.md index 21053517e6..072b74e03c 100644 --- a/packages/ecs/README.md +++ b/packages/ecs/README.md @@ -36,6 +36,8 @@ Entity Component System based around typed arrays & sparse sets. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Becs%5D) + ## Installation ```bash diff --git a/packages/egf/README.md b/packages/egf/README.md index ad93c7ee88..70f7c55231 100644 --- a/packages/egf/README.md +++ b/packages/egf/README.md @@ -108,7 +108,7 @@ yarn add @thi.ng/egf ``` -Package sizes (gzipped, pre-treeshake): ESM: 2.70 KB / CJS: 2.77 KB / UMD: 2.78 KB +Package sizes (gzipped, pre-treeshake): ESM: 2.76 KB / CJS: 2.84 KB / UMD: 2.84 KB ## Dependencies diff --git a/packages/equiv/README.md b/packages/equiv/README.md index e902a2705b..dbfe6a4012 100644 --- a/packages/equiv/README.md +++ b/packages/equiv/README.md @@ -38,6 +38,8 @@ Supports: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bequiv%5D) + ## Installation ```bash diff --git a/packages/errors/README.md b/packages/errors/README.md index 43db2d36b7..3959dd54c5 100644 --- a/packages/errors/README.md +++ b/packages/errors/README.md @@ -28,6 +28,8 @@ Additional error types can be defined using **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Berrors%5D) + ## Installation ```bash diff --git a/packages/fsm/README.md b/packages/fsm/README.md index 2bbd948cec..3c4b6ca76b 100644 --- a/packages/fsm/README.md +++ b/packages/fsm/README.md @@ -33,6 +33,8 @@ case. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bfsm%5D) + This package will be merged with and update the existing [@thi.ng/transducers-fsm](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers-fsm) package. diff --git a/packages/geom-accel/README.md b/packages/geom-accel/README.md index b1e60f8541..92f258a5a8 100644 --- a/packages/geom-accel/README.md +++ b/packages/geom-accel/README.md @@ -38,6 +38,8 @@ Currently available: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-accel%5D) + ## Installation ```bash @@ -52,7 +54,7 @@ yarn add @thi.ng/geom-accel ``` -Package sizes (gzipped, pre-treeshake): ESM: 3.76 KB / CJS: 3.82 KB / UMD: 3.83 KB +Package sizes (gzipped, pre-treeshake): ESM: 3.78 KB / CJS: 3.84 KB / UMD: 3.84 KB ## Dependencies diff --git a/packages/geom-api/README.md b/packages/geom-api/README.md index 7d312462cd..e19244acdb 100644 --- a/packages/geom-api/README.md +++ b/packages/geom-api/README.md @@ -25,6 +25,8 @@ Shared type & interface declarations for [@thi.ng/geom](https://github.com/thi-n **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-api%5D) + ## Installation ```bash @@ -39,7 +41,7 @@ yarn add @thi.ng/geom-api ``` -Package sizes (gzipped, pre-treeshake): ESM: 603 bytes / CJS: 627 bytes / UMD: 773 bytes +Package sizes (gzipped, pre-treeshake): ESM: 618 bytes / CJS: 643 bytes / UMD: 791 bytes ## Dependencies diff --git a/packages/geom-arc/README.md b/packages/geom-arc/README.md index 0c443da5a3..eded18185a 100644 --- a/packages/geom-arc/README.md +++ b/packages/geom-arc/README.md @@ -25,6 +25,8 @@ This project is part of the **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-arc%5D) + ## Installation ```bash diff --git a/packages/geom-clip-line/README.md b/packages/geom-clip-line/README.md index aed173e58d..f3ee0a4b1e 100644 --- a/packages/geom-clip-line/README.md +++ b/packages/geom-clip-line/README.md @@ -31,6 +31,8 @@ This package has been extracted from the former (now obsolete) **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-clip-line%5D) + ## Installation ```bash diff --git a/packages/geom-clip-poly/README.md b/packages/geom-clip-poly/README.md index ad03cc6468..d8e2d8894d 100644 --- a/packages/geom-clip-poly/README.md +++ b/packages/geom-clip-poly/README.md @@ -31,6 +31,8 @@ This package has been extracted from the former (now obsolete) **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-clip-poly%5D) + ## Installation ```bash diff --git a/packages/geom-closest-point/README.md b/packages/geom-closest-point/README.md index 95930d0270..82c946896e 100644 --- a/packages/geom-closest-point/README.md +++ b/packages/geom-closest-point/README.md @@ -30,6 +30,8 @@ Current implementations partially based on **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-closest-point%5D) + ## Installation ```bash @@ -44,7 +46,7 @@ yarn add @thi.ng/geom-closest-point ``` -Package sizes (gzipped, pre-treeshake): CJS: 1.10 KB +Package sizes (gzipped, pre-treeshake): ESM: 1.01 KB / CJS: 1.10 KB / UMD: 1.14 KB ## Dependencies diff --git a/packages/geom-fuzz/README.md b/packages/geom-fuzz/README.md index 79325e5909..6a2e7f92e9 100644 --- a/packages/geom-fuzz/README.md +++ b/packages/geom-fuzz/README.md @@ -29,6 +29,8 @@ Highly configurable, fuzzy line & polygon creation with presets and composable f **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-fuzz%5D) + ### Related packages - [@thi.ng/hiccup-canvas](https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup-canvas) - Hiccup shape tree renderer for vanilla Canvas 2D contexts diff --git a/packages/geom-hull/README.md b/packages/geom-hull/README.md index 39aed5ebde..2adebbf564 100644 --- a/packages/geom-hull/README.md +++ b/packages/geom-hull/README.md @@ -29,6 +29,8 @@ Current implementation is partially based on Clojure version of **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-hull%5D) + ## Installation ```bash diff --git a/packages/geom-io-obj/README.md b/packages/geom-io-obj/README.md index c51932833e..94cf3010d3 100644 --- a/packages/geom-io-obj/README.md +++ b/packages/geom-io-obj/README.md @@ -46,6 +46,8 @@ Wavefront OBJ parser (& exporter soon). **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-io-obj%5D) + ## Installation ```bash @@ -60,7 +62,7 @@ yarn add @thi.ng/geom-io-obj ``` -Package sizes (gzipped, pre-treeshake): ESM: 1.02 KB / CJS: 1.07 KB / UMD: 1.20 KB +Package sizes (gzipped, pre-treeshake): ESM: 1.03 KB / CJS: 1.08 KB / UMD: 1.19 KB ## Dependencies diff --git a/packages/geom-isec/README.md b/packages/geom-isec/README.md index 9c8e80a720..8a910c3a7c 100644 --- a/packages/geom-isec/README.md +++ b/packages/geom-isec/README.md @@ -48,6 +48,8 @@ Current implementations partially based on **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-isec%5D) + ## Installation ```bash @@ -62,7 +64,7 @@ yarn add @thi.ng/geom-isec ``` -Package sizes (gzipped, pre-treeshake): ESM: 2.48 KB / CJS: 2.64 KB / UMD: 2.60 KB +Package sizes (gzipped, pre-treeshake): ESM: 2.45 KB / CJS: 2.61 KB / UMD: 2.60 KB ## Dependencies diff --git a/packages/geom-isoline/README.md b/packages/geom-isoline/README.md index 95dc7826cc..e68e1ef270 100644 --- a/packages/geom-isoline/README.md +++ b/packages/geom-isoline/README.md @@ -29,6 +29,8 @@ the Clojure version of **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-isoline%5D) + ## Installation ```bash diff --git a/packages/geom-poly-utils/README.md b/packages/geom-poly-utils/README.md index 4b5eed26b0..745fd6f066 100644 --- a/packages/geom-poly-utils/README.md +++ b/packages/geom-poly-utils/README.md @@ -39,6 +39,8 @@ Current implementations partially based on **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-poly-utils%5D) + ## Installation ```bash diff --git a/packages/geom-resample/README.md b/packages/geom-resample/README.md index f3c9ccb0ca..1284196471 100644 --- a/packages/geom-resample/README.md +++ b/packages/geom-resample/README.md @@ -33,6 +33,8 @@ Current implementations partially based on **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-resample%5D) + ## Installation ```bash @@ -47,7 +49,7 @@ yarn add @thi.ng/geom-resample ``` -Package sizes (gzipped, pre-treeshake): ESM: 1.21 KB / CJS: 1.27 KB / UMD: 1.38 KB +Package sizes (gzipped, pre-treeshake): ESM: 1.18 KB / CJS: 1.24 KB / UMD: 1.35 KB ## Dependencies diff --git a/packages/geom-splines/README.md b/packages/geom-splines/README.md index c5642c9ca6..c74855b2e2 100644 --- a/packages/geom-splines/README.md +++ b/packages/geom-splines/README.md @@ -33,6 +33,8 @@ Current implementations partially based on **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-splines%5D) + ## Installation ```bash diff --git a/packages/geom-subdiv-curve/README.md b/packages/geom-subdiv-curve/README.md index a706ec4667..68b6fc5bff 100644 --- a/packages/geom-subdiv-curve/README.md +++ b/packages/geom-subdiv-curve/README.md @@ -42,6 +42,8 @@ Supplied / implemented subdivision schemes: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-subdiv-curve%5D) + ## Installation ```bash @@ -56,7 +58,7 @@ yarn add @thi.ng/geom-subdiv-curve ``` -Package sizes (gzipped, pre-treeshake): ESM: 640 bytes / CJS: 721 bytes / UMD: 780 bytes +Package sizes (gzipped, pre-treeshake): ESM: 657 bytes / CJS: 734 bytes / UMD: 788 bytes ## Dependencies diff --git a/packages/geom-tessellate/README.md b/packages/geom-tessellate/README.md index c342380dee..31c303ed56 100644 --- a/packages/geom-tessellate/README.md +++ b/packages/geom-tessellate/README.md @@ -37,6 +37,8 @@ highly dependent on the concavities present. YMMV! **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-tessellate%5D) + ## Installation ```bash diff --git a/packages/geom-voronoi/README.md b/packages/geom-voronoi/README.md index bdeddd2d5a..aa8801083b 100644 --- a/packages/geom-voronoi/README.md +++ b/packages/geom-voronoi/README.md @@ -39,6 +39,8 @@ in ~850ms (Chrome 72, MBP 2016) **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom-voronoi%5D) + ## Installation ```bash diff --git a/packages/geom/README.md b/packages/geom/README.md index 00ce1bb0f9..6dfb1a3746 100644 --- a/packages/geom/README.md +++ b/packages/geom/README.md @@ -57,6 +57,8 @@ themselves too): **BETA** - possibly breaking changes forthcoming +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgeom%5D) + ## Installation ```bash @@ -71,7 +73,7 @@ yarn add @thi.ng/geom ``` -Package sizes (gzipped, pre-treeshake): ESM: 10.33 KB / CJS: 10.65 KB / UMD: 10.01 KB +Package sizes (gzipped, pre-treeshake): ESM: 10.42 KB / CJS: 10.76 KB / UMD: 10.11 KB ## Dependencies diff --git a/packages/gp/README.md b/packages/gp/README.md index 40764c0723..f1eb600def 100644 --- a/packages/gp/README.md +++ b/packages/gp/README.md @@ -49,6 +49,8 @@ References: **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgp%5D) + ### Related packages - [@thi.ng/defmulti](https://github.com/thi-ng/umbrella/tree/develop/packages/defmulti) - Dynamic, extensible multiple dispatch via user supplied dispatch function. diff --git a/packages/grid-iterators/README.md b/packages/grid-iterators/README.md index 4c38d22b7d..656415fd5a 100644 --- a/packages/grid-iterators/README.md +++ b/packages/grid-iterators/README.md @@ -151,6 +151,8 @@ Additionally, the following shape iterators are available: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bgrid-iterators%5D) + ### Related packages - [@thi.ng/morton](https://github.com/thi-ng/umbrella/tree/develop/packages/morton) - Z-order curve / Morton encoding, decoding & range extraction for arbitrary dimensions diff --git a/packages/hdiff/README.md b/packages/hdiff/README.md index b3db0fcc52..6b74e1a6e3 100644 --- a/packages/hdiff/README.md +++ b/packages/hdiff/README.md @@ -33,6 +33,8 @@ String diffing w/ hiccup output for further processing, e.g. with [@thi.ng/hdom] **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhdiff%5D) + ## Installation ```bash diff --git a/packages/hdom-canvas/README.md b/packages/hdom-canvas/README.md index 1506218596..24e23261eb 100644 --- a/packages/hdom-canvas/README.md +++ b/packages/hdom-canvas/README.md @@ -43,6 +43,8 @@ API draw calls during the hdom update process / cycle. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhdom-canvas%5D) + ### BREAKING CHANGES 3.0.0 The actual tree traversal & drawing has been extracted to the new diff --git a/packages/hdom-components/README.md b/packages/hdom-components/README.md index ca12279ab1..30ee66c8ac 100644 --- a/packages/hdom-components/README.md +++ b/packages/hdom-components/README.md @@ -41,6 +41,8 @@ components**. Feedback welcome! **BETA** - possibly breaking changes forthcoming +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhdom-components%5D) + ## Installation ```bash diff --git a/packages/hdom-mock/README.md b/packages/hdom-mock/README.md index 7e5115ba5f..418d2061b3 100644 --- a/packages/hdom-mock/README.md +++ b/packages/hdom-mock/README.md @@ -30,6 +30,8 @@ custom target implementations. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhdom-mock%5D) + ## Installation ```bash diff --git a/packages/hdom/README.md b/packages/hdom/README.md index aff7b270b2..5b84cf7f89 100644 --- a/packages/hdom/README.md +++ b/packages/hdom/README.md @@ -100,6 +100,8 @@ Benefits: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhdom%5D) + ### Support packages - [@thi.ng/hdom-canvas](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom-canvas) - [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom) component wrapper for declarative canvas scenegraphs @@ -140,7 +142,7 @@ yarn install yarn start ``` -Package sizes (gzipped, pre-treeshake): ESM: 3.69 KB / CJS: 3.79 KB / UMD: 3.72 KB +Package sizes (gzipped, pre-treeshake): ESM: 3.65 KB / CJS: 3.75 KB / UMD: 3.67 KB ## Dependencies diff --git a/packages/heaps/README.md b/packages/heaps/README.md index 4773334327..840bfc2431 100644 --- a/packages/heaps/README.md +++ b/packages/heaps/README.md @@ -30,6 +30,8 @@ additional operations. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bheaps%5D) + ## Installation ```bash diff --git a/packages/hiccup-canvas/README.md b/packages/hiccup-canvas/README.md index e3b42a298c..accc4b76d1 100644 --- a/packages/hiccup-canvas/README.md +++ b/packages/hiccup-canvas/README.md @@ -65,6 +65,8 @@ implementations) and then translates these into canvas API draw calls. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhiccup-canvas%5D) + ### Related packages - [@thi.ng/hdom-canvas](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom-canvas) - [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom) component wrapper for declarative canvas scenegraphs diff --git a/packages/hiccup-carbon-icons/README.md b/packages/hiccup-carbon-icons/README.md index 2a7c88668b..931307bb15 100644 --- a/packages/hiccup-carbon-icons/README.md +++ b/packages/hiccup-carbon-icons/README.md @@ -43,6 +43,8 @@ code](https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup-carbon-ico **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhiccup-carbon-icons%5D) + ## Installation ```bash diff --git a/packages/hiccup-css/README.md b/packages/hiccup-css/README.md index 91ef92fff2..d94837d8e8 100644 --- a/packages/hiccup-css/README.md +++ b/packages/hiccup-css/README.md @@ -88,6 +88,8 @@ Clojure projects: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhiccup-css%5D) + ## Installation ```bash @@ -102,7 +104,7 @@ yarn add @thi.ng/hiccup-css ``` -Package sizes (gzipped, pre-treeshake): ESM: 2.04 KB / CJS: 2.19 KB / UMD: 2.13 KB +Package sizes (gzipped, pre-treeshake): ESM: 2.05 KB / CJS: 2.21 KB / UMD: 2.13 KB ## Dependencies diff --git a/packages/hiccup-html/README.md b/packages/hiccup-html/README.md index 117e13bd33..8085c8e010 100644 --- a/packages/hiccup-html/README.md +++ b/packages/hiccup-html/README.md @@ -154,6 +154,8 @@ thi.ng/umbrella eco system (most relevant: **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhiccup-html%5D) + The current aim is not necessarily to have wrappers for *each* possible HTML5 element, but certainly to support the most commonly used ones. PRs welcome! diff --git a/packages/hiccup-markdown/README.md b/packages/hiccup-markdown/README.md index a88bcfba7b..471aeb7e14 100644 --- a/packages/hiccup-markdown/README.md +++ b/packages/hiccup-markdown/README.md @@ -40,6 +40,8 @@ parser and an extensible Hiccup-to-Markdown converter. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhiccup-markdown%5D) + ## Installation ```bash diff --git a/packages/hiccup-svg/README.md b/packages/hiccup-svg/README.md index d56745a7b4..68ded07e31 100644 --- a/packages/hiccup-svg/README.md +++ b/packages/hiccup-svg/README.md @@ -115,6 +115,8 @@ therefore need to be complete, e.g. `{ rotate: "rotate(60)" }` **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhiccup-svg%5D) + ## Installation ```bash diff --git a/packages/hiccup/README.md b/packages/hiccup/README.md index 9db4b3a2af..c2785691d5 100644 --- a/packages/hiccup/README.md +++ b/packages/hiccup/README.md @@ -114,6 +114,8 @@ iterable **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bhiccup%5D) + ### Support packages - [@thi.ng/hiccup-canvas](https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup-canvas) - Hiccup shape tree renderer for vanilla Canvas 2D contexts @@ -147,7 +149,7 @@ yarn add @thi.ng/hiccup ``` -Package sizes (gzipped, pre-treeshake): ESM: 2.24 KB / CJS: 2.34 KB / UMD: 2.35 KB +Package sizes (gzipped, pre-treeshake): ESM: 2.28 KB / CJS: 2.39 KB / UMD: 2.41 KB ## Dependencies diff --git a/packages/idgen/README.md b/packages/idgen/README.md index 3c69d0caf6..4f9f58182f 100644 --- a/packages/idgen/README.md +++ b/packages/idgen/README.md @@ -47,6 +47,8 @@ be checked for validity via `.has(id)` (in constant time). **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bidgen%5D) + ## Installation ```bash diff --git a/packages/iges/README.md b/packages/iges/README.md index f548ca5215..2abcd09fb0 100644 --- a/packages/iges/README.md +++ b/packages/iges/README.md @@ -30,6 +30,8 @@ applications (e.g. Rhino, Houdini, Fusion 360) **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Biges%5D) + ## Installation ```bash diff --git a/packages/imgui/README.md b/packages/imgui/README.md index 048a10a3c4..24d600e154 100644 --- a/packages/imgui/README.md +++ b/packages/imgui/README.md @@ -223,6 +223,8 @@ Some of the most obvious missing features: **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bimgui%5D) + ## Installation ```bash @@ -237,7 +239,7 @@ yarn add @thi.ng/imgui ``` -Package sizes (gzipped, pre-treeshake): ESM: 6.64 KB / CJS: 6.83 KB / UMD: 6.94 KB +Package sizes (gzipped, pre-treeshake): ESM: 6.73 KB / CJS: 6.92 KB / UMD: 6.97 KB ## Dependencies diff --git a/packages/interceptors/README.md b/packages/interceptors/README.md index 1a50a968ce..815fd8e321 100644 --- a/packages/interceptors/README.md +++ b/packages/interceptors/README.md @@ -118,6 +118,8 @@ commented source code and examples for now: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Binterceptors%5D) + ## Installation ```bash diff --git a/packages/intervals/README.md b/packages/intervals/README.md index f8d0d4f752..9a3ac24dbf 100644 --- a/packages/intervals/README.md +++ b/packages/intervals/README.md @@ -35,6 +35,8 @@ for details. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bintervals%5D) + ## Installation ```bash diff --git a/packages/iterators/README.md b/packages/iterators/README.md index 86a1ccbea8..31c7bc3750 100644 --- a/packages/iterators/README.md +++ b/packages/iterators/README.md @@ -81,6 +81,8 @@ more composable & efficient transducers via **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Biterators%5D) + ## Installation ```bash diff --git a/packages/layout/README.md b/packages/layout/README.md index 004ffc4982..0ffde9ce30 100644 --- a/packages/layout/README.md +++ b/packages/layout/README.md @@ -32,6 +32,8 @@ to define other layout types / implementations. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Blayout%5D) + ## Installation ```bash diff --git a/packages/leb128/README.md b/packages/leb128/README.md index fecdcd3ad8..8109461129 100644 --- a/packages/leb128/README.md +++ b/packages/leb128/README.md @@ -43,6 +43,8 @@ References: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bleb128%5D) + ## Installation ```bash diff --git a/packages/lsys/README.md b/packages/lsys/README.md index 669a0b2657..90c98de32e 100644 --- a/packages/lsys/README.md +++ b/packages/lsys/README.md @@ -44,6 +44,8 @@ Planned features: **BETA** - possibly breaking changes forthcoming +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Blsys%5D) + ### Blog posts - [Workshop report: Generative design with Clojure](https://medium.com/@thi.ng/workshop-report-generative-design-with-clojure-7d6d8ea9a6e8) diff --git a/packages/malloc/README.md b/packages/malloc/README.md index cae783a5ae..f46c63a41c 100644 --- a/packages/malloc/README.md +++ b/packages/malloc/README.md @@ -123,6 +123,8 @@ capacity: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bmalloc%5D) + ## Installation ```bash @@ -137,7 +139,7 @@ yarn add @thi.ng/malloc ``` -Package sizes (gzipped, pre-treeshake): ESM: 1.80 KB / CJS: 1.86 KB / UMD: 1.86 KB +Package sizes (gzipped, pre-treeshake): ESM: 1.83 KB / CJS: 1.90 KB / UMD: 1.89 KB ## Dependencies diff --git a/packages/math/README.md b/packages/math/README.md index a27424790a..8d7dba61f2 100644 --- a/packages/math/README.md +++ b/packages/math/README.md @@ -32,6 +32,8 @@ Partially ported from Clojure version of **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bmath%5D) + ## Installation ```bash diff --git a/packages/matrices/README.md b/packages/matrices/README.md index d36f272708..7804cf37c7 100644 --- a/packages/matrices/README.md +++ b/packages/matrices/README.md @@ -52,6 +52,8 @@ sensible). **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bmatrices%5D) + ### Related packages - [@thi.ng/color](https://github.com/thi-ng/umbrella/tree/develop/packages/color) - Array-based color ops, conversions, multi-color gradients, presets diff --git a/packages/memoize/README.md b/packages/memoize/README.md index 27154e4ede..e1739219a7 100644 --- a/packages/memoize/README.md +++ b/packages/memoize/README.md @@ -40,6 +40,8 @@ based on different strategies. See doc strings for further details. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bmemoize%5D) + ## Installation ```bash diff --git a/packages/mime/README.md b/packages/mime/README.md index c0052f2eba..d3b54cd937 100644 --- a/packages/mime/README.md +++ b/packages/mime/README.md @@ -28,6 +28,8 @@ All MIME type mappings based on **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bmime%5D) + ## Installation ```bash diff --git a/packages/morton/README.md b/packages/morton/README.md index 6dba757c1b..d73ccacd75 100644 --- a/packages/morton/README.md +++ b/packages/morton/README.md @@ -36,6 +36,8 @@ References: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bmorton%5D) + ### Related packages - [@thi.ng/grid-iterators](https://github.com/thi-ng/umbrella/tree/develop/packages/grid-iterators) - 2D grid iterators w/ multiple orderings diff --git a/packages/oquery/README.md b/packages/oquery/README.md index 67413fd132..fa8a4ff681 100644 --- a/packages/oquery/README.md +++ b/packages/oquery/README.md @@ -42,6 +42,8 @@ See basic query examples below... **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Boquery%5D) + ### Related packages - [@thi.ng/rstream-query](https://github.com/thi-ng/umbrella/tree/develop/packages/rstream-query) - [@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/develop/packages/rstream) based triple store & reactive query engine @@ -60,7 +62,7 @@ yarn add @thi.ng/oquery ``` -Package sizes (gzipped, pre-treeshake): ESM: 823 bytes / CJS: 883 bytes / UMD: 957 bytes +Package sizes (gzipped, pre-treeshake): ESM: 846 bytes / CJS: 903 bytes / UMD: 962 bytes ## Dependencies diff --git a/packages/parse/README.md b/packages/parse/README.md index af432e0016..12eae18f6e 100644 --- a/packages/parse/README.md +++ b/packages/parse/README.md @@ -60,6 +60,8 @@ Purely functional parser combinators & AST generation for generic inputs. **BETA** - possibly breaking changes forthcoming +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bparse%5D) + ### Related packages - [@thi.ng/fsm](https://github.com/thi-ng/umbrella/tree/develop/packages/fsm) - Composable primitives for building declarative, transducer based Finite-State Machines & matchers for arbitrary data streams @@ -79,7 +81,7 @@ yarn add @thi.ng/parse ``` -Package sizes (gzipped, pre-treeshake): ESM: 5.27 KB / CJS: 5.65 KB / UMD: 5.31 KB +Package sizes (gzipped, pre-treeshake): ESM: 5.23 KB / CJS: 5.62 KB / UMD: 5.29 KB ## Dependencies diff --git a/packages/paths/README.md b/packages/paths/README.md index c5826fe2e2..1407c4a333 100644 --- a/packages/paths/README.md +++ b/packages/paths/README.md @@ -39,6 +39,8 @@ Immutable, optimized and optionally typed path-based object property / array acc **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bpaths%5D) + ## Breaking changes ### 4.0.0 diff --git a/packages/pixel/README.md b/packages/pixel/README.md index 9794e388aa..de751ff733 100644 --- a/packages/pixel/README.md +++ b/packages/pixel/README.md @@ -113,6 +113,8 @@ formats can be defined via `defFloatFormat()`. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bpixel%5D) + ### Related packages - [@thi.ng/porter-duff](https://github.com/thi-ng/umbrella/tree/develop/packages/porter-duff) - Porter-Duff operators for packed ints & float-array alpha compositing diff --git a/packages/pointfree-lang/README.md b/packages/pointfree-lang/README.md index 9fe9553c8a..59de05fcb2 100644 --- a/packages/pointfree-lang/README.md +++ b/packages/pointfree-lang/README.md @@ -64,6 +64,8 @@ an ES6 embedded DSL for concatenative programming: **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bpointfree-lang%5D) + ## Installation ```bash @@ -78,7 +80,7 @@ yarn add @thi.ng/pointfree-lang ``` -Package sizes (gzipped, pre-treeshake): ESM: 5.29 KB / CJS: 5.29 KB / UMD: 5.20 KB +Package sizes (gzipped, pre-treeshake): ESM: 5.30 KB / CJS: 5.30 KB / UMD: 5.21 KB ## Dependencies diff --git a/packages/pointfree/README.md b/packages/pointfree/README.md index efc84a9123..cf55933585 100644 --- a/packages/pointfree/README.md +++ b/packages/pointfree/README.md @@ -186,6 +186,8 @@ non-linear control flow. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bpointfree%5D) + ### Support packages - [@thi.ng/pointfree-lang](https://github.com/thi-ng/umbrella/tree/develop/packages/pointfree-lang) - Forth style syntax layer/compiler & CLI for the [@thi.ng/pointfree](https://github.com/thi-ng/umbrella/tree/develop/packages/pointfree) DSL diff --git a/packages/poisson/README.md b/packages/poisson/README.md index 90c1e682e6..d7a718ed59 100644 --- a/packages/poisson/README.md +++ b/packages/poisson/README.md @@ -43,6 +43,8 @@ indices are supported as well... **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bpoisson%5D) + ### Related packages - [@thi.ng/geom-voronoi](https://github.com/thi-ng/umbrella/tree/develop/packages/geom-voronoi) - Fast, incremental 2D Delaunay & Voronoi mesh implementation diff --git a/packages/porter-duff/README.md b/packages/porter-duff/README.md index bf343936bb..7e3694a245 100644 --- a/packages/porter-duff/README.md +++ b/packages/porter-duff/README.md @@ -47,6 +47,8 @@ ints or RGBA float vectors. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bporter-duff%5D) + ### Related packages - [@thi.ng/pixel](https://github.com/thi-ng/umbrella/tree/develop/packages/pixel) - Typed array backed, packed integer and unpacked floating point pixel buffers w/ customizable formats, blitting, dithering, conversions diff --git a/packages/prefixes/README.md b/packages/prefixes/README.md index 4edefe8982..218bb333cb 100644 --- a/packages/prefixes/README.md +++ b/packages/prefixes/README.md @@ -26,6 +26,8 @@ This project is part of the **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bprefixes%5D) + ## Installation ```bash diff --git a/packages/quad-edge/README.md b/packages/quad-edge/README.md index f7e578c027..25f3c484ef 100644 --- a/packages/quad-edge/README.md +++ b/packages/quad-edge/README.md @@ -39,6 +39,8 @@ Reference: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bquad-edge%5D) + ### Related packages - [@thi.ng/geom-voronoi](https://github.com/thi-ng/umbrella/tree/develop/packages/geom-voronoi) - Fast, incremental 2D Delaunay & Voronoi mesh implementation diff --git a/packages/ramp/README.md b/packages/ramp/README.md index 4b9a94193b..501331a668 100644 --- a/packages/ramp/README.md +++ b/packages/ramp/README.md @@ -26,6 +26,8 @@ Parametric interpolated 1D lookup tables for remapping values. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bramp%5D) + ## Installation ```bash diff --git a/packages/random/README.md b/packages/random/README.md index 163b7e2f03..c8495ee9e7 100644 --- a/packages/random/README.md +++ b/packages/random/README.md @@ -41,6 +41,8 @@ Partially ported from C implementations taken from **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brandom%5D) + ## Installation ```bash diff --git a/packages/range-coder/README.md b/packages/range-coder/README.md index 942babfcac..43f0136a06 100644 --- a/packages/range-coder/README.md +++ b/packages/range-coder/README.md @@ -27,6 +27,8 @@ by Joe Halliwell](https://www.winterwell.com/software/compressor.php). **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brange-coder%5D) + ### Related packages - [@thi.ng/bitstream](https://github.com/thi-ng/umbrella/tree/develop/packages/bitstream) - ES6 iterator based read/write bit streams with support for variable word widths diff --git a/packages/rdom-canvas/README.md b/packages/rdom-canvas/README.md index 3e9946f4fa..7b451b457b 100644 --- a/packages/rdom-canvas/README.md +++ b/packages/rdom-canvas/README.md @@ -27,6 +27,8 @@ This project is part of the **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brdom-canvas%5D) + ### Related packages - [@thi.ng/hiccup-canvas](https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup-canvas) - Hiccup shape tree renderer for vanilla Canvas 2D contexts diff --git a/packages/rdom-components/README.md b/packages/rdom-components/README.md index 8e22b78a8c..1480551c31 100644 --- a/packages/rdom-components/README.md +++ b/packages/rdom-components/README.md @@ -34,6 +34,8 @@ Currently, this package provides: **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brdom-components%5D) + ## Installation ```bash diff --git a/packages/rdom/README.md b/packages/rdom/README.md index 555d9cb860..f8e6f330ff 100644 --- a/packages/rdom/README.md +++ b/packages/rdom/README.md @@ -29,6 +29,8 @@ Lightweight, reactive, VDOM-less UI/DOM components with async lifecycle and [@th **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brdom%5D) + #### HIC SUNT DRACONES This is still a young project. Even though most of the overall approach, @@ -72,7 +74,7 @@ yarn add @thi.ng/rdom ``` -Package sizes (gzipped, pre-treeshake): ESM: 3.75 KB / CJS: 3.89 KB / UMD: 3.86 KB +Package sizes (gzipped, pre-treeshake): ESM: 3.71 KB / CJS: 3.86 KB / UMD: 3.84 KB ## Dependencies diff --git a/packages/resolve-map/README.md b/packages/resolve-map/README.md index 2b2cd24331..801b55524e 100644 --- a/packages/resolve-map/README.md +++ b/packages/resolve-map/README.md @@ -44,6 +44,8 @@ supported. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bresolve-map%5D) + ## Installation ```bash diff --git a/packages/rle-pack/README.md b/packages/rle-pack/README.md index 3f8a3853b6..2d99b97729 100644 --- a/packages/rle-pack/README.md +++ b/packages/rle-pack/README.md @@ -53,6 +53,8 @@ Then per value: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brle-pack%5D) + ### Related packages - [@thi.ng/bitstream](https://github.com/thi-ng/umbrella/tree/develop/packages/bitstream) - ES6 iterator based read/write bit streams with support for variable word widths diff --git a/packages/router/README.md b/packages/router/README.md index e77580bd50..1d9889f75e 100644 --- a/packages/router/README.md +++ b/packages/router/README.md @@ -39,6 +39,8 @@ Partially based on the Clojure implementation in **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brouter%5D) + ## Installation ```bash diff --git a/packages/rstream-csp/README.md b/packages/rstream-csp/README.md index aa4ebe8a93..723c408a50 100644 --- a/packages/rstream-csp/README.md +++ b/packages/rstream-csp/README.md @@ -29,6 +29,8 @@ and synchronous stream subscriptions/transformations of **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brstream-csp%5D) + ### Related packages - [@thi.ng/csp](https://github.com/thi-ng/umbrella/tree/develop/packages/csp) - ES6 promise based CSP primitives & operations diff --git a/packages/rstream-dot/README.md b/packages/rstream-dot/README.md index 4807004b32..320b420ea4 100644 --- a/packages/rstream-dot/README.md +++ b/packages/rstream-dot/README.md @@ -26,6 +26,8 @@ Graphviz DOT conversion of [@thi.ng/rstream](https://github.com/thi-ng/umbrella/ **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brstream-dot%5D) + ### Related packages - [@thi.ng/dot](https://github.com/thi-ng/umbrella/tree/develop/packages/dot) - Graphviz document abstraction & serialization to DOT format diff --git a/packages/rstream-gestures/README.md b/packages/rstream-gestures/README.md index 76f0f8b9af..716807b6b8 100644 --- a/packages/rstream-gestures/README.md +++ b/packages/rstream-gestures/README.md @@ -33,6 +33,8 @@ Unified mouse, mouse wheel & multi-touch event stream abstraction. This is a sup **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brstream-gestures%5D) + ### Breaking changes Multi-touch support has been added in v2.0.0, resulting in a complete diff --git a/packages/rstream-graph/README.md b/packages/rstream-graph/README.md index d4e6d0ed1f..eda66da10e 100644 --- a/packages/rstream-graph/README.md +++ b/packages/rstream-graph/README.md @@ -40,6 +40,8 @@ these and keep any cycles async). **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brstream-graph%5D) + ## Installation ```bash @@ -54,7 +56,7 @@ yarn add @thi.ng/rstream-graph ``` -Package sizes (gzipped, pre-treeshake): ESM: 1.03 KB / CJS: 1.13 KB / UMD: 1.17 KB +Package sizes (gzipped, pre-treeshake): ESM: 1.04 KB / CJS: 1.14 KB / UMD: 1.19 KB ## Dependencies diff --git a/packages/rstream-log-file/README.md b/packages/rstream-log-file/README.md index d5ce1fd5aa..a6457f3271 100644 --- a/packages/rstream-log-file/README.md +++ b/packages/rstream-log-file/README.md @@ -25,6 +25,8 @@ File output handler for structured, multilevel & hierarchical loggers based on [ **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brstream-log-file%5D) + ## Installation ```bash diff --git a/packages/rstream-log/README.md b/packages/rstream-log/README.md index 394f80836b..c896e01371 100644 --- a/packages/rstream-log/README.md +++ b/packages/rstream-log/README.md @@ -36,6 +36,8 @@ filtering. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brstream-log%5D) + ### Support packages - [@thi.ng/rstream-log-file](https://github.com/thi-ng/umbrella/tree/develop/packages/rstream-log-file) - File output handler for structured, multilevel & hierarchical loggers based on [@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/develop/packages/rstream) diff --git a/packages/rstream-query/README.md b/packages/rstream-query/README.md index cf12265f6b..dc350ad183 100644 --- a/packages/rstream-query/README.md +++ b/packages/rstream-query/README.md @@ -55,6 +55,8 @@ feature is currently WIP). **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brstream-query%5D) + This project is currently still in early development and intended as a continuation of the Clojure based [thi.ng/fabric](http://thi.ng/fabric), this time built on the streaming primitives provided by diff --git a/packages/rstream/README.md b/packages/rstream/README.md index 19ddf1439f..2d63854926 100644 --- a/packages/rstream/README.md +++ b/packages/rstream/README.md @@ -100,6 +100,8 @@ programming: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Brstream%5D) + ### Breaking changes in 5.0.0 Type inference for `sync()` (aka `StreamSync`), one of the main pillars of this @@ -180,7 +182,7 @@ yarn add @thi.ng/rstream ``` -Package sizes (gzipped, pre-treeshake): ESM: 5.40 KB / CJS: 5.58 KB / UMD: 5.54 KB +Package sizes (gzipped, pre-treeshake): ESM: 5.41 KB / CJS: 5.60 KB / UMD: 5.54 KB ## Dependencies diff --git a/packages/sax/README.md b/packages/sax/README.md index c77d28920b..48e9671903 100644 --- a/packages/sax/README.md +++ b/packages/sax/README.md @@ -48,6 +48,8 @@ well (see SVG parsing example further below). The choice is yours! **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bsax%5D) + ### Related packages - [@thi.ng/hiccup-svg](https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup-svg) - SVG element functions for [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup) & [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom) diff --git a/packages/scenegraph/README.md b/packages/scenegraph/README.md index 3ba37b7e82..d7e4e5c288 100644 --- a/packages/scenegraph/README.md +++ b/packages/scenegraph/README.md @@ -26,6 +26,8 @@ Extensible 2D/3D scene graph with [@thi.ng/hiccup-canvas](https://github.com/thi **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bscenegraph%5D) + ## Installation ```bash @@ -40,7 +42,7 @@ yarn add @thi.ng/scenegraph ``` -Package sizes (gzipped, pre-treeshake): ESM: 881 bytes / CJS: 923 bytes / UMD: 1.01 KB +Package sizes (gzipped, pre-treeshake): ESM: 898 bytes / CJS: 937 bytes / UMD: 1.03 KB ## Dependencies diff --git a/packages/seq/README.md b/packages/seq/README.md index afc6efbddb..22434872ae 100644 --- a/packages/seq/README.md +++ b/packages/seq/README.md @@ -38,6 +38,8 @@ the remaining values at their own pace. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bseq%5D) + ## Installation ```bash diff --git a/packages/sexpr/README.md b/packages/sexpr/README.md index 7537601cfc..ea4139c728 100644 --- a/packages/sexpr/README.md +++ b/packages/sexpr/README.md @@ -42,6 +42,8 @@ Everything else is parsed as is, i.e. as symbol. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bsexpr%5D) + ## Installation ```bash diff --git a/packages/shader-ast-glsl/README.md b/packages/shader-ast-glsl/README.md index 8191e17b9f..c51039f676 100644 --- a/packages/shader-ast-glsl/README.md +++ b/packages/shader-ast-glsl/README.md @@ -33,6 +33,8 @@ This package is also used for shader assembly by **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bshader-ast-glsl%5D) + ### Related packages - [@thi.ng/shader-ast-js](https://github.com/thi-ng/umbrella/tree/develop/packages/shader-ast-js) - Customizable JS codegen, compiler & runtime for [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/develop/packages/shader-ast) diff --git a/packages/shader-ast-js/README.md b/packages/shader-ast-js/README.md index 020ae183fe..3a6da2bd89 100644 --- a/packages/shader-ast-js/README.md +++ b/packages/shader-ast-js/README.md @@ -48,6 +48,8 @@ which altogether provide ~750 optimized vector/matrix functions. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bshader-ast-js%5D) + ### Related packages - [@thi.ng/shader-ast-glsl](https://github.com/thi-ng/umbrella/tree/develop/packages/shader-ast-glsl) - Customizable GLSL codegen for [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/develop/packages/shader-ast) diff --git a/packages/shader-ast-stdlib/README.md b/packages/shader-ast-stdlib/README.md index 5ff5852830..5691d875d1 100644 --- a/packages/shader-ast-stdlib/README.md +++ b/packages/shader-ast-stdlib/README.md @@ -68,6 +68,8 @@ Reference: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bshader-ast-stdlib%5D) + ### Related packages - [@thi.ng/shader-ast-glsl](https://github.com/thi-ng/umbrella/tree/develop/packages/shader-ast-glsl) - Customizable GLSL codegen for [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/develop/packages/shader-ast) diff --git a/packages/shader-ast/README.md b/packages/shader-ast/README.md index e5f7093d19..92ed8bdbb5 100644 --- a/packages/shader-ast/README.md +++ b/packages/shader-ast/README.md @@ -156,6 +156,8 @@ status. The TL;DR list... **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bshader-ast%5D) + ### Support packages - [@thi.ng/shader-ast-glsl](https://github.com/thi-ng/umbrella/tree/develop/packages/shader-ast-glsl) - Customizable GLSL codegen for [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/develop/packages/shader-ast) diff --git a/packages/simd/README.md b/packages/simd/README.md index 1c88cccf76..f85f1ec0c9 100644 --- a/packages/simd/README.md +++ b/packages/simd/README.md @@ -82,6 +82,8 @@ for documentation about the exposed TS/JS API... **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bsimd%5D) + The [WebAssembly SIMD spec](https://github.com/WebAssembly/simd) is still WIP and (at the time of writing) only partially implemented and hidden behind feature flags. Currently only fully tested (& testable for diff --git a/packages/soa/README.md b/packages/soa/README.md index f73b3b1ba6..5796895c06 100644 --- a/packages/soa/README.md +++ b/packages/soa/README.md @@ -27,6 +27,8 @@ SOA & AOS memory mapped structured views with optional & extensible serializatio **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bsoa%5D) + See tests for usage. This package might be merged with and/or superseded by [@thi.ng/ecs](https://github.com/thi-ng/umbrella/tree/develop/packages/ecs). diff --git a/packages/sparse/README.md b/packages/sparse/README.md index a4e177179e..9871f5b57c 100644 --- a/packages/sparse/README.md +++ b/packages/sparse/README.md @@ -25,6 +25,8 @@ Sparse vector & matrix implementations. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bsparse%5D) + ## Installation ```bash diff --git a/packages/strings/README.md b/packages/strings/README.md index d1bdec1f55..2df0101f5e 100644 --- a/packages/strings/README.md +++ b/packages/strings/README.md @@ -36,6 +36,8 @@ Partially based on Clojure version of [thi.ng/strf](http://thi.ng/strf). **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bstrings%5D) + ## Installation ```bash @@ -50,7 +52,7 @@ yarn add @thi.ng/strings ``` -Package sizes (gzipped, pre-treeshake): ESM: 2.44 KB / CJS: 2.67 KB / UMD: 2.55 KB +Package sizes (gzipped, pre-treeshake): ESM: 2.72 KB / CJS: 2.97 KB / UMD: 2.84 KB ## Dependencies diff --git a/packages/system/README.md b/packages/system/README.md index a4ffccb661..46f84442b2 100644 --- a/packages/system/README.md +++ b/packages/system/README.md @@ -33,6 +33,8 @@ Clojure/ClojureScript. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bsystem%5D) + ## Installation ```bash diff --git a/packages/text-canvas/README.md b/packages/text-canvas/README.md index 28cfaa5454..fdd2e94493 100644 --- a/packages/text-canvas/README.md +++ b/packages/text-canvas/README.md @@ -40,6 +40,8 @@ Text based canvas, drawing, tables with arbitrary formatting (incl. ANSI/HTML). **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Btext-canvas%5D) + ## Installation ```bash diff --git a/packages/transducers-binary/README.md b/packages/transducers-binary/README.md index 8c94053fb5..e3a6ea49df 100644 --- a/packages/transducers-binary/README.md +++ b/packages/transducers-binary/README.md @@ -39,6 +39,8 @@ iterable for direct use. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Btransducers-binary%5D) + ### Related packages - [@thi.ng/binary](https://github.com/thi-ng/umbrella/tree/develop/packages/binary) - 95+ assorted binary / bitwise operations, conversions, utilities diff --git a/packages/transducers-fsm/README.md b/packages/transducers-fsm/README.md index 2c0e784ea5..5b0a3ec41c 100644 --- a/packages/transducers-fsm/README.md +++ b/packages/transducers-fsm/README.md @@ -35,6 +35,8 @@ transformation pipeline. **BETA** - possibly breaking changes forthcoming +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Btransducers-fsm%5D) + This package might be merged with (or deprecated by) the newer [@thi.ng/fsm](https://github.com/thi-ng/umbrella/tree/develop/packages/fsm) package. diff --git a/packages/transducers-hdom/README.md b/packages/transducers-hdom/README.md index b0b2d93d46..4401c6104d 100644 --- a/packages/transducers-hdom/README.md +++ b/packages/transducers-hdom/README.md @@ -55,6 +55,8 @@ Please also see the following hdom references for further details: **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Btransducers-hdom%5D) + ### Related packages - [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom) - Lightweight vanilla ES6 UI component trees with customizable branch-local behaviors diff --git a/packages/transducers-patch/README.md b/packages/transducers-patch/README.md index 63c35fb4df..9826d4777d 100644 --- a/packages/transducers-patch/README.md +++ b/packages/transducers-patch/README.md @@ -32,6 +32,8 @@ state update. By default all edits are performed non-destructively, but **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Btransducers-patch%5D) + ## Installation ```bash diff --git a/packages/transducers-stats/README.md b/packages/transducers-stats/README.md index 3f67d93b97..359c8953cf 100644 --- a/packages/transducers-stats/README.md +++ b/packages/transducers-stats/README.md @@ -56,6 +56,8 @@ transforming ES6 iterator (generator) instead of a transducer. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Btransducers-stats%5D) + ## Installation ```bash diff --git a/packages/transducers/README.md b/packages/transducers/README.md index 9f631ee60d..3189a54d5e 100644 --- a/packages/transducers/README.md +++ b/packages/transducers/README.md @@ -83,6 +83,8 @@ a reduced result of the given input iterable. **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Btransducers%5D) + ### 7.0.0 release Thanks to a [PR](https://github.com/thi-ng/umbrella/pull/223) and @@ -165,7 +167,7 @@ yarn add @thi.ng/transducers ``` -Package sizes (gzipped, pre-treeshake): ESM: 8.14 KB / CJS: 8.69 KB / UMD: 7.88 KB +Package sizes (gzipped, pre-treeshake): ESM: 8.17 KB / CJS: 8.71 KB / UMD: 7.89 KB ## Dependencies diff --git a/packages/unionstruct/README.md b/packages/unionstruct/README.md index 38362d036a..14c329eee5 100644 --- a/packages/unionstruct/README.md +++ b/packages/unionstruct/README.md @@ -44,6 +44,8 @@ Currently does not support array fields (incl. strings). **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bunionstruct%5D) + ## Installation ```bash diff --git a/packages/vector-pools/README.md b/packages/vector-pools/README.md index 17bb773419..db81ea5a55 100644 --- a/packages/vector-pools/README.md +++ b/packages/vector-pools/README.md @@ -39,6 +39,8 @@ region of a WebGL or WASM memory buffer. **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bvector-pools%5D) + This package might be merged with and/or superseded by [@thi.ng/ecs](https://github.com/thi-ng/umbrella/tree/develop/packages/ecs) / diff --git a/packages/vectors/README.md b/packages/vectors/README.md index 333cd0773f..0cec59b098 100644 --- a/packages/vectors/README.md +++ b/packages/vectors/README.md @@ -115,6 +115,8 @@ Partially ported from [thi.ng/geom](http://thi.ng/geom) (Clojure) and **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bvectors%5D) + ### Breaking changes in v3.0.0 - to avoid confusion, the arg order of `madd` and `maddN` functions have @@ -153,7 +155,7 @@ yarn add @thi.ng/vectors ``` -Package sizes (gzipped, pre-treeshake): ESM: 11.14 KB / CJS: 14.02 KB / UMD: 12.38 KB +Package sizes (gzipped, pre-treeshake): ESM: 11.15 KB / CJS: 14.03 KB / UMD: 12.40 KB ## Dependencies diff --git a/packages/viz/README.md b/packages/viz/README.md index 104680a909..6d7c605610 100644 --- a/packages/viz/README.md +++ b/packages/viz/README.md @@ -30,33 +30,34 @@ For reference & what to expect (links to the Clojure version): - [Examples](https://github.com/thi-ng/geom/blob/feature/no-org/org/examples/viz/demos.org) - [Source](https://github.com/thi-ng/geom/blob/feature/no-org/org/src/viz/core.org) -| Example outputs | | -|---------------------------------------------------------------|---------------------------------------------------------| +| Example outputs | | +|----------------------------------------------------------------|----------------------------------------------------------| | ![](https://media.thi.ng/geom/viz/scatter-linear-3.svg) | ![](https://media.thi.ng/geom/viz/scatter-log-3.svg) | -| Logarithmic X-axis, linear Y | Log X, Log Y | +| Logarithmic X-axis, linear Y | Log X, Log Y | | ![](https://media.thi.ng/geom/viz/lineplot-3.svg) | ![](https://media.thi.ng/geom/viz/areaplot-3.svg) | -| Line plot (cartesian) | Area plot (cartesian) | +| Line plot (cartesian) | Area plot (cartesian) | | ![](https://media.thi.ng/geom/viz/lineplot-polar-3.svg) | ![](https://media.thi.ng/geom/viz/areaplot-polar-3.svg) | -| Line plot (polar) | Area plot (polar) | +| Line plot (polar) | Area plot (polar) | | ![](https://media.thi.ng/geom/viz/bars-3.svg) | ![](https://media.thi.ng/geom/viz/bars-interleave-3.svg) | -| Single value per domain position | 3 interleaved values (datasets) per domain position | +| Single value per domain position | 3 interleaved values (datasets) per domain position | | ![](https://media.thi.ng/geom/viz/radarplot-3.svg) | ![](https://media.thi.ng/geom/viz/radarplot-minmax.svg) | -| 6 categories, 3 data sets, single values | 6 categories, 3 data sets, min-max intervals | +| 6 categories, 3 data sets, single values | 6 categories, 3 data sets, min-max intervals | | ![](https://media.thi.ng/geom/viz/hm-rainbow2.svg) | ![](https://media.thi.ng/geom/viz/hm-orange-blue.svg) | -| Heatmap w/ rainbow gradient presets | | +| Heatmap w/ rainbow gradient presets | | | ![](https://media.thi.ng/geom/viz/hmp-yellow-magenta-cyan.svg) | ![](https://media.thi.ng/geom/viz/hmp-green-magenta.svg) | -| Heatmap polar projection | | +| Heatmap polar projection | | | ![](https://media.thi.ng/geom/viz/hms-rainbow2.svg) | ![](https://media.thi.ng/geom/viz/hmsp-rainbow2.svg) | -| w/ custom shape fn | polar projection, custom shape fn | +| w/ custom shape fn | polar projection, custom shape fn | | ![](https://media.thi.ng/geom/viz/contours-4.svg) | ![](https://media.thi.ng/geom/viz/terrain-6.svg) | -| Contour plot | | - -![](https://media.thi.ng/geom/viz/timeline-3.svg) +| Contour plot | | +| ![](https://media.thi.ng/geom/viz/timeline-3.svg) | | ### Status **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bviz%5D) + ## Installation ```bash diff --git a/packages/viz/tpl.readme.md b/packages/viz/tpl.readme.md index 47e25333ff..c22bb19a00 100644 --- a/packages/viz/tpl.readme.md +++ b/packages/viz/tpl.readme.md @@ -22,28 +22,27 @@ For reference & what to expect (links to the Clojure version): - [Examples](https://github.com/thi-ng/geom/blob/feature/no-org/org/examples/viz/demos.org) - [Source](https://github.com/thi-ng/geom/blob/feature/no-org/org/src/viz/core.org) -| Example outputs | | -|---------------------------------------------------------------|---------------------------------------------------------| +| Example outputs | | +|----------------------------------------------------------------|----------------------------------------------------------| | ![](https://media.thi.ng/geom/viz/scatter-linear-3.svg) | ![](https://media.thi.ng/geom/viz/scatter-log-3.svg) | -| Logarithmic X-axis, linear Y | Log X, Log Y | +| Logarithmic X-axis, linear Y | Log X, Log Y | | ![](https://media.thi.ng/geom/viz/lineplot-3.svg) | ![](https://media.thi.ng/geom/viz/areaplot-3.svg) | -| Line plot (cartesian) | Area plot (cartesian) | +| Line plot (cartesian) | Area plot (cartesian) | | ![](https://media.thi.ng/geom/viz/lineplot-polar-3.svg) | ![](https://media.thi.ng/geom/viz/areaplot-polar-3.svg) | -| Line plot (polar) | Area plot (polar) | +| Line plot (polar) | Area plot (polar) | | ![](https://media.thi.ng/geom/viz/bars-3.svg) | ![](https://media.thi.ng/geom/viz/bars-interleave-3.svg) | -| Single value per domain position | 3 interleaved values (datasets) per domain position | +| Single value per domain position | 3 interleaved values (datasets) per domain position | | ![](https://media.thi.ng/geom/viz/radarplot-3.svg) | ![](https://media.thi.ng/geom/viz/radarplot-minmax.svg) | -| 6 categories, 3 data sets, single values | 6 categories, 3 data sets, min-max intervals | +| 6 categories, 3 data sets, single values | 6 categories, 3 data sets, min-max intervals | | ![](https://media.thi.ng/geom/viz/hm-rainbow2.svg) | ![](https://media.thi.ng/geom/viz/hm-orange-blue.svg) | -| Heatmap w/ rainbow gradient presets | | +| Heatmap w/ rainbow gradient presets | | | ![](https://media.thi.ng/geom/viz/hmp-yellow-magenta-cyan.svg) | ![](https://media.thi.ng/geom/viz/hmp-green-magenta.svg) | -| Heatmap polar projection | | +| Heatmap polar projection | | | ![](https://media.thi.ng/geom/viz/hms-rainbow2.svg) | ![](https://media.thi.ng/geom/viz/hmsp-rainbow2.svg) | -| w/ custom shape fn | polar projection, custom shape fn | +| w/ custom shape fn | polar projection, custom shape fn | | ![](https://media.thi.ng/geom/viz/contours-4.svg) | ![](https://media.thi.ng/geom/viz/terrain-6.svg) | -| Contour plot | | - -![](https://media.thi.ng/geom/viz/timeline-3.svg) +| Contour plot | | +| ![](https://media.thi.ng/geom/viz/timeline-3.svg) | | ${status} diff --git a/packages/webgl-msdf/README.md b/packages/webgl-msdf/README.md index 2fc980ea0c..3d2fbf89f0 100644 --- a/packages/webgl-msdf/README.md +++ b/packages/webgl-msdf/README.md @@ -39,6 +39,8 @@ McCurdy's](https://msdf-bmfont.donmccurdy.com/). **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bwebgl-msdf%5D) + ## Installation ```bash diff --git a/packages/webgl-shadertoy/README.md b/packages/webgl-shadertoy/README.md index 81bcb96fe2..e0dcf7b1ea 100644 --- a/packages/webgl-shadertoy/README.md +++ b/packages/webgl-shadertoy/README.md @@ -27,6 +27,8 @@ Basic WebGL scaffolding for running interactive fragment shaders via [@thi.ng/sh **ALPHA** - bleeding edge / work-in-progress +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bwebgl-shadertoy%5D) + ### Related packages - [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/develop/packages/shader-ast) - DSL to define shader code in TypeScript and cross-compile to GLSL, JS and other targets diff --git a/packages/webgl/README.md b/packages/webgl/README.md index d2cd7bb2f3..ff5aec7903 100644 --- a/packages/webgl/README.md +++ b/packages/webgl/README.md @@ -59,6 +59,8 @@ Largely declarative WebGL 1.0 / 2.0 abstraction layer, partially ported **BETA** - possibly breaking changes forthcoming +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bwebgl%5D) + ### Support packages - [@thi.ng/webgl-msdf](https://github.com/thi-ng/umbrella/tree/develop/packages/webgl-msdf) - Multi-channel SDF font rendering & basic text layout for WebGL @@ -89,7 +91,7 @@ yarn add @thi.ng/webgl ``` -Package sizes (gzipped, pre-treeshake): ESM: 11.52 KB / CJS: 11.69 KB / UMD: 11.52 KB +Package sizes (gzipped, pre-treeshake): ESM: 11.56 KB / CJS: 11.74 KB / UMD: 11.58 KB ## Dependencies diff --git a/packages/zipper/README.md b/packages/zipper/README.md index 8e7a6cef0c..0bbdcb161a 100644 --- a/packages/zipper/README.md +++ b/packages/zipper/README.md @@ -38,6 +38,8 @@ Reference: https://en.wikipedia.org/wiki/Zipper_(data_structure) **STABLE** - used in production +[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=is%3Aissue+is%3Aopen+%5Bzipper%5D) + ### Related packages - [@thi.ng/gp](https://github.com/thi-ng/umbrella/tree/develop/packages/gp) - Genetic programming helpers & strategies (tree based & multi-expression programming) From 130dff672b56f789205177c2243169d33d479948 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 22 Sep 2020 11:58:01 +0100 Subject: [PATCH 106/106] Publish - @thi.ng/adapt-dpi@1.0.9 - @thi.ng/adjacency@0.1.62 - @thi.ng/api@6.13.1 - @thi.ng/arrays@0.8.1 - @thi.ng/associative@5.0.7 - @thi.ng/atom@4.1.21 - @thi.ng/bench@2.0.21 - @thi.ng/bencode@0.3.40 - @thi.ng/binary@2.0.16 - @thi.ng/bitfield@0.3.22 - @thi.ng/bitstream@1.1.27 - @thi.ng/cache@1.0.59 - @thi.ng/checks@2.7.9 - @thi.ng/color@1.2.17 - @thi.ng/colored-noise@0.1.2 - @thi.ng/compare@1.3.17 - @thi.ng/compose@1.4.18 - @thi.ng/csp@1.1.39 - @thi.ng/date@0.2.0 - @thi.ng/dcons@2.2.32 - @thi.ng/defmulti@1.2.26 - @thi.ng/dgraph-dot@0.1.27 - @thi.ng/dgraph@1.2.27 - @thi.ng/diff@3.2.32 - @thi.ng/dl-asset@0.4.6 - @thi.ng/dlogic@1.0.32 - @thi.ng/dot@1.2.18 - @thi.ng/dsp-io-wav@0.1.30 - @thi.ng/dsp@2.1.2 - @thi.ng/dual-algebra@0.1.1 - @thi.ng/dynvar@0.1.24 - @thi.ng/ecs@0.3.34 - @thi.ng/egf@0.3.0 - @thi.ng/equiv@1.0.32 - @thi.ng/errors@1.2.22 - @thi.ng/fsm@2.4.26 - @thi.ng/geom-accel@2.1.24 - @thi.ng/geom-api@1.1.0 - @thi.ng/geom-arc@0.3.13 - @thi.ng/geom-clip-line@1.2.9 - @thi.ng/geom-clip-poly@1.0.34 - @thi.ng/geom-closest-point@0.5.0 - @thi.ng/geom-fuzz@0.1.19 - @thi.ng/geom-hull@0.0.66 - @thi.ng/geom-io-obj@0.1.24 - @thi.ng/geom-isec@0.6.0 - @thi.ng/geom-isoline@0.1.64 - @thi.ng/geom-poly-utils@0.1.65 - @thi.ng/geom-resample@0.2.46 - @thi.ng/geom-splines@0.5.33 - @thi.ng/geom-subdiv-curve@0.1.63 - @thi.ng/geom-tessellate@0.2.47 - @thi.ng/geom-voronoi@0.2.9 - @thi.ng/geom@1.12.0 - @thi.ng/gp@0.1.32 - @thi.ng/grid-iterators@0.4.11 - @thi.ng/hdiff@0.1.16 - @thi.ng/hdom-canvas@3.0.19 - @thi.ng/hdom-components@4.0.13 - @thi.ng/hdom-mock@1.1.42 - @thi.ng/hdom@8.2.10 - @thi.ng/heaps@1.2.25 - @thi.ng/hiccup-canvas@1.1.9 - @thi.ng/hiccup-carbon-icons@2.0.4 - @thi.ng/hiccup-css@1.1.39 - @thi.ng/hiccup-html@0.3.6 - @thi.ng/hiccup-markdown@1.2.34 - @thi.ng/hiccup-svg@3.6.1 - @thi.ng/hiccup@3.6.1 - @thi.ng/idgen@0.2.23 - @thi.ng/iges@1.1.48 - @thi.ng/imgui@0.2.40 - @thi.ng/interceptors@2.2.32 - @thi.ng/intervals@2.0.25 - @thi.ng/iterators@5.1.39 - @thi.ng/layout@0.1.23 - @thi.ng/leb128@1.0.34 - @thi.ng/lsys@0.2.61 - @thi.ng/malloc@4.1.26 - @thi.ng/math@2.1.1 - @thi.ng/matrices@0.6.33 - @thi.ng/memoize@2.1.3 - @thi.ng/mime@0.1.22 - @thi.ng/morton@2.0.25 - @thi.ng/oquery@0.1.12 - @thi.ng/parse@0.9.4 - @thi.ng/paths@4.1.7 - @thi.ng/pixel@0.4.6 - @thi.ng/pointfree-lang@1.4.14 - @thi.ng/pointfree@2.0.15 - @thi.ng/poisson@1.1.17 - @thi.ng/porter-duff@0.1.31 - @thi.ng/prefixes@0.1.6 - @thi.ng/quad-edge@0.2.24 - @thi.ng/ramp@0.1.35 - @thi.ng/random@2.0.2 - @thi.ng/range-coder@1.0.59 - @thi.ng/rdom-canvas@0.1.16 - @thi.ng/rdom-components@0.1.13 - @thi.ng/rdom@0.2.12 - @thi.ng/resolve-map@4.2.6 - @thi.ng/rle-pack@2.1.27 - @thi.ng/router@2.0.32 - @thi.ng/rstream-csp@2.0.40 - @thi.ng/rstream-dot@1.1.47 - @thi.ng/rstream-gestures@2.0.39 - @thi.ng/rstream-graph@3.2.41 - @thi.ng/rstream-log-file@0.1.62 - @thi.ng/rstream-log@3.1.47 - @thi.ng/rstream-query@1.1.47 - @thi.ng/rstream@5.0.5 - @thi.ng/sax@1.1.39 - @thi.ng/scenegraph@0.3.7 - @thi.ng/seq@0.2.24 - @thi.ng/sexpr@0.2.27 - @thi.ng/shader-ast-glsl@0.2.10 - @thi.ng/shader-ast-js@0.5.7 - @thi.ng/shader-ast-stdlib@0.5.2 - @thi.ng/shader-ast@0.7.2 - @thi.ng/simd@0.4.7 - @thi.ng/soa@0.1.37 - @thi.ng/sparse@0.1.55 - @thi.ng/strings@1.10.0 - @thi.ng/system@0.2.27 - @thi.ng/text-canvas@0.2.31 - @thi.ng/transducers-binary@0.5.30 - @thi.ng/transducers-fsm@1.1.39 - @thi.ng/transducers-hdom@2.0.71 - @thi.ng/transducers-patch@0.1.30 - @thi.ng/transducers-stats@1.1.39 - @thi.ng/transducers@7.4.0 - @thi.ng/unionstruct@1.1.25 - @thi.ng/vector-pools@1.0.46 - @thi.ng/vectors@4.6.6 - @thi.ng/viz@0.1.1 - @thi.ng/webgl-msdf@0.1.60 - @thi.ng/webgl-shadertoy@0.2.47 - @thi.ng/webgl@3.3.3 - @thi.ng/zipper@0.1.26 --- packages/adapt-dpi/CHANGELOG.md | 8 ++++ packages/adapt-dpi/package.json | 2 +- packages/adjacency/CHANGELOG.md | 8 ++++ packages/adjacency/package.json | 16 +++---- packages/api/CHANGELOG.md | 8 ++++ packages/api/package.json | 2 +- packages/arrays/CHANGELOG.md | 8 ++++ packages/arrays/package.json | 14 +++--- packages/associative/CHANGELOG.md | 8 ++++ packages/associative/package.json | 18 ++++---- packages/atom/CHANGELOG.md | 8 ++++ packages/atom/package.json | 10 ++--- packages/bench/CHANGELOG.md | 8 ++++ packages/bench/package.json | 2 +- packages/bencode/CHANGELOG.md | 8 ++++ packages/bencode/package.json | 16 +++---- packages/binary/CHANGELOG.md | 8 ++++ packages/binary/package.json | 4 +- packages/bitfield/CHANGELOG.md | 8 ++++ packages/bitfield/package.json | 8 ++-- packages/bitstream/CHANGELOG.md | 8 ++++ packages/bitstream/package.json | 4 +- packages/cache/CHANGELOG.md | 8 ++++ packages/cache/package.json | 8 ++-- packages/checks/CHANGELOG.md | 8 ++++ packages/checks/package.json | 2 +- packages/color/CHANGELOG.md | 8 ++++ packages/color/package.json | 20 ++++----- packages/colored-noise/CHANGELOG.md | 8 ++++ packages/colored-noise/package.json | 18 ++++---- packages/compare/CHANGELOG.md | 8 ++++ packages/compare/package.json | 4 +- packages/compose/CHANGELOG.md | 8 ++++ packages/compose/package.json | 6 +-- packages/csp/CHANGELOG.md | 8 ++++ packages/csp/package.json | 14 +++--- packages/date/CHANGELOG.md | 20 +++++++++ packages/date/package.json | 4 +- packages/dcons/CHANGELOG.md | 8 ++++ packages/dcons/package.json | 16 +++---- packages/defmulti/CHANGELOG.md | 8 ++++ packages/defmulti/package.json | 6 +-- packages/dgraph-dot/CHANGELOG.md | 8 ++++ packages/dgraph-dot/package.json | 8 ++-- packages/dgraph/CHANGELOG.md | 8 ++++ packages/dgraph/package.json | 12 ++--- packages/diff/CHANGELOG.md | 8 ++++ packages/diff/package.json | 6 +-- packages/dl-asset/CHANGELOG.md | 8 ++++ packages/dl-asset/package.json | 8 ++-- packages/dlogic/CHANGELOG.md | 8 ++++ packages/dlogic/package.json | 4 +- packages/dot/CHANGELOG.md | 8 ++++ packages/dot/package.json | 6 +-- packages/dsp-io-wav/CHANGELOG.md | 8 ++++ packages/dsp-io-wav/package.json | 10 ++--- packages/dsp/CHANGELOG.md | 8 ++++ packages/dsp/package.json | 14 +++--- packages/dual-algebra/CHANGELOG.md | 8 ++++ packages/dual-algebra/package.json | 4 +- packages/dynvar/CHANGELOG.md | 8 ++++ packages/dynvar/package.json | 4 +- packages/ecs/CHANGELOG.md | 8 ++++ packages/ecs/package.json | 18 ++++---- packages/egf/CHANGELOG.md | 19 ++++++++ packages/egf/package.json | 20 ++++----- packages/equiv/CHANGELOG.md | 8 ++++ packages/equiv/package.json | 2 +- packages/errors/CHANGELOG.md | 8 ++++ packages/errors/package.json | 2 +- packages/fsm/CHANGELOG.md | 8 ++++ packages/fsm/package.json | 14 +++--- packages/geom-accel/CHANGELOG.md | 8 ++++ packages/geom-accel/package.json | 22 ++++----- packages/geom-api/CHANGELOG.md | 11 +++++ packages/geom-api/package.json | 6 +-- packages/geom-arc/CHANGELOG.md | 8 ++++ packages/geom-arc/package.json | 12 ++--- packages/geom-clip-line/CHANGELOG.md | 8 ++++ packages/geom-clip-line/package.json | 8 ++-- packages/geom-clip-poly/CHANGELOG.md | 8 ++++ packages/geom-clip-poly/package.json | 10 ++--- packages/geom-closest-point/CHANGELOG.md | 16 +++++++ packages/geom-closest-point/package.json | 8 ++-- packages/geom-fuzz/CHANGELOG.md | 8 ++++ packages/geom-fuzz/package.json | 22 ++++----- packages/geom-hull/CHANGELOG.md | 8 ++++ packages/geom-hull/package.json | 6 +-- packages/geom-io-obj/CHANGELOG.md | 8 ++++ packages/geom-io-obj/package.json | 6 +-- packages/geom-isec/CHANGELOG.md | 16 +++++++ packages/geom-isec/package.json | 12 ++--- packages/geom-isoline/CHANGELOG.md | 8 ++++ packages/geom-isoline/package.json | 8 ++-- packages/geom-poly-utils/CHANGELOG.md | 8 ++++ packages/geom-poly-utils/package.json | 12 ++--- packages/geom-resample/CHANGELOG.md | 8 ++++ packages/geom-resample/package.json | 12 ++--- packages/geom-splines/CHANGELOG.md | 8 ++++ packages/geom-splines/package.json | 16 +++---- packages/geom-subdiv-curve/CHANGELOG.md | 8 ++++ packages/geom-subdiv-curve/package.json | 8 ++-- packages/geom-tessellate/CHANGELOG.md | 8 ++++ packages/geom-tessellate/package.json | 14 +++--- packages/geom-voronoi/CHANGELOG.md | 8 ++++ packages/geom-voronoi/package.json | 20 ++++----- packages/geom/CHANGELOG.md | 11 +++++ packages/geom/package.json | 54 +++++++++++------------ packages/gp/CHANGELOG.md | 8 ++++ packages/gp/package.json | 12 ++--- packages/grid-iterators/CHANGELOG.md | 8 ++++ packages/grid-iterators/package.json | 12 ++--- packages/hdiff/CHANGELOG.md | 8 ++++ packages/hdiff/package.json | 12 ++--- packages/hdom-canvas/CHANGELOG.md | 8 ++++ packages/hdom-canvas/package.json | 12 ++--- packages/hdom-components/CHANGELOG.md | 8 ++++ packages/hdom-components/package.json | 14 +++--- packages/hdom-mock/CHANGELOG.md | 8 ++++ packages/hdom-mock/package.json | 8 ++-- packages/hdom/CHANGELOG.md | 8 ++++ packages/hdom/package.json | 18 ++++---- packages/heaps/CHANGELOG.md | 8 ++++ packages/heaps/package.json | 6 +-- packages/hiccup-canvas/CHANGELOG.md | 8 ++++ packages/hiccup-canvas/package.json | 12 ++--- packages/hiccup-carbon-icons/CHANGELOG.md | 8 ++++ packages/hiccup-carbon-icons/package.json | 4 +- packages/hiccup-css/CHANGELOG.md | 8 ++++ packages/hiccup-css/package.json | 10 ++--- packages/hiccup-html/CHANGELOG.md | 8 ++++ packages/hiccup-html/package.json | 4 +- packages/hiccup-markdown/CHANGELOG.md | 8 ++++ packages/hiccup-markdown/package.json | 22 ++++----- packages/hiccup-svg/CHANGELOG.md | 8 ++++ packages/hiccup-svg/package.json | 8 ++-- packages/hiccup/CHANGELOG.md | 8 ++++ packages/hiccup/package.json | 12 ++--- packages/idgen/CHANGELOG.md | 8 ++++ packages/idgen/package.json | 4 +- packages/iges/CHANGELOG.md | 8 ++++ packages/iges/package.json | 14 +++--- packages/imgui/CHANGELOG.md | 8 ++++ packages/imgui/package.json | 22 ++++----- packages/interceptors/CHANGELOG.md | 8 ++++ packages/interceptors/package.json | 12 ++--- packages/intervals/CHANGELOG.md | 8 ++++ packages/intervals/package.json | 10 ++--- packages/iterators/CHANGELOG.md | 8 ++++ packages/iterators/package.json | 8 ++-- packages/layout/CHANGELOG.md | 8 ++++ packages/layout/package.json | 4 +- packages/leb128/CHANGELOG.md | 8 ++++ packages/leb128/package.json | 8 ++-- packages/lsys/CHANGELOG.md | 8 ++++ packages/lsys/package.json | 16 +++---- packages/malloc/CHANGELOG.md | 8 ++++ packages/malloc/package.json | 10 ++--- packages/math/CHANGELOG.md | 8 ++++ packages/math/package.json | 4 +- packages/matrices/CHANGELOG.md | 8 ++++ packages/matrices/package.json | 10 ++--- packages/memoize/CHANGELOG.md | 8 ++++ packages/memoize/package.json | 4 +- packages/mime/CHANGELOG.md | 8 ++++ packages/mime/package.json | 4 +- packages/morton/CHANGELOG.md | 8 ++++ packages/morton/package.json | 8 ++-- packages/oquery/CHANGELOG.md | 8 ++++ packages/oquery/package.json | 12 ++--- packages/parse/CHANGELOG.md | 8 ++++ packages/parse/package.json | 12 ++--- packages/paths/CHANGELOG.md | 8 ++++ packages/paths/package.json | 8 ++-- packages/pixel/CHANGELOG.md | 8 ++++ packages/pixel/package.json | 10 ++--- packages/pointfree-lang/CHANGELOG.md | 8 ++++ packages/pointfree-lang/package.json | 10 ++--- packages/pointfree/CHANGELOG.md | 8 ++++ packages/pointfree/package.json | 12 ++--- packages/poisson/CHANGELOG.md | 8 ++++ packages/poisson/package.json | 14 +++--- packages/porter-duff/CHANGELOG.md | 8 ++++ packages/porter-duff/package.json | 6 +-- packages/prefixes/CHANGELOG.md | 8 ++++ packages/prefixes/package.json | 2 +- packages/quad-edge/CHANGELOG.md | 8 ++++ packages/quad-edge/package.json | 2 +- packages/ramp/CHANGELOG.md | 8 ++++ packages/ramp/package.json | 12 ++--- packages/random/CHANGELOG.md | 8 ++++ packages/random/package.json | 6 +-- packages/range-coder/CHANGELOG.md | 8 ++++ packages/range-coder/package.json | 6 +-- packages/rdom-canvas/CHANGELOG.md | 8 ++++ packages/rdom-canvas/package.json | 16 +++---- packages/rdom-components/CHANGELOG.md | 8 ++++ packages/rdom-components/package.json | 16 +++---- packages/rdom/CHANGELOG.md | 8 ++++ packages/rdom/package.json | 18 ++++---- packages/resolve-map/CHANGELOG.md | 8 ++++ packages/resolve-map/package.json | 10 ++--- packages/rle-pack/CHANGELOG.md | 8 ++++ packages/rle-pack/package.json | 6 +-- packages/router/CHANGELOG.md | 8 ++++ packages/router/package.json | 10 ++--- packages/rstream-csp/CHANGELOG.md | 8 ++++ packages/rstream-csp/package.json | 6 +-- packages/rstream-dot/CHANGELOG.md | 8 ++++ packages/rstream-dot/package.json | 4 +- packages/rstream-gestures/CHANGELOG.md | 8 ++++ packages/rstream-gestures/package.json | 12 ++--- packages/rstream-graph/CHANGELOG.md | 8 ++++ packages/rstream-graph/package.json | 18 ++++---- packages/rstream-log-file/CHANGELOG.md | 8 ++++ packages/rstream-log-file/package.json | 4 +- packages/rstream-log/CHANGELOG.md | 8 ++++ packages/rstream-log/package.json | 12 ++--- packages/rstream-query/CHANGELOG.md | 8 ++++ packages/rstream-query/package.json | 20 ++++----- packages/rstream/CHANGELOG.md | 8 ++++ packages/rstream/package.json | 16 +++---- packages/sax/CHANGELOG.md | 8 ++++ packages/sax/package.json | 8 ++-- packages/scenegraph/CHANGELOG.md | 8 ++++ packages/scenegraph/package.json | 10 ++--- packages/seq/CHANGELOG.md | 8 ++++ packages/seq/package.json | 6 +-- packages/sexpr/CHANGELOG.md | 8 ++++ packages/sexpr/package.json | 8 ++-- packages/shader-ast-glsl/CHANGELOG.md | 8 ++++ packages/shader-ast-glsl/package.json | 10 ++--- packages/shader-ast-js/CHANGELOG.md | 8 ++++ packages/shader-ast-js/package.json | 18 ++++---- packages/shader-ast-stdlib/CHANGELOG.md | 8 ++++ packages/shader-ast-stdlib/package.json | 6 +-- packages/shader-ast/CHANGELOG.md | 8 ++++ packages/shader-ast/package.json | 12 ++--- packages/simd/CHANGELOG.md | 8 ++++ packages/simd/package.json | 4 +- packages/soa/CHANGELOG.md | 8 ++++ packages/soa/package.json | 12 ++--- packages/sparse/CHANGELOG.md | 8 ++++ packages/sparse/package.json | 6 +-- packages/strings/CHANGELOG.md | 13 ++++++ packages/strings/package.json | 8 ++-- packages/system/CHANGELOG.md | 8 ++++ packages/system/package.json | 6 +-- packages/text-canvas/CHANGELOG.md | 8 ++++ packages/text-canvas/package.json | 18 ++++---- packages/transducers-binary/CHANGELOG.md | 8 ++++ packages/transducers-binary/package.json | 14 +++--- packages/transducers-fsm/CHANGELOG.md | 8 ++++ packages/transducers-fsm/package.json | 6 +-- packages/transducers-hdom/CHANGELOG.md | 8 ++++ packages/transducers-hdom/package.json | 8 ++-- packages/transducers-patch/CHANGELOG.md | 8 ++++ packages/transducers-patch/package.json | 12 ++--- packages/transducers-stats/CHANGELOG.md | 8 ++++ packages/transducers-stats/package.json | 10 ++--- packages/transducers/CHANGELOG.md | 11 +++++ packages/transducers/package.json | 18 ++++---- packages/unionstruct/CHANGELOG.md | 8 ++++ packages/unionstruct/package.json | 2 +- packages/vector-pools/CHANGELOG.md | 8 ++++ packages/vector-pools/package.json | 14 +++--- packages/vectors/CHANGELOG.md | 8 ++++ packages/vectors/package.json | 20 ++++----- packages/viz/CHANGELOG.md | 8 ++++ packages/viz/package.json | 18 ++++---- packages/webgl-msdf/CHANGELOG.md | 8 ++++ packages/webgl-msdf/package.json | 14 +++--- packages/webgl-shadertoy/CHANGELOG.md | 8 ++++ packages/webgl-shadertoy/package.json | 10 ++--- packages/webgl/CHANGELOG.md | 8 ++++ packages/webgl/package.json | 32 +++++++------- packages/zipper/CHANGELOG.md | 8 ++++ packages/zipper/package.json | 8 ++-- 278 files changed, 1907 insertions(+), 742 deletions(-) create mode 100644 packages/egf/CHANGELOG.md diff --git a/packages/adapt-dpi/CHANGELOG.md b/packages/adapt-dpi/CHANGELOG.md index 18ec7236fb..fe856bd16c 100644 --- a/packages/adapt-dpi/CHANGELOG.md +++ b/packages/adapt-dpi/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/adapt-dpi@1.0.8...@thi.ng/adapt-dpi@1.0.9) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/adapt-dpi + + + + + ## [1.0.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/adapt-dpi@1.0.7...@thi.ng/adapt-dpi@1.0.8) (2020-09-13) **Note:** Version bump only for package @thi.ng/adapt-dpi diff --git a/packages/adapt-dpi/package.json b/packages/adapt-dpi/package.json index 5a241c6796..cad534b56c 100644 --- a/packages/adapt-dpi/package.json +++ b/packages/adapt-dpi/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/adapt-dpi", - "version": "1.0.8", + "version": "1.0.9", "description": "HDPI canvas adapter / styling utility", "module": "./index.js", "main": "./lib/index.js", diff --git a/packages/adjacency/CHANGELOG.md b/packages/adjacency/CHANGELOG.md index 5bcfdb798e..5056e42559 100644 --- a/packages/adjacency/CHANGELOG.md +++ b/packages/adjacency/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.62](https://github.com/thi-ng/umbrella/compare/@thi.ng/adjacency@0.1.61...@thi.ng/adjacency@0.1.62) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/adjacency + + + + + ## [0.1.61](https://github.com/thi-ng/umbrella/compare/@thi.ng/adjacency@0.1.60...@thi.ng/adjacency@0.1.61) (2020-09-13) **Note:** Version bump only for package @thi.ng/adjacency diff --git a/packages/adjacency/package.json b/packages/adjacency/package.json index b234fe37f1..5fd3de5ac2 100644 --- a/packages/adjacency/package.json +++ b/packages/adjacency/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/adjacency", - "version": "0.1.61", + "version": "0.1.62", "description": "Sparse & bitwise adjacency matrices and related functions for directed & undirected graphs", "module": "./index.js", "main": "./lib/index.js", @@ -40,7 +40,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/vectors": "^4.6.5", + "@thi.ng/vectors": "^4.6.6", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", @@ -50,12 +50,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/bitfield": "^0.3.21", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/dcons": "^2.2.31", - "@thi.ng/sparse": "^0.1.54" + "@thi.ng/api": "^6.13.1", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/bitfield": "^0.3.22", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/dcons": "^2.2.32", + "@thi.ng/sparse": "^0.1.55" }, "files": [ "*.js", diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index dd4254469d..161f2a7ec9 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.13.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/api@6.13.0...@thi.ng/api@6.13.1) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/api + + + + + # [6.13.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/api@6.12.3...@thi.ng/api@6.13.0) (2020-09-13) diff --git a/packages/api/package.json b/packages/api/package.json index 6629dc5116..d0b438dd59 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/api", - "version": "6.13.0", + "version": "6.13.1", "description": "Common, generic types, interfaces & mixins", "module": "./index.js", "main": "./lib/index.js", diff --git a/packages/arrays/CHANGELOG.md b/packages/arrays/CHANGELOG.md index d092372733..35e7c234da 100644 --- a/packages/arrays/CHANGELOG.md +++ b/packages/arrays/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.8.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/arrays@0.8.0...@thi.ng/arrays@0.8.1) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/arrays + + + + + # [0.8.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/arrays@0.7.0...@thi.ng/arrays@0.8.0) (2020-09-13) diff --git a/packages/arrays/package.json b/packages/arrays/package.json index e901dce28e..ee2455a3d1 100644 --- a/packages/arrays/package.json +++ b/packages/arrays/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/arrays", - "version": "0.8.0", + "version": "0.8.1", "description": "Array / Arraylike utilities", "module": "./index.js", "main": "./lib/index.js", @@ -49,12 +49,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/compare": "^1.3.16", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/random": "^2.0.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/compare": "^1.3.17", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/random": "^2.0.2" }, "files": [ "*.js", diff --git a/packages/associative/CHANGELOG.md b/packages/associative/CHANGELOG.md index fe7791b3be..6898f9c1ab 100644 --- a/packages/associative/CHANGELOG.md +++ b/packages/associative/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@5.0.6...@thi.ng/associative@5.0.7) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/associative + + + + + ## [5.0.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@5.0.5...@thi.ng/associative@5.0.6) (2020-09-13) **Note:** Version bump only for package @thi.ng/associative diff --git a/packages/associative/package.json b/packages/associative/package.json index e28801e87d..144b6f4413 100644 --- a/packages/associative/package.json +++ b/packages/associative/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/associative", - "version": "5.0.6", + "version": "5.0.7", "description": "Alternative Map and Set implementations with customizable equality semantics & supporting operations", "module": "./index.js", "main": "./lib/index.js", @@ -49,14 +49,14 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/compare": "^1.3.16", - "@thi.ng/dcons": "^2.2.31", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/transducers": "^7.3.1", + "@thi.ng/api": "^6.13.1", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/compare": "^1.3.17", + "@thi.ng/dcons": "^2.2.32", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/transducers": "^7.4.0", "tslib": "^2.0.1" }, "files": [ diff --git a/packages/atom/CHANGELOG.md b/packages/atom/CHANGELOG.md index adf2bf91f9..35489e6f67 100644 --- a/packages/atom/CHANGELOG.md +++ b/packages/atom/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [4.1.21](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@4.1.20...@thi.ng/atom@4.1.21) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/atom + + + + + ## [4.1.20](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@4.1.19...@thi.ng/atom@4.1.20) (2020-09-13) **Note:** Version bump only for package @thi.ng/atom diff --git a/packages/atom/package.json b/packages/atom/package.json index 90323a43cf..e54d5c0e03 100644 --- a/packages/atom/package.json +++ b/packages/atom/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/atom", - "version": "4.1.20", + "version": "4.1.21", "description": "Mutable wrappers for nested immutable values with optional undo/redo history and transaction support", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/paths": "^4.1.6", + "@thi.ng/api": "^6.13.1", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/paths": "^4.1.7", "tslib": "^2.0.1" }, "files": [ diff --git a/packages/bench/CHANGELOG.md b/packages/bench/CHANGELOG.md index 262b3cec44..2a485a4046 100644 --- a/packages/bench/CHANGELOG.md +++ b/packages/bench/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.21](https://github.com/thi-ng/umbrella/compare/@thi.ng/bench@2.0.20...@thi.ng/bench@2.0.21) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/bench + + + + + ## [2.0.20](https://github.com/thi-ng/umbrella/compare/@thi.ng/bench@2.0.19...@thi.ng/bench@2.0.20) (2020-09-13) **Note:** Version bump only for package @thi.ng/bench diff --git a/packages/bench/package.json b/packages/bench/package.json index bebc3ba5a3..0c4f2b0d16 100644 --- a/packages/bench/package.json +++ b/packages/bench/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/bench", - "version": "2.0.20", + "version": "2.0.21", "description": "Benchmarking utilities w/ optional statistics", "module": "./index.js", "main": "./lib/index.js", diff --git a/packages/bencode/CHANGELOG.md b/packages/bencode/CHANGELOG.md index 05cc42aaa4..c14b354ecf 100644 --- a/packages/bencode/CHANGELOG.md +++ b/packages/bencode/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.3.40](https://github.com/thi-ng/umbrella/compare/@thi.ng/bencode@0.3.39...@thi.ng/bencode@0.3.40) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/bencode + + + + + ## [0.3.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/bencode@0.3.38...@thi.ng/bencode@0.3.39) (2020-09-13) **Note:** Version bump only for package @thi.ng/bencode diff --git a/packages/bencode/package.json b/packages/bencode/package.json index febdf47401..100e59b997 100644 --- a/packages/bencode/package.json +++ b/packages/bencode/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/bencode", - "version": "0.3.39", + "version": "0.3.40", "description": "Bencode binary encoder / decoder with optional UTF8 encoding & floating point support", "module": "./index.js", "main": "./lib/index.js", @@ -49,13 +49,13 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/defmulti": "^1.2.25", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/transducers-binary": "^0.5.29" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/defmulti": "^1.2.26", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/transducers-binary": "^0.5.30" }, "files": [ "*.js", diff --git a/packages/binary/CHANGELOG.md b/packages/binary/CHANGELOG.md index d9af6e2ad5..6fccb3baef 100644 --- a/packages/binary/CHANGELOG.md +++ b/packages/binary/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/binary@2.0.15...@thi.ng/binary@2.0.16) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/binary + + + + + ## [2.0.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/binary@2.0.14...@thi.ng/binary@2.0.15) (2020-09-13) **Note:** Version bump only for package @thi.ng/binary diff --git a/packages/binary/package.json b/packages/binary/package.json index c909b2990f..89de92e30d 100644 --- a/packages/binary/package.json +++ b/packages/binary/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/binary", - "version": "2.0.15", + "version": "2.0.16", "description": "95+ assorted binary / bitwise operations, conversions, utilities", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", + "@thi.ng/api": "^6.13.1", "tslib": "^2.0.1" }, "files": [ diff --git a/packages/bitfield/CHANGELOG.md b/packages/bitfield/CHANGELOG.md index de15616b11..9cba6fd34a 100644 --- a/packages/bitfield/CHANGELOG.md +++ b/packages/bitfield/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.3.22](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitfield@0.3.21...@thi.ng/bitfield@0.3.22) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/bitfield + + + + + ## [0.3.21](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitfield@0.3.20...@thi.ng/bitfield@0.3.21) (2020-09-13) **Note:** Version bump only for package @thi.ng/bitfield diff --git a/packages/bitfield/package.json b/packages/bitfield/package.json index 72fdfbdb38..acee21cd3f 100644 --- a/packages/bitfield/package.json +++ b/packages/bitfield/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/bitfield", - "version": "0.3.21", + "version": "0.3.22", "description": "1D / 2D bit field implementations", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/strings": "^1.9.6" + "@thi.ng/api": "^6.13.1", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/strings": "^1.10.0" }, "files": [ "*.js", diff --git a/packages/bitstream/CHANGELOG.md b/packages/bitstream/CHANGELOG.md index a311a37b1a..874166be08 100644 --- a/packages/bitstream/CHANGELOG.md +++ b/packages/bitstream/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.27](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitstream@1.1.26...@thi.ng/bitstream@1.1.27) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/bitstream + + + + + ## [1.1.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitstream@1.1.25...@thi.ng/bitstream@1.1.26) (2020-09-13) **Note:** Version bump only for package @thi.ng/bitstream diff --git a/packages/bitstream/package.json b/packages/bitstream/package.json index 2713cf0c2d..fe4c81513f 100644 --- a/packages/bitstream/package.json +++ b/packages/bitstream/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/bitstream", - "version": "1.1.26", + "version": "1.1.27", "description": "ES6 iterator based read/write bit streams with support for variable word widths", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/errors": "^1.2.21" + "@thi.ng/errors": "^1.2.22" }, "files": [ "*.js", diff --git a/packages/cache/CHANGELOG.md b/packages/cache/CHANGELOG.md index 0b48253f28..65413d7e3a 100644 --- a/packages/cache/CHANGELOG.md +++ b/packages/cache/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.59](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@1.0.58...@thi.ng/cache@1.0.59) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/cache + + + + + ## [1.0.58](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@1.0.57...@thi.ng/cache@1.0.58) (2020-09-13) **Note:** Version bump only for package @thi.ng/cache diff --git a/packages/cache/package.json b/packages/cache/package.json index ef75fca0e3..4e18f2b79e 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/cache", - "version": "1.0.58", + "version": "1.0.59", "description": "In-memory cache implementations with ES6 Map-like API and different eviction strategies", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/dcons": "^2.2.31", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/dcons": "^2.2.32", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/checks/CHANGELOG.md b/packages/checks/CHANGELOG.md index 460106146c..d46d09b1cb 100644 --- a/packages/checks/CHANGELOG.md +++ b/packages/checks/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.7.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/checks@2.7.8...@thi.ng/checks@2.7.9) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/checks + + + + + ## [2.7.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/checks@2.7.7...@thi.ng/checks@2.7.8) (2020-09-13) **Note:** Version bump only for package @thi.ng/checks diff --git a/packages/checks/package.json b/packages/checks/package.json index 57a2844e57..2971750a7f 100644 --- a/packages/checks/package.json +++ b/packages/checks/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/checks", - "version": "2.7.8", + "version": "2.7.9", "description": "Collection of 50+ type, feature & value checks", "module": "./index.js", "main": "./lib/index.js", diff --git a/packages/color/CHANGELOG.md b/packages/color/CHANGELOG.md index ac19871ca1..71042ca8ba 100644 --- a/packages/color/CHANGELOG.md +++ b/packages/color/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.2.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/color@1.2.16...@thi.ng/color@1.2.17) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/color + + + + + ## [1.2.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/color@1.2.15...@thi.ng/color@1.2.16) (2020-09-13) **Note:** Version bump only for package @thi.ng/color diff --git a/packages/color/package.json b/packages/color/package.json index 9aa00da0a6..16c7b72541 100644 --- a/packages/color/package.json +++ b/packages/color/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/color", - "version": "1.2.16", + "version": "1.2.17", "description": "Array-based color ops, conversions, multi-color gradients, presets", "module": "./index.js", "main": "./lib/index.js", @@ -49,15 +49,15 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/compose": "^1.4.17", - "@thi.ng/defmulti": "^1.2.25", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/math": "^2.1.0", - "@thi.ng/strings": "^1.9.6", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/compose": "^1.4.18", + "@thi.ng/defmulti": "^1.2.26", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/math": "^2.1.1", + "@thi.ng/strings": "^1.10.0", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/colored-noise/CHANGELOG.md b/packages/colored-noise/CHANGELOG.md index faaac2dfc3..8e0abe77e4 100644 --- a/packages/colored-noise/CHANGELOG.md +++ b/packages/colored-noise/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/colored-noise@0.1.1...@thi.ng/colored-noise@0.1.2) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/colored-noise + + + + + ## [0.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/colored-noise@0.1.0...@thi.ng/colored-noise@0.1.1) (2020-09-13) **Note:** Version bump only for package @thi.ng/colored-noise diff --git a/packages/colored-noise/package.json b/packages/colored-noise/package.json index a3a30422ac..3b61b7a9db 100644 --- a/packages/colored-noise/package.json +++ b/packages/colored-noise/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/colored-noise", - "version": "0.1.1", + "version": "0.1.2", "description": "Customizable O(1) ES6 generators for colored noise", "module": "./index.js", "main": "./lib/index.js", @@ -39,12 +39,12 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/api": "^6.13.0", - "@thi.ng/dsp": "^2.1.1", - "@thi.ng/dsp-io-wav": "^0.1.29", - "@thi.ng/text-canvas": "^0.2.30", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5", + "@thi.ng/api": "^6.13.1", + "@thi.ng/dsp": "^2.1.2", + "@thi.ng/dsp-io-wav": "^0.1.30", + "@thi.ng/text-canvas": "^0.2.31", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", @@ -54,8 +54,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/binary": "^2.0.15", - "@thi.ng/random": "^2.0.1" + "@thi.ng/binary": "^2.0.16", + "@thi.ng/random": "^2.0.2" }, "files": [ "*.js", diff --git a/packages/compare/CHANGELOG.md b/packages/compare/CHANGELOG.md index 67b90facb1..0c60668de5 100644 --- a/packages/compare/CHANGELOG.md +++ b/packages/compare/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.3.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/compare@1.3.16...@thi.ng/compare@1.3.17) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/compare + + + + + ## [1.3.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/compare@1.3.15...@thi.ng/compare@1.3.16) (2020-09-13) **Note:** Version bump only for package @thi.ng/compare diff --git a/packages/compare/package.json b/packages/compare/package.json index 4d944bbfdb..9ae2f8a686 100644 --- a/packages/compare/package.json +++ b/packages/compare/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/compare", - "version": "1.3.16", + "version": "1.3.17", "description": "Comparators with support for types implementing the @thi.ng/api/ICompare interface", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0" + "@thi.ng/api": "^6.13.1" }, "files": [ "*.js", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 58ce2aba89..78452d4919 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.4.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/compose@1.4.17...@thi.ng/compose@1.4.18) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/compose + + + + + ## [1.4.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/compose@1.4.16...@thi.ng/compose@1.4.17) (2020-09-13) **Note:** Version bump only for package @thi.ng/compose diff --git a/packages/compose/package.json b/packages/compose/package.json index 5571bb55c5..d7c1fe3a8b 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/compose", - "version": "1.4.17", + "version": "1.4.18", "description": "Optimized functional composition helpers", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/errors": "^1.2.21" + "@thi.ng/api": "^6.13.1", + "@thi.ng/errors": "^1.2.22" }, "files": [ "*.js", diff --git a/packages/csp/CHANGELOG.md b/packages/csp/CHANGELOG.md index 1b25524023..aaeaae5a67 100644 --- a/packages/csp/CHANGELOG.md +++ b/packages/csp/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@1.1.38...@thi.ng/csp@1.1.39) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/csp + + + + + ## [1.1.38](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@1.1.37...@thi.ng/csp@1.1.38) (2020-09-13) **Note:** Version bump only for package @thi.ng/csp diff --git a/packages/csp/package.json b/packages/csp/package.json index 62acd8577c..4cb2980e6d 100644 --- a/packages/csp/package.json +++ b/packages/csp/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/csp", - "version": "1.1.38", + "version": "1.1.39", "description": "ES6 promise based CSP primitives & operations", "module": "./index.js", "main": "./lib/index.js", @@ -53,12 +53,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/dcons": "^2.2.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/dcons": "^2.2.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index c8862218af..8139bf592f 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -3,6 +3,26 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/date@0.1.0...@thi.ng/date@0.2.0) (2020-09-22) + + +### Bug Fixes + +* **date:** update ceilMonth(), add docstrings ([0c6c2cc](https://github.com/thi-ng/umbrella/commit/0c6c2cc8d75c7f89be14acec098c865d5b518f20)) + + +### Features + +* **date:** add DateTime, defIterator, add/update iterators ([0e31c69](https://github.com/thi-ng/umbrella/commit/0e31c69942c2b88df9239a13051f158efe7fc38c)) +* **date:** add defTimecode() formatter ([42753e1](https://github.com/thi-ng/umbrella/commit/42753e1e53e1c4af02928e6a6158f4e3be4f2e3a)) +* **date:** add iterator arg coercions, refactor, add docs ([1256201](https://github.com/thi-ng/umbrella/commit/1256201c20e4cd01e4f7e0a1d2fbc9a163a96ac4)) +* **date:** add/update formatters, add locale ([c8e84ad](https://github.com/thi-ng/umbrella/commit/c8e84ad2f2d7cfaa94684fd3873d55714eab88e7)) +* **date:** update/fix DateTime ([27c8617](https://github.com/thi-ng/umbrella/commit/27c8617be90153abea3098ef4120e348fac4934b)) + + + + + # 0.1.0 (2020-09-13) diff --git a/packages/date/package.json b/packages/date/package.json index a7c9a0f100..4d48f267db 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/date", - "version": "0.1.0", + "version": "0.2.0", "description": "Date/timestamp iterators, formatters, rounding", "module": "./index.js", "main": "./lib/index.js", @@ -48,7 +48,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0" + "@thi.ng/api": "^6.13.1" }, "files": [ "*.js", diff --git a/packages/dcons/CHANGELOG.md b/packages/dcons/CHANGELOG.md index f0d3f76ce6..0d70261754 100644 --- a/packages/dcons/CHANGELOG.md +++ b/packages/dcons/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.2.32](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@2.2.31...@thi.ng/dcons@2.2.32) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/dcons + + + + + ## [2.2.31](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@2.2.30...@thi.ng/dcons@2.2.31) (2020-09-13) **Note:** Version bump only for package @thi.ng/dcons diff --git a/packages/dcons/package.json b/packages/dcons/package.json index 4f868ba49d..1f692ee806 100644 --- a/packages/dcons/package.json +++ b/packages/dcons/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dcons", - "version": "2.2.31", + "version": "2.2.32", "description": "Double-linked list with comprehensive set of operations", "module": "./index.js", "main": "./lib/index.js", @@ -49,13 +49,13 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/compare": "^1.3.16", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/random": "^2.0.1", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/compare": "^1.3.17", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/random": "^2.0.2", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/defmulti/CHANGELOG.md b/packages/defmulti/CHANGELOG.md index a49dde5830..c86eaa114a 100644 --- a/packages/defmulti/CHANGELOG.md +++ b/packages/defmulti/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.2.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/defmulti@1.2.25...@thi.ng/defmulti@1.2.26) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/defmulti + + + + + ## [1.2.25](https://github.com/thi-ng/umbrella/compare/@thi.ng/defmulti@1.2.24...@thi.ng/defmulti@1.2.25) (2020-09-13) **Note:** Version bump only for package @thi.ng/defmulti diff --git a/packages/defmulti/package.json b/packages/defmulti/package.json index 7169890291..5b80ac53c8 100644 --- a/packages/defmulti/package.json +++ b/packages/defmulti/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/defmulti", - "version": "1.2.25", + "version": "1.2.26", "description": "Dynamic, extensible multiple dispatch via user supplied dispatch function.", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/errors": "^1.2.21" + "@thi.ng/api": "^6.13.1", + "@thi.ng/errors": "^1.2.22" }, "files": [ "*.js", diff --git a/packages/dgraph-dot/CHANGELOG.md b/packages/dgraph-dot/CHANGELOG.md index cdd4fa5ae7..91118a57b2 100644 --- a/packages/dgraph-dot/CHANGELOG.md +++ b/packages/dgraph-dot/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.27](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph-dot@0.1.26...@thi.ng/dgraph-dot@0.1.27) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/dgraph-dot + + + + + ## [0.1.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph-dot@0.1.25...@thi.ng/dgraph-dot@0.1.26) (2020-09-13) **Note:** Version bump only for package @thi.ng/dgraph-dot diff --git a/packages/dgraph-dot/package.json b/packages/dgraph-dot/package.json index 40c8025033..6953e22417 100644 --- a/packages/dgraph-dot/package.json +++ b/packages/dgraph-dot/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dgraph-dot", - "version": "0.1.26", + "version": "0.1.27", "description": "Customizable Graphviz DOT serialization for @thi.ng/dgraph", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/dgraph": "^1.2.26", - "@thi.ng/dot": "^1.2.17" + "@thi.ng/api": "^6.13.1", + "@thi.ng/dgraph": "^1.2.27", + "@thi.ng/dot": "^1.2.18" }, "files": [ "*.js", diff --git a/packages/dgraph/CHANGELOG.md b/packages/dgraph/CHANGELOG.md index aa9454bcd9..2b3d862c2f 100644 --- a/packages/dgraph/CHANGELOG.md +++ b/packages/dgraph/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.2.27](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@1.2.26...@thi.ng/dgraph@1.2.27) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/dgraph + + + + + ## [1.2.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@1.2.25...@thi.ng/dgraph@1.2.26) (2020-09-13) **Note:** Version bump only for package @thi.ng/dgraph diff --git a/packages/dgraph/package.json b/packages/dgraph/package.json index 9a73fe8ea8..43f8448dc0 100644 --- a/packages/dgraph/package.json +++ b/packages/dgraph/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dgraph", - "version": "1.2.26", + "version": "1.2.27", "description": "Type-agnostic directed acyclic graph (DAG) & graph operations", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/associative": "^5.0.6", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/associative": "^5.0.7", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/diff/CHANGELOG.md b/packages/diff/CHANGELOG.md index baa7be9a53..095f9f8840 100644 --- a/packages/diff/CHANGELOG.md +++ b/packages/diff/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.2.32](https://github.com/thi-ng/umbrella/compare/@thi.ng/diff@3.2.31...@thi.ng/diff@3.2.32) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/diff + + + + + ## [3.2.31](https://github.com/thi-ng/umbrella/compare/@thi.ng/diff@3.2.30...@thi.ng/diff@3.2.31) (2020-09-13) **Note:** Version bump only for package @thi.ng/diff diff --git a/packages/diff/package.json b/packages/diff/package.json index b19937207f..c5cc4ed79f 100644 --- a/packages/diff/package.json +++ b/packages/diff/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/diff", - "version": "3.2.31", + "version": "3.2.32", "description": "Customizable diff implementations for arrays (sequential) & objects (associative), with or without linear edit logs", "module": "./index.js", "main": "./lib/index.js", @@ -48,8 +48,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/equiv": "^1.0.31" + "@thi.ng/api": "^6.13.1", + "@thi.ng/equiv": "^1.0.32" }, "files": [ "*.js", diff --git a/packages/dl-asset/CHANGELOG.md b/packages/dl-asset/CHANGELOG.md index 5f19ae58a9..1b82c0360f 100644 --- a/packages/dl-asset/CHANGELOG.md +++ b/packages/dl-asset/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.4.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/dl-asset@0.4.5...@thi.ng/dl-asset@0.4.6) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/dl-asset + + + + + ## [0.4.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/dl-asset@0.4.4...@thi.ng/dl-asset@0.4.5) (2020-09-13) **Note:** Version bump only for package @thi.ng/dl-asset diff --git a/packages/dl-asset/package.json b/packages/dl-asset/package.json index b378bc63bc..505fdfa8d3 100644 --- a/packages/dl-asset/package.json +++ b/packages/dl-asset/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dl-asset", - "version": "0.4.5", + "version": "0.4.6", "description": "Local asset download for web apps, with automatic MIME type detection", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/mime": "^0.1.21" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/mime": "^0.1.22" }, "files": [ "*.js", diff --git a/packages/dlogic/CHANGELOG.md b/packages/dlogic/CHANGELOG.md index a8a67ba3c0..f82792239f 100644 --- a/packages/dlogic/CHANGELOG.md +++ b/packages/dlogic/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.32](https://github.com/thi-ng/umbrella/compare/@thi.ng/dlogic@1.0.31...@thi.ng/dlogic@1.0.32) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/dlogic + + + + + ## [1.0.31](https://github.com/thi-ng/umbrella/compare/@thi.ng/dlogic@1.0.30...@thi.ng/dlogic@1.0.31) (2020-09-13) **Note:** Version bump only for package @thi.ng/dlogic diff --git a/packages/dlogic/package.json b/packages/dlogic/package.json index 7e64ed7941..864c7fa984 100644 --- a/packages/dlogic/package.json +++ b/packages/dlogic/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dlogic", - "version": "1.0.31", + "version": "1.0.32", "description": "Assorted digital logic ops / constructs", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", + "@thi.ng/api": "^6.13.1", "tslib": "^2.0.1" }, "files": [ diff --git a/packages/dot/CHANGELOG.md b/packages/dot/CHANGELOG.md index 0d352e9646..37819db5eb 100644 --- a/packages/dot/CHANGELOG.md +++ b/packages/dot/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.2.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/dot@1.2.17...@thi.ng/dot@1.2.18) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/dot + + + + + ## [1.2.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/dot@1.2.16...@thi.ng/dot@1.2.17) (2020-09-13) **Note:** Version bump only for package @thi.ng/dot diff --git a/packages/dot/package.json b/packages/dot/package.json index eb43a278cb..5ee3e01931 100644 --- a/packages/dot/package.json +++ b/packages/dot/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dot", - "version": "1.2.17", + "version": "1.2.18", "description": "Graphviz document abstraction & serialization to DOT format", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9" }, "files": [ "*.js", diff --git a/packages/dsp-io-wav/CHANGELOG.md b/packages/dsp-io-wav/CHANGELOG.md index 9a1ac98d8b..33853fba41 100644 --- a/packages/dsp-io-wav/CHANGELOG.md +++ b/packages/dsp-io-wav/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.30](https://github.com/thi-ng/umbrella/compare/@thi.ng/dsp-io-wav@0.1.29...@thi.ng/dsp-io-wav@0.1.30) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/dsp-io-wav + + + + + ## [0.1.29](https://github.com/thi-ng/umbrella/compare/@thi.ng/dsp-io-wav@0.1.28...@thi.ng/dsp-io-wav@0.1.29) (2020-09-13) **Note:** Version bump only for package @thi.ng/dsp-io-wav diff --git a/packages/dsp-io-wav/package.json b/packages/dsp-io-wav/package.json index fa2d3c90aa..57dd1d0d26 100644 --- a/packages/dsp-io-wav/package.json +++ b/packages/dsp-io-wav/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dsp-io-wav", - "version": "0.1.29", + "version": "0.1.30", "description": "WAV file format generation", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/transducers-binary": "^0.5.29" + "@thi.ng/api": "^6.13.1", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/transducers-binary": "^0.5.30" }, "files": [ "*.js", diff --git a/packages/dsp/CHANGELOG.md b/packages/dsp/CHANGELOG.md index 25961bc074..fce46bdcb5 100644 --- a/packages/dsp/CHANGELOG.md +++ b/packages/dsp/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/dsp@2.1.1...@thi.ng/dsp@2.1.2) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/dsp + + + + + ## [2.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/dsp@2.1.0...@thi.ng/dsp@2.1.1) (2020-09-13) **Note:** Version bump only for package @thi.ng/dsp diff --git a/packages/dsp/package.json b/packages/dsp/package.json index 2975d9b6f8..d4338421c6 100644 --- a/packages/dsp/package.json +++ b/packages/dsp/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dsp", - "version": "2.1.1", + "version": "2.1.2", "description": "Composable signal generators, oscillators, filters, FFT, spectrum, windowing & related DSP utils", "module": "./index.js", "main": "./lib/index.js", @@ -49,12 +49,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/math": "^2.1.0", - "@thi.ng/random": "^2.0.1", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/math": "^2.1.1", + "@thi.ng/random": "^2.0.2", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/dual-algebra/CHANGELOG.md b/packages/dual-algebra/CHANGELOG.md index 35cf287415..7feae42d57 100644 --- a/packages/dual-algebra/CHANGELOG.md +++ b/packages/dual-algebra/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/dual-algebra@0.1.0...@thi.ng/dual-algebra@0.1.1) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/dual-algebra + + + + + # 0.1.0 (2020-09-13) diff --git a/packages/dual-algebra/package.json b/packages/dual-algebra/package.json index 33e55a4c1c..6be474b2be 100644 --- a/packages/dual-algebra/package.json +++ b/packages/dual-algebra/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dual-algebra", - "version": "0.1.0", + "version": "0.1.1", "description": "Multivariate dual number algebra, automatic differentiation", "module": "./index.js", "main": "./lib/index.js", @@ -48,7 +48,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0" + "@thi.ng/api": "^6.13.1" }, "files": [ "*.js", diff --git a/packages/dynvar/CHANGELOG.md b/packages/dynvar/CHANGELOG.md index 045c560c96..8ea4f5b010 100644 --- a/packages/dynvar/CHANGELOG.md +++ b/packages/dynvar/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/dynvar@0.1.23...@thi.ng/dynvar@0.1.24) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/dynvar + + + + + ## [0.1.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/dynvar@0.1.22...@thi.ng/dynvar@0.1.23) (2020-09-13) **Note:** Version bump only for package @thi.ng/dynvar diff --git a/packages/dynvar/package.json b/packages/dynvar/package.json index 9e485d03f0..c7bc649913 100644 --- a/packages/dynvar/package.json +++ b/packages/dynvar/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dynvar", - "version": "0.1.23", + "version": "0.1.24", "description": "Dynamically scoped variable bindings", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0" + "@thi.ng/api": "^6.13.1" }, "files": [ "*.js", diff --git a/packages/ecs/CHANGELOG.md b/packages/ecs/CHANGELOG.md index 1041dc8a0a..d1bc541f5d 100644 --- a/packages/ecs/CHANGELOG.md +++ b/packages/ecs/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.3.34](https://github.com/thi-ng/umbrella/compare/@thi.ng/ecs@0.3.33...@thi.ng/ecs@0.3.34) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/ecs + + + + + ## [0.3.33](https://github.com/thi-ng/umbrella/compare/@thi.ng/ecs@0.3.32...@thi.ng/ecs@0.3.33) (2020-09-13) **Note:** Version bump only for package @thi.ng/ecs diff --git a/packages/ecs/package.json b/packages/ecs/package.json index a9d03b2cff..a79f7f09e6 100644 --- a/packages/ecs/package.json +++ b/packages/ecs/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/ecs", - "version": "0.3.33", + "version": "0.3.34", "description": "Entity Component System based around typed arrays & sparse sets", "module": "./index.js", "main": "./lib/index.js", @@ -40,7 +40,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/equiv": "^1.0.31", + "@thi.ng/equiv": "^1.0.32", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", @@ -50,13 +50,13 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/associative": "^5.0.6", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/dcons": "^2.2.31", - "@thi.ng/idgen": "^0.2.22", - "@thi.ng/transducers": "^7.3.1", + "@thi.ng/api": "^6.13.1", + "@thi.ng/associative": "^5.0.7", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/dcons": "^2.2.32", + "@thi.ng/idgen": "^0.2.23", + "@thi.ng/transducers": "^7.4.0", "tslib": "^2.0.1" }, "files": [ diff --git a/packages/egf/CHANGELOG.md b/packages/egf/CHANGELOG.md new file mode 100644 index 0000000000..e70698cf77 --- /dev/null +++ b/packages/egf/CHANGELOG.md @@ -0,0 +1,19 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.3.0 (2020-09-22) + + +### Features + +* **egf:** add <> escape hatch for prefix IDs ([5aca174](https://github.com/thi-ng/umbrella/commit/5aca174cd4ceef7c03c08cb27d736eb5dd1fd35c)) +* **egf:** add escape seq support in parser ([c7fe807](https://github.com/thi-ng/umbrella/commit/c7fe807fb726388d707e839140249a09028533db)) +* **egf:** add include cycle breaker, prop merge logic ([eb4d7d1](https://github.com/thi-ng/umbrella/commit/eb4d7d138524fca7421c414a743824ae40807338)), closes [#237](https://github.com/thi-ng/umbrella/issues/237) +* **egf:** add prune option & pruneNodes() ([634a118](https://github.com/thi-ng/umbrella/commit/634a118e2b612d5979fca7b897ed3d8bf512f28b)) +* **egf:** add toEGF() implementation ([ed6d3a8](https://github.com/thi-ng/umbrella/commit/ed6d3a8d0e7140ed12a5948057f736aa634ca7f6)) +* **egf:** fix [#235](https://github.com/thi-ng/umbrella/issues/235), replace #ref tag w/ `->` form ([0dd2f2d](https://github.com/thi-ng/umbrella/commit/0dd2f2d4efe21afce28a00191ee1047a7fe462b6)) +* **egf:** import as new package ([76b472d](https://github.com/thi-ng/umbrella/commit/76b472d017f3bf456db8204158de6ac4746447b3)) +* **egf:** update DOT export prop filter ([41a70ee](https://github.com/thi-ng/umbrella/commit/41a70eeaada5b91d7507a52b6b45083548002cda)) +* **egf:** update tag parser handling ([55b119c](https://github.com/thi-ng/umbrella/commit/55b119ce497f67e939ba865c25930348aaaad380)) diff --git a/packages/egf/package.json b/packages/egf/package.json index 0a50a35784..5ef189d54b 100644 --- a/packages/egf/package.json +++ b/packages/egf/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/egf", - "version": "0.2.2", + "version": "0.3.0", "description": "Extensible Graph Format", "module": "./index.js", "main": "./lib/index.js", @@ -34,7 +34,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/equiv": "^1.0.31", + "@thi.ng/equiv": "^1.0.32", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", @@ -44,14 +44,14 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/associative": "^5.0.6", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/dot": "^1.2.17", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/prefixes": "^0.1.5", - "@thi.ng/strings": "^1.9.6", - "@thi.ng/transducers-binary": "^0.5.29" + "@thi.ng/api": "^6.13.1", + "@thi.ng/associative": "^5.0.7", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/dot": "^1.2.18", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/prefixes": "^0.1.6", + "@thi.ng/strings": "^1.10.0", + "@thi.ng/transducers-binary": "^0.5.30" }, "files": [ "*.js", diff --git a/packages/equiv/CHANGELOG.md b/packages/equiv/CHANGELOG.md index d699f83bde..7642428c2f 100644 --- a/packages/equiv/CHANGELOG.md +++ b/packages/equiv/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.32](https://github.com/thi-ng/umbrella/compare/@thi.ng/equiv@1.0.31...@thi.ng/equiv@1.0.32) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/equiv + + + + + ## [1.0.31](https://github.com/thi-ng/umbrella/compare/@thi.ng/equiv@1.0.30...@thi.ng/equiv@1.0.31) (2020-09-13) **Note:** Version bump only for package @thi.ng/equiv diff --git a/packages/equiv/package.json b/packages/equiv/package.json index 7dd7d86a3e..a5f14e05e2 100644 --- a/packages/equiv/package.json +++ b/packages/equiv/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/equiv", - "version": "1.0.31", + "version": "1.0.32", "description": "Extensible deep value equivalence checking for any data types", "module": "./index.js", "main": "./lib/index.js", diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index 148105499a..f21257689a 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.2.22](https://github.com/thi-ng/umbrella/compare/@thi.ng/errors@1.2.21...@thi.ng/errors@1.2.22) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/errors + + + + + ## [1.2.21](https://github.com/thi-ng/umbrella/compare/@thi.ng/errors@1.2.20...@thi.ng/errors@1.2.21) (2020-09-13) **Note:** Version bump only for package @thi.ng/errors diff --git a/packages/errors/package.json b/packages/errors/package.json index ed41ed423c..a527a2418e 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/errors", - "version": "1.2.21", + "version": "1.2.22", "description": "Custom error types and error factory functions", "module": "./index.js", "main": "./lib/index.js", diff --git a/packages/fsm/CHANGELOG.md b/packages/fsm/CHANGELOG.md index d7176e1565..94dd163ae7 100644 --- a/packages/fsm/CHANGELOG.md +++ b/packages/fsm/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.4.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/fsm@2.4.25...@thi.ng/fsm@2.4.26) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/fsm + + + + + ## [2.4.25](https://github.com/thi-ng/umbrella/compare/@thi.ng/fsm@2.4.24...@thi.ng/fsm@2.4.25) (2020-09-13) **Note:** Version bump only for package @thi.ng/fsm diff --git a/packages/fsm/package.json b/packages/fsm/package.json index 94adcc7a15..7abc886381 100644 --- a/packages/fsm/package.json +++ b/packages/fsm/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/fsm", - "version": "2.4.25", + "version": "2.4.26", "description": "Composable primitives for building declarative, transducer based Finite-State Machines & matchers for arbitrary data streams", "module": "./index.js", "main": "./lib/index.js", @@ -49,12 +49,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/strings": "^1.9.6", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/strings": "^1.10.0", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/geom-accel/CHANGELOG.md b/packages/geom-accel/CHANGELOG.md index c53ce1e034..006cba67ae 100644 --- a/packages/geom-accel/CHANGELOG.md +++ b/packages/geom-accel/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-accel@2.1.23...@thi.ng/geom-accel@2.1.24) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-accel + + + + + ## [2.1.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-accel@2.1.22...@thi.ng/geom-accel@2.1.23) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-accel diff --git a/packages/geom-accel/package.json b/packages/geom-accel/package.json index 37c6279e15..7c5d5e4421 100644 --- a/packages/geom-accel/package.json +++ b/packages/geom-accel/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-accel", - "version": "2.1.23", + "version": "2.1.24", "description": "n-D spatial indexing data structures with a shared ES6 Map/Set-like API", "module": "./index.js", "main": "./lib/index.js", @@ -50,16 +50,16 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/geom-isec": "^0.5.8", - "@thi.ng/heaps": "^1.2.24", - "@thi.ng/math": "^2.1.0", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/geom-isec": "^0.6.0", + "@thi.ng/heaps": "^1.2.25", + "@thi.ng/math": "^2.1.1", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-api/CHANGELOG.md b/packages/geom-api/CHANGELOG.md index b56ed676bf..d94af29527 100644 --- a/packages/geom-api/CHANGELOG.md +++ b/packages/geom-api/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-api@1.0.34...@thi.ng/geom-api@1.1.0) (2020-09-22) + + +### Features + +* **geom-api:** add Type.TEXT/3 ([0a45ef8](https://github.com/thi-ng/umbrella/commit/0a45ef8aa99d3dab1bb98c503cf87d1bef0ab8e2)) + + + + + ## [1.0.34](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-api@1.0.33...@thi.ng/geom-api@1.0.34) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-api diff --git a/packages/geom-api/package.json b/packages/geom-api/package.json index c108e85d13..c77e72eec3 100644 --- a/packages/geom-api/package.json +++ b/packages/geom-api/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-api", - "version": "1.0.34", + "version": "1.1.0", "description": "Shared type & interface declarations for @thi.ng/geom packages", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-arc/CHANGELOG.md b/packages/geom-arc/CHANGELOG.md index a50c5c2bef..f2be5096eb 100644 --- a/packages/geom-arc/CHANGELOG.md +++ b/packages/geom-arc/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.3.13](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-arc@0.3.12...@thi.ng/geom-arc@0.3.13) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-arc + + + + + ## [0.3.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-arc@0.3.11...@thi.ng/geom-arc@0.3.12) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-arc diff --git a/packages/geom-arc/package.json b/packages/geom-arc/package.json index 48ccf2c36d..321179f068 100644 --- a/packages/geom-arc/package.json +++ b/packages/geom-arc/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-arc", - "version": "0.3.12", + "version": "0.3.13", "description": "2D circular / elliptic arc operations", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/checks": "^2.7.8", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/geom-resample": "^0.2.45", - "@thi.ng/math": "^2.1.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/checks": "^2.7.9", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/geom-resample": "^0.2.46", + "@thi.ng/math": "^2.1.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-clip-line/CHANGELOG.md b/packages/geom-clip-line/CHANGELOG.md index 6285ba5302..a99c68f8b9 100644 --- a/packages/geom-clip-line/CHANGELOG.md +++ b/packages/geom-clip-line/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.2.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-clip-line@1.2.8...@thi.ng/geom-clip-line@1.2.9) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-clip-line + + + + + ## [1.2.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-clip-line@1.2.7...@thi.ng/geom-clip-line@1.2.8) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-clip-line diff --git a/packages/geom-clip-line/package.json b/packages/geom-clip-line/package.json index e4b8f90566..120aeede21 100644 --- a/packages/geom-clip-line/package.json +++ b/packages/geom-clip-line/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-clip-line", - "version": "1.2.8", + "version": "1.2.9", "description": "2D line clipping (Liang-Barsky)", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/geom-isec": "^0.5.8", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/geom-isec": "^0.6.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-clip-poly/CHANGELOG.md b/packages/geom-clip-poly/CHANGELOG.md index 46b3cd7d78..5c1a805624 100644 --- a/packages/geom-clip-poly/CHANGELOG.md +++ b/packages/geom-clip-poly/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.34](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-clip-poly@1.0.33...@thi.ng/geom-clip-poly@1.0.34) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-clip-poly + + + + + ## [1.0.33](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-clip-poly@1.0.32...@thi.ng/geom-clip-poly@1.0.33) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-clip-poly diff --git a/packages/geom-clip-poly/package.json b/packages/geom-clip-poly/package.json index ca74369171..450fd35508 100644 --- a/packages/geom-clip-poly/package.json +++ b/packages/geom-clip-poly/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-clip-poly", - "version": "1.0.33", + "version": "1.0.34", "description": "2D convex polygon clipping (Sutherland-Hodgeman)", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/geom-isec": "^0.5.8", - "@thi.ng/geom-poly-utils": "^0.1.64", - "@thi.ng/math": "^2.1.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/geom-isec": "^0.6.0", + "@thi.ng/geom-poly-utils": "^0.1.65", + "@thi.ng/math": "^2.1.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-closest-point/CHANGELOG.md b/packages/geom-closest-point/CHANGELOG.md index 0bc6d40210..3c5e807790 100644 --- a/packages/geom-closest-point/CHANGELOG.md +++ b/packages/geom-closest-point/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.5.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-closest-point@0.4.0...@thi.ng/geom-closest-point@0.5.0) (2020-09-22) + + +### Bug Fixes + +* **geom-closest-point:** update closestPointPolyline() ([1358bac](https://github.com/thi-ng/umbrella/commit/1358bac1a95359340b19adb91b1813edf3e1645a)) + + +### Features + +* **geom-closest-point:** add support for custom dist fn ([95557f6](https://github.com/thi-ng/umbrella/commit/95557f6716071a92433868ce8536ca1c38a54073)) + + + + + # [0.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-closest-point@0.3.44...@thi.ng/geom-closest-point@0.4.0) (2020-09-13) diff --git a/packages/geom-closest-point/package.json b/packages/geom-closest-point/package.json index b879fbd96d..a47afd14f7 100644 --- a/packages/geom-closest-point/package.json +++ b/packages/geom-closest-point/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-closest-point", - "version": "0.4.0", + "version": "0.5.0", "description": "2D / 3D closest point / proximity helpers", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/math": "^2.1.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/math": "^2.1.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-fuzz/CHANGELOG.md b/packages/geom-fuzz/CHANGELOG.md index 6432722dc3..3c1359e0f4 100644 --- a/packages/geom-fuzz/CHANGELOG.md +++ b/packages/geom-fuzz/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-fuzz@0.1.18...@thi.ng/geom-fuzz@0.1.19) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-fuzz + + + + + ## [0.1.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-fuzz@0.1.17...@thi.ng/geom-fuzz@0.1.18) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-fuzz diff --git a/packages/geom-fuzz/package.json b/packages/geom-fuzz/package.json index 92eb6111a5..6459036da6 100644 --- a/packages/geom-fuzz/package.json +++ b/packages/geom-fuzz/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-fuzz", - "version": "0.1.18", + "version": "0.1.19", "description": "Highly configurable, fuzzy line & polygon creation with presets and composable fill & stroke styles. Canvas & SVG support", "module": "./index.js", "main": "./lib/index.js", @@ -48,16 +48,16 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/associative": "^5.0.6", - "@thi.ng/color": "^1.2.16", - "@thi.ng/geom": "^1.11.8", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/geom-clip-line": "^1.2.8", - "@thi.ng/geom-resample": "^0.2.45", - "@thi.ng/grid-iterators": "^0.4.10", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/associative": "^5.0.7", + "@thi.ng/color": "^1.2.17", + "@thi.ng/geom": "^1.12.0", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/geom-clip-line": "^1.2.9", + "@thi.ng/geom-resample": "^0.2.46", + "@thi.ng/grid-iterators": "^0.4.11", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-hull/CHANGELOG.md b/packages/geom-hull/CHANGELOG.md index 7a56c07082..83cd6d70b1 100644 --- a/packages/geom-hull/CHANGELOG.md +++ b/packages/geom-hull/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.0.66](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-hull@0.0.65...@thi.ng/geom-hull@0.0.66) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-hull + + + + + ## [0.0.65](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-hull@0.0.64...@thi.ng/geom-hull@0.0.65) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-hull diff --git a/packages/geom-hull/package.json b/packages/geom-hull/package.json index 72efdd4dc3..9f24643d18 100644 --- a/packages/geom-hull/package.json +++ b/packages/geom-hull/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-hull", - "version": "0.0.65", + "version": "0.0.66", "description": "Fast 2D convex hull (Graham Scan)", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/math": "^2.1.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/math": "^2.1.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-io-obj/CHANGELOG.md b/packages/geom-io-obj/CHANGELOG.md index 52ec8918a7..d9e4bd10ee 100644 --- a/packages/geom-io-obj/CHANGELOG.md +++ b/packages/geom-io-obj/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-io-obj@0.1.23...@thi.ng/geom-io-obj@0.1.24) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-io-obj + + + + + ## [0.1.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-io-obj@0.1.22...@thi.ng/geom-io-obj@0.1.23) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-io-obj diff --git a/packages/geom-io-obj/package.json b/packages/geom-io-obj/package.json index 6756fdd33c..b37a838eea 100644 --- a/packages/geom-io-obj/package.json +++ b/packages/geom-io-obj/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-io-obj", - "version": "0.1.23", + "version": "0.1.24", "description": "Wavefront OBJ parser (& exporter soon)", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-isec/CHANGELOG.md b/packages/geom-isec/CHANGELOG.md index 812a420fde..a4cf1254ca 100644 --- a/packages/geom-isec/CHANGELOG.md +++ b/packages/geom-isec/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.6.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-isec@0.5.8...@thi.ng/geom-isec@0.6.0) (2020-09-22) + + +### Bug Fixes + +* **geom-isec:** testCenteredAABBSphere() ([95a29b1](https://github.com/thi-ng/umbrella/commit/95a29b199077c741c83f4f78871f9627264f198d)) + + +### Features + +* **geom-isec:** update ray-line/polyline fns ([b3775b0](https://github.com/thi-ng/umbrella/commit/b3775b08e1c33cf7c2e94e0a4b119b33e4a104ba)) + + + + + ## [0.5.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-isec@0.5.7...@thi.ng/geom-isec@0.5.8) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-isec diff --git a/packages/geom-isec/package.json b/packages/geom-isec/package.json index e5a7d4c35b..56322ab8ef 100644 --- a/packages/geom-isec/package.json +++ b/packages/geom-isec/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-isec", - "version": "0.5.8", + "version": "0.6.0", "description": "2D/3D shape intersection checks", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/geom-closest-point": "^0.4.0", - "@thi.ng/math": "^2.1.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/geom-closest-point": "^0.5.0", + "@thi.ng/math": "^2.1.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-isoline/CHANGELOG.md b/packages/geom-isoline/CHANGELOG.md index 7c992c2292..4a8bf3d923 100644 --- a/packages/geom-isoline/CHANGELOG.md +++ b/packages/geom-isoline/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.64](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-isoline@0.1.63...@thi.ng/geom-isoline@0.1.64) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-isoline + + + + + ## [0.1.63](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-isoline@0.1.62...@thi.ng/geom-isoline@0.1.63) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-isoline diff --git a/packages/geom-isoline/package.json b/packages/geom-isoline/package.json index 8413a7c939..54599e44e8 100644 --- a/packages/geom-isoline/package.json +++ b/packages/geom-isoline/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-isoline", - "version": "0.1.63", + "version": "0.1.64", "description": "Fast 2D contour line extraction / generation", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-poly-utils/CHANGELOG.md b/packages/geom-poly-utils/CHANGELOG.md index e4da352119..8fc5c23816 100644 --- a/packages/geom-poly-utils/CHANGELOG.md +++ b/packages/geom-poly-utils/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.65](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-poly-utils@0.1.64...@thi.ng/geom-poly-utils@0.1.65) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-poly-utils + + + + + ## [0.1.64](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-poly-utils@0.1.63...@thi.ng/geom-poly-utils@0.1.64) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-poly-utils diff --git a/packages/geom-poly-utils/package.json b/packages/geom-poly-utils/package.json index 2401738946..f065ee9e5b 100644 --- a/packages/geom-poly-utils/package.json +++ b/packages/geom-poly-utils/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-poly-utils", - "version": "0.1.64", + "version": "0.1.65", "description": "2D polygon / triangle analysis & processing utilities", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/math": "^2.1.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/math": "^2.1.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-resample/CHANGELOG.md b/packages/geom-resample/CHANGELOG.md index 3ae41df3ed..2ebce87ed6 100644 --- a/packages/geom-resample/CHANGELOG.md +++ b/packages/geom-resample/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.46](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-resample@0.2.45...@thi.ng/geom-resample@0.2.46) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-resample + + + + + ## [0.2.45](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-resample@0.2.44...@thi.ng/geom-resample@0.2.45) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-resample diff --git a/packages/geom-resample/package.json b/packages/geom-resample/package.json index ccbdb344be..96ab527121 100644 --- a/packages/geom-resample/package.json +++ b/packages/geom-resample/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-resample", - "version": "0.2.45", + "version": "0.2.46", "description": "Customizable nD polyline interpolation, re-sampling, splitting & nearest point computation", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/checks": "^2.7.8", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/geom-closest-point": "^0.4.0", - "@thi.ng/math": "^2.1.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/checks": "^2.7.9", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/geom-closest-point": "^0.5.0", + "@thi.ng/math": "^2.1.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-splines/CHANGELOG.md b/packages/geom-splines/CHANGELOG.md index 2c58fba04b..f1088afe4c 100644 --- a/packages/geom-splines/CHANGELOG.md +++ b/packages/geom-splines/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.5.33](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-splines@0.5.32...@thi.ng/geom-splines@0.5.33) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-splines + + + + + ## [0.5.32](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-splines@0.5.31...@thi.ng/geom-splines@0.5.32) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-splines diff --git a/packages/geom-splines/package.json b/packages/geom-splines/package.json index d71179a746..2062a36144 100644 --- a/packages/geom-splines/package.json +++ b/packages/geom-splines/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-splines", - "version": "0.5.32", + "version": "0.5.33", "description": "nD cubic & quadratic curve analysis, conversion, interpolation, splitting", "module": "./index.js", "main": "./lib/index.js", @@ -49,13 +49,13 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/geom-arc": "^0.3.12", - "@thi.ng/geom-resample": "^0.2.45", - "@thi.ng/math": "^2.1.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/geom-arc": "^0.3.13", + "@thi.ng/geom-resample": "^0.2.46", + "@thi.ng/math": "^2.1.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-subdiv-curve/CHANGELOG.md b/packages/geom-subdiv-curve/CHANGELOG.md index 51736af2a2..81b803d80b 100644 --- a/packages/geom-subdiv-curve/CHANGELOG.md +++ b/packages/geom-subdiv-curve/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.63](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-subdiv-curve@0.1.62...@thi.ng/geom-subdiv-curve@0.1.63) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-subdiv-curve + + + + + ## [0.1.62](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-subdiv-curve@0.1.61...@thi.ng/geom-subdiv-curve@0.1.62) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-subdiv-curve diff --git a/packages/geom-subdiv-curve/package.json b/packages/geom-subdiv-curve/package.json index 4a51dfb086..a14807e26d 100644 --- a/packages/geom-subdiv-curve/package.json +++ b/packages/geom-subdiv-curve/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-subdiv-curve", - "version": "0.1.62", + "version": "0.1.63", "description": "Freely customizable, iterative nD subdivision curves for open / closed geometries", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-tessellate/CHANGELOG.md b/packages/geom-tessellate/CHANGELOG.md index a24db410a2..5c7f310b6f 100644 --- a/packages/geom-tessellate/CHANGELOG.md +++ b/packages/geom-tessellate/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.47](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-tessellate@0.2.46...@thi.ng/geom-tessellate@0.2.47) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-tessellate + + + + + ## [0.2.46](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-tessellate@0.2.45...@thi.ng/geom-tessellate@0.2.46) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-tessellate diff --git a/packages/geom-tessellate/package.json b/packages/geom-tessellate/package.json index e40c9bdfe9..0794d5dc79 100644 --- a/packages/geom-tessellate/package.json +++ b/packages/geom-tessellate/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-tessellate", - "version": "0.2.46", + "version": "0.2.47", "description": "2D/3D convex polygon tessellators", "module": "./index.js", "main": "./lib/index.js", @@ -49,12 +49,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/checks": "^2.7.8", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/geom-isec": "^0.5.8", - "@thi.ng/geom-poly-utils": "^0.1.64", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/checks": "^2.7.9", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/geom-isec": "^0.6.0", + "@thi.ng/geom-poly-utils": "^0.1.65", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom-voronoi/CHANGELOG.md b/packages/geom-voronoi/CHANGELOG.md index 851533348e..9ffc6c9722 100644 --- a/packages/geom-voronoi/CHANGELOG.md +++ b/packages/geom-voronoi/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-voronoi@0.2.8...@thi.ng/geom-voronoi@0.2.9) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/geom-voronoi + + + + + ## [0.2.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-voronoi@0.2.7...@thi.ng/geom-voronoi@0.2.8) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom-voronoi diff --git a/packages/geom-voronoi/package.json b/packages/geom-voronoi/package.json index c1c922f9da..9acd144c0d 100644 --- a/packages/geom-voronoi/package.json +++ b/packages/geom-voronoi/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-voronoi", - "version": "0.2.8", + "version": "0.2.9", "description": "Fast, incremental 2D Delaunay & Voronoi mesh implementation", "module": "./index.js", "main": "./lib/index.js", @@ -49,15 +49,15 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/geom-clip-line": "^1.2.8", - "@thi.ng/geom-clip-poly": "^1.0.33", - "@thi.ng/geom-isec": "^0.5.8", - "@thi.ng/geom-poly-utils": "^0.1.64", - "@thi.ng/math": "^2.1.0", - "@thi.ng/quad-edge": "^0.2.23", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/geom-clip-line": "^1.2.9", + "@thi.ng/geom-clip-poly": "^1.0.34", + "@thi.ng/geom-isec": "^0.6.0", + "@thi.ng/geom-poly-utils": "^0.1.65", + "@thi.ng/math": "^2.1.1", + "@thi.ng/quad-edge": "^0.2.24", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/geom/CHANGELOG.md b/packages/geom/CHANGELOG.md index 6ab42fbd8d..e91b245cfc 100644 --- a/packages/geom/CHANGELOG.md +++ b/packages/geom/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.12.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom@1.11.8...@thi.ng/geom@1.12.0) (2020-09-22) + + +### Features + +* **geom:** add basic text support ([9d1424d](https://github.com/thi-ng/umbrella/commit/9d1424d1c57e4d2c55fb6cfdd507f3ca7cd85dc3)) + + + + + ## [1.11.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom@1.11.7...@thi.ng/geom@1.11.8) (2020-09-13) **Note:** Version bump only for package @thi.ng/geom diff --git a/packages/geom/package.json b/packages/geom/package.json index 692d189f31..11c6ad373d 100644 --- a/packages/geom/package.json +++ b/packages/geom/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom", - "version": "1.11.8", + "version": "1.12.0", "description": "Functional, polymorphic API for 2D geometry types & SVG generation", "module": "./index.js", "main": "./lib/index.js", @@ -49,32 +49,32 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/defmulti": "^1.2.25", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/geom-arc": "^0.3.12", - "@thi.ng/geom-clip-line": "^1.2.8", - "@thi.ng/geom-clip-poly": "^1.0.33", - "@thi.ng/geom-closest-point": "^0.4.0", - "@thi.ng/geom-hull": "^0.0.65", - "@thi.ng/geom-isec": "^0.5.8", - "@thi.ng/geom-poly-utils": "^0.1.64", - "@thi.ng/geom-resample": "^0.2.45", - "@thi.ng/geom-splines": "^0.5.32", - "@thi.ng/geom-subdiv-curve": "^0.1.62", - "@thi.ng/geom-tessellate": "^0.2.46", - "@thi.ng/hiccup": "^3.6.0", - "@thi.ng/hiccup-svg": "^3.6.0", - "@thi.ng/math": "^2.1.0", - "@thi.ng/matrices": "^0.6.32", - "@thi.ng/random": "^2.0.1", - "@thi.ng/strings": "^1.9.6", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/defmulti": "^1.2.26", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/geom-arc": "^0.3.13", + "@thi.ng/geom-clip-line": "^1.2.9", + "@thi.ng/geom-clip-poly": "^1.0.34", + "@thi.ng/geom-closest-point": "^0.5.0", + "@thi.ng/geom-hull": "^0.0.66", + "@thi.ng/geom-isec": "^0.6.0", + "@thi.ng/geom-poly-utils": "^0.1.65", + "@thi.ng/geom-resample": "^0.2.46", + "@thi.ng/geom-splines": "^0.5.33", + "@thi.ng/geom-subdiv-curve": "^0.1.63", + "@thi.ng/geom-tessellate": "^0.2.47", + "@thi.ng/hiccup": "^3.6.1", + "@thi.ng/hiccup-svg": "^3.6.1", + "@thi.ng/math": "^2.1.1", + "@thi.ng/matrices": "^0.6.33", + "@thi.ng/random": "^2.0.2", + "@thi.ng/strings": "^1.10.0", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/gp/CHANGELOG.md b/packages/gp/CHANGELOG.md index 562789d68b..781194f228 100644 --- a/packages/gp/CHANGELOG.md +++ b/packages/gp/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.32](https://github.com/thi-ng/umbrella/compare/@thi.ng/gp@0.1.31...@thi.ng/gp@0.1.32) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/gp + + + + + ## [0.1.31](https://github.com/thi-ng/umbrella/compare/@thi.ng/gp@0.1.30...@thi.ng/gp@0.1.31) (2020-09-13) **Note:** Version bump only for package @thi.ng/gp diff --git a/packages/gp/package.json b/packages/gp/package.json index 97ccc009e1..7c55b57c37 100644 --- a/packages/gp/package.json +++ b/packages/gp/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/gp", - "version": "0.1.31", + "version": "0.1.32", "description": "Genetic programming helpers & strategies (tree based & multi-expression programming)", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/math": "^2.1.0", - "@thi.ng/random": "^2.0.1", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/zipper": "^0.1.25" + "@thi.ng/api": "^6.13.1", + "@thi.ng/math": "^2.1.1", + "@thi.ng/random": "^2.0.2", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/zipper": "^0.1.26" }, "files": [ "*.js", diff --git a/packages/grid-iterators/CHANGELOG.md b/packages/grid-iterators/CHANGELOG.md index ab5fc98b09..21d896bdc7 100644 --- a/packages/grid-iterators/CHANGELOG.md +++ b/packages/grid-iterators/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.4.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@0.4.10...@thi.ng/grid-iterators@0.4.11) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/grid-iterators + + + + + ## [0.4.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@0.4.9...@thi.ng/grid-iterators@0.4.10) (2020-09-13) **Note:** Version bump only for package @thi.ng/grid-iterators diff --git a/packages/grid-iterators/package.json b/packages/grid-iterators/package.json index 03a73253a8..0a825854b1 100644 --- a/packages/grid-iterators/package.json +++ b/packages/grid-iterators/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/grid-iterators", - "version": "0.4.10", + "version": "0.4.11", "description": "2D grid iterators w/ multiple orderings", "module": "./index.js", "main": "./lib/index.js", @@ -50,11 +50,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/morton": "^2.0.24", - "@thi.ng/random": "^2.0.1", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/morton": "^2.0.25", + "@thi.ng/random": "^2.0.2", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/hdiff/CHANGELOG.md b/packages/hdiff/CHANGELOG.md index cdaf14a933..8de0af9b43 100644 --- a/packages/hdiff/CHANGELOG.md +++ b/packages/hdiff/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdiff@0.1.15...@thi.ng/hdiff@0.1.16) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hdiff + + + + + ## [0.1.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdiff@0.1.14...@thi.ng/hdiff@0.1.15) (2020-09-13) **Note:** Version bump only for package @thi.ng/hdiff diff --git a/packages/hdiff/package.json b/packages/hdiff/package.json index 924df98cce..5c773087a0 100644 --- a/packages/hdiff/package.json +++ b/packages/hdiff/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdiff", - "version": "0.1.15", + "version": "0.1.16", "description": "String diffing w/ hiccup output for further processing, e.g. with @thi.ng/hdom, @thi.ng/hiccup. Includes CLI util to generate HTML, with theme support and code folding", "module": "./index.js", "main": "./lib/index.js", @@ -51,11 +51,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/diff": "^3.2.31", - "@thi.ng/hiccup": "^3.6.0", - "@thi.ng/hiccup-css": "^1.1.38", - "@thi.ng/strings": "^1.9.6" + "@thi.ng/api": "^6.13.1", + "@thi.ng/diff": "^3.2.32", + "@thi.ng/hiccup": "^3.6.1", + "@thi.ng/hiccup-css": "^1.1.39", + "@thi.ng/strings": "^1.10.0" }, "files": [ "*.js", diff --git a/packages/hdom-canvas/CHANGELOG.md b/packages/hdom-canvas/CHANGELOG.md index ce1d69d512..9c4586aae8 100644 --- a/packages/hdom-canvas/CHANGELOG.md +++ b/packages/hdom-canvas/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-canvas@3.0.18...@thi.ng/hdom-canvas@3.0.19) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hdom-canvas + + + + + ## [3.0.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-canvas@3.0.17...@thi.ng/hdom-canvas@3.0.18) (2020-09-13) **Note:** Version bump only for package @thi.ng/hdom-canvas diff --git a/packages/hdom-canvas/package.json b/packages/hdom-canvas/package.json index 75f24bc2c9..3eb3fb10a9 100644 --- a/packages/hdom-canvas/package.json +++ b/packages/hdom-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdom-canvas", - "version": "3.0.18", + "version": "3.0.19", "description": "@thi.ng/hdom component wrapper for declarative canvas scenegraphs", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/diff": "^3.2.31", - "@thi.ng/hdom": "^8.2.9", - "@thi.ng/hiccup-canvas": "^1.1.8" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/diff": "^3.2.32", + "@thi.ng/hdom": "^8.2.10", + "@thi.ng/hiccup-canvas": "^1.1.9" }, "files": [ "*.js", diff --git a/packages/hdom-components/CHANGELOG.md b/packages/hdom-components/CHANGELOG.md index 6fbeeaeec4..fd64f0573e 100644 --- a/packages/hdom-components/CHANGELOG.md +++ b/packages/hdom-components/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [4.0.13](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@4.0.12...@thi.ng/hdom-components@4.0.13) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hdom-components + + + + + ## [4.0.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@4.0.11...@thi.ng/hdom-components@4.0.12) (2020-09-13) **Note:** Version bump only for package @thi.ng/hdom-components diff --git a/packages/hdom-components/package.json b/packages/hdom-components/package.json index 9e732da35d..ff0a23e8c3 100644 --- a/packages/hdom-components/package.json +++ b/packages/hdom-components/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdom-components", - "version": "4.0.12", + "version": "4.0.13", "description": "Raw, skinnable UI & SVG components for @thi.ng/hdom", "module": "./index.js", "main": "./lib/index.js", @@ -49,12 +49,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/adapt-dpi": "^1.0.8", - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/math": "^2.1.0", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/transducers-stats": "^1.1.38" + "@thi.ng/adapt-dpi": "^1.0.9", + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/math": "^2.1.1", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/transducers-stats": "^1.1.39" }, "files": [ "*.js", diff --git a/packages/hdom-mock/CHANGELOG.md b/packages/hdom-mock/CHANGELOG.md index 1bb7cdaed0..1ead91b60d 100644 --- a/packages/hdom-mock/CHANGELOG.md +++ b/packages/hdom-mock/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.42](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-mock@1.1.41...@thi.ng/hdom-mock@1.1.42) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hdom-mock + + + + + ## [1.1.41](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-mock@1.1.40...@thi.ng/hdom-mock@1.1.41) (2020-09-13) **Note:** Version bump only for package @thi.ng/hdom-mock diff --git a/packages/hdom-mock/package.json b/packages/hdom-mock/package.json index d761354c36..50b3180293 100644 --- a/packages/hdom-mock/package.json +++ b/packages/hdom-mock/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdom-mock", - "version": "1.1.41", + "version": "1.1.42", "description": "Mock base implementation for @thi.ng/hdom API", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/hdom": "^8.2.9" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/hdom": "^8.2.10" }, "files": [ "*.js", diff --git a/packages/hdom/CHANGELOG.md b/packages/hdom/CHANGELOG.md index 42af5c9291..1623b674e0 100644 --- a/packages/hdom/CHANGELOG.md +++ b/packages/hdom/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [8.2.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@8.2.9...@thi.ng/hdom@8.2.10) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hdom + + + + + ## [8.2.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@8.2.8...@thi.ng/hdom@8.2.9) (2020-09-13) **Note:** Version bump only for package @thi.ng/hdom diff --git a/packages/hdom/package.json b/packages/hdom/package.json index 7e404ac838..126652cf3d 100644 --- a/packages/hdom/package.json +++ b/packages/hdom/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdom", - "version": "8.2.9", + "version": "8.2.10", "description": "Lightweight vanilla ES6 UI component trees with customizable branch-local behaviors", "module": "./index.js", "main": "./lib/index.js", @@ -40,7 +40,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/atom": "^4.1.20", + "@thi.ng/atom": "^4.1.21", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", @@ -50,13 +50,13 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/diff": "^3.2.31", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/hiccup": "^3.6.0", - "@thi.ng/prefixes": "^0.1.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/diff": "^3.2.32", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/hiccup": "^3.6.1", + "@thi.ng/prefixes": "^0.1.6" }, "files": [ "*.js", diff --git a/packages/heaps/CHANGELOG.md b/packages/heaps/CHANGELOG.md index b8b9b43bf0..8afa365521 100644 --- a/packages/heaps/CHANGELOG.md +++ b/packages/heaps/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.2.25](https://github.com/thi-ng/umbrella/compare/@thi.ng/heaps@1.2.24...@thi.ng/heaps@1.2.25) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/heaps + + + + + ## [1.2.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/heaps@1.2.23...@thi.ng/heaps@1.2.24) (2020-09-13) **Note:** Version bump only for package @thi.ng/heaps diff --git a/packages/heaps/package.json b/packages/heaps/package.json index 78fa98282b..b6d7a89b9e 100644 --- a/packages/heaps/package.json +++ b/packages/heaps/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/heaps", - "version": "1.2.24", + "version": "1.2.25", "description": "Various heap implementations for arbitrary values and with customizable ordering", "module": "./index.js", "main": "./lib/index.js", @@ -50,8 +50,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/compare": "^1.3.16" + "@thi.ng/api": "^6.13.1", + "@thi.ng/compare": "^1.3.17" }, "files": [ "*.js", diff --git a/packages/hiccup-canvas/CHANGELOG.md b/packages/hiccup-canvas/CHANGELOG.md index 7ce7721093..86c76efd5e 100644 --- a/packages/hiccup-canvas/CHANGELOG.md +++ b/packages/hiccup-canvas/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-canvas@1.1.8...@thi.ng/hiccup-canvas@1.1.9) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hiccup-canvas + + + + + ## [1.1.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-canvas@1.1.7...@thi.ng/hiccup-canvas@1.1.8) (2020-09-13) **Note:** Version bump only for package @thi.ng/hiccup-canvas diff --git a/packages/hiccup-canvas/package.json b/packages/hiccup-canvas/package.json index 61a53d470c..f6b9edc83b 100644 --- a/packages/hiccup-canvas/package.json +++ b/packages/hiccup-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup-canvas", - "version": "1.1.8", + "version": "1.1.9", "description": "Hiccup shape tree renderer for vanilla Canvas 2D contexts", "module": "./index.js", "main": "./lib/index.js", @@ -48,11 +48,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/color": "^1.2.16", - "@thi.ng/math": "^2.1.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/color": "^1.2.17", + "@thi.ng/math": "^2.1.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/hiccup-carbon-icons/CHANGELOG.md b/packages/hiccup-carbon-icons/CHANGELOG.md index 75b7762265..dc00a4e415 100644 --- a/packages/hiccup-carbon-icons/CHANGELOG.md +++ b/packages/hiccup-carbon-icons/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-carbon-icons@2.0.3...@thi.ng/hiccup-carbon-icons@2.0.4) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hiccup-carbon-icons + + + + + ## [2.0.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-carbon-icons@2.0.2...@thi.ng/hiccup-carbon-icons@2.0.3) (2020-09-13) **Note:** Version bump only for package @thi.ng/hiccup-carbon-icons diff --git a/packages/hiccup-carbon-icons/package.json b/packages/hiccup-carbon-icons/package.json index 55aea93eaa..567be2fc2a 100644 --- a/packages/hiccup-carbon-icons/package.json +++ b/packages/hiccup-carbon-icons/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup-carbon-icons", - "version": "2.0.3", + "version": "2.0.4", "description": "Full set of IBM's Carbon icons in hiccup format", "module": "./index.js", "main": "./lib/index.js", @@ -42,7 +42,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/hiccup": "^3.6.0", + "@thi.ng/hiccup": "^3.6.1", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", diff --git a/packages/hiccup-css/CHANGELOG.md b/packages/hiccup-css/CHANGELOG.md index 48788da172..a29b31cffd 100644 --- a/packages/hiccup-css/CHANGELOG.md +++ b/packages/hiccup-css/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-css@1.1.38...@thi.ng/hiccup-css@1.1.39) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hiccup-css + + + + + ## [1.1.38](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-css@1.1.37...@thi.ng/hiccup-css@1.1.38) (2020-09-13) **Note:** Version bump only for package @thi.ng/hiccup-css diff --git a/packages/hiccup-css/package.json b/packages/hiccup-css/package.json index 0b3ca7b49e..90b680763e 100644 --- a/packages/hiccup-css/package.json +++ b/packages/hiccup-css/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup-css", - "version": "1.1.38", + "version": "1.1.39", "description": "CSS from nested JS data structures", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/hiccup-html/CHANGELOG.md b/packages/hiccup-html/CHANGELOG.md index 4063baa593..e5f7b1dba9 100644 --- a/packages/hiccup-html/CHANGELOG.md +++ b/packages/hiccup-html/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.3.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-html@0.3.5...@thi.ng/hiccup-html@0.3.6) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hiccup-html + + + + + ## [0.3.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-html@0.3.4...@thi.ng/hiccup-html@0.3.5) (2020-09-13) **Note:** Version bump only for package @thi.ng/hiccup-html diff --git a/packages/hiccup-html/package.json b/packages/hiccup-html/package.json index df93c9e458..36ec68a4eb 100644 --- a/packages/hiccup-html/package.json +++ b/packages/hiccup-html/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup-html", - "version": "0.3.5", + "version": "0.3.6", "description": "100+ type-checked HTML5 element functions for @thi.ng/hiccup related infrastructure", "module": "./index.js", "main": "./lib/index.js", @@ -48,7 +48,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0" + "@thi.ng/api": "^6.13.1" }, "files": [ "*.js", diff --git a/packages/hiccup-markdown/CHANGELOG.md b/packages/hiccup-markdown/CHANGELOG.md index bd3bcfe518..ef023f7ca9 100644 --- a/packages/hiccup-markdown/CHANGELOG.md +++ b/packages/hiccup-markdown/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.2.34](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-markdown@1.2.33...@thi.ng/hiccup-markdown@1.2.34) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hiccup-markdown + + + + + ## [1.2.33](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-markdown@1.2.32...@thi.ng/hiccup-markdown@1.2.33) (2020-09-13) **Note:** Version bump only for package @thi.ng/hiccup-markdown diff --git a/packages/hiccup-markdown/package.json b/packages/hiccup-markdown/package.json index 15ffbc0d8a..346663a4f5 100644 --- a/packages/hiccup-markdown/package.json +++ b/packages/hiccup-markdown/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup-markdown", - "version": "1.2.33", + "version": "1.2.34", "description": "Markdown parser & serializer from/to Hiccup format", "module": "./index.js", "main": "./lib/index.js", @@ -49,16 +49,16 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/defmulti": "^1.2.25", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/fsm": "^2.4.25", - "@thi.ng/hiccup": "^3.6.0", - "@thi.ng/strings": "^1.9.6", - "@thi.ng/text-canvas": "^0.2.30", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/defmulti": "^1.2.26", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/fsm": "^2.4.26", + "@thi.ng/hiccup": "^3.6.1", + "@thi.ng/strings": "^1.10.0", + "@thi.ng/text-canvas": "^0.2.31", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/hiccup-svg/CHANGELOG.md b/packages/hiccup-svg/CHANGELOG.md index cd5885e71c..8f816a1069 100644 --- a/packages/hiccup-svg/CHANGELOG.md +++ b/packages/hiccup-svg/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.6.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-svg@3.6.0...@thi.ng/hiccup-svg@3.6.1) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hiccup-svg + + + + + # [3.6.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-svg@3.5.11...@thi.ng/hiccup-svg@3.6.0) (2020-09-13) diff --git a/packages/hiccup-svg/package.json b/packages/hiccup-svg/package.json index 9cf56ffa3a..ffce462bfa 100644 --- a/packages/hiccup-svg/package.json +++ b/packages/hiccup-svg/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup-svg", - "version": "3.6.0", + "version": "3.6.1", "description": "SVG element functions for @thi.ng/hiccup & @thi.ng/hdom", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/checks": "^2.7.8", - "@thi.ng/color": "^1.2.16", - "@thi.ng/prefixes": "^0.1.5" + "@thi.ng/checks": "^2.7.9", + "@thi.ng/color": "^1.2.17", + "@thi.ng/prefixes": "^0.1.6" }, "files": [ "*.js", diff --git a/packages/hiccup/CHANGELOG.md b/packages/hiccup/CHANGELOG.md index 4a3ed32e5c..53394246d9 100644 --- a/packages/hiccup/CHANGELOG.md +++ b/packages/hiccup/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.6.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup@3.6.0...@thi.ng/hiccup@3.6.1) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/hiccup + + + + + # [3.6.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup@3.5.8...@thi.ng/hiccup@3.6.0) (2020-09-13) diff --git a/packages/hiccup/package.json b/packages/hiccup/package.json index 1fd0d4753b..938db1af7c 100644 --- a/packages/hiccup/package.json +++ b/packages/hiccup/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup", - "version": "3.6.0", + "version": "3.6.1", "description": "HTML/SVG/XML serialization of nested data structures, iterables & closures", "module": "./index.js", "main": "./lib/index.js", @@ -40,7 +40,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/atom": "^4.1.20", + "@thi.ng/atom": "^4.1.21", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", @@ -50,10 +50,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/prefixes": "^0.1.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/prefixes": "^0.1.6" }, "files": [ "*.js", diff --git a/packages/idgen/CHANGELOG.md b/packages/idgen/CHANGELOG.md index 8b5f7d1f1f..956c2bff69 100644 --- a/packages/idgen/CHANGELOG.md +++ b/packages/idgen/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/idgen@0.2.22...@thi.ng/idgen@0.2.23) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/idgen + + + + + ## [0.2.22](https://github.com/thi-ng/umbrella/compare/@thi.ng/idgen@0.2.21...@thi.ng/idgen@0.2.22) (2020-09-13) **Note:** Version bump only for package @thi.ng/idgen diff --git a/packages/idgen/package.json b/packages/idgen/package.json index f58d69153d..9c06077e32 100644 --- a/packages/idgen/package.json +++ b/packages/idgen/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/idgen", - "version": "0.2.22", + "version": "0.2.23", "description": "Generator of opaque numeric identifiers with optional support for ID versioning and efficient re-use", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", + "@thi.ng/api": "^6.13.1", "tslib": "^2.0.1" }, "files": [ diff --git a/packages/iges/CHANGELOG.md b/packages/iges/CHANGELOG.md index 0a4da8069a..b1e8315439 100644 --- a/packages/iges/CHANGELOG.md +++ b/packages/iges/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.48](https://github.com/thi-ng/umbrella/compare/@thi.ng/iges@1.1.47...@thi.ng/iges@1.1.48) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/iges + + + + + ## [1.1.47](https://github.com/thi-ng/umbrella/compare/@thi.ng/iges@1.1.46...@thi.ng/iges@1.1.47) (2020-09-13) **Note:** Version bump only for package @thi.ng/iges diff --git a/packages/iges/package.json b/packages/iges/package.json index 227621eed5..4b443c139d 100644 --- a/packages/iges/package.json +++ b/packages/iges/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/iges", - "version": "1.1.47", + "version": "1.1.48", "description": "IGES 5.3 serializer for (currently only) polygonal geometry, both open & closed", "module": "./index.js", "main": "./lib/index.js", @@ -49,12 +49,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/defmulti": "^1.2.25", - "@thi.ng/strings": "^1.9.6", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/defmulti": "^1.2.26", + "@thi.ng/strings": "^1.10.0", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/imgui/CHANGELOG.md b/packages/imgui/CHANGELOG.md index bac9a9db4b..37ebc5d859 100644 --- a/packages/imgui/CHANGELOG.md +++ b/packages/imgui/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.40](https://github.com/thi-ng/umbrella/compare/@thi.ng/imgui@0.2.39...@thi.ng/imgui@0.2.40) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/imgui + + + + + ## [0.2.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/imgui@0.2.38...@thi.ng/imgui@0.2.39) (2020-09-13) **Note:** Version bump only for package @thi.ng/imgui diff --git a/packages/imgui/package.json b/packages/imgui/package.json index ca25ca9707..969c156136 100644 --- a/packages/imgui/package.json +++ b/packages/imgui/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/imgui", - "version": "0.2.39", + "version": "0.2.40", "description": "Immediate mode GUI with flexible state handling & data only shape output", "module": "./index.js", "main": "./lib/index.js", @@ -49,16 +49,16 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/geom": "^1.11.8", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/geom-isec": "^0.5.8", - "@thi.ng/geom-tessellate": "^0.2.46", - "@thi.ng/layout": "^0.1.22", - "@thi.ng/math": "^2.1.0", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/geom": "^1.12.0", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/geom-isec": "^0.6.0", + "@thi.ng/geom-tessellate": "^0.2.47", + "@thi.ng/layout": "^0.1.23", + "@thi.ng/math": "^2.1.1", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/interceptors/CHANGELOG.md b/packages/interceptors/CHANGELOG.md index 0d91c45db5..93e6a5b8f7 100644 --- a/packages/interceptors/CHANGELOG.md +++ b/packages/interceptors/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.2.32](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@2.2.31...@thi.ng/interceptors@2.2.32) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/interceptors + + + + + ## [2.2.31](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@2.2.30...@thi.ng/interceptors@2.2.31) (2020-09-13) **Note:** Version bump only for package @thi.ng/interceptors diff --git a/packages/interceptors/package.json b/packages/interceptors/package.json index da3ec49f2d..6e7d14c1be 100644 --- a/packages/interceptors/package.json +++ b/packages/interceptors/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/interceptors", - "version": "2.2.31", + "version": "2.2.32", "description": "Interceptor based event bus, side effect & immutable state handling", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/atom": "^4.1.20", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/paths": "^4.1.6" + "@thi.ng/api": "^6.13.1", + "@thi.ng/atom": "^4.1.21", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/paths": "^4.1.7" }, "files": [ "*.js", diff --git a/packages/intervals/CHANGELOG.md b/packages/intervals/CHANGELOG.md index 33c9094f95..07a132cddb 100644 --- a/packages/intervals/CHANGELOG.md +++ b/packages/intervals/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.25](https://github.com/thi-ng/umbrella/compare/@thi.ng/intervals@2.0.24...@thi.ng/intervals@2.0.25) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/intervals + + + + + ## [2.0.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/intervals@2.0.23...@thi.ng/intervals@2.0.24) (2020-09-13) **Note:** Version bump only for package @thi.ng/intervals diff --git a/packages/intervals/package.json b/packages/intervals/package.json index fe5fc8d785..ff6377c663 100644 --- a/packages/intervals/package.json +++ b/packages/intervals/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/intervals", - "version": "2.0.24", + "version": "2.0.25", "description": "Closed/open/semi-open interval data type, queries & operations", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/dlogic": "^1.0.31", - "@thi.ng/errors": "^1.2.21" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/dlogic": "^1.0.32", + "@thi.ng/errors": "^1.2.22" }, "files": [ "*.js", diff --git a/packages/iterators/CHANGELOG.md b/packages/iterators/CHANGELOG.md index 240a6c1f6d..da093d7406 100644 --- a/packages/iterators/CHANGELOG.md +++ b/packages/iterators/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.1.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/iterators@5.1.38...@thi.ng/iterators@5.1.39) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/iterators + + + + + ## [5.1.38](https://github.com/thi-ng/umbrella/compare/@thi.ng/iterators@5.1.37...@thi.ng/iterators@5.1.38) (2020-09-13) **Note:** Version bump only for package @thi.ng/iterators diff --git a/packages/iterators/package.json b/packages/iterators/package.json index 4ce28b8dd7..5893ff27e6 100644 --- a/packages/iterators/package.json +++ b/packages/iterators/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/iterators", - "version": "5.1.38", + "version": "5.1.39", "description": "Clojure inspired, composable ES6 iterators & generators", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/dcons": "^2.2.31", - "@thi.ng/errors": "^1.2.21" + "@thi.ng/api": "^6.13.1", + "@thi.ng/dcons": "^2.2.32", + "@thi.ng/errors": "^1.2.22" }, "files": [ "*.js", diff --git a/packages/layout/CHANGELOG.md b/packages/layout/CHANGELOG.md index 50e13589af..919320c09c 100644 --- a/packages/layout/CHANGELOG.md +++ b/packages/layout/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/layout@0.1.22...@thi.ng/layout@0.1.23) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/layout + + + + + ## [0.1.22](https://github.com/thi-ng/umbrella/compare/@thi.ng/layout@0.1.21...@thi.ng/layout@0.1.22) (2020-09-13) **Note:** Version bump only for package @thi.ng/layout diff --git a/packages/layout/package.json b/packages/layout/package.json index 03de66d0be..1d703f6451 100644 --- a/packages/layout/package.json +++ b/packages/layout/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/layout", - "version": "0.1.22", + "version": "0.1.23", "description": "TODO", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/checks": "^2.7.8" + "@thi.ng/checks": "^2.7.9" }, "files": [ "*.js", diff --git a/packages/leb128/CHANGELOG.md b/packages/leb128/CHANGELOG.md index e935fb2a8b..6d3f789f69 100644 --- a/packages/leb128/CHANGELOG.md +++ b/packages/leb128/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.34](https://github.com/thi-ng/umbrella/compare/@thi.ng/leb128@1.0.33...@thi.ng/leb128@1.0.34) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/leb128 + + + + + ## [1.0.33](https://github.com/thi-ng/umbrella/compare/@thi.ng/leb128@1.0.32...@thi.ng/leb128@1.0.33) (2020-09-13) **Note:** Version bump only for package @thi.ng/leb128 diff --git a/packages/leb128/package.json b/packages/leb128/package.json index 8255784783..8b5b139da8 100644 --- a/packages/leb128/package.json +++ b/packages/leb128/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/leb128", - "version": "1.0.33", + "version": "1.0.34", "description": "WASM based LEB128 encoder / decoder (signed & unsigned)", "module": "./index.js", "main": "./lib/index.js", @@ -50,9 +50,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/transducers-binary": "^0.5.29" + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/transducers-binary": "^0.5.30" }, "files": [ "*.js", diff --git a/packages/lsys/CHANGELOG.md b/packages/lsys/CHANGELOG.md index 262284f4ee..919184c2f0 100644 --- a/packages/lsys/CHANGELOG.md +++ b/packages/lsys/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.61](https://github.com/thi-ng/umbrella/compare/@thi.ng/lsys@0.2.60...@thi.ng/lsys@0.2.61) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/lsys + + + + + ## [0.2.60](https://github.com/thi-ng/umbrella/compare/@thi.ng/lsys@0.2.59...@thi.ng/lsys@0.2.60) (2020-09-13) **Note:** Version bump only for package @thi.ng/lsys diff --git a/packages/lsys/package.json b/packages/lsys/package.json index bc1aa5cb0d..4652cceafd 100644 --- a/packages/lsys/package.json +++ b/packages/lsys/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/lsys", - "version": "0.2.60", + "version": "0.2.61", "description": "Functional, extensible L-System architecture w/ support for probabilistic rules", "module": "./index.js", "main": "./lib/index.js", @@ -49,13 +49,13 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/compose": "^1.4.17", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/math": "^2.1.0", - "@thi.ng/random": "^2.0.1", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/compose": "^1.4.18", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/math": "^2.1.1", + "@thi.ng/random": "^2.0.2", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/malloc/CHANGELOG.md b/packages/malloc/CHANGELOG.md index 5bdfb7536a..7d0ffc8df3 100644 --- a/packages/malloc/CHANGELOG.md +++ b/packages/malloc/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [4.1.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/malloc@4.1.25...@thi.ng/malloc@4.1.26) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/malloc + + + + + ## [4.1.25](https://github.com/thi-ng/umbrella/compare/@thi.ng/malloc@4.1.24...@thi.ng/malloc@4.1.25) (2020-09-13) **Note:** Version bump only for package @thi.ng/malloc diff --git a/packages/malloc/package.json b/packages/malloc/package.json index c2675dd071..3ef173d9f5 100644 --- a/packages/malloc/package.json +++ b/packages/malloc/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/malloc", - "version": "4.1.25", + "version": "4.1.26", "description": "ArrayBuffer based malloc() impl for hybrid JS/WASM use cases, based on thi.ng/tinyalloc", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21" + "@thi.ng/api": "^6.13.1", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22" }, "files": [ "*.js", diff --git a/packages/math/CHANGELOG.md b/packages/math/CHANGELOG.md index 7a56b024b9..b4bddde8d4 100644 --- a/packages/math/CHANGELOG.md +++ b/packages/math/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/math@2.1.0...@thi.ng/math@2.1.1) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/math + + + + + # [2.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/math@2.0.4...@thi.ng/math@2.1.0) (2020-09-13) diff --git a/packages/math/package.json b/packages/math/package.json index de9642dd67..1dd9558f4e 100644 --- a/packages/math/package.json +++ b/packages/math/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/math", - "version": "2.1.0", + "version": "2.1.1", "description": "Assorted common math functions & utilities", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0" + "@thi.ng/api": "^6.13.1" }, "files": [ "*.js", diff --git a/packages/matrices/CHANGELOG.md b/packages/matrices/CHANGELOG.md index 7f3dd31d29..a00ef540a7 100644 --- a/packages/matrices/CHANGELOG.md +++ b/packages/matrices/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.6.33](https://github.com/thi-ng/umbrella/compare/@thi.ng/matrices@0.6.32...@thi.ng/matrices@0.6.33) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/matrices + + + + + ## [0.6.32](https://github.com/thi-ng/umbrella/compare/@thi.ng/matrices@0.6.31...@thi.ng/matrices@0.6.32) (2020-09-13) **Note:** Version bump only for package @thi.ng/matrices diff --git a/packages/matrices/package.json b/packages/matrices/package.json index c04f4b1c0e..19ddcd4d22 100644 --- a/packages/matrices/package.json +++ b/packages/matrices/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/matrices", - "version": "0.6.32", + "version": "0.6.33", "description": "Matrix & quaternion operations for 2D/3D geometry processing", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/math": "^2.1.0", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/math": "^2.1.1", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/memoize/CHANGELOG.md b/packages/memoize/CHANGELOG.md index 29075c9a2b..73d373bf38 100644 --- a/packages/memoize/CHANGELOG.md +++ b/packages/memoize/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/memoize@2.1.2...@thi.ng/memoize@2.1.3) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/memoize + + + + + ## [2.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/memoize@2.1.1...@thi.ng/memoize@2.1.2) (2020-09-13) **Note:** Version bump only for package @thi.ng/memoize diff --git a/packages/memoize/package.json b/packages/memoize/package.json index 819ceddce5..271c6afa9d 100644 --- a/packages/memoize/package.json +++ b/packages/memoize/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/memoize", - "version": "2.1.2", + "version": "2.1.3", "description": "Function memoization with configurable caching", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0" + "@thi.ng/api": "^6.13.1" }, "files": [ "*.js", diff --git a/packages/mime/CHANGELOG.md b/packages/mime/CHANGELOG.md index aeeadd22f3..d17ab17e32 100644 --- a/packages/mime/CHANGELOG.md +++ b/packages/mime/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.22](https://github.com/thi-ng/umbrella/compare/@thi.ng/mime@0.1.21...@thi.ng/mime@0.1.22) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/mime + + + + + ## [0.1.21](https://github.com/thi-ng/umbrella/compare/@thi.ng/mime@0.1.20...@thi.ng/mime@0.1.21) (2020-09-13) **Note:** Version bump only for package @thi.ng/mime diff --git a/packages/mime/package.json b/packages/mime/package.json index b6a3a359b0..721bb19cfc 100644 --- a/packages/mime/package.json +++ b/packages/mime/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/mime", - "version": "0.1.21", + "version": "0.1.22", "description": "350+ file extension to MIME type mappings, based on mime-db", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0" + "@thi.ng/api": "^6.13.1" }, "files": [ "*.js", diff --git a/packages/morton/CHANGELOG.md b/packages/morton/CHANGELOG.md index 0cff2f821a..b633afed62 100644 --- a/packages/morton/CHANGELOG.md +++ b/packages/morton/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.25](https://github.com/thi-ng/umbrella/compare/@thi.ng/morton@2.0.24...@thi.ng/morton@2.0.25) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/morton + + + + + ## [2.0.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/morton@2.0.23...@thi.ng/morton@2.0.24) (2020-09-13) **Note:** Version bump only for package @thi.ng/morton diff --git a/packages/morton/package.json b/packages/morton/package.json index 76dde18978..e00331179d 100644 --- a/packages/morton/package.json +++ b/packages/morton/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/morton", - "version": "2.0.24", + "version": "2.0.25", "description": "Z-order curve / Morton encoding, decoding & range extraction for arbitrary dimensions", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/math": "^2.1.0" + "@thi.ng/api": "^6.13.1", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/math": "^2.1.1" }, "files": [ "*.js", diff --git a/packages/oquery/CHANGELOG.md b/packages/oquery/CHANGELOG.md index ffce405e1e..95ad5ae2aa 100644 --- a/packages/oquery/CHANGELOG.md +++ b/packages/oquery/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/oquery@0.1.11...@thi.ng/oquery@0.1.12) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/oquery + + + + + ## [0.1.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/oquery@0.1.10...@thi.ng/oquery@0.1.11) (2020-09-13) **Note:** Version bump only for package @thi.ng/oquery diff --git a/packages/oquery/package.json b/packages/oquery/package.json index 0cdeeb2944..714f6cc1ee 100644 --- a/packages/oquery/package.json +++ b/packages/oquery/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/oquery", - "version": "0.1.11", + "version": "0.1.12", "description": "Datalog-inspired, optimized pattern/predicate query engine for JS objects", "module": "./index.js", "main": "./lib/index.js", @@ -48,11 +48,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/associative": "^5.0.6", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/defmulti": "^1.2.25", - "@thi.ng/equiv": "^1.0.31" + "@thi.ng/api": "^6.13.1", + "@thi.ng/associative": "^5.0.7", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/defmulti": "^1.2.26", + "@thi.ng/equiv": "^1.0.32" }, "files": [ "*.js", diff --git a/packages/parse/CHANGELOG.md b/packages/parse/CHANGELOG.md index b3b4dd2170..87874211c1 100644 --- a/packages/parse/CHANGELOG.md +++ b/packages/parse/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.9.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/parse@0.9.3...@thi.ng/parse@0.9.4) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/parse + + + + + ## [0.9.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/parse@0.9.2...@thi.ng/parse@0.9.3) (2020-09-13) **Note:** Version bump only for package @thi.ng/parse diff --git a/packages/parse/package.json b/packages/parse/package.json index f4aad52d7e..33c88d77e5 100644 --- a/packages/parse/package.json +++ b/packages/parse/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/parse", - "version": "0.9.3", + "version": "0.9.4", "description": "Purely functional parser combinators & AST generation for generic inputs", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/defmulti": "^1.2.25", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/strings": "^1.9.6" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/defmulti": "^1.2.26", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/strings": "^1.10.0" }, "files": [ "*.js", diff --git a/packages/paths/CHANGELOG.md b/packages/paths/CHANGELOG.md index 64ec440cbe..da21781f47 100644 --- a/packages/paths/CHANGELOG.md +++ b/packages/paths/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [4.1.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/paths@4.1.6...@thi.ng/paths@4.1.7) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/paths + + + + + ## [4.1.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/paths@4.1.5...@thi.ng/paths@4.1.6) (2020-09-13) **Note:** Version bump only for package @thi.ng/paths diff --git a/packages/paths/package.json b/packages/paths/package.json index f8cf2dc8c5..12abcc169a 100644 --- a/packages/paths/package.json +++ b/packages/paths/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/paths", - "version": "4.1.6", + "version": "4.1.7", "description": "Immutable, optimized and optionally typed path-based object property / array accessors with structural sharing", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22" }, "files": [ "*.js", diff --git a/packages/pixel/CHANGELOG.md b/packages/pixel/CHANGELOG.md index 001fdeb441..16a3420701 100644 --- a/packages/pixel/CHANGELOG.md +++ b/packages/pixel/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.4.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.4.5...@thi.ng/pixel@0.4.6) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/pixel + + + + + ## [0.4.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.4.4...@thi.ng/pixel@0.4.5) (2020-09-13) **Note:** Version bump only for package @thi.ng/pixel diff --git a/packages/pixel/package.json b/packages/pixel/package.json index fd245f1fc3..90d6ab91a9 100644 --- a/packages/pixel/package.json +++ b/packages/pixel/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/pixel", - "version": "0.4.5", + "version": "0.4.6", "description": "Typed array backed, packed integer and unpacked floating point pixel buffers w/ customizable formats, blitting, dithering, conversions", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/math": "^2.1.0", - "@thi.ng/porter-duff": "^0.1.30" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/math": "^2.1.1", + "@thi.ng/porter-duff": "^0.1.31" }, "files": [ "*.js", diff --git a/packages/pointfree-lang/CHANGELOG.md b/packages/pointfree-lang/CHANGELOG.md index 8544895fba..779e9e5ca8 100644 --- a/packages/pointfree-lang/CHANGELOG.md +++ b/packages/pointfree-lang/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.4.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree-lang@1.4.13...@thi.ng/pointfree-lang@1.4.14) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/pointfree-lang + + + + + ## [1.4.13](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree-lang@1.4.12...@thi.ng/pointfree-lang@1.4.13) (2020-09-13) **Note:** Version bump only for package @thi.ng/pointfree-lang diff --git a/packages/pointfree-lang/package.json b/packages/pointfree-lang/package.json index b3046b2cd9..8b7c0c7c71 100644 --- a/packages/pointfree-lang/package.json +++ b/packages/pointfree-lang/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/pointfree-lang", - "version": "1.4.13", + "version": "1.4.14", "description": "Forth style syntax layer/compiler & CLI for the @thi.ng/pointfree DSL", "module": "./index.js", "main": "./lib/index.js", @@ -53,10 +53,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/bench": "^2.0.20", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/pointfree": "^2.0.14", + "@thi.ng/api": "^6.13.1", + "@thi.ng/bench": "^2.0.21", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/pointfree": "^2.0.15", "commander": "^6.1.0" }, "files": [ diff --git a/packages/pointfree/CHANGELOG.md b/packages/pointfree/CHANGELOG.md index 3fa72de127..686a1f3342 100644 --- a/packages/pointfree/CHANGELOG.md +++ b/packages/pointfree/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree@2.0.14...@thi.ng/pointfree@2.0.15) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/pointfree + + + + + ## [2.0.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree@2.0.13...@thi.ng/pointfree@2.0.14) (2020-09-13) **Note:** Version bump only for package @thi.ng/pointfree diff --git a/packages/pointfree/package.json b/packages/pointfree/package.json index 533ec18fa9..42cf300039 100644 --- a/packages/pointfree/package.json +++ b/packages/pointfree/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/pointfree", - "version": "2.0.14", + "version": "2.0.15", "description": "Pointfree functional composition / Forth style stack execution engine", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/compose": "^1.4.17", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/compose": "^1.4.18", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22" }, "files": [ "*.js", diff --git a/packages/poisson/CHANGELOG.md b/packages/poisson/CHANGELOG.md index 94a015885f..b34d417c9b 100644 --- a/packages/poisson/CHANGELOG.md +++ b/packages/poisson/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/poisson@1.1.16...@thi.ng/poisson@1.1.17) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/poisson + + + + + ## [1.1.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/poisson@1.1.15...@thi.ng/poisson@1.1.16) (2020-09-13) **Note:** Version bump only for package @thi.ng/poisson diff --git a/packages/poisson/package.json b/packages/poisson/package.json index c8a897687f..5cb4c8ab64 100644 --- a/packages/poisson/package.json +++ b/packages/poisson/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/poisson", - "version": "1.1.16", + "version": "1.1.17", "description": "nD Stratified grid and Poisson-disc sampling w/ support for spatial density functions and custom PRNGs", "module": "./index.js", "main": "./lib/index.js", @@ -49,12 +49,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/geom-api": "^1.0.34", - "@thi.ng/random": "^2.0.1", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/geom-api": "^1.1.0", + "@thi.ng/random": "^2.0.2", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/porter-duff/CHANGELOG.md b/packages/porter-duff/CHANGELOG.md index ad496ef776..704b34d3ef 100644 --- a/packages/porter-duff/CHANGELOG.md +++ b/packages/porter-duff/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.31](https://github.com/thi-ng/umbrella/compare/@thi.ng/porter-duff@0.1.30...@thi.ng/porter-duff@0.1.31) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/porter-duff + + + + + ## [0.1.30](https://github.com/thi-ng/umbrella/compare/@thi.ng/porter-duff@0.1.29...@thi.ng/porter-duff@0.1.30) (2020-09-13) **Note:** Version bump only for package @thi.ng/porter-duff diff --git a/packages/porter-duff/package.json b/packages/porter-duff/package.json index e8b59b9c80..6a8a615f92 100644 --- a/packages/porter-duff/package.json +++ b/packages/porter-duff/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/porter-duff", - "version": "0.1.30", + "version": "0.1.31", "description": "Porter-Duff operators for packed ints & float-array alpha compositing", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/math": "^2.1.0" + "@thi.ng/api": "^6.13.1", + "@thi.ng/math": "^2.1.1" }, "files": [ "*.js", diff --git a/packages/prefixes/CHANGELOG.md b/packages/prefixes/CHANGELOG.md index 5f5aec7b31..0dafba4d0b 100644 --- a/packages/prefixes/CHANGELOG.md +++ b/packages/prefixes/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/prefixes@0.1.5...@thi.ng/prefixes@0.1.6) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/prefixes + + + + + ## [0.1.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/prefixes@0.1.4...@thi.ng/prefixes@0.1.5) (2020-09-13) **Note:** Version bump only for package @thi.ng/prefixes diff --git a/packages/prefixes/package.json b/packages/prefixes/package.json index 2b643b641c..4c88e5c410 100644 --- a/packages/prefixes/package.json +++ b/packages/prefixes/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/prefixes", - "version": "0.1.5", + "version": "0.1.6", "description": "50+ Linked Data vocabulary prefixes and their namespace URLs", "module": "./index.js", "main": "./lib/index.js", diff --git a/packages/quad-edge/CHANGELOG.md b/packages/quad-edge/CHANGELOG.md index 554db68746..bfb75a0287 100644 --- a/packages/quad-edge/CHANGELOG.md +++ b/packages/quad-edge/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/quad-edge@0.2.23...@thi.ng/quad-edge@0.2.24) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/quad-edge + + + + + ## [0.2.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/quad-edge@0.2.22...@thi.ng/quad-edge@0.2.23) (2020-09-13) **Note:** Version bump only for package @thi.ng/quad-edge diff --git a/packages/quad-edge/package.json b/packages/quad-edge/package.json index 572bddf565..18a0e136e6 100644 --- a/packages/quad-edge/package.json +++ b/packages/quad-edge/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/quad-edge", - "version": "0.2.23", + "version": "0.2.24", "description": "Quadedge data structure after Guibas & Stolfi", "module": "./index.js", "main": "./lib/index.js", diff --git a/packages/ramp/CHANGELOG.md b/packages/ramp/CHANGELOG.md index 5284684af2..59460050ca 100644 --- a/packages/ramp/CHANGELOG.md +++ b/packages/ramp/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.35](https://github.com/thi-ng/umbrella/compare/@thi.ng/ramp@0.1.34...@thi.ng/ramp@0.1.35) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/ramp + + + + + ## [0.1.34](https://github.com/thi-ng/umbrella/compare/@thi.ng/ramp@0.1.33...@thi.ng/ramp@0.1.34) (2020-09-13) **Note:** Version bump only for package @thi.ng/ramp diff --git a/packages/ramp/package.json b/packages/ramp/package.json index 82a96741e4..0128f95e79 100644 --- a/packages/ramp/package.json +++ b/packages/ramp/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/ramp", - "version": "0.1.34", + "version": "0.1.35", "description": "Parametric interpolated 1D lookup tables for remapping values", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/compare": "^1.3.16", - "@thi.ng/math": "^2.1.0", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/compare": "^1.3.17", + "@thi.ng/math": "^2.1.1", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/random/CHANGELOG.md b/packages/random/CHANGELOG.md index cb7919e213..50caffd582 100644 --- a/packages/random/CHANGELOG.md +++ b/packages/random/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/random@2.0.1...@thi.ng/random@2.0.2) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/random + + + + + ## [2.0.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/random@2.0.0...@thi.ng/random@2.0.1) (2020-09-13) **Note:** Version bump only for package @thi.ng/random diff --git a/packages/random/package.json b/packages/random/package.json index a27e5d64af..f03ff8ad5b 100644 --- a/packages/random/package.json +++ b/packages/random/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/random", - "version": "2.0.1", + "version": "2.0.2", "description": "Pseudo-random number generators w/ unified API", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9" }, "files": [ "*.js", diff --git a/packages/range-coder/CHANGELOG.md b/packages/range-coder/CHANGELOG.md index 3739d55518..08556d7f15 100644 --- a/packages/range-coder/CHANGELOG.md +++ b/packages/range-coder/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.59](https://github.com/thi-ng/umbrella/compare/@thi.ng/range-coder@1.0.58...@thi.ng/range-coder@1.0.59) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/range-coder + + + + + ## [1.0.58](https://github.com/thi-ng/umbrella/compare/@thi.ng/range-coder@1.0.57...@thi.ng/range-coder@1.0.58) (2020-09-13) **Note:** Version bump only for package @thi.ng/range-coder diff --git a/packages/range-coder/package.json b/packages/range-coder/package.json index 1c37e1f574..e84c9b11f7 100644 --- a/packages/range-coder/package.json +++ b/packages/range-coder/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/range-coder", - "version": "1.0.58", + "version": "1.0.59", "description": "Binary data range encoder / decoder", "module": "./index.js", "main": "./lib/index.js", @@ -40,7 +40,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/transducers": "^7.3.1", + "@thi.ng/transducers": "^7.4.0", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", @@ -50,7 +50,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/bitstream": "^1.1.26" + "@thi.ng/bitstream": "^1.1.27" }, "files": [ "*.js", diff --git a/packages/rdom-canvas/CHANGELOG.md b/packages/rdom-canvas/CHANGELOG.md index f355fc5950..f46537ed22 100644 --- a/packages/rdom-canvas/CHANGELOG.md +++ b/packages/rdom-canvas/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/rdom-canvas@0.1.15...@thi.ng/rdom-canvas@0.1.16) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rdom-canvas + + + + + ## [0.1.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/rdom-canvas@0.1.14...@thi.ng/rdom-canvas@0.1.15) (2020-09-13) **Note:** Version bump only for package @thi.ng/rdom-canvas diff --git a/packages/rdom-canvas/package.json b/packages/rdom-canvas/package.json index 980926f099..b1cb96b8ed 100644 --- a/packages/rdom-canvas/package.json +++ b/packages/rdom-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rdom-canvas", - "version": "0.1.15", + "version": "0.1.16", "description": "@thi.ng/rdom component wrapper for @thi.ng/hiccup-canvas and declarative canvas drawing", "module": "./index.js", "main": "./lib/index.js", @@ -48,13 +48,13 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/adapt-dpi": "^1.0.8", - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/hiccup-canvas": "^1.1.8", - "@thi.ng/rdom": "^0.2.11", - "@thi.ng/rstream": "^5.0.4", - "@thi.ng/transducers": "^7.3.1", + "@thi.ng/adapt-dpi": "^1.0.9", + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/hiccup-canvas": "^1.1.9", + "@thi.ng/rdom": "^0.2.12", + "@thi.ng/rstream": "^5.0.5", + "@thi.ng/transducers": "^7.4.0", "tslib": "^2.0.1" }, "files": [ diff --git a/packages/rdom-components/CHANGELOG.md b/packages/rdom-components/CHANGELOG.md index b4273546ab..9598c412e8 100644 --- a/packages/rdom-components/CHANGELOG.md +++ b/packages/rdom-components/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.13](https://github.com/thi-ng/umbrella/compare/@thi.ng/rdom-components@0.1.12...@thi.ng/rdom-components@0.1.13) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rdom-components + + + + + ## [0.1.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/rdom-components@0.1.11...@thi.ng/rdom-components@0.1.12) (2020-09-13) **Note:** Version bump only for package @thi.ng/rdom-components diff --git a/packages/rdom-components/package.json b/packages/rdom-components/package.json index 4cecfc3cc2..695c7a0b8e 100644 --- a/packages/rdom-components/package.json +++ b/packages/rdom-components/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rdom-components", - "version": "0.1.12", + "version": "0.1.13", "description": "Collection of unstyled, customizable components for @thi.ng/rdom", "module": "./index.js", "main": "./lib/index.js", @@ -48,13 +48,13 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/associative": "^5.0.6", - "@thi.ng/hiccup-html": "^0.3.5", - "@thi.ng/rdom": "^0.2.11", - "@thi.ng/rstream": "^5.0.4", - "@thi.ng/strings": "^1.9.6", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/associative": "^5.0.7", + "@thi.ng/hiccup-html": "^0.3.6", + "@thi.ng/rdom": "^0.2.12", + "@thi.ng/rstream": "^5.0.5", + "@thi.ng/strings": "^1.10.0", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/rdom/CHANGELOG.md b/packages/rdom/CHANGELOG.md index e1f463b4f3..4cef5e5ace 100644 --- a/packages/rdom/CHANGELOG.md +++ b/packages/rdom/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/rdom@0.2.11...@thi.ng/rdom@0.2.12) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rdom + + + + + ## [0.2.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/rdom@0.2.10...@thi.ng/rdom@0.2.11) (2020-09-13) **Note:** Version bump only for package @thi.ng/rdom diff --git a/packages/rdom/package.json b/packages/rdom/package.json index 7686848aa6..7d989f0e76 100644 --- a/packages/rdom/package.json +++ b/packages/rdom/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rdom", - "version": "0.2.11", + "version": "0.2.12", "description": "Lightweight, reactive, VDOM-less UI/DOM components with async lifecycle and @thi.ng/hiccup compatible", "module": "./index.js", "main": "./lib/index.js", @@ -49,14 +49,14 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/hiccup": "^3.6.0", - "@thi.ng/paths": "^4.1.6", - "@thi.ng/prefixes": "^0.1.5", - "@thi.ng/rstream": "^5.0.4", - "@thi.ng/strings": "^1.9.6" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/hiccup": "^3.6.1", + "@thi.ng/paths": "^4.1.7", + "@thi.ng/prefixes": "^0.1.6", + "@thi.ng/rstream": "^5.0.5", + "@thi.ng/strings": "^1.10.0" }, "files": [ "*.js", diff --git a/packages/resolve-map/CHANGELOG.md b/packages/resolve-map/CHANGELOG.md index 6a5f862b7e..1b22fe2a01 100644 --- a/packages/resolve-map/CHANGELOG.md +++ b/packages/resolve-map/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [4.2.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@4.2.5...@thi.ng/resolve-map@4.2.6) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/resolve-map + + + + + ## [4.2.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@4.2.4...@thi.ng/resolve-map@4.2.5) (2020-09-13) **Note:** Version bump only for package @thi.ng/resolve-map diff --git a/packages/resolve-map/package.json b/packages/resolve-map/package.json index d5fd9c5f7b..edb4acf2a6 100644 --- a/packages/resolve-map/package.json +++ b/packages/resolve-map/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/resolve-map", - "version": "4.2.5", + "version": "4.2.6", "description": "DAG resolution of vanilla objects & arrays with internally linked values", "module": "./index.js", "main": "./lib/index.js", @@ -48,10 +48,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/paths": "^4.1.6" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/paths": "^4.1.7" }, "files": [ "*.js", diff --git a/packages/rle-pack/CHANGELOG.md b/packages/rle-pack/CHANGELOG.md index 1a0f699cbf..04f2cc9e35 100644 --- a/packages/rle-pack/CHANGELOG.md +++ b/packages/rle-pack/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.27](https://github.com/thi-ng/umbrella/compare/@thi.ng/rle-pack@2.1.26...@thi.ng/rle-pack@2.1.27) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rle-pack + + + + + ## [2.1.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/rle-pack@2.1.25...@thi.ng/rle-pack@2.1.26) (2020-09-13) **Note:** Version bump only for package @thi.ng/rle-pack diff --git a/packages/rle-pack/package.json b/packages/rle-pack/package.json index 63f94d5d82..fddeb237e9 100644 --- a/packages/rle-pack/package.json +++ b/packages/rle-pack/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rle-pack", - "version": "2.1.26", + "version": "2.1.27", "description": "Binary run-length encoding packer w/ flexible repeat bit widths", "module": "./index.js", "main": "./lib/index.js", @@ -50,8 +50,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/bitstream": "^1.1.26", - "@thi.ng/errors": "^1.2.21" + "@thi.ng/bitstream": "^1.1.27", + "@thi.ng/errors": "^1.2.22" }, "files": [ "*.js", diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index d5f0de270e..c24befd16e 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.32](https://github.com/thi-ng/umbrella/compare/@thi.ng/router@2.0.31...@thi.ng/router@2.0.32) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/router + + + + + ## [2.0.31](https://github.com/thi-ng/umbrella/compare/@thi.ng/router@2.0.30...@thi.ng/router@2.0.31) (2020-09-13) **Note:** Version bump only for package @thi.ng/router diff --git a/packages/router/package.json b/packages/router/package.json index 62034f28ff..be94e18808 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/router", - "version": "2.0.31", + "version": "2.0.32", "description": "Generic router for browser & non-browser based applications", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", "tslib": "^2.0.1" }, "files": [ diff --git a/packages/rstream-csp/CHANGELOG.md b/packages/rstream-csp/CHANGELOG.md index 3cafe320ad..f86fdb5a86 100644 --- a/packages/rstream-csp/CHANGELOG.md +++ b/packages/rstream-csp/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.40](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@2.0.39...@thi.ng/rstream-csp@2.0.40) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rstream-csp + + + + + ## [2.0.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@2.0.38...@thi.ng/rstream-csp@2.0.39) (2020-09-13) **Note:** Version bump only for package @thi.ng/rstream-csp diff --git a/packages/rstream-csp/package.json b/packages/rstream-csp/package.json index d96f559b06..d0050ccb74 100644 --- a/packages/rstream-csp/package.json +++ b/packages/rstream-csp/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-csp", - "version": "2.0.39", + "version": "2.0.40", "description": "@thi.ng/csp bridge module for @thi.ng/rstream", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/csp": "^1.1.38", - "@thi.ng/rstream": "^5.0.4" + "@thi.ng/csp": "^1.1.39", + "@thi.ng/rstream": "^5.0.5" }, "files": [ "*.js", diff --git a/packages/rstream-dot/CHANGELOG.md b/packages/rstream-dot/CHANGELOG.md index b8f9e125ed..a20ea029be 100644 --- a/packages/rstream-dot/CHANGELOG.md +++ b/packages/rstream-dot/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.47](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@1.1.46...@thi.ng/rstream-dot@1.1.47) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rstream-dot + + + + + ## [1.1.46](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@1.1.45...@thi.ng/rstream-dot@1.1.46) (2020-09-13) **Note:** Version bump only for package @thi.ng/rstream-dot diff --git a/packages/rstream-dot/package.json b/packages/rstream-dot/package.json index 99172fa477..c69d09ed24 100644 --- a/packages/rstream-dot/package.json +++ b/packages/rstream-dot/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-dot", - "version": "1.1.46", + "version": "1.1.47", "description": "Graphviz DOT conversion of @thi.ng/rstream dataflow graph topologies", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/rstream": "^5.0.4" + "@thi.ng/rstream": "^5.0.5" }, "files": [ "*.js", diff --git a/packages/rstream-gestures/CHANGELOG.md b/packages/rstream-gestures/CHANGELOG.md index d85502ac67..8d39b270b5 100644 --- a/packages/rstream-gestures/CHANGELOG.md +++ b/packages/rstream-gestures/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@2.0.38...@thi.ng/rstream-gestures@2.0.39) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rstream-gestures + + + + + ## [2.0.38](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@2.0.37...@thi.ng/rstream-gestures@2.0.38) (2020-09-13) **Note:** Version bump only for package @thi.ng/rstream-gestures diff --git a/packages/rstream-gestures/package.json b/packages/rstream-gestures/package.json index d37e2b8e4f..c0afc90864 100644 --- a/packages/rstream-gestures/package.json +++ b/packages/rstream-gestures/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-gestures", - "version": "2.0.38", + "version": "2.0.39", "description": "Unified mouse, mouse wheel & multi-touch event stream abstraction", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/math": "^2.1.0", - "@thi.ng/rstream": "^5.0.4", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/math": "^2.1.1", + "@thi.ng/rstream": "^5.0.5", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/rstream-graph/CHANGELOG.md b/packages/rstream-graph/CHANGELOG.md index 7651794096..d61a792cc0 100644 --- a/packages/rstream-graph/CHANGELOG.md +++ b/packages/rstream-graph/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.2.41](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@3.2.40...@thi.ng/rstream-graph@3.2.41) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rstream-graph + + + + + ## [3.2.40](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@3.2.39...@thi.ng/rstream-graph@3.2.40) (2020-09-13) **Note:** Version bump only for package @thi.ng/rstream-graph diff --git a/packages/rstream-graph/package.json b/packages/rstream-graph/package.json index 9089a88d38..48b0846b93 100644 --- a/packages/rstream-graph/package.json +++ b/packages/rstream-graph/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-graph", - "version": "3.2.40", + "version": "3.2.41", "description": "Declarative dataflow graph construction for @thi.ng/rstream", "module": "./index.js", "main": "./lib/index.js", @@ -49,14 +49,14 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/atom": "^4.1.20", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/paths": "^4.1.6", - "@thi.ng/resolve-map": "^4.2.5", - "@thi.ng/rstream": "^5.0.4", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/atom": "^4.1.21", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/paths": "^4.1.7", + "@thi.ng/resolve-map": "^4.2.6", + "@thi.ng/rstream": "^5.0.5", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/rstream-log-file/CHANGELOG.md b/packages/rstream-log-file/CHANGELOG.md index 50ddbbef59..eadf615873 100644 --- a/packages/rstream-log-file/CHANGELOG.md +++ b/packages/rstream-log-file/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.62](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log-file@0.1.61...@thi.ng/rstream-log-file@0.1.62) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rstream-log-file + + + + + ## [0.1.61](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log-file@0.1.60...@thi.ng/rstream-log-file@0.1.61) (2020-09-13) **Note:** Version bump only for package @thi.ng/rstream-log-file diff --git a/packages/rstream-log-file/package.json b/packages/rstream-log-file/package.json index 9c468c4528..27d08cad98 100644 --- a/packages/rstream-log-file/package.json +++ b/packages/rstream-log-file/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-log-file", - "version": "0.1.61", + "version": "0.1.62", "description": "File output handler for structured, multilevel & hierarchical loggers based on @thi.ng/rstream", "module": "./index.js", "main": "./lib/index.js", @@ -49,7 +49,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/rstream": "^5.0.4" + "@thi.ng/rstream": "^5.0.5" }, "files": [ "*.js", diff --git a/packages/rstream-log/CHANGELOG.md b/packages/rstream-log/CHANGELOG.md index 9170844f41..0223fa9d73 100644 --- a/packages/rstream-log/CHANGELOG.md +++ b/packages/rstream-log/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.1.47](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@3.1.46...@thi.ng/rstream-log@3.1.47) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rstream-log + + + + + ## [3.1.46](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@3.1.45...@thi.ng/rstream-log@3.1.46) (2020-09-13) **Note:** Version bump only for package @thi.ng/rstream-log diff --git a/packages/rstream-log/package.json b/packages/rstream-log/package.json index 045079ae19..0f73e6b7bf 100644 --- a/packages/rstream-log/package.json +++ b/packages/rstream-log/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-log", - "version": "3.1.46", + "version": "3.1.47", "description": "Structured, multilevel & hierarchical loggers based on @thi.ng/rstream", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/rstream": "^5.0.4", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/rstream": "^5.0.5", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/rstream-query/CHANGELOG.md b/packages/rstream-query/CHANGELOG.md index 2fea0435a8..24d9acce1e 100644 --- a/packages/rstream-query/CHANGELOG.md +++ b/packages/rstream-query/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.47](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@1.1.46...@thi.ng/rstream-query@1.1.47) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rstream-query + + + + + ## [1.1.46](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@1.1.45...@thi.ng/rstream-query@1.1.46) (2020-09-13) **Note:** Version bump only for package @thi.ng/rstream-query diff --git a/packages/rstream-query/package.json b/packages/rstream-query/package.json index 7e9b79ead0..d19ad9825e 100644 --- a/packages/rstream-query/package.json +++ b/packages/rstream-query/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-query", - "version": "1.1.46", + "version": "1.1.47", "description": "@thi.ng/rstream based triple store & reactive query engine", "module": "./index.js", "main": "./lib/index.js", @@ -49,15 +49,15 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/associative": "^5.0.6", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/math": "^2.1.0", - "@thi.ng/rstream": "^5.0.4", - "@thi.ng/rstream-dot": "^1.1.46", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/associative": "^5.0.7", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/math": "^2.1.1", + "@thi.ng/rstream": "^5.0.5", + "@thi.ng/rstream-dot": "^1.1.47", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/rstream/CHANGELOG.md b/packages/rstream/CHANGELOG.md index 9c9d72e7b0..65279d130f 100644 --- a/packages/rstream/CHANGELOG.md +++ b/packages/rstream/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [5.0.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@5.0.4...@thi.ng/rstream@5.0.5) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/rstream + + + + + ## [5.0.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@5.0.3...@thi.ng/rstream@5.0.4) (2020-09-13) diff --git a/packages/rstream/package.json b/packages/rstream/package.json index 08dfcba05a..e5d5a8f157 100644 --- a/packages/rstream/package.json +++ b/packages/rstream/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream", - "version": "5.0.4", + "version": "5.0.5", "description": "Reactive streams & subscription primitives for constructing dataflow graphs / pipelines", "module": "./index.js", "main": "./lib/index.js", @@ -49,13 +49,13 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/associative": "^5.0.6", - "@thi.ng/atom": "^4.1.20", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/associative": "^5.0.7", + "@thi.ng/atom": "^4.1.21", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/sax/CHANGELOG.md b/packages/sax/CHANGELOG.md index 6293cbc6ce..6f38b6dc1a 100644 --- a/packages/sax/CHANGELOG.md +++ b/packages/sax/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/sax@1.1.38...@thi.ng/sax@1.1.39) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/sax + + + + + ## [1.1.38](https://github.com/thi-ng/umbrella/compare/@thi.ng/sax@1.1.37...@thi.ng/sax@1.1.38) (2020-09-13) **Note:** Version bump only for package @thi.ng/sax diff --git a/packages/sax/package.json b/packages/sax/package.json index c92b378a70..fa478bac0c 100644 --- a/packages/sax/package.json +++ b/packages/sax/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/sax", - "version": "1.1.38", + "version": "1.1.39", "description": "Transducer-based, SAX-like, non-validating, speedy & tiny XML parser", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/transducers-fsm": "^1.1.38" + "@thi.ng/api": "^6.13.1", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/transducers-fsm": "^1.1.39" }, "files": [ "*.js", diff --git a/packages/scenegraph/CHANGELOG.md b/packages/scenegraph/CHANGELOG.md index 232eaf9497..d138bc0868 100644 --- a/packages/scenegraph/CHANGELOG.md +++ b/packages/scenegraph/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.3.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/scenegraph@0.3.6...@thi.ng/scenegraph@0.3.7) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/scenegraph + + + + + ## [0.3.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/scenegraph@0.3.5...@thi.ng/scenegraph@0.3.6) (2020-09-13) **Note:** Version bump only for package @thi.ng/scenegraph diff --git a/packages/scenegraph/package.json b/packages/scenegraph/package.json index 968bc4966f..c6fe7d8660 100644 --- a/packages/scenegraph/package.json +++ b/packages/scenegraph/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/scenegraph", - "version": "0.3.6", + "version": "0.3.7", "description": "Extensible 2D/3D scene graph with @thi.ng/hiccup-canvas support", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/matrices": "^0.6.32", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/matrices": "^0.6.33", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/seq/CHANGELOG.md b/packages/seq/CHANGELOG.md index 69fc851182..af95cd4979 100644 --- a/packages/seq/CHANGELOG.md +++ b/packages/seq/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/seq@0.2.23...@thi.ng/seq@0.2.24) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/seq + + + + + ## [0.2.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/seq@0.2.22...@thi.ng/seq@0.2.23) (2020-09-13) **Note:** Version bump only for package @thi.ng/seq diff --git a/packages/seq/package.json b/packages/seq/package.json index e6894dfe01..0c12fcf01a 100644 --- a/packages/seq/package.json +++ b/packages/seq/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/seq", - "version": "0.2.23", + "version": "0.2.24", "description": "Various implementations of the @thi.ng/api `ISeq` interface / sequence abstraction", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9" }, "files": [ "*.js", diff --git a/packages/sexpr/CHANGELOG.md b/packages/sexpr/CHANGELOG.md index a37245acb5..363892aa4f 100644 --- a/packages/sexpr/CHANGELOG.md +++ b/packages/sexpr/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.27](https://github.com/thi-ng/umbrella/compare/@thi.ng/sexpr@0.2.26...@thi.ng/sexpr@0.2.27) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/sexpr + + + + + ## [0.2.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/sexpr@0.2.25...@thi.ng/sexpr@0.2.26) (2020-09-13) **Note:** Version bump only for package @thi.ng/sexpr diff --git a/packages/sexpr/package.json b/packages/sexpr/package.json index b5f7ffbda1..87351486fd 100644 --- a/packages/sexpr/package.json +++ b/packages/sexpr/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/sexpr", - "version": "0.2.26", + "version": "0.2.27", "description": "Extensible S-Expression parser & runtime infrastructure", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/defmulti": "^1.2.25" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/defmulti": "^1.2.26" }, "files": [ "*.js", diff --git a/packages/shader-ast-glsl/CHANGELOG.md b/packages/shader-ast-glsl/CHANGELOG.md index 3d5ceffc93..63bd92c5ae 100644 --- a/packages/shader-ast-glsl/CHANGELOG.md +++ b/packages/shader-ast-glsl/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/shader-ast-glsl@0.2.9...@thi.ng/shader-ast-glsl@0.2.10) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/shader-ast-glsl + + + + + ## [0.2.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/shader-ast-glsl@0.2.8...@thi.ng/shader-ast-glsl@0.2.9) (2020-09-13) **Note:** Version bump only for package @thi.ng/shader-ast-glsl diff --git a/packages/shader-ast-glsl/package.json b/packages/shader-ast-glsl/package.json index f7b16ae067..9ccdb08ed0 100644 --- a/packages/shader-ast-glsl/package.json +++ b/packages/shader-ast-glsl/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/shader-ast-glsl", - "version": "0.2.9", + "version": "0.2.10", "description": "Customizable GLSL codegen for @thi.ng/shader-ast", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/shader-ast": "^0.7.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/shader-ast": "^0.7.2" }, "files": [ "*.js", diff --git a/packages/shader-ast-js/CHANGELOG.md b/packages/shader-ast-js/CHANGELOG.md index 7758388332..32b2d5e4e1 100644 --- a/packages/shader-ast-js/CHANGELOG.md +++ b/packages/shader-ast-js/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.5.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/shader-ast-js@0.5.6...@thi.ng/shader-ast-js@0.5.7) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/shader-ast-js + + + + + ## [0.5.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/shader-ast-js@0.5.5...@thi.ng/shader-ast-js@0.5.6) (2020-09-13) **Note:** Version bump only for package @thi.ng/shader-ast-js diff --git a/packages/shader-ast-js/package.json b/packages/shader-ast-js/package.json index 3496f42373..f928a3143e 100644 --- a/packages/shader-ast-js/package.json +++ b/packages/shader-ast-js/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/shader-ast-js", - "version": "0.5.6", + "version": "0.5.7", "description": "Customizable JS codegen, compiler & runtime for @thi.ng/shader-ast", "module": "./index.js", "main": "./lib/index.js", @@ -49,14 +49,14 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/math": "^2.1.0", - "@thi.ng/matrices": "^0.6.32", - "@thi.ng/pixel": "^0.4.5", - "@thi.ng/shader-ast": "^0.7.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/math": "^2.1.1", + "@thi.ng/matrices": "^0.6.33", + "@thi.ng/pixel": "^0.4.6", + "@thi.ng/shader-ast": "^0.7.2", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/shader-ast-stdlib/CHANGELOG.md b/packages/shader-ast-stdlib/CHANGELOG.md index c56bb6a41e..dfda7eb92a 100644 --- a/packages/shader-ast-stdlib/CHANGELOG.md +++ b/packages/shader-ast-stdlib/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.5.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/shader-ast-stdlib@0.5.1...@thi.ng/shader-ast-stdlib@0.5.2) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/shader-ast-stdlib + + + + + ## [0.5.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/shader-ast-stdlib@0.5.0...@thi.ng/shader-ast-stdlib@0.5.1) (2020-09-13) **Note:** Version bump only for package @thi.ng/shader-ast-stdlib diff --git a/packages/shader-ast-stdlib/package.json b/packages/shader-ast-stdlib/package.json index fc73914d09..a11b09bd1d 100644 --- a/packages/shader-ast-stdlib/package.json +++ b/packages/shader-ast-stdlib/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/shader-ast-stdlib", - "version": "0.5.1", + "version": "0.5.2", "description": "Function collection for modular GPGPU / shader programming with @thi.ng/shader-ast", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/shader-ast": "^0.7.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/shader-ast": "^0.7.2" }, "files": [ "*.js", diff --git a/packages/shader-ast/CHANGELOG.md b/packages/shader-ast/CHANGELOG.md index 5f430cbc97..ac40d64d16 100644 --- a/packages/shader-ast/CHANGELOG.md +++ b/packages/shader-ast/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.7.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/shader-ast@0.7.1...@thi.ng/shader-ast@0.7.2) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/shader-ast + + + + + ## [0.7.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/shader-ast@0.7.0...@thi.ng/shader-ast@0.7.1) (2020-09-13) **Note:** Version bump only for package @thi.ng/shader-ast diff --git a/packages/shader-ast/package.json b/packages/shader-ast/package.json index 063f8a931f..781b87e0fe 100644 --- a/packages/shader-ast/package.json +++ b/packages/shader-ast/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/shader-ast", - "version": "0.7.1", + "version": "0.7.2", "description": "DSL to define shader code in TypeScript and cross-compile to GLSL, JS and other targets", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/defmulti": "^1.2.25", - "@thi.ng/dgraph": "^1.2.26", - "@thi.ng/errors": "^1.2.21" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/defmulti": "^1.2.26", + "@thi.ng/dgraph": "^1.2.27", + "@thi.ng/errors": "^1.2.22" }, "files": [ "*.js", diff --git a/packages/simd/CHANGELOG.md b/packages/simd/CHANGELOG.md index 338795477f..b172741b2b 100644 --- a/packages/simd/CHANGELOG.md +++ b/packages/simd/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.4.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/simd@0.4.6...@thi.ng/simd@0.4.7) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/simd + + + + + ## [0.4.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/simd@0.4.5...@thi.ng/simd@0.4.6) (2020-09-13) **Note:** Version bump only for package @thi.ng/simd diff --git a/packages/simd/package.json b/packages/simd/package.json index 9a076fb449..25624668cd 100644 --- a/packages/simd/package.json +++ b/packages/simd/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/simd", - "version": "0.4.6", + "version": "0.4.7", "description": "WASM based SIMD vector operations for batch processing", "module": "./index.js", "main": "./lib/index.js", @@ -52,7 +52,7 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/transducers-binary": "^0.5.29" + "@thi.ng/transducers-binary": "^0.5.30" }, "files": [ "*.js", diff --git a/packages/soa/CHANGELOG.md b/packages/soa/CHANGELOG.md index b172eee602..03f026f2cc 100644 --- a/packages/soa/CHANGELOG.md +++ b/packages/soa/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.37](https://github.com/thi-ng/umbrella/compare/@thi.ng/soa@0.1.36...@thi.ng/soa@0.1.37) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/soa + + + + + ## [0.1.36](https://github.com/thi-ng/umbrella/compare/@thi.ng/soa@0.1.35...@thi.ng/soa@0.1.36) (2020-09-13) **Note:** Version bump only for package @thi.ng/soa diff --git a/packages/soa/package.json b/packages/soa/package.json index aadd0ee669..95b2f0c800 100644 --- a/packages/soa/package.json +++ b/packages/soa/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/soa", - "version": "0.1.36", + "version": "0.1.37", "description": "SOA & AOS memory mapped structured views with optional & extensible serialization", "module": "./index.js", "main": "./lib/index.js", @@ -40,7 +40,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/equiv": "^1.0.31", + "@thi.ng/equiv": "^1.0.32", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", @@ -50,10 +50,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/transducers-binary": "^0.5.29", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/transducers-binary": "^0.5.30", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/sparse/CHANGELOG.md b/packages/sparse/CHANGELOG.md index 87af3feca5..6c73f62bac 100644 --- a/packages/sparse/CHANGELOG.md +++ b/packages/sparse/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.55](https://github.com/thi-ng/umbrella/compare/@thi.ng/sparse@0.1.54...@thi.ng/sparse@0.1.55) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/sparse + + + + + ## [0.1.54](https://github.com/thi-ng/umbrella/compare/@thi.ng/sparse@0.1.53...@thi.ng/sparse@0.1.54) (2020-09-13) **Note:** Version bump only for package @thi.ng/sparse diff --git a/packages/sparse/package.json b/packages/sparse/package.json index 0a179b7641..38c2f280bc 100644 --- a/packages/sparse/package.json +++ b/packages/sparse/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/sparse", - "version": "0.1.54", + "version": "0.1.55", "description": "Sparse vector & matrix implementations", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/strings/CHANGELOG.md b/packages/strings/CHANGELOG.md index a5b54e1a5a..d53f77edc3 100644 --- a/packages/strings/CHANGELOG.md +++ b/packages/strings/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.10.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/strings@1.9.6...@thi.ng/strings@1.10.0) (2020-09-22) + + +### Features + +* **strings:** add BOM const, update pkg meta ([b6751fc](https://github.com/thi-ng/umbrella/commit/b6751fc506a28a075ea9fee1a5f6d3520449f5af)) +* **strings:** add escape(), update unescape(), add tests ([e0d5f1e](https://github.com/thi-ng/umbrella/commit/e0d5f1edcdf78b075908c4973586a0f1732fe006)) +* **strings:** add unescape() ([924466b](https://github.com/thi-ng/umbrella/commit/924466bc5d5f16ced3da95fa2f24dab2bfad0679)) + + + + + ## [1.9.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/strings@1.9.5...@thi.ng/strings@1.9.6) (2020-09-13) **Note:** Version bump only for package @thi.ng/strings diff --git a/packages/strings/package.json b/packages/strings/package.json index c8bf4e5e40..a7397457a3 100644 --- a/packages/strings/package.json +++ b/packages/strings/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/strings", - "version": "1.9.6", + "version": "1.10.0", "description": "Various string formatting & utility functions", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/memoize": "^2.1.2" + "@thi.ng/api": "^6.13.1", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/memoize": "^2.1.3" }, "files": [ "*.js", diff --git a/packages/system/CHANGELOG.md b/packages/system/CHANGELOG.md index 746d877c85..4e9f53d776 100644 --- a/packages/system/CHANGELOG.md +++ b/packages/system/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.27](https://github.com/thi-ng/umbrella/compare/@thi.ng/system@0.2.26...@thi.ng/system@0.2.27) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/system + + + + + ## [0.2.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/system@0.2.25...@thi.ng/system@0.2.26) (2020-09-13) diff --git a/packages/system/package.json b/packages/system/package.json index 8be54d4a62..6238778296 100644 --- a/packages/system/package.json +++ b/packages/system/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/system", - "version": "0.2.26", + "version": "0.2.27", "description": "Minimal DI / life cycle container for stateful app components", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/dgraph": "^1.2.26" + "@thi.ng/api": "^6.13.1", + "@thi.ng/dgraph": "^1.2.27" }, "files": [ "*.js", diff --git a/packages/text-canvas/CHANGELOG.md b/packages/text-canvas/CHANGELOG.md index af6ef6c17c..3546f19d96 100644 --- a/packages/text-canvas/CHANGELOG.md +++ b/packages/text-canvas/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.31](https://github.com/thi-ng/umbrella/compare/@thi.ng/text-canvas@0.2.30...@thi.ng/text-canvas@0.2.31) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/text-canvas + + + + + ## [0.2.30](https://github.com/thi-ng/umbrella/compare/@thi.ng/text-canvas@0.2.29...@thi.ng/text-canvas@0.2.30) (2020-09-13) **Note:** Version bump only for package @thi.ng/text-canvas diff --git a/packages/text-canvas/package.json b/packages/text-canvas/package.json index eebfb57003..80d22e723c 100644 --- a/packages/text-canvas/package.json +++ b/packages/text-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/text-canvas", - "version": "0.2.30", + "version": "0.2.31", "description": "Text based canvas, drawing, tables with arbitrary formatting (incl. ANSI/HTML)", "module": "./index.js", "main": "./lib/index.js", @@ -49,14 +49,14 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/geom-clip-line": "^1.2.8", - "@thi.ng/math": "^2.1.0", - "@thi.ng/memoize": "^2.1.2", - "@thi.ng/strings": "^1.9.6", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/geom-clip-line": "^1.2.9", + "@thi.ng/math": "^2.1.1", + "@thi.ng/memoize": "^2.1.3", + "@thi.ng/strings": "^1.10.0", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/transducers-binary/CHANGELOG.md b/packages/transducers-binary/CHANGELOG.md index 7f697b884b..f3e8ddb51c 100644 --- a/packages/transducers-binary/CHANGELOG.md +++ b/packages/transducers-binary/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.5.30](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-binary@0.5.29...@thi.ng/transducers-binary@0.5.30) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/transducers-binary + + + + + ## [0.5.29](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-binary@0.5.28...@thi.ng/transducers-binary@0.5.29) (2020-09-13) **Note:** Version bump only for package @thi.ng/transducers-binary diff --git a/packages/transducers-binary/package.json b/packages/transducers-binary/package.json index 926fb7d04a..6881fde450 100644 --- a/packages/transducers-binary/package.json +++ b/packages/transducers-binary/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers-binary", - "version": "0.5.29", + "version": "0.5.30", "description": "Binary data related transducers & reducers", "module": "./index.js", "main": "./lib/index.js", @@ -49,12 +49,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/binary": "^2.0.15", - "@thi.ng/compose": "^1.4.17", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/random": "^2.0.1", - "@thi.ng/strings": "^1.9.6", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/binary": "^2.0.16", + "@thi.ng/compose": "^1.4.18", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/random": "^2.0.2", + "@thi.ng/strings": "^1.10.0", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/transducers-fsm/CHANGELOG.md b/packages/transducers-fsm/CHANGELOG.md index e1d7d3ed46..9642ea21c3 100644 --- a/packages/transducers-fsm/CHANGELOG.md +++ b/packages/transducers-fsm/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-fsm@1.1.38...@thi.ng/transducers-fsm@1.1.39) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/transducers-fsm + + + + + ## [1.1.38](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-fsm@1.1.37...@thi.ng/transducers-fsm@1.1.38) (2020-09-13) **Note:** Version bump only for package @thi.ng/transducers-fsm diff --git a/packages/transducers-fsm/package.json b/packages/transducers-fsm/package.json index cc4e43ae53..cad21b2a55 100644 --- a/packages/transducers-fsm/package.json +++ b/packages/transducers-fsm/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers-fsm", - "version": "1.1.38", + "version": "1.1.39", "description": "Transducer-based Finite State Machine transformer", "module": "./index.js", "main": "./lib/index.js", @@ -49,8 +49,8 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/transducers-hdom/CHANGELOG.md b/packages/transducers-hdom/CHANGELOG.md index fb47335f1c..9bfb0616bf 100644 --- a/packages/transducers-hdom/CHANGELOG.md +++ b/packages/transducers-hdom/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.71](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-hdom@2.0.70...@thi.ng/transducers-hdom@2.0.71) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/transducers-hdom + + + + + ## [2.0.70](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-hdom@2.0.69...@thi.ng/transducers-hdom@2.0.70) (2020-09-13) **Note:** Version bump only for package @thi.ng/transducers-hdom diff --git a/packages/transducers-hdom/package.json b/packages/transducers-hdom/package.json index 4d0e4dd6e5..acf036ea76 100644 --- a/packages/transducers-hdom/package.json +++ b/packages/transducers-hdom/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers-hdom", - "version": "2.0.70", + "version": "2.0.71", "description": "Transducer based UI updater for @thi.ng/hdom", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/hdom": "^8.2.9", - "@thi.ng/hiccup": "^3.6.0", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/hdom": "^8.2.10", + "@thi.ng/hiccup": "^3.6.1", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/transducers-patch/CHANGELOG.md b/packages/transducers-patch/CHANGELOG.md index c4610d3e4e..913991f563 100644 --- a/packages/transducers-patch/CHANGELOG.md +++ b/packages/transducers-patch/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.30](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-patch@0.1.29...@thi.ng/transducers-patch@0.1.30) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/transducers-patch + + + + + ## [0.1.29](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-patch@0.1.28...@thi.ng/transducers-patch@0.1.29) (2020-09-13) **Note:** Version bump only for package @thi.ng/transducers-patch diff --git a/packages/transducers-patch/package.json b/packages/transducers-patch/package.json index 31752790cb..14fe942eed 100644 --- a/packages/transducers-patch/package.json +++ b/packages/transducers-patch/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers-patch", - "version": "0.1.29", + "version": "0.1.30", "description": "Reducers for patch-based, immutable-by-default array & object editing", "module": "./index.js", "main": "./lib/index.js", @@ -49,11 +49,11 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/paths": "^4.1.6", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/paths": "^4.1.7", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/transducers-stats/CHANGELOG.md b/packages/transducers-stats/CHANGELOG.md index 0240ee2702..9c4ddc272c 100644 --- a/packages/transducers-stats/CHANGELOG.md +++ b/packages/transducers-stats/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-stats@1.1.38...@thi.ng/transducers-stats@1.1.39) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/transducers-stats + + + + + ## [1.1.38](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-stats@1.1.37...@thi.ng/transducers-stats@1.1.38) (2020-09-13) **Note:** Version bump only for package @thi.ng/transducers-stats diff --git a/packages/transducers-stats/package.json b/packages/transducers-stats/package.json index 637c9b5eba..f7a7c72512 100644 --- a/packages/transducers-stats/package.json +++ b/packages/transducers-stats/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers-stats", - "version": "1.1.38", + "version": "1.1.39", "description": "Transducers for statistical / technical analysis", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/checks": "^2.7.8", - "@thi.ng/dcons": "^2.2.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/checks": "^2.7.9", + "@thi.ng/dcons": "^2.2.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/transducers/CHANGELOG.md b/packages/transducers/CHANGELOG.md index 444142acbd..25f2e3208c 100644 --- a/packages/transducers/CHANGELOG.md +++ b/packages/transducers/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers@7.3.1...@thi.ng/transducers@7.4.0) (2020-09-22) + + +### Features + +* **transducers:** add mapcatIndexed() xform ([4f3d6e0](https://github.com/thi-ng/umbrella/commit/4f3d6e02a0ff3fe7307cd03404277c03123f83e9)) + + + + + ## [7.3.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers@7.3.0...@thi.ng/transducers@7.3.1) (2020-09-13) **Note:** Version bump only for package @thi.ng/transducers diff --git a/packages/transducers/package.json b/packages/transducers/package.json index 3b990ce318..7219223795 100644 --- a/packages/transducers/package.json +++ b/packages/transducers/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers", - "version": "7.3.1", + "version": "7.4.0", "description": "Lightweight transducer implementations for ES6 / TypeScript", "module": "./index.js", "main": "./lib/index.js", @@ -49,14 +49,14 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/compare": "^1.3.16", - "@thi.ng/compose": "^1.4.17", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/math": "^2.1.0", - "@thi.ng/random": "^2.0.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/compare": "^1.3.17", + "@thi.ng/compose": "^1.4.18", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/math": "^2.1.1", + "@thi.ng/random": "^2.0.2" }, "files": [ "*.js", diff --git a/packages/unionstruct/CHANGELOG.md b/packages/unionstruct/CHANGELOG.md index 46d9c6ddea..5ed6d17623 100644 --- a/packages/unionstruct/CHANGELOG.md +++ b/packages/unionstruct/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.25](https://github.com/thi-ng/umbrella/compare/@thi.ng/unionstruct@1.1.24...@thi.ng/unionstruct@1.1.25) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/unionstruct + + + + + ## [1.1.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/unionstruct@1.1.23...@thi.ng/unionstruct@1.1.24) (2020-09-13) **Note:** Version bump only for package @thi.ng/unionstruct diff --git a/packages/unionstruct/package.json b/packages/unionstruct/package.json index fd4571c8b6..797fdbdb9f 100644 --- a/packages/unionstruct/package.json +++ b/packages/unionstruct/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/unionstruct", - "version": "1.1.24", + "version": "1.1.25", "description": "C-style struct, union and bitfield read/write views of ArrayBuffers", "module": "./index.js", "main": "./lib/index.js", diff --git a/packages/vector-pools/CHANGELOG.md b/packages/vector-pools/CHANGELOG.md index 3809ab0a3b..368a598d47 100644 --- a/packages/vector-pools/CHANGELOG.md +++ b/packages/vector-pools/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.46](https://github.com/thi-ng/umbrella/compare/@thi.ng/vector-pools@1.0.45...@thi.ng/vector-pools@1.0.46) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/vector-pools + + + + + ## [1.0.45](https://github.com/thi-ng/umbrella/compare/@thi.ng/vector-pools@1.0.44...@thi.ng/vector-pools@1.0.45) (2020-09-13) **Note:** Version bump only for package @thi.ng/vector-pools diff --git a/packages/vector-pools/package.json b/packages/vector-pools/package.json index 187cbcd9ca..1c82f04ea7 100644 --- a/packages/vector-pools/package.json +++ b/packages/vector-pools/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/vector-pools", - "version": "1.0.45", + "version": "1.0.46", "description": "Data structures for managing & working with strided, memory mapped vectors", "module": "./index.js", "main": "./lib/index.js", @@ -49,12 +49,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/malloc": "^4.1.25", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/api": "^6.13.1", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/malloc": "^4.1.26", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/vectors/CHANGELOG.md b/packages/vectors/CHANGELOG.md index 24dd914d3d..e2407d08ba 100644 --- a/packages/vectors/CHANGELOG.md +++ b/packages/vectors/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [4.6.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@4.6.5...@thi.ng/vectors@4.6.6) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/vectors + + + + + ## [4.6.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@4.6.4...@thi.ng/vectors@4.6.5) (2020-09-13) **Note:** Version bump only for package @thi.ng/vectors diff --git a/packages/vectors/package.json b/packages/vectors/package.json index 5925f1c4fa..b838a8d9be 100644 --- a/packages/vectors/package.json +++ b/packages/vectors/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/vectors", - "version": "4.6.5", + "version": "4.6.6", "description": "Optimized 2d/3d/4d and arbitrary length vector operations", "module": "./index.js", "main": "./lib/index.js", @@ -49,15 +49,15 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/binary": "^2.0.15", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/math": "^2.1.0", - "@thi.ng/memoize": "^2.1.2", - "@thi.ng/random": "^2.0.1", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/binary": "^2.0.16", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/math": "^2.1.1", + "@thi.ng/memoize": "^2.1.3", + "@thi.ng/random": "^2.0.2", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/viz/CHANGELOG.md b/packages/viz/CHANGELOG.md index 1053418f82..6dcbfd0c2a 100644 --- a/packages/viz/CHANGELOG.md +++ b/packages/viz/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/viz@0.1.0...@thi.ng/viz@0.1.1) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/viz + + + + + # 0.1.0 (2020-09-13) diff --git a/packages/viz/package.json b/packages/viz/package.json index 8e2965c11b..961738c052 100644 --- a/packages/viz/package.json +++ b/packages/viz/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/viz", - "version": "0.1.0", + "version": "0.1.1", "description": "Declarative, functional & multi-format data visualization toolkit based around @thi.ng/hiccup", "module": "./index.js", "main": "./lib/index.js", @@ -43,7 +43,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/api-extractor": "^7.9.11", - "@thi.ng/date": "^0.1.0", + "@thi.ng/date": "^0.2.0", "@types/mocha": "^8.0.3", "@types/node": "^14.6.1", "mocha": "^8.1.2", @@ -53,13 +53,13 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/associative": "^5.0.6", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/math": "^2.1.0", - "@thi.ng/strings": "^1.9.6", - "@thi.ng/transducers": "^7.3.1" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/associative": "^5.0.7", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/math": "^2.1.1", + "@thi.ng/strings": "^1.10.0", + "@thi.ng/transducers": "^7.4.0" }, "files": [ "*.js", diff --git a/packages/webgl-msdf/CHANGELOG.md b/packages/webgl-msdf/CHANGELOG.md index 139be3e891..16bd308dde 100644 --- a/packages/webgl-msdf/CHANGELOG.md +++ b/packages/webgl-msdf/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.60](https://github.com/thi-ng/umbrella/compare/@thi.ng/webgl-msdf@0.1.59...@thi.ng/webgl-msdf@0.1.60) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/webgl-msdf + + + + + ## [0.1.59](https://github.com/thi-ng/umbrella/compare/@thi.ng/webgl-msdf@0.1.58...@thi.ng/webgl-msdf@0.1.59) (2020-09-13) **Note:** Version bump only for package @thi.ng/webgl-msdf diff --git a/packages/webgl-msdf/package.json b/packages/webgl-msdf/package.json index e7b5353e9c..4b5ecd47fe 100644 --- a/packages/webgl-msdf/package.json +++ b/packages/webgl-msdf/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/webgl-msdf", - "version": "0.1.59", + "version": "0.1.60", "description": "Multi-channel SDF font rendering & basic text layout for WebGL", "module": "./index.js", "main": "./lib/index.js", @@ -49,12 +49,12 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/shader-ast": "^0.7.1", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vector-pools": "^1.0.45", - "@thi.ng/vectors": "^4.6.5", - "@thi.ng/webgl": "^3.3.2" + "@thi.ng/api": "^6.13.1", + "@thi.ng/shader-ast": "^0.7.2", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vector-pools": "^1.0.46", + "@thi.ng/vectors": "^4.6.6", + "@thi.ng/webgl": "^3.3.3" }, "files": [ "*.js", diff --git a/packages/webgl-shadertoy/CHANGELOG.md b/packages/webgl-shadertoy/CHANGELOG.md index 44294812fe..bb8dd78931 100644 --- a/packages/webgl-shadertoy/CHANGELOG.md +++ b/packages/webgl-shadertoy/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.47](https://github.com/thi-ng/umbrella/compare/@thi.ng/webgl-shadertoy@0.2.46...@thi.ng/webgl-shadertoy@0.2.47) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/webgl-shadertoy + + + + + ## [0.2.46](https://github.com/thi-ng/umbrella/compare/@thi.ng/webgl-shadertoy@0.2.45...@thi.ng/webgl-shadertoy@0.2.46) (2020-09-13) **Note:** Version bump only for package @thi.ng/webgl-shadertoy diff --git a/packages/webgl-shadertoy/package.json b/packages/webgl-shadertoy/package.json index 55fc2df317..0671416797 100644 --- a/packages/webgl-shadertoy/package.json +++ b/packages/webgl-shadertoy/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/webgl-shadertoy", - "version": "0.2.46", + "version": "0.2.47", "description": "Basic WebGL scaffolding for running interactive fragment shaders via @thi.ng/shader-ast", "module": "./index.js", "main": "./lib/index.js", @@ -49,10 +49,10 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/shader-ast": "^0.7.1", - "@thi.ng/shader-ast-glsl": "^0.2.9", - "@thi.ng/webgl": "^3.3.2" + "@thi.ng/api": "^6.13.1", + "@thi.ng/shader-ast": "^0.7.2", + "@thi.ng/shader-ast-glsl": "^0.2.10", + "@thi.ng/webgl": "^3.3.3" }, "files": [ "*.js", diff --git a/packages/webgl/CHANGELOG.md b/packages/webgl/CHANGELOG.md index 92f4e9e475..208c8b0705 100644 --- a/packages/webgl/CHANGELOG.md +++ b/packages/webgl/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.3.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/webgl@3.3.2...@thi.ng/webgl@3.3.3) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/webgl + + + + + ## [3.3.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/webgl@3.3.1...@thi.ng/webgl@3.3.2) (2020-09-13) **Note:** Version bump only for package @thi.ng/webgl diff --git a/packages/webgl/package.json b/packages/webgl/package.json index 64b20a8063..1b32c780f2 100644 --- a/packages/webgl/package.json +++ b/packages/webgl/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/webgl", - "version": "3.3.2", + "version": "3.3.3", "description": "WebGL & GLSL abstraction layer", "module": "./index.js", "main": "./lib/index.js", @@ -49,21 +49,21 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/adapt-dpi": "^1.0.8", - "@thi.ng/api": "^6.13.0", - "@thi.ng/associative": "^5.0.6", - "@thi.ng/checks": "^2.7.8", - "@thi.ng/equiv": "^1.0.31", - "@thi.ng/errors": "^1.2.21", - "@thi.ng/matrices": "^0.6.32", - "@thi.ng/memoize": "^2.1.2", - "@thi.ng/pixel": "^0.4.5", - "@thi.ng/shader-ast": "^0.7.1", - "@thi.ng/shader-ast-glsl": "^0.2.9", - "@thi.ng/shader-ast-stdlib": "^0.5.1", - "@thi.ng/transducers": "^7.3.1", - "@thi.ng/vector-pools": "^1.0.45", - "@thi.ng/vectors": "^4.6.5" + "@thi.ng/adapt-dpi": "^1.0.9", + "@thi.ng/api": "^6.13.1", + "@thi.ng/associative": "^5.0.7", + "@thi.ng/checks": "^2.7.9", + "@thi.ng/equiv": "^1.0.32", + "@thi.ng/errors": "^1.2.22", + "@thi.ng/matrices": "^0.6.33", + "@thi.ng/memoize": "^2.1.3", + "@thi.ng/pixel": "^0.4.6", + "@thi.ng/shader-ast": "^0.7.2", + "@thi.ng/shader-ast-glsl": "^0.2.10", + "@thi.ng/shader-ast-stdlib": "^0.5.2", + "@thi.ng/transducers": "^7.4.0", + "@thi.ng/vector-pools": "^1.0.46", + "@thi.ng/vectors": "^4.6.6" }, "files": [ "*.js", diff --git a/packages/zipper/CHANGELOG.md b/packages/zipper/CHANGELOG.md index 429bf8f10b..4f71c79da4 100644 --- a/packages/zipper/CHANGELOG.md +++ b/packages/zipper/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/zipper@0.1.25...@thi.ng/zipper@0.1.26) (2020-09-22) + +**Note:** Version bump only for package @thi.ng/zipper + + + + + ## [0.1.25](https://github.com/thi-ng/umbrella/compare/@thi.ng/zipper@0.1.24...@thi.ng/zipper@0.1.25) (2020-09-13) **Note:** Version bump only for package @thi.ng/zipper diff --git a/packages/zipper/package.json b/packages/zipper/package.json index f332c0a20d..a7c77793ea 100644 --- a/packages/zipper/package.json +++ b/packages/zipper/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/zipper", - "version": "0.1.25", + "version": "0.1.26", "description": "Functional tree editing, manipulation & navigation", "module": "./index.js", "main": "./lib/index.js", @@ -49,9 +49,9 @@ "typescript": "^4.0.2" }, "dependencies": { - "@thi.ng/api": "^6.13.0", - "@thi.ng/arrays": "^0.8.0", - "@thi.ng/checks": "^2.7.8" + "@thi.ng/api": "^6.13.1", + "@thi.ng/arrays": "^0.8.1", + "@thi.ng/checks": "^2.7.9" }, "files": [ "*.js",