From 3c44bed19350993bf17ad9472255f025b60f307e Mon Sep 17 00:00:00 2001 From: Chuck <33324927+ChuckBuilds@users.noreply.github.com> Date: Thu, 3 Sep 2026 00:16:45 -0400 Subject: [PATCH] docs(incoming-packages): document all 25 settings, with real renders The "Key options" table listed 7 of the 25 settings and pointed at config_schema.json for the rest, which meant the two thirds that shape what actually appears on a card -- show_dashboard, show_delivered, show_delivery_images, include_delivered, the scroll settings, the timezone override -- were undocumented. All 25 are now covered, grouped by connection, card contents, and rotation, with the advanced ones marked. The plugin had no images. It ships a mock provider precisely so the layout can be previewed without credentials, so every screenshot here comes from that: the three card types, four panel sizes, and before/after pairs for show_dashboard, highlight_today, show_carrier_logo and show_delivered. Each pair was hash-compared to confirm the setting actually changes the render. Adds the plugin to the root README, where it was missing (#385). That creates a Productivity section, which #384 also adds for pomodoro-timer -- whichever lands second needs the two rows merged into one section. Rendering used the shots "attrs" seam from #386, not yet on main; the identical tooling change is included so this branch renders on its own. Co-Authored-By: Claude Opus 5 --- README.md | 6 + docs/assets/incoming-packages/card-types.png | Bin 0 -> 13849 bytes docs/assets/incoming-packages/hero.png | Bin 0 -> 1591 bytes .../incoming-packages/highlight-today.png | Bin 0 -> 9643 bytes docs/assets/incoming-packages/panel-sizes.png | Bin 0 -> 14006 bytes docs/assets/incoming-packages/shots.json | 139 ++++++++++++++++++ .../incoming-packages/show-carrier-logo.png | Bin 0 -> 7310 bytes .../incoming-packages/show-dashboard.png | Bin 0 -> 11583 bytes .../incoming-packages/show-delivered.png | Bin 0 -> 7103 bytes docs/assets/incoming-packages/survey.png | Bin 0 -> 12386 bytes plugins.json | 6 +- plugins/incoming-packages/README.md | 110 ++++++++++++-- plugins/incoming-packages/manifest.json | 10 +- scripts/docs_render_support/sitecustomize.py | 62 ++++++++ scripts/render_docs_assets.py | 6 +- 15 files changed, 322 insertions(+), 17 deletions(-) create mode 100644 docs/assets/incoming-packages/card-types.png create mode 100644 docs/assets/incoming-packages/hero.png create mode 100644 docs/assets/incoming-packages/highlight-today.png create mode 100644 docs/assets/incoming-packages/panel-sizes.png create mode 100644 docs/assets/incoming-packages/shots.json create mode 100644 docs/assets/incoming-packages/show-carrier-logo.png create mode 100644 docs/assets/incoming-packages/show-dashboard.png create mode 100644 docs/assets/incoming-packages/show-delivered.png create mode 100644 docs/assets/incoming-packages/survey.png diff --git a/README.md b/README.md index 9fae8532..9bd0c2f3 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,12 @@ curl -X POST http://your-pi-ip:5000/api/v3/plugins/install \ | [MQTT Notifications](./plugins/mqtt-notifications/) | HomeAssistant notifications via MQTT | | | [On Air Light](./plugins/on-air/) | Broadcast ON AIR tally light, triggered remotely via MQTT / Home Assistant | | +### Productivity (1) + +| Plugin | Description | Preview | +|--------|-------------|---------| +| [Incoming Packages](./plugins/incoming-packages/) | Rotating carrier cards for packages arriving today, via Home Assistant | incoming-packages on an LED panel | + ### Custom (3) | Plugin | Description | Preview | diff --git a/docs/assets/incoming-packages/card-types.png b/docs/assets/incoming-packages/card-types.png new file mode 100644 index 0000000000000000000000000000000000000000..c20dc88780489631b5f9de3049ffb5fc66b64532 GIT binary patch literal 13849 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 U=!=D(9t1*GO73zh>W<6*0~M5&LjV8( literal 0 HcmV?d00001 diff --git a/docs/assets/incoming-packages/hero.png b/docs/assets/incoming-packages/hero.png new file mode 100644 index 0000000000000000000000000000000000000000..e88b19790c8a73ac6754838be1bfa9a799f5af87 GIT binary patch literal 1591 zcmeAS@N?(olHy`uVBq!ia0y~yU&Q z2gQrGvxqe)u&&JT@SfSXrg;MI66cbe4jivJ?rLW`JBxO)Co#Th{PIKe+MSOTIrZ_K z>z@BguPHToks$;!8xDSL)wX`~`0?Y<4!iI6Jic=2_Rlp_f1k12oO;DS`mp5H|25x^ z9lXGw$H<_-z{tSiz`(#Hz|g?J!Z2a$)&s}37#u6%%IclWx-BGY>yxazKcn2Y=1l)m zKmVrF>C9bWw@TjLnzsMO-oJScYaqHoI$;K7e^7P(+Ztutv8nJMMjbFfcH3FgP$UF$e&eED8(_Yc{iP3$x0SMG-naeXi@$eAFv2Z>*>_|5+oF!Ji)CdOncjN*xdCmT3w%a>ueBDW94AzsBgrG5+r5XRf!jWDy@Fe8VU5&qxb}P z)S-C*KNl&=@hgPM-v7Szn#2EpU;n+-xBp*faM9xM`6(+)+b-9NGX(#BK7Dql+rO`` zzq;Hvm8m>a+H0A$t1t=Z7o?a41-!!N?FXJ+-Bf6Hw>;7!M`T5t6_wW7d zZ~pxfy?Jq4R&TJ`r;_J34|}pKq9dl=zJ1%je&?=TT0hS0S(a_t`?7UwPQ}_}x1-pS zgMm@9|Jqq+OUk0YozCjL^J$K8Y`4G*pUB5K_v&tL_$;dJfDu?Hv!W6X&)pWZa;9lo z`3BZ42h2844~{&(>gB$uzwLv^s~%dU{%+lB^So5z z@~*6#BHF)w*1p!tuDJSZT~Efxl*YXq{{4`o@{vRZBCTuTN2) zyM9ybmQz+?TdN{;&+okT=cZ5hhV6RNOR}D8&wVRywoK9D&zTwT60u~}i%j18uJ=lP zTV8ehYWCLaS8L_deU`6WQ)+tmg!dll?78;I-|l&R2bzC=&0@{4Yd24N&5lf+ANl%U zjPCO`Q3VEtf2?fC`R2f+H^*vTym@h8?yDn@U;qB(_v^`}=GR9*-+kow^T!pw$h{Sn zRS|bA<7MKi3+C>q-`xo`1C}45`5%pomVSul60NXd@0(M6*49=9@1-hgYU7``&W)+s zp=)!0?WawB{^xCPvjOvRSY<3QFU#dIf6q7H$b=~AU`6K4=!A>h-RHu;99r~Qbnk{2 mHLm(PR`J-BqLd{E-2U>v+$1^oaA|2UNW#DXNDaLNM^Hx)5do1tpwa?F z483Kf*B~W?j`ZF_2@sOp9X-tP%r|%4_T8)%*CKE7zR$DU^WVSiGd&&6y}OR?LLd-( zFI_x;4T0Duj6iImvTcP=y2F$%A`k*jm(Krk-Mwq3*TXrSR3bai+rYLH&#~=%(wTb) zw;#Ov)5G$T3-(-F_B)v57-Dl%#M=|wNdhxIMST|vOvJ23UA~C*_XQe#_~DYNWlG}1 zlkd)j9T5txIrs!|vw>Fa5gk2x68YrZR&SMh)qP`1O?|Y^v15zoG!M+!vrAf9>kc`c1gU^Z5#a0C?@ncSq@ zbn~$~xh-GR(07?{y9NEStnM} zZMNmT7C%k!>l~=}t84LqbBLIa+!3i{DUHkWFinwwYOvWrVq5bC&^^ zsbX|ce9KFudeW6hr(PHG`*-guDl6Y7C;L*1`hDojKH(n+7Wb`S&LqU=1yEFX`xD#uJ{Zv32L!^C>vrGc+``u&~H6#dcOz zzu=|Km$PfixKnCRNl8gXoW5~wc6P)rGA3qYh>s~JD0sI!*S7pAJ7J~Err&cagQJYg z$V}ov$A?#0ws589CGy6N8}jn#=sN=iyPbnsw9w5)iG z&LuXHpMN&~@aw0n+ttV2zx)QvjNl;%Q-BJGW}zzki=s!FimFL$M(h6=@aEIFqHmG)BvEb8{P6)(480%3Yr?=POl0 z=y8kiX>}L5*+&w_A0H%f-vym7mwhIYPvY+Y73CZg9 znkxy(Ql`}Kzvn52d#JH#zBpD(Br>4-@gKof)P|nwhp%vy%@34wa&pSr_2l2G4B${R zGcywi4>nLu3_Ybg+m$2Y@4(9X!^0yaJh%F|SGo;3bLY;TP{88k z924#LA!4>I*i5x&;O{o>LT20dtAOGC*i|lSX$2NvujIUGmA$Y$Mdp)p_{sl_({Rm5 zeT30cIp>I7fiIJRVo)NG{#uX?5HqIP_nLd%`gzri^Bo4DH0Q#z8ML{l915<}hmV*> zUVd~j=JJ&*kOrf$@g67%lFGz45^wYKADEjPp)k-|sX3X$R8(Zevtq zoH8xgcjNX%dhYG&7Z;EGqM=cxI9D7R9Zj1pnq#F#sXW5LuE)u1V|4+Nt{X!1>eXg= zMpZB$A7f#Uk*Ev?au@8KX__}17GV%xG%|;w7J(s7pE@=6IYFIOTqyP8r?jJ%YWRcC zx0hJB4?Kng2|@ywl5!6Y!6s#@*~E{k5GGL2XL<@2;a5_38&*j;3>U8$ze`j?TV%D% zRJ*8IK0L~gi$3d13cd#sC}lX-}Uv%ds{% zX|okU;tYNL+QQUF70NlBG&_;ck1Kn2ezY9Z8?x$uend)AQqsxEX_mmm#G4@4#7c09 zd>dbOK-5@3PD9b!vG3Sw$()b4zn+tXzPXJOoImTeDn9GyiQ}=-3kwTxHG=ADYS@tH ziQBd!28|5fCnafM9%i4vd2>LjNr_Wl-H3d&si7f#Id81fDxO!~>CP%m`}Js3{2c#o z#2{IAej+*E6(SUN>FDUF=sLX$M}{x0yZ`lup`p25vFl7H{uBgGB{xcmeiU?xSq&Ma z$@cKzzjVnrZNimk$26Num{V5oa>PY@P9={~KclkC1wCm!rSG^N`ts$=Gfqn- zy1}&C_Yt`nLr)RsIl80}w774JG*_iYT;ixF-$Mj2RENx?IUTuai`tDiG&Y*RHY zJ|mRM$g}66WSH8OB)P>u*~`PQ9jY1}3`P1^1x4@S#gM<4+Re13E{5=5$jWjINlIk5 zYU`y|R#*BilX5xK)YQtDo|DyDX!Hv{W;`MF(xqklg5_>M`?VDpGPS!X?^iN0R!C^? zTg40%ff0H;o^j`srofPr=TgnAc~N3;b^|hO7TeSL;`q5Gsl7Zhg}29J`;Tsjn~N81 zU~Nrz@7~RCuRmf=#`XW?i3>=|G;8KhUD+`TT8xYL!bFf371O&+f3lCS8OQwdRj^)x zy>_I=k9`iU6S`%*>T|_unz-DVE^5=!)n?Ra_%XG}=GRAV3fLQh}CYN6otE~Ur!35NjFxkc-=-; z0i|x1xzIiZHJ92$jSUwebQD@He!j_Xn6WXa%AE5(YmZs@pg3oe=W4s;-p2@*wWmjP zyG^gI<12UHzBSp4?ssd?Fqg6!otq--7S60B(ATXR<7H2Q+^DE&MtR3E`&$`{gNH<) z?B%=Ka(!ta-IzfZ$()XhE;{M|xd2TDPxGmG=Q{_xy*Lbi63G^HYFOA4*i%(STais$ zZ*#1nAGN>)WYGpvM;#RUWeP!=O(ZQ6^6*J5ItE;Hp% zFE(+M)rF(7FX`%Dxv~do=ISv@8Sxcur9Aq9kL%DOyM6}g$?}v*?iE{7q4t9Z)2PuV z5nyhx;6Yy8LMi4{JtNoMTjy!v& zb?3+80ELY6k^FQGJg@RY%9A!h8JU%#;88wh&pVX?mI-oa?fW*u%p;171oXK@Jx?Yt z{+2rYbE51%WQ>xBBoc{~7g!66e|q_-JpIz|hAmf@*tUFFHxOV&b%02rv^~c0ZB%Q~`RdqOy5Be0`RM$u*Ml*6HATdX^eMRt}exuV)uwa9E9Be963b!EKwil!dt7A}v>;pF21^-!CwIRW?fK<&b(J3NdiL zWttWx=_eCy+S9F@C0*!+zQ$wsTCyjIyo#6mNkxe|B3DN*5}F@qvj5S8l(uQ#C>TSr zy%*E!DnM(Fu=Yt`-zywdc(0jXK6W!O2C%r?M*6&;qULkZd`2tNkzTHInHw2Gc_9!P z_XKz^1b=1*BPwwEHldh_AX)k%AKq%FCu^uB*A|M9QkbyuZl*EeP>C0YL1}0Z;W>Me zh{~D{^Wha!h-sPkWz+++SJ}k^}|uVDI${Pw}@Z zKgKEJUOantW9*tAWk^v>sXJ_qaRP z&V!zZ^Laa4*NcTx=#cCZgDi`drHjf7j7-{O z1_kSm>!qaz?6WFgUlujVZ73eB8>z2*fd)AO=RA+xcoj6m*@hXo;*VYzVvnn0yqn^B z$twjaDk`N`IGdx=)@HSzULPwHvQqR!G&eoyEEbY~f3wMgTv1&e?-Zw1DCYLBstUVr zkW~n{b|cxHwt_p6SE5_Ri~uX{#3*NJ84Q`yK1LfQ3x1abEp z99M5R;y*0Z?}bj&Qs)PT4}Id#W%|eUmHN6Hl+GxUND+#(m=w({n6ivSd4~}04J0EE z#>+Y00x3kNu^)CW4_a8*In|zd>BLM)NqCbzREz3mD+2HKE(mT7PvGv8`&F1234;G+S)lC~Tx3Rj< zJ{n(5<61hUb`6vtmi`-va)ptr{=WHTCFO3VG`;qRJSN%qGChk~3qi zGK$bT)LG?gM`bov->xNXMU<^k@mR2okws?-qEmu{+le_|pc zmp-`Yy@)^zD4Eg=$4ckm{#@MLzR5M8$!>d!@GetJRIAcF3|)bb8}X$~ zd5sOhA@(O<+<2Qn>z=I$?mwil6q^|Y#irp09hL_W`RDc=J}YOY z7ty!vKa|?TRZGBMWd)RS&R=5rxd`>v$Spq^)3*Y&K_Du`zr7cBBOdC}!h114`FEvyUmyG3pRi+n!OC{{iR8gUw80#dAt5Do*JXns#CGg|#cLebRn+8myM^wNzAnD= z+=ula{tJ`yU(BF5)()Fn#ucnLk6NX~j@zasCuz8kuJ4*%J8V7H7xL}K|6+H4Ex=3V zNf+*B`sMJE$SIMSWU6(#O$ipg{U5#X2Sp;KanEdn`)u~Me_TY0x6e&KLQABjrCu(NQV2+U{voL= zwa+Wz0O!{j*$f6&kg)>H!J=<*p@Fncvg1kslN6e98tJ=uOB*1KOKh#JmHuZ=aY{f} z|LLG(kd_v){SoQk0lOJsKc#q|jHz~ck??|~W;mzvT-s%>CMxZ$5}GT}8u{C=%l|bL zQ!ZXHG4afCn{5-oI}BL~hFI5keyBgWJv{A`vchlZhKIlSk<;tgS#ka-^xr)Xi^HCC zXwv-B^EPe&KRIu6MVs01U3P6=`aVhiWtacEOPi@BhpLPlWytfmhI=F#(MFTPg)t_G zuZ!DU#ikq7v<+2$%z2rD-u{qfl+7FbbvZV}dyh5JPeJqB&o@8c^qwA1c<{C#_sTr; z=lC&OdIv&JK;r)WiMv3o<)BJ^Un>6h(Y3>G)i?lCfNojbs>jH81s^YZ| zHXJ2I*={^2+@RDietl^M9d*%AwC>4Y(8W+f*;O|jDg(GU1+T~%jqU)^V}1GJ#eDio zcj&8EPuTe^s603jt$S-n=;+?}CtH4w3)Y=o&C; z{`w?Voy`|eFEBrO*J)!uH$=*A;)93ojJ2_NU&b0bYhm$EXqk_BybKLR57+GH-1@EF z0~)hxjLNxF`zo)`6RZAoU&5pMXBxrBW8noX8UT~xY(Br!&NgLgkA8T2S!$+1n(Gkk z%YB(-#E;X7k&^%d@X_vI#w$@T>MXs>1_yBBjJUY{%5-P2D#QKSwQCbu09O>@qpIge zdJA1dTBiYP0N7S=o9%h86``@Beeoh2aszm2O;Z!9(E0u)eO=|{>lh5i&dx4WP#d!t z-GADmIKQVAr^;MwVonhlB9zrgtGL>xCc<*NsmR37CIHw_o)hnbRn~u&m33=RzY)@_ z&PHEf_M*+?q0wk=QIoSCl;MCrUc{G%D%|tu&wi2cGam$=F7{eEAuc+R)IzQD&Rhy8=SO4RjBy zt&o=&5wV$UON9`azp(Woo|gdMU$5ZQU7BdMS{SSh`MovG04v#j^3*BSrO)a}e?U#_ zyb5PUL`1~Jaa|dt2Sd;d_^b{*<>yfX>IASFMlV8cRHwWvIy#JnVBce$oOmD?FkwM? z&E(jZEE}>71c+oFmU&=Y+rcs*Ok9Av$Hc@)HnL_Duu6DMld$A&djhZ8VPLEmxXqU! zX&9>uLjtK-An-tUcC)}I8vGN;Ev^Ez6i6GVGSMpD$F<`3{UO!NbsRG)GEyG;lgkRi zcrOBm{wg$7oek1zUYcwMNbC*l1mLYNxC=BRVC|XSA}Syc8QZQl76N{Oc!=jF7-pKu zTM=Wn?bz1<5lFdWZEYQCn^`!SR#8#GQP!5K53m*HF|z z?~NX*3xE9hF^j+h)l&muyE4=KROq`;dou{WKTLMfyN-rWfh?MtK8g(vMNzQp(Z}=A=v5~fbypMZ) zfH^^ppR(7=^>3Sij_ow%*ZS9@Av*y6_2${5U^zU}*4HVMFs(YlzB1EooxC zy(!I_d_JR*RwwpLg;Du`f+gx1L1(~%<*U^J#qAlUrsq?P!_z-A9z%9jLRtfq{W2kCAYozIninmnv_<18QNV`uh4i_8fL- zlqUOg+$F}`C{f22zirWpQ(6NsNPzmqngV^eS^nzPE6jRpJYy+YHKnm&PMHZLjj@}18NRy&z?PN@lm)PrW&5hlRj@n(N0c4Cr*^OO?ODh%dag| z^97sfNy88-$A+v?tlbQ@+j|4K`2C-RuQ(@8*)FfI(fliqS^9MJS`&{1-oVaL);G(C1{&A=bdt;mbL;o5M9BFl4}uKRs2~>jd)|!p4ZW zI$MN==L7^&-o56;qPbE<{|^oWWiT?a?JZoUQ~TMG&ag|#T*>h5A#&kw-pIj>0qS)= zq>`m)jKpmX(5`os#huM7>$_e*As}E0q0EO_y$ORuUbmk8YO7%KY|HxB z7ccz-F~5M&bF(i{hBk(Ux%&wOz}&WB#sq!tM8}J zx&TIj{cR$S|{p>%hR9nu0MO zb>me+q=K!qy}dV}YQgED#ukG11#xd+0CgmU?T4+QcdTHpGi4Y{Deh|qBx(G zPEZ9;2>o~NLr$uE1cBqTEgrLe9}Yp&JUd=)?mRH5t}1;gk3hGrwYMaVRN0W@l)XOU z@c@G>TX9#R>5})EF-jJTyvu>eM`YXx=d-q1wqf*ik~**;)%tQ5uMnS@3vPM1y8;wv zIjckai?6e^ChN_yF>9nZ=6*8(6G2kj`n4foNv-cye8P$dA4xv(&;i6(b^N!si!Dcg zErq!MALRe$Bfghz&=LIAwfyZrB>cBsGW+9}_Li|27&=Ne!5Pt3Bh#EnP3vQ`NwfU6 zgTLuwARz;4SM|BV(vEKVtM~k_!36#9?{H{V@Q8Ja#euKVc2iMrDqyxT(~+T9wMBJG z=;gPKO?ryW-Pd)sgXSBSxq22Q+K46m-){Uj$%~+R@5w=x8;1+mOOcJ_bmvIMWKW|p zwtw`(FC(}0qL1`MF7({r@sEqpTXR2}IG1wRI^}4Vu-k9NFGcvi_2HYVtPs~neAUs= zsQR0vi=rYQzK4HMLjJgw^G_2de(!kgedT^>u5h>>1|e-2b(KBWI*-s_o-6aqHYx-lxPfBRqV{w^fGx?5vz z{_v!6HUuVy&$W$?8-{eFgdv4P`;`k>}Gyt;)qh z5r4{C{rSfy8^e(uEE@2sR`V|w@_ldgozeduSDTl<3&u@n{)Ooq2N~!@zcyLrz36^&QCtv0sjdLap{82 K`AoH6AN>!kYOlor literal 0 HcmV?d00001 diff --git a/docs/assets/incoming-packages/panel-sizes.png b/docs/assets/incoming-packages/panel-sizes.png new file mode 100644 index 0000000000000000000000000000000000000000..b89cfc46011d369c2915087f2bbe2706cfa57565 GIT binary patch literal 14006 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 Aa{vGU literal 0 HcmV?d00001 diff --git a/docs/assets/incoming-packages/shots.json b/docs/assets/incoming-packages/shots.json new file mode 100644 index 00000000..224c59a9 --- /dev/null +++ b/docs/assets/incoming-packages/shots.json @@ -0,0 +1,139 @@ +{ + "plugin": "incoming-packages", + "defaults": { + "width": 128, + "height": 32, + "scale": 6, + "freeze_time": "2026-07-24T09:00:00+00:00", + "config": { + "enabled": true, + "provider": "mock" + }, + "attrs": { + "current_index": 0 + } + }, + "shots": [ + { + "name": "hero" + }, + { + "name": "card-dashboard", + "standalone": false + }, + { + "name": "card-today", + "attrs": { + "current_index": 1 + }, + "standalone": false + }, + { + "name": "card-transit", + "attrs": { + "current_index": 3 + }, + "standalone": false + }, + { + "name": "highlight-on", + "attrs": { + "current_index": 1 + }, + "standalone": false, + "config": { + "highlight_today": true + } + }, + { + "name": "highlight-off", + "attrs": { + "current_index": 1 + }, + "standalone": false, + "config": { + "highlight_today": false + } + }, + { + "name": "dashboard-on", + "standalone": false, + "config": { + "show_dashboard": true + } + }, + { + "name": "dashboard-off", + "standalone": false, + "config": { + "show_dashboard": false + } + }, + { + "name": "logo-on", + "attrs": { + "current_index": 1 + }, + "standalone": false, + "config": { + "show_carrier_logo": true + } + }, + { + "name": "logo-off", + "attrs": { + "current_index": 1 + }, + "standalone": false, + "config": { + "show_carrier_logo": false + } + }, + { + "name": "delivered-on", + "width": 128, + "height": 64, + "attrs": { + "current_index": 4 + }, + "standalone": false, + "config": { + "show_delivered": true + } + }, + { + "name": "delivered-off", + "width": 128, + "height": 64, + "attrs": { + "current_index": 4 + }, + "standalone": false, + "config": { + "show_delivered": false + } + }, + { + "name": "size-64x32", + "width": 64, + "standalone": false + }, + { + "name": "size-128x32", + "width": 128, + "standalone": false + }, + { + "name": "size-128x64", + "width": 128, + "height": 64, + "standalone": false + }, + { + "name": "size-256x32", + "width": 256, + "standalone": false + } + ], + "composites": [] +} diff --git a/docs/assets/incoming-packages/show-carrier-logo.png b/docs/assets/incoming-packages/show-carrier-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5dfbec29e5a3988bdfecce089d2095cd46a6e971 GIT binary patch literal 7310 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 literal 0 HcmV?d00001 diff --git a/docs/assets/incoming-packages/survey.png b/docs/assets/incoming-packages/survey.png new file mode 100644 index 0000000000000000000000000000000000000000..aa92a908cb1f192783ebba28d77c7ec0c56f0935 GIT binary patch literal 12386 zcmdUVc|6qX+y6)VLdz)$Ngb8SNsFxroff4+B}TSM3K3H=MwS_ETIEEtjHMz9W5ggc z%!ne{mqEiACEJXd$ugE=NXGck{u2;1XFmkZD4jP0j2y${jX}`1O~(8GJn2JY(*rUdbvhWdk3Si@ z{oBK9D_lk~{rwXSp2!b*&KLi3d)q?skKZfAD_m3bhxm{Gzhi;(vc!v+TFaq7i_)+j z#NH_9xV+DI)l!)A}hV)fnL?onb7Q$&7_y1hT~a=Hn|>j#}Iv|Bq)$z6v=Dz z<8FbIC+H}K9ntIjCDYz!#}K=GpMK?uH_Fnhc3vzDlv0iNA26IKHuORwqb@*CT<%`c zq2l2bLt%%ZunI-iaIT7}sxqyg1to@)oqURAbYlDm$`;D0|53Hc4n;?TRpJYVY0ie@ zALTWi{3rTL$Jx1z&Iq_irc~gJ&F%Dt{!(R8B?3J-+7Y6o2ko)mTEXOSIK9262rkF* zqFt9hzm-+9OtZ=5fW_)}MLK#@gwO7&TjyQw4IT_x9eb8P)cc%q{dHHgTd0?p*B>@HY01gm;EjeoPp%KQPK3ozob4@f8yn~} z6pdBK`+UBmEa*A-+(A!Qw?YRxrg?ybJv;y&N3`XSAw?r>BWW&xZ;nuF#J8MmzLa@ zH}}l|PwFf8QAEP{i7%>^I#A7W{#TF9WfVaRB^FG6Pj0KQCn2N)c!&4AtRNXhZMViW zb2EKpWwe&@BE7zh^z`(rGv`)CZdWNQ-%9c4T-Z!cS{qqN9AkCWw`PdoIA;q9mirN>fvR$de>=rKAK%K^|RhQq- zSB=SFpvTvr$~;?^WP-KF2zXhT#mB3$;WF~B;SiD;8_a0Q(g!Kq1u6^NoMin@qTc6rNN3L zt)A69-^yzAa8})Q#|OKTG!ONTtP!#(!XuHhA`cf6w;g2;L9ceCet8~Y z@7weAR+TO*O(kUaz^7ZvrXPz&VekNC|L1q$v-2=mQ|7ty;faHDSNpW{n&9zg!Qp`` z-6S=4)wTfs5Qrng`GZv?E_r;|zcbyA)K!Tc2}bxk_S8IGY%qGdw+ueu_!63k0 zPil-LZGr-=qOx0B^E@Ne?TGFzIk9>uZxpIJN+Y>xA^5fqiqqO1j}Zz+7>rkrr6s|N zz+#D6>I<)=!&ep0cUEe^J4&aDvt*bl4#L3?hT694hn;|m(QT`PQG zOCXnhTQBszEZfORf*_Rn`LmJXUvAOWOdzPn(m;Q#Lg9fWo!(%4P+Dv07AN*SeBM0h zHTEuEUYt^vP@=xQVX2eUzowpi4;1_g5#NVwO1CSB>+R|3DZX^q+x~S`1DAf{juAQG zt_VGR=lbt8cFl2FX^bV`*C;X35{GZ=o*IkJt;`^5zv2g*8)h@l{y}?BMMha4>d5->6ozWLi>M@>!{um#;;s{^Ty9(2OB&96$`&L#2#Ox<{BkNE1@`%!E8GE!?Sr`fo~ z9`<7$6zi$fNHt3WtJPqzO@V%s$6EHb8|3BN;omGFxywoGOpVn#jj~SG9k4LQTH#7I z(XKo{ZFltm%U6wtY@{^Wri?F7{K~$Y&5vnh(rqYaSF7cKMby6KSBWG)wacloy8G@y z*{%y%EhVqW`grCrH5W#TM+c}!_Yc~qUh*eHV(Cm>YjN~)_lYb?vD#FLsxXRL4Ix>MLGJs+GQJ}MFoVhk5qR* zj&m@vR`K*!{ftgG^%lHve^8JeVr7F1cI;?%1()vSKLB5ZtKZp)e`$()kbxd| zb~Ycmz>GFC3W@mQOz6`_EoK5NQtr#t)aW7xG2l=xS`y?3xwr^08! zGk@U{(WIrIjhW6}l*fEc>Bp2L^!SYL*IL49zQ1BJ91-M`jO?_j$kLNLOp$ilFOQRg zHz);K4hS^JmdOtdMel==G}zet@EF*78!BRzwS@}zA`^v}FKN~92QOg^7mcGWn!P8R zVwz`}=o$)Gt~t5`2nB68N!y>)q@m=9cWJilbk#CNsx)yUS)&hJ+etUOGEcv`W?x+q zvn%Uv(-4lI&9kUOG`~+OYVh7h@A5(}AS*VKe`^yAgVnTj8MtiExy3LIt+tWWog30OYO7x$ z?pv+z@a&4(?aJzO52B-iTSM@M^fjxS2eS7nRVS;)j}?`~MN1#-yO_dZ9@A&VG5gr97W`tyKB{#C7!XB(- z){T^fBMvLd4WpgFDdr;5{g=@u`k40B_v5zJwhn_2jTT=Rv&K7DDIgQd*kNi64^e@4 z^8R}ay3{WOb47x@kz0s2wnwMIZlwTZngqrY`c2NGi>SFjxBD74&1t3Gmi^0=Yu_H! z?7xcM*Sh$7IQ~%v$;y^T`wm2@{|*I`HVqHQZu_7G1>W_NRyL@!5ZiYR*=e5m=j5SE z1m%BjEb-KT5#WE0IROfC0J28guP+8!J%>aZ&uQ_{`+QraLK8Z+=UqNlw>L3tg}Uu1 z0P#40m*31)&Ih<;&Z1Q=nE>wZnFj6yih$I9ZJ|-HLN-8R05bMz#E(^ku0I0cqZ26F zpKa=*H$2*8F8sP!bn*RPYXO>1FbXF2WtNk9I7HMR&>CF7RrY?8%*$LL8xcl~vE_W&-Sx#0m!H%~qql?ia|I@MUO zy7v!NOjbaDt(ccZB$51leOGL;ZeU?dV|HG8cUKn7N&?k=$gZwPI-b(=?4D)1Z5~>{ z2i(BX$Zb#k3+qkw*l~WGQvkIB(5r7` z$pMacXOIQp^tbAJzF&JQ=3>!&0A}I9`5s@O5qiad(-0$!vxx<)%=2e4=j)U71w-|8 zI{kUP(@G7eqoG=0XV%%9%ihVscl!?YpxUlDb6WE#pH^1w9<1P^M@ajEq(1@}84k10 zb1YpH1_+6Jzqgu%0}B`|Q#Fm*aqh0M6jWE_&}f4wu<*?Y7$2^?K1md;6A5Orr{xLM z>BrZ9X9?gaNW-aOv_yxz{d8fVn3cislQDcSfAo3i$sO?_jCIG0UYZ3k2jfK(2_Xi$ zUOhE<|4uc)(4|}fm*F%ch~4{*I9aLd<a(ax~r` zV5FlgOf^JN2aq;#YM77R1|xY}(f#*~$sz$4!%Kw+hy)`h8c@v)1#caT0rAZT6bXah zm@DiF5pFEw3fj2gzVxpKNA0-0WDb z$IS<{5270OKv5^1P$)Ey=QmJ9;}k9$4fs5r){EE0%ni(ulccMwYicMMI? zHTO>pR*M4#M%axJ0^;hm5Zbf!Z^>sm;C#MJyEvibK5Dj9p!SfsNV(tPu>iWL6K)iA z${5{TkQrTBV(US(t}MBkE(N)Nt`DnD`{Y8Un*@U_y`K;X>K*T;;CWfN#w>AyLu>qv z{gwp53XTk;zWpc%y^Znb1VPX-72?7c&&Ry~OBVbnvDOphndHz#Jz;!z5}FZE7n3!@`z8duN;X)j~=7A*}qUg(WIZELD_9Z-w7z2z~xDd zjE5a3o912f~_O*!D zO(wblExGfcj1e&eNJei7=EO?wYTA-&lPT7LmbB{?dYsuZ$n4mKOIe>Bic|QAGADFM zL5Iwdn=CUe)(e6Zo=Z)~;YqmM9)f&m^zd)Gc;6xV%DK=7fmauEbB^xiH*cfw+ZvdT zS!UB<$P~RIW>tYaH%VbEnoLhYgp?|+`FZ_%Tf2DZxD6v+hT&nwf(rm+)IA$oZi0;U zr6LzKrpRYZXa(=SXB}*wS}^mM%u!#6EaML>$pLC=Bj6&rzB6Bt$`QmvPmK!YLYl^>-Z4UV0*ib%8uZ zXiaO2sWR9-h`NbOSL1f2dc=_FuvGiv<+wZe(Nc3eztcF~xo*gJo8^-y=Be#k$i55t z;qq(o2*3Gm)NNK}r%s}hbeEX7n-(bijBJF|vx*Gx4 zc;=~9Z>*6_3*gff4V(qaL7=+?DK}%1r~2_hNhaPzj85e96o8pZ@^L&fW7ptsx*U$Y4Ye|+7D&17(ujOMPV;Stb_ttL0Y=TobZh{4mv z<$rqY-yY|`sa%`yqb7Nwx)S%GTEt5FO=!=MBFKN=!=eP1m&|l)kpQG-GJ``D zG}>fmLA08Mihiy;9soV1kbY7@ev)$kfq|zn`n3F@gcLo=j!Qmw=z8&gO`bjz*M_2u z)8pdeN>}?;e3PUrNH0MRN=~j=du!DhG8Cxk_a6bOR5hCbU>)amN5yvNm=!>{3Yso| zy_A9$xG@S^g+XH68Kk(t=gc@Lxg*F!>z7GG%Wb8&Ns9ouTgPg`i;CpPr>_CX(Ts3H zqEI74Lw^AAs7VAM<>$MyYK=G>6t`exwP(e45*$-|Kn`b{cNx^SKyDVxv}o$(l>djM z%wsp%dYXhjc<=yVHr~+CZsBOhb1d#MP%K$YChe8utzC1VyJ>+a^XJa!v2u8{612v> z?wphPy_fn+wkxjr}kQi(jMR820IZ^_LEN^R%duO!Mi3GkQxgOxg5 z64$^}8q$m<7hpHvJOxU5eh6lwLp9FlOk4gH%Ag*_@dP-fi~mO0XaV0g!Ed4%0N@0) ze{4%GLZ=kkQ{US{dRd2X;sN6UN%Q&~8QqTi8p3{M(WS5LZ@Okfhf@C$E%|IkJDqfUeV5gwb~0Hj`Yow2GC zW}-iSytNy!6k)4Cp$`;GG5~XRDc^ylpTkL@{NIw6KjA9|(RJ5>(#g)F0#p_QH$MfS z9Y6%CAD!a^LU)gS3B%_P93Hy|h>!s}OurleBP1c8g<{jrU6TrQYPbbl$N|WrV&&80 zV`gU()?>5&mA6X|M#@2Jw$wOT<>|EfBn+Jfn(OnqKs#<8oQ6m}oVz@`9--&ULQj-5`#hLnBYXivBmgZ5tG$~Y;A0

meIl1;B_A03$vH7?Jf}CBz@_Eao}egj5(@+@J!)YZ{fBec@xKzNq#p z5U2&bCe@EbBum_LQYbYSU}gcJM)Uzx^X17trX``U+Z{{fD5LM1;Ftiwdu&jITwH_m zu!nb`Cq_N1b~#r&gZ)1QO%0%9VU2tC4z;pLncA8!8wC1Mz~YB|-vBh+RTVo9pd9F8 z7}o;~&Ff1YxZJkrv%s02E8lrNSfvO0LW%)v6z)M!C-a#nS{6Zj^js?F4f_`B6TsI2 zP0=l;TRz>CBMW(W5fv^7zqc4#zW=`|Pp39B(~j#z=d2hkd@Pov33otQkQJ0*fdc(P zH908rNp^G3gwuc4zNfNHLm^qF`4*?h`D+)w8gH_2c-8WfB1#Mfx zUB2k0jB=ghcm5nCoWG?Fw89>pS%J%+n53aQ8q9FI^7phaBki2RFIdpu<9uU#Q_aq) zi0CKE$jp&DYBb8L)N#}`?*kIm{j}xj$MNrTYv!Az5p&Y4gTv%MPMMoK+pszRF7NKZLmxg>-?LnV5e(|ZFjw6dHC!$3WlFU${?EA;tZ0reMcI( z=Iw(AelE(3^~C7oxacB&&ZRU&bt*A{#}3C+ugJ1>u{1YRi$y$OXboi@7o=wZ<4nu<>^EoNjdE3&jGd;kubNuy+oZVS&9H9 zmv#)NAlTfyDhWdcdnT3_#6ouVl#pFMqG&yh zj4xS!xd;7qvZWH1+DKvAn^Oks?B)S|qDSXGXRjcrRxDY3`|tca^uB4@3nW$z)p6W| z7={VV%wuM&Q``fX~=MPpq+Lz$KF+%w}t>l*PWyrl|E z$5dq`9aN*=n;fPt-Bh(Jfp~y_=IkD2|y)R*Ro=iLP~X`mP` z3Ma@CJSm^9&0grMui@Esw6uP}6&YJ8w`W295i4WQGoXJ(;}=EmM$$fYAsrzQdf=$= zN@3%JU+7GU)b?1J#?ivjF8yV|Hs2`hZ%DC7B&y%}&!|`G8RAtAEy*waq5hq0g}jHQ zG5lz-9^o9!~^LPB&-ESq4eik832?UwfenFE^jU;cn)3F^W+zD`H08Gh z`MrLw!KMY)THCabXU*B8=z11*8ack1yC&VBA_3Raz8BOmy zHd(Xa>;3Q+ti#BrJVf`xz~#v|Gb}$~7ldi|s;4FL@RoL0vzf~-eA(XAC#ctUk37IS zd!vCs+9s>HOFNU1F^X|3{kin(9z@7;>I+XzH^(FJR=5Xwmfh6cfJe|fSX)1=Z6;vX zs#v15uLYOGy#_6sR$EaXV*6bQ%<<%W9zI`w+fA;z*j;LUnyW^Lot1&qf+TdnwKl~m zcOQ)g4JY4w)Fd;Y=23C2klHp1;J#u1=Q8!*E&NWGH`&gDqN^n2Y{NeLF$%daQ6-4j zH~SR`zR}z#rM4cQ@1E%>O49ox?i@8RaQw@13g@@~=3$k **This plugin does not use the Shop app** — Shopify exposes no public API for a > consumer's package list. Instead it reads a normalized snapshot from a pluggable > **provider** (default: Home Assistant). The plugin only ever stores an API URL + @@ -83,20 +90,101 @@ count/image, and Home Assistant's own summary string. hiccup rather than blanking, with a small amber "Xm ago" freshness marker once the data is stale (`stale_after_minutes`). +![The three card types](../../docs/assets/incoming-packages/card-types.png) + +Carriers with something arriving today are sorted ahead of carriers that only +have packages in transit, and their count is drawn in `accent_color`. + Carrier badges are drawn (colored badge + abbreviation), so no trademarked logo images are bundled. Drop a `assets/carrier_logos/.png` (e.g. `ups.png`, `fedex.png`) to override a badge with your own image. -## Key options +![The same rotation on four panel sizes](../../docs/assets/incoming-packages/panel-sizes.png) + +The plugin reads the panel size every frame and picks a bitmap font tier to +match, shortening labels rather than overflowing — `in transit` becomes +`in trans.` when the card is narrow. + +## Configuration + +Settings live in the plugin's tab in the web UI and in `config/config.json` +under `incoming-packages`. The full schema is +[`config_schema.json`](config_schema.json). + +### Connection + +| Key | Default | Notes | +|---|---|---| +| `enabled` | `false` | Master switch | +| `provider` | `homeassistant` | `homeassistant`, `aftership`, or `mock` — see [Providers](#providers) | +| `ha_base_url` | `""` | Home Assistant URL, e.g. `http://homeassistant.local:8123`. Used by the `homeassistant` provider | +| `ha_token` | — | Home Assistant long-lived access token. Stored as a secret, so the web UI masks it | +| `api_key` | — | AfterShip API key. Only read when `provider` is `aftership`. Also a secret | +| `entity_prefix` | `sensor.mail_` | Mail and Packages entity prefix. Advanced; the provider auto-discovers the sensors, so this is rarely needed | +| `update_interval` | `600` | Seconds between provider refreshes (60–7200). Advanced | +| `stale_after_minutes` | `60` | Data older than this gets the amber "Xm ago" freshness marker (5–1440). Advanced | + +### What appears on the cards + +| Key | Default | Notes | +|---|---|---| +| `show_dashboard` | `true` | Lead with the badge grid rather than a compact text summary | +| `show_carrier_logo` | `true` | Draw the carrier badge on each card | +| `show_delivered` | `true` | Add the "N delivered" confirmation for packages delivered today | +| `include_delivered` | `false` | Also give already-delivered packages their own card | +| `show_usps_mail_image` | `true` | Include the USPS Informed Delivery mail card when there is mail | +| `show_delivery_images` | `true` | Show a carrier's scanned delivery photo when it is out for delivery today | +| `highlight_today` | `true` | Sort arriving-today carriers first and accent their count | +| `accent_color` | `[0, 220, 120]` | The accent colour used for that highlight | +| `customization.title_text.text_color` | `[255, 255, 255]` | Colour of the primary text | + +### Rotation and motion + +| Key | Default | Notes | +|---|---|---| +| `display_duration` | `30` | Seconds the plugin holds the screen per turn in the rotation (1–300) | +| `rotation_interval` | `6` | Seconds each card is shown before the next (1–60). Advanced | +| `max_cards` | `8` | Cap on how many cards are in the rotation (1–20). Advanced | +| `image_frame_seconds` | `1.5` | Seconds per frame when animating the USPS mail image (0.2–10). Advanced | +| `scroll_enabled` | `true` | Marquee-scroll text too long to fit rather than truncating. Advanced | +| `scroll_speed` | `5` | Frames between marquee steps; higher is slower (1–30). Advanced | +| `scroll_separator` | `" "` | Text inserted between marquee loops. Advanced | +| `timezone` | `""` | Override the timezone used to decide what "today" means. Empty follows the global LEDMatrix timezone. Advanced | + +Settings marked advanced sit in the collapsed **Advanced Settings** section of +the web UI form. + +### What the toggles look like + +`show_dashboard` decides whether the rotation opens with the badge grid or a +compact summary: + +![show_dashboard true and false](../../docs/assets/incoming-packages/show-dashboard.png) + +`highlight_today` controls both the accent colour and the sort order: + +![highlight_today true and false](../../docs/assets/incoming-packages/highlight-today.png) + +`show_carrier_logo` drops the badge and gives the text the full width: + +![show_carrier_logo true and false](../../docs/assets/incoming-packages/show-carrier-logo.png) + +`show_delivered` adds the confirmation line, which needs a panel tall enough +for a third row: + +![show_delivered true and false](../../docs/assets/incoming-packages/show-delivered.png) + +### Previewing without Home Assistant -| Option | Default | Notes | -|--------|---------|-------| -| `provider` | `homeassistant` | `homeassistant` \| `aftership` \| `mock` | -| `ha_base_url` / `ha_token` | — | Home Assistant URL + long-lived token | -| `highlight_today` | `true` | Prioritize + accent arriving-today | -| `accent_color` | `[0,220,120]` | RGB accent | -| `rotation_interval` | `6` | Seconds per card | -| `update_interval` | `600` | Provider refresh cadence (s) | -| `max_cards` | `8` | Cards in the rotation | +Set `provider` to `mock` to see the layout with built-in demo data and no +credentials at all — four carriers, two of them arriving today. Every image in +this README is that provider. -See `config_schema.json` for the full list. +```json +{ + "incoming-packages": { + "enabled": true, + "provider": "mock" + } +} +``` diff --git a/plugins/incoming-packages/manifest.json b/plugins/incoming-packages/manifest.json index 3cf209ef..6f7c1a87 100644 --- a/plugins/incoming-packages/manifest.json +++ b/plugins/incoming-packages/manifest.json @@ -1,7 +1,7 @@ { "id": "incoming-packages", "name": "Incoming Packages", - "version": "1.0.0", + "version": "1.0.1", "author": "ChuckBuilds", "description": "Rotating cards for packages headed your way - per carrier, with the count arriving today highlighted. Reads a normalized snapshot from a pluggable provider: the Home Assistant Mail and Packages integration (default), AfterShip, or a built-in demo. Email scanning stays inside Home Assistant; the plugin only stores an API URL + token.", "category": "productivity", @@ -27,6 +27,12 @@ "pillow" ], "versions": [ + { + "released": "2026-09-03", + "version": "1.0.1", + "notes": "Documentation. The README's 'Key options' table listed 7 of the 25 settings and said to read config_schema.json for the rest; it now documents all 25, grouped by connection, card contents, and rotation, with the advanced ones marked. Adds real rendered screenshots throughout -- the three card types, four panel sizes, and before/after pairs for show_dashboard, highlight_today, show_carrier_logo and show_delivered -- all produced by the built-in mock provider, so they need no credentials to reproduce.", + "ledmatrix_min": "2.0.0" + }, { "released": "2026-07-24", "version": "1.0.0", @@ -34,7 +40,7 @@ "notes": "Initial release. Provider-agnostic incoming-package display with a Home Assistant Mail and Packages provider (default, auto-discovers sensor.mail_* entities over the HA REST API), an AfterShip provider, and a built-in demo provider. Size-adaptive rotating cards: one per active carrier with a drawn carrier badge, the count arriving today (prioritized and shown in an accent color), the count in transit, and a lead summary card, plus optional USPS mail count. Renders on all panel sizes from 64x32 to 256x64 with adaptive font tiers and marquee text; on-panel setup/error messages." } ], - "last_updated": "2026-07-27", + "last_updated": "2026-09-03", "stars": 0, "downloads": 0, "verified": true, diff --git a/scripts/docs_render_support/sitecustomize.py b/scripts/docs_render_support/sitecustomize.py index 20844d5e..90fe76c1 100644 --- a/scripts/docs_render_support/sitecustomize.py +++ b/scripts/docs_render_support/sitecustomize.py @@ -52,3 +52,65 @@ def today(cls): _docs_http_replay.install() except Exception: # never let doc tooling break the render it is measuring pass + + +# Some plugins hold their interesting state in memory, put there by an event +# the renderer cannot produce -- an MQTT message, a webhook, a button press. +# No configuration reaches that state, so a documentation render would only +# ever show the idle frame. LEDMATRIX_DOCS_ATTRS names attributes to set on the +# plugin instance once the core's loader has built it, which is the same thing +# the event would have done, without the plugin knowing it is being rendered. +_ATTRS = os.environ.get("LEDMATRIX_DOCS_ATTRS") +if _ATTRS: + import json as _json + import sys as _sys + + _WANTED = _json.loads(_ATTRS) + _TARGET = "src.plugin_system.plugin_loader" + + def _apply(instance): + for name, value in _WANTED.items(): + if isinstance(value, list) and len(value) == 3 and all( + isinstance(v, int) for v in value): + value = tuple(value) # colours are tuples everywhere in the core + setattr(instance, name, value) + return instance + + class _PatchingLoader: + """Wraps the real loader so the module is patched right after it runs.""" + + def __init__(self, inner): + self._inner = inner + + def create_module(self, spec): + return self._inner.create_module(spec) + + def exec_module(self, module): + self._inner.exec_module(module) + real = module.PluginLoader.load_plugin + + def load_plugin(self, *args, **kwargs): + instance, mod = real(self, *args, **kwargs) + return _apply(instance), mod + + module.PluginLoader.load_plugin = load_plugin + + def __getattr__(self, name): + return getattr(self._inner, name) + + class _AttrFinder: + """Hands back the real spec with its loader wrapped, once.""" + + def find_spec(self, name, path=None, target=None): + if name != _TARGET: + return None + index = _sys.meta_path.index(self) + for finder in _sys.meta_path[index + 1:]: + find = getattr(finder, "find_spec", None) + spec = find(name, path, target) if find else None + if spec is not None and spec.loader is not None: + spec.loader = _PatchingLoader(spec.loader) + return spec + return None + + _sys.meta_path.insert(0, _AttrFinder()) diff --git a/scripts/render_docs_assets.py b/scripts/render_docs_assets.py index 42a1d93d..36c7bd4b 100644 --- a/scripts/render_docs_assets.py +++ b/scripts/render_docs_assets.py @@ -263,12 +263,16 @@ def render_shot( # clock, a countdown, or a "starts in 2h" line differs on every run. freeze_time = shot.get("freeze_time", defaults.get("freeze_time")) http_replay = shot.get("http_replay", defaults.get("http_replay")) - if freeze_time or http_replay: + # Runtime state that an event would normally have set; see the shim. + attrs = shot.get("attrs", defaults.get("attrs")) + if freeze_time or http_replay or attrs: support_dir = str(Path(__file__).resolve().parent / "docs_render_support") existing = env.get("PYTHONPATH") env["PYTHONPATH"] = f"{support_dir}{os.pathsep}{existing}" if existing else support_dir if freeze_time: env["LEDMATRIX_DOCS_FREEZE_TIME"] = str(freeze_time) + if attrs: + env["LEDMATRIX_DOCS_ATTRS"] = json.dumps(attrs) if http_replay: replay_path = (shot_list_dir / http_replay).resolve() if not replay_path.is_file():